diff --git a/app/cli.php b/app/cli.php index 0f98cf3458..71b6464cb9 100644 --- a/app/cli.php +++ b/app/cli.php @@ -103,6 +103,11 @@ CLI::setResource('console', function () { return new Document(Config::getParam('console')); }, []); +CLI::setResource( + 'isResourceBlocked', + fn () => fn (Document $project, string $resourceType, ?string $resourceId) => false +); + CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools diff --git a/app/config/collections/projects.php b/app/config/collections/projects.php index 7fc82b7441..bf0cee3527 100644 --- a/app/config/collections/projects.php +++ b/app/config/collections/projects.php @@ -2521,4 +2521,128 @@ return [ ], ], ], + + 'transactions' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('transactions'), + 'name' => 'Transactions', + 'attributes' => [ + [ + '$id' => ID::custom('status'), + 'type' => Database::VAR_STRING, + 'size' => 16, // pending | committing | committed | failed + 'signed' => true, + 'required' => false, + 'default' => 'pending', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('operations'), + 'type' => Database::VAR_INTEGER, + 'size' => 0, + 'signed' => false, + 'required' => true, + 'default' => 0, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('expiresAt'), + 'type' => Database::VAR_DATETIME, + 'size' => 0, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_expiresAt'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['expiresAt'], + 'lengths' => [], + 'orders' => [Database::ORDER_DESC], + ], + ], + ], + + 'transactionLogs' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('transactionLogs'), + 'name' => 'Transaction Logs', + 'attributes' => [ + [ + '$id' => ID::custom('transactionInternalId'), + 'type' => Database::VAR_STRING, + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('databaseInternalId'), + 'type' => Database::VAR_STRING, + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('collectionInternalId'), + 'type' => Database::VAR_STRING, + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('documentId'), + 'type' => Database::VAR_STRING, + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('action'), + 'type' => Database::VAR_STRING, + 'size' => 32, // create | update | upsert | increment | decrement | delete | bulkCreate | bulkUpdate | bulkUpsert | bulkDelete + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('data'), + 'type' => Database::VAR_STRING, + 'size' => 5_000_000, // Allow large payloads for bulk operations + 'signed' => false, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => ['json'], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_transaction'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['transactionInternalId'], + 'lengths' => [], + 'orders' => [], + ], + ], + ], ]; diff --git a/app/config/errors.php b/app/config/errors.php index 4345884ff5..2e18f05797 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -578,6 +578,11 @@ return [ 'description' => 'The requested runtime is either inactive or unsupported. Please check the value of the _APP_FUNCTIONS_RUNTIMES environment variable.', 'code' => 404, ], + Exception::FUNCTION_ALREADY_EXISTS => [ + 'name' => Exception::FUNCTION_ALREADY_EXISTS, + 'description' => 'Function with the requested ID already exists. Try again with a different ID or use ID.unique() to generate a unique ID.', + 'code' => 409, + ], Exception::FUNCTION_ENTRYPOINT_MISSING => [ 'name' => Exception::FUNCTION_ENTRYPOINT_MISSING, 'description' => 'Entrypoint for your Appwrite Function is missing. Please specify it when making deployment or update the entrypoint under your function\'s "Settings" > "Configuration" > "Entrypoint".', @@ -981,6 +986,48 @@ return [ 'code' => 409, ], + /** Transactions */ + Exception::TRANSACTION_NOT_FOUND => [ + 'name' => Exception::TRANSACTION_NOT_FOUND, + 'description' => 'Transaction with the requested ID could not be found.', + 'code' => 404, + ], + Exception::TRANSACTION_ALREADY_EXISTS => [ + 'name' => Exception::TRANSACTION_ALREADY_EXISTS, + 'description' => 'Transaction with the requested ID already exists. Try again with a different ID or use ID.unique() to generate a unique ID.', + 'code' => 409, + ], + Exception::TRANSACTION_INVALID => [ + 'name' => Exception::TRANSACTION_INVALID, + 'description' => 'The transaction is invalid. Please check the transaction state and try again.', + 'code' => 400, + ], + Exception::TRANSACTION_FAILED => [ + 'name' => Exception::TRANSACTION_FAILED, + 'description' => 'The transaction has errored. Please check the transaction data and try again.', + 'code' => 400, + ], + Exception::TRANSACTION_EXPIRED => [ + 'name' => Exception::TRANSACTION_EXPIRED, + 'description' => 'The transaction has expired. Please create a new transaction and try again.', + 'code' => 410, + ], + Exception::TRANSACTION_CONFLICT => [ + 'name' => Exception::TRANSACTION_CONFLICT, + 'description' => 'The transaction has a conflict. Please resolve the conflict and try again.', + 'code' => 409, + ], + Exception::TRANSACTION_LIMIT_EXCEEDED => [ + 'name' => Exception::TRANSACTION_LIMIT_EXCEEDED, + 'description' => 'The maximum number of operations per transaction has been exceeded.', + 'code' => 400, + ], + Exception::TRANSACTION_NOT_READY => [ + 'name' => Exception::TRANSACTION_NOT_READY, + 'description' => 'The transaction is not ready yet. Please try again later.', + 'code' => 400, + ], + /** Project Errors */ Exception::PROJECT_NOT_FOUND => [ 'name' => Exception::PROJECT_NOT_FOUND, diff --git a/app/config/platforms.php b/app/config/platforms.php index 51930d1728..808ad486b7 100644 --- a/app/config/platforms.php +++ b/app/config/platforms.php @@ -11,7 +11,7 @@ return [ [ 'key' => 'web', 'name' => 'Web', - 'version' => '21.1.0', + 'version' => '21.2.1', 'url' => 'https://github.com/appwrite/sdk-for-web', 'package' => 'https://www.npmjs.com/package/appwrite', 'enabled' => true, @@ -60,7 +60,7 @@ return [ [ 'key' => 'flutter', 'name' => 'Flutter', - 'version' => '20.1.0', + 'version' => '20.2.1', 'url' => 'https://github.com/appwrite/sdk-for-flutter', 'package' => 'https://pub.dev/packages/appwrite', 'enabled' => true, @@ -79,7 +79,7 @@ return [ [ 'key' => 'apple', 'name' => 'Apple', - 'version' => '13.1.0', + 'version' => '13.2.1', 'url' => 'https://github.com/appwrite/sdk-for-apple', 'package' => 'https://github.com/appwrite/sdk-for-apple', 'enabled' => true, @@ -116,7 +116,7 @@ return [ [ 'key' => 'android', 'name' => 'Android', - 'version' => '11.1.0', + 'version' => '11.2.1', 'url' => 'https://github.com/appwrite/sdk-for-android', 'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-android', 'enabled' => true, @@ -139,7 +139,7 @@ return [ [ 'key' => 'react-native', 'name' => 'React Native', - 'version' => '0.16.0', + 'version' => '0.17.1', 'url' => 'https://github.com/appwrite/sdk-for-react-native', 'package' => 'https://npmjs.com/package/react-native-appwrite', 'enabled' => true, @@ -207,7 +207,7 @@ return [ [ 'key' => 'web', 'name' => 'Console', - 'version' => '0.1.0', + 'version' => '0.1.1', 'url' => '', 'package' => '', 'enabled' => true, @@ -226,7 +226,7 @@ return [ [ 'key' => 'cli', 'name' => 'Command Line', - 'version' => '10.1.0', + 'version' => '10.2.1', 'url' => 'https://github.com/appwrite/sdk-for-cli', 'package' => 'https://www.npmjs.com/package/appwrite-cli', 'enabled' => true, @@ -262,7 +262,7 @@ return [ [ 'key' => 'nodejs', 'name' => 'Node.js', - 'version' => '20.1.0', + 'version' => '20.2.1', 'url' => 'https://github.com/appwrite/sdk-for-node', 'package' => 'https://www.npmjs.com/package/node-appwrite', 'enabled' => true, @@ -281,7 +281,7 @@ return [ [ 'key' => 'php', 'name' => 'PHP', - 'version' => '17.3.0', + 'version' => '17.4.1', 'url' => 'https://github.com/appwrite/sdk-for-php', 'package' => 'https://packagist.org/packages/appwrite/appwrite', 'enabled' => true, @@ -300,7 +300,7 @@ return [ [ 'key' => 'python', 'name' => 'Python', - 'version' => '13.3.0', + 'version' => '13.4.1', 'url' => 'https://github.com/appwrite/sdk-for-python', 'package' => 'https://pypi.org/project/appwrite/', 'enabled' => true, @@ -319,7 +319,7 @@ return [ [ 'key' => 'ruby', 'name' => 'Ruby', - 'version' => '19.1.0', + 'version' => '19.2.1', 'url' => 'https://github.com/appwrite/sdk-for-ruby', 'package' => 'https://rubygems.org/gems/appwrite', 'enabled' => true, @@ -338,7 +338,7 @@ return [ [ 'key' => 'go', 'name' => 'Go', - 'version' => 'v0.12.0', + 'version' => 'v0.13.1', 'url' => 'https://github.com/appwrite/sdk-for-go', 'package' => 'https://github.com/appwrite/sdk-for-go', 'enabled' => true, @@ -357,7 +357,7 @@ return [ [ 'key' => 'dotnet', 'name' => '.NET', - 'version' => '0.20.0', + 'version' => '0.21.2', 'url' => 'https://github.com/appwrite/sdk-for-dotnet', 'package' => 'https://www.nuget.org/packages/Appwrite', 'enabled' => true, @@ -376,7 +376,7 @@ return [ [ 'key' => 'dart', 'name' => 'Dart', - 'version' => '19.1.0', + 'version' => '19.2.1', 'url' => 'https://github.com/appwrite/sdk-for-dart', 'package' => 'https://pub.dev/packages/dart_appwrite', 'enabled' => true, @@ -395,7 +395,7 @@ return [ [ 'key' => 'kotlin', 'name' => 'Kotlin', - 'version' => '12.1.0', + 'version' => '12.2.1', 'url' => 'https://github.com/appwrite/sdk-for-kotlin', 'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-kotlin', 'enabled' => true, @@ -418,7 +418,7 @@ return [ [ 'key' => 'swift', 'name' => 'Swift', - 'version' => '13.1.0', + 'version' => '13.2.1', 'url' => 'https://github.com/appwrite/sdk-for-swift', 'package' => 'https://github.com/appwrite/sdk-for-swift', 'enabled' => true, diff --git a/app/config/roles.php b/app/config/roles.php index 4b06e0a6c1..0f0945a2b4 100644 --- a/app/config/roles.php +++ b/app/config/roles.php @@ -28,7 +28,7 @@ $member = [ 'subscribers.write', 'subscribers.read', 'assistant.read', - 'rules.read' + 'rules.read', ]; $admins = [ diff --git a/app/config/specs/open-api3-1.8.x-client.json b/app/config/specs/open-api3-1.8.x-client.json index 4cb47c7f08..b6a6a1afe3 100644 --- a/app/config/specs/open-api3-1.8.x-client.json +++ b/app/config/specs/open-api3-1.8.x-client.json @@ -4910,6 +4910,424 @@ ] } }, + "\/databases\/transactions": { + "get": { + "summary": "List transactions", + "operationId": "databasesListTransactions", + "tags": [ + "databases" + ], + "description": "List transactions across all databases.", + "responses": { + "200": { + "description": "Transaction List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transactionList" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "listTransactions", + "group": "transactions", + "weight": 376, + "cookies": false, + "type": "", + "demo": "databases\/list-transactions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-transactions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries).", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create transaction", + "operationId": "databasesCreateTransaction", + "tags": [ + "databases" + ], + "description": "Create a new transaction.", + "responses": { + "201": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createTransaction", + "group": "transactions", + "weight": 372, + "cookies": false, + "type": "", + "demo": "databases\/create-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "ttl": { + "type": "integer", + "description": "Seconds before the transaction expires.", + "x-example": 60 + } + } + } + } + } + } + } + }, + "\/databases\/transactions\/{transactionId}": { + "get": { + "summary": "Get transaction", + "operationId": "databasesGetTransaction", + "tags": [ + "databases" + ], + "description": "Get a transaction by its unique ID.", + "responses": { + "200": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "getTransaction", + "group": "transactions", + "weight": 373, + "cookies": false, + "type": "", + "demo": "databases\/get-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update transaction", + "operationId": "databasesUpdateTransaction", + "tags": [ + "databases" + ], + "description": "Update a transaction, to either commit or roll back its operations.", + "responses": { + "200": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateTransaction", + "group": "transactions", + "weight": 374, + "cookies": false, + "type": "", + "demo": "databases\/update-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "commit": { + "type": "boolean", + "description": "Commit transaction?", + "x-example": false + }, + "rollback": { + "type": "boolean", + "description": "Rollback transaction?", + "x-example": false + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete transaction", + "operationId": "databasesDeleteTransaction", + "tags": [ + "databases" + ], + "description": "Delete a transaction by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "deprecated": false, + "x-appwrite": { + "method": "deleteTransaction", + "group": "transactions", + "weight": 375, + "cookies": false, + "type": "", + "demo": "databases\/delete-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/databases\/transactions\/{transactionId}\/operations": { + "post": { + "summary": "Create operations", + "operationId": "databasesCreateOperations", + "tags": [ + "databases" + ], + "description": "Create multiple operations in a single transaction.", + "responses": { + "201": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createOperations", + "group": "transactions", + "weight": 377, + "cookies": false, + "type": "", + "demo": "databases\/create-operations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-operations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "operations": { + "type": "array", + "description": "Array of staged operations.", + "x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"\",\n\t \"collectionId\": \"\",\n\t \"documentId\": \"\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]", + "items": { + "type": "object" + } + } + } + } + } + } + } + } + }, "\/databases\/{databaseId}\/collections\/{collectionId}\/documents": { "get": { "summary": "List documents", @@ -4997,6 +5415,16 @@ "default": [] }, "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" } ] }, @@ -5055,7 +5483,8 @@ "collectionId", "documentId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -5141,6 +5570,11 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -5246,6 +5680,16 @@ "default": [] }, "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" } ] }, @@ -5304,7 +5748,8 @@ "collectionId", "documentId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -5387,6 +5832,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } }, "required": [ @@ -5500,6 +5950,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -5584,7 +6039,23 @@ }, "in": "path" } - ] + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" + } + } + } + } + } + } } }, "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/decrement": { @@ -5698,6 +6169,11 @@ "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -5817,6 +6293,11 @@ "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -5849,7 +6330,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 456, + "weight": 468, "cookies": false, "type": "", "demo": "functions\/list-executions.md", @@ -5924,7 +6405,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 454, + "weight": 466, "cookies": false, "type": "", "demo": "functions\/create-execution.md", @@ -6000,9 +6481,9 @@ "x-enum-keys": [] }, "headers": { - "type": "string", + "type": "object", "description": "HTTP headers of execution. Defaults to empty.", - "x-example": null + "x-example": "{}" }, "scheduledAt": { "type": "string", @@ -6040,7 +6521,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 455, + "weight": 467, "cookies": false, "type": "", "demo": "functions\/get-execution.md", @@ -7571,6 +8052,424 @@ ] } }, + "\/tablesdb\/transactions": { + "get": { + "summary": "List transactions", + "operationId": "tablesDBListTransactions", + "tags": [ + "tablesDB" + ], + "description": "List transactions across all databases.", + "responses": { + "200": { + "description": "Transaction List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transactionList" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "listTransactions", + "group": "transactions", + "weight": 441, + "cookies": false, + "type": "", + "demo": "tablesdb\/list-transactions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/list-transactions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries).", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create transaction", + "operationId": "tablesDBCreateTransaction", + "tags": [ + "tablesDB" + ], + "description": "Create a new transaction.", + "responses": { + "201": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createTransaction", + "group": "transactions", + "weight": 437, + "cookies": false, + "type": "", + "demo": "tablesdb\/create-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/create-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "ttl": { + "type": "integer", + "description": "Seconds before the transaction expires.", + "x-example": 60 + } + } + } + } + } + } + } + }, + "\/tablesdb\/transactions\/{transactionId}": { + "get": { + "summary": "Get transaction", + "operationId": "tablesDBGetTransaction", + "tags": [ + "tablesDB" + ], + "description": "Get a transaction by its unique ID.", + "responses": { + "200": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "getTransaction", + "group": "transactions", + "weight": 438, + "cookies": false, + "type": "", + "demo": "tablesdb\/get-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/get-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update transaction", + "operationId": "tablesDBUpdateTransaction", + "tags": [ + "tablesDB" + ], + "description": "Update a transaction, to either commit or roll back its operations.", + "responses": { + "200": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateTransaction", + "group": "transactions", + "weight": 439, + "cookies": false, + "type": "", + "demo": "tablesdb\/update-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/update-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "commit": { + "type": "boolean", + "description": "Commit transaction?", + "x-example": false + }, + "rollback": { + "type": "boolean", + "description": "Rollback transaction?", + "x-example": false + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete transaction", + "operationId": "tablesDBDeleteTransaction", + "tags": [ + "tablesDB" + ], + "description": "Delete a transaction by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "deprecated": false, + "x-appwrite": { + "method": "deleteTransaction", + "group": "transactions", + "weight": 440, + "cookies": false, + "type": "", + "demo": "tablesdb\/delete-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/delete-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/tablesdb\/transactions\/{transactionId}\/operations": { + "post": { + "summary": "Create operations", + "operationId": "tablesDBCreateOperations", + "tags": [ + "tablesDB" + ], + "description": "Create multiple operations in a single transaction.", + "responses": { + "201": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createOperations", + "group": "transactions", + "weight": 442, + "cookies": false, + "type": "", + "demo": "tablesdb\/create-operations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/create-operations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "operations": { + "type": "array", + "description": "Array of staged operations.", + "x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"\",\n\t \"tableId\": \"\",\n\t \"rowId\": \"\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]", + "items": { + "type": "object" + } + } + } + } + } + } + } + } + }, "\/tablesdb\/{databaseId}\/tables\/{tableId}\/rows": { "get": { "summary": "List rows", @@ -7595,7 +8494,7 @@ "x-appwrite": { "method": "listRows", "group": "rows", - "weight": 427, + "weight": 433, "cookies": false, "type": "", "demo": "tablesdb\/list-rows.md", @@ -7657,6 +8556,16 @@ "default": [] }, "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" } ] }, @@ -7683,7 +8592,7 @@ "x-appwrite": { "method": "createRow", "group": "rows", - "weight": 419, + "weight": 425, "cookies": false, "type": "", "demo": "tablesdb\/create-row.md", @@ -7714,7 +8623,8 @@ "tableId", "rowId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -7796,6 +8706,11 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -7828,7 +8743,7 @@ "x-appwrite": { "method": "getRow", "group": "rows", - "weight": 420, + "weight": 426, "cookies": false, "type": "", "demo": "tablesdb\/get-row.md", @@ -7900,6 +8815,16 @@ "default": [] }, "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" } ] }, @@ -7926,7 +8851,7 @@ "x-appwrite": { "method": "upsertRow", "group": "rows", - "weight": 423, + "weight": 429, "cookies": false, "type": "", "demo": "tablesdb\/upsert-row.md", @@ -7957,7 +8882,8 @@ "tableId", "rowId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -8035,6 +8961,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -8065,7 +8996,7 @@ "x-appwrite": { "method": "updateRow", "group": "rows", - "weight": 421, + "weight": 427, "cookies": false, "type": "", "demo": "tablesdb\/update-row.md", @@ -8144,6 +9075,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -8167,7 +9103,7 @@ "x-appwrite": { "method": "deleteRow", "group": "rows", - "weight": 425, + "weight": 431, "cookies": false, "type": "", "demo": "tablesdb\/delete-row.md", @@ -8227,7 +9163,23 @@ }, "in": "path" } - ] + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" + } + } + } + } + } + } } }, "\/tablesdb\/{databaseId}\/tables\/{tableId}\/rows\/{rowId}\/{column}\/decrement": { @@ -8254,7 +9206,7 @@ "x-appwrite": { "method": "decrementRowColumn", "group": "rows", - "weight": 430, + "weight": 436, "cookies": false, "type": "", "demo": "tablesdb\/decrement-row-column.md", @@ -8340,6 +9292,11 @@ "type": "number", "description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.", "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -8372,7 +9329,7 @@ "x-appwrite": { "method": "incrementRowColumn", "group": "rows", - "weight": 429, + "weight": 435, "cookies": false, "type": "", "demo": "tablesdb\/increment-row-column.md", @@ -8458,6 +9415,11 @@ "type": "number", "description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.", "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -10039,6 +11001,34 @@ "localeCodes": "" } }, + "transactionList": { + "description": "Transaction List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of transactions that matched your query.", + "x-example": 5, + "format": "int32" + }, + "transactions": { + "type": "array", + "description": "List of transactions.", + "items": { + "$ref": "#\/components\/schemas\/transaction" + }, + "x-example": "" + } + }, + "required": [ + "total", + "transactions" + ], + "example": { + "total": 5, + "transactions": "" + } + }, "row": { "description": "Row", "type": "object", @@ -11954,6 +12944,59 @@ "recoveryCode": true } }, + "transaction": { + "description": "Transaction", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Transaction ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Transaction creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Transaction update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "status": { + "type": "string", + "description": "Current status of the transaction. One of: pending, committing, committed, rolled_back, failed.", + "x-example": "pending" + }, + "operations": { + "type": "integer", + "description": "Number of operations in the transaction.", + "x-example": 5, + "format": "int32" + }, + "expiresAt": { + "type": "string", + "description": "Expiration time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "status", + "operations", + "expiresAt" + ], + "example": { + "$id": "259125845563242502", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "status": "pending", + "operations": 5, + "expiresAt": "2020-10-15T06:38:00.000+00:00" + } + }, "subscriber": { "description": "Subscriber", "type": "object", diff --git a/app/config/specs/open-api3-1.8.x-console.json b/app/config/specs/open-api3-1.8.x-console.json index cf85dd57ed..c086fe03d0 100644 --- a/app/config/specs/open-api3-1.8.x-console.json +++ b/app/config/specs/open-api3-1.8.x-console.json @@ -4992,7 +4992,7 @@ "x-appwrite": { "method": "getResource", "group": null, - "weight": 496, + "weight": 508, "cookies": false, "type": "", "demo": "console\/get-resource.md", @@ -5309,6 +5309,424 @@ } } }, + "\/databases\/transactions": { + "get": { + "summary": "List transactions", + "operationId": "databasesListTransactions", + "tags": [ + "databases" + ], + "description": "List transactions across all databases.", + "responses": { + "200": { + "description": "Transaction List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transactionList" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "listTransactions", + "group": "transactions", + "weight": 376, + "cookies": false, + "type": "", + "demo": "databases\/list-transactions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-transactions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries).", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create transaction", + "operationId": "databasesCreateTransaction", + "tags": [ + "databases" + ], + "description": "Create a new transaction.", + "responses": { + "201": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createTransaction", + "group": "transactions", + "weight": 372, + "cookies": false, + "type": "", + "demo": "databases\/create-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "ttl": { + "type": "integer", + "description": "Seconds before the transaction expires.", + "x-example": 60 + } + } + } + } + } + } + } + }, + "\/databases\/transactions\/{transactionId}": { + "get": { + "summary": "Get transaction", + "operationId": "databasesGetTransaction", + "tags": [ + "databases" + ], + "description": "Get a transaction by its unique ID.", + "responses": { + "200": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "getTransaction", + "group": "transactions", + "weight": 373, + "cookies": false, + "type": "", + "demo": "databases\/get-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update transaction", + "operationId": "databasesUpdateTransaction", + "tags": [ + "databases" + ], + "description": "Update a transaction, to either commit or roll back its operations.", + "responses": { + "200": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateTransaction", + "group": "transactions", + "weight": 374, + "cookies": false, + "type": "", + "demo": "databases\/update-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "commit": { + "type": "boolean", + "description": "Commit transaction?", + "x-example": false + }, + "rollback": { + "type": "boolean", + "description": "Rollback transaction?", + "x-example": false + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete transaction", + "operationId": "databasesDeleteTransaction", + "tags": [ + "databases" + ], + "description": "Delete a transaction by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "deprecated": false, + "x-appwrite": { + "method": "deleteTransaction", + "group": "transactions", + "weight": 375, + "cookies": false, + "type": "", + "demo": "databases\/delete-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/databases\/transactions\/{transactionId}\/operations": { + "post": { + "summary": "Create operations", + "operationId": "databasesCreateOperations", + "tags": [ + "databases" + ], + "description": "Create multiple operations in a single transaction.", + "responses": { + "201": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createOperations", + "group": "transactions", + "weight": 377, + "cookies": false, + "type": "", + "demo": "databases\/create-operations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-operations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "operations": { + "type": "array", + "description": "Array of staged operations.", + "x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"\",\n\t \"collectionId\": \"\",\n\t \"documentId\": \"\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]", + "items": { + "type": "object" + } + } + } + } + } + } + } + } + }, "\/databases\/usage": { "get": { "summary": "Get databases usage stats", @@ -9564,6 +9982,16 @@ "default": [] }, "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" } ] }, @@ -9622,7 +10050,8 @@ "collectionId", "documentId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -9653,7 +10082,8 @@ "parameters": [ "databaseId", "collectionId", - "documents" + "documents", + "transactionId" ], "required": [ "databaseId", @@ -9738,6 +10168,11 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -9797,7 +10232,8 @@ "parameters": [ "databaseId", "collectionId", - "documents" + "documents", + "transactionId" ], "required": [ "databaseId", @@ -9863,6 +10299,11 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } }, "required": [ @@ -9964,6 +10405,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -10057,6 +10503,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -10162,6 +10613,16 @@ "default": [] }, "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" } ] }, @@ -10220,7 +10681,8 @@ "collectionId", "documentId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -10303,6 +10765,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } }, "required": [ @@ -10416,6 +10883,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -10500,7 +10972,23 @@ }, "in": "path" } - ] + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" + } + } + } + } + } + } } }, "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/logs": { @@ -10711,6 +11199,11 @@ "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -10830,6 +11323,11 @@ "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -11064,7 +11562,7 @@ "tags": [ "databases" ], - "description": "Get index by ID.", + "description": "Get an index by its unique ID.", "responses": { "200": { "description": "Index", @@ -11644,7 +12142,7 @@ "x-appwrite": { "method": "list", "group": "functions", - "weight": 440, + "weight": 452, "cookies": false, "type": "", "demo": "functions\/list.md", @@ -11717,7 +12215,7 @@ "x-appwrite": { "method": "create", "group": "functions", - "weight": 437, + "weight": 449, "cookies": false, "type": "", "demo": "functions\/create.md", @@ -11950,7 +12448,7 @@ "x-appwrite": { "method": "listRuntimes", "group": "runtimes", - "weight": 442, + "weight": 454, "cookies": false, "type": "", "demo": "functions\/list-runtimes.md", @@ -11999,7 +12497,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "runtimes", - "weight": 443, + "weight": 455, "cookies": false, "type": "", "demo": "functions\/list-specifications.md", @@ -12049,7 +12547,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 466, + "weight": 478, "cookies": false, "type": "", "demo": "functions\/list-templates.md", @@ -12149,7 +12647,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 465, + "weight": 477, "cookies": false, "type": "", "demo": "functions\/get-template.md", @@ -12209,7 +12707,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 459, + "weight": 471, "cookies": false, "type": "", "demo": "functions\/list-usage.md", @@ -12281,7 +12779,7 @@ "x-appwrite": { "method": "get", "group": "functions", - "weight": 438, + "weight": 450, "cookies": false, "type": "", "demo": "functions\/get.md", @@ -12340,7 +12838,7 @@ "x-appwrite": { "method": "update", "group": "functions", - "weight": 439, + "weight": 451, "cookies": false, "type": "", "demo": "functions\/update.md", @@ -12570,7 +13068,7 @@ "x-appwrite": { "method": "delete", "group": "functions", - "weight": 441, + "weight": 453, "cookies": false, "type": "", "demo": "functions\/delete.md", @@ -12631,7 +13129,7 @@ "x-appwrite": { "method": "updateFunctionDeployment", "group": "functions", - "weight": 446, + "weight": 458, "cookies": false, "type": "", "demo": "functions\/update-function-deployment.md", @@ -12711,7 +13209,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 447, + "weight": 459, "cookies": false, "type": "", "demo": "functions\/list-deployments.md", @@ -12794,7 +13292,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 444, + "weight": 456, "cookies": false, "type": "upload", "demo": "functions\/create-deployment.md", @@ -12890,7 +13388,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 452, + "weight": 464, "cookies": false, "type": "", "demo": "functions\/create-duplicate-deployment.md", @@ -12975,7 +13473,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 449, + "weight": 461, "cookies": false, "type": "", "demo": "functions\/create-template-deployment.md", @@ -13078,7 +13576,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 450, + "weight": 462, "cookies": false, "type": "", "demo": "functions\/create-vcs-deployment.md", @@ -13175,7 +13673,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 445, + "weight": 457, "cookies": false, "type": "", "demo": "functions\/get-deployment.md", @@ -13237,7 +13735,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 448, + "weight": 460, "cookies": false, "type": "", "demo": "functions\/delete-deployment.md", @@ -13301,7 +13799,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 451, + "weight": 463, "cookies": false, "type": "location", "demo": "functions\/get-deployment-download.md", @@ -13391,7 +13889,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 453, + "weight": 465, "cookies": false, "type": "", "demo": "functions\/update-deployment-status.md", @@ -13462,7 +13960,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 456, + "weight": 468, "cookies": false, "type": "", "demo": "functions\/list-executions.md", @@ -13537,7 +14035,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 454, + "weight": 466, "cookies": false, "type": "", "demo": "functions\/create-execution.md", @@ -13613,9 +14111,9 @@ "x-enum-keys": [] }, "headers": { - "type": "string", + "type": "object", "description": "HTTP headers of execution. Defaults to empty.", - "x-example": null + "x-example": "{}" }, "scheduledAt": { "type": "string", @@ -13653,7 +14151,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 455, + "weight": 467, "cookies": false, "type": "", "demo": "functions\/get-execution.md", @@ -13718,7 +14216,7 @@ "x-appwrite": { "method": "deleteExecution", "group": "executions", - "weight": 457, + "weight": 469, "cookies": false, "type": "", "demo": "functions\/delete-execution.md", @@ -13789,7 +14287,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 458, + "weight": 470, "cookies": false, "type": "", "demo": "functions\/get-usage.md", @@ -13871,7 +14369,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 462, + "weight": 474, "cookies": false, "type": "", "demo": "functions\/list-variables.md", @@ -13930,7 +14428,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 460, + "weight": 472, "cookies": false, "type": "", "demo": "functions\/create-variable.md", @@ -14021,7 +14519,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 461, + "weight": 473, "cookies": false, "type": "", "demo": "functions\/get-variable.md", @@ -14090,7 +14588,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 463, + "weight": 475, "cookies": false, "type": "", "demo": "functions\/update-variable.md", @@ -14181,7 +14679,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 464, + "weight": 476, "cookies": false, "type": "", "demo": "functions\/delete-variable.md", @@ -16515,7 +17013,7 @@ "image": { "type": "string", "description": "Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as :.", - "x-example": "[ID1:ID2]" + "x-example": "" }, "icon": { "type": "string", @@ -16696,7 +17194,7 @@ "image": { "type": "string", "description": "Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as :.", - "x-example": "[ID1:ID2]" + "x-example": "" }, "icon": { "type": "string", @@ -21294,7 +21792,7 @@ "resourceId": { "type": "string", "description": "Composite ID in the format {databaseId:collectionId}, identifying a collection within a database.", - "x-example": "[ID1:ID2]" + "x-example": "" }, "internalFile": { "type": "boolean", @@ -22537,7 +23035,7 @@ "x-appwrite": { "method": "list", "group": "projects", - "weight": 436, + "weight": 448, "cookies": false, "type": "", "demo": "projects\/list.md", @@ -24172,7 +24670,7 @@ "x-appwrite": { "method": "listDevKeys", "group": "devKeys", - "weight": 434, + "weight": 446, "cookies": false, "type": "", "demo": "projects\/list-dev-keys.md", @@ -24210,7 +24708,10 @@ "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: accessedAt, expire", "required": false, "schema": { - "type": "string", + "type": "array", + "items": { + "type": "string" + }, "default": [] }, "in": "query" @@ -24240,7 +24741,7 @@ "x-appwrite": { "method": "createDevKey", "group": "devKeys", - "weight": 431, + "weight": 443, "cookies": false, "type": "", "demo": "projects\/create-dev-key.md", @@ -24325,7 +24826,7 @@ "x-appwrite": { "method": "getDevKey", "group": "devKeys", - "weight": 433, + "weight": 445, "cookies": false, "type": "", "demo": "projects\/get-dev-key.md", @@ -24393,7 +24894,7 @@ "x-appwrite": { "method": "updateDevKey", "group": "devKeys", - "weight": 432, + "weight": 444, "cookies": false, "type": "", "demo": "projects\/update-dev-key.md", @@ -24479,7 +24980,7 @@ "x-appwrite": { "method": "deleteDevKey", "group": "devKeys", - "weight": 435, + "weight": 447, "cookies": false, "type": "", "demo": "projects\/delete-dev-key.md", @@ -28313,7 +28814,7 @@ "x-appwrite": { "method": "listRules", "group": null, - "weight": 502, + "weight": 514, "cookies": false, "type": "", "demo": "proxy\/list-rules.md", @@ -28387,7 +28888,7 @@ "x-appwrite": { "method": "createAPIRule", "group": null, - "weight": 497, + "weight": 509, "cookies": false, "type": "", "demo": "proxy\/create-api-rule.md", @@ -28454,7 +28955,7 @@ "x-appwrite": { "method": "createFunctionRule", "group": null, - "weight": 499, + "weight": 511, "cookies": false, "type": "", "demo": "proxy\/create-function-rule.md", @@ -28532,7 +29033,7 @@ "x-appwrite": { "method": "createRedirectRule", "group": null, - "weight": 500, + "weight": 512, "cookies": false, "type": "", "demo": "proxy\/create-redirect-rule.md", @@ -28645,7 +29146,7 @@ "x-appwrite": { "method": "createSiteRule", "group": null, - "weight": 498, + "weight": 510, "cookies": false, "type": "", "demo": "proxy\/create-site-rule.md", @@ -28723,7 +29224,7 @@ "x-appwrite": { "method": "getRule", "group": null, - "weight": 501, + "weight": 513, "cookies": false, "type": "", "demo": "proxy\/get-rule.md", @@ -28774,7 +29275,7 @@ "x-appwrite": { "method": "deleteRule", "group": null, - "weight": 503, + "weight": 515, "cookies": false, "type": "", "demo": "proxy\/delete-rule.md", @@ -28834,7 +29335,7 @@ "x-appwrite": { "method": "updateRuleVerification", "group": null, - "weight": 504, + "weight": 516, "cookies": false, "type": "", "demo": "proxy\/update-rule-verification.md", @@ -28894,7 +29395,7 @@ "x-appwrite": { "method": "list", "group": "sites", - "weight": 469, + "weight": 481, "cookies": false, "type": "", "demo": "sites\/list.md", @@ -28923,7 +29424,10 @@ "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, enabled, framework, deploymentId, buildCommand, installCommand, outputDirectory, installationId", "required": false, "schema": { - "type": "string", + "type": "array", + "items": { + "type": "string" + }, "default": [] }, "in": "query" @@ -28964,7 +29468,7 @@ "x-appwrite": { "method": "create", "group": "sites", - "weight": 467, + "weight": 479, "cookies": false, "type": "", "demo": "sites\/create.md", @@ -29213,7 +29717,7 @@ "x-appwrite": { "method": "listFrameworks", "group": "frameworks", - "weight": 472, + "weight": 484, "cookies": false, "type": "", "demo": "sites\/list-frameworks.md", @@ -29262,7 +29766,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 495, + "weight": 507, "cookies": false, "type": "", "demo": "sites\/list-specifications.md", @@ -29312,7 +29816,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 491, + "weight": 503, "cookies": false, "type": "", "demo": "sites\/list-templates.md", @@ -29412,7 +29916,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 492, + "weight": 504, "cookies": false, "type": "", "demo": "sites\/get-template.md", @@ -29472,7 +29976,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 493, + "weight": 505, "cookies": false, "type": "", "demo": "sites\/list-usage.md", @@ -29544,7 +30048,7 @@ "x-appwrite": { "method": "get", "group": "sites", - "weight": 468, + "weight": 480, "cookies": false, "type": "", "demo": "sites\/get.md", @@ -29603,7 +30107,7 @@ "x-appwrite": { "method": "update", "group": "sites", - "weight": 470, + "weight": 482, "cookies": false, "type": "", "demo": "sites\/update.md", @@ -29848,7 +30352,7 @@ "x-appwrite": { "method": "delete", "group": "sites", - "weight": 471, + "weight": 483, "cookies": false, "type": "", "demo": "sites\/delete.md", @@ -29909,7 +30413,7 @@ "x-appwrite": { "method": "updateSiteDeployment", "group": "sites", - "weight": 478, + "weight": 490, "cookies": false, "type": "", "demo": "sites\/update-site-deployment.md", @@ -29989,7 +30493,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 477, + "weight": 489, "cookies": false, "type": "", "demo": "sites\/list-deployments.md", @@ -30072,7 +30576,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 473, + "weight": 485, "cookies": false, "type": "upload", "demo": "sites\/create-deployment.md", @@ -30173,7 +30677,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 481, + "weight": 493, "cookies": false, "type": "", "demo": "sites\/create-duplicate-deployment.md", @@ -30253,7 +30757,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 474, + "weight": 486, "cookies": false, "type": "", "demo": "sites\/create-template-deployment.md", @@ -30356,7 +30860,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 475, + "weight": 487, "cookies": false, "type": "", "demo": "sites\/create-vcs-deployment.md", @@ -30454,7 +30958,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 476, + "weight": 488, "cookies": false, "type": "", "demo": "sites\/get-deployment.md", @@ -30516,7 +31020,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 479, + "weight": 491, "cookies": false, "type": "", "demo": "sites\/delete-deployment.md", @@ -30580,7 +31084,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 480, + "weight": 492, "cookies": false, "type": "location", "demo": "sites\/get-deployment-download.md", @@ -30670,7 +31174,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 482, + "weight": 494, "cookies": false, "type": "", "demo": "sites\/update-deployment-status.md", @@ -30741,7 +31245,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 484, + "weight": 496, "cookies": false, "type": "", "demo": "sites\/list-logs.md", @@ -30780,7 +31284,10 @@ "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: trigger, status, responseStatusCode, duration, requestMethod, requestPath, deploymentId", "required": false, "schema": { - "type": "string", + "type": "array", + "items": { + "type": "string" + }, "default": [] }, "in": "query" @@ -30812,7 +31319,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 483, + "weight": 495, "cookies": false, "type": "", "demo": "sites\/get-log.md", @@ -30874,7 +31381,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 485, + "weight": 497, "cookies": false, "type": "", "demo": "sites\/delete-log.md", @@ -30945,7 +31452,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 494, + "weight": 506, "cookies": false, "type": "", "demo": "sites\/get-usage.md", @@ -31027,7 +31534,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 488, + "weight": 500, "cookies": false, "type": "", "demo": "sites\/list-variables.md", @@ -31086,7 +31593,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 486, + "weight": 498, "cookies": false, "type": "", "demo": "sites\/create-variable.md", @@ -31177,7 +31684,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 487, + "weight": 499, "cookies": false, "type": "", "demo": "sites\/get-variable.md", @@ -31246,7 +31753,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 489, + "weight": 501, "cookies": false, "type": "", "demo": "sites\/update-variable.md", @@ -31337,7 +31844,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 490, + "weight": 502, "cookies": false, "type": "", "demo": "sites\/delete-variable.md", @@ -32809,7 +33316,7 @@ "x-appwrite": { "method": "list", "group": "tablesdb", - "weight": 376, + "weight": 382, "cookies": false, "type": "", "demo": "tablesdb\/list.md", @@ -32882,7 +33389,7 @@ "x-appwrite": { "method": "create", "group": "tablesdb", - "weight": 372, + "weight": 378, "cookies": false, "type": "", "demo": "tablesdb\/create.md", @@ -32937,6 +33444,424 @@ } } }, + "\/tablesdb\/transactions": { + "get": { + "summary": "List transactions", + "operationId": "tablesDBListTransactions", + "tags": [ + "tablesDB" + ], + "description": "List transactions across all databases.", + "responses": { + "200": { + "description": "Transaction List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transactionList" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "listTransactions", + "group": "transactions", + "weight": 441, + "cookies": false, + "type": "", + "demo": "tablesdb\/list-transactions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/list-transactions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries).", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create transaction", + "operationId": "tablesDBCreateTransaction", + "tags": [ + "tablesDB" + ], + "description": "Create a new transaction.", + "responses": { + "201": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createTransaction", + "group": "transactions", + "weight": 437, + "cookies": false, + "type": "", + "demo": "tablesdb\/create-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/create-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "ttl": { + "type": "integer", + "description": "Seconds before the transaction expires.", + "x-example": 60 + } + } + } + } + } + } + } + }, + "\/tablesdb\/transactions\/{transactionId}": { + "get": { + "summary": "Get transaction", + "operationId": "tablesDBGetTransaction", + "tags": [ + "tablesDB" + ], + "description": "Get a transaction by its unique ID.", + "responses": { + "200": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "getTransaction", + "group": "transactions", + "weight": 438, + "cookies": false, + "type": "", + "demo": "tablesdb\/get-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/get-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update transaction", + "operationId": "tablesDBUpdateTransaction", + "tags": [ + "tablesDB" + ], + "description": "Update a transaction, to either commit or roll back its operations.", + "responses": { + "200": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateTransaction", + "group": "transactions", + "weight": 439, + "cookies": false, + "type": "", + "demo": "tablesdb\/update-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/update-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "commit": { + "type": "boolean", + "description": "Commit transaction?", + "x-example": false + }, + "rollback": { + "type": "boolean", + "description": "Rollback transaction?", + "x-example": false + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete transaction", + "operationId": "tablesDBDeleteTransaction", + "tags": [ + "tablesDB" + ], + "description": "Delete a transaction by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "deprecated": false, + "x-appwrite": { + "method": "deleteTransaction", + "group": "transactions", + "weight": 440, + "cookies": false, + "type": "", + "demo": "tablesdb\/delete-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/delete-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/tablesdb\/transactions\/{transactionId}\/operations": { + "post": { + "summary": "Create operations", + "operationId": "tablesDBCreateOperations", + "tags": [ + "tablesDB" + ], + "description": "Create multiple operations in a single transaction.", + "responses": { + "201": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createOperations", + "group": "transactions", + "weight": 442, + "cookies": false, + "type": "", + "demo": "tablesdb\/create-operations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/create-operations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "operations": { + "type": "array", + "description": "Array of staged operations.", + "x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"\",\n\t \"tableId\": \"\",\n\t \"rowId\": \"\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]", + "items": { + "type": "object" + } + } + } + } + } + } + } + } + }, "\/tablesdb\/usage": { "get": { "summary": "Get TablesDB usage stats", @@ -32961,7 +33886,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 378, + "weight": 384, "cookies": false, "type": "", "demo": "tablesdb\/list-usage.md", @@ -33058,7 +33983,7 @@ "x-appwrite": { "method": "get", "group": "tablesdb", - "weight": 373, + "weight": 379, "cookies": false, "type": "", "demo": "tablesdb\/get.md", @@ -33117,7 +34042,7 @@ "x-appwrite": { "method": "update", "group": "tablesdb", - "weight": 374, + "weight": 380, "cookies": false, "type": "", "demo": "tablesdb\/update.md", @@ -33193,7 +34118,7 @@ "x-appwrite": { "method": "delete", "group": "tablesdb", - "weight": 375, + "weight": 381, "cookies": false, "type": "", "demo": "tablesdb\/delete.md", @@ -33254,7 +34179,7 @@ "x-appwrite": { "method": "listTables", "group": "tables", - "weight": 383, + "weight": 389, "cookies": false, "type": "", "demo": "tablesdb\/list-tables.md", @@ -33340,7 +34265,7 @@ "x-appwrite": { "method": "createTable", "group": "tables", - "weight": 379, + "weight": 385, "cookies": false, "type": "", "demo": "tablesdb\/create-table.md", @@ -33447,7 +34372,7 @@ "x-appwrite": { "method": "getTable", "group": "tables", - "weight": 380, + "weight": 386, "cookies": false, "type": "", "demo": "tablesdb\/get-table.md", @@ -33519,7 +34444,7 @@ "x-appwrite": { "method": "updateTable", "group": "tables", - "weight": 381, + "weight": 387, "cookies": false, "type": "", "demo": "tablesdb\/update-table.md", @@ -33621,7 +34546,7 @@ "x-appwrite": { "method": "deleteTable", "group": "tables", - "weight": 382, + "weight": 388, "cookies": false, "type": "", "demo": "tablesdb\/delete-table.md", @@ -33695,7 +34620,7 @@ "x-appwrite": { "method": "listColumns", "group": "columns", - "weight": 388, + "weight": 394, "cookies": false, "type": "", "demo": "tablesdb\/list-columns.md", @@ -33782,7 +34707,7 @@ "x-appwrite": { "method": "createBooleanColumn", "group": "columns", - "weight": 389, + "weight": 395, "cookies": false, "type": "", "demo": "tablesdb\/create-boolean-column.md", @@ -33891,7 +34816,7 @@ "x-appwrite": { "method": "updateBooleanColumn", "group": "columns", - "weight": 390, + "weight": 396, "cookies": false, "type": "", "demo": "tablesdb\/update-boolean-column.md", @@ -34005,7 +34930,7 @@ "x-appwrite": { "method": "createDatetimeColumn", "group": "columns", - "weight": 391, + "weight": 397, "cookies": false, "type": "", "demo": "tablesdb\/create-datetime-column.md", @@ -34114,7 +35039,7 @@ "x-appwrite": { "method": "updateDatetimeColumn", "group": "columns", - "weight": 392, + "weight": 398, "cookies": false, "type": "", "demo": "tablesdb\/update-datetime-column.md", @@ -34228,7 +35153,7 @@ "x-appwrite": { "method": "createEmailColumn", "group": "columns", - "weight": 393, + "weight": 399, "cookies": false, "type": "", "demo": "tablesdb\/create-email-column.md", @@ -34337,7 +35262,7 @@ "x-appwrite": { "method": "updateEmailColumn", "group": "columns", - "weight": 394, + "weight": 400, "cookies": false, "type": "", "demo": "tablesdb\/update-email-column.md", @@ -34451,7 +35376,7 @@ "x-appwrite": { "method": "createEnumColumn", "group": "columns", - "weight": 395, + "weight": 401, "cookies": false, "type": "", "demo": "tablesdb\/create-enum-column.md", @@ -34569,7 +35494,7 @@ "x-appwrite": { "method": "updateEnumColumn", "group": "columns", - "weight": 396, + "weight": 402, "cookies": false, "type": "", "demo": "tablesdb\/update-enum-column.md", @@ -34692,7 +35617,7 @@ "x-appwrite": { "method": "createFloatColumn", "group": "columns", - "weight": 397, + "weight": 403, "cookies": false, "type": "", "demo": "tablesdb\/create-float-column.md", @@ -34811,7 +35736,7 @@ "x-appwrite": { "method": "updateFloatColumn", "group": "columns", - "weight": 398, + "weight": 404, "cookies": false, "type": "", "demo": "tablesdb\/update-float-column.md", @@ -34935,7 +35860,7 @@ "x-appwrite": { "method": "createIntegerColumn", "group": "columns", - "weight": 399, + "weight": 405, "cookies": false, "type": "", "demo": "tablesdb\/create-integer-column.md", @@ -35054,7 +35979,7 @@ "x-appwrite": { "method": "updateIntegerColumn", "group": "columns", - "weight": 400, + "weight": 406, "cookies": false, "type": "", "demo": "tablesdb\/update-integer-column.md", @@ -35178,7 +36103,7 @@ "x-appwrite": { "method": "createIpColumn", "group": "columns", - "weight": 401, + "weight": 407, "cookies": false, "type": "", "demo": "tablesdb\/create-ip-column.md", @@ -35287,7 +36212,7 @@ "x-appwrite": { "method": "updateIpColumn", "group": "columns", - "weight": 402, + "weight": 408, "cookies": false, "type": "", "demo": "tablesdb\/update-ip-column.md", @@ -35401,7 +36326,7 @@ "x-appwrite": { "method": "createLineColumn", "group": "columns", - "weight": 403, + "weight": 409, "cookies": false, "type": "", "demo": "tablesdb\/create-line-column.md", @@ -35513,7 +36438,7 @@ "x-appwrite": { "method": "updateLineColumn", "group": "columns", - "weight": 404, + "weight": 410, "cookies": false, "type": "", "demo": "tablesdb\/update-line-column.md", @@ -35633,7 +36558,7 @@ "x-appwrite": { "method": "createPointColumn", "group": "columns", - "weight": 405, + "weight": 411, "cookies": false, "type": "", "demo": "tablesdb\/create-point-column.md", @@ -35745,7 +36670,7 @@ "x-appwrite": { "method": "updatePointColumn", "group": "columns", - "weight": 406, + "weight": 412, "cookies": false, "type": "", "demo": "tablesdb\/update-point-column.md", @@ -35865,7 +36790,7 @@ "x-appwrite": { "method": "createPolygonColumn", "group": "columns", - "weight": 407, + "weight": 413, "cookies": false, "type": "", "demo": "tablesdb\/create-polygon-column.md", @@ -35977,7 +36902,7 @@ "x-appwrite": { "method": "updatePolygonColumn", "group": "columns", - "weight": 408, + "weight": 414, "cookies": false, "type": "", "demo": "tablesdb\/update-polygon-column.md", @@ -36097,7 +37022,7 @@ "x-appwrite": { "method": "createRelationshipColumn", "group": "columns", - "weight": 409, + "weight": 415, "cookies": false, "type": "", "demo": "tablesdb\/create-relationship-column.md", @@ -36231,7 +37156,7 @@ "x-appwrite": { "method": "createStringColumn", "group": "columns", - "weight": 411, + "weight": 417, "cookies": false, "type": "", "demo": "tablesdb\/create-string-column.md", @@ -36351,7 +37276,7 @@ "x-appwrite": { "method": "updateStringColumn", "group": "columns", - "weight": 412, + "weight": 418, "cookies": false, "type": "", "demo": "tablesdb\/update-string-column.md", @@ -36470,7 +37395,7 @@ "x-appwrite": { "method": "createUrlColumn", "group": "columns", - "weight": 413, + "weight": 419, "cookies": false, "type": "", "demo": "tablesdb\/create-url-column.md", @@ -36579,7 +37504,7 @@ "x-appwrite": { "method": "updateUrlColumn", "group": "columns", - "weight": 414, + "weight": 420, "cookies": false, "type": "", "demo": "tablesdb\/update-url-column.md", @@ -36724,7 +37649,7 @@ "x-appwrite": { "method": "getColumn", "group": "columns", - "weight": 386, + "weight": 392, "cookies": false, "type": "", "demo": "tablesdb\/get-column.md", @@ -36798,7 +37723,7 @@ "x-appwrite": { "method": "deleteColumn", "group": "columns", - "weight": 387, + "weight": 393, "cookies": false, "type": "", "demo": "tablesdb\/delete-column.md", @@ -36881,7 +37806,7 @@ "x-appwrite": { "method": "updateRelationshipColumn", "group": "columns", - "weight": 410, + "weight": 416, "cookies": false, "type": "", "demo": "tablesdb\/update-relationship-column.md", @@ -36992,7 +37917,7 @@ "x-appwrite": { "method": "listIndexes", "group": "indexes", - "weight": 418, + "weight": 424, "cookies": false, "type": "", "demo": "tablesdb\/list-indexes.md", @@ -37077,7 +38002,7 @@ "x-appwrite": { "method": "createIndex", "group": "indexes", - "weight": 415, + "weight": 421, "cookies": false, "type": "", "demo": "tablesdb\/create-index.md", @@ -37209,7 +38134,7 @@ "x-appwrite": { "method": "getIndex", "group": "indexes", - "weight": 416, + "weight": 422, "cookies": false, "type": "", "demo": "tablesdb\/get-index.md", @@ -37283,7 +38208,7 @@ "x-appwrite": { "method": "deleteIndex", "group": "indexes", - "weight": 417, + "weight": 423, "cookies": false, "type": "", "demo": "tablesdb\/delete-index.md", @@ -37366,7 +38291,7 @@ "x-appwrite": { "method": "listTableLogs", "group": "tables", - "weight": 384, + "weight": 390, "cookies": false, "type": "", "demo": "tablesdb\/list-table-logs.md", @@ -37452,7 +38377,7 @@ "x-appwrite": { "method": "listRows", "group": "rows", - "weight": 427, + "weight": 433, "cookies": false, "type": "", "demo": "tablesdb\/list-rows.md", @@ -37514,6 +38439,16 @@ "default": [] }, "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" } ] }, @@ -37540,7 +38475,7 @@ "x-appwrite": { "method": "createRow", "group": "rows", - "weight": 419, + "weight": 425, "cookies": false, "type": "", "demo": "tablesdb\/create-row.md", @@ -37571,7 +38506,8 @@ "tableId", "rowId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -37598,7 +38534,8 @@ "parameters": [ "databaseId", "tableId", - "rows" + "rows", + "transactionId" ], "required": [ "databaseId", @@ -37679,6 +38616,11 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -37709,7 +38651,7 @@ "x-appwrite": { "method": "upsertRows", "group": "rows", - "weight": 424, + "weight": 430, "cookies": false, "type": "", "demo": "tablesdb\/upsert-rows.md", @@ -37737,7 +38679,8 @@ "parameters": [ "databaseId", "tableId", - "rows" + "rows", + "transactionId" ], "required": [ "databaseId", @@ -37799,6 +38742,11 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } }, "required": [ @@ -37832,7 +38780,7 @@ "x-appwrite": { "method": "updateRows", "group": "rows", - "weight": 422, + "weight": 428, "cookies": false, "type": "", "demo": "tablesdb\/update-rows.md", @@ -37899,6 +38847,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -37929,7 +38882,7 @@ "x-appwrite": { "method": "deleteRows", "group": "rows", - "weight": 426, + "weight": 432, "cookies": false, "type": "", "demo": "tablesdb\/delete-rows.md", @@ -37991,6 +38944,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -38023,7 +38981,7 @@ "x-appwrite": { "method": "getRow", "group": "rows", - "weight": 420, + "weight": 426, "cookies": false, "type": "", "demo": "tablesdb\/get-row.md", @@ -38095,6 +39053,16 @@ "default": [] }, "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" } ] }, @@ -38121,7 +39089,7 @@ "x-appwrite": { "method": "upsertRow", "group": "rows", - "weight": 423, + "weight": 429, "cookies": false, "type": "", "demo": "tablesdb\/upsert-row.md", @@ -38152,7 +39120,8 @@ "tableId", "rowId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -38230,6 +39199,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -38260,7 +39234,7 @@ "x-appwrite": { "method": "updateRow", "group": "rows", - "weight": 421, + "weight": 427, "cookies": false, "type": "", "demo": "tablesdb\/update-row.md", @@ -38339,6 +39313,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -38362,7 +39341,7 @@ "x-appwrite": { "method": "deleteRow", "group": "rows", - "weight": 425, + "weight": 431, "cookies": false, "type": "", "demo": "tablesdb\/delete-row.md", @@ -38422,7 +39401,23 @@ }, "in": "path" } - ] + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" + } + } + } + } + } + } } }, "\/tablesdb\/{databaseId}\/tables\/{tableId}\/rows\/{rowId}\/logs": { @@ -38449,7 +39444,7 @@ "x-appwrite": { "method": "listRowLogs", "group": "logs", - "weight": 428, + "weight": 434, "cookies": false, "type": "", "demo": "tablesdb\/list-row-logs.md", @@ -38545,7 +39540,7 @@ "x-appwrite": { "method": "decrementRowColumn", "group": "rows", - "weight": 430, + "weight": 436, "cookies": false, "type": "", "demo": "tablesdb\/decrement-row-column.md", @@ -38631,6 +39626,11 @@ "type": "number", "description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.", "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -38663,7 +39663,7 @@ "x-appwrite": { "method": "incrementRowColumn", "group": "rows", - "weight": 429, + "weight": 435, "cookies": false, "type": "", "demo": "tablesdb\/increment-row-column.md", @@ -38749,6 +39749,11 @@ "type": "number", "description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.", "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -38781,7 +39786,7 @@ "x-appwrite": { "method": "getTableUsage", "group": null, - "weight": 385, + "weight": 391, "cookies": false, "type": "", "demo": "tablesdb\/get-table-usage.md", @@ -38876,7 +39881,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 377, + "weight": 383, "cookies": false, "type": "", "demo": "tablesdb\/get-usage.md", @@ -40088,7 +41093,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 507, + "weight": 519, "cookies": false, "type": "", "demo": "tokens\/list.md", @@ -40138,7 +41143,10 @@ "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: expire", "required": false, "schema": { - "type": "string", + "type": "array", + "items": { + "type": "string" + }, "default": [] }, "in": "query" @@ -40168,7 +41176,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 505, + "weight": 517, "cookies": false, "type": "", "demo": "tokens\/create-file-token.md", @@ -40257,7 +41265,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 506, + "weight": 518, "cookies": false, "type": "", "demo": "tokens\/get.md", @@ -40317,7 +41325,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 508, + "weight": 520, "cookies": false, "type": "", "demo": "tokens\/update.md", @@ -40387,7 +41395,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 509, + "weight": 521, "cookies": false, "type": "", "demo": "tokens\/delete.md", @@ -46211,6 +47219,34 @@ "targets": "" } }, + "transactionList": { + "description": "Transaction List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of transactions that matched your query.", + "x-example": 5, + "format": "int32" + }, + "transactions": { + "type": "array", + "description": "List of transactions.", + "items": { + "$ref": "#\/components\/schemas\/transaction" + }, + "x-example": "" + } + }, + "required": [ + "total", + "transactions" + ], + "example": { + "total": 5, + "transactions": "" + } + }, "migrationList": { "description": "Migrations List", "type": "object", @@ -56890,6 +57926,59 @@ "subscribe": "users" } }, + "transaction": { + "description": "Transaction", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Transaction ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Transaction creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Transaction update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "status": { + "type": "string", + "description": "Current status of the transaction. One of: pending, committing, committed, rolled_back, failed.", + "x-example": "pending" + }, + "operations": { + "type": "integer", + "description": "Number of operations in the transaction.", + "x-example": 5, + "format": "int32" + }, + "expiresAt": { + "type": "string", + "description": "Expiration time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "status", + "operations", + "expiresAt" + ], + "example": { + "$id": "259125845563242502", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "status": "pending", + "operations": 5, + "expiresAt": "2020-10-15T06:38:00.000+00:00" + } + }, "subscriber": { "description": "Subscriber", "type": "object", diff --git a/app/config/specs/open-api3-1.8.x-server.json b/app/config/specs/open-api3-1.8.x-server.json index 16e861ba9f..49adaeeefa 100644 --- a/app/config/specs/open-api3-1.8.x-server.json +++ b/app/config/specs/open-api3-1.8.x-server.json @@ -4851,6 +4851,436 @@ } } }, + "\/databases\/transactions": { + "get": { + "summary": "List transactions", + "operationId": "databasesListTransactions", + "tags": [ + "databases" + ], + "description": "List transactions across all databases.", + "responses": { + "200": { + "description": "Transaction List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transactionList" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "listTransactions", + "group": "transactions", + "weight": 376, + "cookies": false, + "type": "", + "demo": "databases\/list-transactions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-transactions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries).", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create transaction", + "operationId": "databasesCreateTransaction", + "tags": [ + "databases" + ], + "description": "Create a new transaction.", + "responses": { + "201": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createTransaction", + "group": "transactions", + "weight": 372, + "cookies": false, + "type": "", + "demo": "databases\/create-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "ttl": { + "type": "integer", + "description": "Seconds before the transaction expires.", + "x-example": 60 + } + } + } + } + } + } + } + }, + "\/databases\/transactions\/{transactionId}": { + "get": { + "summary": "Get transaction", + "operationId": "databasesGetTransaction", + "tags": [ + "databases" + ], + "description": "Get a transaction by its unique ID.", + "responses": { + "200": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "getTransaction", + "group": "transactions", + "weight": 373, + "cookies": false, + "type": "", + "demo": "databases\/get-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update transaction", + "operationId": "databasesUpdateTransaction", + "tags": [ + "databases" + ], + "description": "Update a transaction, to either commit or roll back its operations.", + "responses": { + "200": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateTransaction", + "group": "transactions", + "weight": 374, + "cookies": false, + "type": "", + "demo": "databases\/update-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "commit": { + "type": "boolean", + "description": "Commit transaction?", + "x-example": false + }, + "rollback": { + "type": "boolean", + "description": "Rollback transaction?", + "x-example": false + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete transaction", + "operationId": "databasesDeleteTransaction", + "tags": [ + "databases" + ], + "description": "Delete a transaction by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "deprecated": false, + "x-appwrite": { + "method": "deleteTransaction", + "group": "transactions", + "weight": 375, + "cookies": false, + "type": "", + "demo": "databases\/delete-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/databases\/transactions\/{transactionId}\/operations": { + "post": { + "summary": "Create operations", + "operationId": "databasesCreateOperations", + "tags": [ + "databases" + ], + "description": "Create multiple operations in a single transaction.", + "responses": { + "201": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createOperations", + "group": "transactions", + "weight": 377, + "cookies": false, + "type": "", + "demo": "databases\/create-operations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-operations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "operations": { + "type": "array", + "description": "Array of staged operations.", + "x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"\",\n\t \"collectionId\": \"\",\n\t \"documentId\": \"\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]", + "items": { + "type": "object" + } + } + } + } + } + } + } + } + }, "\/databases\/{databaseId}": { "get": { "summary": "Get database", @@ -9046,6 +9476,16 @@ "default": [] }, "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" } ] }, @@ -9105,7 +9545,8 @@ "collectionId", "documentId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -9137,7 +9578,8 @@ "parameters": [ "databaseId", "collectionId", - "documents" + "documents", + "transactionId" ], "required": [ "databaseId", @@ -9224,6 +9666,11 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -9284,7 +9731,8 @@ "parameters": [ "databaseId", "collectionId", - "documents" + "documents", + "transactionId" ], "required": [ "databaseId", @@ -9351,6 +9799,11 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } }, "required": [ @@ -9453,6 +9906,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -9547,6 +10005,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -9654,6 +10117,16 @@ "default": [] }, "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" } ] }, @@ -9713,7 +10186,8 @@ "collectionId", "documentId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -9798,6 +10272,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } }, "required": [ @@ -9913,6 +10392,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -9999,7 +10483,23 @@ }, "in": "path" } - ] + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" + } + } + } + } + } + } } }, "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/decrement": { @@ -10115,6 +10615,11 @@ "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -10236,6 +10741,11 @@ "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -10472,7 +10982,7 @@ "tags": [ "databases" ], - "description": "Get index by ID.", + "description": "Get an index by its unique ID.", "responses": { "200": { "description": "Index", @@ -10650,7 +11160,7 @@ "x-appwrite": { "method": "list", "group": "functions", - "weight": 440, + "weight": 452, "cookies": false, "type": "", "demo": "functions\/list.md", @@ -10724,7 +11234,7 @@ "x-appwrite": { "method": "create", "group": "functions", - "weight": 437, + "weight": 449, "cookies": false, "type": "", "demo": "functions\/create.md", @@ -10958,7 +11468,7 @@ "x-appwrite": { "method": "listRuntimes", "group": "runtimes", - "weight": 442, + "weight": 454, "cookies": false, "type": "", "demo": "functions\/list-runtimes.md", @@ -11008,7 +11518,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "runtimes", - "weight": 443, + "weight": 455, "cookies": false, "type": "", "demo": "functions\/list-specifications.md", @@ -11059,7 +11569,7 @@ "x-appwrite": { "method": "get", "group": "functions", - "weight": 438, + "weight": 450, "cookies": false, "type": "", "demo": "functions\/get.md", @@ -11119,7 +11629,7 @@ "x-appwrite": { "method": "update", "group": "functions", - "weight": 439, + "weight": 451, "cookies": false, "type": "", "demo": "functions\/update.md", @@ -11350,7 +11860,7 @@ "x-appwrite": { "method": "delete", "group": "functions", - "weight": 441, + "weight": 453, "cookies": false, "type": "", "demo": "functions\/delete.md", @@ -11412,7 +11922,7 @@ "x-appwrite": { "method": "updateFunctionDeployment", "group": "functions", - "weight": 446, + "weight": 458, "cookies": false, "type": "", "demo": "functions\/update-function-deployment.md", @@ -11493,7 +12003,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 447, + "weight": 459, "cookies": false, "type": "", "demo": "functions\/list-deployments.md", @@ -11577,7 +12087,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 444, + "weight": 456, "cookies": false, "type": "upload", "demo": "functions\/create-deployment.md", @@ -11674,7 +12184,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 452, + "weight": 464, "cookies": false, "type": "", "demo": "functions\/create-duplicate-deployment.md", @@ -11760,7 +12270,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 449, + "weight": 461, "cookies": false, "type": "", "demo": "functions\/create-template-deployment.md", @@ -11864,7 +12374,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 450, + "weight": 462, "cookies": false, "type": "", "demo": "functions\/create-vcs-deployment.md", @@ -11962,7 +12472,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 445, + "weight": 457, "cookies": false, "type": "", "demo": "functions\/get-deployment.md", @@ -12025,7 +12535,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 448, + "weight": 460, "cookies": false, "type": "", "demo": "functions\/delete-deployment.md", @@ -12090,7 +12600,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 451, + "weight": 463, "cookies": false, "type": "location", "demo": "functions\/get-deployment-download.md", @@ -12181,7 +12691,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 453, + "weight": 465, "cookies": false, "type": "", "demo": "functions\/update-deployment-status.md", @@ -12253,7 +12763,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 456, + "weight": 468, "cookies": false, "type": "", "demo": "functions\/list-executions.md", @@ -12330,7 +12840,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 454, + "weight": 466, "cookies": false, "type": "", "demo": "functions\/create-execution.md", @@ -12408,9 +12918,9 @@ "x-enum-keys": [] }, "headers": { - "type": "string", + "type": "object", "description": "HTTP headers of execution. Defaults to empty.", - "x-example": null + "x-example": "{}" }, "scheduledAt": { "type": "string", @@ -12448,7 +12958,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 455, + "weight": 467, "cookies": false, "type": "", "demo": "functions\/get-execution.md", @@ -12515,7 +13025,7 @@ "x-appwrite": { "method": "deleteExecution", "group": "executions", - "weight": 457, + "weight": 469, "cookies": false, "type": "", "demo": "functions\/delete-execution.md", @@ -12587,7 +13097,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 462, + "weight": 474, "cookies": false, "type": "", "demo": "functions\/list-variables.md", @@ -12647,7 +13157,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 460, + "weight": 472, "cookies": false, "type": "", "demo": "functions\/create-variable.md", @@ -12739,7 +13249,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 461, + "weight": 473, "cookies": false, "type": "", "demo": "functions\/get-variable.md", @@ -12809,7 +13319,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 463, + "weight": 475, "cookies": false, "type": "", "demo": "functions\/update-variable.md", @@ -12901,7 +13411,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 464, + "weight": 476, "cookies": false, "type": "", "demo": "functions\/delete-variable.md", @@ -15282,7 +15792,7 @@ "image": { "type": "string", "description": "Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as :.", - "x-example": "[ID1:ID2]" + "x-example": "" }, "icon": { "type": "string", @@ -15464,7 +15974,7 @@ "image": { "type": "string", "description": "Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as :.", - "x-example": "[ID1:ID2]" + "x-example": "" }, "icon": { "type": "string", @@ -19825,7 +20335,7 @@ "x-appwrite": { "method": "list", "group": "sites", - "weight": 469, + "weight": 481, "cookies": false, "type": "", "demo": "sites\/list.md", @@ -19855,7 +20365,10 @@ "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, enabled, framework, deploymentId, buildCommand, installCommand, outputDirectory, installationId", "required": false, "schema": { - "type": "string", + "type": "array", + "items": { + "type": "string" + }, "default": [] }, "in": "query" @@ -19896,7 +20409,7 @@ "x-appwrite": { "method": "create", "group": "sites", - "weight": 467, + "weight": 479, "cookies": false, "type": "", "demo": "sites\/create.md", @@ -20146,7 +20659,7 @@ "x-appwrite": { "method": "listFrameworks", "group": "frameworks", - "weight": 472, + "weight": 484, "cookies": false, "type": "", "demo": "sites\/list-frameworks.md", @@ -20196,7 +20709,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 495, + "weight": 507, "cookies": false, "type": "", "demo": "sites\/list-specifications.md", @@ -20247,7 +20760,7 @@ "x-appwrite": { "method": "get", "group": "sites", - "weight": 468, + "weight": 480, "cookies": false, "type": "", "demo": "sites\/get.md", @@ -20307,7 +20820,7 @@ "x-appwrite": { "method": "update", "group": "sites", - "weight": 470, + "weight": 482, "cookies": false, "type": "", "demo": "sites\/update.md", @@ -20553,7 +21066,7 @@ "x-appwrite": { "method": "delete", "group": "sites", - "weight": 471, + "weight": 483, "cookies": false, "type": "", "demo": "sites\/delete.md", @@ -20615,7 +21128,7 @@ "x-appwrite": { "method": "updateSiteDeployment", "group": "sites", - "weight": 478, + "weight": 490, "cookies": false, "type": "", "demo": "sites\/update-site-deployment.md", @@ -20696,7 +21209,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 477, + "weight": 489, "cookies": false, "type": "", "demo": "sites\/list-deployments.md", @@ -20780,7 +21293,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 473, + "weight": 485, "cookies": false, "type": "upload", "demo": "sites\/create-deployment.md", @@ -20882,7 +21395,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 481, + "weight": 493, "cookies": false, "type": "", "demo": "sites\/create-duplicate-deployment.md", @@ -20963,7 +21476,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 474, + "weight": 486, "cookies": false, "type": "", "demo": "sites\/create-template-deployment.md", @@ -21067,7 +21580,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 475, + "weight": 487, "cookies": false, "type": "", "demo": "sites\/create-vcs-deployment.md", @@ -21166,7 +21679,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 476, + "weight": 488, "cookies": false, "type": "", "demo": "sites\/get-deployment.md", @@ -21229,7 +21742,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 479, + "weight": 491, "cookies": false, "type": "", "demo": "sites\/delete-deployment.md", @@ -21294,7 +21807,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 480, + "weight": 492, "cookies": false, "type": "location", "demo": "sites\/get-deployment-download.md", @@ -21385,7 +21898,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 482, + "weight": 494, "cookies": false, "type": "", "demo": "sites\/update-deployment-status.md", @@ -21457,7 +21970,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 484, + "weight": 496, "cookies": false, "type": "", "demo": "sites\/list-logs.md", @@ -21497,7 +22010,10 @@ "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: trigger, status, responseStatusCode, duration, requestMethod, requestPath, deploymentId", "required": false, "schema": { - "type": "string", + "type": "array", + "items": { + "type": "string" + }, "default": [] }, "in": "query" @@ -21529,7 +22045,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 483, + "weight": 495, "cookies": false, "type": "", "demo": "sites\/get-log.md", @@ -21592,7 +22108,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 485, + "weight": 497, "cookies": false, "type": "", "demo": "sites\/delete-log.md", @@ -21664,7 +22180,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 488, + "weight": 500, "cookies": false, "type": "", "demo": "sites\/list-variables.md", @@ -21724,7 +22240,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 486, + "weight": 498, "cookies": false, "type": "", "demo": "sites\/create-variable.md", @@ -21816,7 +22332,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 487, + "weight": 499, "cookies": false, "type": "", "demo": "sites\/get-variable.md", @@ -21886,7 +22402,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 489, + "weight": 501, "cookies": false, "type": "", "demo": "sites\/update-variable.md", @@ -21978,7 +22494,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 490, + "weight": 502, "cookies": false, "type": "", "demo": "sites\/delete-variable.md", @@ -23318,7 +23834,7 @@ "x-appwrite": { "method": "list", "group": "tablesdb", - "weight": 376, + "weight": 382, "cookies": false, "type": "", "demo": "tablesdb\/list.md", @@ -23392,7 +23908,7 @@ "x-appwrite": { "method": "create", "group": "tablesdb", - "weight": 372, + "weight": 378, "cookies": false, "type": "", "demo": "tablesdb\/create.md", @@ -23448,6 +23964,436 @@ } } }, + "\/tablesdb\/transactions": { + "get": { + "summary": "List transactions", + "operationId": "tablesDBListTransactions", + "tags": [ + "tablesDB" + ], + "description": "List transactions across all databases.", + "responses": { + "200": { + "description": "Transaction List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transactionList" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "listTransactions", + "group": "transactions", + "weight": 441, + "cookies": false, + "type": "", + "demo": "tablesdb\/list-transactions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/list-transactions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries).", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create transaction", + "operationId": "tablesDBCreateTransaction", + "tags": [ + "tablesDB" + ], + "description": "Create a new transaction.", + "responses": { + "201": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createTransaction", + "group": "transactions", + "weight": 437, + "cookies": false, + "type": "", + "demo": "tablesdb\/create-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/create-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "ttl": { + "type": "integer", + "description": "Seconds before the transaction expires.", + "x-example": 60 + } + } + } + } + } + } + } + }, + "\/tablesdb\/transactions\/{transactionId}": { + "get": { + "summary": "Get transaction", + "operationId": "tablesDBGetTransaction", + "tags": [ + "tablesDB" + ], + "description": "Get a transaction by its unique ID.", + "responses": { + "200": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "getTransaction", + "group": "transactions", + "weight": 438, + "cookies": false, + "type": "", + "demo": "tablesdb\/get-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/get-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update transaction", + "operationId": "tablesDBUpdateTransaction", + "tags": [ + "tablesDB" + ], + "description": "Update a transaction, to either commit or roll back its operations.", + "responses": { + "200": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateTransaction", + "group": "transactions", + "weight": 439, + "cookies": false, + "type": "", + "demo": "tablesdb\/update-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/update-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "commit": { + "type": "boolean", + "description": "Commit transaction?", + "x-example": false + }, + "rollback": { + "type": "boolean", + "description": "Rollback transaction?", + "x-example": false + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete transaction", + "operationId": "tablesDBDeleteTransaction", + "tags": [ + "tablesDB" + ], + "description": "Delete a transaction by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "deprecated": false, + "x-appwrite": { + "method": "deleteTransaction", + "group": "transactions", + "weight": 440, + "cookies": false, + "type": "", + "demo": "tablesdb\/delete-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/delete-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/tablesdb\/transactions\/{transactionId}\/operations": { + "post": { + "summary": "Create operations", + "operationId": "tablesDBCreateOperations", + "tags": [ + "tablesDB" + ], + "description": "Create multiple operations in a single transaction.", + "responses": { + "201": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createOperations", + "group": "transactions", + "weight": 442, + "cookies": false, + "type": "", + "demo": "tablesdb\/create-operations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/create-operations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "operations": { + "type": "array", + "description": "Array of staged operations.", + "x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"\",\n\t \"tableId\": \"\",\n\t \"rowId\": \"\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]", + "items": { + "type": "object" + } + } + } + } + } + } + } + } + }, "\/tablesdb\/{databaseId}": { "get": { "summary": "Get database", @@ -23472,7 +24418,7 @@ "x-appwrite": { "method": "get", "group": "tablesdb", - "weight": 373, + "weight": 379, "cookies": false, "type": "", "demo": "tablesdb\/get.md", @@ -23532,7 +24478,7 @@ "x-appwrite": { "method": "update", "group": "tablesdb", - "weight": 374, + "weight": 380, "cookies": false, "type": "", "demo": "tablesdb\/update.md", @@ -23609,7 +24555,7 @@ "x-appwrite": { "method": "delete", "group": "tablesdb", - "weight": 375, + "weight": 381, "cookies": false, "type": "", "demo": "tablesdb\/delete.md", @@ -23671,7 +24617,7 @@ "x-appwrite": { "method": "listTables", "group": "tables", - "weight": 383, + "weight": 389, "cookies": false, "type": "", "demo": "tablesdb\/list-tables.md", @@ -23758,7 +24704,7 @@ "x-appwrite": { "method": "createTable", "group": "tables", - "weight": 379, + "weight": 385, "cookies": false, "type": "", "demo": "tablesdb\/create-table.md", @@ -23866,7 +24812,7 @@ "x-appwrite": { "method": "getTable", "group": "tables", - "weight": 380, + "weight": 386, "cookies": false, "type": "", "demo": "tablesdb\/get-table.md", @@ -23939,7 +24885,7 @@ "x-appwrite": { "method": "updateTable", "group": "tables", - "weight": 381, + "weight": 387, "cookies": false, "type": "", "demo": "tablesdb\/update-table.md", @@ -24042,7 +24988,7 @@ "x-appwrite": { "method": "deleteTable", "group": "tables", - "weight": 382, + "weight": 388, "cookies": false, "type": "", "demo": "tablesdb\/delete-table.md", @@ -24117,7 +25063,7 @@ "x-appwrite": { "method": "listColumns", "group": "columns", - "weight": 388, + "weight": 394, "cookies": false, "type": "", "demo": "tablesdb\/list-columns.md", @@ -24205,7 +25151,7 @@ "x-appwrite": { "method": "createBooleanColumn", "group": "columns", - "weight": 389, + "weight": 395, "cookies": false, "type": "", "demo": "tablesdb\/create-boolean-column.md", @@ -24315,7 +25261,7 @@ "x-appwrite": { "method": "updateBooleanColumn", "group": "columns", - "weight": 390, + "weight": 396, "cookies": false, "type": "", "demo": "tablesdb\/update-boolean-column.md", @@ -24430,7 +25376,7 @@ "x-appwrite": { "method": "createDatetimeColumn", "group": "columns", - "weight": 391, + "weight": 397, "cookies": false, "type": "", "demo": "tablesdb\/create-datetime-column.md", @@ -24540,7 +25486,7 @@ "x-appwrite": { "method": "updateDatetimeColumn", "group": "columns", - "weight": 392, + "weight": 398, "cookies": false, "type": "", "demo": "tablesdb\/update-datetime-column.md", @@ -24655,7 +25601,7 @@ "x-appwrite": { "method": "createEmailColumn", "group": "columns", - "weight": 393, + "weight": 399, "cookies": false, "type": "", "demo": "tablesdb\/create-email-column.md", @@ -24765,7 +25711,7 @@ "x-appwrite": { "method": "updateEmailColumn", "group": "columns", - "weight": 394, + "weight": 400, "cookies": false, "type": "", "demo": "tablesdb\/update-email-column.md", @@ -24880,7 +25826,7 @@ "x-appwrite": { "method": "createEnumColumn", "group": "columns", - "weight": 395, + "weight": 401, "cookies": false, "type": "", "demo": "tablesdb\/create-enum-column.md", @@ -24999,7 +25945,7 @@ "x-appwrite": { "method": "updateEnumColumn", "group": "columns", - "weight": 396, + "weight": 402, "cookies": false, "type": "", "demo": "tablesdb\/update-enum-column.md", @@ -25123,7 +26069,7 @@ "x-appwrite": { "method": "createFloatColumn", "group": "columns", - "weight": 397, + "weight": 403, "cookies": false, "type": "", "demo": "tablesdb\/create-float-column.md", @@ -25243,7 +26189,7 @@ "x-appwrite": { "method": "updateFloatColumn", "group": "columns", - "weight": 398, + "weight": 404, "cookies": false, "type": "", "demo": "tablesdb\/update-float-column.md", @@ -25368,7 +26314,7 @@ "x-appwrite": { "method": "createIntegerColumn", "group": "columns", - "weight": 399, + "weight": 405, "cookies": false, "type": "", "demo": "tablesdb\/create-integer-column.md", @@ -25488,7 +26434,7 @@ "x-appwrite": { "method": "updateIntegerColumn", "group": "columns", - "weight": 400, + "weight": 406, "cookies": false, "type": "", "demo": "tablesdb\/update-integer-column.md", @@ -25613,7 +26559,7 @@ "x-appwrite": { "method": "createIpColumn", "group": "columns", - "weight": 401, + "weight": 407, "cookies": false, "type": "", "demo": "tablesdb\/create-ip-column.md", @@ -25723,7 +26669,7 @@ "x-appwrite": { "method": "updateIpColumn", "group": "columns", - "weight": 402, + "weight": 408, "cookies": false, "type": "", "demo": "tablesdb\/update-ip-column.md", @@ -25838,7 +26784,7 @@ "x-appwrite": { "method": "createLineColumn", "group": "columns", - "weight": 403, + "weight": 409, "cookies": false, "type": "", "demo": "tablesdb\/create-line-column.md", @@ -25951,7 +26897,7 @@ "x-appwrite": { "method": "updateLineColumn", "group": "columns", - "weight": 404, + "weight": 410, "cookies": false, "type": "", "demo": "tablesdb\/update-line-column.md", @@ -26072,7 +27018,7 @@ "x-appwrite": { "method": "createPointColumn", "group": "columns", - "weight": 405, + "weight": 411, "cookies": false, "type": "", "demo": "tablesdb\/create-point-column.md", @@ -26185,7 +27131,7 @@ "x-appwrite": { "method": "updatePointColumn", "group": "columns", - "weight": 406, + "weight": 412, "cookies": false, "type": "", "demo": "tablesdb\/update-point-column.md", @@ -26306,7 +27252,7 @@ "x-appwrite": { "method": "createPolygonColumn", "group": "columns", - "weight": 407, + "weight": 413, "cookies": false, "type": "", "demo": "tablesdb\/create-polygon-column.md", @@ -26419,7 +27365,7 @@ "x-appwrite": { "method": "updatePolygonColumn", "group": "columns", - "weight": 408, + "weight": 414, "cookies": false, "type": "", "demo": "tablesdb\/update-polygon-column.md", @@ -26540,7 +27486,7 @@ "x-appwrite": { "method": "createRelationshipColumn", "group": "columns", - "weight": 409, + "weight": 415, "cookies": false, "type": "", "demo": "tablesdb\/create-relationship-column.md", @@ -26675,7 +27621,7 @@ "x-appwrite": { "method": "createStringColumn", "group": "columns", - "weight": 411, + "weight": 417, "cookies": false, "type": "", "demo": "tablesdb\/create-string-column.md", @@ -26796,7 +27742,7 @@ "x-appwrite": { "method": "updateStringColumn", "group": "columns", - "weight": 412, + "weight": 418, "cookies": false, "type": "", "demo": "tablesdb\/update-string-column.md", @@ -26916,7 +27862,7 @@ "x-appwrite": { "method": "createUrlColumn", "group": "columns", - "weight": 413, + "weight": 419, "cookies": false, "type": "", "demo": "tablesdb\/create-url-column.md", @@ -27026,7 +27972,7 @@ "x-appwrite": { "method": "updateUrlColumn", "group": "columns", - "weight": 414, + "weight": 420, "cookies": false, "type": "", "demo": "tablesdb\/update-url-column.md", @@ -27172,7 +28118,7 @@ "x-appwrite": { "method": "getColumn", "group": "columns", - "weight": 386, + "weight": 392, "cookies": false, "type": "", "demo": "tablesdb\/get-column.md", @@ -27247,7 +28193,7 @@ "x-appwrite": { "method": "deleteColumn", "group": "columns", - "weight": 387, + "weight": 393, "cookies": false, "type": "", "demo": "tablesdb\/delete-column.md", @@ -27331,7 +28277,7 @@ "x-appwrite": { "method": "updateRelationshipColumn", "group": "columns", - "weight": 410, + "weight": 416, "cookies": false, "type": "", "demo": "tablesdb\/update-relationship-column.md", @@ -27443,7 +28389,7 @@ "x-appwrite": { "method": "listIndexes", "group": "indexes", - "weight": 418, + "weight": 424, "cookies": false, "type": "", "demo": "tablesdb\/list-indexes.md", @@ -27529,7 +28475,7 @@ "x-appwrite": { "method": "createIndex", "group": "indexes", - "weight": 415, + "weight": 421, "cookies": false, "type": "", "demo": "tablesdb\/create-index.md", @@ -27662,7 +28608,7 @@ "x-appwrite": { "method": "getIndex", "group": "indexes", - "weight": 416, + "weight": 422, "cookies": false, "type": "", "demo": "tablesdb\/get-index.md", @@ -27737,7 +28683,7 @@ "x-appwrite": { "method": "deleteIndex", "group": "indexes", - "weight": 417, + "weight": 423, "cookies": false, "type": "", "demo": "tablesdb\/delete-index.md", @@ -27821,7 +28767,7 @@ "x-appwrite": { "method": "listRows", "group": "rows", - "weight": 427, + "weight": 433, "cookies": false, "type": "", "demo": "tablesdb\/list-rows.md", @@ -27885,6 +28831,16 @@ "default": [] }, "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" } ] }, @@ -27911,7 +28867,7 @@ "x-appwrite": { "method": "createRow", "group": "rows", - "weight": 419, + "weight": 425, "cookies": false, "type": "", "demo": "tablesdb\/create-row.md", @@ -27943,7 +28899,8 @@ "tableId", "rowId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -27971,7 +28928,8 @@ "parameters": [ "databaseId", "tableId", - "rows" + "rows", + "transactionId" ], "required": [ "databaseId", @@ -28054,6 +29012,11 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -28084,7 +29047,7 @@ "x-appwrite": { "method": "upsertRows", "group": "rows", - "weight": 424, + "weight": 430, "cookies": false, "type": "", "demo": "tablesdb\/upsert-rows.md", @@ -28113,7 +29076,8 @@ "parameters": [ "databaseId", "tableId", - "rows" + "rows", + "transactionId" ], "required": [ "databaseId", @@ -28176,6 +29140,11 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } }, "required": [ @@ -28209,7 +29178,7 @@ "x-appwrite": { "method": "updateRows", "group": "rows", - "weight": 422, + "weight": 428, "cookies": false, "type": "", "demo": "tablesdb\/update-rows.md", @@ -28277,6 +29246,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -28307,7 +29281,7 @@ "x-appwrite": { "method": "deleteRows", "group": "rows", - "weight": 426, + "weight": 432, "cookies": false, "type": "", "demo": "tablesdb\/delete-rows.md", @@ -28370,6 +29344,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -28402,7 +29381,7 @@ "x-appwrite": { "method": "getRow", "group": "rows", - "weight": 420, + "weight": 426, "cookies": false, "type": "", "demo": "tablesdb\/get-row.md", @@ -28476,6 +29455,16 @@ "default": [] }, "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" } ] }, @@ -28502,7 +29491,7 @@ "x-appwrite": { "method": "upsertRow", "group": "rows", - "weight": 423, + "weight": 429, "cookies": false, "type": "", "demo": "tablesdb\/upsert-row.md", @@ -28534,7 +29523,8 @@ "tableId", "rowId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -28614,6 +29604,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -28644,7 +29639,7 @@ "x-appwrite": { "method": "updateRow", "group": "rows", - "weight": 421, + "weight": 427, "cookies": false, "type": "", "demo": "tablesdb\/update-row.md", @@ -28725,6 +29720,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -28748,7 +29748,7 @@ "x-appwrite": { "method": "deleteRow", "group": "rows", - "weight": 425, + "weight": 431, "cookies": false, "type": "", "demo": "tablesdb\/delete-row.md", @@ -28810,7 +29810,23 @@ }, "in": "path" } - ] + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" + } + } + } + } + } + } } }, "\/tablesdb\/{databaseId}\/tables\/{tableId}\/rows\/{rowId}\/{column}\/decrement": { @@ -28837,7 +29853,7 @@ "x-appwrite": { "method": "decrementRowColumn", "group": "rows", - "weight": 430, + "weight": 436, "cookies": false, "type": "", "demo": "tablesdb\/decrement-row-column.md", @@ -28925,6 +29941,11 @@ "type": "number", "description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.", "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -28957,7 +29978,7 @@ "x-appwrite": { "method": "incrementRowColumn", "group": "rows", - "weight": 429, + "weight": 435, "cookies": false, "type": "", "demo": "tablesdb\/increment-row-column.md", @@ -29045,6 +30066,11 @@ "type": "number", "description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.", "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -30132,7 +31158,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 507, + "weight": 519, "cookies": false, "type": "", "demo": "tokens\/list.md", @@ -30183,7 +31209,10 @@ "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: expire", "required": false, "schema": { - "type": "string", + "type": "array", + "items": { + "type": "string" + }, "default": [] }, "in": "query" @@ -30213,7 +31242,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 505, + "weight": 517, "cookies": false, "type": "", "demo": "tokens\/create-file-token.md", @@ -30303,7 +31332,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 506, + "weight": 518, "cookies": false, "type": "", "demo": "tokens\/get.md", @@ -30364,7 +31393,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 508, + "weight": 520, "cookies": false, "type": "", "demo": "tokens\/update.md", @@ -30435,7 +31464,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 509, + "weight": 521, "cookies": false, "type": "", "demo": "tokens\/delete.md", @@ -35141,6 +36170,34 @@ "targets": "" } }, + "transactionList": { + "description": "Transaction List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of transactions that matched your query.", + "x-example": 5, + "format": "int32" + }, + "transactions": { + "type": "array", + "description": "List of transactions.", + "items": { + "$ref": "#\/components\/schemas\/transaction" + }, + "x-example": "" + } + }, + "required": [ + "total", + "transactions" + ], + "example": { + "total": 5, + "transactions": "" + } + }, "specificationList": { "description": "Specifications List", "type": "object", @@ -41800,6 +42857,59 @@ "subscribe": "users" } }, + "transaction": { + "description": "Transaction", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Transaction ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Transaction creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Transaction update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "status": { + "type": "string", + "description": "Current status of the transaction. One of: pending, committing, committed, rolled_back, failed.", + "x-example": "pending" + }, + "operations": { + "type": "integer", + "description": "Number of operations in the transaction.", + "x-example": 5, + "format": "int32" + }, + "expiresAt": { + "type": "string", + "description": "Expiration time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "status", + "operations", + "expiresAt" + ], + "example": { + "$id": "259125845563242502", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "status": "pending", + "operations": 5, + "expiresAt": "2020-10-15T06:38:00.000+00:00" + } + }, "subscriber": { "description": "Subscriber", "type": "object", diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index 4cb47c7f08..b6a6a1afe3 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -4910,6 +4910,424 @@ ] } }, + "\/databases\/transactions": { + "get": { + "summary": "List transactions", + "operationId": "databasesListTransactions", + "tags": [ + "databases" + ], + "description": "List transactions across all databases.", + "responses": { + "200": { + "description": "Transaction List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transactionList" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "listTransactions", + "group": "transactions", + "weight": 376, + "cookies": false, + "type": "", + "demo": "databases\/list-transactions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-transactions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries).", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create transaction", + "operationId": "databasesCreateTransaction", + "tags": [ + "databases" + ], + "description": "Create a new transaction.", + "responses": { + "201": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createTransaction", + "group": "transactions", + "weight": 372, + "cookies": false, + "type": "", + "demo": "databases\/create-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "ttl": { + "type": "integer", + "description": "Seconds before the transaction expires.", + "x-example": 60 + } + } + } + } + } + } + } + }, + "\/databases\/transactions\/{transactionId}": { + "get": { + "summary": "Get transaction", + "operationId": "databasesGetTransaction", + "tags": [ + "databases" + ], + "description": "Get a transaction by its unique ID.", + "responses": { + "200": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "getTransaction", + "group": "transactions", + "weight": 373, + "cookies": false, + "type": "", + "demo": "databases\/get-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update transaction", + "operationId": "databasesUpdateTransaction", + "tags": [ + "databases" + ], + "description": "Update a transaction, to either commit or roll back its operations.", + "responses": { + "200": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateTransaction", + "group": "transactions", + "weight": 374, + "cookies": false, + "type": "", + "demo": "databases\/update-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "commit": { + "type": "boolean", + "description": "Commit transaction?", + "x-example": false + }, + "rollback": { + "type": "boolean", + "description": "Rollback transaction?", + "x-example": false + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete transaction", + "operationId": "databasesDeleteTransaction", + "tags": [ + "databases" + ], + "description": "Delete a transaction by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "deprecated": false, + "x-appwrite": { + "method": "deleteTransaction", + "group": "transactions", + "weight": 375, + "cookies": false, + "type": "", + "demo": "databases\/delete-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/databases\/transactions\/{transactionId}\/operations": { + "post": { + "summary": "Create operations", + "operationId": "databasesCreateOperations", + "tags": [ + "databases" + ], + "description": "Create multiple operations in a single transaction.", + "responses": { + "201": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createOperations", + "group": "transactions", + "weight": 377, + "cookies": false, + "type": "", + "demo": "databases\/create-operations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-operations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "operations": { + "type": "array", + "description": "Array of staged operations.", + "x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"\",\n\t \"collectionId\": \"\",\n\t \"documentId\": \"\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]", + "items": { + "type": "object" + } + } + } + } + } + } + } + } + }, "\/databases\/{databaseId}\/collections\/{collectionId}\/documents": { "get": { "summary": "List documents", @@ -4997,6 +5415,16 @@ "default": [] }, "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" } ] }, @@ -5055,7 +5483,8 @@ "collectionId", "documentId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -5141,6 +5570,11 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -5246,6 +5680,16 @@ "default": [] }, "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" } ] }, @@ -5304,7 +5748,8 @@ "collectionId", "documentId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -5387,6 +5832,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } }, "required": [ @@ -5500,6 +5950,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -5584,7 +6039,23 @@ }, "in": "path" } - ] + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" + } + } + } + } + } + } } }, "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/decrement": { @@ -5698,6 +6169,11 @@ "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -5817,6 +6293,11 @@ "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -5849,7 +6330,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 456, + "weight": 468, "cookies": false, "type": "", "demo": "functions\/list-executions.md", @@ -5924,7 +6405,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 454, + "weight": 466, "cookies": false, "type": "", "demo": "functions\/create-execution.md", @@ -6000,9 +6481,9 @@ "x-enum-keys": [] }, "headers": { - "type": "string", + "type": "object", "description": "HTTP headers of execution. Defaults to empty.", - "x-example": null + "x-example": "{}" }, "scheduledAt": { "type": "string", @@ -6040,7 +6521,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 455, + "weight": 467, "cookies": false, "type": "", "demo": "functions\/get-execution.md", @@ -7571,6 +8052,424 @@ ] } }, + "\/tablesdb\/transactions": { + "get": { + "summary": "List transactions", + "operationId": "tablesDBListTransactions", + "tags": [ + "tablesDB" + ], + "description": "List transactions across all databases.", + "responses": { + "200": { + "description": "Transaction List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transactionList" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "listTransactions", + "group": "transactions", + "weight": 441, + "cookies": false, + "type": "", + "demo": "tablesdb\/list-transactions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/list-transactions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries).", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create transaction", + "operationId": "tablesDBCreateTransaction", + "tags": [ + "tablesDB" + ], + "description": "Create a new transaction.", + "responses": { + "201": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createTransaction", + "group": "transactions", + "weight": 437, + "cookies": false, + "type": "", + "demo": "tablesdb\/create-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/create-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "ttl": { + "type": "integer", + "description": "Seconds before the transaction expires.", + "x-example": 60 + } + } + } + } + } + } + } + }, + "\/tablesdb\/transactions\/{transactionId}": { + "get": { + "summary": "Get transaction", + "operationId": "tablesDBGetTransaction", + "tags": [ + "tablesDB" + ], + "description": "Get a transaction by its unique ID.", + "responses": { + "200": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "getTransaction", + "group": "transactions", + "weight": 438, + "cookies": false, + "type": "", + "demo": "tablesdb\/get-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/get-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update transaction", + "operationId": "tablesDBUpdateTransaction", + "tags": [ + "tablesDB" + ], + "description": "Update a transaction, to either commit or roll back its operations.", + "responses": { + "200": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateTransaction", + "group": "transactions", + "weight": 439, + "cookies": false, + "type": "", + "demo": "tablesdb\/update-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/update-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "commit": { + "type": "boolean", + "description": "Commit transaction?", + "x-example": false + }, + "rollback": { + "type": "boolean", + "description": "Rollback transaction?", + "x-example": false + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete transaction", + "operationId": "tablesDBDeleteTransaction", + "tags": [ + "tablesDB" + ], + "description": "Delete a transaction by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "deprecated": false, + "x-appwrite": { + "method": "deleteTransaction", + "group": "transactions", + "weight": 440, + "cookies": false, + "type": "", + "demo": "tablesdb\/delete-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/delete-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/tablesdb\/transactions\/{transactionId}\/operations": { + "post": { + "summary": "Create operations", + "operationId": "tablesDBCreateOperations", + "tags": [ + "tablesDB" + ], + "description": "Create multiple operations in a single transaction.", + "responses": { + "201": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createOperations", + "group": "transactions", + "weight": 442, + "cookies": false, + "type": "", + "demo": "tablesdb\/create-operations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/create-operations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "operations": { + "type": "array", + "description": "Array of staged operations.", + "x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"\",\n\t \"tableId\": \"\",\n\t \"rowId\": \"\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]", + "items": { + "type": "object" + } + } + } + } + } + } + } + } + }, "\/tablesdb\/{databaseId}\/tables\/{tableId}\/rows": { "get": { "summary": "List rows", @@ -7595,7 +8494,7 @@ "x-appwrite": { "method": "listRows", "group": "rows", - "weight": 427, + "weight": 433, "cookies": false, "type": "", "demo": "tablesdb\/list-rows.md", @@ -7657,6 +8556,16 @@ "default": [] }, "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" } ] }, @@ -7683,7 +8592,7 @@ "x-appwrite": { "method": "createRow", "group": "rows", - "weight": 419, + "weight": 425, "cookies": false, "type": "", "demo": "tablesdb\/create-row.md", @@ -7714,7 +8623,8 @@ "tableId", "rowId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -7796,6 +8706,11 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -7828,7 +8743,7 @@ "x-appwrite": { "method": "getRow", "group": "rows", - "weight": 420, + "weight": 426, "cookies": false, "type": "", "demo": "tablesdb\/get-row.md", @@ -7900,6 +8815,16 @@ "default": [] }, "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" } ] }, @@ -7926,7 +8851,7 @@ "x-appwrite": { "method": "upsertRow", "group": "rows", - "weight": 423, + "weight": 429, "cookies": false, "type": "", "demo": "tablesdb\/upsert-row.md", @@ -7957,7 +8882,8 @@ "tableId", "rowId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -8035,6 +8961,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -8065,7 +8996,7 @@ "x-appwrite": { "method": "updateRow", "group": "rows", - "weight": 421, + "weight": 427, "cookies": false, "type": "", "demo": "tablesdb\/update-row.md", @@ -8144,6 +9075,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -8167,7 +9103,7 @@ "x-appwrite": { "method": "deleteRow", "group": "rows", - "weight": 425, + "weight": 431, "cookies": false, "type": "", "demo": "tablesdb\/delete-row.md", @@ -8227,7 +9163,23 @@ }, "in": "path" } - ] + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" + } + } + } + } + } + } } }, "\/tablesdb\/{databaseId}\/tables\/{tableId}\/rows\/{rowId}\/{column}\/decrement": { @@ -8254,7 +9206,7 @@ "x-appwrite": { "method": "decrementRowColumn", "group": "rows", - "weight": 430, + "weight": 436, "cookies": false, "type": "", "demo": "tablesdb\/decrement-row-column.md", @@ -8340,6 +9292,11 @@ "type": "number", "description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.", "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -8372,7 +9329,7 @@ "x-appwrite": { "method": "incrementRowColumn", "group": "rows", - "weight": 429, + "weight": 435, "cookies": false, "type": "", "demo": "tablesdb\/increment-row-column.md", @@ -8458,6 +9415,11 @@ "type": "number", "description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.", "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -10039,6 +11001,34 @@ "localeCodes": "" } }, + "transactionList": { + "description": "Transaction List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of transactions that matched your query.", + "x-example": 5, + "format": "int32" + }, + "transactions": { + "type": "array", + "description": "List of transactions.", + "items": { + "$ref": "#\/components\/schemas\/transaction" + }, + "x-example": "" + } + }, + "required": [ + "total", + "transactions" + ], + "example": { + "total": 5, + "transactions": "" + } + }, "row": { "description": "Row", "type": "object", @@ -11954,6 +12944,59 @@ "recoveryCode": true } }, + "transaction": { + "description": "Transaction", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Transaction ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Transaction creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Transaction update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "status": { + "type": "string", + "description": "Current status of the transaction. One of: pending, committing, committed, rolled_back, failed.", + "x-example": "pending" + }, + "operations": { + "type": "integer", + "description": "Number of operations in the transaction.", + "x-example": 5, + "format": "int32" + }, + "expiresAt": { + "type": "string", + "description": "Expiration time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "status", + "operations", + "expiresAt" + ], + "example": { + "$id": "259125845563242502", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "status": "pending", + "operations": 5, + "expiresAt": "2020-10-15T06:38:00.000+00:00" + } + }, "subscriber": { "description": "Subscriber", "type": "object", diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index cf85dd57ed..c086fe03d0 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -4992,7 +4992,7 @@ "x-appwrite": { "method": "getResource", "group": null, - "weight": 496, + "weight": 508, "cookies": false, "type": "", "demo": "console\/get-resource.md", @@ -5309,6 +5309,424 @@ } } }, + "\/databases\/transactions": { + "get": { + "summary": "List transactions", + "operationId": "databasesListTransactions", + "tags": [ + "databases" + ], + "description": "List transactions across all databases.", + "responses": { + "200": { + "description": "Transaction List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transactionList" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "listTransactions", + "group": "transactions", + "weight": 376, + "cookies": false, + "type": "", + "demo": "databases\/list-transactions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-transactions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries).", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create transaction", + "operationId": "databasesCreateTransaction", + "tags": [ + "databases" + ], + "description": "Create a new transaction.", + "responses": { + "201": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createTransaction", + "group": "transactions", + "weight": 372, + "cookies": false, + "type": "", + "demo": "databases\/create-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "ttl": { + "type": "integer", + "description": "Seconds before the transaction expires.", + "x-example": 60 + } + } + } + } + } + } + } + }, + "\/databases\/transactions\/{transactionId}": { + "get": { + "summary": "Get transaction", + "operationId": "databasesGetTransaction", + "tags": [ + "databases" + ], + "description": "Get a transaction by its unique ID.", + "responses": { + "200": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "getTransaction", + "group": "transactions", + "weight": 373, + "cookies": false, + "type": "", + "demo": "databases\/get-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update transaction", + "operationId": "databasesUpdateTransaction", + "tags": [ + "databases" + ], + "description": "Update a transaction, to either commit or roll back its operations.", + "responses": { + "200": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateTransaction", + "group": "transactions", + "weight": 374, + "cookies": false, + "type": "", + "demo": "databases\/update-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "commit": { + "type": "boolean", + "description": "Commit transaction?", + "x-example": false + }, + "rollback": { + "type": "boolean", + "description": "Rollback transaction?", + "x-example": false + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete transaction", + "operationId": "databasesDeleteTransaction", + "tags": [ + "databases" + ], + "description": "Delete a transaction by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "deprecated": false, + "x-appwrite": { + "method": "deleteTransaction", + "group": "transactions", + "weight": 375, + "cookies": false, + "type": "", + "demo": "databases\/delete-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/databases\/transactions\/{transactionId}\/operations": { + "post": { + "summary": "Create operations", + "operationId": "databasesCreateOperations", + "tags": [ + "databases" + ], + "description": "Create multiple operations in a single transaction.", + "responses": { + "201": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createOperations", + "group": "transactions", + "weight": 377, + "cookies": false, + "type": "", + "demo": "databases\/create-operations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-operations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "operations": { + "type": "array", + "description": "Array of staged operations.", + "x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"\",\n\t \"collectionId\": \"\",\n\t \"documentId\": \"\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]", + "items": { + "type": "object" + } + } + } + } + } + } + } + } + }, "\/databases\/usage": { "get": { "summary": "Get databases usage stats", @@ -9564,6 +9982,16 @@ "default": [] }, "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" } ] }, @@ -9622,7 +10050,8 @@ "collectionId", "documentId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -9653,7 +10082,8 @@ "parameters": [ "databaseId", "collectionId", - "documents" + "documents", + "transactionId" ], "required": [ "databaseId", @@ -9738,6 +10168,11 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -9797,7 +10232,8 @@ "parameters": [ "databaseId", "collectionId", - "documents" + "documents", + "transactionId" ], "required": [ "databaseId", @@ -9863,6 +10299,11 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } }, "required": [ @@ -9964,6 +10405,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -10057,6 +10503,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -10162,6 +10613,16 @@ "default": [] }, "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" } ] }, @@ -10220,7 +10681,8 @@ "collectionId", "documentId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -10303,6 +10765,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } }, "required": [ @@ -10416,6 +10883,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -10500,7 +10972,23 @@ }, "in": "path" } - ] + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" + } + } + } + } + } + } } }, "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/logs": { @@ -10711,6 +11199,11 @@ "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -10830,6 +11323,11 @@ "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -11064,7 +11562,7 @@ "tags": [ "databases" ], - "description": "Get index by ID.", + "description": "Get an index by its unique ID.", "responses": { "200": { "description": "Index", @@ -11644,7 +12142,7 @@ "x-appwrite": { "method": "list", "group": "functions", - "weight": 440, + "weight": 452, "cookies": false, "type": "", "demo": "functions\/list.md", @@ -11717,7 +12215,7 @@ "x-appwrite": { "method": "create", "group": "functions", - "weight": 437, + "weight": 449, "cookies": false, "type": "", "demo": "functions\/create.md", @@ -11950,7 +12448,7 @@ "x-appwrite": { "method": "listRuntimes", "group": "runtimes", - "weight": 442, + "weight": 454, "cookies": false, "type": "", "demo": "functions\/list-runtimes.md", @@ -11999,7 +12497,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "runtimes", - "weight": 443, + "weight": 455, "cookies": false, "type": "", "demo": "functions\/list-specifications.md", @@ -12049,7 +12547,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 466, + "weight": 478, "cookies": false, "type": "", "demo": "functions\/list-templates.md", @@ -12149,7 +12647,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 465, + "weight": 477, "cookies": false, "type": "", "demo": "functions\/get-template.md", @@ -12209,7 +12707,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 459, + "weight": 471, "cookies": false, "type": "", "demo": "functions\/list-usage.md", @@ -12281,7 +12779,7 @@ "x-appwrite": { "method": "get", "group": "functions", - "weight": 438, + "weight": 450, "cookies": false, "type": "", "demo": "functions\/get.md", @@ -12340,7 +12838,7 @@ "x-appwrite": { "method": "update", "group": "functions", - "weight": 439, + "weight": 451, "cookies": false, "type": "", "demo": "functions\/update.md", @@ -12570,7 +13068,7 @@ "x-appwrite": { "method": "delete", "group": "functions", - "weight": 441, + "weight": 453, "cookies": false, "type": "", "demo": "functions\/delete.md", @@ -12631,7 +13129,7 @@ "x-appwrite": { "method": "updateFunctionDeployment", "group": "functions", - "weight": 446, + "weight": 458, "cookies": false, "type": "", "demo": "functions\/update-function-deployment.md", @@ -12711,7 +13209,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 447, + "weight": 459, "cookies": false, "type": "", "demo": "functions\/list-deployments.md", @@ -12794,7 +13292,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 444, + "weight": 456, "cookies": false, "type": "upload", "demo": "functions\/create-deployment.md", @@ -12890,7 +13388,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 452, + "weight": 464, "cookies": false, "type": "", "demo": "functions\/create-duplicate-deployment.md", @@ -12975,7 +13473,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 449, + "weight": 461, "cookies": false, "type": "", "demo": "functions\/create-template-deployment.md", @@ -13078,7 +13576,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 450, + "weight": 462, "cookies": false, "type": "", "demo": "functions\/create-vcs-deployment.md", @@ -13175,7 +13673,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 445, + "weight": 457, "cookies": false, "type": "", "demo": "functions\/get-deployment.md", @@ -13237,7 +13735,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 448, + "weight": 460, "cookies": false, "type": "", "demo": "functions\/delete-deployment.md", @@ -13301,7 +13799,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 451, + "weight": 463, "cookies": false, "type": "location", "demo": "functions\/get-deployment-download.md", @@ -13391,7 +13889,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 453, + "weight": 465, "cookies": false, "type": "", "demo": "functions\/update-deployment-status.md", @@ -13462,7 +13960,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 456, + "weight": 468, "cookies": false, "type": "", "demo": "functions\/list-executions.md", @@ -13537,7 +14035,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 454, + "weight": 466, "cookies": false, "type": "", "demo": "functions\/create-execution.md", @@ -13613,9 +14111,9 @@ "x-enum-keys": [] }, "headers": { - "type": "string", + "type": "object", "description": "HTTP headers of execution. Defaults to empty.", - "x-example": null + "x-example": "{}" }, "scheduledAt": { "type": "string", @@ -13653,7 +14151,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 455, + "weight": 467, "cookies": false, "type": "", "demo": "functions\/get-execution.md", @@ -13718,7 +14216,7 @@ "x-appwrite": { "method": "deleteExecution", "group": "executions", - "weight": 457, + "weight": 469, "cookies": false, "type": "", "demo": "functions\/delete-execution.md", @@ -13789,7 +14287,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 458, + "weight": 470, "cookies": false, "type": "", "demo": "functions\/get-usage.md", @@ -13871,7 +14369,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 462, + "weight": 474, "cookies": false, "type": "", "demo": "functions\/list-variables.md", @@ -13930,7 +14428,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 460, + "weight": 472, "cookies": false, "type": "", "demo": "functions\/create-variable.md", @@ -14021,7 +14519,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 461, + "weight": 473, "cookies": false, "type": "", "demo": "functions\/get-variable.md", @@ -14090,7 +14588,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 463, + "weight": 475, "cookies": false, "type": "", "demo": "functions\/update-variable.md", @@ -14181,7 +14679,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 464, + "weight": 476, "cookies": false, "type": "", "demo": "functions\/delete-variable.md", @@ -16515,7 +17013,7 @@ "image": { "type": "string", "description": "Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as :.", - "x-example": "[ID1:ID2]" + "x-example": "" }, "icon": { "type": "string", @@ -16696,7 +17194,7 @@ "image": { "type": "string", "description": "Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as :.", - "x-example": "[ID1:ID2]" + "x-example": "" }, "icon": { "type": "string", @@ -21294,7 +21792,7 @@ "resourceId": { "type": "string", "description": "Composite ID in the format {databaseId:collectionId}, identifying a collection within a database.", - "x-example": "[ID1:ID2]" + "x-example": "" }, "internalFile": { "type": "boolean", @@ -22537,7 +23035,7 @@ "x-appwrite": { "method": "list", "group": "projects", - "weight": 436, + "weight": 448, "cookies": false, "type": "", "demo": "projects\/list.md", @@ -24172,7 +24670,7 @@ "x-appwrite": { "method": "listDevKeys", "group": "devKeys", - "weight": 434, + "weight": 446, "cookies": false, "type": "", "demo": "projects\/list-dev-keys.md", @@ -24210,7 +24708,10 @@ "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: accessedAt, expire", "required": false, "schema": { - "type": "string", + "type": "array", + "items": { + "type": "string" + }, "default": [] }, "in": "query" @@ -24240,7 +24741,7 @@ "x-appwrite": { "method": "createDevKey", "group": "devKeys", - "weight": 431, + "weight": 443, "cookies": false, "type": "", "demo": "projects\/create-dev-key.md", @@ -24325,7 +24826,7 @@ "x-appwrite": { "method": "getDevKey", "group": "devKeys", - "weight": 433, + "weight": 445, "cookies": false, "type": "", "demo": "projects\/get-dev-key.md", @@ -24393,7 +24894,7 @@ "x-appwrite": { "method": "updateDevKey", "group": "devKeys", - "weight": 432, + "weight": 444, "cookies": false, "type": "", "demo": "projects\/update-dev-key.md", @@ -24479,7 +24980,7 @@ "x-appwrite": { "method": "deleteDevKey", "group": "devKeys", - "weight": 435, + "weight": 447, "cookies": false, "type": "", "demo": "projects\/delete-dev-key.md", @@ -28313,7 +28814,7 @@ "x-appwrite": { "method": "listRules", "group": null, - "weight": 502, + "weight": 514, "cookies": false, "type": "", "demo": "proxy\/list-rules.md", @@ -28387,7 +28888,7 @@ "x-appwrite": { "method": "createAPIRule", "group": null, - "weight": 497, + "weight": 509, "cookies": false, "type": "", "demo": "proxy\/create-api-rule.md", @@ -28454,7 +28955,7 @@ "x-appwrite": { "method": "createFunctionRule", "group": null, - "weight": 499, + "weight": 511, "cookies": false, "type": "", "demo": "proxy\/create-function-rule.md", @@ -28532,7 +29033,7 @@ "x-appwrite": { "method": "createRedirectRule", "group": null, - "weight": 500, + "weight": 512, "cookies": false, "type": "", "demo": "proxy\/create-redirect-rule.md", @@ -28645,7 +29146,7 @@ "x-appwrite": { "method": "createSiteRule", "group": null, - "weight": 498, + "weight": 510, "cookies": false, "type": "", "demo": "proxy\/create-site-rule.md", @@ -28723,7 +29224,7 @@ "x-appwrite": { "method": "getRule", "group": null, - "weight": 501, + "weight": 513, "cookies": false, "type": "", "demo": "proxy\/get-rule.md", @@ -28774,7 +29275,7 @@ "x-appwrite": { "method": "deleteRule", "group": null, - "weight": 503, + "weight": 515, "cookies": false, "type": "", "demo": "proxy\/delete-rule.md", @@ -28834,7 +29335,7 @@ "x-appwrite": { "method": "updateRuleVerification", "group": null, - "weight": 504, + "weight": 516, "cookies": false, "type": "", "demo": "proxy\/update-rule-verification.md", @@ -28894,7 +29395,7 @@ "x-appwrite": { "method": "list", "group": "sites", - "weight": 469, + "weight": 481, "cookies": false, "type": "", "demo": "sites\/list.md", @@ -28923,7 +29424,10 @@ "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, enabled, framework, deploymentId, buildCommand, installCommand, outputDirectory, installationId", "required": false, "schema": { - "type": "string", + "type": "array", + "items": { + "type": "string" + }, "default": [] }, "in": "query" @@ -28964,7 +29468,7 @@ "x-appwrite": { "method": "create", "group": "sites", - "weight": 467, + "weight": 479, "cookies": false, "type": "", "demo": "sites\/create.md", @@ -29213,7 +29717,7 @@ "x-appwrite": { "method": "listFrameworks", "group": "frameworks", - "weight": 472, + "weight": 484, "cookies": false, "type": "", "demo": "sites\/list-frameworks.md", @@ -29262,7 +29766,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 495, + "weight": 507, "cookies": false, "type": "", "demo": "sites\/list-specifications.md", @@ -29312,7 +29816,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 491, + "weight": 503, "cookies": false, "type": "", "demo": "sites\/list-templates.md", @@ -29412,7 +29916,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 492, + "weight": 504, "cookies": false, "type": "", "demo": "sites\/get-template.md", @@ -29472,7 +29976,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 493, + "weight": 505, "cookies": false, "type": "", "demo": "sites\/list-usage.md", @@ -29544,7 +30048,7 @@ "x-appwrite": { "method": "get", "group": "sites", - "weight": 468, + "weight": 480, "cookies": false, "type": "", "demo": "sites\/get.md", @@ -29603,7 +30107,7 @@ "x-appwrite": { "method": "update", "group": "sites", - "weight": 470, + "weight": 482, "cookies": false, "type": "", "demo": "sites\/update.md", @@ -29848,7 +30352,7 @@ "x-appwrite": { "method": "delete", "group": "sites", - "weight": 471, + "weight": 483, "cookies": false, "type": "", "demo": "sites\/delete.md", @@ -29909,7 +30413,7 @@ "x-appwrite": { "method": "updateSiteDeployment", "group": "sites", - "weight": 478, + "weight": 490, "cookies": false, "type": "", "demo": "sites\/update-site-deployment.md", @@ -29989,7 +30493,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 477, + "weight": 489, "cookies": false, "type": "", "demo": "sites\/list-deployments.md", @@ -30072,7 +30576,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 473, + "weight": 485, "cookies": false, "type": "upload", "demo": "sites\/create-deployment.md", @@ -30173,7 +30677,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 481, + "weight": 493, "cookies": false, "type": "", "demo": "sites\/create-duplicate-deployment.md", @@ -30253,7 +30757,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 474, + "weight": 486, "cookies": false, "type": "", "demo": "sites\/create-template-deployment.md", @@ -30356,7 +30860,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 475, + "weight": 487, "cookies": false, "type": "", "demo": "sites\/create-vcs-deployment.md", @@ -30454,7 +30958,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 476, + "weight": 488, "cookies": false, "type": "", "demo": "sites\/get-deployment.md", @@ -30516,7 +31020,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 479, + "weight": 491, "cookies": false, "type": "", "demo": "sites\/delete-deployment.md", @@ -30580,7 +31084,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 480, + "weight": 492, "cookies": false, "type": "location", "demo": "sites\/get-deployment-download.md", @@ -30670,7 +31174,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 482, + "weight": 494, "cookies": false, "type": "", "demo": "sites\/update-deployment-status.md", @@ -30741,7 +31245,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 484, + "weight": 496, "cookies": false, "type": "", "demo": "sites\/list-logs.md", @@ -30780,7 +31284,10 @@ "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: trigger, status, responseStatusCode, duration, requestMethod, requestPath, deploymentId", "required": false, "schema": { - "type": "string", + "type": "array", + "items": { + "type": "string" + }, "default": [] }, "in": "query" @@ -30812,7 +31319,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 483, + "weight": 495, "cookies": false, "type": "", "demo": "sites\/get-log.md", @@ -30874,7 +31381,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 485, + "weight": 497, "cookies": false, "type": "", "demo": "sites\/delete-log.md", @@ -30945,7 +31452,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 494, + "weight": 506, "cookies": false, "type": "", "demo": "sites\/get-usage.md", @@ -31027,7 +31534,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 488, + "weight": 500, "cookies": false, "type": "", "demo": "sites\/list-variables.md", @@ -31086,7 +31593,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 486, + "weight": 498, "cookies": false, "type": "", "demo": "sites\/create-variable.md", @@ -31177,7 +31684,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 487, + "weight": 499, "cookies": false, "type": "", "demo": "sites\/get-variable.md", @@ -31246,7 +31753,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 489, + "weight": 501, "cookies": false, "type": "", "demo": "sites\/update-variable.md", @@ -31337,7 +31844,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 490, + "weight": 502, "cookies": false, "type": "", "demo": "sites\/delete-variable.md", @@ -32809,7 +33316,7 @@ "x-appwrite": { "method": "list", "group": "tablesdb", - "weight": 376, + "weight": 382, "cookies": false, "type": "", "demo": "tablesdb\/list.md", @@ -32882,7 +33389,7 @@ "x-appwrite": { "method": "create", "group": "tablesdb", - "weight": 372, + "weight": 378, "cookies": false, "type": "", "demo": "tablesdb\/create.md", @@ -32937,6 +33444,424 @@ } } }, + "\/tablesdb\/transactions": { + "get": { + "summary": "List transactions", + "operationId": "tablesDBListTransactions", + "tags": [ + "tablesDB" + ], + "description": "List transactions across all databases.", + "responses": { + "200": { + "description": "Transaction List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transactionList" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "listTransactions", + "group": "transactions", + "weight": 441, + "cookies": false, + "type": "", + "demo": "tablesdb\/list-transactions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/list-transactions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries).", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create transaction", + "operationId": "tablesDBCreateTransaction", + "tags": [ + "tablesDB" + ], + "description": "Create a new transaction.", + "responses": { + "201": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createTransaction", + "group": "transactions", + "weight": 437, + "cookies": false, + "type": "", + "demo": "tablesdb\/create-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/create-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "ttl": { + "type": "integer", + "description": "Seconds before the transaction expires.", + "x-example": 60 + } + } + } + } + } + } + } + }, + "\/tablesdb\/transactions\/{transactionId}": { + "get": { + "summary": "Get transaction", + "operationId": "tablesDBGetTransaction", + "tags": [ + "tablesDB" + ], + "description": "Get a transaction by its unique ID.", + "responses": { + "200": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "getTransaction", + "group": "transactions", + "weight": 438, + "cookies": false, + "type": "", + "demo": "tablesdb\/get-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/get-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update transaction", + "operationId": "tablesDBUpdateTransaction", + "tags": [ + "tablesDB" + ], + "description": "Update a transaction, to either commit or roll back its operations.", + "responses": { + "200": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateTransaction", + "group": "transactions", + "weight": 439, + "cookies": false, + "type": "", + "demo": "tablesdb\/update-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/update-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "commit": { + "type": "boolean", + "description": "Commit transaction?", + "x-example": false + }, + "rollback": { + "type": "boolean", + "description": "Rollback transaction?", + "x-example": false + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete transaction", + "operationId": "tablesDBDeleteTransaction", + "tags": [ + "tablesDB" + ], + "description": "Delete a transaction by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "deprecated": false, + "x-appwrite": { + "method": "deleteTransaction", + "group": "transactions", + "weight": 440, + "cookies": false, + "type": "", + "demo": "tablesdb\/delete-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/delete-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/tablesdb\/transactions\/{transactionId}\/operations": { + "post": { + "summary": "Create operations", + "operationId": "tablesDBCreateOperations", + "tags": [ + "tablesDB" + ], + "description": "Create multiple operations in a single transaction.", + "responses": { + "201": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createOperations", + "group": "transactions", + "weight": 442, + "cookies": false, + "type": "", + "demo": "tablesdb\/create-operations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/create-operations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "operations": { + "type": "array", + "description": "Array of staged operations.", + "x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"\",\n\t \"tableId\": \"\",\n\t \"rowId\": \"\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]", + "items": { + "type": "object" + } + } + } + } + } + } + } + } + }, "\/tablesdb\/usage": { "get": { "summary": "Get TablesDB usage stats", @@ -32961,7 +33886,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 378, + "weight": 384, "cookies": false, "type": "", "demo": "tablesdb\/list-usage.md", @@ -33058,7 +33983,7 @@ "x-appwrite": { "method": "get", "group": "tablesdb", - "weight": 373, + "weight": 379, "cookies": false, "type": "", "demo": "tablesdb\/get.md", @@ -33117,7 +34042,7 @@ "x-appwrite": { "method": "update", "group": "tablesdb", - "weight": 374, + "weight": 380, "cookies": false, "type": "", "demo": "tablesdb\/update.md", @@ -33193,7 +34118,7 @@ "x-appwrite": { "method": "delete", "group": "tablesdb", - "weight": 375, + "weight": 381, "cookies": false, "type": "", "demo": "tablesdb\/delete.md", @@ -33254,7 +34179,7 @@ "x-appwrite": { "method": "listTables", "group": "tables", - "weight": 383, + "weight": 389, "cookies": false, "type": "", "demo": "tablesdb\/list-tables.md", @@ -33340,7 +34265,7 @@ "x-appwrite": { "method": "createTable", "group": "tables", - "weight": 379, + "weight": 385, "cookies": false, "type": "", "demo": "tablesdb\/create-table.md", @@ -33447,7 +34372,7 @@ "x-appwrite": { "method": "getTable", "group": "tables", - "weight": 380, + "weight": 386, "cookies": false, "type": "", "demo": "tablesdb\/get-table.md", @@ -33519,7 +34444,7 @@ "x-appwrite": { "method": "updateTable", "group": "tables", - "weight": 381, + "weight": 387, "cookies": false, "type": "", "demo": "tablesdb\/update-table.md", @@ -33621,7 +34546,7 @@ "x-appwrite": { "method": "deleteTable", "group": "tables", - "weight": 382, + "weight": 388, "cookies": false, "type": "", "demo": "tablesdb\/delete-table.md", @@ -33695,7 +34620,7 @@ "x-appwrite": { "method": "listColumns", "group": "columns", - "weight": 388, + "weight": 394, "cookies": false, "type": "", "demo": "tablesdb\/list-columns.md", @@ -33782,7 +34707,7 @@ "x-appwrite": { "method": "createBooleanColumn", "group": "columns", - "weight": 389, + "weight": 395, "cookies": false, "type": "", "demo": "tablesdb\/create-boolean-column.md", @@ -33891,7 +34816,7 @@ "x-appwrite": { "method": "updateBooleanColumn", "group": "columns", - "weight": 390, + "weight": 396, "cookies": false, "type": "", "demo": "tablesdb\/update-boolean-column.md", @@ -34005,7 +34930,7 @@ "x-appwrite": { "method": "createDatetimeColumn", "group": "columns", - "weight": 391, + "weight": 397, "cookies": false, "type": "", "demo": "tablesdb\/create-datetime-column.md", @@ -34114,7 +35039,7 @@ "x-appwrite": { "method": "updateDatetimeColumn", "group": "columns", - "weight": 392, + "weight": 398, "cookies": false, "type": "", "demo": "tablesdb\/update-datetime-column.md", @@ -34228,7 +35153,7 @@ "x-appwrite": { "method": "createEmailColumn", "group": "columns", - "weight": 393, + "weight": 399, "cookies": false, "type": "", "demo": "tablesdb\/create-email-column.md", @@ -34337,7 +35262,7 @@ "x-appwrite": { "method": "updateEmailColumn", "group": "columns", - "weight": 394, + "weight": 400, "cookies": false, "type": "", "demo": "tablesdb\/update-email-column.md", @@ -34451,7 +35376,7 @@ "x-appwrite": { "method": "createEnumColumn", "group": "columns", - "weight": 395, + "weight": 401, "cookies": false, "type": "", "demo": "tablesdb\/create-enum-column.md", @@ -34569,7 +35494,7 @@ "x-appwrite": { "method": "updateEnumColumn", "group": "columns", - "weight": 396, + "weight": 402, "cookies": false, "type": "", "demo": "tablesdb\/update-enum-column.md", @@ -34692,7 +35617,7 @@ "x-appwrite": { "method": "createFloatColumn", "group": "columns", - "weight": 397, + "weight": 403, "cookies": false, "type": "", "demo": "tablesdb\/create-float-column.md", @@ -34811,7 +35736,7 @@ "x-appwrite": { "method": "updateFloatColumn", "group": "columns", - "weight": 398, + "weight": 404, "cookies": false, "type": "", "demo": "tablesdb\/update-float-column.md", @@ -34935,7 +35860,7 @@ "x-appwrite": { "method": "createIntegerColumn", "group": "columns", - "weight": 399, + "weight": 405, "cookies": false, "type": "", "demo": "tablesdb\/create-integer-column.md", @@ -35054,7 +35979,7 @@ "x-appwrite": { "method": "updateIntegerColumn", "group": "columns", - "weight": 400, + "weight": 406, "cookies": false, "type": "", "demo": "tablesdb\/update-integer-column.md", @@ -35178,7 +36103,7 @@ "x-appwrite": { "method": "createIpColumn", "group": "columns", - "weight": 401, + "weight": 407, "cookies": false, "type": "", "demo": "tablesdb\/create-ip-column.md", @@ -35287,7 +36212,7 @@ "x-appwrite": { "method": "updateIpColumn", "group": "columns", - "weight": 402, + "weight": 408, "cookies": false, "type": "", "demo": "tablesdb\/update-ip-column.md", @@ -35401,7 +36326,7 @@ "x-appwrite": { "method": "createLineColumn", "group": "columns", - "weight": 403, + "weight": 409, "cookies": false, "type": "", "demo": "tablesdb\/create-line-column.md", @@ -35513,7 +36438,7 @@ "x-appwrite": { "method": "updateLineColumn", "group": "columns", - "weight": 404, + "weight": 410, "cookies": false, "type": "", "demo": "tablesdb\/update-line-column.md", @@ -35633,7 +36558,7 @@ "x-appwrite": { "method": "createPointColumn", "group": "columns", - "weight": 405, + "weight": 411, "cookies": false, "type": "", "demo": "tablesdb\/create-point-column.md", @@ -35745,7 +36670,7 @@ "x-appwrite": { "method": "updatePointColumn", "group": "columns", - "weight": 406, + "weight": 412, "cookies": false, "type": "", "demo": "tablesdb\/update-point-column.md", @@ -35865,7 +36790,7 @@ "x-appwrite": { "method": "createPolygonColumn", "group": "columns", - "weight": 407, + "weight": 413, "cookies": false, "type": "", "demo": "tablesdb\/create-polygon-column.md", @@ -35977,7 +36902,7 @@ "x-appwrite": { "method": "updatePolygonColumn", "group": "columns", - "weight": 408, + "weight": 414, "cookies": false, "type": "", "demo": "tablesdb\/update-polygon-column.md", @@ -36097,7 +37022,7 @@ "x-appwrite": { "method": "createRelationshipColumn", "group": "columns", - "weight": 409, + "weight": 415, "cookies": false, "type": "", "demo": "tablesdb\/create-relationship-column.md", @@ -36231,7 +37156,7 @@ "x-appwrite": { "method": "createStringColumn", "group": "columns", - "weight": 411, + "weight": 417, "cookies": false, "type": "", "demo": "tablesdb\/create-string-column.md", @@ -36351,7 +37276,7 @@ "x-appwrite": { "method": "updateStringColumn", "group": "columns", - "weight": 412, + "weight": 418, "cookies": false, "type": "", "demo": "tablesdb\/update-string-column.md", @@ -36470,7 +37395,7 @@ "x-appwrite": { "method": "createUrlColumn", "group": "columns", - "weight": 413, + "weight": 419, "cookies": false, "type": "", "demo": "tablesdb\/create-url-column.md", @@ -36579,7 +37504,7 @@ "x-appwrite": { "method": "updateUrlColumn", "group": "columns", - "weight": 414, + "weight": 420, "cookies": false, "type": "", "demo": "tablesdb\/update-url-column.md", @@ -36724,7 +37649,7 @@ "x-appwrite": { "method": "getColumn", "group": "columns", - "weight": 386, + "weight": 392, "cookies": false, "type": "", "demo": "tablesdb\/get-column.md", @@ -36798,7 +37723,7 @@ "x-appwrite": { "method": "deleteColumn", "group": "columns", - "weight": 387, + "weight": 393, "cookies": false, "type": "", "demo": "tablesdb\/delete-column.md", @@ -36881,7 +37806,7 @@ "x-appwrite": { "method": "updateRelationshipColumn", "group": "columns", - "weight": 410, + "weight": 416, "cookies": false, "type": "", "demo": "tablesdb\/update-relationship-column.md", @@ -36992,7 +37917,7 @@ "x-appwrite": { "method": "listIndexes", "group": "indexes", - "weight": 418, + "weight": 424, "cookies": false, "type": "", "demo": "tablesdb\/list-indexes.md", @@ -37077,7 +38002,7 @@ "x-appwrite": { "method": "createIndex", "group": "indexes", - "weight": 415, + "weight": 421, "cookies": false, "type": "", "demo": "tablesdb\/create-index.md", @@ -37209,7 +38134,7 @@ "x-appwrite": { "method": "getIndex", "group": "indexes", - "weight": 416, + "weight": 422, "cookies": false, "type": "", "demo": "tablesdb\/get-index.md", @@ -37283,7 +38208,7 @@ "x-appwrite": { "method": "deleteIndex", "group": "indexes", - "weight": 417, + "weight": 423, "cookies": false, "type": "", "demo": "tablesdb\/delete-index.md", @@ -37366,7 +38291,7 @@ "x-appwrite": { "method": "listTableLogs", "group": "tables", - "weight": 384, + "weight": 390, "cookies": false, "type": "", "demo": "tablesdb\/list-table-logs.md", @@ -37452,7 +38377,7 @@ "x-appwrite": { "method": "listRows", "group": "rows", - "weight": 427, + "weight": 433, "cookies": false, "type": "", "demo": "tablesdb\/list-rows.md", @@ -37514,6 +38439,16 @@ "default": [] }, "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" } ] }, @@ -37540,7 +38475,7 @@ "x-appwrite": { "method": "createRow", "group": "rows", - "weight": 419, + "weight": 425, "cookies": false, "type": "", "demo": "tablesdb\/create-row.md", @@ -37571,7 +38506,8 @@ "tableId", "rowId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -37598,7 +38534,8 @@ "parameters": [ "databaseId", "tableId", - "rows" + "rows", + "transactionId" ], "required": [ "databaseId", @@ -37679,6 +38616,11 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -37709,7 +38651,7 @@ "x-appwrite": { "method": "upsertRows", "group": "rows", - "weight": 424, + "weight": 430, "cookies": false, "type": "", "demo": "tablesdb\/upsert-rows.md", @@ -37737,7 +38679,8 @@ "parameters": [ "databaseId", "tableId", - "rows" + "rows", + "transactionId" ], "required": [ "databaseId", @@ -37799,6 +38742,11 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } }, "required": [ @@ -37832,7 +38780,7 @@ "x-appwrite": { "method": "updateRows", "group": "rows", - "weight": 422, + "weight": 428, "cookies": false, "type": "", "demo": "tablesdb\/update-rows.md", @@ -37899,6 +38847,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -37929,7 +38882,7 @@ "x-appwrite": { "method": "deleteRows", "group": "rows", - "weight": 426, + "weight": 432, "cookies": false, "type": "", "demo": "tablesdb\/delete-rows.md", @@ -37991,6 +38944,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -38023,7 +38981,7 @@ "x-appwrite": { "method": "getRow", "group": "rows", - "weight": 420, + "weight": 426, "cookies": false, "type": "", "demo": "tablesdb\/get-row.md", @@ -38095,6 +39053,16 @@ "default": [] }, "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" } ] }, @@ -38121,7 +39089,7 @@ "x-appwrite": { "method": "upsertRow", "group": "rows", - "weight": 423, + "weight": 429, "cookies": false, "type": "", "demo": "tablesdb\/upsert-row.md", @@ -38152,7 +39120,8 @@ "tableId", "rowId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -38230,6 +39199,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -38260,7 +39234,7 @@ "x-appwrite": { "method": "updateRow", "group": "rows", - "weight": 421, + "weight": 427, "cookies": false, "type": "", "demo": "tablesdb\/update-row.md", @@ -38339,6 +39313,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -38362,7 +39341,7 @@ "x-appwrite": { "method": "deleteRow", "group": "rows", - "weight": 425, + "weight": 431, "cookies": false, "type": "", "demo": "tablesdb\/delete-row.md", @@ -38422,7 +39401,23 @@ }, "in": "path" } - ] + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" + } + } + } + } + } + } } }, "\/tablesdb\/{databaseId}\/tables\/{tableId}\/rows\/{rowId}\/logs": { @@ -38449,7 +39444,7 @@ "x-appwrite": { "method": "listRowLogs", "group": "logs", - "weight": 428, + "weight": 434, "cookies": false, "type": "", "demo": "tablesdb\/list-row-logs.md", @@ -38545,7 +39540,7 @@ "x-appwrite": { "method": "decrementRowColumn", "group": "rows", - "weight": 430, + "weight": 436, "cookies": false, "type": "", "demo": "tablesdb\/decrement-row-column.md", @@ -38631,6 +39626,11 @@ "type": "number", "description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.", "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -38663,7 +39663,7 @@ "x-appwrite": { "method": "incrementRowColumn", "group": "rows", - "weight": 429, + "weight": 435, "cookies": false, "type": "", "demo": "tablesdb\/increment-row-column.md", @@ -38749,6 +39749,11 @@ "type": "number", "description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.", "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -38781,7 +39786,7 @@ "x-appwrite": { "method": "getTableUsage", "group": null, - "weight": 385, + "weight": 391, "cookies": false, "type": "", "demo": "tablesdb\/get-table-usage.md", @@ -38876,7 +39881,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 377, + "weight": 383, "cookies": false, "type": "", "demo": "tablesdb\/get-usage.md", @@ -40088,7 +41093,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 507, + "weight": 519, "cookies": false, "type": "", "demo": "tokens\/list.md", @@ -40138,7 +41143,10 @@ "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: expire", "required": false, "schema": { - "type": "string", + "type": "array", + "items": { + "type": "string" + }, "default": [] }, "in": "query" @@ -40168,7 +41176,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 505, + "weight": 517, "cookies": false, "type": "", "demo": "tokens\/create-file-token.md", @@ -40257,7 +41265,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 506, + "weight": 518, "cookies": false, "type": "", "demo": "tokens\/get.md", @@ -40317,7 +41325,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 508, + "weight": 520, "cookies": false, "type": "", "demo": "tokens\/update.md", @@ -40387,7 +41395,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 509, + "weight": 521, "cookies": false, "type": "", "demo": "tokens\/delete.md", @@ -46211,6 +47219,34 @@ "targets": "" } }, + "transactionList": { + "description": "Transaction List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of transactions that matched your query.", + "x-example": 5, + "format": "int32" + }, + "transactions": { + "type": "array", + "description": "List of transactions.", + "items": { + "$ref": "#\/components\/schemas\/transaction" + }, + "x-example": "" + } + }, + "required": [ + "total", + "transactions" + ], + "example": { + "total": 5, + "transactions": "" + } + }, "migrationList": { "description": "Migrations List", "type": "object", @@ -56890,6 +57926,59 @@ "subscribe": "users" } }, + "transaction": { + "description": "Transaction", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Transaction ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Transaction creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Transaction update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "status": { + "type": "string", + "description": "Current status of the transaction. One of: pending, committing, committed, rolled_back, failed.", + "x-example": "pending" + }, + "operations": { + "type": "integer", + "description": "Number of operations in the transaction.", + "x-example": 5, + "format": "int32" + }, + "expiresAt": { + "type": "string", + "description": "Expiration time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "status", + "operations", + "expiresAt" + ], + "example": { + "$id": "259125845563242502", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "status": "pending", + "operations": 5, + "expiresAt": "2020-10-15T06:38:00.000+00:00" + } + }, "subscriber": { "description": "Subscriber", "type": "object", diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index 16e861ba9f..49adaeeefa 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -4851,6 +4851,436 @@ } } }, + "\/databases\/transactions": { + "get": { + "summary": "List transactions", + "operationId": "databasesListTransactions", + "tags": [ + "databases" + ], + "description": "List transactions across all databases.", + "responses": { + "200": { + "description": "Transaction List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transactionList" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "listTransactions", + "group": "transactions", + "weight": 376, + "cookies": false, + "type": "", + "demo": "databases\/list-transactions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-transactions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries).", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create transaction", + "operationId": "databasesCreateTransaction", + "tags": [ + "databases" + ], + "description": "Create a new transaction.", + "responses": { + "201": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createTransaction", + "group": "transactions", + "weight": 372, + "cookies": false, + "type": "", + "demo": "databases\/create-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "ttl": { + "type": "integer", + "description": "Seconds before the transaction expires.", + "x-example": 60 + } + } + } + } + } + } + } + }, + "\/databases\/transactions\/{transactionId}": { + "get": { + "summary": "Get transaction", + "operationId": "databasesGetTransaction", + "tags": [ + "databases" + ], + "description": "Get a transaction by its unique ID.", + "responses": { + "200": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "getTransaction", + "group": "transactions", + "weight": 373, + "cookies": false, + "type": "", + "demo": "databases\/get-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update transaction", + "operationId": "databasesUpdateTransaction", + "tags": [ + "databases" + ], + "description": "Update a transaction, to either commit or roll back its operations.", + "responses": { + "200": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateTransaction", + "group": "transactions", + "weight": 374, + "cookies": false, + "type": "", + "demo": "databases\/update-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "commit": { + "type": "boolean", + "description": "Commit transaction?", + "x-example": false + }, + "rollback": { + "type": "boolean", + "description": "Rollback transaction?", + "x-example": false + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete transaction", + "operationId": "databasesDeleteTransaction", + "tags": [ + "databases" + ], + "description": "Delete a transaction by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "deprecated": false, + "x-appwrite": { + "method": "deleteTransaction", + "group": "transactions", + "weight": 375, + "cookies": false, + "type": "", + "demo": "databases\/delete-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/databases\/transactions\/{transactionId}\/operations": { + "post": { + "summary": "Create operations", + "operationId": "databasesCreateOperations", + "tags": [ + "databases" + ], + "description": "Create multiple operations in a single transaction.", + "responses": { + "201": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createOperations", + "group": "transactions", + "weight": 377, + "cookies": false, + "type": "", + "demo": "databases\/create-operations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-operations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "operations": { + "type": "array", + "description": "Array of staged operations.", + "x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"\",\n\t \"collectionId\": \"\",\n\t \"documentId\": \"\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]", + "items": { + "type": "object" + } + } + } + } + } + } + } + } + }, "\/databases\/{databaseId}": { "get": { "summary": "Get database", @@ -9046,6 +9476,16 @@ "default": [] }, "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" } ] }, @@ -9105,7 +9545,8 @@ "collectionId", "documentId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -9137,7 +9578,8 @@ "parameters": [ "databaseId", "collectionId", - "documents" + "documents", + "transactionId" ], "required": [ "databaseId", @@ -9224,6 +9666,11 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -9284,7 +9731,8 @@ "parameters": [ "databaseId", "collectionId", - "documents" + "documents", + "transactionId" ], "required": [ "databaseId", @@ -9351,6 +9799,11 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } }, "required": [ @@ -9453,6 +9906,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -9547,6 +10005,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -9654,6 +10117,16 @@ "default": [] }, "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" } ] }, @@ -9713,7 +10186,8 @@ "collectionId", "documentId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -9798,6 +10272,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } }, "required": [ @@ -9913,6 +10392,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -9999,7 +10483,23 @@ }, "in": "path" } - ] + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" + } + } + } + } + } + } } }, "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/decrement": { @@ -10115,6 +10615,11 @@ "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -10236,6 +10741,11 @@ "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -10472,7 +10982,7 @@ "tags": [ "databases" ], - "description": "Get index by ID.", + "description": "Get an index by its unique ID.", "responses": { "200": { "description": "Index", @@ -10650,7 +11160,7 @@ "x-appwrite": { "method": "list", "group": "functions", - "weight": 440, + "weight": 452, "cookies": false, "type": "", "demo": "functions\/list.md", @@ -10724,7 +11234,7 @@ "x-appwrite": { "method": "create", "group": "functions", - "weight": 437, + "weight": 449, "cookies": false, "type": "", "demo": "functions\/create.md", @@ -10958,7 +11468,7 @@ "x-appwrite": { "method": "listRuntimes", "group": "runtimes", - "weight": 442, + "weight": 454, "cookies": false, "type": "", "demo": "functions\/list-runtimes.md", @@ -11008,7 +11518,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "runtimes", - "weight": 443, + "weight": 455, "cookies": false, "type": "", "demo": "functions\/list-specifications.md", @@ -11059,7 +11569,7 @@ "x-appwrite": { "method": "get", "group": "functions", - "weight": 438, + "weight": 450, "cookies": false, "type": "", "demo": "functions\/get.md", @@ -11119,7 +11629,7 @@ "x-appwrite": { "method": "update", "group": "functions", - "weight": 439, + "weight": 451, "cookies": false, "type": "", "demo": "functions\/update.md", @@ -11350,7 +11860,7 @@ "x-appwrite": { "method": "delete", "group": "functions", - "weight": 441, + "weight": 453, "cookies": false, "type": "", "demo": "functions\/delete.md", @@ -11412,7 +11922,7 @@ "x-appwrite": { "method": "updateFunctionDeployment", "group": "functions", - "weight": 446, + "weight": 458, "cookies": false, "type": "", "demo": "functions\/update-function-deployment.md", @@ -11493,7 +12003,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 447, + "weight": 459, "cookies": false, "type": "", "demo": "functions\/list-deployments.md", @@ -11577,7 +12087,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 444, + "weight": 456, "cookies": false, "type": "upload", "demo": "functions\/create-deployment.md", @@ -11674,7 +12184,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 452, + "weight": 464, "cookies": false, "type": "", "demo": "functions\/create-duplicate-deployment.md", @@ -11760,7 +12270,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 449, + "weight": 461, "cookies": false, "type": "", "demo": "functions\/create-template-deployment.md", @@ -11864,7 +12374,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 450, + "weight": 462, "cookies": false, "type": "", "demo": "functions\/create-vcs-deployment.md", @@ -11962,7 +12472,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 445, + "weight": 457, "cookies": false, "type": "", "demo": "functions\/get-deployment.md", @@ -12025,7 +12535,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 448, + "weight": 460, "cookies": false, "type": "", "demo": "functions\/delete-deployment.md", @@ -12090,7 +12600,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 451, + "weight": 463, "cookies": false, "type": "location", "demo": "functions\/get-deployment-download.md", @@ -12181,7 +12691,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 453, + "weight": 465, "cookies": false, "type": "", "demo": "functions\/update-deployment-status.md", @@ -12253,7 +12763,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 456, + "weight": 468, "cookies": false, "type": "", "demo": "functions\/list-executions.md", @@ -12330,7 +12840,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 454, + "weight": 466, "cookies": false, "type": "", "demo": "functions\/create-execution.md", @@ -12408,9 +12918,9 @@ "x-enum-keys": [] }, "headers": { - "type": "string", + "type": "object", "description": "HTTP headers of execution. Defaults to empty.", - "x-example": null + "x-example": "{}" }, "scheduledAt": { "type": "string", @@ -12448,7 +12958,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 455, + "weight": 467, "cookies": false, "type": "", "demo": "functions\/get-execution.md", @@ -12515,7 +13025,7 @@ "x-appwrite": { "method": "deleteExecution", "group": "executions", - "weight": 457, + "weight": 469, "cookies": false, "type": "", "demo": "functions\/delete-execution.md", @@ -12587,7 +13097,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 462, + "weight": 474, "cookies": false, "type": "", "demo": "functions\/list-variables.md", @@ -12647,7 +13157,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 460, + "weight": 472, "cookies": false, "type": "", "demo": "functions\/create-variable.md", @@ -12739,7 +13249,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 461, + "weight": 473, "cookies": false, "type": "", "demo": "functions\/get-variable.md", @@ -12809,7 +13319,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 463, + "weight": 475, "cookies": false, "type": "", "demo": "functions\/update-variable.md", @@ -12901,7 +13411,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 464, + "weight": 476, "cookies": false, "type": "", "demo": "functions\/delete-variable.md", @@ -15282,7 +15792,7 @@ "image": { "type": "string", "description": "Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as :.", - "x-example": "[ID1:ID2]" + "x-example": "" }, "icon": { "type": "string", @@ -15464,7 +15974,7 @@ "image": { "type": "string", "description": "Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as :.", - "x-example": "[ID1:ID2]" + "x-example": "" }, "icon": { "type": "string", @@ -19825,7 +20335,7 @@ "x-appwrite": { "method": "list", "group": "sites", - "weight": 469, + "weight": 481, "cookies": false, "type": "", "demo": "sites\/list.md", @@ -19855,7 +20365,10 @@ "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, enabled, framework, deploymentId, buildCommand, installCommand, outputDirectory, installationId", "required": false, "schema": { - "type": "string", + "type": "array", + "items": { + "type": "string" + }, "default": [] }, "in": "query" @@ -19896,7 +20409,7 @@ "x-appwrite": { "method": "create", "group": "sites", - "weight": 467, + "weight": 479, "cookies": false, "type": "", "demo": "sites\/create.md", @@ -20146,7 +20659,7 @@ "x-appwrite": { "method": "listFrameworks", "group": "frameworks", - "weight": 472, + "weight": 484, "cookies": false, "type": "", "demo": "sites\/list-frameworks.md", @@ -20196,7 +20709,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 495, + "weight": 507, "cookies": false, "type": "", "demo": "sites\/list-specifications.md", @@ -20247,7 +20760,7 @@ "x-appwrite": { "method": "get", "group": "sites", - "weight": 468, + "weight": 480, "cookies": false, "type": "", "demo": "sites\/get.md", @@ -20307,7 +20820,7 @@ "x-appwrite": { "method": "update", "group": "sites", - "weight": 470, + "weight": 482, "cookies": false, "type": "", "demo": "sites\/update.md", @@ -20553,7 +21066,7 @@ "x-appwrite": { "method": "delete", "group": "sites", - "weight": 471, + "weight": 483, "cookies": false, "type": "", "demo": "sites\/delete.md", @@ -20615,7 +21128,7 @@ "x-appwrite": { "method": "updateSiteDeployment", "group": "sites", - "weight": 478, + "weight": 490, "cookies": false, "type": "", "demo": "sites\/update-site-deployment.md", @@ -20696,7 +21209,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 477, + "weight": 489, "cookies": false, "type": "", "demo": "sites\/list-deployments.md", @@ -20780,7 +21293,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 473, + "weight": 485, "cookies": false, "type": "upload", "demo": "sites\/create-deployment.md", @@ -20882,7 +21395,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 481, + "weight": 493, "cookies": false, "type": "", "demo": "sites\/create-duplicate-deployment.md", @@ -20963,7 +21476,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 474, + "weight": 486, "cookies": false, "type": "", "demo": "sites\/create-template-deployment.md", @@ -21067,7 +21580,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 475, + "weight": 487, "cookies": false, "type": "", "demo": "sites\/create-vcs-deployment.md", @@ -21166,7 +21679,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 476, + "weight": 488, "cookies": false, "type": "", "demo": "sites\/get-deployment.md", @@ -21229,7 +21742,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 479, + "weight": 491, "cookies": false, "type": "", "demo": "sites\/delete-deployment.md", @@ -21294,7 +21807,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 480, + "weight": 492, "cookies": false, "type": "location", "demo": "sites\/get-deployment-download.md", @@ -21385,7 +21898,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 482, + "weight": 494, "cookies": false, "type": "", "demo": "sites\/update-deployment-status.md", @@ -21457,7 +21970,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 484, + "weight": 496, "cookies": false, "type": "", "demo": "sites\/list-logs.md", @@ -21497,7 +22010,10 @@ "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: trigger, status, responseStatusCode, duration, requestMethod, requestPath, deploymentId", "required": false, "schema": { - "type": "string", + "type": "array", + "items": { + "type": "string" + }, "default": [] }, "in": "query" @@ -21529,7 +22045,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 483, + "weight": 495, "cookies": false, "type": "", "demo": "sites\/get-log.md", @@ -21592,7 +22108,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 485, + "weight": 497, "cookies": false, "type": "", "demo": "sites\/delete-log.md", @@ -21664,7 +22180,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 488, + "weight": 500, "cookies": false, "type": "", "demo": "sites\/list-variables.md", @@ -21724,7 +22240,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 486, + "weight": 498, "cookies": false, "type": "", "demo": "sites\/create-variable.md", @@ -21816,7 +22332,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 487, + "weight": 499, "cookies": false, "type": "", "demo": "sites\/get-variable.md", @@ -21886,7 +22402,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 489, + "weight": 501, "cookies": false, "type": "", "demo": "sites\/update-variable.md", @@ -21978,7 +22494,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 490, + "weight": 502, "cookies": false, "type": "", "demo": "sites\/delete-variable.md", @@ -23318,7 +23834,7 @@ "x-appwrite": { "method": "list", "group": "tablesdb", - "weight": 376, + "weight": 382, "cookies": false, "type": "", "demo": "tablesdb\/list.md", @@ -23392,7 +23908,7 @@ "x-appwrite": { "method": "create", "group": "tablesdb", - "weight": 372, + "weight": 378, "cookies": false, "type": "", "demo": "tablesdb\/create.md", @@ -23448,6 +23964,436 @@ } } }, + "\/tablesdb\/transactions": { + "get": { + "summary": "List transactions", + "operationId": "tablesDBListTransactions", + "tags": [ + "tablesDB" + ], + "description": "List transactions across all databases.", + "responses": { + "200": { + "description": "Transaction List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transactionList" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "listTransactions", + "group": "transactions", + "weight": 441, + "cookies": false, + "type": "", + "demo": "tablesdb\/list-transactions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/list-transactions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries).", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create transaction", + "operationId": "tablesDBCreateTransaction", + "tags": [ + "tablesDB" + ], + "description": "Create a new transaction.", + "responses": { + "201": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createTransaction", + "group": "transactions", + "weight": 437, + "cookies": false, + "type": "", + "demo": "tablesdb\/create-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/create-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "ttl": { + "type": "integer", + "description": "Seconds before the transaction expires.", + "x-example": 60 + } + } + } + } + } + } + } + }, + "\/tablesdb\/transactions\/{transactionId}": { + "get": { + "summary": "Get transaction", + "operationId": "tablesDBGetTransaction", + "tags": [ + "tablesDB" + ], + "description": "Get a transaction by its unique ID.", + "responses": { + "200": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "getTransaction", + "group": "transactions", + "weight": 438, + "cookies": false, + "type": "", + "demo": "tablesdb\/get-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/get-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update transaction", + "operationId": "tablesDBUpdateTransaction", + "tags": [ + "tablesDB" + ], + "description": "Update a transaction, to either commit or roll back its operations.", + "responses": { + "200": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateTransaction", + "group": "transactions", + "weight": 439, + "cookies": false, + "type": "", + "demo": "tablesdb\/update-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/update-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "commit": { + "type": "boolean", + "description": "Commit transaction?", + "x-example": false + }, + "rollback": { + "type": "boolean", + "description": "Rollback transaction?", + "x-example": false + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete transaction", + "operationId": "tablesDBDeleteTransaction", + "tags": [ + "tablesDB" + ], + "description": "Delete a transaction by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "deprecated": false, + "x-appwrite": { + "method": "deleteTransaction", + "group": "transactions", + "weight": 440, + "cookies": false, + "type": "", + "demo": "tablesdb\/delete-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/delete-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/tablesdb\/transactions\/{transactionId}\/operations": { + "post": { + "summary": "Create operations", + "operationId": "tablesDBCreateOperations", + "tags": [ + "tablesDB" + ], + "description": "Create multiple operations in a single transaction.", + "responses": { + "201": { + "description": "Transaction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/transaction" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createOperations", + "group": "transactions", + "weight": 442, + "cookies": false, + "type": "", + "demo": "tablesdb\/create-operations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/create-operations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "operations": { + "type": "array", + "description": "Array of staged operations.", + "x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"\",\n\t \"tableId\": \"\",\n\t \"rowId\": \"\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]", + "items": { + "type": "object" + } + } + } + } + } + } + } + } + }, "\/tablesdb\/{databaseId}": { "get": { "summary": "Get database", @@ -23472,7 +24418,7 @@ "x-appwrite": { "method": "get", "group": "tablesdb", - "weight": 373, + "weight": 379, "cookies": false, "type": "", "demo": "tablesdb\/get.md", @@ -23532,7 +24478,7 @@ "x-appwrite": { "method": "update", "group": "tablesdb", - "weight": 374, + "weight": 380, "cookies": false, "type": "", "demo": "tablesdb\/update.md", @@ -23609,7 +24555,7 @@ "x-appwrite": { "method": "delete", "group": "tablesdb", - "weight": 375, + "weight": 381, "cookies": false, "type": "", "demo": "tablesdb\/delete.md", @@ -23671,7 +24617,7 @@ "x-appwrite": { "method": "listTables", "group": "tables", - "weight": 383, + "weight": 389, "cookies": false, "type": "", "demo": "tablesdb\/list-tables.md", @@ -23758,7 +24704,7 @@ "x-appwrite": { "method": "createTable", "group": "tables", - "weight": 379, + "weight": 385, "cookies": false, "type": "", "demo": "tablesdb\/create-table.md", @@ -23866,7 +24812,7 @@ "x-appwrite": { "method": "getTable", "group": "tables", - "weight": 380, + "weight": 386, "cookies": false, "type": "", "demo": "tablesdb\/get-table.md", @@ -23939,7 +24885,7 @@ "x-appwrite": { "method": "updateTable", "group": "tables", - "weight": 381, + "weight": 387, "cookies": false, "type": "", "demo": "tablesdb\/update-table.md", @@ -24042,7 +24988,7 @@ "x-appwrite": { "method": "deleteTable", "group": "tables", - "weight": 382, + "weight": 388, "cookies": false, "type": "", "demo": "tablesdb\/delete-table.md", @@ -24117,7 +25063,7 @@ "x-appwrite": { "method": "listColumns", "group": "columns", - "weight": 388, + "weight": 394, "cookies": false, "type": "", "demo": "tablesdb\/list-columns.md", @@ -24205,7 +25151,7 @@ "x-appwrite": { "method": "createBooleanColumn", "group": "columns", - "weight": 389, + "weight": 395, "cookies": false, "type": "", "demo": "tablesdb\/create-boolean-column.md", @@ -24315,7 +25261,7 @@ "x-appwrite": { "method": "updateBooleanColumn", "group": "columns", - "weight": 390, + "weight": 396, "cookies": false, "type": "", "demo": "tablesdb\/update-boolean-column.md", @@ -24430,7 +25376,7 @@ "x-appwrite": { "method": "createDatetimeColumn", "group": "columns", - "weight": 391, + "weight": 397, "cookies": false, "type": "", "demo": "tablesdb\/create-datetime-column.md", @@ -24540,7 +25486,7 @@ "x-appwrite": { "method": "updateDatetimeColumn", "group": "columns", - "weight": 392, + "weight": 398, "cookies": false, "type": "", "demo": "tablesdb\/update-datetime-column.md", @@ -24655,7 +25601,7 @@ "x-appwrite": { "method": "createEmailColumn", "group": "columns", - "weight": 393, + "weight": 399, "cookies": false, "type": "", "demo": "tablesdb\/create-email-column.md", @@ -24765,7 +25711,7 @@ "x-appwrite": { "method": "updateEmailColumn", "group": "columns", - "weight": 394, + "weight": 400, "cookies": false, "type": "", "demo": "tablesdb\/update-email-column.md", @@ -24880,7 +25826,7 @@ "x-appwrite": { "method": "createEnumColumn", "group": "columns", - "weight": 395, + "weight": 401, "cookies": false, "type": "", "demo": "tablesdb\/create-enum-column.md", @@ -24999,7 +25945,7 @@ "x-appwrite": { "method": "updateEnumColumn", "group": "columns", - "weight": 396, + "weight": 402, "cookies": false, "type": "", "demo": "tablesdb\/update-enum-column.md", @@ -25123,7 +26069,7 @@ "x-appwrite": { "method": "createFloatColumn", "group": "columns", - "weight": 397, + "weight": 403, "cookies": false, "type": "", "demo": "tablesdb\/create-float-column.md", @@ -25243,7 +26189,7 @@ "x-appwrite": { "method": "updateFloatColumn", "group": "columns", - "weight": 398, + "weight": 404, "cookies": false, "type": "", "demo": "tablesdb\/update-float-column.md", @@ -25368,7 +26314,7 @@ "x-appwrite": { "method": "createIntegerColumn", "group": "columns", - "weight": 399, + "weight": 405, "cookies": false, "type": "", "demo": "tablesdb\/create-integer-column.md", @@ -25488,7 +26434,7 @@ "x-appwrite": { "method": "updateIntegerColumn", "group": "columns", - "weight": 400, + "weight": 406, "cookies": false, "type": "", "demo": "tablesdb\/update-integer-column.md", @@ -25613,7 +26559,7 @@ "x-appwrite": { "method": "createIpColumn", "group": "columns", - "weight": 401, + "weight": 407, "cookies": false, "type": "", "demo": "tablesdb\/create-ip-column.md", @@ -25723,7 +26669,7 @@ "x-appwrite": { "method": "updateIpColumn", "group": "columns", - "weight": 402, + "weight": 408, "cookies": false, "type": "", "demo": "tablesdb\/update-ip-column.md", @@ -25838,7 +26784,7 @@ "x-appwrite": { "method": "createLineColumn", "group": "columns", - "weight": 403, + "weight": 409, "cookies": false, "type": "", "demo": "tablesdb\/create-line-column.md", @@ -25951,7 +26897,7 @@ "x-appwrite": { "method": "updateLineColumn", "group": "columns", - "weight": 404, + "weight": 410, "cookies": false, "type": "", "demo": "tablesdb\/update-line-column.md", @@ -26072,7 +27018,7 @@ "x-appwrite": { "method": "createPointColumn", "group": "columns", - "weight": 405, + "weight": 411, "cookies": false, "type": "", "demo": "tablesdb\/create-point-column.md", @@ -26185,7 +27131,7 @@ "x-appwrite": { "method": "updatePointColumn", "group": "columns", - "weight": 406, + "weight": 412, "cookies": false, "type": "", "demo": "tablesdb\/update-point-column.md", @@ -26306,7 +27252,7 @@ "x-appwrite": { "method": "createPolygonColumn", "group": "columns", - "weight": 407, + "weight": 413, "cookies": false, "type": "", "demo": "tablesdb\/create-polygon-column.md", @@ -26419,7 +27365,7 @@ "x-appwrite": { "method": "updatePolygonColumn", "group": "columns", - "weight": 408, + "weight": 414, "cookies": false, "type": "", "demo": "tablesdb\/update-polygon-column.md", @@ -26540,7 +27486,7 @@ "x-appwrite": { "method": "createRelationshipColumn", "group": "columns", - "weight": 409, + "weight": 415, "cookies": false, "type": "", "demo": "tablesdb\/create-relationship-column.md", @@ -26675,7 +27621,7 @@ "x-appwrite": { "method": "createStringColumn", "group": "columns", - "weight": 411, + "weight": 417, "cookies": false, "type": "", "demo": "tablesdb\/create-string-column.md", @@ -26796,7 +27742,7 @@ "x-appwrite": { "method": "updateStringColumn", "group": "columns", - "weight": 412, + "weight": 418, "cookies": false, "type": "", "demo": "tablesdb\/update-string-column.md", @@ -26916,7 +27862,7 @@ "x-appwrite": { "method": "createUrlColumn", "group": "columns", - "weight": 413, + "weight": 419, "cookies": false, "type": "", "demo": "tablesdb\/create-url-column.md", @@ -27026,7 +27972,7 @@ "x-appwrite": { "method": "updateUrlColumn", "group": "columns", - "weight": 414, + "weight": 420, "cookies": false, "type": "", "demo": "tablesdb\/update-url-column.md", @@ -27172,7 +28118,7 @@ "x-appwrite": { "method": "getColumn", "group": "columns", - "weight": 386, + "weight": 392, "cookies": false, "type": "", "demo": "tablesdb\/get-column.md", @@ -27247,7 +28193,7 @@ "x-appwrite": { "method": "deleteColumn", "group": "columns", - "weight": 387, + "weight": 393, "cookies": false, "type": "", "demo": "tablesdb\/delete-column.md", @@ -27331,7 +28277,7 @@ "x-appwrite": { "method": "updateRelationshipColumn", "group": "columns", - "weight": 410, + "weight": 416, "cookies": false, "type": "", "demo": "tablesdb\/update-relationship-column.md", @@ -27443,7 +28389,7 @@ "x-appwrite": { "method": "listIndexes", "group": "indexes", - "weight": 418, + "weight": 424, "cookies": false, "type": "", "demo": "tablesdb\/list-indexes.md", @@ -27529,7 +28475,7 @@ "x-appwrite": { "method": "createIndex", "group": "indexes", - "weight": 415, + "weight": 421, "cookies": false, "type": "", "demo": "tablesdb\/create-index.md", @@ -27662,7 +28608,7 @@ "x-appwrite": { "method": "getIndex", "group": "indexes", - "weight": 416, + "weight": 422, "cookies": false, "type": "", "demo": "tablesdb\/get-index.md", @@ -27737,7 +28683,7 @@ "x-appwrite": { "method": "deleteIndex", "group": "indexes", - "weight": 417, + "weight": 423, "cookies": false, "type": "", "demo": "tablesdb\/delete-index.md", @@ -27821,7 +28767,7 @@ "x-appwrite": { "method": "listRows", "group": "rows", - "weight": 427, + "weight": 433, "cookies": false, "type": "", "demo": "tablesdb\/list-rows.md", @@ -27885,6 +28831,16 @@ "default": [] }, "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" } ] }, @@ -27911,7 +28867,7 @@ "x-appwrite": { "method": "createRow", "group": "rows", - "weight": 419, + "weight": 425, "cookies": false, "type": "", "demo": "tablesdb\/create-row.md", @@ -27943,7 +28899,8 @@ "tableId", "rowId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -27971,7 +28928,8 @@ "parameters": [ "databaseId", "tableId", - "rows" + "rows", + "transactionId" ], "required": [ "databaseId", @@ -28054,6 +29012,11 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -28084,7 +29047,7 @@ "x-appwrite": { "method": "upsertRows", "group": "rows", - "weight": 424, + "weight": 430, "cookies": false, "type": "", "demo": "tablesdb\/upsert-rows.md", @@ -28113,7 +29076,8 @@ "parameters": [ "databaseId", "tableId", - "rows" + "rows", + "transactionId" ], "required": [ "databaseId", @@ -28176,6 +29140,11 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } }, "required": [ @@ -28209,7 +29178,7 @@ "x-appwrite": { "method": "updateRows", "group": "rows", - "weight": 422, + "weight": 428, "cookies": false, "type": "", "demo": "tablesdb\/update-rows.md", @@ -28277,6 +29246,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -28307,7 +29281,7 @@ "x-appwrite": { "method": "deleteRows", "group": "rows", - "weight": 426, + "weight": 432, "cookies": false, "type": "", "demo": "tablesdb\/delete-rows.md", @@ -28370,6 +29344,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -28402,7 +29381,7 @@ "x-appwrite": { "method": "getRow", "group": "rows", - "weight": 420, + "weight": 426, "cookies": false, "type": "", "demo": "tablesdb\/get-row.md", @@ -28476,6 +29455,16 @@ "default": [] }, "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" } ] }, @@ -28502,7 +29491,7 @@ "x-appwrite": { "method": "upsertRow", "group": "rows", - "weight": 423, + "weight": 429, "cookies": false, "type": "", "demo": "tablesdb\/upsert-row.md", @@ -28534,7 +29523,8 @@ "tableId", "rowId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -28614,6 +29604,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -28644,7 +29639,7 @@ "x-appwrite": { "method": "updateRow", "group": "rows", - "weight": 421, + "weight": 427, "cookies": false, "type": "", "demo": "tablesdb\/update-row.md", @@ -28725,6 +29720,11 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -28748,7 +29748,7 @@ "x-appwrite": { "method": "deleteRow", "group": "rows", - "weight": 425, + "weight": 431, "cookies": false, "type": "", "demo": "tablesdb\/delete-row.md", @@ -28810,7 +29810,23 @@ }, "in": "path" } - ] + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" + } + } + } + } + } + } } }, "\/tablesdb\/{databaseId}\/tables\/{tableId}\/rows\/{rowId}\/{column}\/decrement": { @@ -28837,7 +29853,7 @@ "x-appwrite": { "method": "decrementRowColumn", "group": "rows", - "weight": 430, + "weight": 436, "cookies": false, "type": "", "demo": "tablesdb\/decrement-row-column.md", @@ -28925,6 +29941,11 @@ "type": "number", "description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.", "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -28957,7 +29978,7 @@ "x-appwrite": { "method": "incrementRowColumn", "group": "rows", - "weight": 429, + "weight": 435, "cookies": false, "type": "", "demo": "tablesdb\/increment-row-column.md", @@ -29045,6 +30066,11 @@ "type": "number", "description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.", "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "x-example": "" } } } @@ -30132,7 +31158,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 507, + "weight": 519, "cookies": false, "type": "", "demo": "tokens\/list.md", @@ -30183,7 +31209,10 @@ "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: expire", "required": false, "schema": { - "type": "string", + "type": "array", + "items": { + "type": "string" + }, "default": [] }, "in": "query" @@ -30213,7 +31242,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 505, + "weight": 517, "cookies": false, "type": "", "demo": "tokens\/create-file-token.md", @@ -30303,7 +31332,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 506, + "weight": 518, "cookies": false, "type": "", "demo": "tokens\/get.md", @@ -30364,7 +31393,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 508, + "weight": 520, "cookies": false, "type": "", "demo": "tokens\/update.md", @@ -30435,7 +31464,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 509, + "weight": 521, "cookies": false, "type": "", "demo": "tokens\/delete.md", @@ -35141,6 +36170,34 @@ "targets": "" } }, + "transactionList": { + "description": "Transaction List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of transactions that matched your query.", + "x-example": 5, + "format": "int32" + }, + "transactions": { + "type": "array", + "description": "List of transactions.", + "items": { + "$ref": "#\/components\/schemas\/transaction" + }, + "x-example": "" + } + }, + "required": [ + "total", + "transactions" + ], + "example": { + "total": 5, + "transactions": "" + } + }, "specificationList": { "description": "Specifications List", "type": "object", @@ -41800,6 +42857,59 @@ "subscribe": "users" } }, + "transaction": { + "description": "Transaction", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Transaction ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Transaction creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Transaction update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "status": { + "type": "string", + "description": "Current status of the transaction. One of: pending, committing, committed, rolled_back, failed.", + "x-example": "pending" + }, + "operations": { + "type": "integer", + "description": "Number of operations in the transaction.", + "x-example": 5, + "format": "int32" + }, + "expiresAt": { + "type": "string", + "description": "Expiration time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "status", + "operations", + "expiresAt" + ], + "example": { + "$id": "259125845563242502", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "status": "pending", + "operations": 5, + "expiresAt": "2020-10-15T06:38:00.000+00:00" + } + }, "subscriber": { "description": "Subscriber", "type": "object", diff --git a/app/config/specs/swagger2-1.8.x-client.json b/app/config/specs/swagger2-1.8.x-client.json index 9b7a240b18..89fc5e7e5c 100644 --- a/app/config/specs/swagger2-1.8.x-client.json +++ b/app/config/specs/swagger2-1.8.x-client.json @@ -5052,6 +5052,419 @@ ] } }, + "\/databases\/transactions": { + "get": { + "summary": "List transactions", + "operationId": "databasesListTransactions", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "List transactions across all databases.", + "responses": { + "200": { + "description": "Transaction List", + "schema": { + "$ref": "#\/definitions\/transactionList" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "listTransactions", + "group": "transactions", + "weight": 376, + "cookies": false, + "type": "", + "demo": "databases\/list-transactions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-transactions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries).", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "post": { + "summary": "Create transaction", + "operationId": "databasesCreateTransaction", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create a new transaction.", + "responses": { + "201": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createTransaction", + "group": "transactions", + "weight": 372, + "cookies": false, + "type": "", + "demo": "databases\/create-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "ttl": { + "type": "integer", + "description": "Seconds before the transaction expires.", + "default": 300, + "x-example": 60 + } + } + } + } + ] + } + }, + "\/databases\/transactions\/{transactionId}": { + "get": { + "summary": "Get transaction", + "operationId": "databasesGetTransaction", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get a transaction by its unique ID.", + "responses": { + "200": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "getTransaction", + "group": "transactions", + "weight": 373, + "cookies": false, + "type": "", + "demo": "databases\/get-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update transaction", + "operationId": "databasesUpdateTransaction", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update a transaction, to either commit or roll back its operations.", + "responses": { + "200": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateTransaction", + "group": "transactions", + "weight": 374, + "cookies": false, + "type": "", + "demo": "databases\/update-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "commit": { + "type": "boolean", + "description": "Commit transaction?", + "default": false, + "x-example": false + }, + "rollback": { + "type": "boolean", + "description": "Rollback transaction?", + "default": false, + "x-example": false + } + } + } + } + ] + }, + "delete": { + "summary": "Delete transaction", + "operationId": "databasesDeleteTransaction", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "databases" + ], + "description": "Delete a transaction by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "deprecated": false, + "x-appwrite": { + "method": "deleteTransaction", + "group": "transactions", + "weight": 375, + "cookies": false, + "type": "", + "demo": "databases\/delete-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + } + }, + "\/databases\/transactions\/{transactionId}\/operations": { + "post": { + "summary": "Create operations", + "operationId": "databasesCreateOperations", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create multiple operations in a single transaction.", + "responses": { + "201": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createOperations", + "group": "transactions", + "weight": 377, + "cookies": false, + "type": "", + "demo": "databases\/create-operations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-operations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "operations": { + "type": "array", + "description": "Array of staged operations.", + "default": [], + "x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"\",\n\t \"collectionId\": \"\",\n\t \"documentId\": \"\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]", + "items": { + "type": "object" + } + } + } + } + } + ] + } + }, "\/databases\/{databaseId}\/collections\/{collectionId}\/documents": { "get": { "summary": "List documents", @@ -5133,6 +5546,14 @@ }, "default": [], "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "type": "string", + "x-example": "", + "in": "query" } ] }, @@ -5192,7 +5613,8 @@ "collectionId", "documentId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -5277,6 +5699,12 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -5373,6 +5801,14 @@ }, "default": [], "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "type": "string", + "x-example": "", + "in": "query" } ] }, @@ -5432,7 +5868,8 @@ "collectionId", "documentId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -5510,6 +5947,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } }, "required": [ @@ -5618,6 +6061,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -5697,6 +6146,21 @@ "type": "string", "x-example": "", "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" + } + } + } } ] } @@ -5806,6 +6270,12 @@ "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -5918,6 +6388,12 @@ "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -5949,7 +6425,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 456, + "weight": 468, "cookies": false, "type": "", "demo": "functions\/list-executions.md", @@ -6022,7 +6498,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 454, + "weight": 466, "cookies": false, "type": "", "demo": "functions\/create-execution.md", @@ -6139,7 +6615,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 455, + "weight": 467, "cookies": false, "type": "", "demo": "functions\/get-execution.md", @@ -7653,6 +8129,419 @@ ] } }, + "\/tablesdb\/transactions": { + "get": { + "summary": "List transactions", + "operationId": "tablesDBListTransactions", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "List transactions across all databases.", + "responses": { + "200": { + "description": "Transaction List", + "schema": { + "$ref": "#\/definitions\/transactionList" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "listTransactions", + "group": "transactions", + "weight": 441, + "cookies": false, + "type": "", + "demo": "tablesdb\/list-transactions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/list-transactions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries).", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "post": { + "summary": "Create transaction", + "operationId": "tablesDBCreateTransaction", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "Create a new transaction.", + "responses": { + "201": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createTransaction", + "group": "transactions", + "weight": 437, + "cookies": false, + "type": "", + "demo": "tablesdb\/create-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/create-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "ttl": { + "type": "integer", + "description": "Seconds before the transaction expires.", + "default": 300, + "x-example": 60 + } + } + } + } + ] + } + }, + "\/tablesdb\/transactions\/{transactionId}": { + "get": { + "summary": "Get transaction", + "operationId": "tablesDBGetTransaction", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "Get a transaction by its unique ID.", + "responses": { + "200": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "getTransaction", + "group": "transactions", + "weight": 438, + "cookies": false, + "type": "", + "demo": "tablesdb\/get-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/get-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update transaction", + "operationId": "tablesDBUpdateTransaction", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "Update a transaction, to either commit or roll back its operations.", + "responses": { + "200": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateTransaction", + "group": "transactions", + "weight": 439, + "cookies": false, + "type": "", + "demo": "tablesdb\/update-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/update-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "commit": { + "type": "boolean", + "description": "Commit transaction?", + "default": false, + "x-example": false + }, + "rollback": { + "type": "boolean", + "description": "Rollback transaction?", + "default": false, + "x-example": false + } + } + } + } + ] + }, + "delete": { + "summary": "Delete transaction", + "operationId": "tablesDBDeleteTransaction", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "tablesDB" + ], + "description": "Delete a transaction by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "deprecated": false, + "x-appwrite": { + "method": "deleteTransaction", + "group": "transactions", + "weight": 440, + "cookies": false, + "type": "", + "demo": "tablesdb\/delete-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/delete-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + } + }, + "\/tablesdb\/transactions\/{transactionId}\/operations": { + "post": { + "summary": "Create operations", + "operationId": "tablesDBCreateOperations", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "Create multiple operations in a single transaction.", + "responses": { + "201": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createOperations", + "group": "transactions", + "weight": 442, + "cookies": false, + "type": "", + "demo": "tablesdb\/create-operations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/create-operations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "operations": { + "type": "array", + "description": "Array of staged operations.", + "default": [], + "x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"\",\n\t \"tableId\": \"\",\n\t \"rowId\": \"\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]", + "items": { + "type": "object" + } + } + } + } + } + ] + } + }, "\/tablesdb\/{databaseId}\/tables\/{tableId}\/rows": { "get": { "summary": "List rows", @@ -7677,7 +8566,7 @@ "x-appwrite": { "method": "listRows", "group": "rows", - "weight": 427, + "weight": 433, "cookies": false, "type": "", "demo": "tablesdb\/list-rows.md", @@ -7733,6 +8622,14 @@ }, "default": [], "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "type": "string", + "x-example": "", + "in": "query" } ] }, @@ -7761,7 +8658,7 @@ "x-appwrite": { "method": "createRow", "group": "rows", - "weight": 419, + "weight": 425, "cookies": false, "type": "", "demo": "tablesdb\/create-row.md", @@ -7791,7 +8688,8 @@ "tableId", "rowId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -7872,6 +8770,12 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -7903,7 +8807,7 @@ "x-appwrite": { "method": "getRow", "group": "rows", - "weight": 420, + "weight": 426, "cookies": false, "type": "", "demo": "tablesdb\/get-row.md", @@ -7967,6 +8871,14 @@ }, "default": [], "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "type": "string", + "x-example": "", + "in": "query" } ] }, @@ -7995,7 +8907,7 @@ "x-appwrite": { "method": "upsertRow", "group": "rows", - "weight": 423, + "weight": 429, "cookies": false, "type": "", "demo": "tablesdb\/upsert-row.md", @@ -8025,7 +8937,8 @@ "tableId", "rowId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -8098,6 +9011,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -8129,7 +9048,7 @@ "x-appwrite": { "method": "updateRow", "group": "rows", - "weight": 421, + "weight": 427, "cookies": false, "type": "", "demo": "tablesdb\/update-row.md", @@ -8202,6 +9121,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -8228,7 +9153,7 @@ "x-appwrite": { "method": "deleteRow", "group": "rows", - "weight": 425, + "weight": 431, "cookies": false, "type": "", "demo": "tablesdb\/delete-row.md", @@ -8280,6 +9205,21 @@ "type": "string", "x-example": "", "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" + } + } + } } ] } @@ -8310,7 +9250,7 @@ "x-appwrite": { "method": "decrementRowColumn", "group": "rows", - "weight": 430, + "weight": 436, "cookies": false, "type": "", "demo": "tablesdb\/decrement-row-column.md", @@ -8388,6 +9328,12 @@ "description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -8421,7 +9367,7 @@ "x-appwrite": { "method": "incrementRowColumn", "group": "rows", - "weight": 429, + "weight": 435, "cookies": false, "type": "", "demo": "tablesdb\/increment-row-column.md", @@ -8499,6 +9445,12 @@ "description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -10035,6 +10987,35 @@ "localeCodes": "" } }, + "transactionList": { + "description": "Transaction List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of transactions that matched your query.", + "x-example": 5, + "format": "int32" + }, + "transactions": { + "type": "array", + "description": "List of transactions.", + "items": { + "type": "object", + "$ref": "#\/definitions\/transaction" + }, + "x-example": "" + } + }, + "required": [ + "total", + "transactions" + ], + "example": { + "total": 5, + "transactions": "" + } + }, "row": { "description": "Row", "type": "object", @@ -11955,6 +12936,59 @@ "recoveryCode": true } }, + "transaction": { + "description": "Transaction", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Transaction ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Transaction creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Transaction update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "status": { + "type": "string", + "description": "Current status of the transaction. One of: pending, committing, committed, rolled_back, failed.", + "x-example": "pending" + }, + "operations": { + "type": "integer", + "description": "Number of operations in the transaction.", + "x-example": 5, + "format": "int32" + }, + "expiresAt": { + "type": "string", + "description": "Expiration time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "status", + "operations", + "expiresAt" + ], + "example": { + "$id": "259125845563242502", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "status": "pending", + "operations": 5, + "expiresAt": "2020-10-15T06:38:00.000+00:00" + } + }, "subscriber": { "description": "Subscriber", "type": "object", diff --git a/app/config/specs/swagger2-1.8.x-console.json b/app/config/specs/swagger2-1.8.x-console.json index affee9509c..098f138b30 100644 --- a/app/config/specs/swagger2-1.8.x-console.json +++ b/app/config/specs/swagger2-1.8.x-console.json @@ -5156,7 +5156,7 @@ "x-appwrite": { "method": "getResource", "group": null, - "weight": 496, + "weight": 508, "cookies": false, "type": "", "demo": "console\/get-resource.md", @@ -5471,6 +5471,419 @@ ] } }, + "\/databases\/transactions": { + "get": { + "summary": "List transactions", + "operationId": "databasesListTransactions", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "List transactions across all databases.", + "responses": { + "200": { + "description": "Transaction List", + "schema": { + "$ref": "#\/definitions\/transactionList" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "listTransactions", + "group": "transactions", + "weight": 376, + "cookies": false, + "type": "", + "demo": "databases\/list-transactions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-transactions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries).", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "post": { + "summary": "Create transaction", + "operationId": "databasesCreateTransaction", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create a new transaction.", + "responses": { + "201": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createTransaction", + "group": "transactions", + "weight": 372, + "cookies": false, + "type": "", + "demo": "databases\/create-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "ttl": { + "type": "integer", + "description": "Seconds before the transaction expires.", + "default": 300, + "x-example": 60 + } + } + } + } + ] + } + }, + "\/databases\/transactions\/{transactionId}": { + "get": { + "summary": "Get transaction", + "operationId": "databasesGetTransaction", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get a transaction by its unique ID.", + "responses": { + "200": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "getTransaction", + "group": "transactions", + "weight": 373, + "cookies": false, + "type": "", + "demo": "databases\/get-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update transaction", + "operationId": "databasesUpdateTransaction", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update a transaction, to either commit or roll back its operations.", + "responses": { + "200": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateTransaction", + "group": "transactions", + "weight": 374, + "cookies": false, + "type": "", + "demo": "databases\/update-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "commit": { + "type": "boolean", + "description": "Commit transaction?", + "default": false, + "x-example": false + }, + "rollback": { + "type": "boolean", + "description": "Rollback transaction?", + "default": false, + "x-example": false + } + } + } + } + ] + }, + "delete": { + "summary": "Delete transaction", + "operationId": "databasesDeleteTransaction", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "databases" + ], + "description": "Delete a transaction by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "deprecated": false, + "x-appwrite": { + "method": "deleteTransaction", + "group": "transactions", + "weight": 375, + "cookies": false, + "type": "", + "demo": "databases\/delete-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + } + }, + "\/databases\/transactions\/{transactionId}\/operations": { + "post": { + "summary": "Create operations", + "operationId": "databasesCreateOperations", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create multiple operations in a single transaction.", + "responses": { + "201": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createOperations", + "group": "transactions", + "weight": 377, + "cookies": false, + "type": "", + "demo": "databases\/create-operations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-operations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "operations": { + "type": "array", + "description": "Array of staged operations.", + "default": [], + "x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"\",\n\t \"collectionId\": \"\",\n\t \"documentId\": \"\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]", + "items": { + "type": "object" + } + } + } + } + } + ] + } + }, "\/databases\/usage": { "get": { "summary": "Get databases usage stats", @@ -9629,6 +10042,14 @@ }, "default": [], "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "type": "string", + "x-example": "", + "in": "query" } ] }, @@ -9688,7 +10109,8 @@ "collectionId", "documentId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -9719,7 +10141,8 @@ "parameters": [ "databaseId", "collectionId", - "documents" + "documents", + "transactionId" ], "required": [ "databaseId", @@ -9803,6 +10226,12 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -9863,7 +10292,8 @@ "parameters": [ "databaseId", "collectionId", - "documents" + "documents", + "transactionId" ], "required": [ "databaseId", @@ -9925,6 +10355,12 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } }, "required": [ @@ -10024,6 +10460,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -10114,6 +10556,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -10210,6 +10658,14 @@ }, "default": [], "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "type": "string", + "x-example": "", + "in": "query" } ] }, @@ -10269,7 +10725,8 @@ "collectionId", "documentId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -10347,6 +10804,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } }, "required": [ @@ -10455,6 +10918,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -10534,6 +11003,21 @@ "type": "string", "x-example": "", "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" + } + } + } } ] } @@ -10733,6 +11217,12 @@ "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -10845,6 +11335,12 @@ "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -11078,7 +11574,7 @@ "tags": [ "databases" ], - "description": "Get index by ID.", + "description": "Get an index by its unique ID.", "responses": { "200": { "description": "Index", @@ -11628,7 +12124,7 @@ "x-appwrite": { "method": "list", "group": "functions", - "weight": 440, + "weight": 452, "cookies": false, "type": "", "demo": "functions\/list.md", @@ -11700,7 +12196,7 @@ "x-appwrite": { "method": "create", "group": "functions", - "weight": 437, + "weight": 449, "cookies": false, "type": "", "demo": "functions\/create.md", @@ -11951,7 +12447,7 @@ "x-appwrite": { "method": "listRuntimes", "group": "runtimes", - "weight": 442, + "weight": 454, "cookies": false, "type": "", "demo": "functions\/list-runtimes.md", @@ -12000,7 +12496,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "runtimes", - "weight": 443, + "weight": 455, "cookies": false, "type": "", "demo": "functions\/list-specifications.md", @@ -12050,7 +12546,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 466, + "weight": 478, "cookies": false, "type": "", "demo": "functions\/list-templates.md", @@ -12144,7 +12640,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 465, + "weight": 477, "cookies": false, "type": "", "demo": "functions\/get-template.md", @@ -12202,7 +12698,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 459, + "weight": 471, "cookies": false, "type": "", "demo": "functions\/list-usage.md", @@ -12272,7 +12768,7 @@ "x-appwrite": { "method": "get", "group": "functions", - "weight": 438, + "weight": 450, "cookies": false, "type": "", "demo": "functions\/get.md", @@ -12331,7 +12827,7 @@ "x-appwrite": { "method": "update", "group": "functions", - "weight": 439, + "weight": 451, "cookies": false, "type": "", "demo": "functions\/update.md", @@ -12578,7 +13074,7 @@ "x-appwrite": { "method": "delete", "group": "functions", - "weight": 441, + "weight": 453, "cookies": false, "type": "", "demo": "functions\/delete.md", @@ -12639,7 +13135,7 @@ "x-appwrite": { "method": "updateFunctionDeployment", "group": "functions", - "weight": 446, + "weight": 458, "cookies": false, "type": "", "demo": "functions\/update-function-deployment.md", @@ -12716,7 +13212,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 447, + "weight": 459, "cookies": false, "type": "", "demo": "functions\/list-deployments.md", @@ -12796,7 +13292,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 444, + "weight": 456, "cookies": false, "type": "upload", "demo": "functions\/create-deployment.md", @@ -12888,7 +13384,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 452, + "weight": 464, "cookies": false, "type": "", "demo": "functions\/create-duplicate-deployment.md", @@ -12973,7 +13469,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 449, + "weight": 461, "cookies": false, "type": "", "demo": "functions\/create-template-deployment.md", @@ -13079,7 +13575,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 450, + "weight": 462, "cookies": false, "type": "", "demo": "functions\/create-vcs-deployment.md", @@ -13175,7 +13671,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 445, + "weight": 457, "cookies": false, "type": "", "demo": "functions\/get-deployment.md", @@ -13237,7 +13733,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 448, + "weight": 460, "cookies": false, "type": "", "demo": "functions\/delete-deployment.md", @@ -13304,7 +13800,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 451, + "weight": 463, "cookies": false, "type": "location", "demo": "functions\/get-deployment-download.md", @@ -13389,7 +13885,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 453, + "weight": 465, "cookies": false, "type": "", "demo": "functions\/update-deployment-status.md", @@ -13456,7 +13952,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 456, + "weight": 468, "cookies": false, "type": "", "demo": "functions\/list-executions.md", @@ -13529,7 +14025,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 454, + "weight": 466, "cookies": false, "type": "", "demo": "functions\/create-execution.md", @@ -13646,7 +14142,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 455, + "weight": 467, "cookies": false, "type": "", "demo": "functions\/get-execution.md", @@ -13710,7 +14206,7 @@ "x-appwrite": { "method": "deleteExecution", "group": "executions", - "weight": 457, + "weight": 469, "cookies": false, "type": "", "demo": "functions\/delete-execution.md", @@ -13777,7 +14273,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 458, + "weight": 470, "cookies": false, "type": "", "demo": "functions\/get-usage.md", @@ -13855,7 +14351,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 462, + "weight": 474, "cookies": false, "type": "", "demo": "functions\/list-variables.md", @@ -13914,7 +14410,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 460, + "weight": 472, "cookies": false, "type": "", "demo": "functions\/create-variable.md", @@ -14004,7 +14500,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 461, + "weight": 473, "cookies": false, "type": "", "demo": "functions\/get-variable.md", @@ -14071,7 +14567,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 463, + "weight": 475, "cookies": false, "type": "", "demo": "functions\/update-variable.md", @@ -14163,7 +14659,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 464, + "weight": 476, "cookies": false, "type": "", "demo": "functions\/delete-variable.md", @@ -16527,7 +17023,7 @@ "type": "string", "description": "Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as :.", "default": "", - "x-example": "[ID1:ID2]" + "x-example": "" }, "icon": { "type": "string", @@ -16724,7 +17220,7 @@ "type": "string", "description": "Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as :.", "default": null, - "x-example": "[ID1:ID2]" + "x-example": "" }, "icon": { "type": "string", @@ -21459,7 +21955,7 @@ "type": "string", "description": "Composite ID in the format {databaseId:collectionId}, identifying a collection within a database.", "default": null, - "x-example": "[ID1:ID2]" + "x-example": "" }, "internalFile": { "type": "boolean", @@ -22694,7 +23190,7 @@ "x-appwrite": { "method": "list", "group": "projects", - "weight": 436, + "weight": 448, "cookies": false, "type": "", "demo": "projects\/list.md", @@ -24337,7 +24833,7 @@ "x-appwrite": { "method": "listDevKeys", "group": "devKeys", - "weight": 434, + "weight": 446, "cookies": false, "type": "", "demo": "projects\/list-dev-keys.md", @@ -24407,7 +24903,7 @@ "x-appwrite": { "method": "createDevKey", "group": "devKeys", - "weight": 431, + "weight": 443, "cookies": false, "type": "", "demo": "projects\/create-dev-key.md", @@ -24490,7 +24986,7 @@ "x-appwrite": { "method": "getDevKey", "group": "devKeys", - "weight": 433, + "weight": 445, "cookies": false, "type": "", "demo": "projects\/get-dev-key.md", @@ -24556,7 +25052,7 @@ "x-appwrite": { "method": "updateDevKey", "group": "devKeys", - "weight": 432, + "weight": 444, "cookies": false, "type": "", "demo": "projects\/update-dev-key.md", @@ -24642,7 +25138,7 @@ "x-appwrite": { "method": "deleteDevKey", "group": "devKeys", - "weight": 435, + "weight": 447, "cookies": false, "type": "", "demo": "projects\/delete-dev-key.md", @@ -28455,7 +28951,7 @@ "x-appwrite": { "method": "listRules", "group": null, - "weight": 502, + "weight": 514, "cookies": false, "type": "", "demo": "proxy\/list-rules.md", @@ -28528,7 +29024,7 @@ "x-appwrite": { "method": "createAPIRule", "group": null, - "weight": 497, + "weight": 509, "cookies": false, "type": "", "demo": "proxy\/create-api-rule.md", @@ -28598,7 +29094,7 @@ "x-appwrite": { "method": "createFunctionRule", "group": null, - "weight": 499, + "weight": 511, "cookies": false, "type": "", "demo": "proxy\/create-function-rule.md", @@ -28681,7 +29177,7 @@ "x-appwrite": { "method": "createRedirectRule", "group": null, - "weight": 500, + "weight": 512, "cookies": false, "type": "", "demo": "proxy\/create-redirect-rule.md", @@ -28801,7 +29297,7 @@ "x-appwrite": { "method": "createSiteRule", "group": null, - "weight": 498, + "weight": 510, "cookies": false, "type": "", "demo": "proxy\/create-site-rule.md", @@ -28882,7 +29378,7 @@ "x-appwrite": { "method": "getRule", "group": null, - "weight": 501, + "weight": 513, "cookies": false, "type": "", "demo": "proxy\/get-rule.md", @@ -28935,7 +29431,7 @@ "x-appwrite": { "method": "deleteRule", "group": null, - "weight": 503, + "weight": 515, "cookies": false, "type": "", "demo": "proxy\/delete-rule.md", @@ -28995,7 +29491,7 @@ "x-appwrite": { "method": "updateRuleVerification", "group": null, - "weight": 504, + "weight": 516, "cookies": false, "type": "", "demo": "proxy\/update-rule-verification.md", @@ -29053,7 +29549,7 @@ "x-appwrite": { "method": "list", "group": "sites", - "weight": 469, + "weight": 481, "cookies": false, "type": "", "demo": "sites\/list.md", @@ -29125,7 +29621,7 @@ "x-appwrite": { "method": "create", "group": "sites", - "weight": 467, + "weight": 479, "cookies": false, "type": "", "demo": "sites\/create.md", @@ -29392,7 +29888,7 @@ "x-appwrite": { "method": "listFrameworks", "group": "frameworks", - "weight": 472, + "weight": 484, "cookies": false, "type": "", "demo": "sites\/list-frameworks.md", @@ -29441,7 +29937,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 495, + "weight": 507, "cookies": false, "type": "", "demo": "sites\/list-specifications.md", @@ -29491,7 +29987,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 491, + "weight": 503, "cookies": false, "type": "", "demo": "sites\/list-templates.md", @@ -29585,7 +30081,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 492, + "weight": 504, "cookies": false, "type": "", "demo": "sites\/get-template.md", @@ -29643,7 +30139,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 493, + "weight": 505, "cookies": false, "type": "", "demo": "sites\/list-usage.md", @@ -29713,7 +30209,7 @@ "x-appwrite": { "method": "get", "group": "sites", - "weight": 468, + "weight": 480, "cookies": false, "type": "", "demo": "sites\/get.md", @@ -29772,7 +30268,7 @@ "x-appwrite": { "method": "update", "group": "sites", - "weight": 470, + "weight": 482, "cookies": false, "type": "", "demo": "sites\/update.md", @@ -30034,7 +30530,7 @@ "x-appwrite": { "method": "delete", "group": "sites", - "weight": 471, + "weight": 483, "cookies": false, "type": "", "demo": "sites\/delete.md", @@ -30095,7 +30591,7 @@ "x-appwrite": { "method": "updateSiteDeployment", "group": "sites", - "weight": 478, + "weight": 490, "cookies": false, "type": "", "demo": "sites\/update-site-deployment.md", @@ -30172,7 +30668,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 477, + "weight": 489, "cookies": false, "type": "", "demo": "sites\/list-deployments.md", @@ -30252,7 +30748,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 473, + "weight": 485, "cookies": false, "type": "upload", "demo": "sites\/create-deployment.md", @@ -30352,7 +30848,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 481, + "weight": 493, "cookies": false, "type": "", "demo": "sites\/create-duplicate-deployment.md", @@ -30431,7 +30927,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 474, + "weight": 486, "cookies": false, "type": "", "demo": "sites\/create-template-deployment.md", @@ -30537,7 +31033,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 475, + "weight": 487, "cookies": false, "type": "", "demo": "sites\/create-vcs-deployment.md", @@ -30634,7 +31130,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 476, + "weight": 488, "cookies": false, "type": "", "demo": "sites\/get-deployment.md", @@ -30696,7 +31192,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 479, + "weight": 491, "cookies": false, "type": "", "demo": "sites\/delete-deployment.md", @@ -30763,7 +31259,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 480, + "weight": 492, "cookies": false, "type": "location", "demo": "sites\/get-deployment-download.md", @@ -30848,7 +31344,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 482, + "weight": 494, "cookies": false, "type": "", "demo": "sites\/update-deployment-status.md", @@ -30915,7 +31411,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 484, + "weight": 496, "cookies": false, "type": "", "demo": "sites\/list-logs.md", @@ -30986,7 +31482,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 483, + "weight": 495, "cookies": false, "type": "", "demo": "sites\/get-log.md", @@ -31050,7 +31546,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 485, + "weight": 497, "cookies": false, "type": "", "demo": "sites\/delete-log.md", @@ -31117,7 +31613,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 494, + "weight": 506, "cookies": false, "type": "", "demo": "sites\/get-usage.md", @@ -31195,7 +31691,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 488, + "weight": 500, "cookies": false, "type": "", "demo": "sites\/list-variables.md", @@ -31254,7 +31750,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 486, + "weight": 498, "cookies": false, "type": "", "demo": "sites\/create-variable.md", @@ -31344,7 +31840,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 487, + "weight": 499, "cookies": false, "type": "", "demo": "sites\/get-variable.md", @@ -31411,7 +31907,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 489, + "weight": 501, "cookies": false, "type": "", "demo": "sites\/update-variable.md", @@ -31503,7 +31999,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 490, + "weight": 502, "cookies": false, "type": "", "demo": "sites\/delete-variable.md", @@ -32937,7 +33433,7 @@ "x-appwrite": { "method": "list", "group": "tablesdb", - "weight": 376, + "weight": 382, "cookies": false, "type": "", "demo": "tablesdb\/list.md", @@ -33009,7 +33505,7 @@ "x-appwrite": { "method": "create", "group": "tablesdb", - "weight": 372, + "weight": 378, "cookies": false, "type": "", "demo": "tablesdb\/create.md", @@ -33067,6 +33563,419 @@ ] } }, + "\/tablesdb\/transactions": { + "get": { + "summary": "List transactions", + "operationId": "tablesDBListTransactions", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "List transactions across all databases.", + "responses": { + "200": { + "description": "Transaction List", + "schema": { + "$ref": "#\/definitions\/transactionList" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "listTransactions", + "group": "transactions", + "weight": 441, + "cookies": false, + "type": "", + "demo": "tablesdb\/list-transactions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/list-transactions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries).", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "post": { + "summary": "Create transaction", + "operationId": "tablesDBCreateTransaction", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "Create a new transaction.", + "responses": { + "201": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createTransaction", + "group": "transactions", + "weight": 437, + "cookies": false, + "type": "", + "demo": "tablesdb\/create-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/create-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "ttl": { + "type": "integer", + "description": "Seconds before the transaction expires.", + "default": 300, + "x-example": 60 + } + } + } + } + ] + } + }, + "\/tablesdb\/transactions\/{transactionId}": { + "get": { + "summary": "Get transaction", + "operationId": "tablesDBGetTransaction", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "Get a transaction by its unique ID.", + "responses": { + "200": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "getTransaction", + "group": "transactions", + "weight": 438, + "cookies": false, + "type": "", + "demo": "tablesdb\/get-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/get-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update transaction", + "operationId": "tablesDBUpdateTransaction", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "Update a transaction, to either commit or roll back its operations.", + "responses": { + "200": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateTransaction", + "group": "transactions", + "weight": 439, + "cookies": false, + "type": "", + "demo": "tablesdb\/update-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/update-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "commit": { + "type": "boolean", + "description": "Commit transaction?", + "default": false, + "x-example": false + }, + "rollback": { + "type": "boolean", + "description": "Rollback transaction?", + "default": false, + "x-example": false + } + } + } + } + ] + }, + "delete": { + "summary": "Delete transaction", + "operationId": "tablesDBDeleteTransaction", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "tablesDB" + ], + "description": "Delete a transaction by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "deprecated": false, + "x-appwrite": { + "method": "deleteTransaction", + "group": "transactions", + "weight": 440, + "cookies": false, + "type": "", + "demo": "tablesdb\/delete-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/delete-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + } + }, + "\/tablesdb\/transactions\/{transactionId}\/operations": { + "post": { + "summary": "Create operations", + "operationId": "tablesDBCreateOperations", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "Create multiple operations in a single transaction.", + "responses": { + "201": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createOperations", + "group": "transactions", + "weight": 442, + "cookies": false, + "type": "", + "demo": "tablesdb\/create-operations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/create-operations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "operations": { + "type": "array", + "description": "Array of staged operations.", + "default": [], + "x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"\",\n\t \"tableId\": \"\",\n\t \"rowId\": \"\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]", + "items": { + "type": "object" + } + } + } + } + } + ] + } + }, "\/tablesdb\/usage": { "get": { "summary": "Get TablesDB usage stats", @@ -33091,7 +34000,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 378, + "weight": 384, "cookies": false, "type": "", "demo": "tablesdb\/list-usage.md", @@ -33186,7 +34095,7 @@ "x-appwrite": { "method": "get", "group": "tablesdb", - "weight": 373, + "weight": 379, "cookies": false, "type": "", "demo": "tablesdb\/get.md", @@ -33245,7 +34154,7 @@ "x-appwrite": { "method": "update", "group": "tablesdb", - "weight": 374, + "weight": 380, "cookies": false, "type": "", "demo": "tablesdb\/update.md", @@ -33323,7 +34232,7 @@ "x-appwrite": { "method": "delete", "group": "tablesdb", - "weight": 375, + "weight": 381, "cookies": false, "type": "", "demo": "tablesdb\/delete.md", @@ -33382,7 +34291,7 @@ "x-appwrite": { "method": "listTables", "group": "tables", - "weight": 383, + "weight": 389, "cookies": false, "type": "", "demo": "tablesdb\/list-tables.md", @@ -33465,7 +34374,7 @@ "x-appwrite": { "method": "createTable", "group": "tables", - "weight": 379, + "weight": 385, "cookies": false, "type": "", "demo": "tablesdb\/create-table.md", @@ -33573,7 +34482,7 @@ "x-appwrite": { "method": "getTable", "group": "tables", - "weight": 380, + "weight": 386, "cookies": false, "type": "", "demo": "tablesdb\/get-table.md", @@ -33643,7 +34552,7 @@ "x-appwrite": { "method": "updateTable", "group": "tables", - "weight": 381, + "weight": 387, "cookies": false, "type": "", "demo": "tablesdb\/update-table.md", @@ -33747,7 +34656,7 @@ "x-appwrite": { "method": "deleteTable", "group": "tables", - "weight": 382, + "weight": 388, "cookies": false, "type": "", "demo": "tablesdb\/delete-table.md", @@ -33817,7 +34726,7 @@ "x-appwrite": { "method": "listColumns", "group": "columns", - "weight": 388, + "weight": 394, "cookies": false, "type": "", "demo": "tablesdb\/list-columns.md", @@ -33901,7 +34810,7 @@ "x-appwrite": { "method": "createBooleanColumn", "group": "columns", - "weight": 389, + "weight": 395, "cookies": false, "type": "", "demo": "tablesdb\/create-boolean-column.md", @@ -34010,7 +34919,7 @@ "x-appwrite": { "method": "updateBooleanColumn", "group": "columns", - "weight": 390, + "weight": 396, "cookies": false, "type": "", "demo": "tablesdb\/update-boolean-column.md", @@ -34121,7 +35030,7 @@ "x-appwrite": { "method": "createDatetimeColumn", "group": "columns", - "weight": 391, + "weight": 397, "cookies": false, "type": "", "demo": "tablesdb\/create-datetime-column.md", @@ -34230,7 +35139,7 @@ "x-appwrite": { "method": "updateDatetimeColumn", "group": "columns", - "weight": 392, + "weight": 398, "cookies": false, "type": "", "demo": "tablesdb\/update-datetime-column.md", @@ -34341,7 +35250,7 @@ "x-appwrite": { "method": "createEmailColumn", "group": "columns", - "weight": 393, + "weight": 399, "cookies": false, "type": "", "demo": "tablesdb\/create-email-column.md", @@ -34450,7 +35359,7 @@ "x-appwrite": { "method": "updateEmailColumn", "group": "columns", - "weight": 394, + "weight": 400, "cookies": false, "type": "", "demo": "tablesdb\/update-email-column.md", @@ -34561,7 +35470,7 @@ "x-appwrite": { "method": "createEnumColumn", "group": "columns", - "weight": 395, + "weight": 401, "cookies": false, "type": "", "demo": "tablesdb\/create-enum-column.md", @@ -34680,7 +35589,7 @@ "x-appwrite": { "method": "updateEnumColumn", "group": "columns", - "weight": 396, + "weight": 402, "cookies": false, "type": "", "demo": "tablesdb\/update-enum-column.md", @@ -34801,7 +35710,7 @@ "x-appwrite": { "method": "createFloatColumn", "group": "columns", - "weight": 397, + "weight": 403, "cookies": false, "type": "", "demo": "tablesdb\/create-float-column.md", @@ -34922,7 +35831,7 @@ "x-appwrite": { "method": "updateFloatColumn", "group": "columns", - "weight": 398, + "weight": 404, "cookies": false, "type": "", "demo": "tablesdb\/update-float-column.md", @@ -35045,7 +35954,7 @@ "x-appwrite": { "method": "createIntegerColumn", "group": "columns", - "weight": 399, + "weight": 405, "cookies": false, "type": "", "demo": "tablesdb\/create-integer-column.md", @@ -35166,7 +36075,7 @@ "x-appwrite": { "method": "updateIntegerColumn", "group": "columns", - "weight": 400, + "weight": 406, "cookies": false, "type": "", "demo": "tablesdb\/update-integer-column.md", @@ -35289,7 +36198,7 @@ "x-appwrite": { "method": "createIpColumn", "group": "columns", - "weight": 401, + "weight": 407, "cookies": false, "type": "", "demo": "tablesdb\/create-ip-column.md", @@ -35398,7 +36307,7 @@ "x-appwrite": { "method": "updateIpColumn", "group": "columns", - "weight": 402, + "weight": 408, "cookies": false, "type": "", "demo": "tablesdb\/update-ip-column.md", @@ -35509,7 +36418,7 @@ "x-appwrite": { "method": "createLineColumn", "group": "columns", - "weight": 403, + "weight": 409, "cookies": false, "type": "", "demo": "tablesdb\/create-line-column.md", @@ -35613,7 +36522,7 @@ "x-appwrite": { "method": "updateLineColumn", "group": "columns", - "weight": 404, + "weight": 410, "cookies": false, "type": "", "demo": "tablesdb\/update-line-column.md", @@ -35723,7 +36632,7 @@ "x-appwrite": { "method": "createPointColumn", "group": "columns", - "weight": 405, + "weight": 411, "cookies": false, "type": "", "demo": "tablesdb\/create-point-column.md", @@ -35827,7 +36736,7 @@ "x-appwrite": { "method": "updatePointColumn", "group": "columns", - "weight": 406, + "weight": 412, "cookies": false, "type": "", "demo": "tablesdb\/update-point-column.md", @@ -35937,7 +36846,7 @@ "x-appwrite": { "method": "createPolygonColumn", "group": "columns", - "weight": 407, + "weight": 413, "cookies": false, "type": "", "demo": "tablesdb\/create-polygon-column.md", @@ -36041,7 +36950,7 @@ "x-appwrite": { "method": "updatePolygonColumn", "group": "columns", - "weight": 408, + "weight": 414, "cookies": false, "type": "", "demo": "tablesdb\/update-polygon-column.md", @@ -36151,7 +37060,7 @@ "x-appwrite": { "method": "createRelationshipColumn", "group": "columns", - "weight": 409, + "weight": 415, "cookies": false, "type": "", "demo": "tablesdb\/create-relationship-column.md", @@ -36287,7 +37196,7 @@ "x-appwrite": { "method": "createStringColumn", "group": "columns", - "weight": 411, + "weight": 417, "cookies": false, "type": "", "demo": "tablesdb\/create-string-column.md", @@ -36409,7 +37318,7 @@ "x-appwrite": { "method": "updateStringColumn", "group": "columns", - "weight": 412, + "weight": 418, "cookies": false, "type": "", "demo": "tablesdb\/update-string-column.md", @@ -36526,7 +37435,7 @@ "x-appwrite": { "method": "createUrlColumn", "group": "columns", - "weight": 413, + "weight": 419, "cookies": false, "type": "", "demo": "tablesdb\/create-url-column.md", @@ -36635,7 +37544,7 @@ "x-appwrite": { "method": "updateUrlColumn", "group": "columns", - "weight": 414, + "weight": 420, "cookies": false, "type": "", "demo": "tablesdb\/update-url-column.md", @@ -36775,7 +37684,7 @@ "x-appwrite": { "method": "getColumn", "group": "columns", - "weight": 386, + "weight": 392, "cookies": false, "type": "", "demo": "tablesdb\/get-column.md", @@ -36847,7 +37756,7 @@ "x-appwrite": { "method": "deleteColumn", "group": "columns", - "weight": 387, + "weight": 393, "cookies": false, "type": "", "demo": "tablesdb\/delete-column.md", @@ -36926,7 +37835,7 @@ "x-appwrite": { "method": "updateRelationshipColumn", "group": "columns", - "weight": 410, + "weight": 416, "cookies": false, "type": "", "demo": "tablesdb\/update-relationship-column.md", @@ -37031,7 +37940,7 @@ "x-appwrite": { "method": "listIndexes", "group": "indexes", - "weight": 418, + "weight": 424, "cookies": false, "type": "", "demo": "tablesdb\/list-indexes.md", @@ -37113,7 +38022,7 @@ "x-appwrite": { "method": "createIndex", "group": "indexes", - "weight": 415, + "weight": 421, "cookies": false, "type": "", "demo": "tablesdb\/create-index.md", @@ -37244,7 +38153,7 @@ "x-appwrite": { "method": "getIndex", "group": "indexes", - "weight": 416, + "weight": 422, "cookies": false, "type": "", "demo": "tablesdb\/get-index.md", @@ -37316,7 +38225,7 @@ "x-appwrite": { "method": "deleteIndex", "group": "indexes", - "weight": 417, + "weight": 423, "cookies": false, "type": "", "demo": "tablesdb\/delete-index.md", @@ -37393,7 +38302,7 @@ "x-appwrite": { "method": "listTableLogs", "group": "tables", - "weight": 384, + "weight": 390, "cookies": false, "type": "", "demo": "tablesdb\/list-table-logs.md", @@ -37474,7 +38383,7 @@ "x-appwrite": { "method": "listRows", "group": "rows", - "weight": 427, + "weight": 433, "cookies": false, "type": "", "demo": "tablesdb\/list-rows.md", @@ -37530,6 +38439,14 @@ }, "default": [], "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "type": "string", + "x-example": "", + "in": "query" } ] }, @@ -37558,7 +38475,7 @@ "x-appwrite": { "method": "createRow", "group": "rows", - "weight": 419, + "weight": 425, "cookies": false, "type": "", "demo": "tablesdb\/create-row.md", @@ -37588,7 +38505,8 @@ "tableId", "rowId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -37615,7 +38533,8 @@ "parameters": [ "databaseId", "tableId", - "rows" + "rows", + "transactionId" ], "required": [ "databaseId", @@ -37695,6 +38614,12 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -37726,7 +38651,7 @@ "x-appwrite": { "method": "upsertRows", "group": "rows", - "weight": 424, + "weight": 430, "cookies": false, "type": "", "demo": "tablesdb\/upsert-rows.md", @@ -37754,7 +38679,8 @@ "parameters": [ "databaseId", "tableId", - "rows" + "rows", + "transactionId" ], "required": [ "databaseId", @@ -37812,6 +38738,12 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } }, "required": [ @@ -37846,7 +38778,7 @@ "x-appwrite": { "method": "updateRows", "group": "rows", - "weight": 422, + "weight": 428, "cookies": false, "type": "", "demo": "tablesdb\/update-rows.md", @@ -37910,6 +38842,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -37941,7 +38879,7 @@ "x-appwrite": { "method": "deleteRows", "group": "rows", - "weight": 426, + "weight": 432, "cookies": false, "type": "", "demo": "tablesdb\/delete-rows.md", @@ -37999,6 +38937,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -38030,7 +38974,7 @@ "x-appwrite": { "method": "getRow", "group": "rows", - "weight": 420, + "weight": 426, "cookies": false, "type": "", "demo": "tablesdb\/get-row.md", @@ -38094,6 +39038,14 @@ }, "default": [], "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "type": "string", + "x-example": "", + "in": "query" } ] }, @@ -38122,7 +39074,7 @@ "x-appwrite": { "method": "upsertRow", "group": "rows", - "weight": 423, + "weight": 429, "cookies": false, "type": "", "demo": "tablesdb\/upsert-row.md", @@ -38152,7 +39104,8 @@ "tableId", "rowId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -38225,6 +39178,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -38256,7 +39215,7 @@ "x-appwrite": { "method": "updateRow", "group": "rows", - "weight": 421, + "weight": 427, "cookies": false, "type": "", "demo": "tablesdb\/update-row.md", @@ -38329,6 +39288,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -38355,7 +39320,7 @@ "x-appwrite": { "method": "deleteRow", "group": "rows", - "weight": 425, + "weight": 431, "cookies": false, "type": "", "demo": "tablesdb\/delete-row.md", @@ -38407,6 +39372,21 @@ "type": "string", "x-example": "", "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" + } + } + } } ] } @@ -38435,7 +39415,7 @@ "x-appwrite": { "method": "listRowLogs", "group": "logs", - "weight": 428, + "weight": 434, "cookies": false, "type": "", "demo": "tablesdb\/list-row-logs.md", @@ -38526,7 +39506,7 @@ "x-appwrite": { "method": "decrementRowColumn", "group": "rows", - "weight": 430, + "weight": 436, "cookies": false, "type": "", "demo": "tablesdb\/decrement-row-column.md", @@ -38604,6 +39584,12 @@ "description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -38637,7 +39623,7 @@ "x-appwrite": { "method": "incrementRowColumn", "group": "rows", - "weight": 429, + "weight": 435, "cookies": false, "type": "", "demo": "tablesdb\/increment-row-column.md", @@ -38715,6 +39701,12 @@ "description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -38746,7 +39738,7 @@ "x-appwrite": { "method": "getTableUsage", "group": null, - "weight": 385, + "weight": 391, "cookies": false, "type": "", "demo": "tablesdb\/get-table-usage.md", @@ -38835,7 +39827,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 377, + "weight": 383, "cookies": false, "type": "", "demo": "tablesdb\/get-usage.md", @@ -40020,7 +41012,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 507, + "weight": 519, "cookies": false, "type": "", "demo": "tokens\/list.md", @@ -40100,7 +41092,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 505, + "weight": 517, "cookies": false, "type": "", "demo": "tokens\/create-file-token.md", @@ -40184,7 +41176,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 506, + "weight": 518, "cookies": false, "type": "", "demo": "tokens\/get.md", @@ -40244,7 +41236,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 508, + "weight": 520, "cookies": false, "type": "", "demo": "tokens\/update.md", @@ -40315,7 +41307,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 509, + "weight": 521, "cookies": false, "type": "", "demo": "tokens\/delete.md", @@ -46144,6 +47136,35 @@ "targets": "" } }, + "transactionList": { + "description": "Transaction List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of transactions that matched your query.", + "x-example": 5, + "format": "int32" + }, + "transactions": { + "type": "array", + "description": "List of transactions.", + "items": { + "type": "object", + "$ref": "#\/definitions\/transaction" + }, + "x-example": "" + } + }, + "required": [ + "total", + "transactions" + ], + "example": { + "total": 5, + "transactions": "" + } + }, "migrationList": { "description": "Migrations List", "type": "object", @@ -56939,6 +57960,59 @@ "subscribe": "users" } }, + "transaction": { + "description": "Transaction", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Transaction ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Transaction creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Transaction update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "status": { + "type": "string", + "description": "Current status of the transaction. One of: pending, committing, committed, rolled_back, failed.", + "x-example": "pending" + }, + "operations": { + "type": "integer", + "description": "Number of operations in the transaction.", + "x-example": 5, + "format": "int32" + }, + "expiresAt": { + "type": "string", + "description": "Expiration time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "status", + "operations", + "expiresAt" + ], + "example": { + "$id": "259125845563242502", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "status": "pending", + "operations": 5, + "expiresAt": "2020-10-15T06:38:00.000+00:00" + } + }, "subscriber": { "description": "Subscriber", "type": "object", diff --git a/app/config/specs/swagger2-1.8.x-server.json b/app/config/specs/swagger2-1.8.x-server.json index 05ad0562a5..9c8ef73243 100644 --- a/app/config/specs/swagger2-1.8.x-server.json +++ b/app/config/specs/swagger2-1.8.x-server.json @@ -5001,6 +5001,431 @@ ] } }, + "\/databases\/transactions": { + "get": { + "summary": "List transactions", + "operationId": "databasesListTransactions", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "List transactions across all databases.", + "responses": { + "200": { + "description": "Transaction List", + "schema": { + "$ref": "#\/definitions\/transactionList" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "listTransactions", + "group": "transactions", + "weight": 376, + "cookies": false, + "type": "", + "demo": "databases\/list-transactions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-transactions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries).", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "post": { + "summary": "Create transaction", + "operationId": "databasesCreateTransaction", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create a new transaction.", + "responses": { + "201": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createTransaction", + "group": "transactions", + "weight": 372, + "cookies": false, + "type": "", + "demo": "databases\/create-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "ttl": { + "type": "integer", + "description": "Seconds before the transaction expires.", + "default": 300, + "x-example": 60 + } + } + } + } + ] + } + }, + "\/databases\/transactions\/{transactionId}": { + "get": { + "summary": "Get transaction", + "operationId": "databasesGetTransaction", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get a transaction by its unique ID.", + "responses": { + "200": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "getTransaction", + "group": "transactions", + "weight": 373, + "cookies": false, + "type": "", + "demo": "databases\/get-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update transaction", + "operationId": "databasesUpdateTransaction", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update a transaction, to either commit or roll back its operations.", + "responses": { + "200": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateTransaction", + "group": "transactions", + "weight": 374, + "cookies": false, + "type": "", + "demo": "databases\/update-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "commit": { + "type": "boolean", + "description": "Commit transaction?", + "default": false, + "x-example": false + }, + "rollback": { + "type": "boolean", + "description": "Rollback transaction?", + "default": false, + "x-example": false + } + } + } + } + ] + }, + "delete": { + "summary": "Delete transaction", + "operationId": "databasesDeleteTransaction", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "databases" + ], + "description": "Delete a transaction by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "deprecated": false, + "x-appwrite": { + "method": "deleteTransaction", + "group": "transactions", + "weight": 375, + "cookies": false, + "type": "", + "demo": "databases\/delete-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + } + }, + "\/databases\/transactions\/{transactionId}\/operations": { + "post": { + "summary": "Create operations", + "operationId": "databasesCreateOperations", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create multiple operations in a single transaction.", + "responses": { + "201": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createOperations", + "group": "transactions", + "weight": 377, + "cookies": false, + "type": "", + "demo": "databases\/create-operations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-operations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "operations": { + "type": "array", + "description": "Array of staged operations.", + "default": [], + "x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"\",\n\t \"collectionId\": \"\",\n\t \"documentId\": \"\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]", + "items": { + "type": "object" + } + } + } + } + } + ] + } + }, "\/databases\/{databaseId}": { "get": { "summary": "Get database", @@ -9101,6 +9526,14 @@ }, "default": [], "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "type": "string", + "x-example": "", + "in": "query" } ] }, @@ -9161,7 +9594,8 @@ "collectionId", "documentId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -9193,7 +9627,8 @@ "parameters": [ "databaseId", "collectionId", - "documents" + "documents", + "transactionId" ], "required": [ "databaseId", @@ -9279,6 +9714,12 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -9340,7 +9781,8 @@ "parameters": [ "databaseId", "collectionId", - "documents" + "documents", + "transactionId" ], "required": [ "databaseId", @@ -9403,6 +9845,12 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } }, "required": [ @@ -9503,6 +9951,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -9594,6 +10048,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -9692,6 +10152,14 @@ }, "default": [], "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "type": "string", + "x-example": "", + "in": "query" } ] }, @@ -9752,7 +10220,8 @@ "collectionId", "documentId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -9832,6 +10301,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } }, "required": [ @@ -9942,6 +10417,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -10023,6 +10504,21 @@ "type": "string", "x-example": "", "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" + } + } + } } ] } @@ -10134,6 +10630,12 @@ "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -10248,6 +10750,12 @@ "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -10483,7 +10991,7 @@ "tags": [ "databases" ], - "description": "Get index by ID.", + "description": "Get an index by its unique ID.", "responses": { "200": { "description": "Index", @@ -10649,7 +11157,7 @@ "x-appwrite": { "method": "list", "group": "functions", - "weight": 440, + "weight": 452, "cookies": false, "type": "", "demo": "functions\/list.md", @@ -10722,7 +11230,7 @@ "x-appwrite": { "method": "create", "group": "functions", - "weight": 437, + "weight": 449, "cookies": false, "type": "", "demo": "functions\/create.md", @@ -10974,7 +11482,7 @@ "x-appwrite": { "method": "listRuntimes", "group": "runtimes", - "weight": 442, + "weight": 454, "cookies": false, "type": "", "demo": "functions\/list-runtimes.md", @@ -11024,7 +11532,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "runtimes", - "weight": 443, + "weight": 455, "cookies": false, "type": "", "demo": "functions\/list-specifications.md", @@ -11075,7 +11583,7 @@ "x-appwrite": { "method": "get", "group": "functions", - "weight": 438, + "weight": 450, "cookies": false, "type": "", "demo": "functions\/get.md", @@ -11135,7 +11643,7 @@ "x-appwrite": { "method": "update", "group": "functions", - "weight": 439, + "weight": 451, "cookies": false, "type": "", "demo": "functions\/update.md", @@ -11383,7 +11891,7 @@ "x-appwrite": { "method": "delete", "group": "functions", - "weight": 441, + "weight": 453, "cookies": false, "type": "", "demo": "functions\/delete.md", @@ -11445,7 +11953,7 @@ "x-appwrite": { "method": "updateFunctionDeployment", "group": "functions", - "weight": 446, + "weight": 458, "cookies": false, "type": "", "demo": "functions\/update-function-deployment.md", @@ -11523,7 +12031,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 447, + "weight": 459, "cookies": false, "type": "", "demo": "functions\/list-deployments.md", @@ -11604,7 +12112,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 444, + "weight": 456, "cookies": false, "type": "upload", "demo": "functions\/create-deployment.md", @@ -11697,7 +12205,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 452, + "weight": 464, "cookies": false, "type": "", "demo": "functions\/create-duplicate-deployment.md", @@ -11783,7 +12291,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 449, + "weight": 461, "cookies": false, "type": "", "demo": "functions\/create-template-deployment.md", @@ -11890,7 +12398,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 450, + "weight": 462, "cookies": false, "type": "", "demo": "functions\/create-vcs-deployment.md", @@ -11987,7 +12495,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 445, + "weight": 457, "cookies": false, "type": "", "demo": "functions\/get-deployment.md", @@ -12050,7 +12558,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 448, + "weight": 460, "cookies": false, "type": "", "demo": "functions\/delete-deployment.md", @@ -12118,7 +12626,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 451, + "weight": 463, "cookies": false, "type": "location", "demo": "functions\/get-deployment-download.md", @@ -12204,7 +12712,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 453, + "weight": 465, "cookies": false, "type": "", "demo": "functions\/update-deployment-status.md", @@ -12272,7 +12780,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 456, + "weight": 468, "cookies": false, "type": "", "demo": "functions\/list-executions.md", @@ -12347,7 +12855,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 454, + "weight": 466, "cookies": false, "type": "", "demo": "functions\/create-execution.md", @@ -12466,7 +12974,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 455, + "weight": 467, "cookies": false, "type": "", "demo": "functions\/get-execution.md", @@ -12532,7 +13040,7 @@ "x-appwrite": { "method": "deleteExecution", "group": "executions", - "weight": 457, + "weight": 469, "cookies": false, "type": "", "demo": "functions\/delete-execution.md", @@ -12600,7 +13108,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 462, + "weight": 474, "cookies": false, "type": "", "demo": "functions\/list-variables.md", @@ -12660,7 +13168,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 460, + "weight": 472, "cookies": false, "type": "", "demo": "functions\/create-variable.md", @@ -12751,7 +13259,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 461, + "weight": 473, "cookies": false, "type": "", "demo": "functions\/get-variable.md", @@ -12819,7 +13327,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 463, + "weight": 475, "cookies": false, "type": "", "demo": "functions\/update-variable.md", @@ -12912,7 +13420,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 464, + "weight": 476, "cookies": false, "type": "", "demo": "functions\/delete-variable.md", @@ -15323,7 +15831,7 @@ "type": "string", "description": "Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as :.", "default": "", - "x-example": "[ID1:ID2]" + "x-example": "" }, "icon": { "type": "string", @@ -15521,7 +16029,7 @@ "type": "string", "description": "Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as :.", "default": null, - "x-example": "[ID1:ID2]" + "x-example": "" }, "icon": { "type": "string", @@ -20017,7 +20525,7 @@ "x-appwrite": { "method": "list", "group": "sites", - "weight": 469, + "weight": 481, "cookies": false, "type": "", "demo": "sites\/list.md", @@ -20090,7 +20598,7 @@ "x-appwrite": { "method": "create", "group": "sites", - "weight": 467, + "weight": 479, "cookies": false, "type": "", "demo": "sites\/create.md", @@ -20358,7 +20866,7 @@ "x-appwrite": { "method": "listFrameworks", "group": "frameworks", - "weight": 472, + "weight": 484, "cookies": false, "type": "", "demo": "sites\/list-frameworks.md", @@ -20408,7 +20916,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 495, + "weight": 507, "cookies": false, "type": "", "demo": "sites\/list-specifications.md", @@ -20459,7 +20967,7 @@ "x-appwrite": { "method": "get", "group": "sites", - "weight": 468, + "weight": 480, "cookies": false, "type": "", "demo": "sites\/get.md", @@ -20519,7 +21027,7 @@ "x-appwrite": { "method": "update", "group": "sites", - "weight": 470, + "weight": 482, "cookies": false, "type": "", "demo": "sites\/update.md", @@ -20782,7 +21290,7 @@ "x-appwrite": { "method": "delete", "group": "sites", - "weight": 471, + "weight": 483, "cookies": false, "type": "", "demo": "sites\/delete.md", @@ -20844,7 +21352,7 @@ "x-appwrite": { "method": "updateSiteDeployment", "group": "sites", - "weight": 478, + "weight": 490, "cookies": false, "type": "", "demo": "sites\/update-site-deployment.md", @@ -20922,7 +21430,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 477, + "weight": 489, "cookies": false, "type": "", "demo": "sites\/list-deployments.md", @@ -21003,7 +21511,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 473, + "weight": 485, "cookies": false, "type": "upload", "demo": "sites\/create-deployment.md", @@ -21104,7 +21612,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 481, + "weight": 493, "cookies": false, "type": "", "demo": "sites\/create-duplicate-deployment.md", @@ -21184,7 +21692,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 474, + "weight": 486, "cookies": false, "type": "", "demo": "sites\/create-template-deployment.md", @@ -21291,7 +21799,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 475, + "weight": 487, "cookies": false, "type": "", "demo": "sites\/create-vcs-deployment.md", @@ -21389,7 +21897,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 476, + "weight": 488, "cookies": false, "type": "", "demo": "sites\/get-deployment.md", @@ -21452,7 +21960,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 479, + "weight": 491, "cookies": false, "type": "", "demo": "sites\/delete-deployment.md", @@ -21520,7 +22028,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 480, + "weight": 492, "cookies": false, "type": "location", "demo": "sites\/get-deployment-download.md", @@ -21606,7 +22114,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 482, + "weight": 494, "cookies": false, "type": "", "demo": "sites\/update-deployment-status.md", @@ -21674,7 +22182,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 484, + "weight": 496, "cookies": false, "type": "", "demo": "sites\/list-logs.md", @@ -21746,7 +22254,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 483, + "weight": 495, "cookies": false, "type": "", "demo": "sites\/get-log.md", @@ -21811,7 +22319,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 485, + "weight": 497, "cookies": false, "type": "", "demo": "sites\/delete-log.md", @@ -21879,7 +22387,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 488, + "weight": 500, "cookies": false, "type": "", "demo": "sites\/list-variables.md", @@ -21939,7 +22447,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 486, + "weight": 498, "cookies": false, "type": "", "demo": "sites\/create-variable.md", @@ -22030,7 +22538,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 487, + "weight": 499, "cookies": false, "type": "", "demo": "sites\/get-variable.md", @@ -22098,7 +22606,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 489, + "weight": 501, "cookies": false, "type": "", "demo": "sites\/update-variable.md", @@ -22191,7 +22699,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 490, + "weight": 502, "cookies": false, "type": "", "demo": "sites\/delete-variable.md", @@ -23499,7 +24007,7 @@ "x-appwrite": { "method": "list", "group": "tablesdb", - "weight": 376, + "weight": 382, "cookies": false, "type": "", "demo": "tablesdb\/list.md", @@ -23572,7 +24080,7 @@ "x-appwrite": { "method": "create", "group": "tablesdb", - "weight": 372, + "weight": 378, "cookies": false, "type": "", "demo": "tablesdb\/create.md", @@ -23631,6 +24139,431 @@ ] } }, + "\/tablesdb\/transactions": { + "get": { + "summary": "List transactions", + "operationId": "tablesDBListTransactions", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "List transactions across all databases.", + "responses": { + "200": { + "description": "Transaction List", + "schema": { + "$ref": "#\/definitions\/transactionList" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "listTransactions", + "group": "transactions", + "weight": 441, + "cookies": false, + "type": "", + "demo": "tablesdb\/list-transactions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/list-transactions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries).", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "post": { + "summary": "Create transaction", + "operationId": "tablesDBCreateTransaction", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "Create a new transaction.", + "responses": { + "201": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createTransaction", + "group": "transactions", + "weight": 437, + "cookies": false, + "type": "", + "demo": "tablesdb\/create-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/create-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "ttl": { + "type": "integer", + "description": "Seconds before the transaction expires.", + "default": 300, + "x-example": 60 + } + } + } + } + ] + } + }, + "\/tablesdb\/transactions\/{transactionId}": { + "get": { + "summary": "Get transaction", + "operationId": "tablesDBGetTransaction", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "Get a transaction by its unique ID.", + "responses": { + "200": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "getTransaction", + "group": "transactions", + "weight": 438, + "cookies": false, + "type": "", + "demo": "tablesdb\/get-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/get-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update transaction", + "operationId": "tablesDBUpdateTransaction", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "Update a transaction, to either commit or roll back its operations.", + "responses": { + "200": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateTransaction", + "group": "transactions", + "weight": 439, + "cookies": false, + "type": "", + "demo": "tablesdb\/update-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/update-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "commit": { + "type": "boolean", + "description": "Commit transaction?", + "default": false, + "x-example": false + }, + "rollback": { + "type": "boolean", + "description": "Rollback transaction?", + "default": false, + "x-example": false + } + } + } + } + ] + }, + "delete": { + "summary": "Delete transaction", + "operationId": "tablesDBDeleteTransaction", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "tablesDB" + ], + "description": "Delete a transaction by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "deprecated": false, + "x-appwrite": { + "method": "deleteTransaction", + "group": "transactions", + "weight": 440, + "cookies": false, + "type": "", + "demo": "tablesdb\/delete-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/delete-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + } + }, + "\/tablesdb\/transactions\/{transactionId}\/operations": { + "post": { + "summary": "Create operations", + "operationId": "tablesDBCreateOperations", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "Create multiple operations in a single transaction.", + "responses": { + "201": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createOperations", + "group": "transactions", + "weight": 442, + "cookies": false, + "type": "", + "demo": "tablesdb\/create-operations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/create-operations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "operations": { + "type": "array", + "description": "Array of staged operations.", + "default": [], + "x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"\",\n\t \"tableId\": \"\",\n\t \"rowId\": \"\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]", + "items": { + "type": "object" + } + } + } + } + } + ] + } + }, "\/tablesdb\/{databaseId}": { "get": { "summary": "Get database", @@ -23655,7 +24588,7 @@ "x-appwrite": { "method": "get", "group": "tablesdb", - "weight": 373, + "weight": 379, "cookies": false, "type": "", "demo": "tablesdb\/get.md", @@ -23715,7 +24648,7 @@ "x-appwrite": { "method": "update", "group": "tablesdb", - "weight": 374, + "weight": 380, "cookies": false, "type": "", "demo": "tablesdb\/update.md", @@ -23794,7 +24727,7 @@ "x-appwrite": { "method": "delete", "group": "tablesdb", - "weight": 375, + "weight": 381, "cookies": false, "type": "", "demo": "tablesdb\/delete.md", @@ -23854,7 +24787,7 @@ "x-appwrite": { "method": "listTables", "group": "tables", - "weight": 383, + "weight": 389, "cookies": false, "type": "", "demo": "tablesdb\/list-tables.md", @@ -23938,7 +24871,7 @@ "x-appwrite": { "method": "createTable", "group": "tables", - "weight": 379, + "weight": 385, "cookies": false, "type": "", "demo": "tablesdb\/create-table.md", @@ -24047,7 +24980,7 @@ "x-appwrite": { "method": "getTable", "group": "tables", - "weight": 380, + "weight": 386, "cookies": false, "type": "", "demo": "tablesdb\/get-table.md", @@ -24118,7 +25051,7 @@ "x-appwrite": { "method": "updateTable", "group": "tables", - "weight": 381, + "weight": 387, "cookies": false, "type": "", "demo": "tablesdb\/update-table.md", @@ -24223,7 +25156,7 @@ "x-appwrite": { "method": "deleteTable", "group": "tables", - "weight": 382, + "weight": 388, "cookies": false, "type": "", "demo": "tablesdb\/delete-table.md", @@ -24294,7 +25227,7 @@ "x-appwrite": { "method": "listColumns", "group": "columns", - "weight": 388, + "weight": 394, "cookies": false, "type": "", "demo": "tablesdb\/list-columns.md", @@ -24379,7 +25312,7 @@ "x-appwrite": { "method": "createBooleanColumn", "group": "columns", - "weight": 389, + "weight": 395, "cookies": false, "type": "", "demo": "tablesdb\/create-boolean-column.md", @@ -24489,7 +25422,7 @@ "x-appwrite": { "method": "updateBooleanColumn", "group": "columns", - "weight": 390, + "weight": 396, "cookies": false, "type": "", "demo": "tablesdb\/update-boolean-column.md", @@ -24601,7 +25534,7 @@ "x-appwrite": { "method": "createDatetimeColumn", "group": "columns", - "weight": 391, + "weight": 397, "cookies": false, "type": "", "demo": "tablesdb\/create-datetime-column.md", @@ -24711,7 +25644,7 @@ "x-appwrite": { "method": "updateDatetimeColumn", "group": "columns", - "weight": 392, + "weight": 398, "cookies": false, "type": "", "demo": "tablesdb\/update-datetime-column.md", @@ -24823,7 +25756,7 @@ "x-appwrite": { "method": "createEmailColumn", "group": "columns", - "weight": 393, + "weight": 399, "cookies": false, "type": "", "demo": "tablesdb\/create-email-column.md", @@ -24933,7 +25866,7 @@ "x-appwrite": { "method": "updateEmailColumn", "group": "columns", - "weight": 394, + "weight": 400, "cookies": false, "type": "", "demo": "tablesdb\/update-email-column.md", @@ -25045,7 +25978,7 @@ "x-appwrite": { "method": "createEnumColumn", "group": "columns", - "weight": 395, + "weight": 401, "cookies": false, "type": "", "demo": "tablesdb\/create-enum-column.md", @@ -25165,7 +26098,7 @@ "x-appwrite": { "method": "updateEnumColumn", "group": "columns", - "weight": 396, + "weight": 402, "cookies": false, "type": "", "demo": "tablesdb\/update-enum-column.md", @@ -25287,7 +26220,7 @@ "x-appwrite": { "method": "createFloatColumn", "group": "columns", - "weight": 397, + "weight": 403, "cookies": false, "type": "", "demo": "tablesdb\/create-float-column.md", @@ -25409,7 +26342,7 @@ "x-appwrite": { "method": "updateFloatColumn", "group": "columns", - "weight": 398, + "weight": 404, "cookies": false, "type": "", "demo": "tablesdb\/update-float-column.md", @@ -25533,7 +26466,7 @@ "x-appwrite": { "method": "createIntegerColumn", "group": "columns", - "weight": 399, + "weight": 405, "cookies": false, "type": "", "demo": "tablesdb\/create-integer-column.md", @@ -25655,7 +26588,7 @@ "x-appwrite": { "method": "updateIntegerColumn", "group": "columns", - "weight": 400, + "weight": 406, "cookies": false, "type": "", "demo": "tablesdb\/update-integer-column.md", @@ -25779,7 +26712,7 @@ "x-appwrite": { "method": "createIpColumn", "group": "columns", - "weight": 401, + "weight": 407, "cookies": false, "type": "", "demo": "tablesdb\/create-ip-column.md", @@ -25889,7 +26822,7 @@ "x-appwrite": { "method": "updateIpColumn", "group": "columns", - "weight": 402, + "weight": 408, "cookies": false, "type": "", "demo": "tablesdb\/update-ip-column.md", @@ -26001,7 +26934,7 @@ "x-appwrite": { "method": "createLineColumn", "group": "columns", - "weight": 403, + "weight": 409, "cookies": false, "type": "", "demo": "tablesdb\/create-line-column.md", @@ -26106,7 +27039,7 @@ "x-appwrite": { "method": "updateLineColumn", "group": "columns", - "weight": 404, + "weight": 410, "cookies": false, "type": "", "demo": "tablesdb\/update-line-column.md", @@ -26217,7 +27150,7 @@ "x-appwrite": { "method": "createPointColumn", "group": "columns", - "weight": 405, + "weight": 411, "cookies": false, "type": "", "demo": "tablesdb\/create-point-column.md", @@ -26322,7 +27255,7 @@ "x-appwrite": { "method": "updatePointColumn", "group": "columns", - "weight": 406, + "weight": 412, "cookies": false, "type": "", "demo": "tablesdb\/update-point-column.md", @@ -26433,7 +27366,7 @@ "x-appwrite": { "method": "createPolygonColumn", "group": "columns", - "weight": 407, + "weight": 413, "cookies": false, "type": "", "demo": "tablesdb\/create-polygon-column.md", @@ -26538,7 +27471,7 @@ "x-appwrite": { "method": "updatePolygonColumn", "group": "columns", - "weight": 408, + "weight": 414, "cookies": false, "type": "", "demo": "tablesdb\/update-polygon-column.md", @@ -26649,7 +27582,7 @@ "x-appwrite": { "method": "createRelationshipColumn", "group": "columns", - "weight": 409, + "weight": 415, "cookies": false, "type": "", "demo": "tablesdb\/create-relationship-column.md", @@ -26786,7 +27719,7 @@ "x-appwrite": { "method": "createStringColumn", "group": "columns", - "weight": 411, + "weight": 417, "cookies": false, "type": "", "demo": "tablesdb\/create-string-column.md", @@ -26909,7 +27842,7 @@ "x-appwrite": { "method": "updateStringColumn", "group": "columns", - "weight": 412, + "weight": 418, "cookies": false, "type": "", "demo": "tablesdb\/update-string-column.md", @@ -27027,7 +27960,7 @@ "x-appwrite": { "method": "createUrlColumn", "group": "columns", - "weight": 413, + "weight": 419, "cookies": false, "type": "", "demo": "tablesdb\/create-url-column.md", @@ -27137,7 +28070,7 @@ "x-appwrite": { "method": "updateUrlColumn", "group": "columns", - "weight": 414, + "weight": 420, "cookies": false, "type": "", "demo": "tablesdb\/update-url-column.md", @@ -27278,7 +28211,7 @@ "x-appwrite": { "method": "getColumn", "group": "columns", - "weight": 386, + "weight": 392, "cookies": false, "type": "", "demo": "tablesdb\/get-column.md", @@ -27351,7 +28284,7 @@ "x-appwrite": { "method": "deleteColumn", "group": "columns", - "weight": 387, + "weight": 393, "cookies": false, "type": "", "demo": "tablesdb\/delete-column.md", @@ -27431,7 +28364,7 @@ "x-appwrite": { "method": "updateRelationshipColumn", "group": "columns", - "weight": 410, + "weight": 416, "cookies": false, "type": "", "demo": "tablesdb\/update-relationship-column.md", @@ -27537,7 +28470,7 @@ "x-appwrite": { "method": "listIndexes", "group": "indexes", - "weight": 418, + "weight": 424, "cookies": false, "type": "", "demo": "tablesdb\/list-indexes.md", @@ -27620,7 +28553,7 @@ "x-appwrite": { "method": "createIndex", "group": "indexes", - "weight": 415, + "weight": 421, "cookies": false, "type": "", "demo": "tablesdb\/create-index.md", @@ -27752,7 +28685,7 @@ "x-appwrite": { "method": "getIndex", "group": "indexes", - "weight": 416, + "weight": 422, "cookies": false, "type": "", "demo": "tablesdb\/get-index.md", @@ -27825,7 +28758,7 @@ "x-appwrite": { "method": "deleteIndex", "group": "indexes", - "weight": 417, + "weight": 423, "cookies": false, "type": "", "demo": "tablesdb\/delete-index.md", @@ -27903,7 +28836,7 @@ "x-appwrite": { "method": "listRows", "group": "rows", - "weight": 427, + "weight": 433, "cookies": false, "type": "", "demo": "tablesdb\/list-rows.md", @@ -27961,6 +28894,14 @@ }, "default": [], "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "type": "string", + "x-example": "", + "in": "query" } ] }, @@ -27989,7 +28930,7 @@ "x-appwrite": { "method": "createRow", "group": "rows", - "weight": 419, + "weight": 425, "cookies": false, "type": "", "demo": "tablesdb\/create-row.md", @@ -28020,7 +28961,8 @@ "tableId", "rowId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -28048,7 +28990,8 @@ "parameters": [ "databaseId", "tableId", - "rows" + "rows", + "transactionId" ], "required": [ "databaseId", @@ -28130,6 +29073,12 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -28161,7 +29110,7 @@ "x-appwrite": { "method": "upsertRows", "group": "rows", - "weight": 424, + "weight": 430, "cookies": false, "type": "", "demo": "tablesdb\/upsert-rows.md", @@ -28190,7 +29139,8 @@ "parameters": [ "databaseId", "tableId", - "rows" + "rows", + "transactionId" ], "required": [ "databaseId", @@ -28249,6 +29199,12 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } }, "required": [ @@ -28283,7 +29239,7 @@ "x-appwrite": { "method": "updateRows", "group": "rows", - "weight": 422, + "weight": 428, "cookies": false, "type": "", "demo": "tablesdb\/update-rows.md", @@ -28348,6 +29304,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -28379,7 +29341,7 @@ "x-appwrite": { "method": "deleteRows", "group": "rows", - "weight": 426, + "weight": 432, "cookies": false, "type": "", "demo": "tablesdb\/delete-rows.md", @@ -28438,6 +29400,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -28469,7 +29437,7 @@ "x-appwrite": { "method": "getRow", "group": "rows", - "weight": 420, + "weight": 426, "cookies": false, "type": "", "demo": "tablesdb\/get-row.md", @@ -28535,6 +29503,14 @@ }, "default": [], "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "type": "string", + "x-example": "", + "in": "query" } ] }, @@ -28563,7 +29539,7 @@ "x-appwrite": { "method": "upsertRow", "group": "rows", - "weight": 423, + "weight": 429, "cookies": false, "type": "", "demo": "tablesdb\/upsert-row.md", @@ -28594,7 +29570,8 @@ "tableId", "rowId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -28669,6 +29646,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -28700,7 +29683,7 @@ "x-appwrite": { "method": "updateRow", "group": "rows", - "weight": 421, + "weight": 427, "cookies": false, "type": "", "demo": "tablesdb\/update-row.md", @@ -28775,6 +29758,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -28801,7 +29790,7 @@ "x-appwrite": { "method": "deleteRow", "group": "rows", - "weight": 425, + "weight": 431, "cookies": false, "type": "", "demo": "tablesdb\/delete-row.md", @@ -28855,6 +29844,21 @@ "type": "string", "x-example": "", "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" + } + } + } } ] } @@ -28885,7 +29889,7 @@ "x-appwrite": { "method": "decrementRowColumn", "group": "rows", - "weight": 430, + "weight": 436, "cookies": false, "type": "", "demo": "tablesdb\/decrement-row-column.md", @@ -28965,6 +29969,12 @@ "description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -28998,7 +30008,7 @@ "x-appwrite": { "method": "incrementRowColumn", "group": "rows", - "weight": 429, + "weight": 435, "cookies": false, "type": "", "demo": "tablesdb\/increment-row-column.md", @@ -29078,6 +30088,12 @@ "description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -30144,7 +31160,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 507, + "weight": 519, "cookies": false, "type": "", "demo": "tokens\/list.md", @@ -30225,7 +31241,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 505, + "weight": 517, "cookies": false, "type": "", "demo": "tokens\/create-file-token.md", @@ -30310,7 +31326,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 506, + "weight": 518, "cookies": false, "type": "", "demo": "tokens\/get.md", @@ -30371,7 +31387,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 508, + "weight": 520, "cookies": false, "type": "", "demo": "tokens\/update.md", @@ -30443,7 +31459,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 509, + "weight": 521, "cookies": false, "type": "", "demo": "tokens\/delete.md", @@ -35167,6 +36183,35 @@ "targets": "" } }, + "transactionList": { + "description": "Transaction List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of transactions that matched your query.", + "x-example": 5, + "format": "int32" + }, + "transactions": { + "type": "array", + "description": "List of transactions.", + "items": { + "type": "object", + "$ref": "#\/definitions\/transaction" + }, + "x-example": "" + } + }, + "required": [ + "total", + "transactions" + ], + "example": { + "total": 5, + "transactions": "" + } + }, "specificationList": { "description": "Specifications List", "type": "object", @@ -41839,6 +42884,59 @@ "subscribe": "users" } }, + "transaction": { + "description": "Transaction", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Transaction ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Transaction creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Transaction update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "status": { + "type": "string", + "description": "Current status of the transaction. One of: pending, committing, committed, rolled_back, failed.", + "x-example": "pending" + }, + "operations": { + "type": "integer", + "description": "Number of operations in the transaction.", + "x-example": 5, + "format": "int32" + }, + "expiresAt": { + "type": "string", + "description": "Expiration time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "status", + "operations", + "expiresAt" + ], + "example": { + "$id": "259125845563242502", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "status": "pending", + "operations": 5, + "expiresAt": "2020-10-15T06:38:00.000+00:00" + } + }, "subscriber": { "description": "Subscriber", "type": "object", diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index 9b7a240b18..89fc5e7e5c 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -5052,6 +5052,419 @@ ] } }, + "\/databases\/transactions": { + "get": { + "summary": "List transactions", + "operationId": "databasesListTransactions", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "List transactions across all databases.", + "responses": { + "200": { + "description": "Transaction List", + "schema": { + "$ref": "#\/definitions\/transactionList" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "listTransactions", + "group": "transactions", + "weight": 376, + "cookies": false, + "type": "", + "demo": "databases\/list-transactions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-transactions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries).", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "post": { + "summary": "Create transaction", + "operationId": "databasesCreateTransaction", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create a new transaction.", + "responses": { + "201": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createTransaction", + "group": "transactions", + "weight": 372, + "cookies": false, + "type": "", + "demo": "databases\/create-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "ttl": { + "type": "integer", + "description": "Seconds before the transaction expires.", + "default": 300, + "x-example": 60 + } + } + } + } + ] + } + }, + "\/databases\/transactions\/{transactionId}": { + "get": { + "summary": "Get transaction", + "operationId": "databasesGetTransaction", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get a transaction by its unique ID.", + "responses": { + "200": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "getTransaction", + "group": "transactions", + "weight": 373, + "cookies": false, + "type": "", + "demo": "databases\/get-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update transaction", + "operationId": "databasesUpdateTransaction", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update a transaction, to either commit or roll back its operations.", + "responses": { + "200": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateTransaction", + "group": "transactions", + "weight": 374, + "cookies": false, + "type": "", + "demo": "databases\/update-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "commit": { + "type": "boolean", + "description": "Commit transaction?", + "default": false, + "x-example": false + }, + "rollback": { + "type": "boolean", + "description": "Rollback transaction?", + "default": false, + "x-example": false + } + } + } + } + ] + }, + "delete": { + "summary": "Delete transaction", + "operationId": "databasesDeleteTransaction", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "databases" + ], + "description": "Delete a transaction by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "deprecated": false, + "x-appwrite": { + "method": "deleteTransaction", + "group": "transactions", + "weight": 375, + "cookies": false, + "type": "", + "demo": "databases\/delete-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + } + }, + "\/databases\/transactions\/{transactionId}\/operations": { + "post": { + "summary": "Create operations", + "operationId": "databasesCreateOperations", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create multiple operations in a single transaction.", + "responses": { + "201": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createOperations", + "group": "transactions", + "weight": 377, + "cookies": false, + "type": "", + "demo": "databases\/create-operations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-operations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "operations": { + "type": "array", + "description": "Array of staged operations.", + "default": [], + "x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"\",\n\t \"collectionId\": \"\",\n\t \"documentId\": \"\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]", + "items": { + "type": "object" + } + } + } + } + } + ] + } + }, "\/databases\/{databaseId}\/collections\/{collectionId}\/documents": { "get": { "summary": "List documents", @@ -5133,6 +5546,14 @@ }, "default": [], "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "type": "string", + "x-example": "", + "in": "query" } ] }, @@ -5192,7 +5613,8 @@ "collectionId", "documentId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -5277,6 +5699,12 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -5373,6 +5801,14 @@ }, "default": [], "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "type": "string", + "x-example": "", + "in": "query" } ] }, @@ -5432,7 +5868,8 @@ "collectionId", "documentId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -5510,6 +5947,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } }, "required": [ @@ -5618,6 +6061,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -5697,6 +6146,21 @@ "type": "string", "x-example": "", "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" + } + } + } } ] } @@ -5806,6 +6270,12 @@ "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -5918,6 +6388,12 @@ "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -5949,7 +6425,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 456, + "weight": 468, "cookies": false, "type": "", "demo": "functions\/list-executions.md", @@ -6022,7 +6498,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 454, + "weight": 466, "cookies": false, "type": "", "demo": "functions\/create-execution.md", @@ -6139,7 +6615,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 455, + "weight": 467, "cookies": false, "type": "", "demo": "functions\/get-execution.md", @@ -7653,6 +8129,419 @@ ] } }, + "\/tablesdb\/transactions": { + "get": { + "summary": "List transactions", + "operationId": "tablesDBListTransactions", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "List transactions across all databases.", + "responses": { + "200": { + "description": "Transaction List", + "schema": { + "$ref": "#\/definitions\/transactionList" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "listTransactions", + "group": "transactions", + "weight": 441, + "cookies": false, + "type": "", + "demo": "tablesdb\/list-transactions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/list-transactions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries).", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "post": { + "summary": "Create transaction", + "operationId": "tablesDBCreateTransaction", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "Create a new transaction.", + "responses": { + "201": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createTransaction", + "group": "transactions", + "weight": 437, + "cookies": false, + "type": "", + "demo": "tablesdb\/create-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/create-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "ttl": { + "type": "integer", + "description": "Seconds before the transaction expires.", + "default": 300, + "x-example": 60 + } + } + } + } + ] + } + }, + "\/tablesdb\/transactions\/{transactionId}": { + "get": { + "summary": "Get transaction", + "operationId": "tablesDBGetTransaction", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "Get a transaction by its unique ID.", + "responses": { + "200": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "getTransaction", + "group": "transactions", + "weight": 438, + "cookies": false, + "type": "", + "demo": "tablesdb\/get-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/get-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update transaction", + "operationId": "tablesDBUpdateTransaction", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "Update a transaction, to either commit or roll back its operations.", + "responses": { + "200": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateTransaction", + "group": "transactions", + "weight": 439, + "cookies": false, + "type": "", + "demo": "tablesdb\/update-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/update-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "commit": { + "type": "boolean", + "description": "Commit transaction?", + "default": false, + "x-example": false + }, + "rollback": { + "type": "boolean", + "description": "Rollback transaction?", + "default": false, + "x-example": false + } + } + } + } + ] + }, + "delete": { + "summary": "Delete transaction", + "operationId": "tablesDBDeleteTransaction", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "tablesDB" + ], + "description": "Delete a transaction by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "deprecated": false, + "x-appwrite": { + "method": "deleteTransaction", + "group": "transactions", + "weight": 440, + "cookies": false, + "type": "", + "demo": "tablesdb\/delete-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/delete-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + } + }, + "\/tablesdb\/transactions\/{transactionId}\/operations": { + "post": { + "summary": "Create operations", + "operationId": "tablesDBCreateOperations", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "Create multiple operations in a single transaction.", + "responses": { + "201": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createOperations", + "group": "transactions", + "weight": 442, + "cookies": false, + "type": "", + "demo": "tablesdb\/create-operations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/create-operations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "operations": { + "type": "array", + "description": "Array of staged operations.", + "default": [], + "x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"\",\n\t \"tableId\": \"\",\n\t \"rowId\": \"\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]", + "items": { + "type": "object" + } + } + } + } + } + ] + } + }, "\/tablesdb\/{databaseId}\/tables\/{tableId}\/rows": { "get": { "summary": "List rows", @@ -7677,7 +8566,7 @@ "x-appwrite": { "method": "listRows", "group": "rows", - "weight": 427, + "weight": 433, "cookies": false, "type": "", "demo": "tablesdb\/list-rows.md", @@ -7733,6 +8622,14 @@ }, "default": [], "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "type": "string", + "x-example": "", + "in": "query" } ] }, @@ -7761,7 +8658,7 @@ "x-appwrite": { "method": "createRow", "group": "rows", - "weight": 419, + "weight": 425, "cookies": false, "type": "", "demo": "tablesdb\/create-row.md", @@ -7791,7 +8688,8 @@ "tableId", "rowId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -7872,6 +8770,12 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -7903,7 +8807,7 @@ "x-appwrite": { "method": "getRow", "group": "rows", - "weight": 420, + "weight": 426, "cookies": false, "type": "", "demo": "tablesdb\/get-row.md", @@ -7967,6 +8871,14 @@ }, "default": [], "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "type": "string", + "x-example": "", + "in": "query" } ] }, @@ -7995,7 +8907,7 @@ "x-appwrite": { "method": "upsertRow", "group": "rows", - "weight": 423, + "weight": 429, "cookies": false, "type": "", "demo": "tablesdb\/upsert-row.md", @@ -8025,7 +8937,8 @@ "tableId", "rowId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -8098,6 +9011,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -8129,7 +9048,7 @@ "x-appwrite": { "method": "updateRow", "group": "rows", - "weight": 421, + "weight": 427, "cookies": false, "type": "", "demo": "tablesdb\/update-row.md", @@ -8202,6 +9121,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -8228,7 +9153,7 @@ "x-appwrite": { "method": "deleteRow", "group": "rows", - "weight": 425, + "weight": 431, "cookies": false, "type": "", "demo": "tablesdb\/delete-row.md", @@ -8280,6 +9205,21 @@ "type": "string", "x-example": "", "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" + } + } + } } ] } @@ -8310,7 +9250,7 @@ "x-appwrite": { "method": "decrementRowColumn", "group": "rows", - "weight": 430, + "weight": 436, "cookies": false, "type": "", "demo": "tablesdb\/decrement-row-column.md", @@ -8388,6 +9328,12 @@ "description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -8421,7 +9367,7 @@ "x-appwrite": { "method": "incrementRowColumn", "group": "rows", - "weight": 429, + "weight": 435, "cookies": false, "type": "", "demo": "tablesdb\/increment-row-column.md", @@ -8499,6 +9445,12 @@ "description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -10035,6 +10987,35 @@ "localeCodes": "" } }, + "transactionList": { + "description": "Transaction List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of transactions that matched your query.", + "x-example": 5, + "format": "int32" + }, + "transactions": { + "type": "array", + "description": "List of transactions.", + "items": { + "type": "object", + "$ref": "#\/definitions\/transaction" + }, + "x-example": "" + } + }, + "required": [ + "total", + "transactions" + ], + "example": { + "total": 5, + "transactions": "" + } + }, "row": { "description": "Row", "type": "object", @@ -11955,6 +12936,59 @@ "recoveryCode": true } }, + "transaction": { + "description": "Transaction", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Transaction ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Transaction creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Transaction update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "status": { + "type": "string", + "description": "Current status of the transaction. One of: pending, committing, committed, rolled_back, failed.", + "x-example": "pending" + }, + "operations": { + "type": "integer", + "description": "Number of operations in the transaction.", + "x-example": 5, + "format": "int32" + }, + "expiresAt": { + "type": "string", + "description": "Expiration time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "status", + "operations", + "expiresAt" + ], + "example": { + "$id": "259125845563242502", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "status": "pending", + "operations": 5, + "expiresAt": "2020-10-15T06:38:00.000+00:00" + } + }, "subscriber": { "description": "Subscriber", "type": "object", diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index affee9509c..098f138b30 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -5156,7 +5156,7 @@ "x-appwrite": { "method": "getResource", "group": null, - "weight": 496, + "weight": 508, "cookies": false, "type": "", "demo": "console\/get-resource.md", @@ -5471,6 +5471,419 @@ ] } }, + "\/databases\/transactions": { + "get": { + "summary": "List transactions", + "operationId": "databasesListTransactions", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "List transactions across all databases.", + "responses": { + "200": { + "description": "Transaction List", + "schema": { + "$ref": "#\/definitions\/transactionList" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "listTransactions", + "group": "transactions", + "weight": 376, + "cookies": false, + "type": "", + "demo": "databases\/list-transactions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-transactions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries).", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "post": { + "summary": "Create transaction", + "operationId": "databasesCreateTransaction", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create a new transaction.", + "responses": { + "201": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createTransaction", + "group": "transactions", + "weight": 372, + "cookies": false, + "type": "", + "demo": "databases\/create-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "ttl": { + "type": "integer", + "description": "Seconds before the transaction expires.", + "default": 300, + "x-example": 60 + } + } + } + } + ] + } + }, + "\/databases\/transactions\/{transactionId}": { + "get": { + "summary": "Get transaction", + "operationId": "databasesGetTransaction", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get a transaction by its unique ID.", + "responses": { + "200": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "getTransaction", + "group": "transactions", + "weight": 373, + "cookies": false, + "type": "", + "demo": "databases\/get-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update transaction", + "operationId": "databasesUpdateTransaction", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update a transaction, to either commit or roll back its operations.", + "responses": { + "200": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateTransaction", + "group": "transactions", + "weight": 374, + "cookies": false, + "type": "", + "demo": "databases\/update-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "commit": { + "type": "boolean", + "description": "Commit transaction?", + "default": false, + "x-example": false + }, + "rollback": { + "type": "boolean", + "description": "Rollback transaction?", + "default": false, + "x-example": false + } + } + } + } + ] + }, + "delete": { + "summary": "Delete transaction", + "operationId": "databasesDeleteTransaction", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "databases" + ], + "description": "Delete a transaction by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "deprecated": false, + "x-appwrite": { + "method": "deleteTransaction", + "group": "transactions", + "weight": 375, + "cookies": false, + "type": "", + "demo": "databases\/delete-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + } + }, + "\/databases\/transactions\/{transactionId}\/operations": { + "post": { + "summary": "Create operations", + "operationId": "databasesCreateOperations", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create multiple operations in a single transaction.", + "responses": { + "201": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createOperations", + "group": "transactions", + "weight": 377, + "cookies": false, + "type": "", + "demo": "databases\/create-operations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-operations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "operations": { + "type": "array", + "description": "Array of staged operations.", + "default": [], + "x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"\",\n\t \"collectionId\": \"\",\n\t \"documentId\": \"\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]", + "items": { + "type": "object" + } + } + } + } + } + ] + } + }, "\/databases\/usage": { "get": { "summary": "Get databases usage stats", @@ -9629,6 +10042,14 @@ }, "default": [], "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "type": "string", + "x-example": "", + "in": "query" } ] }, @@ -9688,7 +10109,8 @@ "collectionId", "documentId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -9719,7 +10141,8 @@ "parameters": [ "databaseId", "collectionId", - "documents" + "documents", + "transactionId" ], "required": [ "databaseId", @@ -9803,6 +10226,12 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -9863,7 +10292,8 @@ "parameters": [ "databaseId", "collectionId", - "documents" + "documents", + "transactionId" ], "required": [ "databaseId", @@ -9925,6 +10355,12 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } }, "required": [ @@ -10024,6 +10460,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -10114,6 +10556,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -10210,6 +10658,14 @@ }, "default": [], "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "type": "string", + "x-example": "", + "in": "query" } ] }, @@ -10269,7 +10725,8 @@ "collectionId", "documentId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -10347,6 +10804,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } }, "required": [ @@ -10455,6 +10918,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -10534,6 +11003,21 @@ "type": "string", "x-example": "", "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" + } + } + } } ] } @@ -10733,6 +11217,12 @@ "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -10845,6 +11335,12 @@ "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -11078,7 +11574,7 @@ "tags": [ "databases" ], - "description": "Get index by ID.", + "description": "Get an index by its unique ID.", "responses": { "200": { "description": "Index", @@ -11628,7 +12124,7 @@ "x-appwrite": { "method": "list", "group": "functions", - "weight": 440, + "weight": 452, "cookies": false, "type": "", "demo": "functions\/list.md", @@ -11700,7 +12196,7 @@ "x-appwrite": { "method": "create", "group": "functions", - "weight": 437, + "weight": 449, "cookies": false, "type": "", "demo": "functions\/create.md", @@ -11951,7 +12447,7 @@ "x-appwrite": { "method": "listRuntimes", "group": "runtimes", - "weight": 442, + "weight": 454, "cookies": false, "type": "", "demo": "functions\/list-runtimes.md", @@ -12000,7 +12496,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "runtimes", - "weight": 443, + "weight": 455, "cookies": false, "type": "", "demo": "functions\/list-specifications.md", @@ -12050,7 +12546,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 466, + "weight": 478, "cookies": false, "type": "", "demo": "functions\/list-templates.md", @@ -12144,7 +12640,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 465, + "weight": 477, "cookies": false, "type": "", "demo": "functions\/get-template.md", @@ -12202,7 +12698,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 459, + "weight": 471, "cookies": false, "type": "", "demo": "functions\/list-usage.md", @@ -12272,7 +12768,7 @@ "x-appwrite": { "method": "get", "group": "functions", - "weight": 438, + "weight": 450, "cookies": false, "type": "", "demo": "functions\/get.md", @@ -12331,7 +12827,7 @@ "x-appwrite": { "method": "update", "group": "functions", - "weight": 439, + "weight": 451, "cookies": false, "type": "", "demo": "functions\/update.md", @@ -12578,7 +13074,7 @@ "x-appwrite": { "method": "delete", "group": "functions", - "weight": 441, + "weight": 453, "cookies": false, "type": "", "demo": "functions\/delete.md", @@ -12639,7 +13135,7 @@ "x-appwrite": { "method": "updateFunctionDeployment", "group": "functions", - "weight": 446, + "weight": 458, "cookies": false, "type": "", "demo": "functions\/update-function-deployment.md", @@ -12716,7 +13212,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 447, + "weight": 459, "cookies": false, "type": "", "demo": "functions\/list-deployments.md", @@ -12796,7 +13292,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 444, + "weight": 456, "cookies": false, "type": "upload", "demo": "functions\/create-deployment.md", @@ -12888,7 +13384,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 452, + "weight": 464, "cookies": false, "type": "", "demo": "functions\/create-duplicate-deployment.md", @@ -12973,7 +13469,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 449, + "weight": 461, "cookies": false, "type": "", "demo": "functions\/create-template-deployment.md", @@ -13079,7 +13575,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 450, + "weight": 462, "cookies": false, "type": "", "demo": "functions\/create-vcs-deployment.md", @@ -13175,7 +13671,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 445, + "weight": 457, "cookies": false, "type": "", "demo": "functions\/get-deployment.md", @@ -13237,7 +13733,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 448, + "weight": 460, "cookies": false, "type": "", "demo": "functions\/delete-deployment.md", @@ -13304,7 +13800,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 451, + "weight": 463, "cookies": false, "type": "location", "demo": "functions\/get-deployment-download.md", @@ -13389,7 +13885,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 453, + "weight": 465, "cookies": false, "type": "", "demo": "functions\/update-deployment-status.md", @@ -13456,7 +13952,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 456, + "weight": 468, "cookies": false, "type": "", "demo": "functions\/list-executions.md", @@ -13529,7 +14025,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 454, + "weight": 466, "cookies": false, "type": "", "demo": "functions\/create-execution.md", @@ -13646,7 +14142,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 455, + "weight": 467, "cookies": false, "type": "", "demo": "functions\/get-execution.md", @@ -13710,7 +14206,7 @@ "x-appwrite": { "method": "deleteExecution", "group": "executions", - "weight": 457, + "weight": 469, "cookies": false, "type": "", "demo": "functions\/delete-execution.md", @@ -13777,7 +14273,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 458, + "weight": 470, "cookies": false, "type": "", "demo": "functions\/get-usage.md", @@ -13855,7 +14351,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 462, + "weight": 474, "cookies": false, "type": "", "demo": "functions\/list-variables.md", @@ -13914,7 +14410,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 460, + "weight": 472, "cookies": false, "type": "", "demo": "functions\/create-variable.md", @@ -14004,7 +14500,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 461, + "weight": 473, "cookies": false, "type": "", "demo": "functions\/get-variable.md", @@ -14071,7 +14567,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 463, + "weight": 475, "cookies": false, "type": "", "demo": "functions\/update-variable.md", @@ -14163,7 +14659,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 464, + "weight": 476, "cookies": false, "type": "", "demo": "functions\/delete-variable.md", @@ -16527,7 +17023,7 @@ "type": "string", "description": "Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as :.", "default": "", - "x-example": "[ID1:ID2]" + "x-example": "" }, "icon": { "type": "string", @@ -16724,7 +17220,7 @@ "type": "string", "description": "Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as :.", "default": null, - "x-example": "[ID1:ID2]" + "x-example": "" }, "icon": { "type": "string", @@ -21459,7 +21955,7 @@ "type": "string", "description": "Composite ID in the format {databaseId:collectionId}, identifying a collection within a database.", "default": null, - "x-example": "[ID1:ID2]" + "x-example": "" }, "internalFile": { "type": "boolean", @@ -22694,7 +23190,7 @@ "x-appwrite": { "method": "list", "group": "projects", - "weight": 436, + "weight": 448, "cookies": false, "type": "", "demo": "projects\/list.md", @@ -24337,7 +24833,7 @@ "x-appwrite": { "method": "listDevKeys", "group": "devKeys", - "weight": 434, + "weight": 446, "cookies": false, "type": "", "demo": "projects\/list-dev-keys.md", @@ -24407,7 +24903,7 @@ "x-appwrite": { "method": "createDevKey", "group": "devKeys", - "weight": 431, + "weight": 443, "cookies": false, "type": "", "demo": "projects\/create-dev-key.md", @@ -24490,7 +24986,7 @@ "x-appwrite": { "method": "getDevKey", "group": "devKeys", - "weight": 433, + "weight": 445, "cookies": false, "type": "", "demo": "projects\/get-dev-key.md", @@ -24556,7 +25052,7 @@ "x-appwrite": { "method": "updateDevKey", "group": "devKeys", - "weight": 432, + "weight": 444, "cookies": false, "type": "", "demo": "projects\/update-dev-key.md", @@ -24642,7 +25138,7 @@ "x-appwrite": { "method": "deleteDevKey", "group": "devKeys", - "weight": 435, + "weight": 447, "cookies": false, "type": "", "demo": "projects\/delete-dev-key.md", @@ -28455,7 +28951,7 @@ "x-appwrite": { "method": "listRules", "group": null, - "weight": 502, + "weight": 514, "cookies": false, "type": "", "demo": "proxy\/list-rules.md", @@ -28528,7 +29024,7 @@ "x-appwrite": { "method": "createAPIRule", "group": null, - "weight": 497, + "weight": 509, "cookies": false, "type": "", "demo": "proxy\/create-api-rule.md", @@ -28598,7 +29094,7 @@ "x-appwrite": { "method": "createFunctionRule", "group": null, - "weight": 499, + "weight": 511, "cookies": false, "type": "", "demo": "proxy\/create-function-rule.md", @@ -28681,7 +29177,7 @@ "x-appwrite": { "method": "createRedirectRule", "group": null, - "weight": 500, + "weight": 512, "cookies": false, "type": "", "demo": "proxy\/create-redirect-rule.md", @@ -28801,7 +29297,7 @@ "x-appwrite": { "method": "createSiteRule", "group": null, - "weight": 498, + "weight": 510, "cookies": false, "type": "", "demo": "proxy\/create-site-rule.md", @@ -28882,7 +29378,7 @@ "x-appwrite": { "method": "getRule", "group": null, - "weight": 501, + "weight": 513, "cookies": false, "type": "", "demo": "proxy\/get-rule.md", @@ -28935,7 +29431,7 @@ "x-appwrite": { "method": "deleteRule", "group": null, - "weight": 503, + "weight": 515, "cookies": false, "type": "", "demo": "proxy\/delete-rule.md", @@ -28995,7 +29491,7 @@ "x-appwrite": { "method": "updateRuleVerification", "group": null, - "weight": 504, + "weight": 516, "cookies": false, "type": "", "demo": "proxy\/update-rule-verification.md", @@ -29053,7 +29549,7 @@ "x-appwrite": { "method": "list", "group": "sites", - "weight": 469, + "weight": 481, "cookies": false, "type": "", "demo": "sites\/list.md", @@ -29125,7 +29621,7 @@ "x-appwrite": { "method": "create", "group": "sites", - "weight": 467, + "weight": 479, "cookies": false, "type": "", "demo": "sites\/create.md", @@ -29392,7 +29888,7 @@ "x-appwrite": { "method": "listFrameworks", "group": "frameworks", - "weight": 472, + "weight": 484, "cookies": false, "type": "", "demo": "sites\/list-frameworks.md", @@ -29441,7 +29937,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 495, + "weight": 507, "cookies": false, "type": "", "demo": "sites\/list-specifications.md", @@ -29491,7 +29987,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 491, + "weight": 503, "cookies": false, "type": "", "demo": "sites\/list-templates.md", @@ -29585,7 +30081,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 492, + "weight": 504, "cookies": false, "type": "", "demo": "sites\/get-template.md", @@ -29643,7 +30139,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 493, + "weight": 505, "cookies": false, "type": "", "demo": "sites\/list-usage.md", @@ -29713,7 +30209,7 @@ "x-appwrite": { "method": "get", "group": "sites", - "weight": 468, + "weight": 480, "cookies": false, "type": "", "demo": "sites\/get.md", @@ -29772,7 +30268,7 @@ "x-appwrite": { "method": "update", "group": "sites", - "weight": 470, + "weight": 482, "cookies": false, "type": "", "demo": "sites\/update.md", @@ -30034,7 +30530,7 @@ "x-appwrite": { "method": "delete", "group": "sites", - "weight": 471, + "weight": 483, "cookies": false, "type": "", "demo": "sites\/delete.md", @@ -30095,7 +30591,7 @@ "x-appwrite": { "method": "updateSiteDeployment", "group": "sites", - "weight": 478, + "weight": 490, "cookies": false, "type": "", "demo": "sites\/update-site-deployment.md", @@ -30172,7 +30668,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 477, + "weight": 489, "cookies": false, "type": "", "demo": "sites\/list-deployments.md", @@ -30252,7 +30748,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 473, + "weight": 485, "cookies": false, "type": "upload", "demo": "sites\/create-deployment.md", @@ -30352,7 +30848,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 481, + "weight": 493, "cookies": false, "type": "", "demo": "sites\/create-duplicate-deployment.md", @@ -30431,7 +30927,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 474, + "weight": 486, "cookies": false, "type": "", "demo": "sites\/create-template-deployment.md", @@ -30537,7 +31033,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 475, + "weight": 487, "cookies": false, "type": "", "demo": "sites\/create-vcs-deployment.md", @@ -30634,7 +31130,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 476, + "weight": 488, "cookies": false, "type": "", "demo": "sites\/get-deployment.md", @@ -30696,7 +31192,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 479, + "weight": 491, "cookies": false, "type": "", "demo": "sites\/delete-deployment.md", @@ -30763,7 +31259,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 480, + "weight": 492, "cookies": false, "type": "location", "demo": "sites\/get-deployment-download.md", @@ -30848,7 +31344,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 482, + "weight": 494, "cookies": false, "type": "", "demo": "sites\/update-deployment-status.md", @@ -30915,7 +31411,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 484, + "weight": 496, "cookies": false, "type": "", "demo": "sites\/list-logs.md", @@ -30986,7 +31482,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 483, + "weight": 495, "cookies": false, "type": "", "demo": "sites\/get-log.md", @@ -31050,7 +31546,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 485, + "weight": 497, "cookies": false, "type": "", "demo": "sites\/delete-log.md", @@ -31117,7 +31613,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 494, + "weight": 506, "cookies": false, "type": "", "demo": "sites\/get-usage.md", @@ -31195,7 +31691,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 488, + "weight": 500, "cookies": false, "type": "", "demo": "sites\/list-variables.md", @@ -31254,7 +31750,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 486, + "weight": 498, "cookies": false, "type": "", "demo": "sites\/create-variable.md", @@ -31344,7 +31840,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 487, + "weight": 499, "cookies": false, "type": "", "demo": "sites\/get-variable.md", @@ -31411,7 +31907,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 489, + "weight": 501, "cookies": false, "type": "", "demo": "sites\/update-variable.md", @@ -31503,7 +31999,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 490, + "weight": 502, "cookies": false, "type": "", "demo": "sites\/delete-variable.md", @@ -32937,7 +33433,7 @@ "x-appwrite": { "method": "list", "group": "tablesdb", - "weight": 376, + "weight": 382, "cookies": false, "type": "", "demo": "tablesdb\/list.md", @@ -33009,7 +33505,7 @@ "x-appwrite": { "method": "create", "group": "tablesdb", - "weight": 372, + "weight": 378, "cookies": false, "type": "", "demo": "tablesdb\/create.md", @@ -33067,6 +33563,419 @@ ] } }, + "\/tablesdb\/transactions": { + "get": { + "summary": "List transactions", + "operationId": "tablesDBListTransactions", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "List transactions across all databases.", + "responses": { + "200": { + "description": "Transaction List", + "schema": { + "$ref": "#\/definitions\/transactionList" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "listTransactions", + "group": "transactions", + "weight": 441, + "cookies": false, + "type": "", + "demo": "tablesdb\/list-transactions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/list-transactions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries).", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "post": { + "summary": "Create transaction", + "operationId": "tablesDBCreateTransaction", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "Create a new transaction.", + "responses": { + "201": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createTransaction", + "group": "transactions", + "weight": 437, + "cookies": false, + "type": "", + "demo": "tablesdb\/create-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/create-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "ttl": { + "type": "integer", + "description": "Seconds before the transaction expires.", + "default": 300, + "x-example": 60 + } + } + } + } + ] + } + }, + "\/tablesdb\/transactions\/{transactionId}": { + "get": { + "summary": "Get transaction", + "operationId": "tablesDBGetTransaction", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "Get a transaction by its unique ID.", + "responses": { + "200": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "getTransaction", + "group": "transactions", + "weight": 438, + "cookies": false, + "type": "", + "demo": "tablesdb\/get-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/get-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update transaction", + "operationId": "tablesDBUpdateTransaction", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "Update a transaction, to either commit or roll back its operations.", + "responses": { + "200": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateTransaction", + "group": "transactions", + "weight": 439, + "cookies": false, + "type": "", + "demo": "tablesdb\/update-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/update-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "commit": { + "type": "boolean", + "description": "Commit transaction?", + "default": false, + "x-example": false + }, + "rollback": { + "type": "boolean", + "description": "Rollback transaction?", + "default": false, + "x-example": false + } + } + } + } + ] + }, + "delete": { + "summary": "Delete transaction", + "operationId": "tablesDBDeleteTransaction", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "tablesDB" + ], + "description": "Delete a transaction by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "deprecated": false, + "x-appwrite": { + "method": "deleteTransaction", + "group": "transactions", + "weight": 440, + "cookies": false, + "type": "", + "demo": "tablesdb\/delete-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/delete-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + } + }, + "\/tablesdb\/transactions\/{transactionId}\/operations": { + "post": { + "summary": "Create operations", + "operationId": "tablesDBCreateOperations", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "Create multiple operations in a single transaction.", + "responses": { + "201": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createOperations", + "group": "transactions", + "weight": 442, + "cookies": false, + "type": "", + "demo": "tablesdb\/create-operations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/create-operations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "operations": { + "type": "array", + "description": "Array of staged operations.", + "default": [], + "x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"\",\n\t \"tableId\": \"\",\n\t \"rowId\": \"\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]", + "items": { + "type": "object" + } + } + } + } + } + ] + } + }, "\/tablesdb\/usage": { "get": { "summary": "Get TablesDB usage stats", @@ -33091,7 +34000,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 378, + "weight": 384, "cookies": false, "type": "", "demo": "tablesdb\/list-usage.md", @@ -33186,7 +34095,7 @@ "x-appwrite": { "method": "get", "group": "tablesdb", - "weight": 373, + "weight": 379, "cookies": false, "type": "", "demo": "tablesdb\/get.md", @@ -33245,7 +34154,7 @@ "x-appwrite": { "method": "update", "group": "tablesdb", - "weight": 374, + "weight": 380, "cookies": false, "type": "", "demo": "tablesdb\/update.md", @@ -33323,7 +34232,7 @@ "x-appwrite": { "method": "delete", "group": "tablesdb", - "weight": 375, + "weight": 381, "cookies": false, "type": "", "demo": "tablesdb\/delete.md", @@ -33382,7 +34291,7 @@ "x-appwrite": { "method": "listTables", "group": "tables", - "weight": 383, + "weight": 389, "cookies": false, "type": "", "demo": "tablesdb\/list-tables.md", @@ -33465,7 +34374,7 @@ "x-appwrite": { "method": "createTable", "group": "tables", - "weight": 379, + "weight": 385, "cookies": false, "type": "", "demo": "tablesdb\/create-table.md", @@ -33573,7 +34482,7 @@ "x-appwrite": { "method": "getTable", "group": "tables", - "weight": 380, + "weight": 386, "cookies": false, "type": "", "demo": "tablesdb\/get-table.md", @@ -33643,7 +34552,7 @@ "x-appwrite": { "method": "updateTable", "group": "tables", - "weight": 381, + "weight": 387, "cookies": false, "type": "", "demo": "tablesdb\/update-table.md", @@ -33747,7 +34656,7 @@ "x-appwrite": { "method": "deleteTable", "group": "tables", - "weight": 382, + "weight": 388, "cookies": false, "type": "", "demo": "tablesdb\/delete-table.md", @@ -33817,7 +34726,7 @@ "x-appwrite": { "method": "listColumns", "group": "columns", - "weight": 388, + "weight": 394, "cookies": false, "type": "", "demo": "tablesdb\/list-columns.md", @@ -33901,7 +34810,7 @@ "x-appwrite": { "method": "createBooleanColumn", "group": "columns", - "weight": 389, + "weight": 395, "cookies": false, "type": "", "demo": "tablesdb\/create-boolean-column.md", @@ -34010,7 +34919,7 @@ "x-appwrite": { "method": "updateBooleanColumn", "group": "columns", - "weight": 390, + "weight": 396, "cookies": false, "type": "", "demo": "tablesdb\/update-boolean-column.md", @@ -34121,7 +35030,7 @@ "x-appwrite": { "method": "createDatetimeColumn", "group": "columns", - "weight": 391, + "weight": 397, "cookies": false, "type": "", "demo": "tablesdb\/create-datetime-column.md", @@ -34230,7 +35139,7 @@ "x-appwrite": { "method": "updateDatetimeColumn", "group": "columns", - "weight": 392, + "weight": 398, "cookies": false, "type": "", "demo": "tablesdb\/update-datetime-column.md", @@ -34341,7 +35250,7 @@ "x-appwrite": { "method": "createEmailColumn", "group": "columns", - "weight": 393, + "weight": 399, "cookies": false, "type": "", "demo": "tablesdb\/create-email-column.md", @@ -34450,7 +35359,7 @@ "x-appwrite": { "method": "updateEmailColumn", "group": "columns", - "weight": 394, + "weight": 400, "cookies": false, "type": "", "demo": "tablesdb\/update-email-column.md", @@ -34561,7 +35470,7 @@ "x-appwrite": { "method": "createEnumColumn", "group": "columns", - "weight": 395, + "weight": 401, "cookies": false, "type": "", "demo": "tablesdb\/create-enum-column.md", @@ -34680,7 +35589,7 @@ "x-appwrite": { "method": "updateEnumColumn", "group": "columns", - "weight": 396, + "weight": 402, "cookies": false, "type": "", "demo": "tablesdb\/update-enum-column.md", @@ -34801,7 +35710,7 @@ "x-appwrite": { "method": "createFloatColumn", "group": "columns", - "weight": 397, + "weight": 403, "cookies": false, "type": "", "demo": "tablesdb\/create-float-column.md", @@ -34922,7 +35831,7 @@ "x-appwrite": { "method": "updateFloatColumn", "group": "columns", - "weight": 398, + "weight": 404, "cookies": false, "type": "", "demo": "tablesdb\/update-float-column.md", @@ -35045,7 +35954,7 @@ "x-appwrite": { "method": "createIntegerColumn", "group": "columns", - "weight": 399, + "weight": 405, "cookies": false, "type": "", "demo": "tablesdb\/create-integer-column.md", @@ -35166,7 +36075,7 @@ "x-appwrite": { "method": "updateIntegerColumn", "group": "columns", - "weight": 400, + "weight": 406, "cookies": false, "type": "", "demo": "tablesdb\/update-integer-column.md", @@ -35289,7 +36198,7 @@ "x-appwrite": { "method": "createIpColumn", "group": "columns", - "weight": 401, + "weight": 407, "cookies": false, "type": "", "demo": "tablesdb\/create-ip-column.md", @@ -35398,7 +36307,7 @@ "x-appwrite": { "method": "updateIpColumn", "group": "columns", - "weight": 402, + "weight": 408, "cookies": false, "type": "", "demo": "tablesdb\/update-ip-column.md", @@ -35509,7 +36418,7 @@ "x-appwrite": { "method": "createLineColumn", "group": "columns", - "weight": 403, + "weight": 409, "cookies": false, "type": "", "demo": "tablesdb\/create-line-column.md", @@ -35613,7 +36522,7 @@ "x-appwrite": { "method": "updateLineColumn", "group": "columns", - "weight": 404, + "weight": 410, "cookies": false, "type": "", "demo": "tablesdb\/update-line-column.md", @@ -35723,7 +36632,7 @@ "x-appwrite": { "method": "createPointColumn", "group": "columns", - "weight": 405, + "weight": 411, "cookies": false, "type": "", "demo": "tablesdb\/create-point-column.md", @@ -35827,7 +36736,7 @@ "x-appwrite": { "method": "updatePointColumn", "group": "columns", - "weight": 406, + "weight": 412, "cookies": false, "type": "", "demo": "tablesdb\/update-point-column.md", @@ -35937,7 +36846,7 @@ "x-appwrite": { "method": "createPolygonColumn", "group": "columns", - "weight": 407, + "weight": 413, "cookies": false, "type": "", "demo": "tablesdb\/create-polygon-column.md", @@ -36041,7 +36950,7 @@ "x-appwrite": { "method": "updatePolygonColumn", "group": "columns", - "weight": 408, + "weight": 414, "cookies": false, "type": "", "demo": "tablesdb\/update-polygon-column.md", @@ -36151,7 +37060,7 @@ "x-appwrite": { "method": "createRelationshipColumn", "group": "columns", - "weight": 409, + "weight": 415, "cookies": false, "type": "", "demo": "tablesdb\/create-relationship-column.md", @@ -36287,7 +37196,7 @@ "x-appwrite": { "method": "createStringColumn", "group": "columns", - "weight": 411, + "weight": 417, "cookies": false, "type": "", "demo": "tablesdb\/create-string-column.md", @@ -36409,7 +37318,7 @@ "x-appwrite": { "method": "updateStringColumn", "group": "columns", - "weight": 412, + "weight": 418, "cookies": false, "type": "", "demo": "tablesdb\/update-string-column.md", @@ -36526,7 +37435,7 @@ "x-appwrite": { "method": "createUrlColumn", "group": "columns", - "weight": 413, + "weight": 419, "cookies": false, "type": "", "demo": "tablesdb\/create-url-column.md", @@ -36635,7 +37544,7 @@ "x-appwrite": { "method": "updateUrlColumn", "group": "columns", - "weight": 414, + "weight": 420, "cookies": false, "type": "", "demo": "tablesdb\/update-url-column.md", @@ -36775,7 +37684,7 @@ "x-appwrite": { "method": "getColumn", "group": "columns", - "weight": 386, + "weight": 392, "cookies": false, "type": "", "demo": "tablesdb\/get-column.md", @@ -36847,7 +37756,7 @@ "x-appwrite": { "method": "deleteColumn", "group": "columns", - "weight": 387, + "weight": 393, "cookies": false, "type": "", "demo": "tablesdb\/delete-column.md", @@ -36926,7 +37835,7 @@ "x-appwrite": { "method": "updateRelationshipColumn", "group": "columns", - "weight": 410, + "weight": 416, "cookies": false, "type": "", "demo": "tablesdb\/update-relationship-column.md", @@ -37031,7 +37940,7 @@ "x-appwrite": { "method": "listIndexes", "group": "indexes", - "weight": 418, + "weight": 424, "cookies": false, "type": "", "demo": "tablesdb\/list-indexes.md", @@ -37113,7 +38022,7 @@ "x-appwrite": { "method": "createIndex", "group": "indexes", - "weight": 415, + "weight": 421, "cookies": false, "type": "", "demo": "tablesdb\/create-index.md", @@ -37244,7 +38153,7 @@ "x-appwrite": { "method": "getIndex", "group": "indexes", - "weight": 416, + "weight": 422, "cookies": false, "type": "", "demo": "tablesdb\/get-index.md", @@ -37316,7 +38225,7 @@ "x-appwrite": { "method": "deleteIndex", "group": "indexes", - "weight": 417, + "weight": 423, "cookies": false, "type": "", "demo": "tablesdb\/delete-index.md", @@ -37393,7 +38302,7 @@ "x-appwrite": { "method": "listTableLogs", "group": "tables", - "weight": 384, + "weight": 390, "cookies": false, "type": "", "demo": "tablesdb\/list-table-logs.md", @@ -37474,7 +38383,7 @@ "x-appwrite": { "method": "listRows", "group": "rows", - "weight": 427, + "weight": 433, "cookies": false, "type": "", "demo": "tablesdb\/list-rows.md", @@ -37530,6 +38439,14 @@ }, "default": [], "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "type": "string", + "x-example": "", + "in": "query" } ] }, @@ -37558,7 +38475,7 @@ "x-appwrite": { "method": "createRow", "group": "rows", - "weight": 419, + "weight": 425, "cookies": false, "type": "", "demo": "tablesdb\/create-row.md", @@ -37588,7 +38505,8 @@ "tableId", "rowId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -37615,7 +38533,8 @@ "parameters": [ "databaseId", "tableId", - "rows" + "rows", + "transactionId" ], "required": [ "databaseId", @@ -37695,6 +38614,12 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -37726,7 +38651,7 @@ "x-appwrite": { "method": "upsertRows", "group": "rows", - "weight": 424, + "weight": 430, "cookies": false, "type": "", "demo": "tablesdb\/upsert-rows.md", @@ -37754,7 +38679,8 @@ "parameters": [ "databaseId", "tableId", - "rows" + "rows", + "transactionId" ], "required": [ "databaseId", @@ -37812,6 +38738,12 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } }, "required": [ @@ -37846,7 +38778,7 @@ "x-appwrite": { "method": "updateRows", "group": "rows", - "weight": 422, + "weight": 428, "cookies": false, "type": "", "demo": "tablesdb\/update-rows.md", @@ -37910,6 +38842,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -37941,7 +38879,7 @@ "x-appwrite": { "method": "deleteRows", "group": "rows", - "weight": 426, + "weight": 432, "cookies": false, "type": "", "demo": "tablesdb\/delete-rows.md", @@ -37999,6 +38937,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -38030,7 +38974,7 @@ "x-appwrite": { "method": "getRow", "group": "rows", - "weight": 420, + "weight": 426, "cookies": false, "type": "", "demo": "tablesdb\/get-row.md", @@ -38094,6 +39038,14 @@ }, "default": [], "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "type": "string", + "x-example": "", + "in": "query" } ] }, @@ -38122,7 +39074,7 @@ "x-appwrite": { "method": "upsertRow", "group": "rows", - "weight": 423, + "weight": 429, "cookies": false, "type": "", "demo": "tablesdb\/upsert-row.md", @@ -38152,7 +39104,8 @@ "tableId", "rowId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -38225,6 +39178,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -38256,7 +39215,7 @@ "x-appwrite": { "method": "updateRow", "group": "rows", - "weight": 421, + "weight": 427, "cookies": false, "type": "", "demo": "tablesdb\/update-row.md", @@ -38329,6 +39288,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -38355,7 +39320,7 @@ "x-appwrite": { "method": "deleteRow", "group": "rows", - "weight": 425, + "weight": 431, "cookies": false, "type": "", "demo": "tablesdb\/delete-row.md", @@ -38407,6 +39372,21 @@ "type": "string", "x-example": "", "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" + } + } + } } ] } @@ -38435,7 +39415,7 @@ "x-appwrite": { "method": "listRowLogs", "group": "logs", - "weight": 428, + "weight": 434, "cookies": false, "type": "", "demo": "tablesdb\/list-row-logs.md", @@ -38526,7 +39506,7 @@ "x-appwrite": { "method": "decrementRowColumn", "group": "rows", - "weight": 430, + "weight": 436, "cookies": false, "type": "", "demo": "tablesdb\/decrement-row-column.md", @@ -38604,6 +39584,12 @@ "description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -38637,7 +39623,7 @@ "x-appwrite": { "method": "incrementRowColumn", "group": "rows", - "weight": 429, + "weight": 435, "cookies": false, "type": "", "demo": "tablesdb\/increment-row-column.md", @@ -38715,6 +39701,12 @@ "description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -38746,7 +39738,7 @@ "x-appwrite": { "method": "getTableUsage", "group": null, - "weight": 385, + "weight": 391, "cookies": false, "type": "", "demo": "tablesdb\/get-table-usage.md", @@ -38835,7 +39827,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 377, + "weight": 383, "cookies": false, "type": "", "demo": "tablesdb\/get-usage.md", @@ -40020,7 +41012,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 507, + "weight": 519, "cookies": false, "type": "", "demo": "tokens\/list.md", @@ -40100,7 +41092,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 505, + "weight": 517, "cookies": false, "type": "", "demo": "tokens\/create-file-token.md", @@ -40184,7 +41176,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 506, + "weight": 518, "cookies": false, "type": "", "demo": "tokens\/get.md", @@ -40244,7 +41236,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 508, + "weight": 520, "cookies": false, "type": "", "demo": "tokens\/update.md", @@ -40315,7 +41307,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 509, + "weight": 521, "cookies": false, "type": "", "demo": "tokens\/delete.md", @@ -46144,6 +47136,35 @@ "targets": "" } }, + "transactionList": { + "description": "Transaction List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of transactions that matched your query.", + "x-example": 5, + "format": "int32" + }, + "transactions": { + "type": "array", + "description": "List of transactions.", + "items": { + "type": "object", + "$ref": "#\/definitions\/transaction" + }, + "x-example": "" + } + }, + "required": [ + "total", + "transactions" + ], + "example": { + "total": 5, + "transactions": "" + } + }, "migrationList": { "description": "Migrations List", "type": "object", @@ -56939,6 +57960,59 @@ "subscribe": "users" } }, + "transaction": { + "description": "Transaction", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Transaction ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Transaction creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Transaction update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "status": { + "type": "string", + "description": "Current status of the transaction. One of: pending, committing, committed, rolled_back, failed.", + "x-example": "pending" + }, + "operations": { + "type": "integer", + "description": "Number of operations in the transaction.", + "x-example": 5, + "format": "int32" + }, + "expiresAt": { + "type": "string", + "description": "Expiration time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "status", + "operations", + "expiresAt" + ], + "example": { + "$id": "259125845563242502", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "status": "pending", + "operations": 5, + "expiresAt": "2020-10-15T06:38:00.000+00:00" + } + }, "subscriber": { "description": "Subscriber", "type": "object", diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 05ad0562a5..9c8ef73243 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -5001,6 +5001,431 @@ ] } }, + "\/databases\/transactions": { + "get": { + "summary": "List transactions", + "operationId": "databasesListTransactions", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "List transactions across all databases.", + "responses": { + "200": { + "description": "Transaction List", + "schema": { + "$ref": "#\/definitions\/transactionList" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "listTransactions", + "group": "transactions", + "weight": 376, + "cookies": false, + "type": "", + "demo": "databases\/list-transactions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-transactions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries).", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "post": { + "summary": "Create transaction", + "operationId": "databasesCreateTransaction", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create a new transaction.", + "responses": { + "201": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createTransaction", + "group": "transactions", + "weight": 372, + "cookies": false, + "type": "", + "demo": "databases\/create-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "ttl": { + "type": "integer", + "description": "Seconds before the transaction expires.", + "default": 300, + "x-example": 60 + } + } + } + } + ] + } + }, + "\/databases\/transactions\/{transactionId}": { + "get": { + "summary": "Get transaction", + "operationId": "databasesGetTransaction", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get a transaction by its unique ID.", + "responses": { + "200": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "getTransaction", + "group": "transactions", + "weight": 373, + "cookies": false, + "type": "", + "demo": "databases\/get-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update transaction", + "operationId": "databasesUpdateTransaction", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update a transaction, to either commit or roll back its operations.", + "responses": { + "200": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateTransaction", + "group": "transactions", + "weight": 374, + "cookies": false, + "type": "", + "demo": "databases\/update-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "commit": { + "type": "boolean", + "description": "Commit transaction?", + "default": false, + "x-example": false + }, + "rollback": { + "type": "boolean", + "description": "Rollback transaction?", + "default": false, + "x-example": false + } + } + } + } + ] + }, + "delete": { + "summary": "Delete transaction", + "operationId": "databasesDeleteTransaction", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "databases" + ], + "description": "Delete a transaction by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "deprecated": false, + "x-appwrite": { + "method": "deleteTransaction", + "group": "transactions", + "weight": 375, + "cookies": false, + "type": "", + "demo": "databases\/delete-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + } + }, + "\/databases\/transactions\/{transactionId}\/operations": { + "post": { + "summary": "Create operations", + "operationId": "databasesCreateOperations", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create multiple operations in a single transaction.", + "responses": { + "201": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createOperations", + "group": "transactions", + "weight": 377, + "cookies": false, + "type": "", + "demo": "databases\/create-operations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-operations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "operations": { + "type": "array", + "description": "Array of staged operations.", + "default": [], + "x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"\",\n\t \"collectionId\": \"\",\n\t \"documentId\": \"\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]", + "items": { + "type": "object" + } + } + } + } + } + ] + } + }, "\/databases\/{databaseId}": { "get": { "summary": "Get database", @@ -9101,6 +9526,14 @@ }, "default": [], "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "type": "string", + "x-example": "", + "in": "query" } ] }, @@ -9161,7 +9594,8 @@ "collectionId", "documentId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -9193,7 +9627,8 @@ "parameters": [ "databaseId", "collectionId", - "documents" + "documents", + "transactionId" ], "required": [ "databaseId", @@ -9279,6 +9714,12 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -9340,7 +9781,8 @@ "parameters": [ "databaseId", "collectionId", - "documents" + "documents", + "transactionId" ], "required": [ "databaseId", @@ -9403,6 +9845,12 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } }, "required": [ @@ -9503,6 +9951,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -9594,6 +10048,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -9692,6 +10152,14 @@ }, "default": [], "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "type": "string", + "x-example": "", + "in": "query" } ] }, @@ -9752,7 +10220,8 @@ "collectionId", "documentId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -9832,6 +10301,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } }, "required": [ @@ -9942,6 +10417,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -10023,6 +10504,21 @@ "type": "string", "x-example": "", "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" + } + } + } } ] } @@ -10134,6 +10630,12 @@ "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -10248,6 +10750,12 @@ "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -10483,7 +10991,7 @@ "tags": [ "databases" ], - "description": "Get index by ID.", + "description": "Get an index by its unique ID.", "responses": { "200": { "description": "Index", @@ -10649,7 +11157,7 @@ "x-appwrite": { "method": "list", "group": "functions", - "weight": 440, + "weight": 452, "cookies": false, "type": "", "demo": "functions\/list.md", @@ -10722,7 +11230,7 @@ "x-appwrite": { "method": "create", "group": "functions", - "weight": 437, + "weight": 449, "cookies": false, "type": "", "demo": "functions\/create.md", @@ -10974,7 +11482,7 @@ "x-appwrite": { "method": "listRuntimes", "group": "runtimes", - "weight": 442, + "weight": 454, "cookies": false, "type": "", "demo": "functions\/list-runtimes.md", @@ -11024,7 +11532,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "runtimes", - "weight": 443, + "weight": 455, "cookies": false, "type": "", "demo": "functions\/list-specifications.md", @@ -11075,7 +11583,7 @@ "x-appwrite": { "method": "get", "group": "functions", - "weight": 438, + "weight": 450, "cookies": false, "type": "", "demo": "functions\/get.md", @@ -11135,7 +11643,7 @@ "x-appwrite": { "method": "update", "group": "functions", - "weight": 439, + "weight": 451, "cookies": false, "type": "", "demo": "functions\/update.md", @@ -11383,7 +11891,7 @@ "x-appwrite": { "method": "delete", "group": "functions", - "weight": 441, + "weight": 453, "cookies": false, "type": "", "demo": "functions\/delete.md", @@ -11445,7 +11953,7 @@ "x-appwrite": { "method": "updateFunctionDeployment", "group": "functions", - "weight": 446, + "weight": 458, "cookies": false, "type": "", "demo": "functions\/update-function-deployment.md", @@ -11523,7 +12031,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 447, + "weight": 459, "cookies": false, "type": "", "demo": "functions\/list-deployments.md", @@ -11604,7 +12112,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 444, + "weight": 456, "cookies": false, "type": "upload", "demo": "functions\/create-deployment.md", @@ -11697,7 +12205,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 452, + "weight": 464, "cookies": false, "type": "", "demo": "functions\/create-duplicate-deployment.md", @@ -11783,7 +12291,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 449, + "weight": 461, "cookies": false, "type": "", "demo": "functions\/create-template-deployment.md", @@ -11890,7 +12398,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 450, + "weight": 462, "cookies": false, "type": "", "demo": "functions\/create-vcs-deployment.md", @@ -11987,7 +12495,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 445, + "weight": 457, "cookies": false, "type": "", "demo": "functions\/get-deployment.md", @@ -12050,7 +12558,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 448, + "weight": 460, "cookies": false, "type": "", "demo": "functions\/delete-deployment.md", @@ -12118,7 +12626,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 451, + "weight": 463, "cookies": false, "type": "location", "demo": "functions\/get-deployment-download.md", @@ -12204,7 +12712,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 453, + "weight": 465, "cookies": false, "type": "", "demo": "functions\/update-deployment-status.md", @@ -12272,7 +12780,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 456, + "weight": 468, "cookies": false, "type": "", "demo": "functions\/list-executions.md", @@ -12347,7 +12855,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 454, + "weight": 466, "cookies": false, "type": "", "demo": "functions\/create-execution.md", @@ -12466,7 +12974,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 455, + "weight": 467, "cookies": false, "type": "", "demo": "functions\/get-execution.md", @@ -12532,7 +13040,7 @@ "x-appwrite": { "method": "deleteExecution", "group": "executions", - "weight": 457, + "weight": 469, "cookies": false, "type": "", "demo": "functions\/delete-execution.md", @@ -12600,7 +13108,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 462, + "weight": 474, "cookies": false, "type": "", "demo": "functions\/list-variables.md", @@ -12660,7 +13168,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 460, + "weight": 472, "cookies": false, "type": "", "demo": "functions\/create-variable.md", @@ -12751,7 +13259,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 461, + "weight": 473, "cookies": false, "type": "", "demo": "functions\/get-variable.md", @@ -12819,7 +13327,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 463, + "weight": 475, "cookies": false, "type": "", "demo": "functions\/update-variable.md", @@ -12912,7 +13420,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 464, + "weight": 476, "cookies": false, "type": "", "demo": "functions\/delete-variable.md", @@ -15323,7 +15831,7 @@ "type": "string", "description": "Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as :.", "default": "", - "x-example": "[ID1:ID2]" + "x-example": "" }, "icon": { "type": "string", @@ -15521,7 +16029,7 @@ "type": "string", "description": "Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as :.", "default": null, - "x-example": "[ID1:ID2]" + "x-example": "" }, "icon": { "type": "string", @@ -20017,7 +20525,7 @@ "x-appwrite": { "method": "list", "group": "sites", - "weight": 469, + "weight": 481, "cookies": false, "type": "", "demo": "sites\/list.md", @@ -20090,7 +20598,7 @@ "x-appwrite": { "method": "create", "group": "sites", - "weight": 467, + "weight": 479, "cookies": false, "type": "", "demo": "sites\/create.md", @@ -20358,7 +20866,7 @@ "x-appwrite": { "method": "listFrameworks", "group": "frameworks", - "weight": 472, + "weight": 484, "cookies": false, "type": "", "demo": "sites\/list-frameworks.md", @@ -20408,7 +20916,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 495, + "weight": 507, "cookies": false, "type": "", "demo": "sites\/list-specifications.md", @@ -20459,7 +20967,7 @@ "x-appwrite": { "method": "get", "group": "sites", - "weight": 468, + "weight": 480, "cookies": false, "type": "", "demo": "sites\/get.md", @@ -20519,7 +21027,7 @@ "x-appwrite": { "method": "update", "group": "sites", - "weight": 470, + "weight": 482, "cookies": false, "type": "", "demo": "sites\/update.md", @@ -20782,7 +21290,7 @@ "x-appwrite": { "method": "delete", "group": "sites", - "weight": 471, + "weight": 483, "cookies": false, "type": "", "demo": "sites\/delete.md", @@ -20844,7 +21352,7 @@ "x-appwrite": { "method": "updateSiteDeployment", "group": "sites", - "weight": 478, + "weight": 490, "cookies": false, "type": "", "demo": "sites\/update-site-deployment.md", @@ -20922,7 +21430,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 477, + "weight": 489, "cookies": false, "type": "", "demo": "sites\/list-deployments.md", @@ -21003,7 +21511,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 473, + "weight": 485, "cookies": false, "type": "upload", "demo": "sites\/create-deployment.md", @@ -21104,7 +21612,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 481, + "weight": 493, "cookies": false, "type": "", "demo": "sites\/create-duplicate-deployment.md", @@ -21184,7 +21692,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 474, + "weight": 486, "cookies": false, "type": "", "demo": "sites\/create-template-deployment.md", @@ -21291,7 +21799,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 475, + "weight": 487, "cookies": false, "type": "", "demo": "sites\/create-vcs-deployment.md", @@ -21389,7 +21897,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 476, + "weight": 488, "cookies": false, "type": "", "demo": "sites\/get-deployment.md", @@ -21452,7 +21960,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 479, + "weight": 491, "cookies": false, "type": "", "demo": "sites\/delete-deployment.md", @@ -21520,7 +22028,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 480, + "weight": 492, "cookies": false, "type": "location", "demo": "sites\/get-deployment-download.md", @@ -21606,7 +22114,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 482, + "weight": 494, "cookies": false, "type": "", "demo": "sites\/update-deployment-status.md", @@ -21674,7 +22182,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 484, + "weight": 496, "cookies": false, "type": "", "demo": "sites\/list-logs.md", @@ -21746,7 +22254,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 483, + "weight": 495, "cookies": false, "type": "", "demo": "sites\/get-log.md", @@ -21811,7 +22319,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 485, + "weight": 497, "cookies": false, "type": "", "demo": "sites\/delete-log.md", @@ -21879,7 +22387,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 488, + "weight": 500, "cookies": false, "type": "", "demo": "sites\/list-variables.md", @@ -21939,7 +22447,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 486, + "weight": 498, "cookies": false, "type": "", "demo": "sites\/create-variable.md", @@ -22030,7 +22538,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 487, + "weight": 499, "cookies": false, "type": "", "demo": "sites\/get-variable.md", @@ -22098,7 +22606,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 489, + "weight": 501, "cookies": false, "type": "", "demo": "sites\/update-variable.md", @@ -22191,7 +22699,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 490, + "weight": 502, "cookies": false, "type": "", "demo": "sites\/delete-variable.md", @@ -23499,7 +24007,7 @@ "x-appwrite": { "method": "list", "group": "tablesdb", - "weight": 376, + "weight": 382, "cookies": false, "type": "", "demo": "tablesdb\/list.md", @@ -23572,7 +24080,7 @@ "x-appwrite": { "method": "create", "group": "tablesdb", - "weight": 372, + "weight": 378, "cookies": false, "type": "", "demo": "tablesdb\/create.md", @@ -23631,6 +24139,431 @@ ] } }, + "\/tablesdb\/transactions": { + "get": { + "summary": "List transactions", + "operationId": "tablesDBListTransactions", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "List transactions across all databases.", + "responses": { + "200": { + "description": "Transaction List", + "schema": { + "$ref": "#\/definitions\/transactionList" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "listTransactions", + "group": "transactions", + "weight": 441, + "cookies": false, + "type": "", + "demo": "tablesdb\/list-transactions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/list-transactions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries).", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "post": { + "summary": "Create transaction", + "operationId": "tablesDBCreateTransaction", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "Create a new transaction.", + "responses": { + "201": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createTransaction", + "group": "transactions", + "weight": 437, + "cookies": false, + "type": "", + "demo": "tablesdb\/create-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/create-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "ttl": { + "type": "integer", + "description": "Seconds before the transaction expires.", + "default": 300, + "x-example": 60 + } + } + } + } + ] + } + }, + "\/tablesdb\/transactions\/{transactionId}": { + "get": { + "summary": "Get transaction", + "operationId": "tablesDBGetTransaction", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "Get a transaction by its unique ID.", + "responses": { + "200": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "getTransaction", + "group": "transactions", + "weight": 438, + "cookies": false, + "type": "", + "demo": "tablesdb\/get-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/get-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.read", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update transaction", + "operationId": "tablesDBUpdateTransaction", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "Update a transaction, to either commit or roll back its operations.", + "responses": { + "200": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "updateTransaction", + "group": "transactions", + "weight": 439, + "cookies": false, + "type": "", + "demo": "tablesdb\/update-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/update-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "commit": { + "type": "boolean", + "description": "Commit transaction?", + "default": false, + "x-example": false + }, + "rollback": { + "type": "boolean", + "description": "Rollback transaction?", + "default": false, + "x-example": false + } + } + } + } + ] + }, + "delete": { + "summary": "Delete transaction", + "operationId": "tablesDBDeleteTransaction", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "tablesDB" + ], + "description": "Delete a transaction by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "deprecated": false, + "x-appwrite": { + "method": "deleteTransaction", + "group": "transactions", + "weight": 440, + "cookies": false, + "type": "", + "demo": "tablesdb\/delete-transaction.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/delete-transaction.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + } + ] + } + }, + "\/tablesdb\/transactions\/{transactionId}\/operations": { + "post": { + "summary": "Create operations", + "operationId": "tablesDBCreateOperations", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "tablesDB" + ], + "description": "Create multiple operations in a single transaction.", + "responses": { + "201": { + "description": "Transaction", + "schema": { + "$ref": "#\/definitions\/transaction" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createOperations", + "group": "transactions", + "weight": 442, + "cookies": false, + "type": "", + "demo": "tablesdb\/create-operations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/tablesdb\/create-operations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rows.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "transactionId", + "description": "Transaction ID.", + "required": true, + "type": "string", + "x-example": "", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "operations": { + "type": "array", + "description": "Array of staged operations.", + "default": [], + "x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"\",\n\t \"tableId\": \"\",\n\t \"rowId\": \"\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]", + "items": { + "type": "object" + } + } + } + } + } + ] + } + }, "\/tablesdb\/{databaseId}": { "get": { "summary": "Get database", @@ -23655,7 +24588,7 @@ "x-appwrite": { "method": "get", "group": "tablesdb", - "weight": 373, + "weight": 379, "cookies": false, "type": "", "demo": "tablesdb\/get.md", @@ -23715,7 +24648,7 @@ "x-appwrite": { "method": "update", "group": "tablesdb", - "weight": 374, + "weight": 380, "cookies": false, "type": "", "demo": "tablesdb\/update.md", @@ -23794,7 +24727,7 @@ "x-appwrite": { "method": "delete", "group": "tablesdb", - "weight": 375, + "weight": 381, "cookies": false, "type": "", "demo": "tablesdb\/delete.md", @@ -23854,7 +24787,7 @@ "x-appwrite": { "method": "listTables", "group": "tables", - "weight": 383, + "weight": 389, "cookies": false, "type": "", "demo": "tablesdb\/list-tables.md", @@ -23938,7 +24871,7 @@ "x-appwrite": { "method": "createTable", "group": "tables", - "weight": 379, + "weight": 385, "cookies": false, "type": "", "demo": "tablesdb\/create-table.md", @@ -24047,7 +24980,7 @@ "x-appwrite": { "method": "getTable", "group": "tables", - "weight": 380, + "weight": 386, "cookies": false, "type": "", "demo": "tablesdb\/get-table.md", @@ -24118,7 +25051,7 @@ "x-appwrite": { "method": "updateTable", "group": "tables", - "weight": 381, + "weight": 387, "cookies": false, "type": "", "demo": "tablesdb\/update-table.md", @@ -24223,7 +25156,7 @@ "x-appwrite": { "method": "deleteTable", "group": "tables", - "weight": 382, + "weight": 388, "cookies": false, "type": "", "demo": "tablesdb\/delete-table.md", @@ -24294,7 +25227,7 @@ "x-appwrite": { "method": "listColumns", "group": "columns", - "weight": 388, + "weight": 394, "cookies": false, "type": "", "demo": "tablesdb\/list-columns.md", @@ -24379,7 +25312,7 @@ "x-appwrite": { "method": "createBooleanColumn", "group": "columns", - "weight": 389, + "weight": 395, "cookies": false, "type": "", "demo": "tablesdb\/create-boolean-column.md", @@ -24489,7 +25422,7 @@ "x-appwrite": { "method": "updateBooleanColumn", "group": "columns", - "weight": 390, + "weight": 396, "cookies": false, "type": "", "demo": "tablesdb\/update-boolean-column.md", @@ -24601,7 +25534,7 @@ "x-appwrite": { "method": "createDatetimeColumn", "group": "columns", - "weight": 391, + "weight": 397, "cookies": false, "type": "", "demo": "tablesdb\/create-datetime-column.md", @@ -24711,7 +25644,7 @@ "x-appwrite": { "method": "updateDatetimeColumn", "group": "columns", - "weight": 392, + "weight": 398, "cookies": false, "type": "", "demo": "tablesdb\/update-datetime-column.md", @@ -24823,7 +25756,7 @@ "x-appwrite": { "method": "createEmailColumn", "group": "columns", - "weight": 393, + "weight": 399, "cookies": false, "type": "", "demo": "tablesdb\/create-email-column.md", @@ -24933,7 +25866,7 @@ "x-appwrite": { "method": "updateEmailColumn", "group": "columns", - "weight": 394, + "weight": 400, "cookies": false, "type": "", "demo": "tablesdb\/update-email-column.md", @@ -25045,7 +25978,7 @@ "x-appwrite": { "method": "createEnumColumn", "group": "columns", - "weight": 395, + "weight": 401, "cookies": false, "type": "", "demo": "tablesdb\/create-enum-column.md", @@ -25165,7 +26098,7 @@ "x-appwrite": { "method": "updateEnumColumn", "group": "columns", - "weight": 396, + "weight": 402, "cookies": false, "type": "", "demo": "tablesdb\/update-enum-column.md", @@ -25287,7 +26220,7 @@ "x-appwrite": { "method": "createFloatColumn", "group": "columns", - "weight": 397, + "weight": 403, "cookies": false, "type": "", "demo": "tablesdb\/create-float-column.md", @@ -25409,7 +26342,7 @@ "x-appwrite": { "method": "updateFloatColumn", "group": "columns", - "weight": 398, + "weight": 404, "cookies": false, "type": "", "demo": "tablesdb\/update-float-column.md", @@ -25533,7 +26466,7 @@ "x-appwrite": { "method": "createIntegerColumn", "group": "columns", - "weight": 399, + "weight": 405, "cookies": false, "type": "", "demo": "tablesdb\/create-integer-column.md", @@ -25655,7 +26588,7 @@ "x-appwrite": { "method": "updateIntegerColumn", "group": "columns", - "weight": 400, + "weight": 406, "cookies": false, "type": "", "demo": "tablesdb\/update-integer-column.md", @@ -25779,7 +26712,7 @@ "x-appwrite": { "method": "createIpColumn", "group": "columns", - "weight": 401, + "weight": 407, "cookies": false, "type": "", "demo": "tablesdb\/create-ip-column.md", @@ -25889,7 +26822,7 @@ "x-appwrite": { "method": "updateIpColumn", "group": "columns", - "weight": 402, + "weight": 408, "cookies": false, "type": "", "demo": "tablesdb\/update-ip-column.md", @@ -26001,7 +26934,7 @@ "x-appwrite": { "method": "createLineColumn", "group": "columns", - "weight": 403, + "weight": 409, "cookies": false, "type": "", "demo": "tablesdb\/create-line-column.md", @@ -26106,7 +27039,7 @@ "x-appwrite": { "method": "updateLineColumn", "group": "columns", - "weight": 404, + "weight": 410, "cookies": false, "type": "", "demo": "tablesdb\/update-line-column.md", @@ -26217,7 +27150,7 @@ "x-appwrite": { "method": "createPointColumn", "group": "columns", - "weight": 405, + "weight": 411, "cookies": false, "type": "", "demo": "tablesdb\/create-point-column.md", @@ -26322,7 +27255,7 @@ "x-appwrite": { "method": "updatePointColumn", "group": "columns", - "weight": 406, + "weight": 412, "cookies": false, "type": "", "demo": "tablesdb\/update-point-column.md", @@ -26433,7 +27366,7 @@ "x-appwrite": { "method": "createPolygonColumn", "group": "columns", - "weight": 407, + "weight": 413, "cookies": false, "type": "", "demo": "tablesdb\/create-polygon-column.md", @@ -26538,7 +27471,7 @@ "x-appwrite": { "method": "updatePolygonColumn", "group": "columns", - "weight": 408, + "weight": 414, "cookies": false, "type": "", "demo": "tablesdb\/update-polygon-column.md", @@ -26649,7 +27582,7 @@ "x-appwrite": { "method": "createRelationshipColumn", "group": "columns", - "weight": 409, + "weight": 415, "cookies": false, "type": "", "demo": "tablesdb\/create-relationship-column.md", @@ -26786,7 +27719,7 @@ "x-appwrite": { "method": "createStringColumn", "group": "columns", - "weight": 411, + "weight": 417, "cookies": false, "type": "", "demo": "tablesdb\/create-string-column.md", @@ -26909,7 +27842,7 @@ "x-appwrite": { "method": "updateStringColumn", "group": "columns", - "weight": 412, + "weight": 418, "cookies": false, "type": "", "demo": "tablesdb\/update-string-column.md", @@ -27027,7 +27960,7 @@ "x-appwrite": { "method": "createUrlColumn", "group": "columns", - "weight": 413, + "weight": 419, "cookies": false, "type": "", "demo": "tablesdb\/create-url-column.md", @@ -27137,7 +28070,7 @@ "x-appwrite": { "method": "updateUrlColumn", "group": "columns", - "weight": 414, + "weight": 420, "cookies": false, "type": "", "demo": "tablesdb\/update-url-column.md", @@ -27278,7 +28211,7 @@ "x-appwrite": { "method": "getColumn", "group": "columns", - "weight": 386, + "weight": 392, "cookies": false, "type": "", "demo": "tablesdb\/get-column.md", @@ -27351,7 +28284,7 @@ "x-appwrite": { "method": "deleteColumn", "group": "columns", - "weight": 387, + "weight": 393, "cookies": false, "type": "", "demo": "tablesdb\/delete-column.md", @@ -27431,7 +28364,7 @@ "x-appwrite": { "method": "updateRelationshipColumn", "group": "columns", - "weight": 410, + "weight": 416, "cookies": false, "type": "", "demo": "tablesdb\/update-relationship-column.md", @@ -27537,7 +28470,7 @@ "x-appwrite": { "method": "listIndexes", "group": "indexes", - "weight": 418, + "weight": 424, "cookies": false, "type": "", "demo": "tablesdb\/list-indexes.md", @@ -27620,7 +28553,7 @@ "x-appwrite": { "method": "createIndex", "group": "indexes", - "weight": 415, + "weight": 421, "cookies": false, "type": "", "demo": "tablesdb\/create-index.md", @@ -27752,7 +28685,7 @@ "x-appwrite": { "method": "getIndex", "group": "indexes", - "weight": 416, + "weight": 422, "cookies": false, "type": "", "demo": "tablesdb\/get-index.md", @@ -27825,7 +28758,7 @@ "x-appwrite": { "method": "deleteIndex", "group": "indexes", - "weight": 417, + "weight": 423, "cookies": false, "type": "", "demo": "tablesdb\/delete-index.md", @@ -27903,7 +28836,7 @@ "x-appwrite": { "method": "listRows", "group": "rows", - "weight": 427, + "weight": 433, "cookies": false, "type": "", "demo": "tablesdb\/list-rows.md", @@ -27961,6 +28894,14 @@ }, "default": [], "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "type": "string", + "x-example": "", + "in": "query" } ] }, @@ -27989,7 +28930,7 @@ "x-appwrite": { "method": "createRow", "group": "rows", - "weight": 419, + "weight": 425, "cookies": false, "type": "", "demo": "tablesdb\/create-row.md", @@ -28020,7 +28961,8 @@ "tableId", "rowId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -28048,7 +28990,8 @@ "parameters": [ "databaseId", "tableId", - "rows" + "rows", + "transactionId" ], "required": [ "databaseId", @@ -28130,6 +29073,12 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -28161,7 +29110,7 @@ "x-appwrite": { "method": "upsertRows", "group": "rows", - "weight": 424, + "weight": 430, "cookies": false, "type": "", "demo": "tablesdb\/upsert-rows.md", @@ -28190,7 +29139,8 @@ "parameters": [ "databaseId", "tableId", - "rows" + "rows", + "transactionId" ], "required": [ "databaseId", @@ -28249,6 +29199,12 @@ "items": { "type": "object" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } }, "required": [ @@ -28283,7 +29239,7 @@ "x-appwrite": { "method": "updateRows", "group": "rows", - "weight": 422, + "weight": 428, "cookies": false, "type": "", "demo": "tablesdb\/update-rows.md", @@ -28348,6 +29304,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -28379,7 +29341,7 @@ "x-appwrite": { "method": "deleteRows", "group": "rows", - "weight": 426, + "weight": 432, "cookies": false, "type": "", "demo": "tablesdb\/delete-rows.md", @@ -28438,6 +29400,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -28469,7 +29437,7 @@ "x-appwrite": { "method": "getRow", "group": "rows", - "weight": 420, + "weight": 426, "cookies": false, "type": "", "demo": "tablesdb\/get-row.md", @@ -28535,6 +29503,14 @@ }, "default": [], "in": "query" + }, + { + "name": "transactionId", + "description": "Transaction ID to read uncommitted changes within the transaction.", + "required": false, + "type": "string", + "x-example": "", + "in": "query" } ] }, @@ -28563,7 +29539,7 @@ "x-appwrite": { "method": "upsertRow", "group": "rows", - "weight": 423, + "weight": 429, "cookies": false, "type": "", "demo": "tablesdb\/upsert-row.md", @@ -28594,7 +29570,8 @@ "tableId", "rowId", "data", - "permissions" + "permissions", + "transactionId" ], "required": [ "databaseId", @@ -28669,6 +29646,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -28700,7 +29683,7 @@ "x-appwrite": { "method": "updateRow", "group": "rows", - "weight": 421, + "weight": 427, "cookies": false, "type": "", "demo": "tablesdb\/update-row.md", @@ -28775,6 +29758,12 @@ "items": { "type": "string" } + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -28801,7 +29790,7 @@ "x-appwrite": { "method": "deleteRow", "group": "rows", - "weight": 425, + "weight": 431, "cookies": false, "type": "", "demo": "tablesdb\/delete-row.md", @@ -28855,6 +29844,21 @@ "type": "string", "x-example": "", "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" + } + } + } } ] } @@ -28885,7 +29889,7 @@ "x-appwrite": { "method": "decrementRowColumn", "group": "rows", - "weight": 430, + "weight": 436, "cookies": false, "type": "", "demo": "tablesdb\/decrement-row-column.md", @@ -28965,6 +29969,12 @@ "description": "Minimum value for the column. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -28998,7 +30008,7 @@ "x-appwrite": { "method": "incrementRowColumn", "group": "rows", - "weight": 429, + "weight": 435, "cookies": false, "type": "", "demo": "tablesdb\/increment-row-column.md", @@ -29078,6 +30088,12 @@ "description": "Maximum value for the column. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null + }, + "transactionId": { + "type": "string", + "description": "Transaction ID for staging the operation.", + "default": null, + "x-example": "" } } } @@ -30144,7 +31160,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 507, + "weight": 519, "cookies": false, "type": "", "demo": "tokens\/list.md", @@ -30225,7 +31241,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 505, + "weight": 517, "cookies": false, "type": "", "demo": "tokens\/create-file-token.md", @@ -30310,7 +31326,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 506, + "weight": 518, "cookies": false, "type": "", "demo": "tokens\/get.md", @@ -30371,7 +31387,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 508, + "weight": 520, "cookies": false, "type": "", "demo": "tokens\/update.md", @@ -30443,7 +31459,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 509, + "weight": 521, "cookies": false, "type": "", "demo": "tokens\/delete.md", @@ -35167,6 +36183,35 @@ "targets": "" } }, + "transactionList": { + "description": "Transaction List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of transactions that matched your query.", + "x-example": 5, + "format": "int32" + }, + "transactions": { + "type": "array", + "description": "List of transactions.", + "items": { + "type": "object", + "$ref": "#\/definitions\/transaction" + }, + "x-example": "" + } + }, + "required": [ + "total", + "transactions" + ], + "example": { + "total": 5, + "transactions": "" + } + }, "specificationList": { "description": "Specifications List", "type": "object", @@ -41839,6 +42884,59 @@ "subscribe": "users" } }, + "transaction": { + "description": "Transaction", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Transaction ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Transaction creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Transaction update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "status": { + "type": "string", + "description": "Current status of the transaction. One of: pending, committing, committed, rolled_back, failed.", + "x-example": "pending" + }, + "operations": { + "type": "integer", + "description": "Number of operations in the transaction.", + "x-example": 5, + "format": "int32" + }, + "expiresAt": { + "type": "string", + "description": "Expiration time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "status", + "operations", + "expiresAt" + ], + "example": { + "$id": "259125845563242502", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "status": "pending", + "operations": 5, + "expiresAt": "2020-10-15T06:38:00.000+00:00" + } + }, "subscriber": { "description": "Subscriber", "type": "object", diff --git a/app/controllers/general.php b/app/controllers/general.php index 1dbecd8a8a..43db196dfb 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1253,7 +1253,7 @@ App::error() } /** - * If its not a publishable error, track usage stats. Publishable errors are >= 500 or those explicitly marked as publish=true in errors.php + * If not a publishable error, track usage stats. Publishable errors are >= 500 or those explicitly marked as publish=true in errors.php */ if (!$publish && $project->getId() !== 'console') { if (!Auth::isPrivilegedUser(Authorization::getRoles())) { @@ -1355,6 +1355,7 @@ App::error() case 409: // Error allowed publicly case 412: // Error allowed publicly case 416: // Error allowed publicly + case 422: // Error allowed publicly case 429: // Error allowed publicly case 451: // Error allowed publicly case 501: // Error allowed publicly diff --git a/app/init/constants.php b/app/init/constants.php index f7e3f3fc2d..3163f9d130 100644 --- a/app/init/constants.php +++ b/app/init/constants.php @@ -31,6 +31,7 @@ const APP_LIMIT_WRITE_RATE_DEFAULT = 60; // Default maximum write rate per rate const APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT = 60; // Default maximum write rate period in seconds const APP_LIMIT_LIST_DEFAULT = 25; // Default maximum number of items to return in list API calls const APP_LIMIT_DATABASE_BATCH = 100; // Default maximum batch size for database operations +const APP_LIMIT_DATABASE_TRANSACTION = 100; // Default maximum operations per transaction const APP_KEY_ACCESS = 24 * 60 * 60; // 24 hours const APP_USER_ACCESS = 24 * 60 * 60; // 24 hours const APP_PROJECT_ACCESS = 24 * 60 * 60; // 24 hours @@ -55,6 +56,10 @@ const APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER = 300 * 1000; // 5 minutes const APP_DATABASE_TIMEOUT_MILLISECONDS_TASK = 300 * 1000; // 5 minutes const APP_DATABASE_QUERY_MAX_VALUES = 500; const APP_DATABASE_ENCRYPT_SIZE_MIN = 150; +const APP_DATABASE_TXN_TTL_MIN = 60; // 1 minute +const APP_DATABASE_TXN_TTL_MAX = 3600; // 1 hour +const APP_DATABASE_TXN_TTL_DEFAULT = 300; // 5 minutes +const APP_DATABASE_TXN_MAX_OPERATIONS = 100; // Maximum operations per transaction const APP_STORAGE_UPLOADS = '/storage/uploads'; const APP_STORAGE_SITES = '/storage/sites'; const APP_STORAGE_FUNCTIONS = '/storage/functions'; @@ -105,8 +110,11 @@ const BUILD_TYPE_RETRY = 'retry'; // Deletion Types const DELETE_TYPE_DATABASES = 'databases'; + const DELETE_TYPE_DOCUMENT = 'document'; const DELETE_TYPE_COLLECTIONS = 'collections'; +const DELETE_TYPE_TRANSACTION = 'transaction'; +const DELETE_TYPE_EXPIRED_TRANSACTIONS = 'expired_transactions'; const DELETE_TYPE_PROJECTS = 'projects'; const DELETE_TYPE_SITES = 'sites'; const DELETE_TYPE_FUNCTIONS = 'functions'; diff --git a/app/init/resources.php b/app/init/resources.php index 16307edee3..f91d18f698 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -4,6 +4,7 @@ use Ahc\Jwt\JWT; use Ahc\Jwt\JWTException; use Appwrite\Auth\Auth; use Appwrite\Auth\Key; +use Appwrite\Databases\TransactionState; use Appwrite\Event\Audit; use Appwrite\Event\Build; use Appwrite\Event\Certificate; @@ -1041,3 +1042,7 @@ App::setResource('httpReferrerSafe', function (Request $request, string $httpRef $referrer = (!empty($protocol) ? $protocol : $request->getProtocol()) . '://' . $origin . (!empty($port) ? ':' . $port : ''); return $referrer; }, ['request', 'httpReferrer', 'platforms', 'dbForPlatform', 'project', 'utopia']); + +App::setResource('transactionState', function (Database $dbForProject) { + return new TransactionState($dbForProject); +}, ['dbForProject']); diff --git a/app/realtime.php b/app/realtime.php index fccf5c9a20..e18ab8e10d 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -606,8 +606,8 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $message = $th->getMessage(); - // sanitize 5xx errors - if ($code >= 500 && !App::isDevelopment()) { + // sanitize 0 && 5xx errors + if (($code === 0 || $code >= 500) && !App::isDevelopment()) { $message = 'Error: Server Error'; } @@ -719,8 +719,8 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re $message = $th->getMessage(); - // sanitize 5xx errors - if ($code >= 500 && !App::isDevelopment()) { + // sanitize 0 && 5xx errors + if (($code === 0 || $code >= 500) && !App::isDevelopment()) { $message = 'Error: Server Error'; } diff --git a/composer.lock b/composer.lock index 1afa3f5109..b544b18aab 100644 --- a/composer.lock +++ b/composer.lock @@ -3792,16 +3792,16 @@ }, { "name": "utopia-php/domains", - "version": "0.8.1", + "version": "0.8.2", "source": { "type": "git", "url": "https://github.com/utopia-php/domains.git", - "reference": "d5f903e93c105407da6374e411c4805b7decd8a8" + "reference": "caa294dcebd05c8af876c8afef3e992faccdf645" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/domains/zipball/d5f903e93c105407da6374e411c4805b7decd8a8", - "reference": "d5f903e93c105407da6374e411c4805b7decd8a8", + "url": "https://api.github.com/repos/utopia-php/domains/zipball/caa294dcebd05c8af876c8afef3e992faccdf645", + "reference": "caa294dcebd05c8af876c8afef3e992faccdf645", "shasum": "" }, "require": { @@ -3847,9 +3847,9 @@ ], "support": { "issues": "https://github.com/utopia-php/domains/issues", - "source": "https://github.com/utopia-php/domains/tree/0.8.1" + "source": "https://github.com/utopia-php/domains/tree/0.8.2" }, - "time": "2025-10-03T11:58:53+00:00" + "time": "2025-10-06T09:56:54+00:00" }, { "name": "utopia-php/dsn", @@ -5004,16 +5004,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "1.4.3", + "version": "1.4.4", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "e1ca749398189f36ec6d6afb8e9f64e9cb37e0a3" + "reference": "a20b20cfd70a1879f0d0fb2b4f669aa5ed836c49" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/e1ca749398189f36ec6d6afb8e9f64e9cb37e0a3", - "reference": "e1ca749398189f36ec6d6afb8e9f64e9cb37e0a3", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/a20b20cfd70a1879f0d0fb2b4f669aa5ed836c49", + "reference": "a20b20cfd70a1879f0d0fb2b4f669aa5ed836c49", "shasum": "" }, "require": { @@ -5049,9 +5049,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/1.4.3" + "source": "https://github.com/appwrite/sdk-generator/tree/1.4.4" }, - "time": "2025-10-01T06:25:19+00:00" + "time": "2025-10-13T09:20:49+00:00" }, { "name": "doctrine/annotations", diff --git a/docs/examples/1.8.x/client-android/java/databases/create-document.md b/docs/examples/1.8.x/client-android/java/databases/create-document.md index bd0b57ac4c..694d99a089 100644 --- a/docs/examples/1.8.x/client-android/java/databases/create-document.md +++ b/docs/examples/1.8.x/client-android/java/databases/create-document.md @@ -20,6 +20,7 @@ databases.createDocument( "isAdmin" to false ), // data listOf("read("any")"), // permissions (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/client-android/java/databases/create-operations.md b/docs/examples/1.8.x/client-android/java/databases/create-operations.md new file mode 100644 index 0000000000..def58af773 --- /dev/null +++ b/docs/examples/1.8.x/client-android/java/databases/create-operations.md @@ -0,0 +1,33 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Databases; + +Client client = new Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject(""); // Your project ID + +Databases databases = new Databases(client); + +databases.createOperations( + "", // transactionId + listOf( + { + "action": "create", + "databaseId": "", + "collectionId": "", + "documentId": "", + "data": { + "name": "Walter O'Brien" + } + } + ), // operations (optional) + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + Log.d("Appwrite", result.toString()); + }) +); + diff --git a/docs/examples/1.8.x/client-android/java/databases/create-transaction.md b/docs/examples/1.8.x/client-android/java/databases/create-transaction.md new file mode 100644 index 0000000000..871d1907f6 --- /dev/null +++ b/docs/examples/1.8.x/client-android/java/databases/create-transaction.md @@ -0,0 +1,22 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Databases; + +Client client = new Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject(""); // Your project ID + +Databases databases = new Databases(client); + +databases.createTransaction( + 60, // ttl (optional) + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + Log.d("Appwrite", result.toString()); + }) +); + diff --git a/docs/examples/1.8.x/client-android/java/databases/decrement-document-attribute.md b/docs/examples/1.8.x/client-android/java/databases/decrement-document-attribute.md index de6a4ab48d..8669494532 100644 --- a/docs/examples/1.8.x/client-android/java/databases/decrement-document-attribute.md +++ b/docs/examples/1.8.x/client-android/java/databases/decrement-document-attribute.md @@ -15,6 +15,7 @@ databases.decrementDocumentAttribute( "", // attribute 0, // value (optional) 0, // min (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/client-android/java/databases/delete-document.md b/docs/examples/1.8.x/client-android/java/databases/delete-document.md index 5288e53bed..2795670807 100644 --- a/docs/examples/1.8.x/client-android/java/databases/delete-document.md +++ b/docs/examples/1.8.x/client-android/java/databases/delete-document.md @@ -12,6 +12,7 @@ databases.deleteDocument( "", // databaseId "", // collectionId "", // documentId + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/client-android/java/databases/delete-transaction.md b/docs/examples/1.8.x/client-android/java/databases/delete-transaction.md new file mode 100644 index 0000000000..ac1121e9b9 --- /dev/null +++ b/docs/examples/1.8.x/client-android/java/databases/delete-transaction.md @@ -0,0 +1,22 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Databases; + +Client client = new Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject(""); // Your project ID + +Databases databases = new Databases(client); + +databases.deleteTransaction( + "", // transactionId + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + Log.d("Appwrite", result.toString()); + }) +); + diff --git a/docs/examples/1.8.x/client-android/java/databases/get-document.md b/docs/examples/1.8.x/client-android/java/databases/get-document.md index e7ae2079ed..92d6b5ed23 100644 --- a/docs/examples/1.8.x/client-android/java/databases/get-document.md +++ b/docs/examples/1.8.x/client-android/java/databases/get-document.md @@ -13,6 +13,7 @@ databases.getDocument( "", // collectionId "", // documentId listOf(), // queries (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/client-android/java/databases/get-transaction.md b/docs/examples/1.8.x/client-android/java/databases/get-transaction.md new file mode 100644 index 0000000000..5dee850305 --- /dev/null +++ b/docs/examples/1.8.x/client-android/java/databases/get-transaction.md @@ -0,0 +1,22 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Databases; + +Client client = new Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject(""); // Your project ID + +Databases databases = new Databases(client); + +databases.getTransaction( + "", // transactionId + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + Log.d("Appwrite", result.toString()); + }) +); + diff --git a/docs/examples/1.8.x/client-android/java/databases/increment-document-attribute.md b/docs/examples/1.8.x/client-android/java/databases/increment-document-attribute.md index 94ffa9d749..5928b455c6 100644 --- a/docs/examples/1.8.x/client-android/java/databases/increment-document-attribute.md +++ b/docs/examples/1.8.x/client-android/java/databases/increment-document-attribute.md @@ -15,6 +15,7 @@ databases.incrementDocumentAttribute( "", // attribute 0, // value (optional) 0, // max (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/client-android/java/databases/list-documents.md b/docs/examples/1.8.x/client-android/java/databases/list-documents.md index 606d67705d..7b2ba23453 100644 --- a/docs/examples/1.8.x/client-android/java/databases/list-documents.md +++ b/docs/examples/1.8.x/client-android/java/databases/list-documents.md @@ -12,6 +12,7 @@ databases.listDocuments( "", // databaseId "", // collectionId listOf(), // queries (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/client-android/java/databases/list-transactions.md b/docs/examples/1.8.x/client-android/java/databases/list-transactions.md new file mode 100644 index 0000000000..39f58f3490 --- /dev/null +++ b/docs/examples/1.8.x/client-android/java/databases/list-transactions.md @@ -0,0 +1,22 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Databases; + +Client client = new Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject(""); // Your project ID + +Databases databases = new Databases(client); + +databases.listTransactions( + listOf(), // queries (optional) + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + Log.d("Appwrite", result.toString()); + }) +); + diff --git a/docs/examples/1.8.x/client-android/java/databases/update-document.md b/docs/examples/1.8.x/client-android/java/databases/update-document.md index baa827cdf5..a6103e44d1 100644 --- a/docs/examples/1.8.x/client-android/java/databases/update-document.md +++ b/docs/examples/1.8.x/client-android/java/databases/update-document.md @@ -14,6 +14,7 @@ databases.updateDocument( "", // documentId mapOf( "a" to "b" ), // data (optional) listOf("read("any")"), // permissions (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/client-android/java/databases/update-transaction.md b/docs/examples/1.8.x/client-android/java/databases/update-transaction.md new file mode 100644 index 0000000000..c5f586fce3 --- /dev/null +++ b/docs/examples/1.8.x/client-android/java/databases/update-transaction.md @@ -0,0 +1,24 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Databases; + +Client client = new Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject(""); // Your project ID + +Databases databases = new Databases(client); + +databases.updateTransaction( + "", // transactionId + false, // commit (optional) + false, // rollback (optional) + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + Log.d("Appwrite", result.toString()); + }) +); + diff --git a/docs/examples/1.8.x/client-android/java/databases/upsert-document.md b/docs/examples/1.8.x/client-android/java/databases/upsert-document.md index 868576b982..52be46ebe6 100644 --- a/docs/examples/1.8.x/client-android/java/databases/upsert-document.md +++ b/docs/examples/1.8.x/client-android/java/databases/upsert-document.md @@ -14,6 +14,7 @@ databases.upsertDocument( "", // documentId mapOf( "a" to "b" ), // data listOf("read("any")"), // permissions (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/client-android/java/tablesdb/create-operations.md b/docs/examples/1.8.x/client-android/java/tablesdb/create-operations.md new file mode 100644 index 0000000000..7ca288c2ae --- /dev/null +++ b/docs/examples/1.8.x/client-android/java/tablesdb/create-operations.md @@ -0,0 +1,33 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.TablesDB; + +Client client = new Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject(""); // Your project ID + +TablesDB tablesDB = new TablesDB(client); + +tablesDB.createOperations( + "", // transactionId + listOf( + { + "action": "create", + "databaseId": "", + "tableId": "", + "rowId": "", + "data": { + "name": "Walter O'Brien" + } + } + ), // operations (optional) + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + Log.d("Appwrite", result.toString()); + }) +); + diff --git a/docs/examples/1.8.x/client-android/java/tablesdb/create-row.md b/docs/examples/1.8.x/client-android/java/tablesdb/create-row.md index 8273573ddd..92a9058401 100644 --- a/docs/examples/1.8.x/client-android/java/tablesdb/create-row.md +++ b/docs/examples/1.8.x/client-android/java/tablesdb/create-row.md @@ -20,6 +20,7 @@ tablesDB.createRow( "isAdmin" to false ), // data listOf("read("any")"), // permissions (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/client-android/java/tablesdb/create-transaction.md b/docs/examples/1.8.x/client-android/java/tablesdb/create-transaction.md new file mode 100644 index 0000000000..c232c56991 --- /dev/null +++ b/docs/examples/1.8.x/client-android/java/tablesdb/create-transaction.md @@ -0,0 +1,22 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.TablesDB; + +Client client = new Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject(""); // Your project ID + +TablesDB tablesDB = new TablesDB(client); + +tablesDB.createTransaction( + 60, // ttl (optional) + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + Log.d("Appwrite", result.toString()); + }) +); + diff --git a/docs/examples/1.8.x/client-android/java/tablesdb/decrement-row-column.md b/docs/examples/1.8.x/client-android/java/tablesdb/decrement-row-column.md index 73f2128a8f..2252564e73 100644 --- a/docs/examples/1.8.x/client-android/java/tablesdb/decrement-row-column.md +++ b/docs/examples/1.8.x/client-android/java/tablesdb/decrement-row-column.md @@ -15,6 +15,7 @@ tablesDB.decrementRowColumn( "", // column 0, // value (optional) 0, // min (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/client-android/java/tablesdb/delete-row.md b/docs/examples/1.8.x/client-android/java/tablesdb/delete-row.md index d4c351bc32..6680100499 100644 --- a/docs/examples/1.8.x/client-android/java/tablesdb/delete-row.md +++ b/docs/examples/1.8.x/client-android/java/tablesdb/delete-row.md @@ -12,6 +12,7 @@ tablesDB.deleteRow( "", // databaseId "", // tableId "", // rowId + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/client-android/java/tablesdb/delete-transaction.md b/docs/examples/1.8.x/client-android/java/tablesdb/delete-transaction.md new file mode 100644 index 0000000000..18cb2357d3 --- /dev/null +++ b/docs/examples/1.8.x/client-android/java/tablesdb/delete-transaction.md @@ -0,0 +1,22 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.TablesDB; + +Client client = new Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject(""); // Your project ID + +TablesDB tablesDB = new TablesDB(client); + +tablesDB.deleteTransaction( + "", // transactionId + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + Log.d("Appwrite", result.toString()); + }) +); + diff --git a/docs/examples/1.8.x/client-android/java/tablesdb/get-row.md b/docs/examples/1.8.x/client-android/java/tablesdb/get-row.md index 191fc896e9..45efc6b061 100644 --- a/docs/examples/1.8.x/client-android/java/tablesdb/get-row.md +++ b/docs/examples/1.8.x/client-android/java/tablesdb/get-row.md @@ -13,6 +13,7 @@ tablesDB.getRow( "", // tableId "", // rowId listOf(), // queries (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/client-android/java/tablesdb/get-transaction.md b/docs/examples/1.8.x/client-android/java/tablesdb/get-transaction.md new file mode 100644 index 0000000000..fb51916264 --- /dev/null +++ b/docs/examples/1.8.x/client-android/java/tablesdb/get-transaction.md @@ -0,0 +1,22 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.TablesDB; + +Client client = new Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject(""); // Your project ID + +TablesDB tablesDB = new TablesDB(client); + +tablesDB.getTransaction( + "", // transactionId + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + Log.d("Appwrite", result.toString()); + }) +); + diff --git a/docs/examples/1.8.x/client-android/java/tablesdb/increment-row-column.md b/docs/examples/1.8.x/client-android/java/tablesdb/increment-row-column.md index dc2120ea07..a1194a67a5 100644 --- a/docs/examples/1.8.x/client-android/java/tablesdb/increment-row-column.md +++ b/docs/examples/1.8.x/client-android/java/tablesdb/increment-row-column.md @@ -15,6 +15,7 @@ tablesDB.incrementRowColumn( "", // column 0, // value (optional) 0, // max (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/client-android/java/tablesdb/list-rows.md b/docs/examples/1.8.x/client-android/java/tablesdb/list-rows.md index dc50574f1e..21f0005b2d 100644 --- a/docs/examples/1.8.x/client-android/java/tablesdb/list-rows.md +++ b/docs/examples/1.8.x/client-android/java/tablesdb/list-rows.md @@ -12,6 +12,7 @@ tablesDB.listRows( "", // databaseId "", // tableId listOf(), // queries (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/client-android/java/tablesdb/list-transactions.md b/docs/examples/1.8.x/client-android/java/tablesdb/list-transactions.md new file mode 100644 index 0000000000..c37ccf1931 --- /dev/null +++ b/docs/examples/1.8.x/client-android/java/tablesdb/list-transactions.md @@ -0,0 +1,22 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.TablesDB; + +Client client = new Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject(""); // Your project ID + +TablesDB tablesDB = new TablesDB(client); + +tablesDB.listTransactions( + listOf(), // queries (optional) + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + Log.d("Appwrite", result.toString()); + }) +); + diff --git a/docs/examples/1.8.x/client-android/java/tablesdb/update-row.md b/docs/examples/1.8.x/client-android/java/tablesdb/update-row.md index 0f1fabc91e..cea7baaa16 100644 --- a/docs/examples/1.8.x/client-android/java/tablesdb/update-row.md +++ b/docs/examples/1.8.x/client-android/java/tablesdb/update-row.md @@ -14,6 +14,7 @@ tablesDB.updateRow( "", // rowId mapOf( "a" to "b" ), // data (optional) listOf("read("any")"), // permissions (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/client-android/java/tablesdb/update-transaction.md b/docs/examples/1.8.x/client-android/java/tablesdb/update-transaction.md new file mode 100644 index 0000000000..804b5d5023 --- /dev/null +++ b/docs/examples/1.8.x/client-android/java/tablesdb/update-transaction.md @@ -0,0 +1,24 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.TablesDB; + +Client client = new Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject(""); // Your project ID + +TablesDB tablesDB = new TablesDB(client); + +tablesDB.updateTransaction( + "", // transactionId + false, // commit (optional) + false, // rollback (optional) + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + Log.d("Appwrite", result.toString()); + }) +); + diff --git a/docs/examples/1.8.x/client-android/java/tablesdb/upsert-row.md b/docs/examples/1.8.x/client-android/java/tablesdb/upsert-row.md index 22c0e94b44..9d6323fffa 100644 --- a/docs/examples/1.8.x/client-android/java/tablesdb/upsert-row.md +++ b/docs/examples/1.8.x/client-android/java/tablesdb/upsert-row.md @@ -14,6 +14,7 @@ tablesDB.upsertRow( "", // rowId mapOf( "a" to "b" ), // data (optional) listOf("read("any")"), // permissions (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/client-android/kotlin/databases/create-document.md b/docs/examples/1.8.x/client-android/kotlin/databases/create-document.md index 7f0aaf81f4..7d4b04d13a 100644 --- a/docs/examples/1.8.x/client-android/kotlin/databases/create-document.md +++ b/docs/examples/1.8.x/client-android/kotlin/databases/create-document.md @@ -20,4 +20,5 @@ val result = databases.createDocument( "isAdmin" to false ), permissions = listOf("read("any")"), // (optional) + transactionId = "", // (optional) ) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/databases/create-operations.md b/docs/examples/1.8.x/client-android/kotlin/databases/create-operations.md new file mode 100644 index 0000000000..62c93351e7 --- /dev/null +++ b/docs/examples/1.8.x/client-android/kotlin/databases/create-operations.md @@ -0,0 +1,24 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.Databases + +val client = Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +val databases = Databases(client) + +val result = databases.createOperations( + transactionId = "", + operations = listOf( + { + "action": "create", + "databaseId": "", + "collectionId": "", + "documentId": "", + "data": { + "name": "Walter O'Brien" + } + } + ), // (optional) +) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/databases/create-transaction.md b/docs/examples/1.8.x/client-android/kotlin/databases/create-transaction.md new file mode 100644 index 0000000000..3b953c3bda --- /dev/null +++ b/docs/examples/1.8.x/client-android/kotlin/databases/create-transaction.md @@ -0,0 +1,13 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.Databases + +val client = Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +val databases = Databases(client) + +val result = databases.createTransaction( + ttl = 60, // (optional) +) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/databases/decrement-document-attribute.md b/docs/examples/1.8.x/client-android/kotlin/databases/decrement-document-attribute.md index c500fa8687..84a4a0edea 100644 --- a/docs/examples/1.8.x/client-android/kotlin/databases/decrement-document-attribute.md +++ b/docs/examples/1.8.x/client-android/kotlin/databases/decrement-document-attribute.md @@ -15,4 +15,5 @@ val result = databases.decrementDocumentAttribute( attribute = "", value = 0, // (optional) min = 0, // (optional) + transactionId = "", // (optional) ) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/databases/delete-document.md b/docs/examples/1.8.x/client-android/kotlin/databases/delete-document.md index 052bf97f89..242655ec1f 100644 --- a/docs/examples/1.8.x/client-android/kotlin/databases/delete-document.md +++ b/docs/examples/1.8.x/client-android/kotlin/databases/delete-document.md @@ -12,4 +12,5 @@ val result = databases.deleteDocument( databaseId = "", collectionId = "", documentId = "", + transactionId = "", // (optional) ) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/databases/delete-transaction.md b/docs/examples/1.8.x/client-android/kotlin/databases/delete-transaction.md new file mode 100644 index 0000000000..bbce98c661 --- /dev/null +++ b/docs/examples/1.8.x/client-android/kotlin/databases/delete-transaction.md @@ -0,0 +1,13 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.Databases + +val client = Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +val databases = Databases(client) + +val result = databases.deleteTransaction( + transactionId = "", +) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/databases/get-document.md b/docs/examples/1.8.x/client-android/kotlin/databases/get-document.md index 157af2b562..f21b6f34f0 100644 --- a/docs/examples/1.8.x/client-android/kotlin/databases/get-document.md +++ b/docs/examples/1.8.x/client-android/kotlin/databases/get-document.md @@ -13,4 +13,5 @@ val result = databases.getDocument( collectionId = "", documentId = "", queries = listOf(), // (optional) + transactionId = "", // (optional) ) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/databases/get-transaction.md b/docs/examples/1.8.x/client-android/kotlin/databases/get-transaction.md new file mode 100644 index 0000000000..0a1fda69df --- /dev/null +++ b/docs/examples/1.8.x/client-android/kotlin/databases/get-transaction.md @@ -0,0 +1,13 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.Databases + +val client = Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +val databases = Databases(client) + +val result = databases.getTransaction( + transactionId = "", +) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/databases/increment-document-attribute.md b/docs/examples/1.8.x/client-android/kotlin/databases/increment-document-attribute.md index 0ae6b02d3d..ca32cfcb5c 100644 --- a/docs/examples/1.8.x/client-android/kotlin/databases/increment-document-attribute.md +++ b/docs/examples/1.8.x/client-android/kotlin/databases/increment-document-attribute.md @@ -15,4 +15,5 @@ val result = databases.incrementDocumentAttribute( attribute = "", value = 0, // (optional) max = 0, // (optional) + transactionId = "", // (optional) ) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/databases/list-documents.md b/docs/examples/1.8.x/client-android/kotlin/databases/list-documents.md index 1cc785fab1..a2b6e0e0b6 100644 --- a/docs/examples/1.8.x/client-android/kotlin/databases/list-documents.md +++ b/docs/examples/1.8.x/client-android/kotlin/databases/list-documents.md @@ -12,4 +12,5 @@ val result = databases.listDocuments( databaseId = "", collectionId = "", queries = listOf(), // (optional) + transactionId = "", // (optional) ) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/databases/list-transactions.md b/docs/examples/1.8.x/client-android/kotlin/databases/list-transactions.md new file mode 100644 index 0000000000..da5cd4ba7a --- /dev/null +++ b/docs/examples/1.8.x/client-android/kotlin/databases/list-transactions.md @@ -0,0 +1,13 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.Databases + +val client = Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +val databases = Databases(client) + +val result = databases.listTransactions( + queries = listOf(), // (optional) +) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/databases/update-document.md b/docs/examples/1.8.x/client-android/kotlin/databases/update-document.md index d61fdea5b1..2cacce6f95 100644 --- a/docs/examples/1.8.x/client-android/kotlin/databases/update-document.md +++ b/docs/examples/1.8.x/client-android/kotlin/databases/update-document.md @@ -14,4 +14,5 @@ val result = databases.updateDocument( documentId = "", data = mapOf( "a" to "b" ), // (optional) permissions = listOf("read("any")"), // (optional) + transactionId = "", // (optional) ) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/databases/update-transaction.md b/docs/examples/1.8.x/client-android/kotlin/databases/update-transaction.md new file mode 100644 index 0000000000..c9d6a852ce --- /dev/null +++ b/docs/examples/1.8.x/client-android/kotlin/databases/update-transaction.md @@ -0,0 +1,15 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.Databases + +val client = Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +val databases = Databases(client) + +val result = databases.updateTransaction( + transactionId = "", + commit = false, // (optional) + rollback = false, // (optional) +) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/databases/upsert-document.md b/docs/examples/1.8.x/client-android/kotlin/databases/upsert-document.md index a31dfc8797..e5ac4375e8 100644 --- a/docs/examples/1.8.x/client-android/kotlin/databases/upsert-document.md +++ b/docs/examples/1.8.x/client-android/kotlin/databases/upsert-document.md @@ -14,4 +14,5 @@ val result = databases.upsertDocument( documentId = "", data = mapOf( "a" to "b" ), permissions = listOf("read("any")"), // (optional) + transactionId = "", // (optional) ) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/tablesdb/create-operations.md b/docs/examples/1.8.x/client-android/kotlin/tablesdb/create-operations.md new file mode 100644 index 0000000000..3073a00bca --- /dev/null +++ b/docs/examples/1.8.x/client-android/kotlin/tablesdb/create-operations.md @@ -0,0 +1,24 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.TablesDB + +val client = Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +val tablesDB = TablesDB(client) + +val result = tablesDB.createOperations( + transactionId = "", + operations = listOf( + { + "action": "create", + "databaseId": "", + "tableId": "", + "rowId": "", + "data": { + "name": "Walter O'Brien" + } + } + ), // (optional) +) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/tablesdb/create-row.md b/docs/examples/1.8.x/client-android/kotlin/tablesdb/create-row.md index eb44cc48d6..f5850b23be 100644 --- a/docs/examples/1.8.x/client-android/kotlin/tablesdb/create-row.md +++ b/docs/examples/1.8.x/client-android/kotlin/tablesdb/create-row.md @@ -20,4 +20,5 @@ val result = tablesDB.createRow( "isAdmin" to false ), permissions = listOf("read("any")"), // (optional) + transactionId = "", // (optional) ) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/tablesdb/create-transaction.md b/docs/examples/1.8.x/client-android/kotlin/tablesdb/create-transaction.md new file mode 100644 index 0000000000..b011fa051f --- /dev/null +++ b/docs/examples/1.8.x/client-android/kotlin/tablesdb/create-transaction.md @@ -0,0 +1,13 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.TablesDB + +val client = Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +val tablesDB = TablesDB(client) + +val result = tablesDB.createTransaction( + ttl = 60, // (optional) +) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/tablesdb/decrement-row-column.md b/docs/examples/1.8.x/client-android/kotlin/tablesdb/decrement-row-column.md index 645e9f4a66..1a8964078e 100644 --- a/docs/examples/1.8.x/client-android/kotlin/tablesdb/decrement-row-column.md +++ b/docs/examples/1.8.x/client-android/kotlin/tablesdb/decrement-row-column.md @@ -15,4 +15,5 @@ val result = tablesDB.decrementRowColumn( column = "", value = 0, // (optional) min = 0, // (optional) + transactionId = "", // (optional) ) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/tablesdb/delete-row.md b/docs/examples/1.8.x/client-android/kotlin/tablesdb/delete-row.md index 3fcd409295..6912afa10a 100644 --- a/docs/examples/1.8.x/client-android/kotlin/tablesdb/delete-row.md +++ b/docs/examples/1.8.x/client-android/kotlin/tablesdb/delete-row.md @@ -12,4 +12,5 @@ val result = tablesDB.deleteRow( databaseId = "", tableId = "", rowId = "", + transactionId = "", // (optional) ) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/tablesdb/delete-transaction.md b/docs/examples/1.8.x/client-android/kotlin/tablesdb/delete-transaction.md new file mode 100644 index 0000000000..92c0074acc --- /dev/null +++ b/docs/examples/1.8.x/client-android/kotlin/tablesdb/delete-transaction.md @@ -0,0 +1,13 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.TablesDB + +val client = Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +val tablesDB = TablesDB(client) + +val result = tablesDB.deleteTransaction( + transactionId = "", +) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/tablesdb/get-row.md b/docs/examples/1.8.x/client-android/kotlin/tablesdb/get-row.md index b754cba915..adea429759 100644 --- a/docs/examples/1.8.x/client-android/kotlin/tablesdb/get-row.md +++ b/docs/examples/1.8.x/client-android/kotlin/tablesdb/get-row.md @@ -13,4 +13,5 @@ val result = tablesDB.getRow( tableId = "", rowId = "", queries = listOf(), // (optional) + transactionId = "", // (optional) ) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/tablesdb/get-transaction.md b/docs/examples/1.8.x/client-android/kotlin/tablesdb/get-transaction.md new file mode 100644 index 0000000000..38b7c33e83 --- /dev/null +++ b/docs/examples/1.8.x/client-android/kotlin/tablesdb/get-transaction.md @@ -0,0 +1,13 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.TablesDB + +val client = Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +val tablesDB = TablesDB(client) + +val result = tablesDB.getTransaction( + transactionId = "", +) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/tablesdb/increment-row-column.md b/docs/examples/1.8.x/client-android/kotlin/tablesdb/increment-row-column.md index 230408abac..1b679e181b 100644 --- a/docs/examples/1.8.x/client-android/kotlin/tablesdb/increment-row-column.md +++ b/docs/examples/1.8.x/client-android/kotlin/tablesdb/increment-row-column.md @@ -15,4 +15,5 @@ val result = tablesDB.incrementRowColumn( column = "", value = 0, // (optional) max = 0, // (optional) + transactionId = "", // (optional) ) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/tablesdb/list-rows.md b/docs/examples/1.8.x/client-android/kotlin/tablesdb/list-rows.md index 05d9ca33b3..6d2a4b8b40 100644 --- a/docs/examples/1.8.x/client-android/kotlin/tablesdb/list-rows.md +++ b/docs/examples/1.8.x/client-android/kotlin/tablesdb/list-rows.md @@ -12,4 +12,5 @@ val result = tablesDB.listRows( databaseId = "", tableId = "", queries = listOf(), // (optional) + transactionId = "", // (optional) ) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/tablesdb/list-transactions.md b/docs/examples/1.8.x/client-android/kotlin/tablesdb/list-transactions.md new file mode 100644 index 0000000000..b7764c719f --- /dev/null +++ b/docs/examples/1.8.x/client-android/kotlin/tablesdb/list-transactions.md @@ -0,0 +1,13 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.TablesDB + +val client = Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +val tablesDB = TablesDB(client) + +val result = tablesDB.listTransactions( + queries = listOf(), // (optional) +) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/tablesdb/update-row.md b/docs/examples/1.8.x/client-android/kotlin/tablesdb/update-row.md index f99f8f275e..a17f231418 100644 --- a/docs/examples/1.8.x/client-android/kotlin/tablesdb/update-row.md +++ b/docs/examples/1.8.x/client-android/kotlin/tablesdb/update-row.md @@ -14,4 +14,5 @@ val result = tablesDB.updateRow( rowId = "", data = mapOf( "a" to "b" ), // (optional) permissions = listOf("read("any")"), // (optional) + transactionId = "", // (optional) ) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/tablesdb/update-transaction.md b/docs/examples/1.8.x/client-android/kotlin/tablesdb/update-transaction.md new file mode 100644 index 0000000000..791649ff09 --- /dev/null +++ b/docs/examples/1.8.x/client-android/kotlin/tablesdb/update-transaction.md @@ -0,0 +1,15 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.TablesDB + +val client = Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +val tablesDB = TablesDB(client) + +val result = tablesDB.updateTransaction( + transactionId = "", + commit = false, // (optional) + rollback = false, // (optional) +) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-android/kotlin/tablesdb/upsert-row.md b/docs/examples/1.8.x/client-android/kotlin/tablesdb/upsert-row.md index d82406a7f8..074fa339cb 100644 --- a/docs/examples/1.8.x/client-android/kotlin/tablesdb/upsert-row.md +++ b/docs/examples/1.8.x/client-android/kotlin/tablesdb/upsert-row.md @@ -14,4 +14,5 @@ val result = tablesDB.upsertRow( rowId = "", data = mapOf( "a" to "b" ), // (optional) permissions = listOf("read("any")"), // (optional) + transactionId = "", // (optional) ) \ No newline at end of file diff --git a/docs/examples/1.8.x/client-apple/examples/databases/create-document.md b/docs/examples/1.8.x/client-apple/examples/databases/create-document.md index c044eee17a..d7fa796ed1 100644 --- a/docs/examples/1.8.x/client-apple/examples/databases/create-document.md +++ b/docs/examples/1.8.x/client-apple/examples/databases/create-document.md @@ -17,6 +17,7 @@ let document = try await databases.createDocument( "age": 30, "isAdmin": false ], - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/client-apple/examples/databases/create-operations.md b/docs/examples/1.8.x/client-apple/examples/databases/create-operations.md new file mode 100644 index 0000000000..7c22de38ca --- /dev/null +++ b/docs/examples/1.8.x/client-apple/examples/databases/create-operations.md @@ -0,0 +1,23 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +let databases = Databases(client) + +let transaction = try await databases.createOperations( + transactionId: "", + operations: [ + { + "action": "create", + "databaseId": "", + "collectionId": "", + "documentId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] // optional +) + diff --git a/docs/examples/1.8.x/client-apple/examples/databases/create-transaction.md b/docs/examples/1.8.x/client-apple/examples/databases/create-transaction.md new file mode 100644 index 0000000000..4319907a65 --- /dev/null +++ b/docs/examples/1.8.x/client-apple/examples/databases/create-transaction.md @@ -0,0 +1,12 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +let databases = Databases(client) + +let transaction = try await databases.createTransaction( + ttl: 60 // optional +) + diff --git a/docs/examples/1.8.x/client-apple/examples/databases/decrement-document-attribute.md b/docs/examples/1.8.x/client-apple/examples/databases/decrement-document-attribute.md index 8ef2637bf2..714d7baabb 100644 --- a/docs/examples/1.8.x/client-apple/examples/databases/decrement-document-attribute.md +++ b/docs/examples/1.8.x/client-apple/examples/databases/decrement-document-attribute.md @@ -12,6 +12,7 @@ let document = try await databases.decrementDocumentAttribute( documentId: "", attribute: "", value: 0, // optional - min: 0 // optional + min: 0, // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/client-apple/examples/databases/delete-document.md b/docs/examples/1.8.x/client-apple/examples/databases/delete-document.md index 301203dc7f..4d8f5074ea 100644 --- a/docs/examples/1.8.x/client-apple/examples/databases/delete-document.md +++ b/docs/examples/1.8.x/client-apple/examples/databases/delete-document.md @@ -9,6 +9,7 @@ let databases = Databases(client) let result = try await databases.deleteDocument( databaseId: "", collectionId: "", - documentId: "" + documentId: "", + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/client-apple/examples/databases/delete-transaction.md b/docs/examples/1.8.x/client-apple/examples/databases/delete-transaction.md new file mode 100644 index 0000000000..134d72df9c --- /dev/null +++ b/docs/examples/1.8.x/client-apple/examples/databases/delete-transaction.md @@ -0,0 +1,12 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +let databases = Databases(client) + +let result = try await databases.deleteTransaction( + transactionId: "" +) + diff --git a/docs/examples/1.8.x/client-apple/examples/databases/get-document.md b/docs/examples/1.8.x/client-apple/examples/databases/get-document.md index 6e4dc55c6d..89c89a3868 100644 --- a/docs/examples/1.8.x/client-apple/examples/databases/get-document.md +++ b/docs/examples/1.8.x/client-apple/examples/databases/get-document.md @@ -10,6 +10,7 @@ let document = try await databases.getDocument( databaseId: "", collectionId: "", documentId: "", - queries: [] // optional + queries: [], // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/client-apple/examples/databases/get-transaction.md b/docs/examples/1.8.x/client-apple/examples/databases/get-transaction.md new file mode 100644 index 0000000000..6274ff8d15 --- /dev/null +++ b/docs/examples/1.8.x/client-apple/examples/databases/get-transaction.md @@ -0,0 +1,12 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +let databases = Databases(client) + +let transaction = try await databases.getTransaction( + transactionId: "" +) + diff --git a/docs/examples/1.8.x/client-apple/examples/databases/increment-document-attribute.md b/docs/examples/1.8.x/client-apple/examples/databases/increment-document-attribute.md index f64b2cd76c..9c771a7490 100644 --- a/docs/examples/1.8.x/client-apple/examples/databases/increment-document-attribute.md +++ b/docs/examples/1.8.x/client-apple/examples/databases/increment-document-attribute.md @@ -12,6 +12,7 @@ let document = try await databases.incrementDocumentAttribute( documentId: "", attribute: "", value: 0, // optional - max: 0 // optional + max: 0, // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/client-apple/examples/databases/list-documents.md b/docs/examples/1.8.x/client-apple/examples/databases/list-documents.md index 0d624f3a92..528d9992a4 100644 --- a/docs/examples/1.8.x/client-apple/examples/databases/list-documents.md +++ b/docs/examples/1.8.x/client-apple/examples/databases/list-documents.md @@ -9,6 +9,7 @@ let databases = Databases(client) let documentList = try await databases.listDocuments( databaseId: "", collectionId: "", - queries: [] // optional + queries: [], // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/client-apple/examples/databases/list-transactions.md b/docs/examples/1.8.x/client-apple/examples/databases/list-transactions.md new file mode 100644 index 0000000000..3f889c213c --- /dev/null +++ b/docs/examples/1.8.x/client-apple/examples/databases/list-transactions.md @@ -0,0 +1,12 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +let databases = Databases(client) + +let transactionList = try await databases.listTransactions( + queries: [] // optional +) + diff --git a/docs/examples/1.8.x/client-apple/examples/databases/update-document.md b/docs/examples/1.8.x/client-apple/examples/databases/update-document.md index af224c8e09..d626d7d3c0 100644 --- a/docs/examples/1.8.x/client-apple/examples/databases/update-document.md +++ b/docs/examples/1.8.x/client-apple/examples/databases/update-document.md @@ -11,6 +11,7 @@ let document = try await databases.updateDocument( collectionId: "", documentId: "", data: [:], // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/client-apple/examples/databases/update-transaction.md b/docs/examples/1.8.x/client-apple/examples/databases/update-transaction.md new file mode 100644 index 0000000000..96705d019f --- /dev/null +++ b/docs/examples/1.8.x/client-apple/examples/databases/update-transaction.md @@ -0,0 +1,14 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +let databases = Databases(client) + +let transaction = try await databases.updateTransaction( + transactionId: "", + commit: false, // optional + rollback: false // optional +) + diff --git a/docs/examples/1.8.x/client-apple/examples/databases/upsert-document.md b/docs/examples/1.8.x/client-apple/examples/databases/upsert-document.md index 3e1bf83a66..8e2a4a09e9 100644 --- a/docs/examples/1.8.x/client-apple/examples/databases/upsert-document.md +++ b/docs/examples/1.8.x/client-apple/examples/databases/upsert-document.md @@ -11,6 +11,7 @@ let document = try await databases.upsertDocument( collectionId: "", documentId: "", data: [:], - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/client-apple/examples/tablesdb/create-operations.md b/docs/examples/1.8.x/client-apple/examples/tablesdb/create-operations.md new file mode 100644 index 0000000000..c4032cc02c --- /dev/null +++ b/docs/examples/1.8.x/client-apple/examples/tablesdb/create-operations.md @@ -0,0 +1,23 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +let tablesDB = TablesDB(client) + +let transaction = try await tablesDB.createOperations( + transactionId: "", + operations: [ + { + "action": "create", + "databaseId": "", + "tableId": "", + "rowId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] // optional +) + diff --git a/docs/examples/1.8.x/client-apple/examples/tablesdb/create-row.md b/docs/examples/1.8.x/client-apple/examples/tablesdb/create-row.md index 2ee601340f..4d66980bb5 100644 --- a/docs/examples/1.8.x/client-apple/examples/tablesdb/create-row.md +++ b/docs/examples/1.8.x/client-apple/examples/tablesdb/create-row.md @@ -17,6 +17,7 @@ let row = try await tablesDB.createRow( "age": 30, "isAdmin": false ], - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/client-apple/examples/tablesdb/create-transaction.md b/docs/examples/1.8.x/client-apple/examples/tablesdb/create-transaction.md new file mode 100644 index 0000000000..366aa5b663 --- /dev/null +++ b/docs/examples/1.8.x/client-apple/examples/tablesdb/create-transaction.md @@ -0,0 +1,12 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +let tablesDB = TablesDB(client) + +let transaction = try await tablesDB.createTransaction( + ttl: 60 // optional +) + diff --git a/docs/examples/1.8.x/client-apple/examples/tablesdb/decrement-row-column.md b/docs/examples/1.8.x/client-apple/examples/tablesdb/decrement-row-column.md index ab8ac5b0b8..8a41d43362 100644 --- a/docs/examples/1.8.x/client-apple/examples/tablesdb/decrement-row-column.md +++ b/docs/examples/1.8.x/client-apple/examples/tablesdb/decrement-row-column.md @@ -12,6 +12,7 @@ let row = try await tablesDB.decrementRowColumn( rowId: "", column: "", value: 0, // optional - min: 0 // optional + min: 0, // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/client-apple/examples/tablesdb/delete-row.md b/docs/examples/1.8.x/client-apple/examples/tablesdb/delete-row.md index b527acaed9..6ddd1c5fc2 100644 --- a/docs/examples/1.8.x/client-apple/examples/tablesdb/delete-row.md +++ b/docs/examples/1.8.x/client-apple/examples/tablesdb/delete-row.md @@ -9,6 +9,7 @@ let tablesDB = TablesDB(client) let result = try await tablesDB.deleteRow( databaseId: "", tableId: "", - rowId: "" + rowId: "", + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/client-apple/examples/tablesdb/delete-transaction.md b/docs/examples/1.8.x/client-apple/examples/tablesdb/delete-transaction.md new file mode 100644 index 0000000000..12cf45fa2c --- /dev/null +++ b/docs/examples/1.8.x/client-apple/examples/tablesdb/delete-transaction.md @@ -0,0 +1,12 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +let tablesDB = TablesDB(client) + +let result = try await tablesDB.deleteTransaction( + transactionId: "" +) + diff --git a/docs/examples/1.8.x/client-apple/examples/tablesdb/get-row.md b/docs/examples/1.8.x/client-apple/examples/tablesdb/get-row.md index bc2e2c6b55..7a3aa40806 100644 --- a/docs/examples/1.8.x/client-apple/examples/tablesdb/get-row.md +++ b/docs/examples/1.8.x/client-apple/examples/tablesdb/get-row.md @@ -10,6 +10,7 @@ let row = try await tablesDB.getRow( databaseId: "", tableId: "", rowId: "", - queries: [] // optional + queries: [], // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/client-apple/examples/tablesdb/get-transaction.md b/docs/examples/1.8.x/client-apple/examples/tablesdb/get-transaction.md new file mode 100644 index 0000000000..fe3cbf78b2 --- /dev/null +++ b/docs/examples/1.8.x/client-apple/examples/tablesdb/get-transaction.md @@ -0,0 +1,12 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +let tablesDB = TablesDB(client) + +let transaction = try await tablesDB.getTransaction( + transactionId: "" +) + diff --git a/docs/examples/1.8.x/client-apple/examples/tablesdb/increment-row-column.md b/docs/examples/1.8.x/client-apple/examples/tablesdb/increment-row-column.md index 550d6685af..29b346e27d 100644 --- a/docs/examples/1.8.x/client-apple/examples/tablesdb/increment-row-column.md +++ b/docs/examples/1.8.x/client-apple/examples/tablesdb/increment-row-column.md @@ -12,6 +12,7 @@ let row = try await tablesDB.incrementRowColumn( rowId: "", column: "", value: 0, // optional - max: 0 // optional + max: 0, // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/client-apple/examples/tablesdb/list-rows.md b/docs/examples/1.8.x/client-apple/examples/tablesdb/list-rows.md index 94853c24a0..dee2ab9e81 100644 --- a/docs/examples/1.8.x/client-apple/examples/tablesdb/list-rows.md +++ b/docs/examples/1.8.x/client-apple/examples/tablesdb/list-rows.md @@ -9,6 +9,7 @@ let tablesDB = TablesDB(client) let rowList = try await tablesDB.listRows( databaseId: "", tableId: "", - queries: [] // optional + queries: [], // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/client-apple/examples/tablesdb/list-transactions.md b/docs/examples/1.8.x/client-apple/examples/tablesdb/list-transactions.md new file mode 100644 index 0000000000..b7edd2d1a0 --- /dev/null +++ b/docs/examples/1.8.x/client-apple/examples/tablesdb/list-transactions.md @@ -0,0 +1,12 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +let tablesDB = TablesDB(client) + +let transactionList = try await tablesDB.listTransactions( + queries: [] // optional +) + diff --git a/docs/examples/1.8.x/client-apple/examples/tablesdb/update-row.md b/docs/examples/1.8.x/client-apple/examples/tablesdb/update-row.md index 87a8f27313..cd5591db80 100644 --- a/docs/examples/1.8.x/client-apple/examples/tablesdb/update-row.md +++ b/docs/examples/1.8.x/client-apple/examples/tablesdb/update-row.md @@ -11,6 +11,7 @@ let row = try await tablesDB.updateRow( tableId: "", rowId: "", data: [:], // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/client-apple/examples/tablesdb/update-transaction.md b/docs/examples/1.8.x/client-apple/examples/tablesdb/update-transaction.md new file mode 100644 index 0000000000..2c0e6a7a37 --- /dev/null +++ b/docs/examples/1.8.x/client-apple/examples/tablesdb/update-transaction.md @@ -0,0 +1,14 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + +let tablesDB = TablesDB(client) + +let transaction = try await tablesDB.updateTransaction( + transactionId: "", + commit: false, // optional + rollback: false // optional +) + diff --git a/docs/examples/1.8.x/client-apple/examples/tablesdb/upsert-row.md b/docs/examples/1.8.x/client-apple/examples/tablesdb/upsert-row.md index ed95da7b62..955935adef 100644 --- a/docs/examples/1.8.x/client-apple/examples/tablesdb/upsert-row.md +++ b/docs/examples/1.8.x/client-apple/examples/tablesdb/upsert-row.md @@ -11,6 +11,7 @@ let row = try await tablesDB.upsertRow( tableId: "", rowId: "", data: [:], // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/client-flutter/examples/databases/create-document.md b/docs/examples/1.8.x/client-flutter/examples/databases/create-document.md index 3becbcf1fc..0acbe689dc 100644 --- a/docs/examples/1.8.x/client-flutter/examples/databases/create-document.md +++ b/docs/examples/1.8.x/client-flutter/examples/databases/create-document.md @@ -18,4 +18,5 @@ Document result = await databases.createDocument( "isAdmin": false }, permissions: ["read("any")"], // optional + transactionId: '', // optional ); diff --git a/docs/examples/1.8.x/client-flutter/examples/databases/create-operations.md b/docs/examples/1.8.x/client-flutter/examples/databases/create-operations.md new file mode 100644 index 0000000000..2dec7ff7c8 --- /dev/null +++ b/docs/examples/1.8.x/client-flutter/examples/databases/create-operations.md @@ -0,0 +1,22 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +Databases databases = Databases(client); + +Transaction result = await databases.createOperations( + transactionId: '', + operations: [ + { + "action": "create", + "databaseId": "", + "collectionId": "", + "documentId": "", + "data": { + "name": "Walter O'Brien" + } + } + ], // optional +); diff --git a/docs/examples/1.8.x/client-flutter/examples/databases/create-transaction.md b/docs/examples/1.8.x/client-flutter/examples/databases/create-transaction.md new file mode 100644 index 0000000000..3d7ddc3efa --- /dev/null +++ b/docs/examples/1.8.x/client-flutter/examples/databases/create-transaction.md @@ -0,0 +1,11 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +Databases databases = Databases(client); + +Transaction result = await databases.createTransaction( + ttl: 60, // optional +); diff --git a/docs/examples/1.8.x/client-flutter/examples/databases/decrement-document-attribute.md b/docs/examples/1.8.x/client-flutter/examples/databases/decrement-document-attribute.md index ec0d9ee300..dad45bc836 100644 --- a/docs/examples/1.8.x/client-flutter/examples/databases/decrement-document-attribute.md +++ b/docs/examples/1.8.x/client-flutter/examples/databases/decrement-document-attribute.md @@ -13,4 +13,5 @@ Document result = await databases.decrementDocumentAttribute( attribute: '', value: 0, // optional min: 0, // optional + transactionId: '', // optional ); diff --git a/docs/examples/1.8.x/client-flutter/examples/databases/delete-document.md b/docs/examples/1.8.x/client-flutter/examples/databases/delete-document.md index 3354917c20..bd101370a6 100644 --- a/docs/examples/1.8.x/client-flutter/examples/databases/delete-document.md +++ b/docs/examples/1.8.x/client-flutter/examples/databases/delete-document.md @@ -10,4 +10,5 @@ await databases.deleteDocument( databaseId: '', collectionId: '', documentId: '', + transactionId: '', // optional ); diff --git a/docs/examples/1.8.x/client-flutter/examples/databases/delete-transaction.md b/docs/examples/1.8.x/client-flutter/examples/databases/delete-transaction.md new file mode 100644 index 0000000000..333dd1d3a1 --- /dev/null +++ b/docs/examples/1.8.x/client-flutter/examples/databases/delete-transaction.md @@ -0,0 +1,11 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +Databases databases = Databases(client); + +await databases.deleteTransaction( + transactionId: '', +); diff --git a/docs/examples/1.8.x/client-flutter/examples/databases/get-document.md b/docs/examples/1.8.x/client-flutter/examples/databases/get-document.md index f85c1f9b5a..9dcf2cf119 100644 --- a/docs/examples/1.8.x/client-flutter/examples/databases/get-document.md +++ b/docs/examples/1.8.x/client-flutter/examples/databases/get-document.md @@ -11,4 +11,5 @@ Document result = await databases.getDocument( collectionId: '', documentId: '', queries: [], // optional + transactionId: '', // optional ); diff --git a/docs/examples/1.8.x/client-flutter/examples/databases/get-transaction.md b/docs/examples/1.8.x/client-flutter/examples/databases/get-transaction.md new file mode 100644 index 0000000000..153b0f3856 --- /dev/null +++ b/docs/examples/1.8.x/client-flutter/examples/databases/get-transaction.md @@ -0,0 +1,11 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +Databases databases = Databases(client); + +Transaction result = await databases.getTransaction( + transactionId: '', +); diff --git a/docs/examples/1.8.x/client-flutter/examples/databases/increment-document-attribute.md b/docs/examples/1.8.x/client-flutter/examples/databases/increment-document-attribute.md index 78f5b0cb6f..855fd8f51e 100644 --- a/docs/examples/1.8.x/client-flutter/examples/databases/increment-document-attribute.md +++ b/docs/examples/1.8.x/client-flutter/examples/databases/increment-document-attribute.md @@ -13,4 +13,5 @@ Document result = await databases.incrementDocumentAttribute( attribute: '', value: 0, // optional max: 0, // optional + transactionId: '', // optional ); diff --git a/docs/examples/1.8.x/client-flutter/examples/databases/list-documents.md b/docs/examples/1.8.x/client-flutter/examples/databases/list-documents.md index 31fec1f522..b53120cb4e 100644 --- a/docs/examples/1.8.x/client-flutter/examples/databases/list-documents.md +++ b/docs/examples/1.8.x/client-flutter/examples/databases/list-documents.md @@ -10,4 +10,5 @@ DocumentList result = await databases.listDocuments( databaseId: '', collectionId: '', queries: [], // optional + transactionId: '', // optional ); diff --git a/docs/examples/1.8.x/client-flutter/examples/databases/list-transactions.md b/docs/examples/1.8.x/client-flutter/examples/databases/list-transactions.md new file mode 100644 index 0000000000..467a1ced84 --- /dev/null +++ b/docs/examples/1.8.x/client-flutter/examples/databases/list-transactions.md @@ -0,0 +1,11 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +Databases databases = Databases(client); + +TransactionList result = await databases.listTransactions( + queries: [], // optional +); diff --git a/docs/examples/1.8.x/client-flutter/examples/databases/update-document.md b/docs/examples/1.8.x/client-flutter/examples/databases/update-document.md index 1f444d875a..44ade30c3a 100644 --- a/docs/examples/1.8.x/client-flutter/examples/databases/update-document.md +++ b/docs/examples/1.8.x/client-flutter/examples/databases/update-document.md @@ -12,4 +12,5 @@ Document result = await databases.updateDocument( documentId: '', data: {}, // optional permissions: ["read("any")"], // optional + transactionId: '', // optional ); diff --git a/docs/examples/1.8.x/client-flutter/examples/databases/update-transaction.md b/docs/examples/1.8.x/client-flutter/examples/databases/update-transaction.md new file mode 100644 index 0000000000..a51f9d05d6 --- /dev/null +++ b/docs/examples/1.8.x/client-flutter/examples/databases/update-transaction.md @@ -0,0 +1,13 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +Databases databases = Databases(client); + +Transaction result = await databases.updateTransaction( + transactionId: '', + commit: false, // optional + rollback: false, // optional +); diff --git a/docs/examples/1.8.x/client-flutter/examples/databases/upsert-document.md b/docs/examples/1.8.x/client-flutter/examples/databases/upsert-document.md index 398a99cb1d..10117ac78d 100644 --- a/docs/examples/1.8.x/client-flutter/examples/databases/upsert-document.md +++ b/docs/examples/1.8.x/client-flutter/examples/databases/upsert-document.md @@ -12,4 +12,5 @@ Document result = await databases.upsertDocument( documentId: '', data: {}, permissions: ["read("any")"], // optional + transactionId: '', // optional ); diff --git a/docs/examples/1.8.x/client-flutter/examples/tablesdb/create-operations.md b/docs/examples/1.8.x/client-flutter/examples/tablesdb/create-operations.md new file mode 100644 index 0000000000..631aefe603 --- /dev/null +++ b/docs/examples/1.8.x/client-flutter/examples/tablesdb/create-operations.md @@ -0,0 +1,22 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +TablesDB tablesDB = TablesDB(client); + +Transaction result = await tablesDB.createOperations( + transactionId: '', + operations: [ + { + "action": "create", + "databaseId": "", + "tableId": "", + "rowId": "", + "data": { + "name": "Walter O'Brien" + } + } + ], // optional +); diff --git a/docs/examples/1.8.x/client-flutter/examples/tablesdb/create-row.md b/docs/examples/1.8.x/client-flutter/examples/tablesdb/create-row.md index 038bb2bac6..345f0c239a 100644 --- a/docs/examples/1.8.x/client-flutter/examples/tablesdb/create-row.md +++ b/docs/examples/1.8.x/client-flutter/examples/tablesdb/create-row.md @@ -18,4 +18,5 @@ Row result = await tablesDB.createRow( "isAdmin": false }, permissions: ["read("any")"], // optional + transactionId: '', // optional ); diff --git a/docs/examples/1.8.x/client-flutter/examples/tablesdb/create-transaction.md b/docs/examples/1.8.x/client-flutter/examples/tablesdb/create-transaction.md new file mode 100644 index 0000000000..0ad0eb5223 --- /dev/null +++ b/docs/examples/1.8.x/client-flutter/examples/tablesdb/create-transaction.md @@ -0,0 +1,11 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +TablesDB tablesDB = TablesDB(client); + +Transaction result = await tablesDB.createTransaction( + ttl: 60, // optional +); diff --git a/docs/examples/1.8.x/client-flutter/examples/tablesdb/decrement-row-column.md b/docs/examples/1.8.x/client-flutter/examples/tablesdb/decrement-row-column.md index 4f3b4bdb61..65f67513f4 100644 --- a/docs/examples/1.8.x/client-flutter/examples/tablesdb/decrement-row-column.md +++ b/docs/examples/1.8.x/client-flutter/examples/tablesdb/decrement-row-column.md @@ -13,4 +13,5 @@ Row result = await tablesDB.decrementRowColumn( column: '', value: 0, // optional min: 0, // optional + transactionId: '', // optional ); diff --git a/docs/examples/1.8.x/client-flutter/examples/tablesdb/delete-row.md b/docs/examples/1.8.x/client-flutter/examples/tablesdb/delete-row.md index cc902fa198..b8ea1d2656 100644 --- a/docs/examples/1.8.x/client-flutter/examples/tablesdb/delete-row.md +++ b/docs/examples/1.8.x/client-flutter/examples/tablesdb/delete-row.md @@ -10,4 +10,5 @@ await tablesDB.deleteRow( databaseId: '', tableId: '', rowId: '', + transactionId: '', // optional ); diff --git a/docs/examples/1.8.x/client-flutter/examples/tablesdb/delete-transaction.md b/docs/examples/1.8.x/client-flutter/examples/tablesdb/delete-transaction.md new file mode 100644 index 0000000000..2d27c6afda --- /dev/null +++ b/docs/examples/1.8.x/client-flutter/examples/tablesdb/delete-transaction.md @@ -0,0 +1,11 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +TablesDB tablesDB = TablesDB(client); + +await tablesDB.deleteTransaction( + transactionId: '', +); diff --git a/docs/examples/1.8.x/client-flutter/examples/tablesdb/get-row.md b/docs/examples/1.8.x/client-flutter/examples/tablesdb/get-row.md index 29e6eaab93..eb75da5073 100644 --- a/docs/examples/1.8.x/client-flutter/examples/tablesdb/get-row.md +++ b/docs/examples/1.8.x/client-flutter/examples/tablesdb/get-row.md @@ -11,4 +11,5 @@ Row result = await tablesDB.getRow( tableId: '', rowId: '', queries: [], // optional + transactionId: '', // optional ); diff --git a/docs/examples/1.8.x/client-flutter/examples/tablesdb/get-transaction.md b/docs/examples/1.8.x/client-flutter/examples/tablesdb/get-transaction.md new file mode 100644 index 0000000000..000e230227 --- /dev/null +++ b/docs/examples/1.8.x/client-flutter/examples/tablesdb/get-transaction.md @@ -0,0 +1,11 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +TablesDB tablesDB = TablesDB(client); + +Transaction result = await tablesDB.getTransaction( + transactionId: '', +); diff --git a/docs/examples/1.8.x/client-flutter/examples/tablesdb/increment-row-column.md b/docs/examples/1.8.x/client-flutter/examples/tablesdb/increment-row-column.md index e05dc76753..91cd0ce351 100644 --- a/docs/examples/1.8.x/client-flutter/examples/tablesdb/increment-row-column.md +++ b/docs/examples/1.8.x/client-flutter/examples/tablesdb/increment-row-column.md @@ -13,4 +13,5 @@ Row result = await tablesDB.incrementRowColumn( column: '', value: 0, // optional max: 0, // optional + transactionId: '', // optional ); diff --git a/docs/examples/1.8.x/client-flutter/examples/tablesdb/list-rows.md b/docs/examples/1.8.x/client-flutter/examples/tablesdb/list-rows.md index 7763e2ae3d..01d7066501 100644 --- a/docs/examples/1.8.x/client-flutter/examples/tablesdb/list-rows.md +++ b/docs/examples/1.8.x/client-flutter/examples/tablesdb/list-rows.md @@ -10,4 +10,5 @@ RowList result = await tablesDB.listRows( databaseId: '', tableId: '', queries: [], // optional + transactionId: '', // optional ); diff --git a/docs/examples/1.8.x/client-flutter/examples/tablesdb/list-transactions.md b/docs/examples/1.8.x/client-flutter/examples/tablesdb/list-transactions.md new file mode 100644 index 0000000000..5e088cedc3 --- /dev/null +++ b/docs/examples/1.8.x/client-flutter/examples/tablesdb/list-transactions.md @@ -0,0 +1,11 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +TablesDB tablesDB = TablesDB(client); + +TransactionList result = await tablesDB.listTransactions( + queries: [], // optional +); diff --git a/docs/examples/1.8.x/client-flutter/examples/tablesdb/update-row.md b/docs/examples/1.8.x/client-flutter/examples/tablesdb/update-row.md index c2cc84d7f6..08ab309363 100644 --- a/docs/examples/1.8.x/client-flutter/examples/tablesdb/update-row.md +++ b/docs/examples/1.8.x/client-flutter/examples/tablesdb/update-row.md @@ -12,4 +12,5 @@ Row result = await tablesDB.updateRow( rowId: '', data: {}, // optional permissions: ["read("any")"], // optional + transactionId: '', // optional ); diff --git a/docs/examples/1.8.x/client-flutter/examples/tablesdb/update-transaction.md b/docs/examples/1.8.x/client-flutter/examples/tablesdb/update-transaction.md new file mode 100644 index 0000000000..ef56443e99 --- /dev/null +++ b/docs/examples/1.8.x/client-flutter/examples/tablesdb/update-transaction.md @@ -0,0 +1,13 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +TablesDB tablesDB = TablesDB(client); + +Transaction result = await tablesDB.updateTransaction( + transactionId: '', + commit: false, // optional + rollback: false, // optional +); diff --git a/docs/examples/1.8.x/client-flutter/examples/tablesdb/upsert-row.md b/docs/examples/1.8.x/client-flutter/examples/tablesdb/upsert-row.md index 6a958a1898..061bb0b85a 100644 --- a/docs/examples/1.8.x/client-flutter/examples/tablesdb/upsert-row.md +++ b/docs/examples/1.8.x/client-flutter/examples/tablesdb/upsert-row.md @@ -12,4 +12,5 @@ Row result = await tablesDB.upsertRow( rowId: '', data: {}, // optional permissions: ["read("any")"], // optional + transactionId: '', // optional ); diff --git a/docs/examples/1.8.x/client-graphql/examples/databases/create-document.md b/docs/examples/1.8.x/client-graphql/examples/databases/create-document.md index 39e4bba1cb..411615f7a7 100644 --- a/docs/examples/1.8.x/client-graphql/examples/databases/create-document.md +++ b/docs/examples/1.8.x/client-graphql/examples/databases/create-document.md @@ -4,7 +4,8 @@ mutation { collectionId: "", documentId: "", data: "{\"username\":\"walter.obrien\",\"email\":\"walter.obrien@example.com\",\"fullName\":\"Walter O'Brien\",\"age\":30,\"isAdmin\":false}", - permissions: ["read("any")"] + permissions: ["read("any")"], + transactionId: "" ) { _id _sequence diff --git a/docs/examples/1.8.x/client-graphql/examples/databases/create-operations.md b/docs/examples/1.8.x/client-graphql/examples/databases/create-operations.md new file mode 100644 index 0000000000..1be3b39ee1 --- /dev/null +++ b/docs/examples/1.8.x/client-graphql/examples/databases/create-operations.md @@ -0,0 +1,23 @@ +mutation { + databasesCreateOperations( + transactionId: "", + operations: [ + { + "action": "create", + "databaseId": "", + "collectionId": "", + "documentId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] + ) { + _id + _createdAt + _updatedAt + status + operations + expiresAt + } +} diff --git a/docs/examples/1.8.x/client-graphql/examples/databases/create-transaction.md b/docs/examples/1.8.x/client-graphql/examples/databases/create-transaction.md new file mode 100644 index 0000000000..7fea034ab6 --- /dev/null +++ b/docs/examples/1.8.x/client-graphql/examples/databases/create-transaction.md @@ -0,0 +1,12 @@ +mutation { + databasesCreateTransaction( + ttl: 60 + ) { + _id + _createdAt + _updatedAt + status + operations + expiresAt + } +} diff --git a/docs/examples/1.8.x/client-graphql/examples/databases/decrement-document-attribute.md b/docs/examples/1.8.x/client-graphql/examples/databases/decrement-document-attribute.md index 2e7970049d..e6032fd0e7 100644 --- a/docs/examples/1.8.x/client-graphql/examples/databases/decrement-document-attribute.md +++ b/docs/examples/1.8.x/client-graphql/examples/databases/decrement-document-attribute.md @@ -5,7 +5,8 @@ mutation { documentId: "", attribute: "", value: 0, - min: 0 + min: 0, + transactionId: "" ) { _id _sequence diff --git a/docs/examples/1.8.x/client-graphql/examples/databases/delete-document.md b/docs/examples/1.8.x/client-graphql/examples/databases/delete-document.md index 848371bca0..2e172aa5dd 100644 --- a/docs/examples/1.8.x/client-graphql/examples/databases/delete-document.md +++ b/docs/examples/1.8.x/client-graphql/examples/databases/delete-document.md @@ -2,7 +2,8 @@ mutation { databasesDeleteDocument( databaseId: "", collectionId: "", - documentId: "" + documentId: "", + transactionId: "" ) { status } diff --git a/docs/examples/1.8.x/client-graphql/examples/databases/delete-transaction.md b/docs/examples/1.8.x/client-graphql/examples/databases/delete-transaction.md new file mode 100644 index 0000000000..cd29a0b8a6 --- /dev/null +++ b/docs/examples/1.8.x/client-graphql/examples/databases/delete-transaction.md @@ -0,0 +1,7 @@ +mutation { + databasesDeleteTransaction( + transactionId: "" + ) { + status + } +} diff --git a/docs/examples/1.8.x/client-graphql/examples/databases/get-transaction.md b/docs/examples/1.8.x/client-graphql/examples/databases/get-transaction.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/examples/1.8.x/client-graphql/examples/databases/increment-document-attribute.md b/docs/examples/1.8.x/client-graphql/examples/databases/increment-document-attribute.md index 322ed69ced..3518ff1583 100644 --- a/docs/examples/1.8.x/client-graphql/examples/databases/increment-document-attribute.md +++ b/docs/examples/1.8.x/client-graphql/examples/databases/increment-document-attribute.md @@ -5,7 +5,8 @@ mutation { documentId: "", attribute: "", value: 0, - max: 0 + max: 0, + transactionId: "" ) { _id _sequence diff --git a/docs/examples/1.8.x/client-graphql/examples/databases/list-transactions.md b/docs/examples/1.8.x/client-graphql/examples/databases/list-transactions.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/examples/1.8.x/client-graphql/examples/databases/update-document.md b/docs/examples/1.8.x/client-graphql/examples/databases/update-document.md index aea605d9d7..cf43d9eed0 100644 --- a/docs/examples/1.8.x/client-graphql/examples/databases/update-document.md +++ b/docs/examples/1.8.x/client-graphql/examples/databases/update-document.md @@ -4,7 +4,8 @@ mutation { collectionId: "", documentId: "", data: "{}", - permissions: ["read("any")"] + permissions: ["read("any")"], + transactionId: "" ) { _id _sequence diff --git a/docs/examples/1.8.x/client-graphql/examples/databases/update-transaction.md b/docs/examples/1.8.x/client-graphql/examples/databases/update-transaction.md new file mode 100644 index 0000000000..b56c7139ac --- /dev/null +++ b/docs/examples/1.8.x/client-graphql/examples/databases/update-transaction.md @@ -0,0 +1,14 @@ +mutation { + databasesUpdateTransaction( + transactionId: "", + commit: false, + rollback: false + ) { + _id + _createdAt + _updatedAt + status + operations + expiresAt + } +} diff --git a/docs/examples/1.8.x/client-graphql/examples/databases/upsert-document.md b/docs/examples/1.8.x/client-graphql/examples/databases/upsert-document.md index 9d1e753081..d487c0d303 100644 --- a/docs/examples/1.8.x/client-graphql/examples/databases/upsert-document.md +++ b/docs/examples/1.8.x/client-graphql/examples/databases/upsert-document.md @@ -4,7 +4,8 @@ mutation { collectionId: "", documentId: "", data: "{}", - permissions: ["read("any")"] + permissions: ["read("any")"], + transactionId: "" ) { _id _sequence diff --git a/docs/examples/1.8.x/client-graphql/examples/tablesdb/create-operations.md b/docs/examples/1.8.x/client-graphql/examples/tablesdb/create-operations.md new file mode 100644 index 0000000000..bb2be8085a --- /dev/null +++ b/docs/examples/1.8.x/client-graphql/examples/tablesdb/create-operations.md @@ -0,0 +1,23 @@ +mutation { + tablesDBCreateOperations( + transactionId: "", + operations: [ + { + "action": "create", + "databaseId": "", + "tableId": "", + "rowId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] + ) { + _id + _createdAt + _updatedAt + status + operations + expiresAt + } +} diff --git a/docs/examples/1.8.x/client-graphql/examples/tablesdb/create-row.md b/docs/examples/1.8.x/client-graphql/examples/tablesdb/create-row.md index c7d2ec7d03..109bc008d6 100644 --- a/docs/examples/1.8.x/client-graphql/examples/tablesdb/create-row.md +++ b/docs/examples/1.8.x/client-graphql/examples/tablesdb/create-row.md @@ -4,7 +4,8 @@ mutation { tableId: "", rowId: "", data: "{\"username\":\"walter.obrien\",\"email\":\"walter.obrien@example.com\",\"fullName\":\"Walter O'Brien\",\"age\":30,\"isAdmin\":false}", - permissions: ["read("any")"] + permissions: ["read("any")"], + transactionId: "" ) { _id _sequence diff --git a/docs/examples/1.8.x/client-graphql/examples/tablesdb/create-transaction.md b/docs/examples/1.8.x/client-graphql/examples/tablesdb/create-transaction.md new file mode 100644 index 0000000000..0e874f0c78 --- /dev/null +++ b/docs/examples/1.8.x/client-graphql/examples/tablesdb/create-transaction.md @@ -0,0 +1,12 @@ +mutation { + tablesDBCreateTransaction( + ttl: 60 + ) { + _id + _createdAt + _updatedAt + status + operations + expiresAt + } +} diff --git a/docs/examples/1.8.x/client-graphql/examples/tablesdb/decrement-row-column.md b/docs/examples/1.8.x/client-graphql/examples/tablesdb/decrement-row-column.md index 398ec19901..1d57d79b54 100644 --- a/docs/examples/1.8.x/client-graphql/examples/tablesdb/decrement-row-column.md +++ b/docs/examples/1.8.x/client-graphql/examples/tablesdb/decrement-row-column.md @@ -5,7 +5,8 @@ mutation { rowId: "", column: "", value: 0, - min: 0 + min: 0, + transactionId: "" ) { _id _sequence diff --git a/docs/examples/1.8.x/client-graphql/examples/tablesdb/delete-row.md b/docs/examples/1.8.x/client-graphql/examples/tablesdb/delete-row.md index 1a08b0f60d..3b44913049 100644 --- a/docs/examples/1.8.x/client-graphql/examples/tablesdb/delete-row.md +++ b/docs/examples/1.8.x/client-graphql/examples/tablesdb/delete-row.md @@ -2,7 +2,8 @@ mutation { tablesDBDeleteRow( databaseId: "", tableId: "", - rowId: "" + rowId: "", + transactionId: "" ) { status } diff --git a/docs/examples/1.8.x/client-graphql/examples/tablesdb/delete-transaction.md b/docs/examples/1.8.x/client-graphql/examples/tablesdb/delete-transaction.md new file mode 100644 index 0000000000..4a2d6f15a2 --- /dev/null +++ b/docs/examples/1.8.x/client-graphql/examples/tablesdb/delete-transaction.md @@ -0,0 +1,7 @@ +mutation { + tablesDBDeleteTransaction( + transactionId: "" + ) { + status + } +} diff --git a/docs/examples/1.8.x/client-graphql/examples/tablesdb/get-transaction.md b/docs/examples/1.8.x/client-graphql/examples/tablesdb/get-transaction.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/examples/1.8.x/client-graphql/examples/tablesdb/increment-row-column.md b/docs/examples/1.8.x/client-graphql/examples/tablesdb/increment-row-column.md index b7ff87f387..3ae008e718 100644 --- a/docs/examples/1.8.x/client-graphql/examples/tablesdb/increment-row-column.md +++ b/docs/examples/1.8.x/client-graphql/examples/tablesdb/increment-row-column.md @@ -5,7 +5,8 @@ mutation { rowId: "", column: "", value: 0, - max: 0 + max: 0, + transactionId: "" ) { _id _sequence diff --git a/docs/examples/1.8.x/client-graphql/examples/tablesdb/list-transactions.md b/docs/examples/1.8.x/client-graphql/examples/tablesdb/list-transactions.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/examples/1.8.x/client-graphql/examples/tablesdb/update-row.md b/docs/examples/1.8.x/client-graphql/examples/tablesdb/update-row.md index 5a5b288ab8..aa89e6ae01 100644 --- a/docs/examples/1.8.x/client-graphql/examples/tablesdb/update-row.md +++ b/docs/examples/1.8.x/client-graphql/examples/tablesdb/update-row.md @@ -4,7 +4,8 @@ mutation { tableId: "", rowId: "", data: "{}", - permissions: ["read("any")"] + permissions: ["read("any")"], + transactionId: "" ) { _id _sequence diff --git a/docs/examples/1.8.x/client-graphql/examples/tablesdb/update-transaction.md b/docs/examples/1.8.x/client-graphql/examples/tablesdb/update-transaction.md new file mode 100644 index 0000000000..2094877303 --- /dev/null +++ b/docs/examples/1.8.x/client-graphql/examples/tablesdb/update-transaction.md @@ -0,0 +1,14 @@ +mutation { + tablesDBUpdateTransaction( + transactionId: "", + commit: false, + rollback: false + ) { + _id + _createdAt + _updatedAt + status + operations + expiresAt + } +} diff --git a/docs/examples/1.8.x/client-graphql/examples/tablesdb/upsert-row.md b/docs/examples/1.8.x/client-graphql/examples/tablesdb/upsert-row.md index cc3b63de4a..3fe36ee7f1 100644 --- a/docs/examples/1.8.x/client-graphql/examples/tablesdb/upsert-row.md +++ b/docs/examples/1.8.x/client-graphql/examples/tablesdb/upsert-row.md @@ -4,7 +4,8 @@ mutation { tableId: "", rowId: "", data: "{}", - permissions: ["read("any")"] + permissions: ["read("any")"], + transactionId: "" ) { _id _sequence diff --git a/docs/examples/1.8.x/client-react-native/examples/databases/create-document.md b/docs/examples/1.8.x/client-react-native/examples/databases/create-document.md index e7cffc13d4..3f7fd9af8f 100644 --- a/docs/examples/1.8.x/client-react-native/examples/databases/create-document.md +++ b/docs/examples/1.8.x/client-react-native/examples/databases/create-document.md @@ -17,7 +17,8 @@ const result = await databases.createDocument({ "age": 30, "isAdmin": false }, - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/databases/create-operations.md b/docs/examples/1.8.x/client-react-native/examples/databases/create-operations.md new file mode 100644 index 0000000000..bf02fd2c29 --- /dev/null +++ b/docs/examples/1.8.x/client-react-native/examples/databases/create-operations.md @@ -0,0 +1,24 @@ +import { Client, Databases } from "react-native-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.createOperations({ + transactionId: '', + operations: [ + { + "action": "create", + "databaseId": "", + "collectionId": "", + "documentId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] // optional +}); + +console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/databases/create-transaction.md b/docs/examples/1.8.x/client-react-native/examples/databases/create-transaction.md new file mode 100644 index 0000000000..07a2103e59 --- /dev/null +++ b/docs/examples/1.8.x/client-react-native/examples/databases/create-transaction.md @@ -0,0 +1,13 @@ +import { Client, Databases } from "react-native-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.createTransaction({ + ttl: 60 // optional +}); + +console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/databases/decrement-document-attribute.md b/docs/examples/1.8.x/client-react-native/examples/databases/decrement-document-attribute.md index ddf43c9758..5edce7b091 100644 --- a/docs/examples/1.8.x/client-react-native/examples/databases/decrement-document-attribute.md +++ b/docs/examples/1.8.x/client-react-native/examples/databases/decrement-document-attribute.md @@ -12,7 +12,8 @@ const result = await databases.decrementDocumentAttribute({ documentId: '', attribute: '', value: 0, // optional - min: 0 // optional + min: 0, // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/databases/delete-document.md b/docs/examples/1.8.x/client-react-native/examples/databases/delete-document.md index 828cefdda8..6cad3f9585 100644 --- a/docs/examples/1.8.x/client-react-native/examples/databases/delete-document.md +++ b/docs/examples/1.8.x/client-react-native/examples/databases/delete-document.md @@ -9,7 +9,8 @@ const databases = new Databases(client); const result = await databases.deleteDocument({ databaseId: '', collectionId: '', - documentId: '' + documentId: '', + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/databases/delete-transaction.md b/docs/examples/1.8.x/client-react-native/examples/databases/delete-transaction.md new file mode 100644 index 0000000000..9ad2661362 --- /dev/null +++ b/docs/examples/1.8.x/client-react-native/examples/databases/delete-transaction.md @@ -0,0 +1,13 @@ +import { Client, Databases } from "react-native-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.deleteTransaction({ + transactionId: '' +}); + +console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/databases/get-document.md b/docs/examples/1.8.x/client-react-native/examples/databases/get-document.md index 7d28ee03d5..c61d396d3e 100644 --- a/docs/examples/1.8.x/client-react-native/examples/databases/get-document.md +++ b/docs/examples/1.8.x/client-react-native/examples/databases/get-document.md @@ -10,7 +10,8 @@ const result = await databases.getDocument({ databaseId: '', collectionId: '', documentId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/databases/get-transaction.md b/docs/examples/1.8.x/client-react-native/examples/databases/get-transaction.md new file mode 100644 index 0000000000..47f93691e0 --- /dev/null +++ b/docs/examples/1.8.x/client-react-native/examples/databases/get-transaction.md @@ -0,0 +1,13 @@ +import { Client, Databases } from "react-native-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.getTransaction({ + transactionId: '' +}); + +console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/databases/increment-document-attribute.md b/docs/examples/1.8.x/client-react-native/examples/databases/increment-document-attribute.md index c129c38a25..259a184e3a 100644 --- a/docs/examples/1.8.x/client-react-native/examples/databases/increment-document-attribute.md +++ b/docs/examples/1.8.x/client-react-native/examples/databases/increment-document-attribute.md @@ -12,7 +12,8 @@ const result = await databases.incrementDocumentAttribute({ documentId: '', attribute: '', value: 0, // optional - max: 0 // optional + max: 0, // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/databases/list-documents.md b/docs/examples/1.8.x/client-react-native/examples/databases/list-documents.md index 8d210b08e9..a744a531a1 100644 --- a/docs/examples/1.8.x/client-react-native/examples/databases/list-documents.md +++ b/docs/examples/1.8.x/client-react-native/examples/databases/list-documents.md @@ -9,7 +9,8 @@ const databases = new Databases(client); const result = await databases.listDocuments({ databaseId: '', collectionId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/databases/list-transactions.md b/docs/examples/1.8.x/client-react-native/examples/databases/list-transactions.md new file mode 100644 index 0000000000..2339673803 --- /dev/null +++ b/docs/examples/1.8.x/client-react-native/examples/databases/list-transactions.md @@ -0,0 +1,13 @@ +import { Client, Databases } from "react-native-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.listTransactions({ + queries: [] // optional +}); + +console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/databases/update-document.md b/docs/examples/1.8.x/client-react-native/examples/databases/update-document.md index ce4a6f2222..29674bd3d0 100644 --- a/docs/examples/1.8.x/client-react-native/examples/databases/update-document.md +++ b/docs/examples/1.8.x/client-react-native/examples/databases/update-document.md @@ -11,7 +11,8 @@ const result = await databases.updateDocument({ collectionId: '', documentId: '', data: {}, // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/databases/update-transaction.md b/docs/examples/1.8.x/client-react-native/examples/databases/update-transaction.md new file mode 100644 index 0000000000..c333850656 --- /dev/null +++ b/docs/examples/1.8.x/client-react-native/examples/databases/update-transaction.md @@ -0,0 +1,15 @@ +import { Client, Databases } from "react-native-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.updateTransaction({ + transactionId: '', + commit: false, // optional + rollback: false // optional +}); + +console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/databases/upsert-document.md b/docs/examples/1.8.x/client-react-native/examples/databases/upsert-document.md index a351ed7d4d..aa8fd1ca94 100644 --- a/docs/examples/1.8.x/client-react-native/examples/databases/upsert-document.md +++ b/docs/examples/1.8.x/client-react-native/examples/databases/upsert-document.md @@ -11,7 +11,8 @@ const result = await databases.upsertDocument({ collectionId: '', documentId: '', data: {}, - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/tablesdb/create-operations.md b/docs/examples/1.8.x/client-react-native/examples/tablesdb/create-operations.md new file mode 100644 index 0000000000..1c76de77d2 --- /dev/null +++ b/docs/examples/1.8.x/client-react-native/examples/tablesdb/create-operations.md @@ -0,0 +1,24 @@ +import { Client, TablesDB } from "react-native-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const tablesDB = new TablesDB(client); + +const result = await tablesDB.createOperations({ + transactionId: '', + operations: [ + { + "action": "create", + "databaseId": "", + "tableId": "", + "rowId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] // optional +}); + +console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/tablesdb/create-row.md b/docs/examples/1.8.x/client-react-native/examples/tablesdb/create-row.md index a02a8376d5..6be799f547 100644 --- a/docs/examples/1.8.x/client-react-native/examples/tablesdb/create-row.md +++ b/docs/examples/1.8.x/client-react-native/examples/tablesdb/create-row.md @@ -17,7 +17,8 @@ const result = await tablesDB.createRow({ "age": 30, "isAdmin": false }, - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/tablesdb/create-transaction.md b/docs/examples/1.8.x/client-react-native/examples/tablesdb/create-transaction.md new file mode 100644 index 0000000000..c2eca27695 --- /dev/null +++ b/docs/examples/1.8.x/client-react-native/examples/tablesdb/create-transaction.md @@ -0,0 +1,13 @@ +import { Client, TablesDB } from "react-native-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const tablesDB = new TablesDB(client); + +const result = await tablesDB.createTransaction({ + ttl: 60 // optional +}); + +console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/tablesdb/decrement-row-column.md b/docs/examples/1.8.x/client-react-native/examples/tablesdb/decrement-row-column.md index e00eeb84bf..7bf6d77a46 100644 --- a/docs/examples/1.8.x/client-react-native/examples/tablesdb/decrement-row-column.md +++ b/docs/examples/1.8.x/client-react-native/examples/tablesdb/decrement-row-column.md @@ -12,7 +12,8 @@ const result = await tablesDB.decrementRowColumn({ rowId: '', column: '', value: 0, // optional - min: 0 // optional + min: 0, // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/tablesdb/delete-row.md b/docs/examples/1.8.x/client-react-native/examples/tablesdb/delete-row.md index 624f1a191f..3ab81237eb 100644 --- a/docs/examples/1.8.x/client-react-native/examples/tablesdb/delete-row.md +++ b/docs/examples/1.8.x/client-react-native/examples/tablesdb/delete-row.md @@ -9,7 +9,8 @@ const tablesDB = new TablesDB(client); const result = await tablesDB.deleteRow({ databaseId: '', tableId: '', - rowId: '' + rowId: '', + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/tablesdb/delete-transaction.md b/docs/examples/1.8.x/client-react-native/examples/tablesdb/delete-transaction.md new file mode 100644 index 0000000000..121e6b3f67 --- /dev/null +++ b/docs/examples/1.8.x/client-react-native/examples/tablesdb/delete-transaction.md @@ -0,0 +1,13 @@ +import { Client, TablesDB } from "react-native-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const tablesDB = new TablesDB(client); + +const result = await tablesDB.deleteTransaction({ + transactionId: '' +}); + +console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/tablesdb/get-row.md b/docs/examples/1.8.x/client-react-native/examples/tablesdb/get-row.md index 081db46f18..a3a8775b4a 100644 --- a/docs/examples/1.8.x/client-react-native/examples/tablesdb/get-row.md +++ b/docs/examples/1.8.x/client-react-native/examples/tablesdb/get-row.md @@ -10,7 +10,8 @@ const result = await tablesDB.getRow({ databaseId: '', tableId: '', rowId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/tablesdb/get-transaction.md b/docs/examples/1.8.x/client-react-native/examples/tablesdb/get-transaction.md new file mode 100644 index 0000000000..475e2d83ee --- /dev/null +++ b/docs/examples/1.8.x/client-react-native/examples/tablesdb/get-transaction.md @@ -0,0 +1,13 @@ +import { Client, TablesDB } from "react-native-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const tablesDB = new TablesDB(client); + +const result = await tablesDB.getTransaction({ + transactionId: '' +}); + +console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/tablesdb/increment-row-column.md b/docs/examples/1.8.x/client-react-native/examples/tablesdb/increment-row-column.md index d4b2cf98ad..4bda1efb24 100644 --- a/docs/examples/1.8.x/client-react-native/examples/tablesdb/increment-row-column.md +++ b/docs/examples/1.8.x/client-react-native/examples/tablesdb/increment-row-column.md @@ -12,7 +12,8 @@ const result = await tablesDB.incrementRowColumn({ rowId: '', column: '', value: 0, // optional - max: 0 // optional + max: 0, // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/tablesdb/list-rows.md b/docs/examples/1.8.x/client-react-native/examples/tablesdb/list-rows.md index 6148e97e90..7cab86bc64 100644 --- a/docs/examples/1.8.x/client-react-native/examples/tablesdb/list-rows.md +++ b/docs/examples/1.8.x/client-react-native/examples/tablesdb/list-rows.md @@ -9,7 +9,8 @@ const tablesDB = new TablesDB(client); const result = await tablesDB.listRows({ databaseId: '', tableId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/tablesdb/list-transactions.md b/docs/examples/1.8.x/client-react-native/examples/tablesdb/list-transactions.md new file mode 100644 index 0000000000..9d3004a90c --- /dev/null +++ b/docs/examples/1.8.x/client-react-native/examples/tablesdb/list-transactions.md @@ -0,0 +1,13 @@ +import { Client, TablesDB } from "react-native-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const tablesDB = new TablesDB(client); + +const result = await tablesDB.listTransactions({ + queries: [] // optional +}); + +console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/tablesdb/update-row.md b/docs/examples/1.8.x/client-react-native/examples/tablesdb/update-row.md index 01ed6e6acc..a83e3ea3e1 100644 --- a/docs/examples/1.8.x/client-react-native/examples/tablesdb/update-row.md +++ b/docs/examples/1.8.x/client-react-native/examples/tablesdb/update-row.md @@ -11,7 +11,8 @@ const result = await tablesDB.updateRow({ tableId: '', rowId: '', data: {}, // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/tablesdb/update-transaction.md b/docs/examples/1.8.x/client-react-native/examples/tablesdb/update-transaction.md new file mode 100644 index 0000000000..de29a5bd2c --- /dev/null +++ b/docs/examples/1.8.x/client-react-native/examples/tablesdb/update-transaction.md @@ -0,0 +1,15 @@ +import { Client, TablesDB } from "react-native-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const tablesDB = new TablesDB(client); + +const result = await tablesDB.updateTransaction({ + transactionId: '', + commit: false, // optional + rollback: false // optional +}); + +console.log(result); diff --git a/docs/examples/1.8.x/client-react-native/examples/tablesdb/upsert-row.md b/docs/examples/1.8.x/client-react-native/examples/tablesdb/upsert-row.md index 72fad15ac4..7a82e0711e 100644 --- a/docs/examples/1.8.x/client-react-native/examples/tablesdb/upsert-row.md +++ b/docs/examples/1.8.x/client-react-native/examples/tablesdb/upsert-row.md @@ -11,7 +11,8 @@ const result = await tablesDB.upsertRow({ tableId: '', rowId: '', data: {}, // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-rest/examples/databases/create-document.md b/docs/examples/1.8.x/client-rest/examples/databases/create-document.md index 12f2159402..c53babd482 100644 --- a/docs/examples/1.8.x/client-rest/examples/databases/create-document.md +++ b/docs/examples/1.8.x/client-rest/examples/databases/create-document.md @@ -15,5 +15,6 @@ X-Appwrite-JWT: "age": 30, "isAdmin": false }, - "permissions": ["read(\"any\")"] + "permissions": ["read(\"any\")"], + "transactionId": "" } diff --git a/docs/examples/1.8.x/client-rest/examples/databases/create-operations.md b/docs/examples/1.8.x/client-rest/examples/databases/create-operations.md new file mode 100644 index 0000000000..602effd9a2 --- /dev/null +++ b/docs/examples/1.8.x/client-rest/examples/databases/create-operations.md @@ -0,0 +1,21 @@ +POST /v1/databases/transactions/{transactionId}/operations HTTP/1.1 +Host: cloud.appwrite.io +Content-Type: application/json +X-Appwrite-Response-Format: 1.8.0 +X-Appwrite-Project: +X-Appwrite-Session: +X-Appwrite-JWT: + +{ + "operations": [ + { + "action": "create", + "databaseId": "", + "collectionId": "", + "documentId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] +} diff --git a/docs/examples/1.8.x/client-rest/examples/databases/create-transaction.md b/docs/examples/1.8.x/client-rest/examples/databases/create-transaction.md new file mode 100644 index 0000000000..c58528731e --- /dev/null +++ b/docs/examples/1.8.x/client-rest/examples/databases/create-transaction.md @@ -0,0 +1,11 @@ +POST /v1/databases/transactions HTTP/1.1 +Host: cloud.appwrite.io +Content-Type: application/json +X-Appwrite-Response-Format: 1.8.0 +X-Appwrite-Project: +X-Appwrite-Session: +X-Appwrite-JWT: + +{ + "ttl": 60 +} diff --git a/docs/examples/1.8.x/client-rest/examples/databases/decrement-document-attribute.md b/docs/examples/1.8.x/client-rest/examples/databases/decrement-document-attribute.md index 85ee70588b..be1d8d5bb6 100644 --- a/docs/examples/1.8.x/client-rest/examples/databases/decrement-document-attribute.md +++ b/docs/examples/1.8.x/client-rest/examples/databases/decrement-document-attribute.md @@ -8,5 +8,6 @@ X-Appwrite-JWT: { "value": 0, - "min": 0 + "min": 0, + "transactionId": "" } diff --git a/docs/examples/1.8.x/client-rest/examples/databases/delete-document.md b/docs/examples/1.8.x/client-rest/examples/databases/delete-document.md index 2ee4f92ec4..3fa0a3ca21 100644 --- a/docs/examples/1.8.x/client-rest/examples/databases/delete-document.md +++ b/docs/examples/1.8.x/client-rest/examples/databases/delete-document.md @@ -6,3 +6,6 @@ X-Appwrite-Project: X-Appwrite-Session: X-Appwrite-JWT: +{ + "transactionId": "" +} diff --git a/docs/examples/1.8.x/client-rest/examples/databases/delete-transaction.md b/docs/examples/1.8.x/client-rest/examples/databases/delete-transaction.md new file mode 100644 index 0000000000..1982dbb5a4 --- /dev/null +++ b/docs/examples/1.8.x/client-rest/examples/databases/delete-transaction.md @@ -0,0 +1,8 @@ +DELETE /v1/databases/transactions/{transactionId} HTTP/1.1 +Host: cloud.appwrite.io +Content-Type: application/json +X-Appwrite-Response-Format: 1.8.0 +X-Appwrite-Project: +X-Appwrite-Session: +X-Appwrite-JWT: + diff --git a/docs/examples/1.8.x/client-rest/examples/databases/get-transaction.md b/docs/examples/1.8.x/client-rest/examples/databases/get-transaction.md new file mode 100644 index 0000000000..09cc2e6c95 --- /dev/null +++ b/docs/examples/1.8.x/client-rest/examples/databases/get-transaction.md @@ -0,0 +1,6 @@ +GET /v1/databases/transactions/{transactionId} HTTP/1.1 +Host: cloud.appwrite.io +X-Appwrite-Response-Format: 1.8.0 +X-Appwrite-Project: +X-Appwrite-Session: +X-Appwrite-JWT: diff --git a/docs/examples/1.8.x/client-rest/examples/databases/increment-document-attribute.md b/docs/examples/1.8.x/client-rest/examples/databases/increment-document-attribute.md index 68b091a31e..9eb873d6ff 100644 --- a/docs/examples/1.8.x/client-rest/examples/databases/increment-document-attribute.md +++ b/docs/examples/1.8.x/client-rest/examples/databases/increment-document-attribute.md @@ -8,5 +8,6 @@ X-Appwrite-JWT: { "value": 0, - "max": 0 + "max": 0, + "transactionId": "" } diff --git a/docs/examples/1.8.x/client-rest/examples/databases/list-transactions.md b/docs/examples/1.8.x/client-rest/examples/databases/list-transactions.md new file mode 100644 index 0000000000..f080df9228 --- /dev/null +++ b/docs/examples/1.8.x/client-rest/examples/databases/list-transactions.md @@ -0,0 +1,6 @@ +GET /v1/databases/transactions HTTP/1.1 +Host: cloud.appwrite.io +X-Appwrite-Response-Format: 1.8.0 +X-Appwrite-Project: +X-Appwrite-Session: +X-Appwrite-JWT: diff --git a/docs/examples/1.8.x/client-rest/examples/databases/update-document.md b/docs/examples/1.8.x/client-rest/examples/databases/update-document.md index ffc5d36011..f39cabfec3 100644 --- a/docs/examples/1.8.x/client-rest/examples/databases/update-document.md +++ b/docs/examples/1.8.x/client-rest/examples/databases/update-document.md @@ -8,5 +8,6 @@ X-Appwrite-JWT: { "data": {}, - "permissions": ["read(\"any\")"] + "permissions": ["read(\"any\")"], + "transactionId": "" } diff --git a/docs/examples/1.8.x/client-rest/examples/databases/update-transaction.md b/docs/examples/1.8.x/client-rest/examples/databases/update-transaction.md new file mode 100644 index 0000000000..e8358a9051 --- /dev/null +++ b/docs/examples/1.8.x/client-rest/examples/databases/update-transaction.md @@ -0,0 +1,12 @@ +PATCH /v1/databases/transactions/{transactionId} HTTP/1.1 +Host: cloud.appwrite.io +Content-Type: application/json +X-Appwrite-Response-Format: 1.8.0 +X-Appwrite-Project: +X-Appwrite-Session: +X-Appwrite-JWT: + +{ + "commit": false, + "rollback": false +} diff --git a/docs/examples/1.8.x/client-rest/examples/databases/upsert-document.md b/docs/examples/1.8.x/client-rest/examples/databases/upsert-document.md index d2baeac6a8..c84d74a5ff 100644 --- a/docs/examples/1.8.x/client-rest/examples/databases/upsert-document.md +++ b/docs/examples/1.8.x/client-rest/examples/databases/upsert-document.md @@ -8,5 +8,6 @@ X-Appwrite-JWT: { "data": {}, - "permissions": ["read(\"any\")"] + "permissions": ["read(\"any\")"], + "transactionId": "" } diff --git a/docs/examples/1.8.x/client-rest/examples/tablesdb/create-operations.md b/docs/examples/1.8.x/client-rest/examples/tablesdb/create-operations.md new file mode 100644 index 0000000000..dd3a05e271 --- /dev/null +++ b/docs/examples/1.8.x/client-rest/examples/tablesdb/create-operations.md @@ -0,0 +1,21 @@ +POST /v1/tablesdb/transactions/{transactionId}/operations HTTP/1.1 +Host: cloud.appwrite.io +Content-Type: application/json +X-Appwrite-Response-Format: 1.8.0 +X-Appwrite-Project: +X-Appwrite-Session: +X-Appwrite-JWT: + +{ + "operations": [ + { + "action": "create", + "databaseId": "", + "tableId": "", + "rowId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] +} diff --git a/docs/examples/1.8.x/client-rest/examples/tablesdb/create-row.md b/docs/examples/1.8.x/client-rest/examples/tablesdb/create-row.md index 34d8ab5152..2abe0cc316 100644 --- a/docs/examples/1.8.x/client-rest/examples/tablesdb/create-row.md +++ b/docs/examples/1.8.x/client-rest/examples/tablesdb/create-row.md @@ -15,5 +15,6 @@ X-Appwrite-JWT: "age": 30, "isAdmin": false }, - "permissions": ["read(\"any\")"] + "permissions": ["read(\"any\")"], + "transactionId": "" } diff --git a/docs/examples/1.8.x/client-rest/examples/tablesdb/create-transaction.md b/docs/examples/1.8.x/client-rest/examples/tablesdb/create-transaction.md new file mode 100644 index 0000000000..e796ea2b57 --- /dev/null +++ b/docs/examples/1.8.x/client-rest/examples/tablesdb/create-transaction.md @@ -0,0 +1,11 @@ +POST /v1/tablesdb/transactions HTTP/1.1 +Host: cloud.appwrite.io +Content-Type: application/json +X-Appwrite-Response-Format: 1.8.0 +X-Appwrite-Project: +X-Appwrite-Session: +X-Appwrite-JWT: + +{ + "ttl": 60 +} diff --git a/docs/examples/1.8.x/client-rest/examples/tablesdb/decrement-row-column.md b/docs/examples/1.8.x/client-rest/examples/tablesdb/decrement-row-column.md index 676e090150..b8dd25fdc5 100644 --- a/docs/examples/1.8.x/client-rest/examples/tablesdb/decrement-row-column.md +++ b/docs/examples/1.8.x/client-rest/examples/tablesdb/decrement-row-column.md @@ -8,5 +8,6 @@ X-Appwrite-JWT: { "value": 0, - "min": 0 + "min": 0, + "transactionId": "" } diff --git a/docs/examples/1.8.x/client-rest/examples/tablesdb/delete-row.md b/docs/examples/1.8.x/client-rest/examples/tablesdb/delete-row.md index f3ba056f7e..908bc4cc1f 100644 --- a/docs/examples/1.8.x/client-rest/examples/tablesdb/delete-row.md +++ b/docs/examples/1.8.x/client-rest/examples/tablesdb/delete-row.md @@ -6,3 +6,6 @@ X-Appwrite-Project: X-Appwrite-Session: X-Appwrite-JWT: +{ + "transactionId": "" +} diff --git a/docs/examples/1.8.x/client-rest/examples/tablesdb/delete-transaction.md b/docs/examples/1.8.x/client-rest/examples/tablesdb/delete-transaction.md new file mode 100644 index 0000000000..54421d1c47 --- /dev/null +++ b/docs/examples/1.8.x/client-rest/examples/tablesdb/delete-transaction.md @@ -0,0 +1,8 @@ +DELETE /v1/tablesdb/transactions/{transactionId} HTTP/1.1 +Host: cloud.appwrite.io +Content-Type: application/json +X-Appwrite-Response-Format: 1.8.0 +X-Appwrite-Project: +X-Appwrite-Session: +X-Appwrite-JWT: + diff --git a/docs/examples/1.8.x/client-rest/examples/tablesdb/get-transaction.md b/docs/examples/1.8.x/client-rest/examples/tablesdb/get-transaction.md new file mode 100644 index 0000000000..4276a3fb94 --- /dev/null +++ b/docs/examples/1.8.x/client-rest/examples/tablesdb/get-transaction.md @@ -0,0 +1,6 @@ +GET /v1/tablesdb/transactions/{transactionId} HTTP/1.1 +Host: cloud.appwrite.io +X-Appwrite-Response-Format: 1.8.0 +X-Appwrite-Project: +X-Appwrite-Session: +X-Appwrite-JWT: diff --git a/docs/examples/1.8.x/client-rest/examples/tablesdb/increment-row-column.md b/docs/examples/1.8.x/client-rest/examples/tablesdb/increment-row-column.md index 5172cb420b..be9effd073 100644 --- a/docs/examples/1.8.x/client-rest/examples/tablesdb/increment-row-column.md +++ b/docs/examples/1.8.x/client-rest/examples/tablesdb/increment-row-column.md @@ -8,5 +8,6 @@ X-Appwrite-JWT: { "value": 0, - "max": 0 + "max": 0, + "transactionId": "" } diff --git a/docs/examples/1.8.x/client-rest/examples/tablesdb/list-transactions.md b/docs/examples/1.8.x/client-rest/examples/tablesdb/list-transactions.md new file mode 100644 index 0000000000..91b6108463 --- /dev/null +++ b/docs/examples/1.8.x/client-rest/examples/tablesdb/list-transactions.md @@ -0,0 +1,6 @@ +GET /v1/tablesdb/transactions HTTP/1.1 +Host: cloud.appwrite.io +X-Appwrite-Response-Format: 1.8.0 +X-Appwrite-Project: +X-Appwrite-Session: +X-Appwrite-JWT: diff --git a/docs/examples/1.8.x/client-rest/examples/tablesdb/update-row.md b/docs/examples/1.8.x/client-rest/examples/tablesdb/update-row.md index 40d276a0fe..7249d93906 100644 --- a/docs/examples/1.8.x/client-rest/examples/tablesdb/update-row.md +++ b/docs/examples/1.8.x/client-rest/examples/tablesdb/update-row.md @@ -8,5 +8,6 @@ X-Appwrite-JWT: { "data": {}, - "permissions": ["read(\"any\")"] + "permissions": ["read(\"any\")"], + "transactionId": "" } diff --git a/docs/examples/1.8.x/client-rest/examples/tablesdb/update-transaction.md b/docs/examples/1.8.x/client-rest/examples/tablesdb/update-transaction.md new file mode 100644 index 0000000000..f0f96d735f --- /dev/null +++ b/docs/examples/1.8.x/client-rest/examples/tablesdb/update-transaction.md @@ -0,0 +1,12 @@ +PATCH /v1/tablesdb/transactions/{transactionId} HTTP/1.1 +Host: cloud.appwrite.io +Content-Type: application/json +X-Appwrite-Response-Format: 1.8.0 +X-Appwrite-Project: +X-Appwrite-Session: +X-Appwrite-JWT: + +{ + "commit": false, + "rollback": false +} diff --git a/docs/examples/1.8.x/client-rest/examples/tablesdb/upsert-row.md b/docs/examples/1.8.x/client-rest/examples/tablesdb/upsert-row.md index 581790fc01..93f6236eca 100644 --- a/docs/examples/1.8.x/client-rest/examples/tablesdb/upsert-row.md +++ b/docs/examples/1.8.x/client-rest/examples/tablesdb/upsert-row.md @@ -8,5 +8,6 @@ X-Appwrite-JWT: { "data": {}, - "permissions": ["read(\"any\")"] + "permissions": ["read(\"any\")"], + "transactionId": "" } diff --git a/docs/examples/1.8.x/client-web/examples/databases/create-document.md b/docs/examples/1.8.x/client-web/examples/databases/create-document.md index 08606c9b4f..8417575ebf 100644 --- a/docs/examples/1.8.x/client-web/examples/databases/create-document.md +++ b/docs/examples/1.8.x/client-web/examples/databases/create-document.md @@ -17,7 +17,8 @@ const result = await databases.createDocument({ "age": 30, "isAdmin": false }, - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/databases/create-operations.md b/docs/examples/1.8.x/client-web/examples/databases/create-operations.md new file mode 100644 index 0000000000..2ebc085d44 --- /dev/null +++ b/docs/examples/1.8.x/client-web/examples/databases/create-operations.md @@ -0,0 +1,24 @@ +import { Client, Databases } from "appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.createOperations({ + transactionId: '', + operations: [ + { + "action": "create", + "databaseId": "", + "collectionId": "", + "documentId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] // optional +}); + +console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/databases/create-transaction.md b/docs/examples/1.8.x/client-web/examples/databases/create-transaction.md new file mode 100644 index 0000000000..5371412cc9 --- /dev/null +++ b/docs/examples/1.8.x/client-web/examples/databases/create-transaction.md @@ -0,0 +1,13 @@ +import { Client, Databases } from "appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.createTransaction({ + ttl: 60 // optional +}); + +console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/databases/decrement-document-attribute.md b/docs/examples/1.8.x/client-web/examples/databases/decrement-document-attribute.md index 98629c4e6c..f8e0ae9829 100644 --- a/docs/examples/1.8.x/client-web/examples/databases/decrement-document-attribute.md +++ b/docs/examples/1.8.x/client-web/examples/databases/decrement-document-attribute.md @@ -12,7 +12,8 @@ const result = await databases.decrementDocumentAttribute({ documentId: '', attribute: '', value: null, // optional - min: null // optional + min: null, // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/databases/delete-document.md b/docs/examples/1.8.x/client-web/examples/databases/delete-document.md index 4192085653..4d10afdac5 100644 --- a/docs/examples/1.8.x/client-web/examples/databases/delete-document.md +++ b/docs/examples/1.8.x/client-web/examples/databases/delete-document.md @@ -9,7 +9,8 @@ const databases = new Databases(client); const result = await databases.deleteDocument({ databaseId: '', collectionId: '', - documentId: '' + documentId: '', + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/databases/delete-transaction.md b/docs/examples/1.8.x/client-web/examples/databases/delete-transaction.md new file mode 100644 index 0000000000..afe55c547a --- /dev/null +++ b/docs/examples/1.8.x/client-web/examples/databases/delete-transaction.md @@ -0,0 +1,13 @@ +import { Client, Databases } from "appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.deleteTransaction({ + transactionId: '' +}); + +console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/databases/get-document.md b/docs/examples/1.8.x/client-web/examples/databases/get-document.md index b3a7558907..5a44aeb73e 100644 --- a/docs/examples/1.8.x/client-web/examples/databases/get-document.md +++ b/docs/examples/1.8.x/client-web/examples/databases/get-document.md @@ -10,7 +10,8 @@ const result = await databases.getDocument({ databaseId: '', collectionId: '', documentId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/databases/get-transaction.md b/docs/examples/1.8.x/client-web/examples/databases/get-transaction.md new file mode 100644 index 0000000000..cc51199a76 --- /dev/null +++ b/docs/examples/1.8.x/client-web/examples/databases/get-transaction.md @@ -0,0 +1,13 @@ +import { Client, Databases } from "appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.getTransaction({ + transactionId: '' +}); + +console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/databases/increment-document-attribute.md b/docs/examples/1.8.x/client-web/examples/databases/increment-document-attribute.md index 8adb5d8091..eaf718e98d 100644 --- a/docs/examples/1.8.x/client-web/examples/databases/increment-document-attribute.md +++ b/docs/examples/1.8.x/client-web/examples/databases/increment-document-attribute.md @@ -12,7 +12,8 @@ const result = await databases.incrementDocumentAttribute({ documentId: '', attribute: '', value: null, // optional - max: null // optional + max: null, // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/databases/list-documents.md b/docs/examples/1.8.x/client-web/examples/databases/list-documents.md index fb1d508fed..ece656a644 100644 --- a/docs/examples/1.8.x/client-web/examples/databases/list-documents.md +++ b/docs/examples/1.8.x/client-web/examples/databases/list-documents.md @@ -9,7 +9,8 @@ const databases = new Databases(client); const result = await databases.listDocuments({ databaseId: '', collectionId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/databases/list-transactions.md b/docs/examples/1.8.x/client-web/examples/databases/list-transactions.md new file mode 100644 index 0000000000..f2ce1f7536 --- /dev/null +++ b/docs/examples/1.8.x/client-web/examples/databases/list-transactions.md @@ -0,0 +1,13 @@ +import { Client, Databases } from "appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.listTransactions({ + queries: [] // optional +}); + +console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/databases/update-document.md b/docs/examples/1.8.x/client-web/examples/databases/update-document.md index bf3554812d..33a6d73a12 100644 --- a/docs/examples/1.8.x/client-web/examples/databases/update-document.md +++ b/docs/examples/1.8.x/client-web/examples/databases/update-document.md @@ -11,7 +11,8 @@ const result = await databases.updateDocument({ collectionId: '', documentId: '', data: {}, // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/databases/update-transaction.md b/docs/examples/1.8.x/client-web/examples/databases/update-transaction.md new file mode 100644 index 0000000000..9274b0f9bf --- /dev/null +++ b/docs/examples/1.8.x/client-web/examples/databases/update-transaction.md @@ -0,0 +1,15 @@ +import { Client, Databases } from "appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.updateTransaction({ + transactionId: '', + commit: false, // optional + rollback: false // optional +}); + +console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/databases/upsert-document.md b/docs/examples/1.8.x/client-web/examples/databases/upsert-document.md index c56bc5534d..e14ad5fc6b 100644 --- a/docs/examples/1.8.x/client-web/examples/databases/upsert-document.md +++ b/docs/examples/1.8.x/client-web/examples/databases/upsert-document.md @@ -11,7 +11,8 @@ const result = await databases.upsertDocument({ collectionId: '', documentId: '', data: {}, - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/tablesdb/create-operations.md b/docs/examples/1.8.x/client-web/examples/tablesdb/create-operations.md new file mode 100644 index 0000000000..c25b051430 --- /dev/null +++ b/docs/examples/1.8.x/client-web/examples/tablesdb/create-operations.md @@ -0,0 +1,24 @@ +import { Client, TablesDB } from "appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const tablesDB = new TablesDB(client); + +const result = await tablesDB.createOperations({ + transactionId: '', + operations: [ + { + "action": "create", + "databaseId": "", + "tableId": "", + "rowId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] // optional +}); + +console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/tablesdb/create-row.md b/docs/examples/1.8.x/client-web/examples/tablesdb/create-row.md index 1dd1fe4241..3bbcf89d4f 100644 --- a/docs/examples/1.8.x/client-web/examples/tablesdb/create-row.md +++ b/docs/examples/1.8.x/client-web/examples/tablesdb/create-row.md @@ -17,7 +17,8 @@ const result = await tablesDB.createRow({ "age": 30, "isAdmin": false }, - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/tablesdb/create-transaction.md b/docs/examples/1.8.x/client-web/examples/tablesdb/create-transaction.md new file mode 100644 index 0000000000..17787dc9a3 --- /dev/null +++ b/docs/examples/1.8.x/client-web/examples/tablesdb/create-transaction.md @@ -0,0 +1,13 @@ +import { Client, TablesDB } from "appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const tablesDB = new TablesDB(client); + +const result = await tablesDB.createTransaction({ + ttl: 60 // optional +}); + +console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/tablesdb/decrement-row-column.md b/docs/examples/1.8.x/client-web/examples/tablesdb/decrement-row-column.md index 59f66d973f..d6c64645f3 100644 --- a/docs/examples/1.8.x/client-web/examples/tablesdb/decrement-row-column.md +++ b/docs/examples/1.8.x/client-web/examples/tablesdb/decrement-row-column.md @@ -12,7 +12,8 @@ const result = await tablesDB.decrementRowColumn({ rowId: '', column: '', value: null, // optional - min: null // optional + min: null, // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/tablesdb/delete-row.md b/docs/examples/1.8.x/client-web/examples/tablesdb/delete-row.md index 637114d413..54c005c702 100644 --- a/docs/examples/1.8.x/client-web/examples/tablesdb/delete-row.md +++ b/docs/examples/1.8.x/client-web/examples/tablesdb/delete-row.md @@ -9,7 +9,8 @@ const tablesDB = new TablesDB(client); const result = await tablesDB.deleteRow({ databaseId: '', tableId: '', - rowId: '' + rowId: '', + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/tablesdb/delete-transaction.md b/docs/examples/1.8.x/client-web/examples/tablesdb/delete-transaction.md new file mode 100644 index 0000000000..2ff1198225 --- /dev/null +++ b/docs/examples/1.8.x/client-web/examples/tablesdb/delete-transaction.md @@ -0,0 +1,13 @@ +import { Client, TablesDB } from "appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const tablesDB = new TablesDB(client); + +const result = await tablesDB.deleteTransaction({ + transactionId: '' +}); + +console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/tablesdb/get-row.md b/docs/examples/1.8.x/client-web/examples/tablesdb/get-row.md index 4e436432b7..b345d145aa 100644 --- a/docs/examples/1.8.x/client-web/examples/tablesdb/get-row.md +++ b/docs/examples/1.8.x/client-web/examples/tablesdb/get-row.md @@ -10,7 +10,8 @@ const result = await tablesDB.getRow({ databaseId: '', tableId: '', rowId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/tablesdb/get-transaction.md b/docs/examples/1.8.x/client-web/examples/tablesdb/get-transaction.md new file mode 100644 index 0000000000..8e2f24cd4c --- /dev/null +++ b/docs/examples/1.8.x/client-web/examples/tablesdb/get-transaction.md @@ -0,0 +1,13 @@ +import { Client, TablesDB } from "appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const tablesDB = new TablesDB(client); + +const result = await tablesDB.getTransaction({ + transactionId: '' +}); + +console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/tablesdb/increment-row-column.md b/docs/examples/1.8.x/client-web/examples/tablesdb/increment-row-column.md index a7f3a8c312..5baca80c35 100644 --- a/docs/examples/1.8.x/client-web/examples/tablesdb/increment-row-column.md +++ b/docs/examples/1.8.x/client-web/examples/tablesdb/increment-row-column.md @@ -12,7 +12,8 @@ const result = await tablesDB.incrementRowColumn({ rowId: '', column: '', value: null, // optional - max: null // optional + max: null, // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/tablesdb/list-rows.md b/docs/examples/1.8.x/client-web/examples/tablesdb/list-rows.md index 63149aaba4..c0efd8486c 100644 --- a/docs/examples/1.8.x/client-web/examples/tablesdb/list-rows.md +++ b/docs/examples/1.8.x/client-web/examples/tablesdb/list-rows.md @@ -9,7 +9,8 @@ const tablesDB = new TablesDB(client); const result = await tablesDB.listRows({ databaseId: '', tableId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/tablesdb/list-transactions.md b/docs/examples/1.8.x/client-web/examples/tablesdb/list-transactions.md new file mode 100644 index 0000000000..fbf0908a81 --- /dev/null +++ b/docs/examples/1.8.x/client-web/examples/tablesdb/list-transactions.md @@ -0,0 +1,13 @@ +import { Client, TablesDB } from "appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const tablesDB = new TablesDB(client); + +const result = await tablesDB.listTransactions({ + queries: [] // optional +}); + +console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/tablesdb/update-row.md b/docs/examples/1.8.x/client-web/examples/tablesdb/update-row.md index 1dba006762..ecbcd4fc7a 100644 --- a/docs/examples/1.8.x/client-web/examples/tablesdb/update-row.md +++ b/docs/examples/1.8.x/client-web/examples/tablesdb/update-row.md @@ -11,7 +11,8 @@ const result = await tablesDB.updateRow({ tableId: '', rowId: '', data: {}, // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/tablesdb/update-transaction.md b/docs/examples/1.8.x/client-web/examples/tablesdb/update-transaction.md new file mode 100644 index 0000000000..2d987e4235 --- /dev/null +++ b/docs/examples/1.8.x/client-web/examples/tablesdb/update-transaction.md @@ -0,0 +1,15 @@ +import { Client, TablesDB } from "appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const tablesDB = new TablesDB(client); + +const result = await tablesDB.updateTransaction({ + transactionId: '', + commit: false, // optional + rollback: false // optional +}); + +console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/tablesdb/upsert-row.md b/docs/examples/1.8.x/client-web/examples/tablesdb/upsert-row.md index 1add1c45b9..ddac9ff327 100644 --- a/docs/examples/1.8.x/client-web/examples/tablesdb/upsert-row.md +++ b/docs/examples/1.8.x/client-web/examples/tablesdb/upsert-row.md @@ -11,7 +11,8 @@ const result = await tablesDB.upsertRow({ tableId: '', rowId: '', data: {}, // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-cli/examples/databases/create-operations.md b/docs/examples/1.8.x/console-cli/examples/databases/create-operations.md new file mode 100644 index 0000000000..367b435c9d --- /dev/null +++ b/docs/examples/1.8.x/console-cli/examples/databases/create-operations.md @@ -0,0 +1,2 @@ +appwrite databases create-operations \ + --transaction-id diff --git a/docs/examples/1.8.x/console-cli/examples/databases/create-transaction.md b/docs/examples/1.8.x/console-cli/examples/databases/create-transaction.md new file mode 100644 index 0000000000..ef348e75ad --- /dev/null +++ b/docs/examples/1.8.x/console-cli/examples/databases/create-transaction.md @@ -0,0 +1 @@ +appwrite databases create-transaction diff --git a/docs/examples/1.8.x/console-cli/examples/databases/delete-transaction.md b/docs/examples/1.8.x/console-cli/examples/databases/delete-transaction.md new file mode 100644 index 0000000000..13c02b676b --- /dev/null +++ b/docs/examples/1.8.x/console-cli/examples/databases/delete-transaction.md @@ -0,0 +1,2 @@ +appwrite databases delete-transaction \ + --transaction-id diff --git a/docs/examples/1.8.x/console-cli/examples/databases/get-transaction.md b/docs/examples/1.8.x/console-cli/examples/databases/get-transaction.md new file mode 100644 index 0000000000..7fc80e40d2 --- /dev/null +++ b/docs/examples/1.8.x/console-cli/examples/databases/get-transaction.md @@ -0,0 +1,2 @@ +appwrite databases get-transaction \ + --transaction-id diff --git a/docs/examples/1.8.x/console-cli/examples/databases/list-transactions.md b/docs/examples/1.8.x/console-cli/examples/databases/list-transactions.md new file mode 100644 index 0000000000..f0cc259b43 --- /dev/null +++ b/docs/examples/1.8.x/console-cli/examples/databases/list-transactions.md @@ -0,0 +1 @@ +appwrite databases list-transactions diff --git a/docs/examples/1.8.x/console-cli/examples/databases/update-transaction.md b/docs/examples/1.8.x/console-cli/examples/databases/update-transaction.md new file mode 100644 index 0000000000..cda11d4e5f --- /dev/null +++ b/docs/examples/1.8.x/console-cli/examples/databases/update-transaction.md @@ -0,0 +1,2 @@ +appwrite databases update-transaction \ + --transaction-id diff --git a/docs/examples/1.8.x/console-cli/examples/migrations/create-csv-migration.md b/docs/examples/1.8.x/console-cli/examples/migrations/create-csv-migration.md index 4b72b6f689..10e7b42b6c 100644 --- a/docs/examples/1.8.x/console-cli/examples/migrations/create-csv-migration.md +++ b/docs/examples/1.8.x/console-cli/examples/migrations/create-csv-migration.md @@ -1,4 +1,4 @@ appwrite migrations create-csv-migration \ --bucket-id \ --file-id \ - --resource-id [ID1:ID2] + --resource-id diff --git a/docs/examples/1.8.x/console-cli/examples/tablesdb/create-operations.md b/docs/examples/1.8.x/console-cli/examples/tablesdb/create-operations.md new file mode 100644 index 0000000000..dbea61862b --- /dev/null +++ b/docs/examples/1.8.x/console-cli/examples/tablesdb/create-operations.md @@ -0,0 +1,2 @@ +appwrite tables-db create-operations \ + --transaction-id diff --git a/docs/examples/1.8.x/console-cli/examples/tablesdb/create-transaction.md b/docs/examples/1.8.x/console-cli/examples/tablesdb/create-transaction.md new file mode 100644 index 0000000000..c6487fd74a --- /dev/null +++ b/docs/examples/1.8.x/console-cli/examples/tablesdb/create-transaction.md @@ -0,0 +1 @@ +appwrite tables-db create-transaction diff --git a/docs/examples/1.8.x/console-cli/examples/tablesdb/delete-transaction.md b/docs/examples/1.8.x/console-cli/examples/tablesdb/delete-transaction.md new file mode 100644 index 0000000000..59e40d2fda --- /dev/null +++ b/docs/examples/1.8.x/console-cli/examples/tablesdb/delete-transaction.md @@ -0,0 +1,2 @@ +appwrite tables-db delete-transaction \ + --transaction-id diff --git a/docs/examples/1.8.x/console-cli/examples/tablesdb/get-transaction.md b/docs/examples/1.8.x/console-cli/examples/tablesdb/get-transaction.md new file mode 100644 index 0000000000..29ea9d75da --- /dev/null +++ b/docs/examples/1.8.x/console-cli/examples/tablesdb/get-transaction.md @@ -0,0 +1,2 @@ +appwrite tables-db get-transaction \ + --transaction-id diff --git a/docs/examples/1.8.x/console-cli/examples/tablesdb/list-transactions.md b/docs/examples/1.8.x/console-cli/examples/tablesdb/list-transactions.md new file mode 100644 index 0000000000..4dfbc2e567 --- /dev/null +++ b/docs/examples/1.8.x/console-cli/examples/tablesdb/list-transactions.md @@ -0,0 +1 @@ +appwrite tables-db list-transactions diff --git a/docs/examples/1.8.x/console-cli/examples/tablesdb/update-transaction.md b/docs/examples/1.8.x/console-cli/examples/tablesdb/update-transaction.md new file mode 100644 index 0000000000..6fa6d9510e --- /dev/null +++ b/docs/examples/1.8.x/console-cli/examples/tablesdb/update-transaction.md @@ -0,0 +1,2 @@ +appwrite tables-db update-transaction \ + --transaction-id diff --git a/docs/examples/1.8.x/console-web/examples/databases/create-document.md b/docs/examples/1.8.x/console-web/examples/databases/create-document.md index 40fbd4ad85..80f3fe66ad 100644 --- a/docs/examples/1.8.x/console-web/examples/databases/create-document.md +++ b/docs/examples/1.8.x/console-web/examples/databases/create-document.md @@ -17,7 +17,8 @@ const result = await databases.createDocument({ "age": 30, "isAdmin": false }, - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/databases/create-documents.md b/docs/examples/1.8.x/console-web/examples/databases/create-documents.md index 901133ac0a..10738b0f11 100644 --- a/docs/examples/1.8.x/console-web/examples/databases/create-documents.md +++ b/docs/examples/1.8.x/console-web/examples/databases/create-documents.md @@ -9,7 +9,8 @@ const databases = new Databases(client); const result = await databases.createDocuments({ databaseId: '', collectionId: '', - documents: [] + documents: [], + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/databases/create-operations.md b/docs/examples/1.8.x/console-web/examples/databases/create-operations.md new file mode 100644 index 0000000000..ec511b0ddc --- /dev/null +++ b/docs/examples/1.8.x/console-web/examples/databases/create-operations.md @@ -0,0 +1,24 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.createOperations({ + transactionId: '', + operations: [ + { + "action": "create", + "databaseId": "", + "collectionId": "", + "documentId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] // optional +}); + +console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/databases/create-transaction.md b/docs/examples/1.8.x/console-web/examples/databases/create-transaction.md new file mode 100644 index 0000000000..fc84f1d14f --- /dev/null +++ b/docs/examples/1.8.x/console-web/examples/databases/create-transaction.md @@ -0,0 +1,13 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.createTransaction({ + ttl: 60 // optional +}); + +console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/databases/decrement-document-attribute.md b/docs/examples/1.8.x/console-web/examples/databases/decrement-document-attribute.md index ec014643bb..64f469c6ef 100644 --- a/docs/examples/1.8.x/console-web/examples/databases/decrement-document-attribute.md +++ b/docs/examples/1.8.x/console-web/examples/databases/decrement-document-attribute.md @@ -12,7 +12,8 @@ const result = await databases.decrementDocumentAttribute({ documentId: '', attribute: '', value: null, // optional - min: null // optional + min: null, // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/databases/delete-document.md b/docs/examples/1.8.x/console-web/examples/databases/delete-document.md index 11cf317147..c2cdad3d84 100644 --- a/docs/examples/1.8.x/console-web/examples/databases/delete-document.md +++ b/docs/examples/1.8.x/console-web/examples/databases/delete-document.md @@ -9,7 +9,8 @@ const databases = new Databases(client); const result = await databases.deleteDocument({ databaseId: '', collectionId: '', - documentId: '' + documentId: '', + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/databases/delete-documents.md b/docs/examples/1.8.x/console-web/examples/databases/delete-documents.md index 45601a5985..0749194c97 100644 --- a/docs/examples/1.8.x/console-web/examples/databases/delete-documents.md +++ b/docs/examples/1.8.x/console-web/examples/databases/delete-documents.md @@ -9,7 +9,8 @@ const databases = new Databases(client); const result = await databases.deleteDocuments({ databaseId: '', collectionId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/databases/delete-transaction.md b/docs/examples/1.8.x/console-web/examples/databases/delete-transaction.md new file mode 100644 index 0000000000..16b7c64022 --- /dev/null +++ b/docs/examples/1.8.x/console-web/examples/databases/delete-transaction.md @@ -0,0 +1,13 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.deleteTransaction({ + transactionId: '' +}); + +console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/databases/get-document.md b/docs/examples/1.8.x/console-web/examples/databases/get-document.md index 00595b1033..8d893df7d9 100644 --- a/docs/examples/1.8.x/console-web/examples/databases/get-document.md +++ b/docs/examples/1.8.x/console-web/examples/databases/get-document.md @@ -10,7 +10,8 @@ const result = await databases.getDocument({ databaseId: '', collectionId: '', documentId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/databases/get-transaction.md b/docs/examples/1.8.x/console-web/examples/databases/get-transaction.md new file mode 100644 index 0000000000..8b6733b423 --- /dev/null +++ b/docs/examples/1.8.x/console-web/examples/databases/get-transaction.md @@ -0,0 +1,13 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.getTransaction({ + transactionId: '' +}); + +console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/databases/increment-document-attribute.md b/docs/examples/1.8.x/console-web/examples/databases/increment-document-attribute.md index 2207e94563..dbba4b0688 100644 --- a/docs/examples/1.8.x/console-web/examples/databases/increment-document-attribute.md +++ b/docs/examples/1.8.x/console-web/examples/databases/increment-document-attribute.md @@ -12,7 +12,8 @@ const result = await databases.incrementDocumentAttribute({ documentId: '', attribute: '', value: null, // optional - max: null // optional + max: null, // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/databases/list-documents.md b/docs/examples/1.8.x/console-web/examples/databases/list-documents.md index dda036951c..f0a7a27890 100644 --- a/docs/examples/1.8.x/console-web/examples/databases/list-documents.md +++ b/docs/examples/1.8.x/console-web/examples/databases/list-documents.md @@ -9,7 +9,8 @@ const databases = new Databases(client); const result = await databases.listDocuments({ databaseId: '', collectionId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/databases/list-transactions.md b/docs/examples/1.8.x/console-web/examples/databases/list-transactions.md new file mode 100644 index 0000000000..53e8d61f3e --- /dev/null +++ b/docs/examples/1.8.x/console-web/examples/databases/list-transactions.md @@ -0,0 +1,13 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.listTransactions({ + queries: [] // optional +}); + +console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/databases/update-document.md b/docs/examples/1.8.x/console-web/examples/databases/update-document.md index 168ad11bda..8a92d5b9f4 100644 --- a/docs/examples/1.8.x/console-web/examples/databases/update-document.md +++ b/docs/examples/1.8.x/console-web/examples/databases/update-document.md @@ -11,7 +11,8 @@ const result = await databases.updateDocument({ collectionId: '', documentId: '', data: {}, // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/databases/update-documents.md b/docs/examples/1.8.x/console-web/examples/databases/update-documents.md index 7462502c81..9f9054bad2 100644 --- a/docs/examples/1.8.x/console-web/examples/databases/update-documents.md +++ b/docs/examples/1.8.x/console-web/examples/databases/update-documents.md @@ -10,7 +10,8 @@ const result = await databases.updateDocuments({ databaseId: '', collectionId: '', data: {}, // optional - queries: [] // optional + queries: [], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/databases/update-transaction.md b/docs/examples/1.8.x/console-web/examples/databases/update-transaction.md new file mode 100644 index 0000000000..4a219f4beb --- /dev/null +++ b/docs/examples/1.8.x/console-web/examples/databases/update-transaction.md @@ -0,0 +1,15 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.updateTransaction({ + transactionId: '', + commit: false, // optional + rollback: false // optional +}); + +console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/databases/upsert-document.md b/docs/examples/1.8.x/console-web/examples/databases/upsert-document.md index 3f8705f7c8..e7a52fd7cd 100644 --- a/docs/examples/1.8.x/console-web/examples/databases/upsert-document.md +++ b/docs/examples/1.8.x/console-web/examples/databases/upsert-document.md @@ -11,7 +11,8 @@ const result = await databases.upsertDocument({ collectionId: '', documentId: '', data: {}, - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/databases/upsert-documents.md b/docs/examples/1.8.x/console-web/examples/databases/upsert-documents.md index b045516281..cc561de247 100644 --- a/docs/examples/1.8.x/console-web/examples/databases/upsert-documents.md +++ b/docs/examples/1.8.x/console-web/examples/databases/upsert-documents.md @@ -9,7 +9,8 @@ const databases = new Databases(client); const result = await databases.upsertDocuments({ databaseId: '', collectionId: '', - documents: [] + documents: [], + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/messaging/create-push.md b/docs/examples/1.8.x/console-web/examples/messaging/create-push.md index f0f54aa72f..783d8fe535 100644 --- a/docs/examples/1.8.x/console-web/examples/messaging/create-push.md +++ b/docs/examples/1.8.x/console-web/examples/messaging/create-push.md @@ -15,7 +15,7 @@ const result = await messaging.createPush({ targets: [], // optional data: {}, // optional action: '', // optional - image: '[ID1:ID2]', // optional + image: '', // optional icon: '', // optional sound: '', // optional color: '', // optional diff --git a/docs/examples/1.8.x/console-web/examples/messaging/update-push.md b/docs/examples/1.8.x/console-web/examples/messaging/update-push.md index 5f5d6e5da2..e1b0cc6b9d 100644 --- a/docs/examples/1.8.x/console-web/examples/messaging/update-push.md +++ b/docs/examples/1.8.x/console-web/examples/messaging/update-push.md @@ -15,7 +15,7 @@ const result = await messaging.updatePush({ body: '', // optional data: {}, // optional action: '', // optional - image: '[ID1:ID2]', // optional + image: '', // optional icon: '', // optional sound: '', // optional color: '', // optional diff --git a/docs/examples/1.8.x/console-web/examples/migrations/create-csv-migration.md b/docs/examples/1.8.x/console-web/examples/migrations/create-csv-migration.md index b25193ed21..f32adcb53c 100644 --- a/docs/examples/1.8.x/console-web/examples/migrations/create-csv-migration.md +++ b/docs/examples/1.8.x/console-web/examples/migrations/create-csv-migration.md @@ -9,7 +9,7 @@ const migrations = new Migrations(client); const result = await migrations.createCsvMigration({ bucketId: '', fileId: '', - resourceId: '[ID1:ID2]', + resourceId: '', internalFile: false // optional }); diff --git a/docs/examples/1.8.x/console-web/examples/tablesdb/create-operations.md b/docs/examples/1.8.x/console-web/examples/tablesdb/create-operations.md new file mode 100644 index 0000000000..744627adae --- /dev/null +++ b/docs/examples/1.8.x/console-web/examples/tablesdb/create-operations.md @@ -0,0 +1,24 @@ +import { Client, TablesDB } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const tablesDB = new TablesDB(client); + +const result = await tablesDB.createOperations({ + transactionId: '', + operations: [ + { + "action": "create", + "databaseId": "", + "tableId": "", + "rowId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] // optional +}); + +console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/tablesdb/create-row.md b/docs/examples/1.8.x/console-web/examples/tablesdb/create-row.md index 6123b5fc31..1991d44258 100644 --- a/docs/examples/1.8.x/console-web/examples/tablesdb/create-row.md +++ b/docs/examples/1.8.x/console-web/examples/tablesdb/create-row.md @@ -17,7 +17,8 @@ const result = await tablesDB.createRow({ "age": 30, "isAdmin": false }, - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/tablesdb/create-rows.md b/docs/examples/1.8.x/console-web/examples/tablesdb/create-rows.md index b827beb048..1054433a74 100644 --- a/docs/examples/1.8.x/console-web/examples/tablesdb/create-rows.md +++ b/docs/examples/1.8.x/console-web/examples/tablesdb/create-rows.md @@ -9,7 +9,8 @@ const tablesDB = new TablesDB(client); const result = await tablesDB.createRows({ databaseId: '', tableId: '', - rows: [] + rows: [], + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/tablesdb/create-transaction.md b/docs/examples/1.8.x/console-web/examples/tablesdb/create-transaction.md new file mode 100644 index 0000000000..68465d4968 --- /dev/null +++ b/docs/examples/1.8.x/console-web/examples/tablesdb/create-transaction.md @@ -0,0 +1,13 @@ +import { Client, TablesDB } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const tablesDB = new TablesDB(client); + +const result = await tablesDB.createTransaction({ + ttl: 60 // optional +}); + +console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/tablesdb/decrement-row-column.md b/docs/examples/1.8.x/console-web/examples/tablesdb/decrement-row-column.md index 067afc7820..2f46b6d958 100644 --- a/docs/examples/1.8.x/console-web/examples/tablesdb/decrement-row-column.md +++ b/docs/examples/1.8.x/console-web/examples/tablesdb/decrement-row-column.md @@ -12,7 +12,8 @@ const result = await tablesDB.decrementRowColumn({ rowId: '', column: '', value: null, // optional - min: null // optional + min: null, // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/tablesdb/delete-row.md b/docs/examples/1.8.x/console-web/examples/tablesdb/delete-row.md index 9b7def4f00..1bcb477c18 100644 --- a/docs/examples/1.8.x/console-web/examples/tablesdb/delete-row.md +++ b/docs/examples/1.8.x/console-web/examples/tablesdb/delete-row.md @@ -9,7 +9,8 @@ const tablesDB = new TablesDB(client); const result = await tablesDB.deleteRow({ databaseId: '', tableId: '', - rowId: '' + rowId: '', + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/tablesdb/delete-rows.md b/docs/examples/1.8.x/console-web/examples/tablesdb/delete-rows.md index 16868a0c6e..c955326753 100644 --- a/docs/examples/1.8.x/console-web/examples/tablesdb/delete-rows.md +++ b/docs/examples/1.8.x/console-web/examples/tablesdb/delete-rows.md @@ -9,7 +9,8 @@ const tablesDB = new TablesDB(client); const result = await tablesDB.deleteRows({ databaseId: '', tableId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/tablesdb/delete-transaction.md b/docs/examples/1.8.x/console-web/examples/tablesdb/delete-transaction.md new file mode 100644 index 0000000000..b4f427a727 --- /dev/null +++ b/docs/examples/1.8.x/console-web/examples/tablesdb/delete-transaction.md @@ -0,0 +1,13 @@ +import { Client, TablesDB } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const tablesDB = new TablesDB(client); + +const result = await tablesDB.deleteTransaction({ + transactionId: '' +}); + +console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/tablesdb/get-row.md b/docs/examples/1.8.x/console-web/examples/tablesdb/get-row.md index f170078430..831a9d1af2 100644 --- a/docs/examples/1.8.x/console-web/examples/tablesdb/get-row.md +++ b/docs/examples/1.8.x/console-web/examples/tablesdb/get-row.md @@ -10,7 +10,8 @@ const result = await tablesDB.getRow({ databaseId: '', tableId: '', rowId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/tablesdb/get-transaction.md b/docs/examples/1.8.x/console-web/examples/tablesdb/get-transaction.md new file mode 100644 index 0000000000..99d405e0a2 --- /dev/null +++ b/docs/examples/1.8.x/console-web/examples/tablesdb/get-transaction.md @@ -0,0 +1,13 @@ +import { Client, TablesDB } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const tablesDB = new TablesDB(client); + +const result = await tablesDB.getTransaction({ + transactionId: '' +}); + +console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/tablesdb/increment-row-column.md b/docs/examples/1.8.x/console-web/examples/tablesdb/increment-row-column.md index 95694d49a4..a0047abb86 100644 --- a/docs/examples/1.8.x/console-web/examples/tablesdb/increment-row-column.md +++ b/docs/examples/1.8.x/console-web/examples/tablesdb/increment-row-column.md @@ -12,7 +12,8 @@ const result = await tablesDB.incrementRowColumn({ rowId: '', column: '', value: null, // optional - max: null // optional + max: null, // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/tablesdb/list-rows.md b/docs/examples/1.8.x/console-web/examples/tablesdb/list-rows.md index 46159b3d42..d87bd450d0 100644 --- a/docs/examples/1.8.x/console-web/examples/tablesdb/list-rows.md +++ b/docs/examples/1.8.x/console-web/examples/tablesdb/list-rows.md @@ -9,7 +9,8 @@ const tablesDB = new TablesDB(client); const result = await tablesDB.listRows({ databaseId: '', tableId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/tablesdb/list-transactions.md b/docs/examples/1.8.x/console-web/examples/tablesdb/list-transactions.md new file mode 100644 index 0000000000..8ecfcefee1 --- /dev/null +++ b/docs/examples/1.8.x/console-web/examples/tablesdb/list-transactions.md @@ -0,0 +1,13 @@ +import { Client, TablesDB } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const tablesDB = new TablesDB(client); + +const result = await tablesDB.listTransactions({ + queries: [] // optional +}); + +console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/tablesdb/update-row.md b/docs/examples/1.8.x/console-web/examples/tablesdb/update-row.md index 5d6109c04c..6193d79567 100644 --- a/docs/examples/1.8.x/console-web/examples/tablesdb/update-row.md +++ b/docs/examples/1.8.x/console-web/examples/tablesdb/update-row.md @@ -11,7 +11,8 @@ const result = await tablesDB.updateRow({ tableId: '', rowId: '', data: {}, // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/tablesdb/update-rows.md b/docs/examples/1.8.x/console-web/examples/tablesdb/update-rows.md index 0ce117efa3..7601955b8b 100644 --- a/docs/examples/1.8.x/console-web/examples/tablesdb/update-rows.md +++ b/docs/examples/1.8.x/console-web/examples/tablesdb/update-rows.md @@ -10,7 +10,8 @@ const result = await tablesDB.updateRows({ databaseId: '', tableId: '', data: {}, // optional - queries: [] // optional + queries: [], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/tablesdb/update-transaction.md b/docs/examples/1.8.x/console-web/examples/tablesdb/update-transaction.md new file mode 100644 index 0000000000..9095edc161 --- /dev/null +++ b/docs/examples/1.8.x/console-web/examples/tablesdb/update-transaction.md @@ -0,0 +1,15 @@ +import { Client, TablesDB } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const tablesDB = new TablesDB(client); + +const result = await tablesDB.updateTransaction({ + transactionId: '', + commit: false, // optional + rollback: false // optional +}); + +console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/tablesdb/upsert-row.md b/docs/examples/1.8.x/console-web/examples/tablesdb/upsert-row.md index 665f181d8b..f56eff55fa 100644 --- a/docs/examples/1.8.x/console-web/examples/tablesdb/upsert-row.md +++ b/docs/examples/1.8.x/console-web/examples/tablesdb/upsert-row.md @@ -11,7 +11,8 @@ const result = await tablesDB.upsertRow({ tableId: '', rowId: '', data: {}, // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/tablesdb/upsert-rows.md b/docs/examples/1.8.x/console-web/examples/tablesdb/upsert-rows.md index 05e78e3efa..173d0e3065 100644 --- a/docs/examples/1.8.x/console-web/examples/tablesdb/upsert-rows.md +++ b/docs/examples/1.8.x/console-web/examples/tablesdb/upsert-rows.md @@ -9,7 +9,8 @@ const tablesDB = new TablesDB(client); const result = await tablesDB.upsertRows({ databaseId: '', tableId: '', - rows: [] + rows: [], + transactionId: '' // optional }); console.log(result); diff --git a/docs/examples/1.8.x/server-dart/examples/databases/create-document.md b/docs/examples/1.8.x/server-dart/examples/databases/create-document.md index e3bae98162..0f663a67f6 100644 --- a/docs/examples/1.8.x/server-dart/examples/databases/create-document.md +++ b/docs/examples/1.8.x/server-dart/examples/databases/create-document.md @@ -19,4 +19,5 @@ Document result = await databases.createDocument( "isAdmin": false }, permissions: ["read("any")"], // (optional) + transactionId: '', // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/databases/create-documents.md b/docs/examples/1.8.x/server-dart/examples/databases/create-documents.md index ba0e34950b..6c77b78fe2 100644 --- a/docs/examples/1.8.x/server-dart/examples/databases/create-documents.md +++ b/docs/examples/1.8.x/server-dart/examples/databases/create-documents.md @@ -11,4 +11,5 @@ DocumentList result = await databases.createDocuments( databaseId: '', collectionId: '', documents: [], + transactionId: '', // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/databases/create-operations.md b/docs/examples/1.8.x/server-dart/examples/databases/create-operations.md new file mode 100644 index 0000000000..2fe1121bf4 --- /dev/null +++ b/docs/examples/1.8.x/server-dart/examples/databases/create-operations.md @@ -0,0 +1,23 @@ +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your secret API key + +Databases databases = Databases(client); + +Transaction result = await databases.createOperations( + transactionId: '', + operations: [ + { + "action": "create", + "databaseId": "", + "collectionId": "", + "documentId": "", + "data": { + "name": "Walter O'Brien" + } + } + ], // (optional) +); diff --git a/docs/examples/1.8.x/server-dart/examples/databases/create-transaction.md b/docs/examples/1.8.x/server-dart/examples/databases/create-transaction.md new file mode 100644 index 0000000000..69af666c73 --- /dev/null +++ b/docs/examples/1.8.x/server-dart/examples/databases/create-transaction.md @@ -0,0 +1,12 @@ +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your secret API key + +Databases databases = Databases(client); + +Transaction result = await databases.createTransaction( + ttl: 60, // (optional) +); diff --git a/docs/examples/1.8.x/server-dart/examples/databases/decrement-document-attribute.md b/docs/examples/1.8.x/server-dart/examples/databases/decrement-document-attribute.md index e46244874d..6fb7ab68e6 100644 --- a/docs/examples/1.8.x/server-dart/examples/databases/decrement-document-attribute.md +++ b/docs/examples/1.8.x/server-dart/examples/databases/decrement-document-attribute.md @@ -14,4 +14,5 @@ Document result = await databases.decrementDocumentAttribute( attribute: '', value: 0, // (optional) min: 0, // (optional) + transactionId: '', // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/databases/delete-document.md b/docs/examples/1.8.x/server-dart/examples/databases/delete-document.md index dd04d89959..eb9c3eba36 100644 --- a/docs/examples/1.8.x/server-dart/examples/databases/delete-document.md +++ b/docs/examples/1.8.x/server-dart/examples/databases/delete-document.md @@ -11,4 +11,5 @@ await databases.deleteDocument( databaseId: '', collectionId: '', documentId: '', + transactionId: '', // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/databases/delete-documents.md b/docs/examples/1.8.x/server-dart/examples/databases/delete-documents.md index 66bd5584c7..2e4e0c3cc2 100644 --- a/docs/examples/1.8.x/server-dart/examples/databases/delete-documents.md +++ b/docs/examples/1.8.x/server-dart/examples/databases/delete-documents.md @@ -11,4 +11,5 @@ await databases.deleteDocuments( databaseId: '', collectionId: '', queries: [], // (optional) + transactionId: '', // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/databases/delete-transaction.md b/docs/examples/1.8.x/server-dart/examples/databases/delete-transaction.md new file mode 100644 index 0000000000..6cebc33f83 --- /dev/null +++ b/docs/examples/1.8.x/server-dart/examples/databases/delete-transaction.md @@ -0,0 +1,12 @@ +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your secret API key + +Databases databases = Databases(client); + +await databases.deleteTransaction( + transactionId: '', +); diff --git a/docs/examples/1.8.x/server-dart/examples/databases/get-document.md b/docs/examples/1.8.x/server-dart/examples/databases/get-document.md index 45745186e6..cd87138b7e 100644 --- a/docs/examples/1.8.x/server-dart/examples/databases/get-document.md +++ b/docs/examples/1.8.x/server-dart/examples/databases/get-document.md @@ -12,4 +12,5 @@ Document result = await databases.getDocument( collectionId: '', documentId: '', queries: [], // (optional) + transactionId: '', // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/databases/get-transaction.md b/docs/examples/1.8.x/server-dart/examples/databases/get-transaction.md new file mode 100644 index 0000000000..dfa1b583c1 --- /dev/null +++ b/docs/examples/1.8.x/server-dart/examples/databases/get-transaction.md @@ -0,0 +1,12 @@ +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your secret API key + +Databases databases = Databases(client); + +Transaction result = await databases.getTransaction( + transactionId: '', +); diff --git a/docs/examples/1.8.x/server-dart/examples/databases/increment-document-attribute.md b/docs/examples/1.8.x/server-dart/examples/databases/increment-document-attribute.md index a2d2622629..ab108ebb27 100644 --- a/docs/examples/1.8.x/server-dart/examples/databases/increment-document-attribute.md +++ b/docs/examples/1.8.x/server-dart/examples/databases/increment-document-attribute.md @@ -14,4 +14,5 @@ Document result = await databases.incrementDocumentAttribute( attribute: '', value: 0, // (optional) max: 0, // (optional) + transactionId: '', // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/databases/list-documents.md b/docs/examples/1.8.x/server-dart/examples/databases/list-documents.md index cdecc59e33..74d849a2cb 100644 --- a/docs/examples/1.8.x/server-dart/examples/databases/list-documents.md +++ b/docs/examples/1.8.x/server-dart/examples/databases/list-documents.md @@ -11,4 +11,5 @@ DocumentList result = await databases.listDocuments( databaseId: '', collectionId: '', queries: [], // (optional) + transactionId: '', // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/databases/list-transactions.md b/docs/examples/1.8.x/server-dart/examples/databases/list-transactions.md new file mode 100644 index 0000000000..856e5e86ac --- /dev/null +++ b/docs/examples/1.8.x/server-dart/examples/databases/list-transactions.md @@ -0,0 +1,12 @@ +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your secret API key + +Databases databases = Databases(client); + +TransactionList result = await databases.listTransactions( + queries: [], // (optional) +); diff --git a/docs/examples/1.8.x/server-dart/examples/databases/update-document.md b/docs/examples/1.8.x/server-dart/examples/databases/update-document.md index 47a1867c10..077a08f606 100644 --- a/docs/examples/1.8.x/server-dart/examples/databases/update-document.md +++ b/docs/examples/1.8.x/server-dart/examples/databases/update-document.md @@ -13,4 +13,5 @@ Document result = await databases.updateDocument( documentId: '', data: {}, // (optional) permissions: ["read("any")"], // (optional) + transactionId: '', // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/databases/update-documents.md b/docs/examples/1.8.x/server-dart/examples/databases/update-documents.md index 70b7cbf86d..babc2d96fb 100644 --- a/docs/examples/1.8.x/server-dart/examples/databases/update-documents.md +++ b/docs/examples/1.8.x/server-dart/examples/databases/update-documents.md @@ -12,4 +12,5 @@ DocumentList result = await databases.updateDocuments( collectionId: '', data: {}, // (optional) queries: [], // (optional) + transactionId: '', // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/databases/update-transaction.md b/docs/examples/1.8.x/server-dart/examples/databases/update-transaction.md new file mode 100644 index 0000000000..b2b35f20eb --- /dev/null +++ b/docs/examples/1.8.x/server-dart/examples/databases/update-transaction.md @@ -0,0 +1,14 @@ +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your secret API key + +Databases databases = Databases(client); + +Transaction result = await databases.updateTransaction( + transactionId: '', + commit: false, // (optional) + rollback: false, // (optional) +); diff --git a/docs/examples/1.8.x/server-dart/examples/databases/upsert-document.md b/docs/examples/1.8.x/server-dart/examples/databases/upsert-document.md index 93e306ebce..be4216da67 100644 --- a/docs/examples/1.8.x/server-dart/examples/databases/upsert-document.md +++ b/docs/examples/1.8.x/server-dart/examples/databases/upsert-document.md @@ -13,4 +13,5 @@ Document result = await databases.upsertDocument( documentId: '', data: {}, permissions: ["read("any")"], // (optional) + transactionId: '', // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/databases/upsert-documents.md b/docs/examples/1.8.x/server-dart/examples/databases/upsert-documents.md index cd35014f63..009fe18b4a 100644 --- a/docs/examples/1.8.x/server-dart/examples/databases/upsert-documents.md +++ b/docs/examples/1.8.x/server-dart/examples/databases/upsert-documents.md @@ -11,4 +11,5 @@ DocumentList result = await databases.upsertDocuments( databaseId: '', collectionId: '', documents: [], + transactionId: '', // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/messaging/create-push.md b/docs/examples/1.8.x/server-dart/examples/messaging/create-push.md index 58d82c7a0a..4b9f7d3c52 100644 --- a/docs/examples/1.8.x/server-dart/examples/messaging/create-push.md +++ b/docs/examples/1.8.x/server-dart/examples/messaging/create-push.md @@ -16,7 +16,7 @@ Message result = await messaging.createPush( targets: [], // (optional) data: {}, // (optional) action: '', // (optional) - image: '[ID1:ID2]', // (optional) + image: '', // (optional) icon: '', // (optional) sound: '', // (optional) color: '', // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/messaging/update-push.md b/docs/examples/1.8.x/server-dart/examples/messaging/update-push.md index f7cc117b64..cbae5dfabb 100644 --- a/docs/examples/1.8.x/server-dart/examples/messaging/update-push.md +++ b/docs/examples/1.8.x/server-dart/examples/messaging/update-push.md @@ -16,7 +16,7 @@ Message result = await messaging.updatePush( body: '', // (optional) data: {}, // (optional) action: '', // (optional) - image: '[ID1:ID2]', // (optional) + image: '', // (optional) icon: '', // (optional) sound: '', // (optional) color: '', // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/tablesdb/create-operations.md b/docs/examples/1.8.x/server-dart/examples/tablesdb/create-operations.md new file mode 100644 index 0000000000..2b5c046b14 --- /dev/null +++ b/docs/examples/1.8.x/server-dart/examples/tablesdb/create-operations.md @@ -0,0 +1,23 @@ +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your secret API key + +TablesDB tablesDB = TablesDB(client); + +Transaction result = await tablesDB.createOperations( + transactionId: '', + operations: [ + { + "action": "create", + "databaseId": "", + "tableId": "", + "rowId": "", + "data": { + "name": "Walter O'Brien" + } + } + ], // (optional) +); diff --git a/docs/examples/1.8.x/server-dart/examples/tablesdb/create-row.md b/docs/examples/1.8.x/server-dart/examples/tablesdb/create-row.md index c2f5dd8293..255bd9615e 100644 --- a/docs/examples/1.8.x/server-dart/examples/tablesdb/create-row.md +++ b/docs/examples/1.8.x/server-dart/examples/tablesdb/create-row.md @@ -19,4 +19,5 @@ Row result = await tablesDB.createRow( "isAdmin": false }, permissions: ["read("any")"], // (optional) + transactionId: '', // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/tablesdb/create-rows.md b/docs/examples/1.8.x/server-dart/examples/tablesdb/create-rows.md index c22fdba506..6366006c31 100644 --- a/docs/examples/1.8.x/server-dart/examples/tablesdb/create-rows.md +++ b/docs/examples/1.8.x/server-dart/examples/tablesdb/create-rows.md @@ -11,4 +11,5 @@ RowList result = await tablesDB.createRows( databaseId: '', tableId: '', rows: [], + transactionId: '', // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/tablesdb/create-transaction.md b/docs/examples/1.8.x/server-dart/examples/tablesdb/create-transaction.md new file mode 100644 index 0000000000..721ac4cf8b --- /dev/null +++ b/docs/examples/1.8.x/server-dart/examples/tablesdb/create-transaction.md @@ -0,0 +1,12 @@ +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your secret API key + +TablesDB tablesDB = TablesDB(client); + +Transaction result = await tablesDB.createTransaction( + ttl: 60, // (optional) +); diff --git a/docs/examples/1.8.x/server-dart/examples/tablesdb/decrement-row-column.md b/docs/examples/1.8.x/server-dart/examples/tablesdb/decrement-row-column.md index 8c376563d8..304e6b0219 100644 --- a/docs/examples/1.8.x/server-dart/examples/tablesdb/decrement-row-column.md +++ b/docs/examples/1.8.x/server-dart/examples/tablesdb/decrement-row-column.md @@ -14,4 +14,5 @@ Row result = await tablesDB.decrementRowColumn( column: '', value: 0, // (optional) min: 0, // (optional) + transactionId: '', // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/tablesdb/delete-row.md b/docs/examples/1.8.x/server-dart/examples/tablesdb/delete-row.md index f3966c0930..da1e280cba 100644 --- a/docs/examples/1.8.x/server-dart/examples/tablesdb/delete-row.md +++ b/docs/examples/1.8.x/server-dart/examples/tablesdb/delete-row.md @@ -11,4 +11,5 @@ await tablesDB.deleteRow( databaseId: '', tableId: '', rowId: '', + transactionId: '', // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/tablesdb/delete-rows.md b/docs/examples/1.8.x/server-dart/examples/tablesdb/delete-rows.md index eb2aebb3e6..6738ac78fc 100644 --- a/docs/examples/1.8.x/server-dart/examples/tablesdb/delete-rows.md +++ b/docs/examples/1.8.x/server-dart/examples/tablesdb/delete-rows.md @@ -11,4 +11,5 @@ await tablesDB.deleteRows( databaseId: '', tableId: '', queries: [], // (optional) + transactionId: '', // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/tablesdb/delete-transaction.md b/docs/examples/1.8.x/server-dart/examples/tablesdb/delete-transaction.md new file mode 100644 index 0000000000..8dc80418a0 --- /dev/null +++ b/docs/examples/1.8.x/server-dart/examples/tablesdb/delete-transaction.md @@ -0,0 +1,12 @@ +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your secret API key + +TablesDB tablesDB = TablesDB(client); + +await tablesDB.deleteTransaction( + transactionId: '', +); diff --git a/docs/examples/1.8.x/server-dart/examples/tablesdb/get-row.md b/docs/examples/1.8.x/server-dart/examples/tablesdb/get-row.md index 0af17b612a..a0d7a83b39 100644 --- a/docs/examples/1.8.x/server-dart/examples/tablesdb/get-row.md +++ b/docs/examples/1.8.x/server-dart/examples/tablesdb/get-row.md @@ -12,4 +12,5 @@ Row result = await tablesDB.getRow( tableId: '', rowId: '', queries: [], // (optional) + transactionId: '', // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/tablesdb/get-transaction.md b/docs/examples/1.8.x/server-dart/examples/tablesdb/get-transaction.md new file mode 100644 index 0000000000..267af59aa9 --- /dev/null +++ b/docs/examples/1.8.x/server-dart/examples/tablesdb/get-transaction.md @@ -0,0 +1,12 @@ +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your secret API key + +TablesDB tablesDB = TablesDB(client); + +Transaction result = await tablesDB.getTransaction( + transactionId: '', +); diff --git a/docs/examples/1.8.x/server-dart/examples/tablesdb/increment-row-column.md b/docs/examples/1.8.x/server-dart/examples/tablesdb/increment-row-column.md index bbe262e5c9..049a48a7d0 100644 --- a/docs/examples/1.8.x/server-dart/examples/tablesdb/increment-row-column.md +++ b/docs/examples/1.8.x/server-dart/examples/tablesdb/increment-row-column.md @@ -14,4 +14,5 @@ Row result = await tablesDB.incrementRowColumn( column: '', value: 0, // (optional) max: 0, // (optional) + transactionId: '', // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/tablesdb/list-rows.md b/docs/examples/1.8.x/server-dart/examples/tablesdb/list-rows.md index 83bbe38fca..a429de72f6 100644 --- a/docs/examples/1.8.x/server-dart/examples/tablesdb/list-rows.md +++ b/docs/examples/1.8.x/server-dart/examples/tablesdb/list-rows.md @@ -11,4 +11,5 @@ RowList result = await tablesDB.listRows( databaseId: '', tableId: '', queries: [], // (optional) + transactionId: '', // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/tablesdb/list-transactions.md b/docs/examples/1.8.x/server-dart/examples/tablesdb/list-transactions.md new file mode 100644 index 0000000000..d4b3a5e2c3 --- /dev/null +++ b/docs/examples/1.8.x/server-dart/examples/tablesdb/list-transactions.md @@ -0,0 +1,12 @@ +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your secret API key + +TablesDB tablesDB = TablesDB(client); + +TransactionList result = await tablesDB.listTransactions( + queries: [], // (optional) +); diff --git a/docs/examples/1.8.x/server-dart/examples/tablesdb/update-row.md b/docs/examples/1.8.x/server-dart/examples/tablesdb/update-row.md index d66c24f505..e4f683cae0 100644 --- a/docs/examples/1.8.x/server-dart/examples/tablesdb/update-row.md +++ b/docs/examples/1.8.x/server-dart/examples/tablesdb/update-row.md @@ -13,4 +13,5 @@ Row result = await tablesDB.updateRow( rowId: '', data: {}, // (optional) permissions: ["read("any")"], // (optional) + transactionId: '', // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/tablesdb/update-rows.md b/docs/examples/1.8.x/server-dart/examples/tablesdb/update-rows.md index a0973b47d1..a7c0d61b45 100644 --- a/docs/examples/1.8.x/server-dart/examples/tablesdb/update-rows.md +++ b/docs/examples/1.8.x/server-dart/examples/tablesdb/update-rows.md @@ -12,4 +12,5 @@ RowList result = await tablesDB.updateRows( tableId: '', data: {}, // (optional) queries: [], // (optional) + transactionId: '', // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/tablesdb/update-transaction.md b/docs/examples/1.8.x/server-dart/examples/tablesdb/update-transaction.md new file mode 100644 index 0000000000..bb3837d4ec --- /dev/null +++ b/docs/examples/1.8.x/server-dart/examples/tablesdb/update-transaction.md @@ -0,0 +1,14 @@ +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your secret API key + +TablesDB tablesDB = TablesDB(client); + +Transaction result = await tablesDB.updateTransaction( + transactionId: '', + commit: false, // (optional) + rollback: false, // (optional) +); diff --git a/docs/examples/1.8.x/server-dart/examples/tablesdb/upsert-row.md b/docs/examples/1.8.x/server-dart/examples/tablesdb/upsert-row.md index fbe4d2928a..f9b8c848ae 100644 --- a/docs/examples/1.8.x/server-dart/examples/tablesdb/upsert-row.md +++ b/docs/examples/1.8.x/server-dart/examples/tablesdb/upsert-row.md @@ -13,4 +13,5 @@ Row result = await tablesDB.upsertRow( rowId: '', data: {}, // (optional) permissions: ["read("any")"], // (optional) + transactionId: '', // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/tablesdb/upsert-rows.md b/docs/examples/1.8.x/server-dart/examples/tablesdb/upsert-rows.md index 031aa50bea..d48e9094f4 100644 --- a/docs/examples/1.8.x/server-dart/examples/tablesdb/upsert-rows.md +++ b/docs/examples/1.8.x/server-dart/examples/tablesdb/upsert-rows.md @@ -11,4 +11,5 @@ RowList result = await tablesDB.upsertRows( databaseId: '', tableId: '', rows: [], + transactionId: '', // (optional) ); diff --git a/docs/examples/1.8.x/server-dotnet/examples/databases/create-document.md b/docs/examples/1.8.x/server-dotnet/examples/databases/create-document.md index 4a7444db7a..9fcfdd041d 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/databases/create-document.md +++ b/docs/examples/1.8.x/server-dotnet/examples/databases/create-document.md @@ -20,5 +20,6 @@ Document result = await databases.CreateDocument( age = 30, isAdmin = false }, - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/databases/create-documents.md b/docs/examples/1.8.x/server-dotnet/examples/databases/create-documents.md index dad710f0df..cc6cfb7606 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/databases/create-documents.md +++ b/docs/examples/1.8.x/server-dotnet/examples/databases/create-documents.md @@ -12,5 +12,6 @@ Databases databases = new Databases(client); DocumentList result = await databases.CreateDocuments( databaseId: "", collectionId: "", - documents: new List() + documents: new List(), + transactionId: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/databases/create-operations.md b/docs/examples/1.8.x/server-dotnet/examples/databases/create-operations.md new file mode 100644 index 0000000000..701c6432b8 --- /dev/null +++ b/docs/examples/1.8.x/server-dotnet/examples/databases/create-operations.md @@ -0,0 +1,25 @@ +using Appwrite; +using Appwrite.Models; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .SetProject("") // Your project ID + .SetKey(""); // Your secret API key + +Databases databases = new Databases(client); + +Transaction result = await databases.CreateOperations( + transactionId: "", + operations: [ + { + "action": "create", + "databaseId": "", + "collectionId": "", + "documentId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] // optional +); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/databases/create-transaction.md b/docs/examples/1.8.x/server-dotnet/examples/databases/create-transaction.md new file mode 100644 index 0000000000..f8d7b34ffd --- /dev/null +++ b/docs/examples/1.8.x/server-dotnet/examples/databases/create-transaction.md @@ -0,0 +1,14 @@ +using Appwrite; +using Appwrite.Models; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .SetProject("") // Your project ID + .SetKey(""); // Your secret API key + +Databases databases = new Databases(client); + +Transaction result = await databases.CreateTransaction( + ttl: 60 // optional +); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/databases/decrement-document-attribute.md b/docs/examples/1.8.x/server-dotnet/examples/databases/decrement-document-attribute.md index 2e48d4578e..9ff62a08aa 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/databases/decrement-document-attribute.md +++ b/docs/examples/1.8.x/server-dotnet/examples/databases/decrement-document-attribute.md @@ -15,5 +15,6 @@ Document result = await databases.DecrementDocumentAttribute( documentId: "", attribute: "", value: 0, // optional - min: 0 // optional + min: 0, // optional + transactionId: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/databases/delete-document.md b/docs/examples/1.8.x/server-dotnet/examples/databases/delete-document.md index 221b80e254..34bdbdafcd 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/databases/delete-document.md +++ b/docs/examples/1.8.x/server-dotnet/examples/databases/delete-document.md @@ -12,5 +12,6 @@ Databases databases = new Databases(client); await databases.DeleteDocument( databaseId: "", collectionId: "", - documentId: "" + documentId: "", + transactionId: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/databases/delete-documents.md b/docs/examples/1.8.x/server-dotnet/examples/databases/delete-documents.md index a9bc9c277b..52f711b842 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/databases/delete-documents.md +++ b/docs/examples/1.8.x/server-dotnet/examples/databases/delete-documents.md @@ -12,5 +12,6 @@ Databases databases = new Databases(client); await databases.DeleteDocuments( databaseId: "", collectionId: "", - queries: new List() // optional + queries: new List(), // optional + transactionId: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/databases/delete-transaction.md b/docs/examples/1.8.x/server-dotnet/examples/databases/delete-transaction.md new file mode 100644 index 0000000000..713a75787e --- /dev/null +++ b/docs/examples/1.8.x/server-dotnet/examples/databases/delete-transaction.md @@ -0,0 +1,14 @@ +using Appwrite; +using Appwrite.Models; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .SetProject("") // Your project ID + .SetKey(""); // Your secret API key + +Databases databases = new Databases(client); + +await databases.DeleteTransaction( + transactionId: "" +); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/databases/get-document.md b/docs/examples/1.8.x/server-dotnet/examples/databases/get-document.md index d7e9b68807..bbafc3c888 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/databases/get-document.md +++ b/docs/examples/1.8.x/server-dotnet/examples/databases/get-document.md @@ -13,5 +13,6 @@ Document result = await databases.GetDocument( databaseId: "", collectionId: "", documentId: "", - queries: new List() // optional + queries: new List(), // optional + transactionId: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/databases/get-transaction.md b/docs/examples/1.8.x/server-dotnet/examples/databases/get-transaction.md new file mode 100644 index 0000000000..d66ab6e205 --- /dev/null +++ b/docs/examples/1.8.x/server-dotnet/examples/databases/get-transaction.md @@ -0,0 +1,14 @@ +using Appwrite; +using Appwrite.Models; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .SetProject("") // Your project ID + .SetKey(""); // Your secret API key + +Databases databases = new Databases(client); + +Transaction result = await databases.GetTransaction( + transactionId: "" +); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/databases/increment-document-attribute.md b/docs/examples/1.8.x/server-dotnet/examples/databases/increment-document-attribute.md index 923c8d63e2..37a4ed76eb 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/databases/increment-document-attribute.md +++ b/docs/examples/1.8.x/server-dotnet/examples/databases/increment-document-attribute.md @@ -15,5 +15,6 @@ Document result = await databases.IncrementDocumentAttribute( documentId: "", attribute: "", value: 0, // optional - max: 0 // optional + max: 0, // optional + transactionId: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/databases/list-documents.md b/docs/examples/1.8.x/server-dotnet/examples/databases/list-documents.md index f59e4576bd..643c42015d 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/databases/list-documents.md +++ b/docs/examples/1.8.x/server-dotnet/examples/databases/list-documents.md @@ -12,5 +12,6 @@ Databases databases = new Databases(client); DocumentList result = await databases.ListDocuments( databaseId: "", collectionId: "", - queries: new List() // optional + queries: new List(), // optional + transactionId: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/databases/list-transactions.md b/docs/examples/1.8.x/server-dotnet/examples/databases/list-transactions.md new file mode 100644 index 0000000000..3f2ce0df24 --- /dev/null +++ b/docs/examples/1.8.x/server-dotnet/examples/databases/list-transactions.md @@ -0,0 +1,14 @@ +using Appwrite; +using Appwrite.Models; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .SetProject("") // Your project ID + .SetKey(""); // Your secret API key + +Databases databases = new Databases(client); + +TransactionList result = await databases.ListTransactions( + queries: new List() // optional +); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/databases/update-document.md b/docs/examples/1.8.x/server-dotnet/examples/databases/update-document.md index 3121c15e08..838b2790a9 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/databases/update-document.md +++ b/docs/examples/1.8.x/server-dotnet/examples/databases/update-document.md @@ -14,5 +14,6 @@ Document result = await databases.UpdateDocument( collectionId: "", documentId: "", data: [object], // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/databases/update-documents.md b/docs/examples/1.8.x/server-dotnet/examples/databases/update-documents.md index 63ded21ac9..077ec04da6 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/databases/update-documents.md +++ b/docs/examples/1.8.x/server-dotnet/examples/databases/update-documents.md @@ -13,5 +13,6 @@ DocumentList result = await databases.UpdateDocuments( databaseId: "", collectionId: "", data: [object], // optional - queries: new List() // optional + queries: new List(), // optional + transactionId: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/databases/update-transaction.md b/docs/examples/1.8.x/server-dotnet/examples/databases/update-transaction.md new file mode 100644 index 0000000000..056f0d86f0 --- /dev/null +++ b/docs/examples/1.8.x/server-dotnet/examples/databases/update-transaction.md @@ -0,0 +1,16 @@ +using Appwrite; +using Appwrite.Models; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .SetProject("") // Your project ID + .SetKey(""); // Your secret API key + +Databases databases = new Databases(client); + +Transaction result = await databases.UpdateTransaction( + transactionId: "", + commit: false, // optional + rollback: false // optional +); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/databases/upsert-document.md b/docs/examples/1.8.x/server-dotnet/examples/databases/upsert-document.md index c0876bfa73..e12c5dd0d7 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/databases/upsert-document.md +++ b/docs/examples/1.8.x/server-dotnet/examples/databases/upsert-document.md @@ -14,5 +14,6 @@ Document result = await databases.UpsertDocument( collectionId: "", documentId: "", data: [object], - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/databases/upsert-documents.md b/docs/examples/1.8.x/server-dotnet/examples/databases/upsert-documents.md index 6c124c16e5..4fefbfcc38 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/databases/upsert-documents.md +++ b/docs/examples/1.8.x/server-dotnet/examples/databases/upsert-documents.md @@ -12,5 +12,6 @@ Databases databases = new Databases(client); DocumentList result = await databases.UpsertDocuments( databaseId: "", collectionId: "", - documents: new List() + documents: new List(), + transactionId: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/messaging/create-push.md b/docs/examples/1.8.x/server-dotnet/examples/messaging/create-push.md index 1d2dbec1f2..ec90fa6d90 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/messaging/create-push.md +++ b/docs/examples/1.8.x/server-dotnet/examples/messaging/create-push.md @@ -19,7 +19,7 @@ Message result = await messaging.CreatePush( targets: new List(), // optional data: [object], // optional action: "", // optional - image: "[ID1:ID2]", // optional + image: "", // optional icon: "", // optional sound: "", // optional color: "", // optional diff --git a/docs/examples/1.8.x/server-dotnet/examples/messaging/update-push.md b/docs/examples/1.8.x/server-dotnet/examples/messaging/update-push.md index 37da215e82..b45752c815 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/messaging/update-push.md +++ b/docs/examples/1.8.x/server-dotnet/examples/messaging/update-push.md @@ -19,7 +19,7 @@ Message result = await messaging.UpdatePush( body: "", // optional data: [object], // optional action: "", // optional - image: "[ID1:ID2]", // optional + image: "", // optional icon: "", // optional sound: "", // optional color: "", // optional diff --git a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/create-operations.md b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/create-operations.md new file mode 100644 index 0000000000..0a8da3e8cc --- /dev/null +++ b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/create-operations.md @@ -0,0 +1,25 @@ +using Appwrite; +using Appwrite.Models; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .SetProject("") // Your project ID + .SetKey(""); // Your secret API key + +TablesDB tablesDB = new TablesDB(client); + +Transaction result = await tablesDB.CreateOperations( + transactionId: "", + operations: [ + { + "action": "create", + "databaseId": "", + "tableId": "", + "rowId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] // optional +); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/create-row.md b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/create-row.md index 01a21b0dcd..8d56063f1f 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/create-row.md +++ b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/create-row.md @@ -20,5 +20,6 @@ Row result = await tablesDB.CreateRow( age = 30, isAdmin = false }, - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/create-rows.md b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/create-rows.md index c23e795a84..c73c474f45 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/create-rows.md +++ b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/create-rows.md @@ -12,5 +12,6 @@ TablesDB tablesDB = new TablesDB(client); RowList result = await tablesDB.CreateRows( databaseId: "", tableId: "", - rows: new List() + rows: new List(), + transactionId: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/create-transaction.md b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/create-transaction.md new file mode 100644 index 0000000000..b42b087539 --- /dev/null +++ b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/create-transaction.md @@ -0,0 +1,14 @@ +using Appwrite; +using Appwrite.Models; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .SetProject("") // Your project ID + .SetKey(""); // Your secret API key + +TablesDB tablesDB = new TablesDB(client); + +Transaction result = await tablesDB.CreateTransaction( + ttl: 60 // optional +); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/decrement-row-column.md b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/decrement-row-column.md index 66d98b65b9..19498d035f 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/decrement-row-column.md +++ b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/decrement-row-column.md @@ -15,5 +15,6 @@ Row result = await tablesDB.DecrementRowColumn( rowId: "", column: "", value: 0, // optional - min: 0 // optional + min: 0, // optional + transactionId: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/delete-row.md b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/delete-row.md index 86d7fbf392..81bd084f62 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/delete-row.md +++ b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/delete-row.md @@ -12,5 +12,6 @@ TablesDB tablesDB = new TablesDB(client); await tablesDB.DeleteRow( databaseId: "", tableId: "", - rowId: "" + rowId: "", + transactionId: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/delete-rows.md b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/delete-rows.md index 13d5758fdb..c0f656cda5 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/delete-rows.md +++ b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/delete-rows.md @@ -12,5 +12,6 @@ TablesDB tablesDB = new TablesDB(client); await tablesDB.DeleteRows( databaseId: "", tableId: "", - queries: new List() // optional + queries: new List(), // optional + transactionId: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/delete-transaction.md b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/delete-transaction.md new file mode 100644 index 0000000000..6e41c80c02 --- /dev/null +++ b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/delete-transaction.md @@ -0,0 +1,14 @@ +using Appwrite; +using Appwrite.Models; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .SetProject("") // Your project ID + .SetKey(""); // Your secret API key + +TablesDB tablesDB = new TablesDB(client); + +await tablesDB.DeleteTransaction( + transactionId: "" +); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/get-row.md b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/get-row.md index 99d79ac3dd..66f6a230e3 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/get-row.md +++ b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/get-row.md @@ -13,5 +13,6 @@ Row result = await tablesDB.GetRow( databaseId: "", tableId: "", rowId: "", - queries: new List() // optional + queries: new List(), // optional + transactionId: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/get-transaction.md b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/get-transaction.md new file mode 100644 index 0000000000..73e0904982 --- /dev/null +++ b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/get-transaction.md @@ -0,0 +1,14 @@ +using Appwrite; +using Appwrite.Models; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .SetProject("") // Your project ID + .SetKey(""); // Your secret API key + +TablesDB tablesDB = new TablesDB(client); + +Transaction result = await tablesDB.GetTransaction( + transactionId: "" +); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/increment-row-column.md b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/increment-row-column.md index 48eabc34d4..cbac61f159 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/increment-row-column.md +++ b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/increment-row-column.md @@ -15,5 +15,6 @@ Row result = await tablesDB.IncrementRowColumn( rowId: "", column: "", value: 0, // optional - max: 0 // optional + max: 0, // optional + transactionId: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/list-rows.md b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/list-rows.md index d3f860e869..79f809d35d 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/list-rows.md +++ b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/list-rows.md @@ -12,5 +12,6 @@ TablesDB tablesDB = new TablesDB(client); RowList result = await tablesDB.ListRows( databaseId: "", tableId: "", - queries: new List() // optional + queries: new List(), // optional + transactionId: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/list-transactions.md b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/list-transactions.md new file mode 100644 index 0000000000..b1a00e1a44 --- /dev/null +++ b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/list-transactions.md @@ -0,0 +1,14 @@ +using Appwrite; +using Appwrite.Models; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .SetProject("") // Your project ID + .SetKey(""); // Your secret API key + +TablesDB tablesDB = new TablesDB(client); + +TransactionList result = await tablesDB.ListTransactions( + queries: new List() // optional +); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/update-row.md b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/update-row.md index 5eb5acdbd2..40f4eb4314 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/update-row.md +++ b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/update-row.md @@ -14,5 +14,6 @@ Row result = await tablesDB.UpdateRow( tableId: "", rowId: "", data: [object], // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/update-rows.md b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/update-rows.md index 401464d66a..368977a0cc 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/update-rows.md +++ b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/update-rows.md @@ -13,5 +13,6 @@ RowList result = await tablesDB.UpdateRows( databaseId: "", tableId: "", data: [object], // optional - queries: new List() // optional + queries: new List(), // optional + transactionId: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/update-transaction.md b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/update-transaction.md new file mode 100644 index 0000000000..3b44fd5d37 --- /dev/null +++ b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/update-transaction.md @@ -0,0 +1,16 @@ +using Appwrite; +using Appwrite.Models; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .SetProject("") // Your project ID + .SetKey(""); // Your secret API key + +TablesDB tablesDB = new TablesDB(client); + +Transaction result = await tablesDB.UpdateTransaction( + transactionId: "", + commit: false, // optional + rollback: false // optional +); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/upsert-row.md b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/upsert-row.md index e1f68a7dfb..18b8419146 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/upsert-row.md +++ b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/upsert-row.md @@ -14,5 +14,6 @@ Row result = await tablesDB.UpsertRow( tableId: "", rowId: "", data: [object], // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/upsert-rows.md b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/upsert-rows.md index 199dc2ba85..fde5df7149 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/tablesdb/upsert-rows.md +++ b/docs/examples/1.8.x/server-dotnet/examples/tablesdb/upsert-rows.md @@ -12,5 +12,6 @@ TablesDB tablesDB = new TablesDB(client); RowList result = await tablesDB.UpsertRows( databaseId: "", tableId: "", - rows: new List() + rows: new List(), + transactionId: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-go/examples/databases/create-document.md b/docs/examples/1.8.x/server-go/examples/databases/create-document.md index ea6305a06e..1c7a489129 100644 --- a/docs/examples/1.8.x/server-go/examples/databases/create-document.md +++ b/docs/examples/1.8.x/server-go/examples/databases/create-document.md @@ -26,4 +26,5 @@ response, error := service.CreateDocument( "isAdmin": false }, databases.WithCreateDocumentPermissions(interface{}{"read("any")"}), + databases.WithCreateDocumentTransactionId(""), ) diff --git a/docs/examples/1.8.x/server-go/examples/databases/create-documents.md b/docs/examples/1.8.x/server-go/examples/databases/create-documents.md index 8bd0a5761a..ae08b2e7d8 100644 --- a/docs/examples/1.8.x/server-go/examples/databases/create-documents.md +++ b/docs/examples/1.8.x/server-go/examples/databases/create-documents.md @@ -18,4 +18,5 @@ response, error := service.CreateDocuments( "", "", []interface{}{}, + databases.WithCreateDocumentsTransactionId(""), ) diff --git a/docs/examples/1.8.x/server-go/examples/databases/create-operations.md b/docs/examples/1.8.x/server-go/examples/databases/create-operations.md new file mode 100644 index 0000000000..c73ad57738 --- /dev/null +++ b/docs/examples/1.8.x/server-go/examples/databases/create-operations.md @@ -0,0 +1,30 @@ +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/client" + "github.com/appwrite/sdk-for-go/databases" +) + +client := client.New( + client.WithEndpoint("https://.cloud.appwrite.io/v1") + client.WithProject("") + client.WithKey("") +) + +service := databases.New(client) + +response, error := service.CreateOperations( + "", + databases.WithCreateOperationsOperations(interface{}{ + { + "action": "create", + "databaseId": "", + "collectionId": "", + "documentId": "", + "data": { + "name": "Walter O'Brien" + } + } + }), +) diff --git a/docs/examples/1.8.x/server-go/examples/databases/create-transaction.md b/docs/examples/1.8.x/server-go/examples/databases/create-transaction.md new file mode 100644 index 0000000000..f74b9152c1 --- /dev/null +++ b/docs/examples/1.8.x/server-go/examples/databases/create-transaction.md @@ -0,0 +1,19 @@ +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/client" + "github.com/appwrite/sdk-for-go/databases" +) + +client := client.New( + client.WithEndpoint("https://.cloud.appwrite.io/v1") + client.WithProject("") + client.WithKey("") +) + +service := databases.New(client) + +response, error := service.CreateTransaction( + databases.WithCreateTransactionTtl(60), +) diff --git a/docs/examples/1.8.x/server-go/examples/databases/decrement-document-attribute.md b/docs/examples/1.8.x/server-go/examples/databases/decrement-document-attribute.md index af463743b5..7cb2c1c3c3 100644 --- a/docs/examples/1.8.x/server-go/examples/databases/decrement-document-attribute.md +++ b/docs/examples/1.8.x/server-go/examples/databases/decrement-document-attribute.md @@ -21,4 +21,5 @@ response, error := service.DecrementDocumentAttribute( "", databases.WithDecrementDocumentAttributeValue(0), databases.WithDecrementDocumentAttributeMin(0), + databases.WithDecrementDocumentAttributeTransactionId(""), ) diff --git a/docs/examples/1.8.x/server-go/examples/databases/delete-document.md b/docs/examples/1.8.x/server-go/examples/databases/delete-document.md index 6e9b58a56d..80e44b89eb 100644 --- a/docs/examples/1.8.x/server-go/examples/databases/delete-document.md +++ b/docs/examples/1.8.x/server-go/examples/databases/delete-document.md @@ -18,4 +18,5 @@ response, error := service.DeleteDocument( "", "", "", + databases.WithDeleteDocumentTransactionId(""), ) diff --git a/docs/examples/1.8.x/server-go/examples/databases/delete-documents.md b/docs/examples/1.8.x/server-go/examples/databases/delete-documents.md index 43e0d4cb36..5c070a0dc4 100644 --- a/docs/examples/1.8.x/server-go/examples/databases/delete-documents.md +++ b/docs/examples/1.8.x/server-go/examples/databases/delete-documents.md @@ -18,4 +18,5 @@ response, error := service.DeleteDocuments( "", "", databases.WithDeleteDocumentsQueries([]interface{}{}), + databases.WithDeleteDocumentsTransactionId(""), ) diff --git a/docs/examples/1.8.x/server-go/examples/databases/delete-transaction.md b/docs/examples/1.8.x/server-go/examples/databases/delete-transaction.md new file mode 100644 index 0000000000..b06f8bf6f3 --- /dev/null +++ b/docs/examples/1.8.x/server-go/examples/databases/delete-transaction.md @@ -0,0 +1,19 @@ +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/client" + "github.com/appwrite/sdk-for-go/databases" +) + +client := client.New( + client.WithEndpoint("https://.cloud.appwrite.io/v1") + client.WithProject("") + client.WithKey("") +) + +service := databases.New(client) + +response, error := service.DeleteTransaction( + "", +) diff --git a/docs/examples/1.8.x/server-go/examples/databases/get-document.md b/docs/examples/1.8.x/server-go/examples/databases/get-document.md index 5e63077aac..e075084f61 100644 --- a/docs/examples/1.8.x/server-go/examples/databases/get-document.md +++ b/docs/examples/1.8.x/server-go/examples/databases/get-document.md @@ -19,4 +19,5 @@ response, error := service.GetDocument( "", "", databases.WithGetDocumentQueries([]interface{}{}), + databases.WithGetDocumentTransactionId(""), ) diff --git a/docs/examples/1.8.x/server-go/examples/databases/get-transaction.md b/docs/examples/1.8.x/server-go/examples/databases/get-transaction.md new file mode 100644 index 0000000000..4c15d73231 --- /dev/null +++ b/docs/examples/1.8.x/server-go/examples/databases/get-transaction.md @@ -0,0 +1,19 @@ +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/client" + "github.com/appwrite/sdk-for-go/databases" +) + +client := client.New( + client.WithEndpoint("https://.cloud.appwrite.io/v1") + client.WithProject("") + client.WithKey("") +) + +service := databases.New(client) + +response, error := service.GetTransaction( + "", +) diff --git a/docs/examples/1.8.x/server-go/examples/databases/increment-document-attribute.md b/docs/examples/1.8.x/server-go/examples/databases/increment-document-attribute.md index d2e91ee4c1..510d6486b8 100644 --- a/docs/examples/1.8.x/server-go/examples/databases/increment-document-attribute.md +++ b/docs/examples/1.8.x/server-go/examples/databases/increment-document-attribute.md @@ -21,4 +21,5 @@ response, error := service.IncrementDocumentAttribute( "", databases.WithIncrementDocumentAttributeValue(0), databases.WithIncrementDocumentAttributeMax(0), + databases.WithIncrementDocumentAttributeTransactionId(""), ) diff --git a/docs/examples/1.8.x/server-go/examples/databases/list-documents.md b/docs/examples/1.8.x/server-go/examples/databases/list-documents.md index 0aaef36c59..3d83145a61 100644 --- a/docs/examples/1.8.x/server-go/examples/databases/list-documents.md +++ b/docs/examples/1.8.x/server-go/examples/databases/list-documents.md @@ -18,4 +18,5 @@ response, error := service.ListDocuments( "", "", databases.WithListDocumentsQueries([]interface{}{}), + databases.WithListDocumentsTransactionId(""), ) diff --git a/docs/examples/1.8.x/server-go/examples/databases/list-transactions.md b/docs/examples/1.8.x/server-go/examples/databases/list-transactions.md new file mode 100644 index 0000000000..662874bb8c --- /dev/null +++ b/docs/examples/1.8.x/server-go/examples/databases/list-transactions.md @@ -0,0 +1,19 @@ +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/client" + "github.com/appwrite/sdk-for-go/databases" +) + +client := client.New( + client.WithEndpoint("https://.cloud.appwrite.io/v1") + client.WithProject("") + client.WithKey("") +) + +service := databases.New(client) + +response, error := service.ListTransactions( + databases.WithListTransactionsQueries([]interface{}{}), +) diff --git a/docs/examples/1.8.x/server-go/examples/databases/update-document.md b/docs/examples/1.8.x/server-go/examples/databases/update-document.md index 90c0947536..314385d6a8 100644 --- a/docs/examples/1.8.x/server-go/examples/databases/update-document.md +++ b/docs/examples/1.8.x/server-go/examples/databases/update-document.md @@ -20,4 +20,5 @@ response, error := service.UpdateDocument( "", databases.WithUpdateDocumentData(map[string]interface{}{}), databases.WithUpdateDocumentPermissions(interface{}{"read("any")"}), + databases.WithUpdateDocumentTransactionId(""), ) diff --git a/docs/examples/1.8.x/server-go/examples/databases/update-documents.md b/docs/examples/1.8.x/server-go/examples/databases/update-documents.md index 7caee918e4..729656affd 100644 --- a/docs/examples/1.8.x/server-go/examples/databases/update-documents.md +++ b/docs/examples/1.8.x/server-go/examples/databases/update-documents.md @@ -19,4 +19,5 @@ response, error := service.UpdateDocuments( "", databases.WithUpdateDocumentsData(map[string]interface{}{}), databases.WithUpdateDocumentsQueries([]interface{}{}), + databases.WithUpdateDocumentsTransactionId(""), ) diff --git a/docs/examples/1.8.x/server-go/examples/databases/update-transaction.md b/docs/examples/1.8.x/server-go/examples/databases/update-transaction.md new file mode 100644 index 0000000000..76ef4acb72 --- /dev/null +++ b/docs/examples/1.8.x/server-go/examples/databases/update-transaction.md @@ -0,0 +1,21 @@ +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/client" + "github.com/appwrite/sdk-for-go/databases" +) + +client := client.New( + client.WithEndpoint("https://.cloud.appwrite.io/v1") + client.WithProject("") + client.WithKey("") +) + +service := databases.New(client) + +response, error := service.UpdateTransaction( + "", + databases.WithUpdateTransactionCommit(false), + databases.WithUpdateTransactionRollback(false), +) diff --git a/docs/examples/1.8.x/server-go/examples/databases/upsert-document.md b/docs/examples/1.8.x/server-go/examples/databases/upsert-document.md index 00cf8ad408..471c39185b 100644 --- a/docs/examples/1.8.x/server-go/examples/databases/upsert-document.md +++ b/docs/examples/1.8.x/server-go/examples/databases/upsert-document.md @@ -20,4 +20,5 @@ response, error := service.UpsertDocument( "", map[string]interface{}{}, databases.WithUpsertDocumentPermissions(interface{}{"read("any")"}), + databases.WithUpsertDocumentTransactionId(""), ) diff --git a/docs/examples/1.8.x/server-go/examples/databases/upsert-documents.md b/docs/examples/1.8.x/server-go/examples/databases/upsert-documents.md index a81ee4446e..9088883b1f 100644 --- a/docs/examples/1.8.x/server-go/examples/databases/upsert-documents.md +++ b/docs/examples/1.8.x/server-go/examples/databases/upsert-documents.md @@ -18,4 +18,5 @@ response, error := service.UpsertDocuments( "", "", []interface{}{}, + databases.WithUpsertDocumentsTransactionId(""), ) diff --git a/docs/examples/1.8.x/server-go/examples/messaging/create-push.md b/docs/examples/1.8.x/server-go/examples/messaging/create-push.md index fe2371bacd..a607f4391b 100644 --- a/docs/examples/1.8.x/server-go/examples/messaging/create-push.md +++ b/docs/examples/1.8.x/server-go/examples/messaging/create-push.md @@ -23,7 +23,7 @@ response, error := service.CreatePush( messaging.WithCreatePushTargets([]interface{}{}), messaging.WithCreatePushData(map[string]interface{}{}), messaging.WithCreatePushAction(""), - messaging.WithCreatePushImage("[ID1:ID2]"), + messaging.WithCreatePushImage(""), messaging.WithCreatePushIcon(""), messaging.WithCreatePushSound(""), messaging.WithCreatePushColor(""), diff --git a/docs/examples/1.8.x/server-go/examples/messaging/update-push.md b/docs/examples/1.8.x/server-go/examples/messaging/update-push.md index 190627fa43..d364159e35 100644 --- a/docs/examples/1.8.x/server-go/examples/messaging/update-push.md +++ b/docs/examples/1.8.x/server-go/examples/messaging/update-push.md @@ -23,7 +23,7 @@ response, error := service.UpdatePush( messaging.WithUpdatePushBody(""), messaging.WithUpdatePushData(map[string]interface{}{}), messaging.WithUpdatePushAction(""), - messaging.WithUpdatePushImage("[ID1:ID2]"), + messaging.WithUpdatePushImage(""), messaging.WithUpdatePushIcon(""), messaging.WithUpdatePushSound(""), messaging.WithUpdatePushColor(""), diff --git a/docs/examples/1.8.x/server-go/examples/tablesdb/create-operations.md b/docs/examples/1.8.x/server-go/examples/tablesdb/create-operations.md new file mode 100644 index 0000000000..330ece2bb9 --- /dev/null +++ b/docs/examples/1.8.x/server-go/examples/tablesdb/create-operations.md @@ -0,0 +1,30 @@ +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/client" + "github.com/appwrite/sdk-for-go/tablesdb" +) + +client := client.New( + client.WithEndpoint("https://.cloud.appwrite.io/v1") + client.WithProject("") + client.WithKey("") +) + +service := tablesdb.New(client) + +response, error := service.CreateOperations( + "", + tablesdb.WithCreateOperationsOperations(interface{}{ + { + "action": "create", + "databaseId": "", + "tableId": "", + "rowId": "", + "data": { + "name": "Walter O'Brien" + } + } + }), +) diff --git a/docs/examples/1.8.x/server-go/examples/tablesdb/create-row.md b/docs/examples/1.8.x/server-go/examples/tablesdb/create-row.md index 596f11cf75..24054ace1d 100644 --- a/docs/examples/1.8.x/server-go/examples/tablesdb/create-row.md +++ b/docs/examples/1.8.x/server-go/examples/tablesdb/create-row.md @@ -26,4 +26,5 @@ response, error := service.CreateRow( "isAdmin": false }, tablesdb.WithCreateRowPermissions(interface{}{"read("any")"}), + tablesdb.WithCreateRowTransactionId(""), ) diff --git a/docs/examples/1.8.x/server-go/examples/tablesdb/create-rows.md b/docs/examples/1.8.x/server-go/examples/tablesdb/create-rows.md index 2d83be06df..6ddeb067db 100644 --- a/docs/examples/1.8.x/server-go/examples/tablesdb/create-rows.md +++ b/docs/examples/1.8.x/server-go/examples/tablesdb/create-rows.md @@ -18,4 +18,5 @@ response, error := service.CreateRows( "", "", []interface{}{}, + tablesdb.WithCreateRowsTransactionId(""), ) diff --git a/docs/examples/1.8.x/server-go/examples/tablesdb/create-transaction.md b/docs/examples/1.8.x/server-go/examples/tablesdb/create-transaction.md new file mode 100644 index 0000000000..165f897cf8 --- /dev/null +++ b/docs/examples/1.8.x/server-go/examples/tablesdb/create-transaction.md @@ -0,0 +1,19 @@ +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/client" + "github.com/appwrite/sdk-for-go/tablesdb" +) + +client := client.New( + client.WithEndpoint("https://.cloud.appwrite.io/v1") + client.WithProject("") + client.WithKey("") +) + +service := tablesdb.New(client) + +response, error := service.CreateTransaction( + tablesdb.WithCreateTransactionTtl(60), +) diff --git a/docs/examples/1.8.x/server-go/examples/tablesdb/decrement-row-column.md b/docs/examples/1.8.x/server-go/examples/tablesdb/decrement-row-column.md index cd8d6c8983..a74bdda219 100644 --- a/docs/examples/1.8.x/server-go/examples/tablesdb/decrement-row-column.md +++ b/docs/examples/1.8.x/server-go/examples/tablesdb/decrement-row-column.md @@ -21,4 +21,5 @@ response, error := service.DecrementRowColumn( "", tablesdb.WithDecrementRowColumnValue(0), tablesdb.WithDecrementRowColumnMin(0), + tablesdb.WithDecrementRowColumnTransactionId(""), ) diff --git a/docs/examples/1.8.x/server-go/examples/tablesdb/delete-row.md b/docs/examples/1.8.x/server-go/examples/tablesdb/delete-row.md index 8571a54c6c..39338452bc 100644 --- a/docs/examples/1.8.x/server-go/examples/tablesdb/delete-row.md +++ b/docs/examples/1.8.x/server-go/examples/tablesdb/delete-row.md @@ -18,4 +18,5 @@ response, error := service.DeleteRow( "", "", "", + tablesdb.WithDeleteRowTransactionId(""), ) diff --git a/docs/examples/1.8.x/server-go/examples/tablesdb/delete-rows.md b/docs/examples/1.8.x/server-go/examples/tablesdb/delete-rows.md index 364a4c942f..b9fa49b5fb 100644 --- a/docs/examples/1.8.x/server-go/examples/tablesdb/delete-rows.md +++ b/docs/examples/1.8.x/server-go/examples/tablesdb/delete-rows.md @@ -18,4 +18,5 @@ response, error := service.DeleteRows( "", "", tablesdb.WithDeleteRowsQueries([]interface{}{}), + tablesdb.WithDeleteRowsTransactionId(""), ) diff --git a/docs/examples/1.8.x/server-go/examples/tablesdb/delete-transaction.md b/docs/examples/1.8.x/server-go/examples/tablesdb/delete-transaction.md new file mode 100644 index 0000000000..16ee050534 --- /dev/null +++ b/docs/examples/1.8.x/server-go/examples/tablesdb/delete-transaction.md @@ -0,0 +1,19 @@ +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/client" + "github.com/appwrite/sdk-for-go/tablesdb" +) + +client := client.New( + client.WithEndpoint("https://.cloud.appwrite.io/v1") + client.WithProject("") + client.WithKey("") +) + +service := tablesdb.New(client) + +response, error := service.DeleteTransaction( + "", +) diff --git a/docs/examples/1.8.x/server-go/examples/tablesdb/get-row.md b/docs/examples/1.8.x/server-go/examples/tablesdb/get-row.md index 3a555f07c5..025c6b55a1 100644 --- a/docs/examples/1.8.x/server-go/examples/tablesdb/get-row.md +++ b/docs/examples/1.8.x/server-go/examples/tablesdb/get-row.md @@ -19,4 +19,5 @@ response, error := service.GetRow( "", "", tablesdb.WithGetRowQueries([]interface{}{}), + tablesdb.WithGetRowTransactionId(""), ) diff --git a/docs/examples/1.8.x/server-go/examples/tablesdb/get-transaction.md b/docs/examples/1.8.x/server-go/examples/tablesdb/get-transaction.md new file mode 100644 index 0000000000..d478007b62 --- /dev/null +++ b/docs/examples/1.8.x/server-go/examples/tablesdb/get-transaction.md @@ -0,0 +1,19 @@ +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/client" + "github.com/appwrite/sdk-for-go/tablesdb" +) + +client := client.New( + client.WithEndpoint("https://.cloud.appwrite.io/v1") + client.WithProject("") + client.WithKey("") +) + +service := tablesdb.New(client) + +response, error := service.GetTransaction( + "", +) diff --git a/docs/examples/1.8.x/server-go/examples/tablesdb/increment-row-column.md b/docs/examples/1.8.x/server-go/examples/tablesdb/increment-row-column.md index d072099cc6..4548f3cbb1 100644 --- a/docs/examples/1.8.x/server-go/examples/tablesdb/increment-row-column.md +++ b/docs/examples/1.8.x/server-go/examples/tablesdb/increment-row-column.md @@ -21,4 +21,5 @@ response, error := service.IncrementRowColumn( "", tablesdb.WithIncrementRowColumnValue(0), tablesdb.WithIncrementRowColumnMax(0), + tablesdb.WithIncrementRowColumnTransactionId(""), ) diff --git a/docs/examples/1.8.x/server-go/examples/tablesdb/list-rows.md b/docs/examples/1.8.x/server-go/examples/tablesdb/list-rows.md index 34a7b6fb98..784fbc81d9 100644 --- a/docs/examples/1.8.x/server-go/examples/tablesdb/list-rows.md +++ b/docs/examples/1.8.x/server-go/examples/tablesdb/list-rows.md @@ -18,4 +18,5 @@ response, error := service.ListRows( "", "", tablesdb.WithListRowsQueries([]interface{}{}), + tablesdb.WithListRowsTransactionId(""), ) diff --git a/docs/examples/1.8.x/server-go/examples/tablesdb/list-transactions.md b/docs/examples/1.8.x/server-go/examples/tablesdb/list-transactions.md new file mode 100644 index 0000000000..7379d8555e --- /dev/null +++ b/docs/examples/1.8.x/server-go/examples/tablesdb/list-transactions.md @@ -0,0 +1,19 @@ +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/client" + "github.com/appwrite/sdk-for-go/tablesdb" +) + +client := client.New( + client.WithEndpoint("https://.cloud.appwrite.io/v1") + client.WithProject("") + client.WithKey("") +) + +service := tablesdb.New(client) + +response, error := service.ListTransactions( + tablesdb.WithListTransactionsQueries([]interface{}{}), +) diff --git a/docs/examples/1.8.x/server-go/examples/tablesdb/update-row.md b/docs/examples/1.8.x/server-go/examples/tablesdb/update-row.md index 1e819bb589..12ea0b10a4 100644 --- a/docs/examples/1.8.x/server-go/examples/tablesdb/update-row.md +++ b/docs/examples/1.8.x/server-go/examples/tablesdb/update-row.md @@ -20,4 +20,5 @@ response, error := service.UpdateRow( "", tablesdb.WithUpdateRowData(map[string]interface{}{}), tablesdb.WithUpdateRowPermissions(interface{}{"read("any")"}), + tablesdb.WithUpdateRowTransactionId(""), ) diff --git a/docs/examples/1.8.x/server-go/examples/tablesdb/update-rows.md b/docs/examples/1.8.x/server-go/examples/tablesdb/update-rows.md index 3541dce134..ff6a81e57c 100644 --- a/docs/examples/1.8.x/server-go/examples/tablesdb/update-rows.md +++ b/docs/examples/1.8.x/server-go/examples/tablesdb/update-rows.md @@ -19,4 +19,5 @@ response, error := service.UpdateRows( "", tablesdb.WithUpdateRowsData(map[string]interface{}{}), tablesdb.WithUpdateRowsQueries([]interface{}{}), + tablesdb.WithUpdateRowsTransactionId(""), ) diff --git a/docs/examples/1.8.x/server-go/examples/tablesdb/update-transaction.md b/docs/examples/1.8.x/server-go/examples/tablesdb/update-transaction.md new file mode 100644 index 0000000000..9842a4555c --- /dev/null +++ b/docs/examples/1.8.x/server-go/examples/tablesdb/update-transaction.md @@ -0,0 +1,21 @@ +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/client" + "github.com/appwrite/sdk-for-go/tablesdb" +) + +client := client.New( + client.WithEndpoint("https://.cloud.appwrite.io/v1") + client.WithProject("") + client.WithKey("") +) + +service := tablesdb.New(client) + +response, error := service.UpdateTransaction( + "", + tablesdb.WithUpdateTransactionCommit(false), + tablesdb.WithUpdateTransactionRollback(false), +) diff --git a/docs/examples/1.8.x/server-go/examples/tablesdb/upsert-row.md b/docs/examples/1.8.x/server-go/examples/tablesdb/upsert-row.md index 9fec778142..4caa5415e9 100644 --- a/docs/examples/1.8.x/server-go/examples/tablesdb/upsert-row.md +++ b/docs/examples/1.8.x/server-go/examples/tablesdb/upsert-row.md @@ -20,4 +20,5 @@ response, error := service.UpsertRow( "", tablesdb.WithUpsertRowData(map[string]interface{}{}), tablesdb.WithUpsertRowPermissions(interface{}{"read("any")"}), + tablesdb.WithUpsertRowTransactionId(""), ) diff --git a/docs/examples/1.8.x/server-go/examples/tablesdb/upsert-rows.md b/docs/examples/1.8.x/server-go/examples/tablesdb/upsert-rows.md index 5ded736cd0..a74d6ee9b1 100644 --- a/docs/examples/1.8.x/server-go/examples/tablesdb/upsert-rows.md +++ b/docs/examples/1.8.x/server-go/examples/tablesdb/upsert-rows.md @@ -18,4 +18,5 @@ response, error := service.UpsertRows( "", "", []interface{}{}, + tablesdb.WithUpsertRowsTransactionId(""), ) diff --git a/docs/examples/1.8.x/server-graphql/examples/databases/create-document.md b/docs/examples/1.8.x/server-graphql/examples/databases/create-document.md index 39e4bba1cb..411615f7a7 100644 --- a/docs/examples/1.8.x/server-graphql/examples/databases/create-document.md +++ b/docs/examples/1.8.x/server-graphql/examples/databases/create-document.md @@ -4,7 +4,8 @@ mutation { collectionId: "", documentId: "", data: "{\"username\":\"walter.obrien\",\"email\":\"walter.obrien@example.com\",\"fullName\":\"Walter O'Brien\",\"age\":30,\"isAdmin\":false}", - permissions: ["read("any")"] + permissions: ["read("any")"], + transactionId: "" ) { _id _sequence diff --git a/docs/examples/1.8.x/server-graphql/examples/databases/create-documents.md b/docs/examples/1.8.x/server-graphql/examples/databases/create-documents.md index 8ce79dcbb5..01a8914d0e 100644 --- a/docs/examples/1.8.x/server-graphql/examples/databases/create-documents.md +++ b/docs/examples/1.8.x/server-graphql/examples/databases/create-documents.md @@ -2,7 +2,8 @@ mutation { databasesCreateDocuments( databaseId: "", collectionId: "", - documents: [] + documents: [], + transactionId: "" ) { total documents { diff --git a/docs/examples/1.8.x/server-graphql/examples/databases/create-operations.md b/docs/examples/1.8.x/server-graphql/examples/databases/create-operations.md new file mode 100644 index 0000000000..1be3b39ee1 --- /dev/null +++ b/docs/examples/1.8.x/server-graphql/examples/databases/create-operations.md @@ -0,0 +1,23 @@ +mutation { + databasesCreateOperations( + transactionId: "", + operations: [ + { + "action": "create", + "databaseId": "", + "collectionId": "", + "documentId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] + ) { + _id + _createdAt + _updatedAt + status + operations + expiresAt + } +} diff --git a/docs/examples/1.8.x/server-graphql/examples/databases/create-transaction.md b/docs/examples/1.8.x/server-graphql/examples/databases/create-transaction.md new file mode 100644 index 0000000000..7fea034ab6 --- /dev/null +++ b/docs/examples/1.8.x/server-graphql/examples/databases/create-transaction.md @@ -0,0 +1,12 @@ +mutation { + databasesCreateTransaction( + ttl: 60 + ) { + _id + _createdAt + _updatedAt + status + operations + expiresAt + } +} diff --git a/docs/examples/1.8.x/server-graphql/examples/databases/decrement-document-attribute.md b/docs/examples/1.8.x/server-graphql/examples/databases/decrement-document-attribute.md index 2e7970049d..e6032fd0e7 100644 --- a/docs/examples/1.8.x/server-graphql/examples/databases/decrement-document-attribute.md +++ b/docs/examples/1.8.x/server-graphql/examples/databases/decrement-document-attribute.md @@ -5,7 +5,8 @@ mutation { documentId: "", attribute: "", value: 0, - min: 0 + min: 0, + transactionId: "" ) { _id _sequence diff --git a/docs/examples/1.8.x/server-graphql/examples/databases/delete-document.md b/docs/examples/1.8.x/server-graphql/examples/databases/delete-document.md index 848371bca0..2e172aa5dd 100644 --- a/docs/examples/1.8.x/server-graphql/examples/databases/delete-document.md +++ b/docs/examples/1.8.x/server-graphql/examples/databases/delete-document.md @@ -2,7 +2,8 @@ mutation { databasesDeleteDocument( databaseId: "", collectionId: "", - documentId: "" + documentId: "", + transactionId: "" ) { status } diff --git a/docs/examples/1.8.x/server-graphql/examples/databases/delete-documents.md b/docs/examples/1.8.x/server-graphql/examples/databases/delete-documents.md index 5822d3b950..aed5f6333f 100644 --- a/docs/examples/1.8.x/server-graphql/examples/databases/delete-documents.md +++ b/docs/examples/1.8.x/server-graphql/examples/databases/delete-documents.md @@ -2,7 +2,8 @@ mutation { databasesDeleteDocuments( databaseId: "", collectionId: "", - queries: [] + queries: [], + transactionId: "" ) { total documents { diff --git a/docs/examples/1.8.x/server-graphql/examples/databases/delete-transaction.md b/docs/examples/1.8.x/server-graphql/examples/databases/delete-transaction.md new file mode 100644 index 0000000000..cd29a0b8a6 --- /dev/null +++ b/docs/examples/1.8.x/server-graphql/examples/databases/delete-transaction.md @@ -0,0 +1,7 @@ +mutation { + databasesDeleteTransaction( + transactionId: "" + ) { + status + } +} diff --git a/docs/examples/1.8.x/server-graphql/examples/databases/get-transaction.md b/docs/examples/1.8.x/server-graphql/examples/databases/get-transaction.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/examples/1.8.x/server-graphql/examples/databases/increment-document-attribute.md b/docs/examples/1.8.x/server-graphql/examples/databases/increment-document-attribute.md index 322ed69ced..3518ff1583 100644 --- a/docs/examples/1.8.x/server-graphql/examples/databases/increment-document-attribute.md +++ b/docs/examples/1.8.x/server-graphql/examples/databases/increment-document-attribute.md @@ -5,7 +5,8 @@ mutation { documentId: "", attribute: "", value: 0, - max: 0 + max: 0, + transactionId: "" ) { _id _sequence diff --git a/docs/examples/1.8.x/server-graphql/examples/databases/list-transactions.md b/docs/examples/1.8.x/server-graphql/examples/databases/list-transactions.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/examples/1.8.x/server-graphql/examples/databases/update-document.md b/docs/examples/1.8.x/server-graphql/examples/databases/update-document.md index aea605d9d7..cf43d9eed0 100644 --- a/docs/examples/1.8.x/server-graphql/examples/databases/update-document.md +++ b/docs/examples/1.8.x/server-graphql/examples/databases/update-document.md @@ -4,7 +4,8 @@ mutation { collectionId: "", documentId: "", data: "{}", - permissions: ["read("any")"] + permissions: ["read("any")"], + transactionId: "" ) { _id _sequence diff --git a/docs/examples/1.8.x/server-graphql/examples/databases/update-documents.md b/docs/examples/1.8.x/server-graphql/examples/databases/update-documents.md index 83c0c07f84..d6eb18de2a 100644 --- a/docs/examples/1.8.x/server-graphql/examples/databases/update-documents.md +++ b/docs/examples/1.8.x/server-graphql/examples/databases/update-documents.md @@ -3,7 +3,8 @@ mutation { databaseId: "", collectionId: "", data: "{}", - queries: [] + queries: [], + transactionId: "" ) { total documents { diff --git a/docs/examples/1.8.x/server-graphql/examples/databases/update-transaction.md b/docs/examples/1.8.x/server-graphql/examples/databases/update-transaction.md new file mode 100644 index 0000000000..b56c7139ac --- /dev/null +++ b/docs/examples/1.8.x/server-graphql/examples/databases/update-transaction.md @@ -0,0 +1,14 @@ +mutation { + databasesUpdateTransaction( + transactionId: "", + commit: false, + rollback: false + ) { + _id + _createdAt + _updatedAt + status + operations + expiresAt + } +} diff --git a/docs/examples/1.8.x/server-graphql/examples/databases/upsert-document.md b/docs/examples/1.8.x/server-graphql/examples/databases/upsert-document.md index 9d1e753081..d487c0d303 100644 --- a/docs/examples/1.8.x/server-graphql/examples/databases/upsert-document.md +++ b/docs/examples/1.8.x/server-graphql/examples/databases/upsert-document.md @@ -4,7 +4,8 @@ mutation { collectionId: "", documentId: "", data: "{}", - permissions: ["read("any")"] + permissions: ["read("any")"], + transactionId: "" ) { _id _sequence diff --git a/docs/examples/1.8.x/server-graphql/examples/databases/upsert-documents.md b/docs/examples/1.8.x/server-graphql/examples/databases/upsert-documents.md index 2bfb765915..7852ba93f8 100644 --- a/docs/examples/1.8.x/server-graphql/examples/databases/upsert-documents.md +++ b/docs/examples/1.8.x/server-graphql/examples/databases/upsert-documents.md @@ -2,7 +2,8 @@ mutation { databasesUpsertDocuments( databaseId: "", collectionId: "", - documents: [] + documents: [], + transactionId: "" ) { total documents { diff --git a/docs/examples/1.8.x/server-graphql/examples/messaging/create-push.md b/docs/examples/1.8.x/server-graphql/examples/messaging/create-push.md index 92264d1b67..dc924dfd32 100644 --- a/docs/examples/1.8.x/server-graphql/examples/messaging/create-push.md +++ b/docs/examples/1.8.x/server-graphql/examples/messaging/create-push.md @@ -8,7 +8,7 @@ mutation { targets: [], data: "{}", action: "", - image: "[ID1:ID2]", + image: "", icon: "", sound: "", color: "", diff --git a/docs/examples/1.8.x/server-graphql/examples/messaging/update-push.md b/docs/examples/1.8.x/server-graphql/examples/messaging/update-push.md index 8ee2f57610..3436e0cf2f 100644 --- a/docs/examples/1.8.x/server-graphql/examples/messaging/update-push.md +++ b/docs/examples/1.8.x/server-graphql/examples/messaging/update-push.md @@ -8,7 +8,7 @@ mutation { body: "", data: "{}", action: "", - image: "[ID1:ID2]", + image: "", icon: "", sound: "", color: "", diff --git a/docs/examples/1.8.x/server-graphql/examples/tablesdb/create-operations.md b/docs/examples/1.8.x/server-graphql/examples/tablesdb/create-operations.md new file mode 100644 index 0000000000..bb2be8085a --- /dev/null +++ b/docs/examples/1.8.x/server-graphql/examples/tablesdb/create-operations.md @@ -0,0 +1,23 @@ +mutation { + tablesDBCreateOperations( + transactionId: "", + operations: [ + { + "action": "create", + "databaseId": "", + "tableId": "", + "rowId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] + ) { + _id + _createdAt + _updatedAt + status + operations + expiresAt + } +} diff --git a/docs/examples/1.8.x/server-graphql/examples/tablesdb/create-row.md b/docs/examples/1.8.x/server-graphql/examples/tablesdb/create-row.md index c7d2ec7d03..109bc008d6 100644 --- a/docs/examples/1.8.x/server-graphql/examples/tablesdb/create-row.md +++ b/docs/examples/1.8.x/server-graphql/examples/tablesdb/create-row.md @@ -4,7 +4,8 @@ mutation { tableId: "", rowId: "", data: "{\"username\":\"walter.obrien\",\"email\":\"walter.obrien@example.com\",\"fullName\":\"Walter O'Brien\",\"age\":30,\"isAdmin\":false}", - permissions: ["read("any")"] + permissions: ["read("any")"], + transactionId: "" ) { _id _sequence diff --git a/docs/examples/1.8.x/server-graphql/examples/tablesdb/create-rows.md b/docs/examples/1.8.x/server-graphql/examples/tablesdb/create-rows.md index 25dc9a367d..9364b5676d 100644 --- a/docs/examples/1.8.x/server-graphql/examples/tablesdb/create-rows.md +++ b/docs/examples/1.8.x/server-graphql/examples/tablesdb/create-rows.md @@ -2,7 +2,8 @@ mutation { tablesDBCreateRows( databaseId: "", tableId: "", - rows: [] + rows: [], + transactionId: "" ) { total rows { diff --git a/docs/examples/1.8.x/server-graphql/examples/tablesdb/create-transaction.md b/docs/examples/1.8.x/server-graphql/examples/tablesdb/create-transaction.md new file mode 100644 index 0000000000..0e874f0c78 --- /dev/null +++ b/docs/examples/1.8.x/server-graphql/examples/tablesdb/create-transaction.md @@ -0,0 +1,12 @@ +mutation { + tablesDBCreateTransaction( + ttl: 60 + ) { + _id + _createdAt + _updatedAt + status + operations + expiresAt + } +} diff --git a/docs/examples/1.8.x/server-graphql/examples/tablesdb/decrement-row-column.md b/docs/examples/1.8.x/server-graphql/examples/tablesdb/decrement-row-column.md index 398ec19901..1d57d79b54 100644 --- a/docs/examples/1.8.x/server-graphql/examples/tablesdb/decrement-row-column.md +++ b/docs/examples/1.8.x/server-graphql/examples/tablesdb/decrement-row-column.md @@ -5,7 +5,8 @@ mutation { rowId: "", column: "", value: 0, - min: 0 + min: 0, + transactionId: "" ) { _id _sequence diff --git a/docs/examples/1.8.x/server-graphql/examples/tablesdb/delete-row.md b/docs/examples/1.8.x/server-graphql/examples/tablesdb/delete-row.md index 1a08b0f60d..3b44913049 100644 --- a/docs/examples/1.8.x/server-graphql/examples/tablesdb/delete-row.md +++ b/docs/examples/1.8.x/server-graphql/examples/tablesdb/delete-row.md @@ -2,7 +2,8 @@ mutation { tablesDBDeleteRow( databaseId: "", tableId: "", - rowId: "" + rowId: "", + transactionId: "" ) { status } diff --git a/docs/examples/1.8.x/server-graphql/examples/tablesdb/delete-rows.md b/docs/examples/1.8.x/server-graphql/examples/tablesdb/delete-rows.md index dfa7c13779..9dae8fc679 100644 --- a/docs/examples/1.8.x/server-graphql/examples/tablesdb/delete-rows.md +++ b/docs/examples/1.8.x/server-graphql/examples/tablesdb/delete-rows.md @@ -2,7 +2,8 @@ mutation { tablesDBDeleteRows( databaseId: "", tableId: "", - queries: [] + queries: [], + transactionId: "" ) { total rows { diff --git a/docs/examples/1.8.x/server-graphql/examples/tablesdb/delete-transaction.md b/docs/examples/1.8.x/server-graphql/examples/tablesdb/delete-transaction.md new file mode 100644 index 0000000000..4a2d6f15a2 --- /dev/null +++ b/docs/examples/1.8.x/server-graphql/examples/tablesdb/delete-transaction.md @@ -0,0 +1,7 @@ +mutation { + tablesDBDeleteTransaction( + transactionId: "" + ) { + status + } +} diff --git a/docs/examples/1.8.x/server-graphql/examples/tablesdb/get-transaction.md b/docs/examples/1.8.x/server-graphql/examples/tablesdb/get-transaction.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/examples/1.8.x/server-graphql/examples/tablesdb/increment-row-column.md b/docs/examples/1.8.x/server-graphql/examples/tablesdb/increment-row-column.md index b7ff87f387..3ae008e718 100644 --- a/docs/examples/1.8.x/server-graphql/examples/tablesdb/increment-row-column.md +++ b/docs/examples/1.8.x/server-graphql/examples/tablesdb/increment-row-column.md @@ -5,7 +5,8 @@ mutation { rowId: "", column: "", value: 0, - max: 0 + max: 0, + transactionId: "" ) { _id _sequence diff --git a/docs/examples/1.8.x/server-graphql/examples/tablesdb/list-transactions.md b/docs/examples/1.8.x/server-graphql/examples/tablesdb/list-transactions.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/examples/1.8.x/server-graphql/examples/tablesdb/update-row.md b/docs/examples/1.8.x/server-graphql/examples/tablesdb/update-row.md index 5a5b288ab8..aa89e6ae01 100644 --- a/docs/examples/1.8.x/server-graphql/examples/tablesdb/update-row.md +++ b/docs/examples/1.8.x/server-graphql/examples/tablesdb/update-row.md @@ -4,7 +4,8 @@ mutation { tableId: "", rowId: "", data: "{}", - permissions: ["read("any")"] + permissions: ["read("any")"], + transactionId: "" ) { _id _sequence diff --git a/docs/examples/1.8.x/server-graphql/examples/tablesdb/update-rows.md b/docs/examples/1.8.x/server-graphql/examples/tablesdb/update-rows.md index 4816748352..5a6203a4dc 100644 --- a/docs/examples/1.8.x/server-graphql/examples/tablesdb/update-rows.md +++ b/docs/examples/1.8.x/server-graphql/examples/tablesdb/update-rows.md @@ -3,7 +3,8 @@ mutation { databaseId: "", tableId: "", data: "{}", - queries: [] + queries: [], + transactionId: "" ) { total rows { diff --git a/docs/examples/1.8.x/server-graphql/examples/tablesdb/update-transaction.md b/docs/examples/1.8.x/server-graphql/examples/tablesdb/update-transaction.md new file mode 100644 index 0000000000..2094877303 --- /dev/null +++ b/docs/examples/1.8.x/server-graphql/examples/tablesdb/update-transaction.md @@ -0,0 +1,14 @@ +mutation { + tablesDBUpdateTransaction( + transactionId: "", + commit: false, + rollback: false + ) { + _id + _createdAt + _updatedAt + status + operations + expiresAt + } +} diff --git a/docs/examples/1.8.x/server-graphql/examples/tablesdb/upsert-row.md b/docs/examples/1.8.x/server-graphql/examples/tablesdb/upsert-row.md index cc3b63de4a..3fe36ee7f1 100644 --- a/docs/examples/1.8.x/server-graphql/examples/tablesdb/upsert-row.md +++ b/docs/examples/1.8.x/server-graphql/examples/tablesdb/upsert-row.md @@ -4,7 +4,8 @@ mutation { tableId: "", rowId: "", data: "{}", - permissions: ["read("any")"] + permissions: ["read("any")"], + transactionId: "" ) { _id _sequence diff --git a/docs/examples/1.8.x/server-graphql/examples/tablesdb/upsert-rows.md b/docs/examples/1.8.x/server-graphql/examples/tablesdb/upsert-rows.md index f4e01c0af7..bbfc09c763 100644 --- a/docs/examples/1.8.x/server-graphql/examples/tablesdb/upsert-rows.md +++ b/docs/examples/1.8.x/server-graphql/examples/tablesdb/upsert-rows.md @@ -2,7 +2,8 @@ mutation { tablesDBUpsertRows( databaseId: "", tableId: "", - rows: [] + rows: [], + transactionId: "" ) { total rows { diff --git a/docs/examples/1.8.x/server-kotlin/java/databases/create-document.md b/docs/examples/1.8.x/server-kotlin/java/databases/create-document.md index d5e777d157..9c6357dfae 100644 --- a/docs/examples/1.8.x/server-kotlin/java/databases/create-document.md +++ b/docs/examples/1.8.x/server-kotlin/java/databases/create-document.md @@ -21,6 +21,7 @@ databases.createDocument( "isAdmin" to false ), // data listOf("read("any")"), // permissions (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/java/databases/create-documents.md b/docs/examples/1.8.x/server-kotlin/java/databases/create-documents.md index 0de0c276ed..3a4540974b 100644 --- a/docs/examples/1.8.x/server-kotlin/java/databases/create-documents.md +++ b/docs/examples/1.8.x/server-kotlin/java/databases/create-documents.md @@ -13,6 +13,7 @@ databases.createDocuments( "", // databaseId "", // collectionId listOf(), // documents + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/java/databases/create-operations.md b/docs/examples/1.8.x/server-kotlin/java/databases/create-operations.md new file mode 100644 index 0000000000..2dad8a15ac --- /dev/null +++ b/docs/examples/1.8.x/server-kotlin/java/databases/create-operations.md @@ -0,0 +1,34 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Databases; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey(""); // Your secret API key + +Databases databases = new Databases(client); + +databases.createOperations( + "", // transactionId + listOf( + { + "action": "create", + "databaseId": "", + "collectionId": "", + "documentId": "", + "data": { + "name": "Walter O'Brien" + } + } + ), // operations (optional) + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + System.out.println(result); + }) +); + diff --git a/docs/examples/1.8.x/server-kotlin/java/databases/create-transaction.md b/docs/examples/1.8.x/server-kotlin/java/databases/create-transaction.md new file mode 100644 index 0000000000..5fb7c5936a --- /dev/null +++ b/docs/examples/1.8.x/server-kotlin/java/databases/create-transaction.md @@ -0,0 +1,23 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Databases; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey(""); // Your secret API key + +Databases databases = new Databases(client); + +databases.createTransaction( + 60, // ttl (optional) + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + System.out.println(result); + }) +); + diff --git a/docs/examples/1.8.x/server-kotlin/java/databases/decrement-document-attribute.md b/docs/examples/1.8.x/server-kotlin/java/databases/decrement-document-attribute.md index a44cc51260..a852083bce 100644 --- a/docs/examples/1.8.x/server-kotlin/java/databases/decrement-document-attribute.md +++ b/docs/examples/1.8.x/server-kotlin/java/databases/decrement-document-attribute.md @@ -16,6 +16,7 @@ databases.decrementDocumentAttribute( "", // attribute 0, // value (optional) 0, // min (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/java/databases/delete-document.md b/docs/examples/1.8.x/server-kotlin/java/databases/delete-document.md index f6e6209f36..2f7003b234 100644 --- a/docs/examples/1.8.x/server-kotlin/java/databases/delete-document.md +++ b/docs/examples/1.8.x/server-kotlin/java/databases/delete-document.md @@ -13,6 +13,7 @@ databases.deleteDocument( "", // databaseId "", // collectionId "", // documentId + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/java/databases/delete-documents.md b/docs/examples/1.8.x/server-kotlin/java/databases/delete-documents.md index e8394b1ff9..958c40c382 100644 --- a/docs/examples/1.8.x/server-kotlin/java/databases/delete-documents.md +++ b/docs/examples/1.8.x/server-kotlin/java/databases/delete-documents.md @@ -13,6 +13,7 @@ databases.deleteDocuments( "", // databaseId "", // collectionId listOf(), // queries (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/java/databases/delete-transaction.md b/docs/examples/1.8.x/server-kotlin/java/databases/delete-transaction.md new file mode 100644 index 0000000000..200bbbdc26 --- /dev/null +++ b/docs/examples/1.8.x/server-kotlin/java/databases/delete-transaction.md @@ -0,0 +1,23 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Databases; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey(""); // Your secret API key + +Databases databases = new Databases(client); + +databases.deleteTransaction( + "", // transactionId + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + System.out.println(result); + }) +); + diff --git a/docs/examples/1.8.x/server-kotlin/java/databases/get-document.md b/docs/examples/1.8.x/server-kotlin/java/databases/get-document.md index 2719073a7d..489447f599 100644 --- a/docs/examples/1.8.x/server-kotlin/java/databases/get-document.md +++ b/docs/examples/1.8.x/server-kotlin/java/databases/get-document.md @@ -14,6 +14,7 @@ databases.getDocument( "", // collectionId "", // documentId listOf(), // queries (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/java/databases/get-transaction.md b/docs/examples/1.8.x/server-kotlin/java/databases/get-transaction.md new file mode 100644 index 0000000000..d896ca0751 --- /dev/null +++ b/docs/examples/1.8.x/server-kotlin/java/databases/get-transaction.md @@ -0,0 +1,23 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Databases; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey(""); // Your secret API key + +Databases databases = new Databases(client); + +databases.getTransaction( + "", // transactionId + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + System.out.println(result); + }) +); + diff --git a/docs/examples/1.8.x/server-kotlin/java/databases/increment-document-attribute.md b/docs/examples/1.8.x/server-kotlin/java/databases/increment-document-attribute.md index b5b5054e25..be837d00f8 100644 --- a/docs/examples/1.8.x/server-kotlin/java/databases/increment-document-attribute.md +++ b/docs/examples/1.8.x/server-kotlin/java/databases/increment-document-attribute.md @@ -16,6 +16,7 @@ databases.incrementDocumentAttribute( "", // attribute 0, // value (optional) 0, // max (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/java/databases/list-documents.md b/docs/examples/1.8.x/server-kotlin/java/databases/list-documents.md index 36982c0eb0..1e84348c1a 100644 --- a/docs/examples/1.8.x/server-kotlin/java/databases/list-documents.md +++ b/docs/examples/1.8.x/server-kotlin/java/databases/list-documents.md @@ -13,6 +13,7 @@ databases.listDocuments( "", // databaseId "", // collectionId listOf(), // queries (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/java/databases/list-transactions.md b/docs/examples/1.8.x/server-kotlin/java/databases/list-transactions.md new file mode 100644 index 0000000000..281fc1205b --- /dev/null +++ b/docs/examples/1.8.x/server-kotlin/java/databases/list-transactions.md @@ -0,0 +1,23 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Databases; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey(""); // Your secret API key + +Databases databases = new Databases(client); + +databases.listTransactions( + listOf(), // queries (optional) + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + System.out.println(result); + }) +); + diff --git a/docs/examples/1.8.x/server-kotlin/java/databases/update-document.md b/docs/examples/1.8.x/server-kotlin/java/databases/update-document.md index f7b05c9601..f3019ab95b 100644 --- a/docs/examples/1.8.x/server-kotlin/java/databases/update-document.md +++ b/docs/examples/1.8.x/server-kotlin/java/databases/update-document.md @@ -15,6 +15,7 @@ databases.updateDocument( "", // documentId mapOf( "a" to "b" ), // data (optional) listOf("read("any")"), // permissions (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/java/databases/update-documents.md b/docs/examples/1.8.x/server-kotlin/java/databases/update-documents.md index b4138b41d2..a685ac81fc 100644 --- a/docs/examples/1.8.x/server-kotlin/java/databases/update-documents.md +++ b/docs/examples/1.8.x/server-kotlin/java/databases/update-documents.md @@ -14,6 +14,7 @@ databases.updateDocuments( "", // collectionId mapOf( "a" to "b" ), // data (optional) listOf(), // queries (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/java/databases/update-transaction.md b/docs/examples/1.8.x/server-kotlin/java/databases/update-transaction.md new file mode 100644 index 0000000000..8479ed31aa --- /dev/null +++ b/docs/examples/1.8.x/server-kotlin/java/databases/update-transaction.md @@ -0,0 +1,25 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Databases; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey(""); // Your secret API key + +Databases databases = new Databases(client); + +databases.updateTransaction( + "", // transactionId + false, // commit (optional) + false, // rollback (optional) + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + System.out.println(result); + }) +); + diff --git a/docs/examples/1.8.x/server-kotlin/java/databases/upsert-document.md b/docs/examples/1.8.x/server-kotlin/java/databases/upsert-document.md index daa44141e2..39864b9ac3 100644 --- a/docs/examples/1.8.x/server-kotlin/java/databases/upsert-document.md +++ b/docs/examples/1.8.x/server-kotlin/java/databases/upsert-document.md @@ -15,6 +15,7 @@ databases.upsertDocument( "", // documentId mapOf( "a" to "b" ), // data listOf("read("any")"), // permissions (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/java/databases/upsert-documents.md b/docs/examples/1.8.x/server-kotlin/java/databases/upsert-documents.md index 95e9a33ef2..b8fcd8781a 100644 --- a/docs/examples/1.8.x/server-kotlin/java/databases/upsert-documents.md +++ b/docs/examples/1.8.x/server-kotlin/java/databases/upsert-documents.md @@ -13,6 +13,7 @@ databases.upsertDocuments( "", // databaseId "", // collectionId listOf(), // documents + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/java/messaging/create-push.md b/docs/examples/1.8.x/server-kotlin/java/messaging/create-push.md index 277ab9655c..14e8ca2679 100644 --- a/docs/examples/1.8.x/server-kotlin/java/messaging/create-push.md +++ b/docs/examples/1.8.x/server-kotlin/java/messaging/create-push.md @@ -18,7 +18,7 @@ messaging.createPush( listOf(), // targets (optional) mapOf( "a" to "b" ), // data (optional) "", // action (optional) - "[ID1:ID2]", // image (optional) + "", // image (optional) "", // icon (optional) "", // sound (optional) "", // color (optional) diff --git a/docs/examples/1.8.x/server-kotlin/java/messaging/update-push.md b/docs/examples/1.8.x/server-kotlin/java/messaging/update-push.md index b7038de6a4..ce56683674 100644 --- a/docs/examples/1.8.x/server-kotlin/java/messaging/update-push.md +++ b/docs/examples/1.8.x/server-kotlin/java/messaging/update-push.md @@ -18,7 +18,7 @@ messaging.updatePush( "", // body (optional) mapOf( "a" to "b" ), // data (optional) "", // action (optional) - "[ID1:ID2]", // image (optional) + "", // image (optional) "", // icon (optional) "", // sound (optional) "", // color (optional) diff --git a/docs/examples/1.8.x/server-kotlin/java/tablesdb/create-operations.md b/docs/examples/1.8.x/server-kotlin/java/tablesdb/create-operations.md new file mode 100644 index 0000000000..9504f623b3 --- /dev/null +++ b/docs/examples/1.8.x/server-kotlin/java/tablesdb/create-operations.md @@ -0,0 +1,34 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.TablesDB; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey(""); // Your secret API key + +TablesDB tablesDB = new TablesDB(client); + +tablesDB.createOperations( + "", // transactionId + listOf( + { + "action": "create", + "databaseId": "", + "tableId": "", + "rowId": "", + "data": { + "name": "Walter O'Brien" + } + } + ), // operations (optional) + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + System.out.println(result); + }) +); + diff --git a/docs/examples/1.8.x/server-kotlin/java/tablesdb/create-row.md b/docs/examples/1.8.x/server-kotlin/java/tablesdb/create-row.md index 6c7d84702d..d041511c11 100644 --- a/docs/examples/1.8.x/server-kotlin/java/tablesdb/create-row.md +++ b/docs/examples/1.8.x/server-kotlin/java/tablesdb/create-row.md @@ -21,6 +21,7 @@ tablesDB.createRow( "isAdmin" to false ), // data listOf("read("any")"), // permissions (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/java/tablesdb/create-rows.md b/docs/examples/1.8.x/server-kotlin/java/tablesdb/create-rows.md index 21bdd21879..956d812165 100644 --- a/docs/examples/1.8.x/server-kotlin/java/tablesdb/create-rows.md +++ b/docs/examples/1.8.x/server-kotlin/java/tablesdb/create-rows.md @@ -13,6 +13,7 @@ tablesDB.createRows( "", // databaseId "", // tableId listOf(), // rows + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/java/tablesdb/create-transaction.md b/docs/examples/1.8.x/server-kotlin/java/tablesdb/create-transaction.md new file mode 100644 index 0000000000..3529956c54 --- /dev/null +++ b/docs/examples/1.8.x/server-kotlin/java/tablesdb/create-transaction.md @@ -0,0 +1,23 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.TablesDB; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey(""); // Your secret API key + +TablesDB tablesDB = new TablesDB(client); + +tablesDB.createTransaction( + 60, // ttl (optional) + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + System.out.println(result); + }) +); + diff --git a/docs/examples/1.8.x/server-kotlin/java/tablesdb/decrement-row-column.md b/docs/examples/1.8.x/server-kotlin/java/tablesdb/decrement-row-column.md index b9f250f48f..78a811676d 100644 --- a/docs/examples/1.8.x/server-kotlin/java/tablesdb/decrement-row-column.md +++ b/docs/examples/1.8.x/server-kotlin/java/tablesdb/decrement-row-column.md @@ -16,6 +16,7 @@ tablesDB.decrementRowColumn( "", // column 0, // value (optional) 0, // min (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/java/tablesdb/delete-row.md b/docs/examples/1.8.x/server-kotlin/java/tablesdb/delete-row.md index fd66525a8d..5da1ba0cf3 100644 --- a/docs/examples/1.8.x/server-kotlin/java/tablesdb/delete-row.md +++ b/docs/examples/1.8.x/server-kotlin/java/tablesdb/delete-row.md @@ -13,6 +13,7 @@ tablesDB.deleteRow( "", // databaseId "", // tableId "", // rowId + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/java/tablesdb/delete-rows.md b/docs/examples/1.8.x/server-kotlin/java/tablesdb/delete-rows.md index 43b772e1a3..80ca0bb40f 100644 --- a/docs/examples/1.8.x/server-kotlin/java/tablesdb/delete-rows.md +++ b/docs/examples/1.8.x/server-kotlin/java/tablesdb/delete-rows.md @@ -13,6 +13,7 @@ tablesDB.deleteRows( "", // databaseId "", // tableId listOf(), // queries (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/java/tablesdb/delete-transaction.md b/docs/examples/1.8.x/server-kotlin/java/tablesdb/delete-transaction.md new file mode 100644 index 0000000000..816b6e5dee --- /dev/null +++ b/docs/examples/1.8.x/server-kotlin/java/tablesdb/delete-transaction.md @@ -0,0 +1,23 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.TablesDB; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey(""); // Your secret API key + +TablesDB tablesDB = new TablesDB(client); + +tablesDB.deleteTransaction( + "", // transactionId + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + System.out.println(result); + }) +); + diff --git a/docs/examples/1.8.x/server-kotlin/java/tablesdb/get-row.md b/docs/examples/1.8.x/server-kotlin/java/tablesdb/get-row.md index 03cf3fb234..d642ebcaf1 100644 --- a/docs/examples/1.8.x/server-kotlin/java/tablesdb/get-row.md +++ b/docs/examples/1.8.x/server-kotlin/java/tablesdb/get-row.md @@ -14,6 +14,7 @@ tablesDB.getRow( "", // tableId "", // rowId listOf(), // queries (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/java/tablesdb/get-transaction.md b/docs/examples/1.8.x/server-kotlin/java/tablesdb/get-transaction.md new file mode 100644 index 0000000000..dab07dce4e --- /dev/null +++ b/docs/examples/1.8.x/server-kotlin/java/tablesdb/get-transaction.md @@ -0,0 +1,23 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.TablesDB; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey(""); // Your secret API key + +TablesDB tablesDB = new TablesDB(client); + +tablesDB.getTransaction( + "", // transactionId + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + System.out.println(result); + }) +); + diff --git a/docs/examples/1.8.x/server-kotlin/java/tablesdb/increment-row-column.md b/docs/examples/1.8.x/server-kotlin/java/tablesdb/increment-row-column.md index db48d05c37..33715721a8 100644 --- a/docs/examples/1.8.x/server-kotlin/java/tablesdb/increment-row-column.md +++ b/docs/examples/1.8.x/server-kotlin/java/tablesdb/increment-row-column.md @@ -16,6 +16,7 @@ tablesDB.incrementRowColumn( "", // column 0, // value (optional) 0, // max (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/java/tablesdb/list-rows.md b/docs/examples/1.8.x/server-kotlin/java/tablesdb/list-rows.md index 52cf2a1670..96520e2bc5 100644 --- a/docs/examples/1.8.x/server-kotlin/java/tablesdb/list-rows.md +++ b/docs/examples/1.8.x/server-kotlin/java/tablesdb/list-rows.md @@ -13,6 +13,7 @@ tablesDB.listRows( "", // databaseId "", // tableId listOf(), // queries (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/java/tablesdb/list-transactions.md b/docs/examples/1.8.x/server-kotlin/java/tablesdb/list-transactions.md new file mode 100644 index 0000000000..acc4902da4 --- /dev/null +++ b/docs/examples/1.8.x/server-kotlin/java/tablesdb/list-transactions.md @@ -0,0 +1,23 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.TablesDB; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey(""); // Your secret API key + +TablesDB tablesDB = new TablesDB(client); + +tablesDB.listTransactions( + listOf(), // queries (optional) + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + System.out.println(result); + }) +); + diff --git a/docs/examples/1.8.x/server-kotlin/java/tablesdb/update-row.md b/docs/examples/1.8.x/server-kotlin/java/tablesdb/update-row.md index bedc816f14..b4f9631222 100644 --- a/docs/examples/1.8.x/server-kotlin/java/tablesdb/update-row.md +++ b/docs/examples/1.8.x/server-kotlin/java/tablesdb/update-row.md @@ -15,6 +15,7 @@ tablesDB.updateRow( "", // rowId mapOf( "a" to "b" ), // data (optional) listOf("read("any")"), // permissions (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/java/tablesdb/update-rows.md b/docs/examples/1.8.x/server-kotlin/java/tablesdb/update-rows.md index 169b57c3e5..7d39e4422c 100644 --- a/docs/examples/1.8.x/server-kotlin/java/tablesdb/update-rows.md +++ b/docs/examples/1.8.x/server-kotlin/java/tablesdb/update-rows.md @@ -14,6 +14,7 @@ tablesDB.updateRows( "", // tableId mapOf( "a" to "b" ), // data (optional) listOf(), // queries (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/java/tablesdb/update-transaction.md b/docs/examples/1.8.x/server-kotlin/java/tablesdb/update-transaction.md new file mode 100644 index 0000000000..f043d5dc44 --- /dev/null +++ b/docs/examples/1.8.x/server-kotlin/java/tablesdb/update-transaction.md @@ -0,0 +1,25 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.TablesDB; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey(""); // Your secret API key + +TablesDB tablesDB = new TablesDB(client); + +tablesDB.updateTransaction( + "", // transactionId + false, // commit (optional) + false, // rollback (optional) + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + System.out.println(result); + }) +); + diff --git a/docs/examples/1.8.x/server-kotlin/java/tablesdb/upsert-row.md b/docs/examples/1.8.x/server-kotlin/java/tablesdb/upsert-row.md index d6155fcd1b..b6a986ef4d 100644 --- a/docs/examples/1.8.x/server-kotlin/java/tablesdb/upsert-row.md +++ b/docs/examples/1.8.x/server-kotlin/java/tablesdb/upsert-row.md @@ -15,6 +15,7 @@ tablesDB.upsertRow( "", // rowId mapOf( "a" to "b" ), // data (optional) listOf("read("any")"), // permissions (optional) + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/java/tablesdb/upsert-rows.md b/docs/examples/1.8.x/server-kotlin/java/tablesdb/upsert-rows.md index da15f6a0db..c4b2bf3857 100644 --- a/docs/examples/1.8.x/server-kotlin/java/tablesdb/upsert-rows.md +++ b/docs/examples/1.8.x/server-kotlin/java/tablesdb/upsert-rows.md @@ -13,6 +13,7 @@ tablesDB.upsertRows( "", // databaseId "", // tableId listOf(), // rows + "", // transactionId (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/databases/create-document.md b/docs/examples/1.8.x/server-kotlin/kotlin/databases/create-document.md index 1c1d628729..46cb711b62 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/databases/create-document.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/databases/create-document.md @@ -20,5 +20,6 @@ val response = databases.createDocument( "age" to 30, "isAdmin" to false ), - permissions = listOf("read("any")") // optional + permissions = listOf("read("any")"), // optional + transactionId = "" // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/databases/create-documents.md b/docs/examples/1.8.x/server-kotlin/kotlin/databases/create-documents.md index 41a98dc016..114d5cc707 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/databases/create-documents.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/databases/create-documents.md @@ -12,5 +12,6 @@ val databases = Databases(client) val response = databases.createDocuments( databaseId = "", collectionId = "", - documents = listOf() + documents = listOf(), + transactionId = "" // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/databases/create-operations.md b/docs/examples/1.8.x/server-kotlin/kotlin/databases/create-operations.md new file mode 100644 index 0000000000..1c741818b9 --- /dev/null +++ b/docs/examples/1.8.x/server-kotlin/kotlin/databases/create-operations.md @@ -0,0 +1,25 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.Databases + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +val databases = Databases(client) + +val response = databases.createOperations( + transactionId = "", + operations = listOf( + { + "action": "create", + "databaseId": "", + "collectionId": "", + "documentId": "", + "data": { + "name": "Walter O'Brien" + } + } + ) // optional +) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/databases/create-transaction.md b/docs/examples/1.8.x/server-kotlin/kotlin/databases/create-transaction.md new file mode 100644 index 0000000000..83ff583038 --- /dev/null +++ b/docs/examples/1.8.x/server-kotlin/kotlin/databases/create-transaction.md @@ -0,0 +1,14 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.Databases + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +val databases = Databases(client) + +val response = databases.createTransaction( + ttl = 60 // optional +) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/databases/decrement-document-attribute.md b/docs/examples/1.8.x/server-kotlin/kotlin/databases/decrement-document-attribute.md index d0226c0bdb..3ccd662d59 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/databases/decrement-document-attribute.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/databases/decrement-document-attribute.md @@ -15,5 +15,6 @@ val response = databases.decrementDocumentAttribute( documentId = "", attribute = "", value = 0, // optional - min = 0 // optional + min = 0, // optional + transactionId = "" // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/databases/delete-document.md b/docs/examples/1.8.x/server-kotlin/kotlin/databases/delete-document.md index a9eea6b648..3be4372987 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/databases/delete-document.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/databases/delete-document.md @@ -12,5 +12,6 @@ val databases = Databases(client) val response = databases.deleteDocument( databaseId = "", collectionId = "", - documentId = "" + documentId = "", + transactionId = "" // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/databases/delete-documents.md b/docs/examples/1.8.x/server-kotlin/kotlin/databases/delete-documents.md index c4caa63aae..9b9ea263c4 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/databases/delete-documents.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/databases/delete-documents.md @@ -12,5 +12,6 @@ val databases = Databases(client) val response = databases.deleteDocuments( databaseId = "", collectionId = "", - queries = listOf() // optional + queries = listOf(), // optional + transactionId = "" // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/databases/delete-transaction.md b/docs/examples/1.8.x/server-kotlin/kotlin/databases/delete-transaction.md new file mode 100644 index 0000000000..ef11e9fad8 --- /dev/null +++ b/docs/examples/1.8.x/server-kotlin/kotlin/databases/delete-transaction.md @@ -0,0 +1,14 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.Databases + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +val databases = Databases(client) + +val response = databases.deleteTransaction( + transactionId = "" +) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/databases/get-document.md b/docs/examples/1.8.x/server-kotlin/kotlin/databases/get-document.md index d21a19869b..98855d0984 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/databases/get-document.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/databases/get-document.md @@ -13,5 +13,6 @@ val response = databases.getDocument( databaseId = "", collectionId = "", documentId = "", - queries = listOf() // optional + queries = listOf(), // optional + transactionId = "" // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/databases/get-transaction.md b/docs/examples/1.8.x/server-kotlin/kotlin/databases/get-transaction.md new file mode 100644 index 0000000000..1e44376ab7 --- /dev/null +++ b/docs/examples/1.8.x/server-kotlin/kotlin/databases/get-transaction.md @@ -0,0 +1,14 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.Databases + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +val databases = Databases(client) + +val response = databases.getTransaction( + transactionId = "" +) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/databases/increment-document-attribute.md b/docs/examples/1.8.x/server-kotlin/kotlin/databases/increment-document-attribute.md index b56ed91d75..fb358868d2 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/databases/increment-document-attribute.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/databases/increment-document-attribute.md @@ -15,5 +15,6 @@ val response = databases.incrementDocumentAttribute( documentId = "", attribute = "", value = 0, // optional - max = 0 // optional + max = 0, // optional + transactionId = "" // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/databases/list-documents.md b/docs/examples/1.8.x/server-kotlin/kotlin/databases/list-documents.md index ed9cb3165d..ab75493964 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/databases/list-documents.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/databases/list-documents.md @@ -12,5 +12,6 @@ val databases = Databases(client) val response = databases.listDocuments( databaseId = "", collectionId = "", - queries = listOf() // optional + queries = listOf(), // optional + transactionId = "" // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/databases/list-transactions.md b/docs/examples/1.8.x/server-kotlin/kotlin/databases/list-transactions.md new file mode 100644 index 0000000000..0d122b108d --- /dev/null +++ b/docs/examples/1.8.x/server-kotlin/kotlin/databases/list-transactions.md @@ -0,0 +1,14 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.Databases + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +val databases = Databases(client) + +val response = databases.listTransactions( + queries = listOf() // optional +) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/databases/update-document.md b/docs/examples/1.8.x/server-kotlin/kotlin/databases/update-document.md index 4dd0349823..c64a705676 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/databases/update-document.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/databases/update-document.md @@ -14,5 +14,6 @@ val response = databases.updateDocument( collectionId = "", documentId = "", data = mapOf( "a" to "b" ), // optional - permissions = listOf("read("any")") // optional + permissions = listOf("read("any")"), // optional + transactionId = "" // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/databases/update-documents.md b/docs/examples/1.8.x/server-kotlin/kotlin/databases/update-documents.md index 9d6c2b5ea8..b5b76fcaee 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/databases/update-documents.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/databases/update-documents.md @@ -13,5 +13,6 @@ val response = databases.updateDocuments( databaseId = "", collectionId = "", data = mapOf( "a" to "b" ), // optional - queries = listOf() // optional + queries = listOf(), // optional + transactionId = "" // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/databases/update-transaction.md b/docs/examples/1.8.x/server-kotlin/kotlin/databases/update-transaction.md new file mode 100644 index 0000000000..834d0dc78d --- /dev/null +++ b/docs/examples/1.8.x/server-kotlin/kotlin/databases/update-transaction.md @@ -0,0 +1,16 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.Databases + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +val databases = Databases(client) + +val response = databases.updateTransaction( + transactionId = "", + commit = false, // optional + rollback = false // optional +) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/databases/upsert-document.md b/docs/examples/1.8.x/server-kotlin/kotlin/databases/upsert-document.md index d8be0e13db..d6d6800864 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/databases/upsert-document.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/databases/upsert-document.md @@ -14,5 +14,6 @@ val response = databases.upsertDocument( collectionId = "", documentId = "", data = mapOf( "a" to "b" ), - permissions = listOf("read("any")") // optional + permissions = listOf("read("any")"), // optional + transactionId = "" // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/databases/upsert-documents.md b/docs/examples/1.8.x/server-kotlin/kotlin/databases/upsert-documents.md index ca861c61b2..db9e2b3e2d 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/databases/upsert-documents.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/databases/upsert-documents.md @@ -12,5 +12,6 @@ val databases = Databases(client) val response = databases.upsertDocuments( databaseId = "", collectionId = "", - documents = listOf() + documents = listOf(), + transactionId = "" // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/messaging/create-push.md b/docs/examples/1.8.x/server-kotlin/kotlin/messaging/create-push.md index 5b07f5355b..d0d765a32a 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/messaging/create-push.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/messaging/create-push.md @@ -18,7 +18,7 @@ val response = messaging.createPush( targets = listOf(), // optional data = mapOf( "a" to "b" ), // optional action = "", // optional - image = "[ID1:ID2]", // optional + image = "", // optional icon = "", // optional sound = "", // optional color = "", // optional diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/messaging/update-push.md b/docs/examples/1.8.x/server-kotlin/kotlin/messaging/update-push.md index 710a37e518..0b9c4c6535 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/messaging/update-push.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/messaging/update-push.md @@ -18,7 +18,7 @@ val response = messaging.updatePush( body = "", // optional data = mapOf( "a" to "b" ), // optional action = "", // optional - image = "[ID1:ID2]", // optional + image = "", // optional icon = "", // optional sound = "", // optional color = "", // optional diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/create-operations.md b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/create-operations.md new file mode 100644 index 0000000000..40c98d1c81 --- /dev/null +++ b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/create-operations.md @@ -0,0 +1,25 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.TablesDB + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +val tablesDB = TablesDB(client) + +val response = tablesDB.createOperations( + transactionId = "", + operations = listOf( + { + "action": "create", + "databaseId": "", + "tableId": "", + "rowId": "", + "data": { + "name": "Walter O'Brien" + } + } + ) // optional +) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/create-row.md b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/create-row.md index 774800d8f4..b06038964b 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/create-row.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/create-row.md @@ -20,5 +20,6 @@ val response = tablesDB.createRow( "age" to 30, "isAdmin" to false ), - permissions = listOf("read("any")") // optional + permissions = listOf("read("any")"), // optional + transactionId = "" // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/create-rows.md b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/create-rows.md index 1da47b5c18..8cef6028a2 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/create-rows.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/create-rows.md @@ -12,5 +12,6 @@ val tablesDB = TablesDB(client) val response = tablesDB.createRows( databaseId = "", tableId = "", - rows = listOf() + rows = listOf(), + transactionId = "" // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/create-transaction.md b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/create-transaction.md new file mode 100644 index 0000000000..31385700c5 --- /dev/null +++ b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/create-transaction.md @@ -0,0 +1,14 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.TablesDB + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +val tablesDB = TablesDB(client) + +val response = tablesDB.createTransaction( + ttl = 60 // optional +) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/decrement-row-column.md b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/decrement-row-column.md index e284ec3980..30a8d54b1a 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/decrement-row-column.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/decrement-row-column.md @@ -15,5 +15,6 @@ val response = tablesDB.decrementRowColumn( rowId = "", column = "", value = 0, // optional - min = 0 // optional + min = 0, // optional + transactionId = "" // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/delete-row.md b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/delete-row.md index f24b9353e0..6ba7d6057c 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/delete-row.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/delete-row.md @@ -12,5 +12,6 @@ val tablesDB = TablesDB(client) val response = tablesDB.deleteRow( databaseId = "", tableId = "", - rowId = "" + rowId = "", + transactionId = "" // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/delete-rows.md b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/delete-rows.md index c915a5c55a..da2b709f8a 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/delete-rows.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/delete-rows.md @@ -12,5 +12,6 @@ val tablesDB = TablesDB(client) val response = tablesDB.deleteRows( databaseId = "", tableId = "", - queries = listOf() // optional + queries = listOf(), // optional + transactionId = "" // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/delete-transaction.md b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/delete-transaction.md new file mode 100644 index 0000000000..2ef1f27a25 --- /dev/null +++ b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/delete-transaction.md @@ -0,0 +1,14 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.TablesDB + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +val tablesDB = TablesDB(client) + +val response = tablesDB.deleteTransaction( + transactionId = "" +) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/get-row.md b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/get-row.md index ec54631646..f92a1ccf27 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/get-row.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/get-row.md @@ -13,5 +13,6 @@ val response = tablesDB.getRow( databaseId = "", tableId = "", rowId = "", - queries = listOf() // optional + queries = listOf(), // optional + transactionId = "" // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/get-transaction.md b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/get-transaction.md new file mode 100644 index 0000000000..f4467dc914 --- /dev/null +++ b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/get-transaction.md @@ -0,0 +1,14 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.TablesDB + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +val tablesDB = TablesDB(client) + +val response = tablesDB.getTransaction( + transactionId = "" +) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/increment-row-column.md b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/increment-row-column.md index cac151e41b..af3676e75b 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/increment-row-column.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/increment-row-column.md @@ -15,5 +15,6 @@ val response = tablesDB.incrementRowColumn( rowId = "", column = "", value = 0, // optional - max = 0 // optional + max = 0, // optional + transactionId = "" // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/list-rows.md b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/list-rows.md index b0f5df476b..711e4e1a31 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/list-rows.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/list-rows.md @@ -12,5 +12,6 @@ val tablesDB = TablesDB(client) val response = tablesDB.listRows( databaseId = "", tableId = "", - queries = listOf() // optional + queries = listOf(), // optional + transactionId = "" // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/list-transactions.md b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/list-transactions.md new file mode 100644 index 0000000000..a060b9fac3 --- /dev/null +++ b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/list-transactions.md @@ -0,0 +1,14 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.TablesDB + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +val tablesDB = TablesDB(client) + +val response = tablesDB.listTransactions( + queries = listOf() // optional +) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/update-row.md b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/update-row.md index 9c5248f4e8..0fefb78e5f 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/update-row.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/update-row.md @@ -14,5 +14,6 @@ val response = tablesDB.updateRow( tableId = "", rowId = "", data = mapOf( "a" to "b" ), // optional - permissions = listOf("read("any")") // optional + permissions = listOf("read("any")"), // optional + transactionId = "" // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/update-rows.md b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/update-rows.md index c285d5b4fb..61041a7783 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/update-rows.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/update-rows.md @@ -13,5 +13,6 @@ val response = tablesDB.updateRows( databaseId = "", tableId = "", data = mapOf( "a" to "b" ), // optional - queries = listOf() // optional + queries = listOf(), // optional + transactionId = "" // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/update-transaction.md b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/update-transaction.md new file mode 100644 index 0000000000..a3797ca5ca --- /dev/null +++ b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/update-transaction.md @@ -0,0 +1,16 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.TablesDB + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +val tablesDB = TablesDB(client) + +val response = tablesDB.updateTransaction( + transactionId = "", + commit = false, // optional + rollback = false // optional +) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/upsert-row.md b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/upsert-row.md index 3fcbc61617..5bcc73b4b1 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/upsert-row.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/upsert-row.md @@ -14,5 +14,6 @@ val response = tablesDB.upsertRow( tableId = "", rowId = "", data = mapOf( "a" to "b" ), // optional - permissions = listOf("read("any")") // optional + permissions = listOf("read("any")"), // optional + transactionId = "" // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/upsert-rows.md b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/upsert-rows.md index 7059c6018b..2f08375c4a 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/upsert-rows.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/upsert-rows.md @@ -12,5 +12,6 @@ val tablesDB = TablesDB(client) val response = tablesDB.upsertRows( databaseId = "", tableId = "", - rows = listOf() + rows = listOf(), + transactionId = "" // optional ) diff --git a/docs/examples/1.8.x/server-nodejs/examples/databases/create-document.md b/docs/examples/1.8.x/server-nodejs/examples/databases/create-document.md index 175e06301e..6fe77c42be 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/databases/create-document.md +++ b/docs/examples/1.8.x/server-nodejs/examples/databases/create-document.md @@ -18,5 +18,6 @@ const result = await databases.createDocument({ "age": 30, "isAdmin": false }, - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/databases/create-documents.md b/docs/examples/1.8.x/server-nodejs/examples/databases/create-documents.md index 73d08aa21e..8815d8d90f 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/databases/create-documents.md +++ b/docs/examples/1.8.x/server-nodejs/examples/databases/create-documents.md @@ -10,5 +10,6 @@ const databases = new sdk.Databases(client); const result = await databases.createDocuments({ databaseId: '', collectionId: '', - documents: [] + documents: [], + transactionId: '' // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/databases/create-operations.md b/docs/examples/1.8.x/server-nodejs/examples/databases/create-operations.md new file mode 100644 index 0000000000..da8452e3db --- /dev/null +++ b/docs/examples/1.8.x/server-nodejs/examples/databases/create-operations.md @@ -0,0 +1,23 @@ +const sdk = require('node-appwrite'); + +const client = new sdk.Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your secret API key + +const databases = new sdk.Databases(client); + +const result = await databases.createOperations({ + transactionId: '', + operations: [ + { + "action": "create", + "databaseId": "", + "collectionId": "", + "documentId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] // optional +}); diff --git a/docs/examples/1.8.x/server-nodejs/examples/databases/create-transaction.md b/docs/examples/1.8.x/server-nodejs/examples/databases/create-transaction.md new file mode 100644 index 0000000000..f3da2919f8 --- /dev/null +++ b/docs/examples/1.8.x/server-nodejs/examples/databases/create-transaction.md @@ -0,0 +1,12 @@ +const sdk = require('node-appwrite'); + +const client = new sdk.Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your secret API key + +const databases = new sdk.Databases(client); + +const result = await databases.createTransaction({ + ttl: 60 // optional +}); diff --git a/docs/examples/1.8.x/server-nodejs/examples/databases/decrement-document-attribute.md b/docs/examples/1.8.x/server-nodejs/examples/databases/decrement-document-attribute.md index 87e4d7d25c..c01b250b08 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/databases/decrement-document-attribute.md +++ b/docs/examples/1.8.x/server-nodejs/examples/databases/decrement-document-attribute.md @@ -13,5 +13,6 @@ const result = await databases.decrementDocumentAttribute({ documentId: '', attribute: '', value: null, // optional - min: null // optional + min: null, // optional + transactionId: '' // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/databases/delete-document.md b/docs/examples/1.8.x/server-nodejs/examples/databases/delete-document.md index 429554b74b..bfc19777f9 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/databases/delete-document.md +++ b/docs/examples/1.8.x/server-nodejs/examples/databases/delete-document.md @@ -10,5 +10,6 @@ const databases = new sdk.Databases(client); const result = await databases.deleteDocument({ databaseId: '', collectionId: '', - documentId: '' + documentId: '', + transactionId: '' // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/databases/delete-documents.md b/docs/examples/1.8.x/server-nodejs/examples/databases/delete-documents.md index 0965d8ddaf..9440d20999 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/databases/delete-documents.md +++ b/docs/examples/1.8.x/server-nodejs/examples/databases/delete-documents.md @@ -10,5 +10,6 @@ const databases = new sdk.Databases(client); const result = await databases.deleteDocuments({ databaseId: '', collectionId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/databases/delete-transaction.md b/docs/examples/1.8.x/server-nodejs/examples/databases/delete-transaction.md new file mode 100644 index 0000000000..53d676e74c --- /dev/null +++ b/docs/examples/1.8.x/server-nodejs/examples/databases/delete-transaction.md @@ -0,0 +1,12 @@ +const sdk = require('node-appwrite'); + +const client = new sdk.Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your secret API key + +const databases = new sdk.Databases(client); + +const result = await databases.deleteTransaction({ + transactionId: '' +}); diff --git a/docs/examples/1.8.x/server-nodejs/examples/databases/get-document.md b/docs/examples/1.8.x/server-nodejs/examples/databases/get-document.md index 7cc71cd0c3..7abea4e44e 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/databases/get-document.md +++ b/docs/examples/1.8.x/server-nodejs/examples/databases/get-document.md @@ -11,5 +11,6 @@ const result = await databases.getDocument({ databaseId: '', collectionId: '', documentId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/databases/get-transaction.md b/docs/examples/1.8.x/server-nodejs/examples/databases/get-transaction.md new file mode 100644 index 0000000000..9b7297c7e7 --- /dev/null +++ b/docs/examples/1.8.x/server-nodejs/examples/databases/get-transaction.md @@ -0,0 +1,12 @@ +const sdk = require('node-appwrite'); + +const client = new sdk.Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your secret API key + +const databases = new sdk.Databases(client); + +const result = await databases.getTransaction({ + transactionId: '' +}); diff --git a/docs/examples/1.8.x/server-nodejs/examples/databases/increment-document-attribute.md b/docs/examples/1.8.x/server-nodejs/examples/databases/increment-document-attribute.md index 2b47f5a75d..843d163bca 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/databases/increment-document-attribute.md +++ b/docs/examples/1.8.x/server-nodejs/examples/databases/increment-document-attribute.md @@ -13,5 +13,6 @@ const result = await databases.incrementDocumentAttribute({ documentId: '', attribute: '', value: null, // optional - max: null // optional + max: null, // optional + transactionId: '' // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/databases/list-documents.md b/docs/examples/1.8.x/server-nodejs/examples/databases/list-documents.md index 148bf83c8f..7405f3e28d 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/databases/list-documents.md +++ b/docs/examples/1.8.x/server-nodejs/examples/databases/list-documents.md @@ -10,5 +10,6 @@ const databases = new sdk.Databases(client); const result = await databases.listDocuments({ databaseId: '', collectionId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/databases/list-transactions.md b/docs/examples/1.8.x/server-nodejs/examples/databases/list-transactions.md new file mode 100644 index 0000000000..9a36eb0f93 --- /dev/null +++ b/docs/examples/1.8.x/server-nodejs/examples/databases/list-transactions.md @@ -0,0 +1,12 @@ +const sdk = require('node-appwrite'); + +const client = new sdk.Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your secret API key + +const databases = new sdk.Databases(client); + +const result = await databases.listTransactions({ + queries: [] // optional +}); diff --git a/docs/examples/1.8.x/server-nodejs/examples/databases/update-document.md b/docs/examples/1.8.x/server-nodejs/examples/databases/update-document.md index 8a9a6856b4..3e953760a1 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/databases/update-document.md +++ b/docs/examples/1.8.x/server-nodejs/examples/databases/update-document.md @@ -12,5 +12,6 @@ const result = await databases.updateDocument({ collectionId: '', documentId: '', data: {}, // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/databases/update-documents.md b/docs/examples/1.8.x/server-nodejs/examples/databases/update-documents.md index 2cfb8c7800..dc79e433aa 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/databases/update-documents.md +++ b/docs/examples/1.8.x/server-nodejs/examples/databases/update-documents.md @@ -11,5 +11,6 @@ const result = await databases.updateDocuments({ databaseId: '', collectionId: '', data: {}, // optional - queries: [] // optional + queries: [], // optional + transactionId: '' // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/databases/update-transaction.md b/docs/examples/1.8.x/server-nodejs/examples/databases/update-transaction.md new file mode 100644 index 0000000000..57654495ba --- /dev/null +++ b/docs/examples/1.8.x/server-nodejs/examples/databases/update-transaction.md @@ -0,0 +1,14 @@ +const sdk = require('node-appwrite'); + +const client = new sdk.Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your secret API key + +const databases = new sdk.Databases(client); + +const result = await databases.updateTransaction({ + transactionId: '', + commit: false, // optional + rollback: false // optional +}); diff --git a/docs/examples/1.8.x/server-nodejs/examples/databases/upsert-document.md b/docs/examples/1.8.x/server-nodejs/examples/databases/upsert-document.md index 5ec3e0541e..0aaec4e6cb 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/databases/upsert-document.md +++ b/docs/examples/1.8.x/server-nodejs/examples/databases/upsert-document.md @@ -12,5 +12,6 @@ const result = await databases.upsertDocument({ collectionId: '', documentId: '', data: {}, - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/databases/upsert-documents.md b/docs/examples/1.8.x/server-nodejs/examples/databases/upsert-documents.md index 8deec536ff..16ed70fae9 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/databases/upsert-documents.md +++ b/docs/examples/1.8.x/server-nodejs/examples/databases/upsert-documents.md @@ -10,5 +10,6 @@ const databases = new sdk.Databases(client); const result = await databases.upsertDocuments({ databaseId: '', collectionId: '', - documents: [] + documents: [], + transactionId: '' // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/messaging/create-push.md b/docs/examples/1.8.x/server-nodejs/examples/messaging/create-push.md index c0a7f4713f..4c64813f25 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/messaging/create-push.md +++ b/docs/examples/1.8.x/server-nodejs/examples/messaging/create-push.md @@ -16,7 +16,7 @@ const result = await messaging.createPush({ targets: [], // optional data: {}, // optional action: '', // optional - image: '[ID1:ID2]', // optional + image: '', // optional icon: '', // optional sound: '', // optional color: '', // optional diff --git a/docs/examples/1.8.x/server-nodejs/examples/messaging/update-push.md b/docs/examples/1.8.x/server-nodejs/examples/messaging/update-push.md index 5e857f1ff6..6f5899f8c7 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/messaging/update-push.md +++ b/docs/examples/1.8.x/server-nodejs/examples/messaging/update-push.md @@ -16,7 +16,7 @@ const result = await messaging.updatePush({ body: '', // optional data: {}, // optional action: '', // optional - image: '[ID1:ID2]', // optional + image: '', // optional icon: '', // optional sound: '', // optional color: '', // optional diff --git a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/create-operations.md b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/create-operations.md new file mode 100644 index 0000000000..25492396dd --- /dev/null +++ b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/create-operations.md @@ -0,0 +1,23 @@ +const sdk = require('node-appwrite'); + +const client = new sdk.Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your secret API key + +const tablesDB = new sdk.TablesDB(client); + +const result = await tablesDB.createOperations({ + transactionId: '', + operations: [ + { + "action": "create", + "databaseId": "", + "tableId": "", + "rowId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] // optional +}); diff --git a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/create-row.md b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/create-row.md index 29ddab6652..4468c168e8 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/create-row.md +++ b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/create-row.md @@ -18,5 +18,6 @@ const result = await tablesDB.createRow({ "age": 30, "isAdmin": false }, - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/create-rows.md b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/create-rows.md index 61eb1d1db8..20807c1612 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/create-rows.md +++ b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/create-rows.md @@ -10,5 +10,6 @@ const tablesDB = new sdk.TablesDB(client); const result = await tablesDB.createRows({ databaseId: '', tableId: '', - rows: [] + rows: [], + transactionId: '' // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/create-transaction.md b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/create-transaction.md new file mode 100644 index 0000000000..249406e333 --- /dev/null +++ b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/create-transaction.md @@ -0,0 +1,12 @@ +const sdk = require('node-appwrite'); + +const client = new sdk.Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your secret API key + +const tablesDB = new sdk.TablesDB(client); + +const result = await tablesDB.createTransaction({ + ttl: 60 // optional +}); diff --git a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/decrement-row-column.md b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/decrement-row-column.md index e3b13a887e..0310399239 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/decrement-row-column.md +++ b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/decrement-row-column.md @@ -13,5 +13,6 @@ const result = await tablesDB.decrementRowColumn({ rowId: '', column: '', value: null, // optional - min: null // optional + min: null, // optional + transactionId: '' // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/delete-row.md b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/delete-row.md index 9802f0d03e..68a965dc97 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/delete-row.md +++ b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/delete-row.md @@ -10,5 +10,6 @@ const tablesDB = new sdk.TablesDB(client); const result = await tablesDB.deleteRow({ databaseId: '', tableId: '', - rowId: '' + rowId: '', + transactionId: '' // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/delete-rows.md b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/delete-rows.md index 6f4d7cd68b..ce1d0f4ba1 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/delete-rows.md +++ b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/delete-rows.md @@ -10,5 +10,6 @@ const tablesDB = new sdk.TablesDB(client); const result = await tablesDB.deleteRows({ databaseId: '', tableId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/delete-transaction.md b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/delete-transaction.md new file mode 100644 index 0000000000..28d086b9cf --- /dev/null +++ b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/delete-transaction.md @@ -0,0 +1,12 @@ +const sdk = require('node-appwrite'); + +const client = new sdk.Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your secret API key + +const tablesDB = new sdk.TablesDB(client); + +const result = await tablesDB.deleteTransaction({ + transactionId: '' +}); diff --git a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/get-row.md b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/get-row.md index 7ea3d1fca2..fe67e2fda3 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/get-row.md +++ b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/get-row.md @@ -11,5 +11,6 @@ const result = await tablesDB.getRow({ databaseId: '', tableId: '', rowId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/get-transaction.md b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/get-transaction.md new file mode 100644 index 0000000000..208368bc00 --- /dev/null +++ b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/get-transaction.md @@ -0,0 +1,12 @@ +const sdk = require('node-appwrite'); + +const client = new sdk.Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your secret API key + +const tablesDB = new sdk.TablesDB(client); + +const result = await tablesDB.getTransaction({ + transactionId: '' +}); diff --git a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/increment-row-column.md b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/increment-row-column.md index f5cac2ebaa..aaa6cd6205 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/increment-row-column.md +++ b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/increment-row-column.md @@ -13,5 +13,6 @@ const result = await tablesDB.incrementRowColumn({ rowId: '', column: '', value: null, // optional - max: null // optional + max: null, // optional + transactionId: '' // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/list-rows.md b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/list-rows.md index 6d3b883bd4..3f29781a91 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/list-rows.md +++ b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/list-rows.md @@ -10,5 +10,6 @@ const tablesDB = new sdk.TablesDB(client); const result = await tablesDB.listRows({ databaseId: '', tableId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/list-transactions.md b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/list-transactions.md new file mode 100644 index 0000000000..3ad0c95425 --- /dev/null +++ b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/list-transactions.md @@ -0,0 +1,12 @@ +const sdk = require('node-appwrite'); + +const client = new sdk.Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your secret API key + +const tablesDB = new sdk.TablesDB(client); + +const result = await tablesDB.listTransactions({ + queries: [] // optional +}); diff --git a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/update-row.md b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/update-row.md index 1c7f0af197..58583af745 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/update-row.md +++ b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/update-row.md @@ -12,5 +12,6 @@ const result = await tablesDB.updateRow({ tableId: '', rowId: '', data: {}, // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/update-rows.md b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/update-rows.md index 31628d7150..d66fc28a62 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/update-rows.md +++ b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/update-rows.md @@ -11,5 +11,6 @@ const result = await tablesDB.updateRows({ databaseId: '', tableId: '', data: {}, // optional - queries: [] // optional + queries: [], // optional + transactionId: '' // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/update-transaction.md b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/update-transaction.md new file mode 100644 index 0000000000..03501d2cbf --- /dev/null +++ b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/update-transaction.md @@ -0,0 +1,14 @@ +const sdk = require('node-appwrite'); + +const client = new sdk.Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your secret API key + +const tablesDB = new sdk.TablesDB(client); + +const result = await tablesDB.updateTransaction({ + transactionId: '', + commit: false, // optional + rollback: false // optional +}); diff --git a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/upsert-row.md b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/upsert-row.md index 9963bb6ced..bfb833356a 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/upsert-row.md +++ b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/upsert-row.md @@ -12,5 +12,6 @@ const result = await tablesDB.upsertRow({ tableId: '', rowId: '', data: {}, // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/upsert-rows.md b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/upsert-rows.md index cca2b777bb..c985c9515b 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/tablesdb/upsert-rows.md +++ b/docs/examples/1.8.x/server-nodejs/examples/tablesdb/upsert-rows.md @@ -10,5 +10,6 @@ const tablesDB = new sdk.TablesDB(client); const result = await tablesDB.upsertRows({ databaseId: '', tableId: '', - rows: [] + rows: [], + transactionId: '' // optional }); diff --git a/docs/examples/1.8.x/server-php/examples/databases/create-document.md b/docs/examples/1.8.x/server-php/examples/databases/create-document.md index 9f2e8f3643..19d3cfb566 100644 --- a/docs/examples/1.8.x/server-php/examples/databases/create-document.md +++ b/docs/examples/1.8.x/server-php/examples/databases/create-document.md @@ -21,5 +21,6 @@ $result = $databases->createDocument( 'age' => 30, 'isAdmin' => false ], - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/databases/create-documents.md b/docs/examples/1.8.x/server-php/examples/databases/create-documents.md index bc05f67260..ced7a5a83f 100644 --- a/docs/examples/1.8.x/server-php/examples/databases/create-documents.md +++ b/docs/examples/1.8.x/server-php/examples/databases/create-documents.md @@ -13,5 +13,6 @@ $databases = new Databases($client); $result = $databases->createDocuments( databaseId: '', collectionId: '', - documents: [] + documents: [], + transactionId: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/databases/create-operations.md b/docs/examples/1.8.x/server-php/examples/databases/create-operations.md new file mode 100644 index 0000000000..05038cb6f6 --- /dev/null +++ b/docs/examples/1.8.x/server-php/examples/databases/create-operations.md @@ -0,0 +1,26 @@ +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your secret API key + +$databases = new Databases($client); + +$result = $databases->createOperations( + transactionId: '', + operations: [ + { + "action": "create", + "databaseId": "", + "collectionId": "", + "documentId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] // optional +); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/databases/create-transaction.md b/docs/examples/1.8.x/server-php/examples/databases/create-transaction.md new file mode 100644 index 0000000000..ea6faf73b1 --- /dev/null +++ b/docs/examples/1.8.x/server-php/examples/databases/create-transaction.md @@ -0,0 +1,15 @@ +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your secret API key + +$databases = new Databases($client); + +$result = $databases->createTransaction( + ttl: 60 // optional +); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/databases/decrement-document-attribute.md b/docs/examples/1.8.x/server-php/examples/databases/decrement-document-attribute.md index 6464a26818..dfb1873cdd 100644 --- a/docs/examples/1.8.x/server-php/examples/databases/decrement-document-attribute.md +++ b/docs/examples/1.8.x/server-php/examples/databases/decrement-document-attribute.md @@ -16,5 +16,6 @@ $result = $databases->decrementDocumentAttribute( documentId: '', attribute: '', value: null, // optional - min: null // optional + min: null, // optional + transactionId: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/databases/delete-document.md b/docs/examples/1.8.x/server-php/examples/databases/delete-document.md index def7f24569..6e4d7aa2a6 100644 --- a/docs/examples/1.8.x/server-php/examples/databases/delete-document.md +++ b/docs/examples/1.8.x/server-php/examples/databases/delete-document.md @@ -13,5 +13,6 @@ $databases = new Databases($client); $result = $databases->deleteDocument( databaseId: '', collectionId: '', - documentId: '' + documentId: '', + transactionId: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/databases/delete-documents.md b/docs/examples/1.8.x/server-php/examples/databases/delete-documents.md index 3552d85317..3b2b0c79c5 100644 --- a/docs/examples/1.8.x/server-php/examples/databases/delete-documents.md +++ b/docs/examples/1.8.x/server-php/examples/databases/delete-documents.md @@ -13,5 +13,6 @@ $databases = new Databases($client); $result = $databases->deleteDocuments( databaseId: '', collectionId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/databases/delete-transaction.md b/docs/examples/1.8.x/server-php/examples/databases/delete-transaction.md new file mode 100644 index 0000000000..0559aace08 --- /dev/null +++ b/docs/examples/1.8.x/server-php/examples/databases/delete-transaction.md @@ -0,0 +1,15 @@ +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your secret API key + +$databases = new Databases($client); + +$result = $databases->deleteTransaction( + transactionId: '' +); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/databases/get-document.md b/docs/examples/1.8.x/server-php/examples/databases/get-document.md index a3204c50a7..834602d89f 100644 --- a/docs/examples/1.8.x/server-php/examples/databases/get-document.md +++ b/docs/examples/1.8.x/server-php/examples/databases/get-document.md @@ -14,5 +14,6 @@ $result = $databases->getDocument( databaseId: '', collectionId: '', documentId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/databases/get-transaction.md b/docs/examples/1.8.x/server-php/examples/databases/get-transaction.md new file mode 100644 index 0000000000..16ca28da1a --- /dev/null +++ b/docs/examples/1.8.x/server-php/examples/databases/get-transaction.md @@ -0,0 +1,15 @@ +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your secret API key + +$databases = new Databases($client); + +$result = $databases->getTransaction( + transactionId: '' +); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/databases/increment-document-attribute.md b/docs/examples/1.8.x/server-php/examples/databases/increment-document-attribute.md index 9ad4bdfdec..63162d3224 100644 --- a/docs/examples/1.8.x/server-php/examples/databases/increment-document-attribute.md +++ b/docs/examples/1.8.x/server-php/examples/databases/increment-document-attribute.md @@ -16,5 +16,6 @@ $result = $databases->incrementDocumentAttribute( documentId: '', attribute: '', value: null, // optional - max: null // optional + max: null, // optional + transactionId: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/databases/list-documents.md b/docs/examples/1.8.x/server-php/examples/databases/list-documents.md index 07183ac8bf..10dcc82340 100644 --- a/docs/examples/1.8.x/server-php/examples/databases/list-documents.md +++ b/docs/examples/1.8.x/server-php/examples/databases/list-documents.md @@ -13,5 +13,6 @@ $databases = new Databases($client); $result = $databases->listDocuments( databaseId: '', collectionId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/databases/list-transactions.md b/docs/examples/1.8.x/server-php/examples/databases/list-transactions.md new file mode 100644 index 0000000000..858e905ba5 --- /dev/null +++ b/docs/examples/1.8.x/server-php/examples/databases/list-transactions.md @@ -0,0 +1,15 @@ +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your secret API key + +$databases = new Databases($client); + +$result = $databases->listTransactions( + queries: [] // optional +); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/databases/update-document.md b/docs/examples/1.8.x/server-php/examples/databases/update-document.md index f1c8a34680..d903252886 100644 --- a/docs/examples/1.8.x/server-php/examples/databases/update-document.md +++ b/docs/examples/1.8.x/server-php/examples/databases/update-document.md @@ -15,5 +15,6 @@ $result = $databases->updateDocument( collectionId: '', documentId: '', data: [], // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/databases/update-documents.md b/docs/examples/1.8.x/server-php/examples/databases/update-documents.md index 51b4e18bc2..72632461a9 100644 --- a/docs/examples/1.8.x/server-php/examples/databases/update-documents.md +++ b/docs/examples/1.8.x/server-php/examples/databases/update-documents.md @@ -14,5 +14,6 @@ $result = $databases->updateDocuments( databaseId: '', collectionId: '', data: [], // optional - queries: [] // optional + queries: [], // optional + transactionId: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/databases/update-transaction.md b/docs/examples/1.8.x/server-php/examples/databases/update-transaction.md new file mode 100644 index 0000000000..750eb861f9 --- /dev/null +++ b/docs/examples/1.8.x/server-php/examples/databases/update-transaction.md @@ -0,0 +1,17 @@ +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your secret API key + +$databases = new Databases($client); + +$result = $databases->updateTransaction( + transactionId: '', + commit: false, // optional + rollback: false // optional +); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/databases/upsert-document.md b/docs/examples/1.8.x/server-php/examples/databases/upsert-document.md index 6cff8296a3..6db7462ac7 100644 --- a/docs/examples/1.8.x/server-php/examples/databases/upsert-document.md +++ b/docs/examples/1.8.x/server-php/examples/databases/upsert-document.md @@ -15,5 +15,6 @@ $result = $databases->upsertDocument( collectionId: '', documentId: '', data: [], - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/databases/upsert-documents.md b/docs/examples/1.8.x/server-php/examples/databases/upsert-documents.md index d9f9efda5c..06d3a319af 100644 --- a/docs/examples/1.8.x/server-php/examples/databases/upsert-documents.md +++ b/docs/examples/1.8.x/server-php/examples/databases/upsert-documents.md @@ -13,5 +13,6 @@ $databases = new Databases($client); $result = $databases->upsertDocuments( databaseId: '', collectionId: '', - documents: [] + documents: [], + transactionId: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/messaging/create-push.md b/docs/examples/1.8.x/server-php/examples/messaging/create-push.md index 46aeeb3b8b..51fc0d0a92 100644 --- a/docs/examples/1.8.x/server-php/examples/messaging/create-push.md +++ b/docs/examples/1.8.x/server-php/examples/messaging/create-push.md @@ -19,7 +19,7 @@ $result = $messaging->createPush( targets: [], // optional data: [], // optional action: '', // optional - image: '[ID1:ID2]', // optional + image: '', // optional icon: '', // optional sound: '', // optional color: '', // optional diff --git a/docs/examples/1.8.x/server-php/examples/messaging/update-push.md b/docs/examples/1.8.x/server-php/examples/messaging/update-push.md index e1df0b9132..05a51783c9 100644 --- a/docs/examples/1.8.x/server-php/examples/messaging/update-push.md +++ b/docs/examples/1.8.x/server-php/examples/messaging/update-push.md @@ -19,7 +19,7 @@ $result = $messaging->updatePush( body: '', // optional data: [], // optional action: '', // optional - image: '[ID1:ID2]', // optional + image: '', // optional icon: '', // optional sound: '', // optional color: '', // optional diff --git a/docs/examples/1.8.x/server-php/examples/tablesdb/create-operations.md b/docs/examples/1.8.x/server-php/examples/tablesdb/create-operations.md new file mode 100644 index 0000000000..429a0bb546 --- /dev/null +++ b/docs/examples/1.8.x/server-php/examples/tablesdb/create-operations.md @@ -0,0 +1,26 @@ +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your secret API key + +$tablesDB = new TablesDB($client); + +$result = $tablesDB->createOperations( + transactionId: '', + operations: [ + { + "action": "create", + "databaseId": "", + "tableId": "", + "rowId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] // optional +); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/tablesdb/create-row.md b/docs/examples/1.8.x/server-php/examples/tablesdb/create-row.md index fa5137b99e..873ecaf448 100644 --- a/docs/examples/1.8.x/server-php/examples/tablesdb/create-row.md +++ b/docs/examples/1.8.x/server-php/examples/tablesdb/create-row.md @@ -21,5 +21,6 @@ $result = $tablesDB->createRow( 'age' => 30, 'isAdmin' => false ], - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/tablesdb/create-rows.md b/docs/examples/1.8.x/server-php/examples/tablesdb/create-rows.md index 011443859f..44c9c7d140 100644 --- a/docs/examples/1.8.x/server-php/examples/tablesdb/create-rows.md +++ b/docs/examples/1.8.x/server-php/examples/tablesdb/create-rows.md @@ -13,5 +13,6 @@ $tablesDB = new TablesDB($client); $result = $tablesDB->createRows( databaseId: '', tableId: '', - rows: [] + rows: [], + transactionId: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/tablesdb/create-transaction.md b/docs/examples/1.8.x/server-php/examples/tablesdb/create-transaction.md new file mode 100644 index 0000000000..32488185b1 --- /dev/null +++ b/docs/examples/1.8.x/server-php/examples/tablesdb/create-transaction.md @@ -0,0 +1,15 @@ +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your secret API key + +$tablesDB = new TablesDB($client); + +$result = $tablesDB->createTransaction( + ttl: 60 // optional +); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/tablesdb/decrement-row-column.md b/docs/examples/1.8.x/server-php/examples/tablesdb/decrement-row-column.md index a58bd71071..ede258e8bd 100644 --- a/docs/examples/1.8.x/server-php/examples/tablesdb/decrement-row-column.md +++ b/docs/examples/1.8.x/server-php/examples/tablesdb/decrement-row-column.md @@ -16,5 +16,6 @@ $result = $tablesDB->decrementRowColumn( rowId: '', column: '', value: null, // optional - min: null // optional + min: null, // optional + transactionId: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/tablesdb/delete-row.md b/docs/examples/1.8.x/server-php/examples/tablesdb/delete-row.md index 4ffc112d66..df87c5077b 100644 --- a/docs/examples/1.8.x/server-php/examples/tablesdb/delete-row.md +++ b/docs/examples/1.8.x/server-php/examples/tablesdb/delete-row.md @@ -13,5 +13,6 @@ $tablesDB = new TablesDB($client); $result = $tablesDB->deleteRow( databaseId: '', tableId: '', - rowId: '' + rowId: '', + transactionId: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/tablesdb/delete-rows.md b/docs/examples/1.8.x/server-php/examples/tablesdb/delete-rows.md index 10a3c87ff2..79ed607c47 100644 --- a/docs/examples/1.8.x/server-php/examples/tablesdb/delete-rows.md +++ b/docs/examples/1.8.x/server-php/examples/tablesdb/delete-rows.md @@ -13,5 +13,6 @@ $tablesDB = new TablesDB($client); $result = $tablesDB->deleteRows( databaseId: '', tableId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/tablesdb/delete-transaction.md b/docs/examples/1.8.x/server-php/examples/tablesdb/delete-transaction.md new file mode 100644 index 0000000000..d1650158c9 --- /dev/null +++ b/docs/examples/1.8.x/server-php/examples/tablesdb/delete-transaction.md @@ -0,0 +1,15 @@ +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your secret API key + +$tablesDB = new TablesDB($client); + +$result = $tablesDB->deleteTransaction( + transactionId: '' +); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/tablesdb/get-row.md b/docs/examples/1.8.x/server-php/examples/tablesdb/get-row.md index 00ba9b65b5..4bbea5594d 100644 --- a/docs/examples/1.8.x/server-php/examples/tablesdb/get-row.md +++ b/docs/examples/1.8.x/server-php/examples/tablesdb/get-row.md @@ -14,5 +14,6 @@ $result = $tablesDB->getRow( databaseId: '', tableId: '', rowId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/tablesdb/get-transaction.md b/docs/examples/1.8.x/server-php/examples/tablesdb/get-transaction.md new file mode 100644 index 0000000000..146e7d191b --- /dev/null +++ b/docs/examples/1.8.x/server-php/examples/tablesdb/get-transaction.md @@ -0,0 +1,15 @@ +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your secret API key + +$tablesDB = new TablesDB($client); + +$result = $tablesDB->getTransaction( + transactionId: '' +); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/tablesdb/increment-row-column.md b/docs/examples/1.8.x/server-php/examples/tablesdb/increment-row-column.md index d72a1e374f..66bf2e8489 100644 --- a/docs/examples/1.8.x/server-php/examples/tablesdb/increment-row-column.md +++ b/docs/examples/1.8.x/server-php/examples/tablesdb/increment-row-column.md @@ -16,5 +16,6 @@ $result = $tablesDB->incrementRowColumn( rowId: '', column: '', value: null, // optional - max: null // optional + max: null, // optional + transactionId: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/tablesdb/list-rows.md b/docs/examples/1.8.x/server-php/examples/tablesdb/list-rows.md index c3b713703e..5f8c9aa1ef 100644 --- a/docs/examples/1.8.x/server-php/examples/tablesdb/list-rows.md +++ b/docs/examples/1.8.x/server-php/examples/tablesdb/list-rows.md @@ -13,5 +13,6 @@ $tablesDB = new TablesDB($client); $result = $tablesDB->listRows( databaseId: '', tableId: '', - queries: [] // optional + queries: [], // optional + transactionId: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/tablesdb/list-transactions.md b/docs/examples/1.8.x/server-php/examples/tablesdb/list-transactions.md new file mode 100644 index 0000000000..15095d6f0c --- /dev/null +++ b/docs/examples/1.8.x/server-php/examples/tablesdb/list-transactions.md @@ -0,0 +1,15 @@ +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your secret API key + +$tablesDB = new TablesDB($client); + +$result = $tablesDB->listTransactions( + queries: [] // optional +); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/tablesdb/update-row.md b/docs/examples/1.8.x/server-php/examples/tablesdb/update-row.md index 70e5d159fd..c01eba8d57 100644 --- a/docs/examples/1.8.x/server-php/examples/tablesdb/update-row.md +++ b/docs/examples/1.8.x/server-php/examples/tablesdb/update-row.md @@ -15,5 +15,6 @@ $result = $tablesDB->updateRow( tableId: '', rowId: '', data: [], // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/tablesdb/update-rows.md b/docs/examples/1.8.x/server-php/examples/tablesdb/update-rows.md index 8a676289d2..681a9f0d8b 100644 --- a/docs/examples/1.8.x/server-php/examples/tablesdb/update-rows.md +++ b/docs/examples/1.8.x/server-php/examples/tablesdb/update-rows.md @@ -14,5 +14,6 @@ $result = $tablesDB->updateRows( databaseId: '', tableId: '', data: [], // optional - queries: [] // optional + queries: [], // optional + transactionId: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/tablesdb/update-transaction.md b/docs/examples/1.8.x/server-php/examples/tablesdb/update-transaction.md new file mode 100644 index 0000000000..fed3810b5a --- /dev/null +++ b/docs/examples/1.8.x/server-php/examples/tablesdb/update-transaction.md @@ -0,0 +1,17 @@ +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your secret API key + +$tablesDB = new TablesDB($client); + +$result = $tablesDB->updateTransaction( + transactionId: '', + commit: false, // optional + rollback: false // optional +); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/tablesdb/upsert-row.md b/docs/examples/1.8.x/server-php/examples/tablesdb/upsert-row.md index 235f0e577b..bec3c0af92 100644 --- a/docs/examples/1.8.x/server-php/examples/tablesdb/upsert-row.md +++ b/docs/examples/1.8.x/server-php/examples/tablesdb/upsert-row.md @@ -15,5 +15,6 @@ $result = $tablesDB->upsertRow( tableId: '', rowId: '', data: [], // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/tablesdb/upsert-rows.md b/docs/examples/1.8.x/server-php/examples/tablesdb/upsert-rows.md index c1890f1ea3..fb93df8bcd 100644 --- a/docs/examples/1.8.x/server-php/examples/tablesdb/upsert-rows.md +++ b/docs/examples/1.8.x/server-php/examples/tablesdb/upsert-rows.md @@ -13,5 +13,6 @@ $tablesDB = new TablesDB($client); $result = $tablesDB->upsertRows( databaseId: '', tableId: '', - rows: [] + rows: [], + transactionId: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-python/examples/databases/create-document.md b/docs/examples/1.8.x/server-python/examples/databases/create-document.md index 3d7dee1a4f..f42a3d82b6 100644 --- a/docs/examples/1.8.x/server-python/examples/databases/create-document.md +++ b/docs/examples/1.8.x/server-python/examples/databases/create-document.md @@ -19,5 +19,6 @@ result = databases.create_document( "age": 30, "isAdmin": False }, - permissions = ["read("any")"] # optional + permissions = ["read("any")"], # optional + transaction_id = '' # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/databases/create-documents.md b/docs/examples/1.8.x/server-python/examples/databases/create-documents.md index 1b94e5165a..97fa4c6840 100644 --- a/docs/examples/1.8.x/server-python/examples/databases/create-documents.md +++ b/docs/examples/1.8.x/server-python/examples/databases/create-documents.md @@ -11,5 +11,6 @@ databases = Databases(client) result = databases.create_documents( database_id = '', collection_id = '', - documents = [] + documents = [], + transaction_id = '' # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/databases/create-operations.md b/docs/examples/1.8.x/server-python/examples/databases/create-operations.md new file mode 100644 index 0000000000..d8fc1fa772 --- /dev/null +++ b/docs/examples/1.8.x/server-python/examples/databases/create-operations.md @@ -0,0 +1,24 @@ +from appwrite.client import Client +from appwrite.services.databases import Databases + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +databases = Databases(client) + +result = databases.create_operations( + transaction_id = '', + operations = [ + { + "action": "create", + "databaseId": "", + "collectionId": "", + "documentId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] # optional +) diff --git a/docs/examples/1.8.x/server-python/examples/databases/create-transaction.md b/docs/examples/1.8.x/server-python/examples/databases/create-transaction.md new file mode 100644 index 0000000000..a733b658f8 --- /dev/null +++ b/docs/examples/1.8.x/server-python/examples/databases/create-transaction.md @@ -0,0 +1,13 @@ +from appwrite.client import Client +from appwrite.services.databases import Databases + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +databases = Databases(client) + +result = databases.create_transaction( + ttl = 60 # optional +) diff --git a/docs/examples/1.8.x/server-python/examples/databases/decrement-document-attribute.md b/docs/examples/1.8.x/server-python/examples/databases/decrement-document-attribute.md index 3efedf766e..09ed9fcb47 100644 --- a/docs/examples/1.8.x/server-python/examples/databases/decrement-document-attribute.md +++ b/docs/examples/1.8.x/server-python/examples/databases/decrement-document-attribute.md @@ -14,5 +14,6 @@ result = databases.decrement_document_attribute( document_id = '', attribute = '', value = None, # optional - min = None # optional + min = None, # optional + transaction_id = '' # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/databases/delete-document.md b/docs/examples/1.8.x/server-python/examples/databases/delete-document.md index 57f8b3bd9d..89d85853e4 100644 --- a/docs/examples/1.8.x/server-python/examples/databases/delete-document.md +++ b/docs/examples/1.8.x/server-python/examples/databases/delete-document.md @@ -11,5 +11,6 @@ databases = Databases(client) result = databases.delete_document( database_id = '', collection_id = '', - document_id = '' + document_id = '', + transaction_id = '' # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/databases/delete-documents.md b/docs/examples/1.8.x/server-python/examples/databases/delete-documents.md index a315f0c200..63130fb05e 100644 --- a/docs/examples/1.8.x/server-python/examples/databases/delete-documents.md +++ b/docs/examples/1.8.x/server-python/examples/databases/delete-documents.md @@ -11,5 +11,6 @@ databases = Databases(client) result = databases.delete_documents( database_id = '', collection_id = '', - queries = [] # optional + queries = [], # optional + transaction_id = '' # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/databases/delete-transaction.md b/docs/examples/1.8.x/server-python/examples/databases/delete-transaction.md new file mode 100644 index 0000000000..fab1f2a586 --- /dev/null +++ b/docs/examples/1.8.x/server-python/examples/databases/delete-transaction.md @@ -0,0 +1,13 @@ +from appwrite.client import Client +from appwrite.services.databases import Databases + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +databases = Databases(client) + +result = databases.delete_transaction( + transaction_id = '' +) diff --git a/docs/examples/1.8.x/server-python/examples/databases/get-document.md b/docs/examples/1.8.x/server-python/examples/databases/get-document.md index aff5008fa0..6cd0bc2b95 100644 --- a/docs/examples/1.8.x/server-python/examples/databases/get-document.md +++ b/docs/examples/1.8.x/server-python/examples/databases/get-document.md @@ -12,5 +12,6 @@ result = databases.get_document( database_id = '', collection_id = '', document_id = '', - queries = [] # optional + queries = [], # optional + transaction_id = '' # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/databases/get-transaction.md b/docs/examples/1.8.x/server-python/examples/databases/get-transaction.md new file mode 100644 index 0000000000..2a89f3d83d --- /dev/null +++ b/docs/examples/1.8.x/server-python/examples/databases/get-transaction.md @@ -0,0 +1,13 @@ +from appwrite.client import Client +from appwrite.services.databases import Databases + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +databases = Databases(client) + +result = databases.get_transaction( + transaction_id = '' +) diff --git a/docs/examples/1.8.x/server-python/examples/databases/increment-document-attribute.md b/docs/examples/1.8.x/server-python/examples/databases/increment-document-attribute.md index 9ae1cedfe4..3e85656c10 100644 --- a/docs/examples/1.8.x/server-python/examples/databases/increment-document-attribute.md +++ b/docs/examples/1.8.x/server-python/examples/databases/increment-document-attribute.md @@ -14,5 +14,6 @@ result = databases.increment_document_attribute( document_id = '', attribute = '', value = None, # optional - max = None # optional + max = None, # optional + transaction_id = '' # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/databases/list-documents.md b/docs/examples/1.8.x/server-python/examples/databases/list-documents.md index 8b450cd020..cecac30585 100644 --- a/docs/examples/1.8.x/server-python/examples/databases/list-documents.md +++ b/docs/examples/1.8.x/server-python/examples/databases/list-documents.md @@ -11,5 +11,6 @@ databases = Databases(client) result = databases.list_documents( database_id = '', collection_id = '', - queries = [] # optional + queries = [], # optional + transaction_id = '' # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/databases/list-transactions.md b/docs/examples/1.8.x/server-python/examples/databases/list-transactions.md new file mode 100644 index 0000000000..a410c96b05 --- /dev/null +++ b/docs/examples/1.8.x/server-python/examples/databases/list-transactions.md @@ -0,0 +1,13 @@ +from appwrite.client import Client +from appwrite.services.databases import Databases + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +databases = Databases(client) + +result = databases.list_transactions( + queries = [] # optional +) diff --git a/docs/examples/1.8.x/server-python/examples/databases/update-document.md b/docs/examples/1.8.x/server-python/examples/databases/update-document.md index 9ef6527934..c9ef02f72e 100644 --- a/docs/examples/1.8.x/server-python/examples/databases/update-document.md +++ b/docs/examples/1.8.x/server-python/examples/databases/update-document.md @@ -13,5 +13,6 @@ result = databases.update_document( collection_id = '', document_id = '', data = {}, # optional - permissions = ["read("any")"] # optional + permissions = ["read("any")"], # optional + transaction_id = '' # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/databases/update-documents.md b/docs/examples/1.8.x/server-python/examples/databases/update-documents.md index 5a50d1a912..2aab8c61c4 100644 --- a/docs/examples/1.8.x/server-python/examples/databases/update-documents.md +++ b/docs/examples/1.8.x/server-python/examples/databases/update-documents.md @@ -12,5 +12,6 @@ result = databases.update_documents( database_id = '', collection_id = '', data = {}, # optional - queries = [] # optional + queries = [], # optional + transaction_id = '' # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/databases/update-transaction.md b/docs/examples/1.8.x/server-python/examples/databases/update-transaction.md new file mode 100644 index 0000000000..571f98c7ce --- /dev/null +++ b/docs/examples/1.8.x/server-python/examples/databases/update-transaction.md @@ -0,0 +1,15 @@ +from appwrite.client import Client +from appwrite.services.databases import Databases + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +databases = Databases(client) + +result = databases.update_transaction( + transaction_id = '', + commit = False, # optional + rollback = False # optional +) diff --git a/docs/examples/1.8.x/server-python/examples/databases/upsert-document.md b/docs/examples/1.8.x/server-python/examples/databases/upsert-document.md index c491ea4f44..e1a2f44d8c 100644 --- a/docs/examples/1.8.x/server-python/examples/databases/upsert-document.md +++ b/docs/examples/1.8.x/server-python/examples/databases/upsert-document.md @@ -13,5 +13,6 @@ result = databases.upsert_document( collection_id = '', document_id = '', data = {}, - permissions = ["read("any")"] # optional + permissions = ["read("any")"], # optional + transaction_id = '' # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/databases/upsert-documents.md b/docs/examples/1.8.x/server-python/examples/databases/upsert-documents.md index 5136d5fcb1..f0720e34c0 100644 --- a/docs/examples/1.8.x/server-python/examples/databases/upsert-documents.md +++ b/docs/examples/1.8.x/server-python/examples/databases/upsert-documents.md @@ -11,5 +11,6 @@ databases = Databases(client) result = databases.upsert_documents( database_id = '', collection_id = '', - documents = [] + documents = [], + transaction_id = '' # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/messaging/create-push.md b/docs/examples/1.8.x/server-python/examples/messaging/create-push.md index 8671b56a39..b706234227 100644 --- a/docs/examples/1.8.x/server-python/examples/messaging/create-push.md +++ b/docs/examples/1.8.x/server-python/examples/messaging/create-push.md @@ -17,7 +17,7 @@ result = messaging.create_push( targets = [], # optional data = {}, # optional action = '', # optional - image = '[ID1:ID2]', # optional + image = '', # optional icon = '', # optional sound = '', # optional color = '', # optional diff --git a/docs/examples/1.8.x/server-python/examples/messaging/update-push.md b/docs/examples/1.8.x/server-python/examples/messaging/update-push.md index e3bb02e71f..ce5d39466f 100644 --- a/docs/examples/1.8.x/server-python/examples/messaging/update-push.md +++ b/docs/examples/1.8.x/server-python/examples/messaging/update-push.md @@ -17,7 +17,7 @@ result = messaging.update_push( body = '', # optional data = {}, # optional action = '', # optional - image = '[ID1:ID2]', # optional + image = '', # optional icon = '', # optional sound = '', # optional color = '', # optional diff --git a/docs/examples/1.8.x/server-python/examples/tablesdb/create-operations.md b/docs/examples/1.8.x/server-python/examples/tablesdb/create-operations.md new file mode 100644 index 0000000000..a4881a9e8f --- /dev/null +++ b/docs/examples/1.8.x/server-python/examples/tablesdb/create-operations.md @@ -0,0 +1,24 @@ +from appwrite.client import Client +from appwrite.services.tables_db import TablesDB + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +tables_db = TablesDB(client) + +result = tables_db.create_operations( + transaction_id = '', + operations = [ + { + "action": "create", + "databaseId": "", + "tableId": "", + "rowId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] # optional +) diff --git a/docs/examples/1.8.x/server-python/examples/tablesdb/create-row.md b/docs/examples/1.8.x/server-python/examples/tablesdb/create-row.md index d4c1cdad14..d2de58617f 100644 --- a/docs/examples/1.8.x/server-python/examples/tablesdb/create-row.md +++ b/docs/examples/1.8.x/server-python/examples/tablesdb/create-row.md @@ -19,5 +19,6 @@ result = tables_db.create_row( "age": 30, "isAdmin": False }, - permissions = ["read("any")"] # optional + permissions = ["read("any")"], # optional + transaction_id = '' # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/tablesdb/create-rows.md b/docs/examples/1.8.x/server-python/examples/tablesdb/create-rows.md index 656a47aa0b..1527e0b30d 100644 --- a/docs/examples/1.8.x/server-python/examples/tablesdb/create-rows.md +++ b/docs/examples/1.8.x/server-python/examples/tablesdb/create-rows.md @@ -11,5 +11,6 @@ tables_db = TablesDB(client) result = tables_db.create_rows( database_id = '', table_id = '', - rows = [] + rows = [], + transaction_id = '' # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/tablesdb/create-transaction.md b/docs/examples/1.8.x/server-python/examples/tablesdb/create-transaction.md new file mode 100644 index 0000000000..05cc80eaa2 --- /dev/null +++ b/docs/examples/1.8.x/server-python/examples/tablesdb/create-transaction.md @@ -0,0 +1,13 @@ +from appwrite.client import Client +from appwrite.services.tables_db import TablesDB + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +tables_db = TablesDB(client) + +result = tables_db.create_transaction( + ttl = 60 # optional +) diff --git a/docs/examples/1.8.x/server-python/examples/tablesdb/decrement-row-column.md b/docs/examples/1.8.x/server-python/examples/tablesdb/decrement-row-column.md index 096bc4dbaa..d207bb1b4d 100644 --- a/docs/examples/1.8.x/server-python/examples/tablesdb/decrement-row-column.md +++ b/docs/examples/1.8.x/server-python/examples/tablesdb/decrement-row-column.md @@ -14,5 +14,6 @@ result = tables_db.decrement_row_column( row_id = '', column = '', value = None, # optional - min = None # optional + min = None, # optional + transaction_id = '' # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/tablesdb/delete-row.md b/docs/examples/1.8.x/server-python/examples/tablesdb/delete-row.md index 569b607020..3943ab27a5 100644 --- a/docs/examples/1.8.x/server-python/examples/tablesdb/delete-row.md +++ b/docs/examples/1.8.x/server-python/examples/tablesdb/delete-row.md @@ -11,5 +11,6 @@ tables_db = TablesDB(client) result = tables_db.delete_row( database_id = '', table_id = '', - row_id = '' + row_id = '', + transaction_id = '' # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/tablesdb/delete-rows.md b/docs/examples/1.8.x/server-python/examples/tablesdb/delete-rows.md index c3e836e7c6..290d6d346b 100644 --- a/docs/examples/1.8.x/server-python/examples/tablesdb/delete-rows.md +++ b/docs/examples/1.8.x/server-python/examples/tablesdb/delete-rows.md @@ -11,5 +11,6 @@ tables_db = TablesDB(client) result = tables_db.delete_rows( database_id = '', table_id = '', - queries = [] # optional + queries = [], # optional + transaction_id = '' # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/tablesdb/delete-transaction.md b/docs/examples/1.8.x/server-python/examples/tablesdb/delete-transaction.md new file mode 100644 index 0000000000..6d2957f3d6 --- /dev/null +++ b/docs/examples/1.8.x/server-python/examples/tablesdb/delete-transaction.md @@ -0,0 +1,13 @@ +from appwrite.client import Client +from appwrite.services.tables_db import TablesDB + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +tables_db = TablesDB(client) + +result = tables_db.delete_transaction( + transaction_id = '' +) diff --git a/docs/examples/1.8.x/server-python/examples/tablesdb/get-row.md b/docs/examples/1.8.x/server-python/examples/tablesdb/get-row.md index c806214297..4398c9a43d 100644 --- a/docs/examples/1.8.x/server-python/examples/tablesdb/get-row.md +++ b/docs/examples/1.8.x/server-python/examples/tablesdb/get-row.md @@ -12,5 +12,6 @@ result = tables_db.get_row( database_id = '', table_id = '', row_id = '', - queries = [] # optional + queries = [], # optional + transaction_id = '' # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/tablesdb/get-transaction.md b/docs/examples/1.8.x/server-python/examples/tablesdb/get-transaction.md new file mode 100644 index 0000000000..e50c63af9d --- /dev/null +++ b/docs/examples/1.8.x/server-python/examples/tablesdb/get-transaction.md @@ -0,0 +1,13 @@ +from appwrite.client import Client +from appwrite.services.tables_db import TablesDB + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +tables_db = TablesDB(client) + +result = tables_db.get_transaction( + transaction_id = '' +) diff --git a/docs/examples/1.8.x/server-python/examples/tablesdb/increment-row-column.md b/docs/examples/1.8.x/server-python/examples/tablesdb/increment-row-column.md index bcb88f7a31..8e121f65f6 100644 --- a/docs/examples/1.8.x/server-python/examples/tablesdb/increment-row-column.md +++ b/docs/examples/1.8.x/server-python/examples/tablesdb/increment-row-column.md @@ -14,5 +14,6 @@ result = tables_db.increment_row_column( row_id = '', column = '', value = None, # optional - max = None # optional + max = None, # optional + transaction_id = '' # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/tablesdb/list-rows.md b/docs/examples/1.8.x/server-python/examples/tablesdb/list-rows.md index 9ae7549fb0..eb0a4ed1b3 100644 --- a/docs/examples/1.8.x/server-python/examples/tablesdb/list-rows.md +++ b/docs/examples/1.8.x/server-python/examples/tablesdb/list-rows.md @@ -11,5 +11,6 @@ tables_db = TablesDB(client) result = tables_db.list_rows( database_id = '', table_id = '', - queries = [] # optional + queries = [], # optional + transaction_id = '' # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/tablesdb/list-transactions.md b/docs/examples/1.8.x/server-python/examples/tablesdb/list-transactions.md new file mode 100644 index 0000000000..e597c2d6fd --- /dev/null +++ b/docs/examples/1.8.x/server-python/examples/tablesdb/list-transactions.md @@ -0,0 +1,13 @@ +from appwrite.client import Client +from appwrite.services.tables_db import TablesDB + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +tables_db = TablesDB(client) + +result = tables_db.list_transactions( + queries = [] # optional +) diff --git a/docs/examples/1.8.x/server-python/examples/tablesdb/update-row.md b/docs/examples/1.8.x/server-python/examples/tablesdb/update-row.md index 86d0cf2b8a..89dbfb0587 100644 --- a/docs/examples/1.8.x/server-python/examples/tablesdb/update-row.md +++ b/docs/examples/1.8.x/server-python/examples/tablesdb/update-row.md @@ -13,5 +13,6 @@ result = tables_db.update_row( table_id = '', row_id = '', data = {}, # optional - permissions = ["read("any")"] # optional + permissions = ["read("any")"], # optional + transaction_id = '' # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/tablesdb/update-rows.md b/docs/examples/1.8.x/server-python/examples/tablesdb/update-rows.md index 386ddf8b88..4717581276 100644 --- a/docs/examples/1.8.x/server-python/examples/tablesdb/update-rows.md +++ b/docs/examples/1.8.x/server-python/examples/tablesdb/update-rows.md @@ -12,5 +12,6 @@ result = tables_db.update_rows( database_id = '', table_id = '', data = {}, # optional - queries = [] # optional + queries = [], # optional + transaction_id = '' # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/tablesdb/update-transaction.md b/docs/examples/1.8.x/server-python/examples/tablesdb/update-transaction.md new file mode 100644 index 0000000000..97b518dc6e --- /dev/null +++ b/docs/examples/1.8.x/server-python/examples/tablesdb/update-transaction.md @@ -0,0 +1,15 @@ +from appwrite.client import Client +from appwrite.services.tables_db import TablesDB + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +tables_db = TablesDB(client) + +result = tables_db.update_transaction( + transaction_id = '', + commit = False, # optional + rollback = False # optional +) diff --git a/docs/examples/1.8.x/server-python/examples/tablesdb/upsert-row.md b/docs/examples/1.8.x/server-python/examples/tablesdb/upsert-row.md index 068fded0c3..8539e12e96 100644 --- a/docs/examples/1.8.x/server-python/examples/tablesdb/upsert-row.md +++ b/docs/examples/1.8.x/server-python/examples/tablesdb/upsert-row.md @@ -13,5 +13,6 @@ result = tables_db.upsert_row( table_id = '', row_id = '', data = {}, # optional - permissions = ["read("any")"] # optional + permissions = ["read("any")"], # optional + transaction_id = '' # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/tablesdb/upsert-rows.md b/docs/examples/1.8.x/server-python/examples/tablesdb/upsert-rows.md index 06436c0fa6..d42e259fb0 100644 --- a/docs/examples/1.8.x/server-python/examples/tablesdb/upsert-rows.md +++ b/docs/examples/1.8.x/server-python/examples/tablesdb/upsert-rows.md @@ -11,5 +11,6 @@ tables_db = TablesDB(client) result = tables_db.upsert_rows( database_id = '', table_id = '', - rows = [] + rows = [], + transaction_id = '' # optional ) diff --git a/docs/examples/1.8.x/server-rest/examples/databases/create-document.md b/docs/examples/1.8.x/server-rest/examples/databases/create-document.md index 57c38f0ba7..e1ca57e0bf 100644 --- a/docs/examples/1.8.x/server-rest/examples/databases/create-document.md +++ b/docs/examples/1.8.x/server-rest/examples/databases/create-document.md @@ -16,5 +16,6 @@ X-Appwrite-JWT: "age": 30, "isAdmin": false }, - "permissions": ["read(\"any\")"] + "permissions": ["read(\"any\")"], + "transactionId": "" } diff --git a/docs/examples/1.8.x/server-rest/examples/databases/create-documents.md b/docs/examples/1.8.x/server-rest/examples/databases/create-documents.md index cee5405fb2..4e23244620 100644 --- a/docs/examples/1.8.x/server-rest/examples/databases/create-documents.md +++ b/docs/examples/1.8.x/server-rest/examples/databases/create-documents.md @@ -8,5 +8,6 @@ X-Appwrite-Key: X-Appwrite-JWT: { - "documents": [] + "documents": [], + "transactionId": "" } diff --git a/docs/examples/1.8.x/server-rest/examples/databases/create-operations.md b/docs/examples/1.8.x/server-rest/examples/databases/create-operations.md new file mode 100644 index 0000000000..212d60df29 --- /dev/null +++ b/docs/examples/1.8.x/server-rest/examples/databases/create-operations.md @@ -0,0 +1,22 @@ +POST /v1/databases/transactions/{transactionId}/operations HTTP/1.1 +Host: cloud.appwrite.io +Content-Type: application/json +X-Appwrite-Response-Format: 1.8.0 +X-Appwrite-Project: +X-Appwrite-Key: +X-Appwrite-Session: +X-Appwrite-JWT: + +{ + "operations": [ + { + "action": "create", + "databaseId": "", + "collectionId": "", + "documentId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] +} diff --git a/docs/examples/1.8.x/server-rest/examples/databases/create-transaction.md b/docs/examples/1.8.x/server-rest/examples/databases/create-transaction.md new file mode 100644 index 0000000000..3647e2d128 --- /dev/null +++ b/docs/examples/1.8.x/server-rest/examples/databases/create-transaction.md @@ -0,0 +1,12 @@ +POST /v1/databases/transactions HTTP/1.1 +Host: cloud.appwrite.io +Content-Type: application/json +X-Appwrite-Response-Format: 1.8.0 +X-Appwrite-Project: +X-Appwrite-Key: +X-Appwrite-Session: +X-Appwrite-JWT: + +{ + "ttl": 60 +} diff --git a/docs/examples/1.8.x/server-rest/examples/databases/decrement-document-attribute.md b/docs/examples/1.8.x/server-rest/examples/databases/decrement-document-attribute.md index 78694a804d..0bd736b0e4 100644 --- a/docs/examples/1.8.x/server-rest/examples/databases/decrement-document-attribute.md +++ b/docs/examples/1.8.x/server-rest/examples/databases/decrement-document-attribute.md @@ -9,5 +9,6 @@ X-Appwrite-Key: { "value": 0, - "min": 0 + "min": 0, + "transactionId": "" } diff --git a/docs/examples/1.8.x/server-rest/examples/databases/delete-document.md b/docs/examples/1.8.x/server-rest/examples/databases/delete-document.md index b5580b04bf..1031bfe18d 100644 --- a/docs/examples/1.8.x/server-rest/examples/databases/delete-document.md +++ b/docs/examples/1.8.x/server-rest/examples/databases/delete-document.md @@ -7,3 +7,6 @@ X-Appwrite-Session: X-Appwrite-Key: X-Appwrite-JWT: +{ + "transactionId": "" +} diff --git a/docs/examples/1.8.x/server-rest/examples/databases/delete-documents.md b/docs/examples/1.8.x/server-rest/examples/databases/delete-documents.md index cb27719953..13ad4c6600 100644 --- a/docs/examples/1.8.x/server-rest/examples/databases/delete-documents.md +++ b/docs/examples/1.8.x/server-rest/examples/databases/delete-documents.md @@ -6,5 +6,6 @@ X-Appwrite-Project: X-Appwrite-Key: { - "queries": [] + "queries": [], + "transactionId": "" } diff --git a/docs/examples/1.8.x/server-rest/examples/databases/delete-transaction.md b/docs/examples/1.8.x/server-rest/examples/databases/delete-transaction.md new file mode 100644 index 0000000000..09fc4e21f7 --- /dev/null +++ b/docs/examples/1.8.x/server-rest/examples/databases/delete-transaction.md @@ -0,0 +1,9 @@ +DELETE /v1/databases/transactions/{transactionId} HTTP/1.1 +Host: cloud.appwrite.io +Content-Type: application/json +X-Appwrite-Response-Format: 1.8.0 +X-Appwrite-Project: +X-Appwrite-Key: +X-Appwrite-Session: +X-Appwrite-JWT: + diff --git a/docs/examples/1.8.x/server-rest/examples/databases/get-transaction.md b/docs/examples/1.8.x/server-rest/examples/databases/get-transaction.md new file mode 100644 index 0000000000..e3d89d72de --- /dev/null +++ b/docs/examples/1.8.x/server-rest/examples/databases/get-transaction.md @@ -0,0 +1,7 @@ +GET /v1/databases/transactions/{transactionId} HTTP/1.1 +Host: cloud.appwrite.io +X-Appwrite-Response-Format: 1.8.0 +X-Appwrite-Project: +X-Appwrite-Key: +X-Appwrite-Session: +X-Appwrite-JWT: diff --git a/docs/examples/1.8.x/server-rest/examples/databases/increment-document-attribute.md b/docs/examples/1.8.x/server-rest/examples/databases/increment-document-attribute.md index cd6b4122eb..924f0e9b0c 100644 --- a/docs/examples/1.8.x/server-rest/examples/databases/increment-document-attribute.md +++ b/docs/examples/1.8.x/server-rest/examples/databases/increment-document-attribute.md @@ -9,5 +9,6 @@ X-Appwrite-Key: { "value": 0, - "max": 0 + "max": 0, + "transactionId": "" } diff --git a/docs/examples/1.8.x/server-rest/examples/databases/list-transactions.md b/docs/examples/1.8.x/server-rest/examples/databases/list-transactions.md new file mode 100644 index 0000000000..7a6f680a5f --- /dev/null +++ b/docs/examples/1.8.x/server-rest/examples/databases/list-transactions.md @@ -0,0 +1,7 @@ +GET /v1/databases/transactions HTTP/1.1 +Host: cloud.appwrite.io +X-Appwrite-Response-Format: 1.8.0 +X-Appwrite-Project: +X-Appwrite-Key: +X-Appwrite-Session: +X-Appwrite-JWT: diff --git a/docs/examples/1.8.x/server-rest/examples/databases/update-document.md b/docs/examples/1.8.x/server-rest/examples/databases/update-document.md index 9a156375de..dafd249c31 100644 --- a/docs/examples/1.8.x/server-rest/examples/databases/update-document.md +++ b/docs/examples/1.8.x/server-rest/examples/databases/update-document.md @@ -9,5 +9,6 @@ X-Appwrite-JWT: { "data": {}, - "permissions": ["read(\"any\")"] + "permissions": ["read(\"any\")"], + "transactionId": "" } diff --git a/docs/examples/1.8.x/server-rest/examples/databases/update-documents.md b/docs/examples/1.8.x/server-rest/examples/databases/update-documents.md index 69ea7a0d6f..69d2dccd13 100644 --- a/docs/examples/1.8.x/server-rest/examples/databases/update-documents.md +++ b/docs/examples/1.8.x/server-rest/examples/databases/update-documents.md @@ -7,5 +7,6 @@ X-Appwrite-Key: { "data": {}, - "queries": [] + "queries": [], + "transactionId": "" } diff --git a/docs/examples/1.8.x/server-rest/examples/databases/update-transaction.md b/docs/examples/1.8.x/server-rest/examples/databases/update-transaction.md new file mode 100644 index 0000000000..21f1921e41 --- /dev/null +++ b/docs/examples/1.8.x/server-rest/examples/databases/update-transaction.md @@ -0,0 +1,13 @@ +PATCH /v1/databases/transactions/{transactionId} HTTP/1.1 +Host: cloud.appwrite.io +Content-Type: application/json +X-Appwrite-Response-Format: 1.8.0 +X-Appwrite-Project: +X-Appwrite-Key: +X-Appwrite-Session: +X-Appwrite-JWT: + +{ + "commit": false, + "rollback": false +} diff --git a/docs/examples/1.8.x/server-rest/examples/databases/upsert-document.md b/docs/examples/1.8.x/server-rest/examples/databases/upsert-document.md index 97b61bfc7f..e4a9c7796a 100644 --- a/docs/examples/1.8.x/server-rest/examples/databases/upsert-document.md +++ b/docs/examples/1.8.x/server-rest/examples/databases/upsert-document.md @@ -9,5 +9,6 @@ X-Appwrite-JWT: { "data": {}, - "permissions": ["read(\"any\")"] + "permissions": ["read(\"any\")"], + "transactionId": "" } diff --git a/docs/examples/1.8.x/server-rest/examples/databases/upsert-documents.md b/docs/examples/1.8.x/server-rest/examples/databases/upsert-documents.md index 4bcb9cb0c0..7b15435e90 100644 --- a/docs/examples/1.8.x/server-rest/examples/databases/upsert-documents.md +++ b/docs/examples/1.8.x/server-rest/examples/databases/upsert-documents.md @@ -6,5 +6,6 @@ X-Appwrite-Project: X-Appwrite-Key: { - "documents": [] + "documents": [], + "transactionId": "" } diff --git a/docs/examples/1.8.x/server-rest/examples/messaging/create-push.md b/docs/examples/1.8.x/server-rest/examples/messaging/create-push.md index a70702c014..f873bfe6ee 100644 --- a/docs/examples/1.8.x/server-rest/examples/messaging/create-push.md +++ b/docs/examples/1.8.x/server-rest/examples/messaging/create-push.md @@ -14,7 +14,7 @@ X-Appwrite-Key: "targets": [], "data": {}, "action": "", - "image": "[ID1:ID2]", + "image": "", "icon": "", "sound": "", "color": "", diff --git a/docs/examples/1.8.x/server-rest/examples/messaging/update-push.md b/docs/examples/1.8.x/server-rest/examples/messaging/update-push.md index b3b953bc31..a3a6f84ae6 100644 --- a/docs/examples/1.8.x/server-rest/examples/messaging/update-push.md +++ b/docs/examples/1.8.x/server-rest/examples/messaging/update-push.md @@ -13,7 +13,7 @@ X-Appwrite-Key: "body": "", "data": {}, "action": "", - "image": "[ID1:ID2]", + "image": "", "icon": "", "sound": "", "color": "", diff --git a/docs/examples/1.8.x/server-rest/examples/tablesdb/create-operations.md b/docs/examples/1.8.x/server-rest/examples/tablesdb/create-operations.md new file mode 100644 index 0000000000..87ca296db2 --- /dev/null +++ b/docs/examples/1.8.x/server-rest/examples/tablesdb/create-operations.md @@ -0,0 +1,22 @@ +POST /v1/tablesdb/transactions/{transactionId}/operations HTTP/1.1 +Host: cloud.appwrite.io +Content-Type: application/json +X-Appwrite-Response-Format: 1.8.0 +X-Appwrite-Project: +X-Appwrite-Key: +X-Appwrite-Session: +X-Appwrite-JWT: + +{ + "operations": [ + { + "action": "create", + "databaseId": "", + "tableId": "", + "rowId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] +} diff --git a/docs/examples/1.8.x/server-rest/examples/tablesdb/create-row.md b/docs/examples/1.8.x/server-rest/examples/tablesdb/create-row.md index 3c42d0f172..cec287f4b3 100644 --- a/docs/examples/1.8.x/server-rest/examples/tablesdb/create-row.md +++ b/docs/examples/1.8.x/server-rest/examples/tablesdb/create-row.md @@ -16,5 +16,6 @@ X-Appwrite-JWT: "age": 30, "isAdmin": false }, - "permissions": ["read(\"any\")"] + "permissions": ["read(\"any\")"], + "transactionId": "" } diff --git a/docs/examples/1.8.x/server-rest/examples/tablesdb/create-rows.md b/docs/examples/1.8.x/server-rest/examples/tablesdb/create-rows.md index 176b4cdb02..0ff4426b84 100644 --- a/docs/examples/1.8.x/server-rest/examples/tablesdb/create-rows.md +++ b/docs/examples/1.8.x/server-rest/examples/tablesdb/create-rows.md @@ -8,5 +8,6 @@ X-Appwrite-Key: X-Appwrite-JWT: { - "rows": [] + "rows": [], + "transactionId": "" } diff --git a/docs/examples/1.8.x/server-rest/examples/tablesdb/create-transaction.md b/docs/examples/1.8.x/server-rest/examples/tablesdb/create-transaction.md new file mode 100644 index 0000000000..a2b8b184bd --- /dev/null +++ b/docs/examples/1.8.x/server-rest/examples/tablesdb/create-transaction.md @@ -0,0 +1,12 @@ +POST /v1/tablesdb/transactions HTTP/1.1 +Host: cloud.appwrite.io +Content-Type: application/json +X-Appwrite-Response-Format: 1.8.0 +X-Appwrite-Project: +X-Appwrite-Key: +X-Appwrite-Session: +X-Appwrite-JWT: + +{ + "ttl": 60 +} diff --git a/docs/examples/1.8.x/server-rest/examples/tablesdb/decrement-row-column.md b/docs/examples/1.8.x/server-rest/examples/tablesdb/decrement-row-column.md index 26d8e1118c..74b06974f1 100644 --- a/docs/examples/1.8.x/server-rest/examples/tablesdb/decrement-row-column.md +++ b/docs/examples/1.8.x/server-rest/examples/tablesdb/decrement-row-column.md @@ -9,5 +9,6 @@ X-Appwrite-Key: { "value": 0, - "min": 0 + "min": 0, + "transactionId": "" } diff --git a/docs/examples/1.8.x/server-rest/examples/tablesdb/delete-row.md b/docs/examples/1.8.x/server-rest/examples/tablesdb/delete-row.md index 3dbbf45a3c..b1376ee7cd 100644 --- a/docs/examples/1.8.x/server-rest/examples/tablesdb/delete-row.md +++ b/docs/examples/1.8.x/server-rest/examples/tablesdb/delete-row.md @@ -7,3 +7,6 @@ X-Appwrite-Session: X-Appwrite-Key: X-Appwrite-JWT: +{ + "transactionId": "" +} diff --git a/docs/examples/1.8.x/server-rest/examples/tablesdb/delete-rows.md b/docs/examples/1.8.x/server-rest/examples/tablesdb/delete-rows.md index c57d62ede3..22eae7d599 100644 --- a/docs/examples/1.8.x/server-rest/examples/tablesdb/delete-rows.md +++ b/docs/examples/1.8.x/server-rest/examples/tablesdb/delete-rows.md @@ -6,5 +6,6 @@ X-Appwrite-Project: X-Appwrite-Key: { - "queries": [] + "queries": [], + "transactionId": "" } diff --git a/docs/examples/1.8.x/server-rest/examples/tablesdb/delete-transaction.md b/docs/examples/1.8.x/server-rest/examples/tablesdb/delete-transaction.md new file mode 100644 index 0000000000..ed6e20dcc8 --- /dev/null +++ b/docs/examples/1.8.x/server-rest/examples/tablesdb/delete-transaction.md @@ -0,0 +1,9 @@ +DELETE /v1/tablesdb/transactions/{transactionId} HTTP/1.1 +Host: cloud.appwrite.io +Content-Type: application/json +X-Appwrite-Response-Format: 1.8.0 +X-Appwrite-Project: +X-Appwrite-Key: +X-Appwrite-Session: +X-Appwrite-JWT: + diff --git a/docs/examples/1.8.x/server-rest/examples/tablesdb/get-transaction.md b/docs/examples/1.8.x/server-rest/examples/tablesdb/get-transaction.md new file mode 100644 index 0000000000..690351d711 --- /dev/null +++ b/docs/examples/1.8.x/server-rest/examples/tablesdb/get-transaction.md @@ -0,0 +1,7 @@ +GET /v1/tablesdb/transactions/{transactionId} HTTP/1.1 +Host: cloud.appwrite.io +X-Appwrite-Response-Format: 1.8.0 +X-Appwrite-Project: +X-Appwrite-Key: +X-Appwrite-Session: +X-Appwrite-JWT: diff --git a/docs/examples/1.8.x/server-rest/examples/tablesdb/increment-row-column.md b/docs/examples/1.8.x/server-rest/examples/tablesdb/increment-row-column.md index d687727806..e9047669cd 100644 --- a/docs/examples/1.8.x/server-rest/examples/tablesdb/increment-row-column.md +++ b/docs/examples/1.8.x/server-rest/examples/tablesdb/increment-row-column.md @@ -9,5 +9,6 @@ X-Appwrite-Key: { "value": 0, - "max": 0 + "max": 0, + "transactionId": "" } diff --git a/docs/examples/1.8.x/server-rest/examples/tablesdb/list-transactions.md b/docs/examples/1.8.x/server-rest/examples/tablesdb/list-transactions.md new file mode 100644 index 0000000000..8b7f9301e3 --- /dev/null +++ b/docs/examples/1.8.x/server-rest/examples/tablesdb/list-transactions.md @@ -0,0 +1,7 @@ +GET /v1/tablesdb/transactions HTTP/1.1 +Host: cloud.appwrite.io +X-Appwrite-Response-Format: 1.8.0 +X-Appwrite-Project: +X-Appwrite-Key: +X-Appwrite-Session: +X-Appwrite-JWT: diff --git a/docs/examples/1.8.x/server-rest/examples/tablesdb/update-row.md b/docs/examples/1.8.x/server-rest/examples/tablesdb/update-row.md index 51f10f7f97..5c37e3d929 100644 --- a/docs/examples/1.8.x/server-rest/examples/tablesdb/update-row.md +++ b/docs/examples/1.8.x/server-rest/examples/tablesdb/update-row.md @@ -9,5 +9,6 @@ X-Appwrite-JWT: { "data": {}, - "permissions": ["read(\"any\")"] + "permissions": ["read(\"any\")"], + "transactionId": "" } diff --git a/docs/examples/1.8.x/server-rest/examples/tablesdb/update-rows.md b/docs/examples/1.8.x/server-rest/examples/tablesdb/update-rows.md index 2f282d8e13..c872907d30 100644 --- a/docs/examples/1.8.x/server-rest/examples/tablesdb/update-rows.md +++ b/docs/examples/1.8.x/server-rest/examples/tablesdb/update-rows.md @@ -7,5 +7,6 @@ X-Appwrite-Key: { "data": {}, - "queries": [] + "queries": [], + "transactionId": "" } diff --git a/docs/examples/1.8.x/server-rest/examples/tablesdb/update-transaction.md b/docs/examples/1.8.x/server-rest/examples/tablesdb/update-transaction.md new file mode 100644 index 0000000000..118366e4a6 --- /dev/null +++ b/docs/examples/1.8.x/server-rest/examples/tablesdb/update-transaction.md @@ -0,0 +1,13 @@ +PATCH /v1/tablesdb/transactions/{transactionId} HTTP/1.1 +Host: cloud.appwrite.io +Content-Type: application/json +X-Appwrite-Response-Format: 1.8.0 +X-Appwrite-Project: +X-Appwrite-Key: +X-Appwrite-Session: +X-Appwrite-JWT: + +{ + "commit": false, + "rollback": false +} diff --git a/docs/examples/1.8.x/server-rest/examples/tablesdb/upsert-row.md b/docs/examples/1.8.x/server-rest/examples/tablesdb/upsert-row.md index edb74043fb..9f698fb195 100644 --- a/docs/examples/1.8.x/server-rest/examples/tablesdb/upsert-row.md +++ b/docs/examples/1.8.x/server-rest/examples/tablesdb/upsert-row.md @@ -9,5 +9,6 @@ X-Appwrite-JWT: { "data": {}, - "permissions": ["read(\"any\")"] + "permissions": ["read(\"any\")"], + "transactionId": "" } diff --git a/docs/examples/1.8.x/server-rest/examples/tablesdb/upsert-rows.md b/docs/examples/1.8.x/server-rest/examples/tablesdb/upsert-rows.md index 147e4f66c3..822c7aaec2 100644 --- a/docs/examples/1.8.x/server-rest/examples/tablesdb/upsert-rows.md +++ b/docs/examples/1.8.x/server-rest/examples/tablesdb/upsert-rows.md @@ -6,5 +6,6 @@ X-Appwrite-Project: X-Appwrite-Key: { - "rows": [] + "rows": [], + "transactionId": "" } diff --git a/docs/examples/1.8.x/server-ruby/examples/databases/create-document.md b/docs/examples/1.8.x/server-ruby/examples/databases/create-document.md index 22ce5745fd..d12a3dbb8d 100644 --- a/docs/examples/1.8.x/server-ruby/examples/databases/create-document.md +++ b/docs/examples/1.8.x/server-ruby/examples/databases/create-document.md @@ -20,5 +20,6 @@ result = databases.create_document( "age" => 30, "isAdmin" => false }, - permissions: ["read("any")"] # optional + permissions: ["read("any")"], # optional + transaction_id: '' # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/databases/create-documents.md b/docs/examples/1.8.x/server-ruby/examples/databases/create-documents.md index 16abc5e465..db45bd78a9 100644 --- a/docs/examples/1.8.x/server-ruby/examples/databases/create-documents.md +++ b/docs/examples/1.8.x/server-ruby/examples/databases/create-documents.md @@ -12,5 +12,6 @@ databases = Databases.new(client) result = databases.create_documents( database_id: '', collection_id: '', - documents: [] + documents: [], + transaction_id: '' # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/databases/create-operations.md b/docs/examples/1.8.x/server-ruby/examples/databases/create-operations.md new file mode 100644 index 0000000000..687932bd3e --- /dev/null +++ b/docs/examples/1.8.x/server-ruby/examples/databases/create-operations.md @@ -0,0 +1,25 @@ +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint + .set_project('') # Your project ID + .set_key('') # Your secret API key + +databases = Databases.new(client) + +result = databases.create_operations( + transaction_id: '', + operations: [ + { + "action": "create", + "databaseId": "", + "collectionId": "", + "documentId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] # optional +) diff --git a/docs/examples/1.8.x/server-ruby/examples/databases/create-transaction.md b/docs/examples/1.8.x/server-ruby/examples/databases/create-transaction.md new file mode 100644 index 0000000000..83d2e4ea4d --- /dev/null +++ b/docs/examples/1.8.x/server-ruby/examples/databases/create-transaction.md @@ -0,0 +1,14 @@ +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint + .set_project('') # Your project ID + .set_key('') # Your secret API key + +databases = Databases.new(client) + +result = databases.create_transaction( + ttl: 60 # optional +) diff --git a/docs/examples/1.8.x/server-ruby/examples/databases/decrement-document-attribute.md b/docs/examples/1.8.x/server-ruby/examples/databases/decrement-document-attribute.md index 9fd0191a0f..ecf15864da 100644 --- a/docs/examples/1.8.x/server-ruby/examples/databases/decrement-document-attribute.md +++ b/docs/examples/1.8.x/server-ruby/examples/databases/decrement-document-attribute.md @@ -15,5 +15,6 @@ result = databases.decrement_document_attribute( document_id: '', attribute: '', value: null, # optional - min: null # optional + min: null, # optional + transaction_id: '' # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/databases/delete-document.md b/docs/examples/1.8.x/server-ruby/examples/databases/delete-document.md index 2102d2695b..079247fc05 100644 --- a/docs/examples/1.8.x/server-ruby/examples/databases/delete-document.md +++ b/docs/examples/1.8.x/server-ruby/examples/databases/delete-document.md @@ -12,5 +12,6 @@ databases = Databases.new(client) result = databases.delete_document( database_id: '', collection_id: '', - document_id: '' + document_id: '', + transaction_id: '' # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/databases/delete-documents.md b/docs/examples/1.8.x/server-ruby/examples/databases/delete-documents.md index d0f10d0b41..838660747c 100644 --- a/docs/examples/1.8.x/server-ruby/examples/databases/delete-documents.md +++ b/docs/examples/1.8.x/server-ruby/examples/databases/delete-documents.md @@ -12,5 +12,6 @@ databases = Databases.new(client) result = databases.delete_documents( database_id: '', collection_id: '', - queries: [] # optional + queries: [], # optional + transaction_id: '' # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/databases/delete-transaction.md b/docs/examples/1.8.x/server-ruby/examples/databases/delete-transaction.md new file mode 100644 index 0000000000..2024818ad4 --- /dev/null +++ b/docs/examples/1.8.x/server-ruby/examples/databases/delete-transaction.md @@ -0,0 +1,14 @@ +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint + .set_project('') # Your project ID + .set_key('') # Your secret API key + +databases = Databases.new(client) + +result = databases.delete_transaction( + transaction_id: '' +) diff --git a/docs/examples/1.8.x/server-ruby/examples/databases/get-document.md b/docs/examples/1.8.x/server-ruby/examples/databases/get-document.md index f43a1a2924..47404fee80 100644 --- a/docs/examples/1.8.x/server-ruby/examples/databases/get-document.md +++ b/docs/examples/1.8.x/server-ruby/examples/databases/get-document.md @@ -13,5 +13,6 @@ result = databases.get_document( database_id: '', collection_id: '', document_id: '', - queries: [] # optional + queries: [], # optional + transaction_id: '' # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/databases/get-transaction.md b/docs/examples/1.8.x/server-ruby/examples/databases/get-transaction.md new file mode 100644 index 0000000000..7d8349dc7d --- /dev/null +++ b/docs/examples/1.8.x/server-ruby/examples/databases/get-transaction.md @@ -0,0 +1,14 @@ +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint + .set_project('') # Your project ID + .set_key('') # Your secret API key + +databases = Databases.new(client) + +result = databases.get_transaction( + transaction_id: '' +) diff --git a/docs/examples/1.8.x/server-ruby/examples/databases/increment-document-attribute.md b/docs/examples/1.8.x/server-ruby/examples/databases/increment-document-attribute.md index 3e8bfe0b2a..8f78675cdd 100644 --- a/docs/examples/1.8.x/server-ruby/examples/databases/increment-document-attribute.md +++ b/docs/examples/1.8.x/server-ruby/examples/databases/increment-document-attribute.md @@ -15,5 +15,6 @@ result = databases.increment_document_attribute( document_id: '', attribute: '', value: null, # optional - max: null # optional + max: null, # optional + transaction_id: '' # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/databases/list-documents.md b/docs/examples/1.8.x/server-ruby/examples/databases/list-documents.md index 6617198d3f..666bfbd5ce 100644 --- a/docs/examples/1.8.x/server-ruby/examples/databases/list-documents.md +++ b/docs/examples/1.8.x/server-ruby/examples/databases/list-documents.md @@ -12,5 +12,6 @@ databases = Databases.new(client) result = databases.list_documents( database_id: '', collection_id: '', - queries: [] # optional + queries: [], # optional + transaction_id: '' # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/databases/list-transactions.md b/docs/examples/1.8.x/server-ruby/examples/databases/list-transactions.md new file mode 100644 index 0000000000..c041a05b5e --- /dev/null +++ b/docs/examples/1.8.x/server-ruby/examples/databases/list-transactions.md @@ -0,0 +1,14 @@ +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint + .set_project('') # Your project ID + .set_key('') # Your secret API key + +databases = Databases.new(client) + +result = databases.list_transactions( + queries: [] # optional +) diff --git a/docs/examples/1.8.x/server-ruby/examples/databases/update-document.md b/docs/examples/1.8.x/server-ruby/examples/databases/update-document.md index 485eb0485a..5831d68b5d 100644 --- a/docs/examples/1.8.x/server-ruby/examples/databases/update-document.md +++ b/docs/examples/1.8.x/server-ruby/examples/databases/update-document.md @@ -14,5 +14,6 @@ result = databases.update_document( collection_id: '', document_id: '', data: {}, # optional - permissions: ["read("any")"] # optional + permissions: ["read("any")"], # optional + transaction_id: '' # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/databases/update-documents.md b/docs/examples/1.8.x/server-ruby/examples/databases/update-documents.md index 2f6907294f..c85f594e55 100644 --- a/docs/examples/1.8.x/server-ruby/examples/databases/update-documents.md +++ b/docs/examples/1.8.x/server-ruby/examples/databases/update-documents.md @@ -13,5 +13,6 @@ result = databases.update_documents( database_id: '', collection_id: '', data: {}, # optional - queries: [] # optional + queries: [], # optional + transaction_id: '' # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/databases/update-transaction.md b/docs/examples/1.8.x/server-ruby/examples/databases/update-transaction.md new file mode 100644 index 0000000000..e53c148b18 --- /dev/null +++ b/docs/examples/1.8.x/server-ruby/examples/databases/update-transaction.md @@ -0,0 +1,16 @@ +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint + .set_project('') # Your project ID + .set_key('') # Your secret API key + +databases = Databases.new(client) + +result = databases.update_transaction( + transaction_id: '', + commit: false, # optional + rollback: false # optional +) diff --git a/docs/examples/1.8.x/server-ruby/examples/databases/upsert-document.md b/docs/examples/1.8.x/server-ruby/examples/databases/upsert-document.md index 238081864f..e5daa554c4 100644 --- a/docs/examples/1.8.x/server-ruby/examples/databases/upsert-document.md +++ b/docs/examples/1.8.x/server-ruby/examples/databases/upsert-document.md @@ -14,5 +14,6 @@ result = databases.upsert_document( collection_id: '', document_id: '', data: {}, - permissions: ["read("any")"] # optional + permissions: ["read("any")"], # optional + transaction_id: '' # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/databases/upsert-documents.md b/docs/examples/1.8.x/server-ruby/examples/databases/upsert-documents.md index 30c42aa439..b470b8d31f 100644 --- a/docs/examples/1.8.x/server-ruby/examples/databases/upsert-documents.md +++ b/docs/examples/1.8.x/server-ruby/examples/databases/upsert-documents.md @@ -12,5 +12,6 @@ databases = Databases.new(client) result = databases.upsert_documents( database_id: '', collection_id: '', - documents: [] + documents: [], + transaction_id: '' # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/messaging/create-push.md b/docs/examples/1.8.x/server-ruby/examples/messaging/create-push.md index 5c58fa542b..f4555aa967 100644 --- a/docs/examples/1.8.x/server-ruby/examples/messaging/create-push.md +++ b/docs/examples/1.8.x/server-ruby/examples/messaging/create-push.md @@ -18,7 +18,7 @@ result = messaging.create_push( targets: [], # optional data: {}, # optional action: '', # optional - image: '[ID1:ID2]', # optional + image: '', # optional icon: '', # optional sound: '', # optional color: '', # optional diff --git a/docs/examples/1.8.x/server-ruby/examples/messaging/update-push.md b/docs/examples/1.8.x/server-ruby/examples/messaging/update-push.md index 42a5104ccb..19b273bb24 100644 --- a/docs/examples/1.8.x/server-ruby/examples/messaging/update-push.md +++ b/docs/examples/1.8.x/server-ruby/examples/messaging/update-push.md @@ -18,7 +18,7 @@ result = messaging.update_push( body: '', # optional data: {}, # optional action: '', # optional - image: '[ID1:ID2]', # optional + image: '', # optional icon: '', # optional sound: '', # optional color: '', # optional diff --git a/docs/examples/1.8.x/server-ruby/examples/tablesdb/create-operations.md b/docs/examples/1.8.x/server-ruby/examples/tablesdb/create-operations.md new file mode 100644 index 0000000000..dfc7180990 --- /dev/null +++ b/docs/examples/1.8.x/server-ruby/examples/tablesdb/create-operations.md @@ -0,0 +1,25 @@ +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint + .set_project('') # Your project ID + .set_key('') # Your secret API key + +tables_db = TablesDB.new(client) + +result = tables_db.create_operations( + transaction_id: '', + operations: [ + { + "action": "create", + "databaseId": "", + "tableId": "", + "rowId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] # optional +) diff --git a/docs/examples/1.8.x/server-ruby/examples/tablesdb/create-row.md b/docs/examples/1.8.x/server-ruby/examples/tablesdb/create-row.md index 5e19136676..5622711642 100644 --- a/docs/examples/1.8.x/server-ruby/examples/tablesdb/create-row.md +++ b/docs/examples/1.8.x/server-ruby/examples/tablesdb/create-row.md @@ -20,5 +20,6 @@ result = tables_db.create_row( "age" => 30, "isAdmin" => false }, - permissions: ["read("any")"] # optional + permissions: ["read("any")"], # optional + transaction_id: '' # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/tablesdb/create-rows.md b/docs/examples/1.8.x/server-ruby/examples/tablesdb/create-rows.md index f258d4d36f..76ee28699a 100644 --- a/docs/examples/1.8.x/server-ruby/examples/tablesdb/create-rows.md +++ b/docs/examples/1.8.x/server-ruby/examples/tablesdb/create-rows.md @@ -12,5 +12,6 @@ tables_db = TablesDB.new(client) result = tables_db.create_rows( database_id: '', table_id: '', - rows: [] + rows: [], + transaction_id: '' # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/tablesdb/create-transaction.md b/docs/examples/1.8.x/server-ruby/examples/tablesdb/create-transaction.md new file mode 100644 index 0000000000..e3525afa19 --- /dev/null +++ b/docs/examples/1.8.x/server-ruby/examples/tablesdb/create-transaction.md @@ -0,0 +1,14 @@ +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint + .set_project('') # Your project ID + .set_key('') # Your secret API key + +tables_db = TablesDB.new(client) + +result = tables_db.create_transaction( + ttl: 60 # optional +) diff --git a/docs/examples/1.8.x/server-ruby/examples/tablesdb/decrement-row-column.md b/docs/examples/1.8.x/server-ruby/examples/tablesdb/decrement-row-column.md index 21439740ed..62b01977b1 100644 --- a/docs/examples/1.8.x/server-ruby/examples/tablesdb/decrement-row-column.md +++ b/docs/examples/1.8.x/server-ruby/examples/tablesdb/decrement-row-column.md @@ -15,5 +15,6 @@ result = tables_db.decrement_row_column( row_id: '', column: '', value: null, # optional - min: null # optional + min: null, # optional + transaction_id: '' # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/tablesdb/delete-row.md b/docs/examples/1.8.x/server-ruby/examples/tablesdb/delete-row.md index 704f52fc39..9747cb938a 100644 --- a/docs/examples/1.8.x/server-ruby/examples/tablesdb/delete-row.md +++ b/docs/examples/1.8.x/server-ruby/examples/tablesdb/delete-row.md @@ -12,5 +12,6 @@ tables_db = TablesDB.new(client) result = tables_db.delete_row( database_id: '', table_id: '', - row_id: '' + row_id: '', + transaction_id: '' # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/tablesdb/delete-rows.md b/docs/examples/1.8.x/server-ruby/examples/tablesdb/delete-rows.md index 5b15c1748a..cf95cfb229 100644 --- a/docs/examples/1.8.x/server-ruby/examples/tablesdb/delete-rows.md +++ b/docs/examples/1.8.x/server-ruby/examples/tablesdb/delete-rows.md @@ -12,5 +12,6 @@ tables_db = TablesDB.new(client) result = tables_db.delete_rows( database_id: '', table_id: '', - queries: [] # optional + queries: [], # optional + transaction_id: '' # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/tablesdb/delete-transaction.md b/docs/examples/1.8.x/server-ruby/examples/tablesdb/delete-transaction.md new file mode 100644 index 0000000000..8fa7b3b8ac --- /dev/null +++ b/docs/examples/1.8.x/server-ruby/examples/tablesdb/delete-transaction.md @@ -0,0 +1,14 @@ +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint + .set_project('') # Your project ID + .set_key('') # Your secret API key + +tables_db = TablesDB.new(client) + +result = tables_db.delete_transaction( + transaction_id: '' +) diff --git a/docs/examples/1.8.x/server-ruby/examples/tablesdb/get-row.md b/docs/examples/1.8.x/server-ruby/examples/tablesdb/get-row.md index 621c2e12f6..bdc1cf5fe6 100644 --- a/docs/examples/1.8.x/server-ruby/examples/tablesdb/get-row.md +++ b/docs/examples/1.8.x/server-ruby/examples/tablesdb/get-row.md @@ -13,5 +13,6 @@ result = tables_db.get_row( database_id: '', table_id: '', row_id: '', - queries: [] # optional + queries: [], # optional + transaction_id: '' # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/tablesdb/get-transaction.md b/docs/examples/1.8.x/server-ruby/examples/tablesdb/get-transaction.md new file mode 100644 index 0000000000..ce8468ba3f --- /dev/null +++ b/docs/examples/1.8.x/server-ruby/examples/tablesdb/get-transaction.md @@ -0,0 +1,14 @@ +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint + .set_project('') # Your project ID + .set_key('') # Your secret API key + +tables_db = TablesDB.new(client) + +result = tables_db.get_transaction( + transaction_id: '' +) diff --git a/docs/examples/1.8.x/server-ruby/examples/tablesdb/increment-row-column.md b/docs/examples/1.8.x/server-ruby/examples/tablesdb/increment-row-column.md index bf9b6cc230..a20d2f5b36 100644 --- a/docs/examples/1.8.x/server-ruby/examples/tablesdb/increment-row-column.md +++ b/docs/examples/1.8.x/server-ruby/examples/tablesdb/increment-row-column.md @@ -15,5 +15,6 @@ result = tables_db.increment_row_column( row_id: '', column: '', value: null, # optional - max: null # optional + max: null, # optional + transaction_id: '' # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/tablesdb/list-rows.md b/docs/examples/1.8.x/server-ruby/examples/tablesdb/list-rows.md index af971fbe10..b205cece5d 100644 --- a/docs/examples/1.8.x/server-ruby/examples/tablesdb/list-rows.md +++ b/docs/examples/1.8.x/server-ruby/examples/tablesdb/list-rows.md @@ -12,5 +12,6 @@ tables_db = TablesDB.new(client) result = tables_db.list_rows( database_id: '', table_id: '', - queries: [] # optional + queries: [], # optional + transaction_id: '' # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/tablesdb/list-transactions.md b/docs/examples/1.8.x/server-ruby/examples/tablesdb/list-transactions.md new file mode 100644 index 0000000000..e969bc9965 --- /dev/null +++ b/docs/examples/1.8.x/server-ruby/examples/tablesdb/list-transactions.md @@ -0,0 +1,14 @@ +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint + .set_project('') # Your project ID + .set_key('') # Your secret API key + +tables_db = TablesDB.new(client) + +result = tables_db.list_transactions( + queries: [] # optional +) diff --git a/docs/examples/1.8.x/server-ruby/examples/tablesdb/update-row.md b/docs/examples/1.8.x/server-ruby/examples/tablesdb/update-row.md index 7a48c5e3f6..02123051ca 100644 --- a/docs/examples/1.8.x/server-ruby/examples/tablesdb/update-row.md +++ b/docs/examples/1.8.x/server-ruby/examples/tablesdb/update-row.md @@ -14,5 +14,6 @@ result = tables_db.update_row( table_id: '', row_id: '', data: {}, # optional - permissions: ["read("any")"] # optional + permissions: ["read("any")"], # optional + transaction_id: '' # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/tablesdb/update-rows.md b/docs/examples/1.8.x/server-ruby/examples/tablesdb/update-rows.md index 7316241139..7c538a137d 100644 --- a/docs/examples/1.8.x/server-ruby/examples/tablesdb/update-rows.md +++ b/docs/examples/1.8.x/server-ruby/examples/tablesdb/update-rows.md @@ -13,5 +13,6 @@ result = tables_db.update_rows( database_id: '', table_id: '', data: {}, # optional - queries: [] # optional + queries: [], # optional + transaction_id: '' # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/tablesdb/update-transaction.md b/docs/examples/1.8.x/server-ruby/examples/tablesdb/update-transaction.md new file mode 100644 index 0000000000..2b8b3e7999 --- /dev/null +++ b/docs/examples/1.8.x/server-ruby/examples/tablesdb/update-transaction.md @@ -0,0 +1,16 @@ +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint + .set_project('') # Your project ID + .set_key('') # Your secret API key + +tables_db = TablesDB.new(client) + +result = tables_db.update_transaction( + transaction_id: '', + commit: false, # optional + rollback: false # optional +) diff --git a/docs/examples/1.8.x/server-ruby/examples/tablesdb/upsert-row.md b/docs/examples/1.8.x/server-ruby/examples/tablesdb/upsert-row.md index 5eb4281002..9feb685927 100644 --- a/docs/examples/1.8.x/server-ruby/examples/tablesdb/upsert-row.md +++ b/docs/examples/1.8.x/server-ruby/examples/tablesdb/upsert-row.md @@ -14,5 +14,6 @@ result = tables_db.upsert_row( table_id: '', row_id: '', data: {}, # optional - permissions: ["read("any")"] # optional + permissions: ["read("any")"], # optional + transaction_id: '' # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/tablesdb/upsert-rows.md b/docs/examples/1.8.x/server-ruby/examples/tablesdb/upsert-rows.md index c48211dcc0..e38f534ea9 100644 --- a/docs/examples/1.8.x/server-ruby/examples/tablesdb/upsert-rows.md +++ b/docs/examples/1.8.x/server-ruby/examples/tablesdb/upsert-rows.md @@ -12,5 +12,6 @@ tables_db = TablesDB.new(client) result = tables_db.upsert_rows( database_id: '', table_id: '', - rows: [] + rows: [], + transaction_id: '' # optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/databases/create-document.md b/docs/examples/1.8.x/server-swift/examples/databases/create-document.md index cc25fd8df8..604bacdc2a 100644 --- a/docs/examples/1.8.x/server-swift/examples/databases/create-document.md +++ b/docs/examples/1.8.x/server-swift/examples/databases/create-document.md @@ -18,6 +18,7 @@ let document = try await databases.createDocument( "age": 30, "isAdmin": false ], - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/databases/create-documents.md b/docs/examples/1.8.x/server-swift/examples/databases/create-documents.md index 2e992d9e3a..82a75125ae 100644 --- a/docs/examples/1.8.x/server-swift/examples/databases/create-documents.md +++ b/docs/examples/1.8.x/server-swift/examples/databases/create-documents.md @@ -10,6 +10,7 @@ let databases = Databases(client) let documentList = try await databases.createDocuments( databaseId: "", collectionId: "", - documents: [] + documents: [], + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/databases/create-operations.md b/docs/examples/1.8.x/server-swift/examples/databases/create-operations.md new file mode 100644 index 0000000000..7cab190bd3 --- /dev/null +++ b/docs/examples/1.8.x/server-swift/examples/databases/create-operations.md @@ -0,0 +1,24 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +let databases = Databases(client) + +let transaction = try await databases.createOperations( + transactionId: "", + operations: [ + { + "action": "create", + "databaseId": "", + "collectionId": "", + "documentId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] // optional +) + diff --git a/docs/examples/1.8.x/server-swift/examples/databases/create-transaction.md b/docs/examples/1.8.x/server-swift/examples/databases/create-transaction.md new file mode 100644 index 0000000000..333632c583 --- /dev/null +++ b/docs/examples/1.8.x/server-swift/examples/databases/create-transaction.md @@ -0,0 +1,13 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +let databases = Databases(client) + +let transaction = try await databases.createTransaction( + ttl: 60 // optional +) + diff --git a/docs/examples/1.8.x/server-swift/examples/databases/decrement-document-attribute.md b/docs/examples/1.8.x/server-swift/examples/databases/decrement-document-attribute.md index 81516fa26a..8c256ad208 100644 --- a/docs/examples/1.8.x/server-swift/examples/databases/decrement-document-attribute.md +++ b/docs/examples/1.8.x/server-swift/examples/databases/decrement-document-attribute.md @@ -13,6 +13,7 @@ let document = try await databases.decrementDocumentAttribute( documentId: "", attribute: "", value: 0, // optional - min: 0 // optional + min: 0, // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/databases/delete-document.md b/docs/examples/1.8.x/server-swift/examples/databases/delete-document.md index 1db59709ab..9120c3d0d0 100644 --- a/docs/examples/1.8.x/server-swift/examples/databases/delete-document.md +++ b/docs/examples/1.8.x/server-swift/examples/databases/delete-document.md @@ -10,6 +10,7 @@ let databases = Databases(client) let result = try await databases.deleteDocument( databaseId: "", collectionId: "", - documentId: "" + documentId: "", + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/databases/delete-documents.md b/docs/examples/1.8.x/server-swift/examples/databases/delete-documents.md index d5321f2b26..79ec772b3b 100644 --- a/docs/examples/1.8.x/server-swift/examples/databases/delete-documents.md +++ b/docs/examples/1.8.x/server-swift/examples/databases/delete-documents.md @@ -10,6 +10,7 @@ let databases = Databases(client) let documentList = try await databases.deleteDocuments( databaseId: "", collectionId: "", - queries: [] // optional + queries: [], // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/databases/delete-transaction.md b/docs/examples/1.8.x/server-swift/examples/databases/delete-transaction.md new file mode 100644 index 0000000000..8ac62ef945 --- /dev/null +++ b/docs/examples/1.8.x/server-swift/examples/databases/delete-transaction.md @@ -0,0 +1,13 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +let databases = Databases(client) + +let result = try await databases.deleteTransaction( + transactionId: "" +) + diff --git a/docs/examples/1.8.x/server-swift/examples/databases/get-document.md b/docs/examples/1.8.x/server-swift/examples/databases/get-document.md index c92856a731..319a7ec3fb 100644 --- a/docs/examples/1.8.x/server-swift/examples/databases/get-document.md +++ b/docs/examples/1.8.x/server-swift/examples/databases/get-document.md @@ -11,6 +11,7 @@ let document = try await databases.getDocument( databaseId: "", collectionId: "", documentId: "", - queries: [] // optional + queries: [], // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/databases/get-transaction.md b/docs/examples/1.8.x/server-swift/examples/databases/get-transaction.md new file mode 100644 index 0000000000..bfabd08b78 --- /dev/null +++ b/docs/examples/1.8.x/server-swift/examples/databases/get-transaction.md @@ -0,0 +1,13 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +let databases = Databases(client) + +let transaction = try await databases.getTransaction( + transactionId: "" +) + diff --git a/docs/examples/1.8.x/server-swift/examples/databases/increment-document-attribute.md b/docs/examples/1.8.x/server-swift/examples/databases/increment-document-attribute.md index 64ba46b413..7dd8805dc0 100644 --- a/docs/examples/1.8.x/server-swift/examples/databases/increment-document-attribute.md +++ b/docs/examples/1.8.x/server-swift/examples/databases/increment-document-attribute.md @@ -13,6 +13,7 @@ let document = try await databases.incrementDocumentAttribute( documentId: "", attribute: "", value: 0, // optional - max: 0 // optional + max: 0, // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/databases/list-documents.md b/docs/examples/1.8.x/server-swift/examples/databases/list-documents.md index 2cac9330b3..1147530d00 100644 --- a/docs/examples/1.8.x/server-swift/examples/databases/list-documents.md +++ b/docs/examples/1.8.x/server-swift/examples/databases/list-documents.md @@ -10,6 +10,7 @@ let databases = Databases(client) let documentList = try await databases.listDocuments( databaseId: "", collectionId: "", - queries: [] // optional + queries: [], // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/databases/list-transactions.md b/docs/examples/1.8.x/server-swift/examples/databases/list-transactions.md new file mode 100644 index 0000000000..bb0d852d0a --- /dev/null +++ b/docs/examples/1.8.x/server-swift/examples/databases/list-transactions.md @@ -0,0 +1,13 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +let databases = Databases(client) + +let transactionList = try await databases.listTransactions( + queries: [] // optional +) + diff --git a/docs/examples/1.8.x/server-swift/examples/databases/update-document.md b/docs/examples/1.8.x/server-swift/examples/databases/update-document.md index 7d452db284..b6260d754d 100644 --- a/docs/examples/1.8.x/server-swift/examples/databases/update-document.md +++ b/docs/examples/1.8.x/server-swift/examples/databases/update-document.md @@ -12,6 +12,7 @@ let document = try await databases.updateDocument( collectionId: "", documentId: "", data: [:], // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/databases/update-documents.md b/docs/examples/1.8.x/server-swift/examples/databases/update-documents.md index 0e934b1424..f1fb34aa3c 100644 --- a/docs/examples/1.8.x/server-swift/examples/databases/update-documents.md +++ b/docs/examples/1.8.x/server-swift/examples/databases/update-documents.md @@ -11,6 +11,7 @@ let documentList = try await databases.updateDocuments( databaseId: "", collectionId: "", data: [:], // optional - queries: [] // optional + queries: [], // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/databases/update-transaction.md b/docs/examples/1.8.x/server-swift/examples/databases/update-transaction.md new file mode 100644 index 0000000000..79f4939b5d --- /dev/null +++ b/docs/examples/1.8.x/server-swift/examples/databases/update-transaction.md @@ -0,0 +1,15 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +let databases = Databases(client) + +let transaction = try await databases.updateTransaction( + transactionId: "", + commit: false, // optional + rollback: false // optional +) + diff --git a/docs/examples/1.8.x/server-swift/examples/databases/upsert-document.md b/docs/examples/1.8.x/server-swift/examples/databases/upsert-document.md index e78bd458a0..26897f4ca5 100644 --- a/docs/examples/1.8.x/server-swift/examples/databases/upsert-document.md +++ b/docs/examples/1.8.x/server-swift/examples/databases/upsert-document.md @@ -12,6 +12,7 @@ let document = try await databases.upsertDocument( collectionId: "", documentId: "", data: [:], - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/databases/upsert-documents.md b/docs/examples/1.8.x/server-swift/examples/databases/upsert-documents.md index 544f02f9c0..92c5fd9810 100644 --- a/docs/examples/1.8.x/server-swift/examples/databases/upsert-documents.md +++ b/docs/examples/1.8.x/server-swift/examples/databases/upsert-documents.md @@ -10,6 +10,7 @@ let databases = Databases(client) let documentList = try await databases.upsertDocuments( databaseId: "", collectionId: "", - documents: [] + documents: [], + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/messaging/create-push.md b/docs/examples/1.8.x/server-swift/examples/messaging/create-push.md index 498eccb51a..ba03b3330d 100644 --- a/docs/examples/1.8.x/server-swift/examples/messaging/create-push.md +++ b/docs/examples/1.8.x/server-swift/examples/messaging/create-push.md @@ -17,7 +17,7 @@ let message = try await messaging.createPush( targets: [], // optional data: [:], // optional action: "", // optional - image: "[ID1:ID2]", // optional + image: "", // optional icon: "", // optional sound: "", // optional color: "", // optional diff --git a/docs/examples/1.8.x/server-swift/examples/messaging/update-push.md b/docs/examples/1.8.x/server-swift/examples/messaging/update-push.md index e443161aa9..b7b5bb0b38 100644 --- a/docs/examples/1.8.x/server-swift/examples/messaging/update-push.md +++ b/docs/examples/1.8.x/server-swift/examples/messaging/update-push.md @@ -17,7 +17,7 @@ let message = try await messaging.updatePush( body: "", // optional data: [:], // optional action: "", // optional - image: "[ID1:ID2]", // optional + image: "", // optional icon: "", // optional sound: "", // optional color: "", // optional diff --git a/docs/examples/1.8.x/server-swift/examples/tablesdb/create-operations.md b/docs/examples/1.8.x/server-swift/examples/tablesdb/create-operations.md new file mode 100644 index 0000000000..5ee356e55b --- /dev/null +++ b/docs/examples/1.8.x/server-swift/examples/tablesdb/create-operations.md @@ -0,0 +1,24 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +let tablesDB = TablesDB(client) + +let transaction = try await tablesDB.createOperations( + transactionId: "", + operations: [ + { + "action": "create", + "databaseId": "", + "tableId": "", + "rowId": "", + "data": { + "name": "Walter O'Brien" + } + } + ] // optional +) + diff --git a/docs/examples/1.8.x/server-swift/examples/tablesdb/create-row.md b/docs/examples/1.8.x/server-swift/examples/tablesdb/create-row.md index 0c59a65755..049ef2da3d 100644 --- a/docs/examples/1.8.x/server-swift/examples/tablesdb/create-row.md +++ b/docs/examples/1.8.x/server-swift/examples/tablesdb/create-row.md @@ -18,6 +18,7 @@ let row = try await tablesDB.createRow( "age": 30, "isAdmin": false ], - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/tablesdb/create-rows.md b/docs/examples/1.8.x/server-swift/examples/tablesdb/create-rows.md index 25ea512590..63fafbd9e5 100644 --- a/docs/examples/1.8.x/server-swift/examples/tablesdb/create-rows.md +++ b/docs/examples/1.8.x/server-swift/examples/tablesdb/create-rows.md @@ -10,6 +10,7 @@ let tablesDB = TablesDB(client) let rowList = try await tablesDB.createRows( databaseId: "", tableId: "", - rows: [] + rows: [], + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/tablesdb/create-transaction.md b/docs/examples/1.8.x/server-swift/examples/tablesdb/create-transaction.md new file mode 100644 index 0000000000..d826446ea2 --- /dev/null +++ b/docs/examples/1.8.x/server-swift/examples/tablesdb/create-transaction.md @@ -0,0 +1,13 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +let tablesDB = TablesDB(client) + +let transaction = try await tablesDB.createTransaction( + ttl: 60 // optional +) + diff --git a/docs/examples/1.8.x/server-swift/examples/tablesdb/decrement-row-column.md b/docs/examples/1.8.x/server-swift/examples/tablesdb/decrement-row-column.md index 196289e994..9c33055202 100644 --- a/docs/examples/1.8.x/server-swift/examples/tablesdb/decrement-row-column.md +++ b/docs/examples/1.8.x/server-swift/examples/tablesdb/decrement-row-column.md @@ -13,6 +13,7 @@ let row = try await tablesDB.decrementRowColumn( rowId: "", column: "", value: 0, // optional - min: 0 // optional + min: 0, // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/tablesdb/delete-row.md b/docs/examples/1.8.x/server-swift/examples/tablesdb/delete-row.md index 5449c74edb..a0a96eea4e 100644 --- a/docs/examples/1.8.x/server-swift/examples/tablesdb/delete-row.md +++ b/docs/examples/1.8.x/server-swift/examples/tablesdb/delete-row.md @@ -10,6 +10,7 @@ let tablesDB = TablesDB(client) let result = try await tablesDB.deleteRow( databaseId: "", tableId: "", - rowId: "" + rowId: "", + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/tablesdb/delete-rows.md b/docs/examples/1.8.x/server-swift/examples/tablesdb/delete-rows.md index 85d8957f78..7235112eca 100644 --- a/docs/examples/1.8.x/server-swift/examples/tablesdb/delete-rows.md +++ b/docs/examples/1.8.x/server-swift/examples/tablesdb/delete-rows.md @@ -10,6 +10,7 @@ let tablesDB = TablesDB(client) let rowList = try await tablesDB.deleteRows( databaseId: "", tableId: "", - queries: [] // optional + queries: [], // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/tablesdb/delete-transaction.md b/docs/examples/1.8.x/server-swift/examples/tablesdb/delete-transaction.md new file mode 100644 index 0000000000..9a5d58bf42 --- /dev/null +++ b/docs/examples/1.8.x/server-swift/examples/tablesdb/delete-transaction.md @@ -0,0 +1,13 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +let tablesDB = TablesDB(client) + +let result = try await tablesDB.deleteTransaction( + transactionId: "" +) + diff --git a/docs/examples/1.8.x/server-swift/examples/tablesdb/get-row.md b/docs/examples/1.8.x/server-swift/examples/tablesdb/get-row.md index 17e6ccbb52..ecadab16aa 100644 --- a/docs/examples/1.8.x/server-swift/examples/tablesdb/get-row.md +++ b/docs/examples/1.8.x/server-swift/examples/tablesdb/get-row.md @@ -11,6 +11,7 @@ let row = try await tablesDB.getRow( databaseId: "", tableId: "", rowId: "", - queries: [] // optional + queries: [], // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/tablesdb/get-transaction.md b/docs/examples/1.8.x/server-swift/examples/tablesdb/get-transaction.md new file mode 100644 index 0000000000..af0bd03b12 --- /dev/null +++ b/docs/examples/1.8.x/server-swift/examples/tablesdb/get-transaction.md @@ -0,0 +1,13 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +let tablesDB = TablesDB(client) + +let transaction = try await tablesDB.getTransaction( + transactionId: "" +) + diff --git a/docs/examples/1.8.x/server-swift/examples/tablesdb/increment-row-column.md b/docs/examples/1.8.x/server-swift/examples/tablesdb/increment-row-column.md index 38aa7581c6..6c35ba8d4a 100644 --- a/docs/examples/1.8.x/server-swift/examples/tablesdb/increment-row-column.md +++ b/docs/examples/1.8.x/server-swift/examples/tablesdb/increment-row-column.md @@ -13,6 +13,7 @@ let row = try await tablesDB.incrementRowColumn( rowId: "", column: "", value: 0, // optional - max: 0 // optional + max: 0, // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/tablesdb/list-rows.md b/docs/examples/1.8.x/server-swift/examples/tablesdb/list-rows.md index 7320147685..92a2813f74 100644 --- a/docs/examples/1.8.x/server-swift/examples/tablesdb/list-rows.md +++ b/docs/examples/1.8.x/server-swift/examples/tablesdb/list-rows.md @@ -10,6 +10,7 @@ let tablesDB = TablesDB(client) let rowList = try await tablesDB.listRows( databaseId: "", tableId: "", - queries: [] // optional + queries: [], // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/tablesdb/list-transactions.md b/docs/examples/1.8.x/server-swift/examples/tablesdb/list-transactions.md new file mode 100644 index 0000000000..c6acb295d6 --- /dev/null +++ b/docs/examples/1.8.x/server-swift/examples/tablesdb/list-transactions.md @@ -0,0 +1,13 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +let tablesDB = TablesDB(client) + +let transactionList = try await tablesDB.listTransactions( + queries: [] // optional +) + diff --git a/docs/examples/1.8.x/server-swift/examples/tablesdb/update-row.md b/docs/examples/1.8.x/server-swift/examples/tablesdb/update-row.md index e06338b3d6..3ebd9e0970 100644 --- a/docs/examples/1.8.x/server-swift/examples/tablesdb/update-row.md +++ b/docs/examples/1.8.x/server-swift/examples/tablesdb/update-row.md @@ -12,6 +12,7 @@ let row = try await tablesDB.updateRow( tableId: "", rowId: "", data: [:], // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/tablesdb/update-rows.md b/docs/examples/1.8.x/server-swift/examples/tablesdb/update-rows.md index 58894f5b85..f18a2a306c 100644 --- a/docs/examples/1.8.x/server-swift/examples/tablesdb/update-rows.md +++ b/docs/examples/1.8.x/server-swift/examples/tablesdb/update-rows.md @@ -11,6 +11,7 @@ let rowList = try await tablesDB.updateRows( databaseId: "", tableId: "", data: [:], // optional - queries: [] // optional + queries: [], // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/tablesdb/update-transaction.md b/docs/examples/1.8.x/server-swift/examples/tablesdb/update-transaction.md new file mode 100644 index 0000000000..faa7d07d63 --- /dev/null +++ b/docs/examples/1.8.x/server-swift/examples/tablesdb/update-transaction.md @@ -0,0 +1,15 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your secret API key + +let tablesDB = TablesDB(client) + +let transaction = try await tablesDB.updateTransaction( + transactionId: "", + commit: false, // optional + rollback: false // optional +) + diff --git a/docs/examples/1.8.x/server-swift/examples/tablesdb/upsert-row.md b/docs/examples/1.8.x/server-swift/examples/tablesdb/upsert-row.md index dc133f6cd1..1b076266a3 100644 --- a/docs/examples/1.8.x/server-swift/examples/tablesdb/upsert-row.md +++ b/docs/examples/1.8.x/server-swift/examples/tablesdb/upsert-row.md @@ -12,6 +12,7 @@ let row = try await tablesDB.upsertRow( tableId: "", rowId: "", data: [:], // optional - permissions: ["read("any")"] // optional + permissions: ["read("any")"], // optional + transactionId: "" // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/tablesdb/upsert-rows.md b/docs/examples/1.8.x/server-swift/examples/tablesdb/upsert-rows.md index fe35f0da91..027087b252 100644 --- a/docs/examples/1.8.x/server-swift/examples/tablesdb/upsert-rows.md +++ b/docs/examples/1.8.x/server-swift/examples/tablesdb/upsert-rows.md @@ -10,6 +10,7 @@ let tablesDB = TablesDB(client) let rowList = try await tablesDB.upsertRows( databaseId: "", tableId: "", - rows: [] + rows: [], + transactionId: "" // optional ) diff --git a/docs/references/databases/create-operations.md b/docs/references/databases/create-operations.md new file mode 100644 index 0000000000..a737b95a55 --- /dev/null +++ b/docs/references/databases/create-operations.md @@ -0,0 +1 @@ +Create multiple operations in a single transaction. \ No newline at end of file diff --git a/docs/references/databases/create-transaction.md b/docs/references/databases/create-transaction.md new file mode 100644 index 0000000000..fdf369a789 --- /dev/null +++ b/docs/references/databases/create-transaction.md @@ -0,0 +1 @@ +Create a new transaction. \ No newline at end of file diff --git a/docs/references/databases/delete-transaction.md b/docs/references/databases/delete-transaction.md new file mode 100644 index 0000000000..f1395c228f --- /dev/null +++ b/docs/references/databases/delete-transaction.md @@ -0,0 +1 @@ +Delete a transaction by its unique ID. \ No newline at end of file diff --git a/docs/references/databases/get-index.md b/docs/references/databases/get-index.md index cdea5b4f27..cdc27fa967 100644 --- a/docs/references/databases/get-index.md +++ b/docs/references/databases/get-index.md @@ -1 +1 @@ -Get index by ID. \ No newline at end of file +Get an index by its unique ID. \ No newline at end of file diff --git a/docs/references/databases/get-transaction.md b/docs/references/databases/get-transaction.md new file mode 100644 index 0000000000..41900f7468 --- /dev/null +++ b/docs/references/databases/get-transaction.md @@ -0,0 +1 @@ +Get a transaction by its unique ID. \ No newline at end of file diff --git a/docs/references/databases/list-transactions.md b/docs/references/databases/list-transactions.md new file mode 100644 index 0000000000..9a63d9f04a --- /dev/null +++ b/docs/references/databases/list-transactions.md @@ -0,0 +1 @@ +List transactions across all databases. \ No newline at end of file diff --git a/docs/references/databases/update-transaction.md b/docs/references/databases/update-transaction.md new file mode 100644 index 0000000000..d9d5f45439 --- /dev/null +++ b/docs/references/databases/update-transaction.md @@ -0,0 +1 @@ +Update a transaction, to either commit or roll back its operations. \ No newline at end of file diff --git a/docs/references/tablesdb/create-operations.md b/docs/references/tablesdb/create-operations.md new file mode 100644 index 0000000000..a737b95a55 --- /dev/null +++ b/docs/references/tablesdb/create-operations.md @@ -0,0 +1 @@ +Create multiple operations in a single transaction. \ No newline at end of file diff --git a/docs/references/tablesdb/create-transaction.md b/docs/references/tablesdb/create-transaction.md new file mode 100644 index 0000000000..fdf369a789 --- /dev/null +++ b/docs/references/tablesdb/create-transaction.md @@ -0,0 +1 @@ +Create a new transaction. \ No newline at end of file diff --git a/docs/references/tablesdb/delete-transaction.md b/docs/references/tablesdb/delete-transaction.md new file mode 100644 index 0000000000..f1395c228f --- /dev/null +++ b/docs/references/tablesdb/delete-transaction.md @@ -0,0 +1 @@ +Delete a transaction by its unique ID. \ No newline at end of file diff --git a/docs/references/tablesdb/get-transaction.md b/docs/references/tablesdb/get-transaction.md new file mode 100644 index 0000000000..41900f7468 --- /dev/null +++ b/docs/references/tablesdb/get-transaction.md @@ -0,0 +1 @@ +Get a transaction by its unique ID. \ No newline at end of file diff --git a/docs/references/tablesdb/list-transactions.md b/docs/references/tablesdb/list-transactions.md new file mode 100644 index 0000000000..9a63d9f04a --- /dev/null +++ b/docs/references/tablesdb/list-transactions.md @@ -0,0 +1 @@ +List transactions across all databases. \ No newline at end of file diff --git a/docs/references/tablesdb/update-transaction.md b/docs/references/tablesdb/update-transaction.md new file mode 100644 index 0000000000..d9d5f45439 --- /dev/null +++ b/docs/references/tablesdb/update-transaction.md @@ -0,0 +1 @@ +Update a transaction, to either commit or roll back its operations. \ No newline at end of file diff --git a/docs/sdks/android/CHANGELOG.md b/docs/sdks/android/CHANGELOG.md index b6b9e4072b..a05da45c4e 100644 --- a/docs/sdks/android/CHANGELOG.md +++ b/docs/sdks/android/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 11.2.1 + +* Add transaction support for Databases and TablesDB + ## 11.1.0 * Deprecate `createVerification` method in `Account` service diff --git a/docs/sdks/apple/CHANGELOG.md b/docs/sdks/apple/CHANGELOG.md index dce2df1804..6d67c4943f 100644 --- a/docs/sdks/apple/CHANGELOG.md +++ b/docs/sdks/apple/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 13.2.1 + +* Add transaction support for Databases and TablesDB + ## 13.1.0 * Deprecate `createVerification` method in `Account` service diff --git a/docs/sdks/cli/CHANGELOG.md b/docs/sdks/cli/CHANGELOG.md index 289c1ef0cb..db3898dd00 100644 --- a/docs/sdks/cli/CHANGELOG.md +++ b/docs/sdks/cli/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 10.2.1 + +* Add transaction support for Databases and TablesDB + ## 10.1.0 * Deprecate `createVerification` method in `Account` service diff --git a/docs/sdks/dart/CHANGELOG.md b/docs/sdks/dart/CHANGELOG.md index c25e66708b..c5ea578d20 100644 --- a/docs/sdks/dart/CHANGELOG.md +++ b/docs/sdks/dart/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 19.2.1 + +* Add transaction support for Databases and TablesDB + ## 19.1.0 * Deprecate `createVerification` method in `Account` service diff --git a/docs/sdks/dotnet/CHANGELOG.md b/docs/sdks/dotnet/CHANGELOG.md index 7bd7d1d267..dfd28ad686 100644 --- a/docs/sdks/dotnet/CHANGELOG.md +++ b/docs/sdks/dotnet/CHANGELOG.md @@ -1,5 +1,13 @@ # Change Log +## 0.21.2 + +* Fix: handle Object[] during array deserialization + +## 0.21.1 + +* Add transaction support for Databases and TablesDB + ## 0.20.0 * Deprecate `createVerification` method in `Account` service diff --git a/docs/sdks/flutter/CHANGELOG.md b/docs/sdks/flutter/CHANGELOG.md index 176efe4a5d..7ac74d0c05 100644 --- a/docs/sdks/flutter/CHANGELOG.md +++ b/docs/sdks/flutter/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 20.2.1 + +* Add transaction support for Databases and TablesDB + ## 20.1.0 * Deprecate `createVerification` method in `Account` service diff --git a/docs/sdks/go/CHANGELOG.md b/docs/sdks/go/CHANGELOG.md index 9191f77aa3..243fdc14a1 100644 --- a/docs/sdks/go/CHANGELOG.md +++ b/docs/sdks/go/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## v0.13.1 + +* Add transaction support for Databases and TablesDB + ## v0.12.0 * Deprecate `createVerification` method in `Account` service diff --git a/docs/sdks/kotlin/CHANGELOG.md b/docs/sdks/kotlin/CHANGELOG.md index 40c32751d7..fe8c8bf46a 100644 --- a/docs/sdks/kotlin/CHANGELOG.md +++ b/docs/sdks/kotlin/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 12.2.1 + +* Add transaction support for Databases and TablesDB + ## 12.1.0 * Deprecate `createVerification` method in `Account` service diff --git a/docs/sdks/nodejs/CHANGELOG.md b/docs/sdks/nodejs/CHANGELOG.md index 7225d3d92f..bd21b954f7 100644 --- a/docs/sdks/nodejs/CHANGELOG.md +++ b/docs/sdks/nodejs/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 20.2.1 + +* Add transaction support for Databases and TablesDB + ## 20.1.0 * Deprecate `createVerification` method in `Account` service diff --git a/docs/sdks/php/CHANGELOG.md b/docs/sdks/php/CHANGELOG.md index b1221264b2..3e5e810e84 100644 --- a/docs/sdks/php/CHANGELOG.md +++ b/docs/sdks/php/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 17.4.1 + +* Add transaction support for Databases and TablesDB + ## 17.3.0 * Deprecate `createVerification` method in `Account` service diff --git a/docs/sdks/python/CHANGELOG.md b/docs/sdks/python/CHANGELOG.md index 584aa5cf5c..7d8327b919 100644 --- a/docs/sdks/python/CHANGELOG.md +++ b/docs/sdks/python/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 13.4.1 + +* Add transaction support for Databases and TablesDB + ## 13.3.0 * Deprecate `createVerification` method in `Account` service diff --git a/docs/sdks/react-native/CHANGELOG.md b/docs/sdks/react-native/CHANGELOG.md index 79ade8cc6c..f1f15907bc 100644 --- a/docs/sdks/react-native/CHANGELOG.md +++ b/docs/sdks/react-native/CHANGELOG.md @@ -1,5 +1,9 @@ # Change log +## 0.17.1 + +* Add transaction support for Databases and TablesDB + ## 0.16.0 * Deprecate `createVerification` method in `Account` service diff --git a/docs/sdks/ruby/CHANGELOG.md b/docs/sdks/ruby/CHANGELOG.md index 0498d7cfb5..22f70c4c3a 100644 --- a/docs/sdks/ruby/CHANGELOG.md +++ b/docs/sdks/ruby/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 19.2.1 + +* Add transaction support for Databases and TablesDB + ## 19.1.0 * Deprecate `createVerification` method in `Account` service diff --git a/docs/sdks/swift/CHANGELOG.md b/docs/sdks/swift/CHANGELOG.md index 3d73a868f3..10119c524b 100644 --- a/docs/sdks/swift/CHANGELOG.md +++ b/docs/sdks/swift/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 13.2.1 + +* Add transaction support for Databases and TablesDB + ## 13.1.0 * Deprecate `createVerification` method in `Account` service diff --git a/docs/sdks/web/CHANGELOG.md b/docs/sdks/web/CHANGELOG.md index a28d868075..338ec9095c 100644 --- a/docs/sdks/web/CHANGELOG.md +++ b/docs/sdks/web/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 21.2.1 + +* Add transaction support for Databases and TablesDB + ## 21.1.0 * Deprecate `createVerification` method in `Account` service diff --git a/src/Appwrite/Databases/TransactionState.php b/src/Appwrite/Databases/TransactionState.php new file mode 100644 index 0000000000..23dc6fc2e9 --- /dev/null +++ b/src/Appwrite/Databases/TransactionState.php @@ -0,0 +1,745 @@ +dbForProject = $dbForProject; + } + + + /** + * Get a document with transaction-aware logic + * + * @param string $collectionId Collection ID + * @param string $documentId Document ID + * @param string|null $transactionId Optional transaction ID + * @param array $queries Optional query filters + * @return Document + * @throws Exception + * @throws Exception\Query + * @throws Timeout + */ + public function getDocument( + string $collectionId, + string $documentId, + ?string $transactionId = null, + array $queries = [] + ): Document { + if ($transactionId === null) { + return $this->dbForProject->getDocument($collectionId, $documentId, $queries); + } + + $state = $this->getTransactionState($transactionId); + + if (isset($state[$collectionId][$documentId])) { + $docState = $state[$collectionId][$documentId]; + + if (!$docState['exists']) { + return new Document(); + } + + if ($docState['action'] === 'create') { + return $this->applyProjection($docState['document'], $queries); + } + + if ($docState['action'] === 'update' || $docState['action'] === 'upsert') { + // Merge with committed version + $committedDoc = $this->dbForProject->getDocument($collectionId, $documentId, $queries); + if (!$committedDoc->isEmpty()) { + foreach ($docState['document']->getAttributes() as $key => $value) { + if ($key !== '$id') { + $committedDoc->setAttribute($key, $value); + } + } + // Reapply projection in case transaction added new fields + return $this->applyProjection($committedDoc, $queries); + } elseif ($docState['action'] === 'upsert') { + return $this->applyProjection($docState['document'], $queries); + } + } + } + + return $this->dbForProject->getDocument($collectionId, $documentId, $queries); + } + + /** + * List documents with transaction-aware logic + * + * @param string $collectionId Collection ID + * @param string|null $transactionId Optional transaction ID + * @param array $queries Optional query filters + * @return array Array of Document objects + * @throws Exception + * @throws Exception\Query + * @throws Timeout + */ + public function listDocuments( + string $collectionId, + ?string $transactionId = null, + array $queries = [] + ): array { + // If no transaction, use normal database retrieval + if ($transactionId === null) { + return $this->dbForProject->find($collectionId, $queries); + } + + $state = $this->getTransactionState($transactionId); + $committedDocs = $this->dbForProject->find($collectionId, $queries); + $documentMap = []; + + // Build map of committed documents + foreach ($committedDocs as $doc) { + $documentMap[$doc->getId()] = $doc; + } + + // Apply transaction state changes + if (isset($state[$collectionId])) { + foreach ($state[$collectionId] as $docId => $docState) { + if (!$docState['exists']) { + // Document was deleted, remove from results + unset($documentMap[$docId]); + } elseif ($docState['action'] === 'create') { + // Document was created, add to results with projection + $documentMap[$docId] = $this->applyProjection($docState['document'], $queries); + } elseif ($docState['action'] === 'update' || $docState['action'] === 'upsert') { + if (isset($documentMap[$docId])) { + // Update existing document + foreach ($docState['document']->getAttributes() as $key => $value) { + if ($key !== '$id') { + $documentMap[$docId]->setAttribute($key, $value); + } + } + // Reapply projection in case transaction added new fields + $documentMap[$docId] = $this->applyProjection($documentMap[$docId], $queries); + } elseif ($docState['action'] === 'upsert') { + // Upsert created a new document, apply projection + $documentMap[$docId] = $this->applyProjection($docState['document'], $queries); + } + } + } + } + + return array_values($documentMap); + } + + /** + * Count documents with transaction-aware logic + * + * @param string $collectionId Collection ID + * @param string|null $transactionId Optional transaction ID + * @param array $queries Optional query filters + * @return int Document count + * @throws Exception + * @throws Exception\Query + * @throws Timeout + */ + public function countDocuments( + string $collectionId, + ?string $transactionId = null, + array $queries = [] + ): int { + if ($transactionId === null) { + return $this->dbForProject->count($collectionId, $queries, APP_LIMIT_COUNT); + } + + $state = $this->getTransactionState($transactionId); + + $baseCount = $this->dbForProject->count($collectionId, $queries, APP_LIMIT_COUNT); + + if (!isset($state[$collectionId])) { + return $baseCount; + } + + $committedDocs = $this->dbForProject->find($collectionId, $queries); + $committedDocIds = []; + foreach ($committedDocs as $doc) { + $committedDocIds[$doc->getId()] = true; + } + + $adjustedCount = $baseCount; + + $filters = $this->extractFilters($queries); + + foreach ($state[$collectionId] as $docId => $docState) { + if (!$docState['exists']) { + if (isset($committedDocIds[$docId])) { + $adjustedCount--; + } + } elseif ($docState['action'] === 'create') { + if ($this->documentMatchesFilters($docState['document'], $filters)) { + $adjustedCount++; + } + } elseif ($docState['action'] === 'update' || $docState['action'] === 'upsert') { + $wasInResults = isset($committedDocIds[$docId]); + $nowMatches = $this->documentMatchesFilters($docState['document'], $filters); + + if (!$wasInResults && $nowMatches && $docState['action'] === 'upsert') { + $adjustedCount++; + } elseif ($wasInResults && !$nowMatches) { + $adjustedCount--; + } elseif (!$wasInResults && $nowMatches) { + // Update shouldn't add a new doc, but upsert might have + if ($docState['action'] === 'upsert') { + $adjustedCount++; + } + } + } + } + + return max(0, $adjustedCount); + } + + /** + * Check if a document exists with transaction-aware logic + * + * @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( + string $collectionId, + string $documentId, + ?string $transactionId = null + ): bool { + $doc = $this->getDocument($collectionId, $documentId, $transactionId); + return !$doc->isEmpty(); + } + + /** + * Apply bulk update to documents in transaction state that match queries + * + * This allows bulk operations within a transaction to see each other's changes. + * + * @param string $collectionId Collection ID + * @param Document $updateData Document with update values + * @param array $queries Query filters to match documents + * @param array &$state Transaction state (passed by reference) + * @return void + */ + public function applyBulkUpdateToState( + string $collectionId, + Document $updateData, + array $queries, + array &$state + ): void { + if (!isset($state[$collectionId])) { + return; + } + + $filters = $this->extractFilters($queries); + + foreach ($state[$collectionId] as $docId => $doc) { + if ($this->documentMatchesFilters($doc, $filters)) { + foreach ($updateData->getArrayCopy() as $key => $value) { + if ($key !== '$id') { + $doc->setAttribute($key, $value); + } + } + } + } + } + + /** + * Apply bulk delete to documents in transaction state that match queries + * + * This allows bulk operations within a transaction to see each other's changes. + * + * @param string $collectionId Collection ID + * @param array $queries Query filters to match documents + * @param array &$state Transaction state (passed by reference) + * @return void + */ + public function applyBulkDeleteToState( + string $collectionId, + array $queries, + array &$state + ): void { + if (!isset($state[$collectionId])) { + return; + } + + $filters = $this->extractFilters($queries); + + foreach ($state[$collectionId] as $docId => $doc) { + if ($this->documentMatchesFilters($doc, $filters)) { + unset($state[$collectionId][$docId]); + } + } + } + + /** + * Apply bulk upsert to documents in transaction state + * + * This merges partial upsert data with full documents from transaction state, + * preventing validation errors when upserting documents created in the same transaction. + * + * @param string $collectionId Collection ID + * @param array $documents Array of Document objects to upsert (can be partial) + * @param array &$state Transaction state (passed by reference) + * @return array Merged documents ready for database upsert + */ + public function applyBulkUpsertToState( + string $collectionId, + array $documents, + array &$state + ): array { + $mergedDocuments = []; + + foreach ($documents as $doc) { + if (!($doc instanceof Document)) { + continue; + } + + $docId = $doc->getId(); + if (!$docId) { + continue; + } + + if (isset($state[$collectionId][$docId])) { + foreach ($doc->getArrayCopy() as $key => $value) { + if ($key !== '$id') { + $state[$collectionId][$docId]->setAttribute($key, $value); + } + } + $mergedDocuments[] = $state[$collectionId][$docId]; + } else { + $mergedDocuments[] = $doc; + } + } + + return $mergedDocuments; + } + + /** + * Get the current state of a transaction by replaying its operations + * + * @param string $transactionId Transaction ID + * @return array State array with structure: [collectionId => [docId => ['action' => ..., 'document' => ..., 'exists' => ...]]] + * @throws Exception + * @throws Exception\Query + * @throws Timeout + */ + private function getTransactionState(string $transactionId): array + { + $transaction = Authorization::skip(fn () => $this->dbForProject->getDocument('transactions', $transactionId)); + if ($transaction->isEmpty() || $transaction->getAttribute('status') !== 'pending') { + return []; + } + + $operations = Authorization::skip(fn () => $this->dbForProject->find('transactionLogs', [ + Query::equal('transactionInternalId', [$transaction->getSequence()]), + Query::orderAsc(), + Query::limit(PHP_INT_MAX) + ])); + + $state = []; + + foreach ($operations as $operation) { + $databaseInternalId = $operation['databaseInternalId']; + $collectionInternalId = $operation['collectionInternalId']; + $collectionId = "database_{$databaseInternalId}_collection_{$collectionInternalId}"; + $documentId = $operation['documentId']; + $action = $operation['action']; + $data = $operation['data']; + + if ($data instanceof Document) { + $data = $data->getArrayCopy(); + } + + switch ($action) { + case 'create': + $docId = $documentId ?? ($data['$id'] ?? null); + if ($docId) { + if (!isset($data['$id'])) { + $data['$id'] = $docId; + } + $state[$collectionId][$docId] = [ + 'action' => 'create', + 'document' => new Document($data), + 'exists' => true + ]; + } + break; + + case 'update': + if (isset($state[$collectionId][$documentId])) { + $existingDocument = $state[$collectionId][$documentId]['document']; + foreach ($data as $key => $value) { + if ($key !== '$id') { + $existingDocument->setAttribute($key, $value); + } + } + // Only set action to 'update' if it's not already 'create' or 'upsert' + $currentAction = $state[$collectionId][$documentId]['action']; + if ($currentAction !== 'create' && $currentAction !== 'upsert') { + $state[$collectionId][$documentId]['action'] = 'update'; + } + } else { + $state[$collectionId][$documentId] = [ + 'action' => 'update', + 'document' => new Document($data), + 'exists' => true + ]; + } + break; + + case 'upsert': + $docId = $documentId ?? ($data['$id'] ?? null); + if (!$docId) { + break; + } + $state[$collectionId][$docId] = [ + 'action' => 'upsert', + 'document' => new Document($data), + 'exists' => true + ]; + break; + + case 'delete': + $state[$collectionId][$documentId] = [ + 'action' => 'delete', + 'exists' => false + ]; + break; + + case 'increment': + case 'decrement': + $attribute = $data['attribute'] ?? null; + $value = $data['value'] ?? 1; + + if ($attribute) { + if (isset($state[$collectionId][$documentId])) { + $existingDocument = $state[$collectionId][$documentId]['document']; + $currentValue = $existingDocument->getAttribute($attribute, 0); + $newValue = $action === 'increment' ? $currentValue + $value : $currentValue - $value; + $existingDocument->setAttribute($attribute, $newValue); + + $currentAction = $state[$collectionId][$documentId]['action']; + if ($currentAction !== 'create' && $currentAction !== 'upsert') { + $state[$collectionId][$documentId]['action'] = 'update'; + } + } else { + $newValue = $action === 'increment' ? $value : -$value; + $state[$collectionId][$documentId] = [ + 'action' => 'update', + 'document' => new Document([$attribute => $newValue]), + 'exists' => true + ]; + } + } + break; + + case 'bulkCreate': + if (\is_array($data)) { + foreach ($data as $doc) { + if ($doc instanceof Document) { + $doc = $doc->getArrayCopy(); + } + $state[$collectionId][$doc['$id']] = [ + 'action' => 'create', + 'document' => new Document($doc), + 'exists' => true + ]; + } + } + break; + + case 'bulkUpdate': + if (isset($data['queries']) && isset($data['data'])) { + $queries = Query::parseQueries($data['queries'] ?? []); + $updateData = $data['data']; + + foreach ($state[$collectionId] ?? [] as $docId => $entry) { + if (!$entry['exists']) { + continue; + } + + $document = $entry['document']; + $filters = $this->extractFilters($queries); + + if ($this->documentMatchesFilters($document, $filters)) { + foreach ($updateData as $key => $value) { + if ($key !== '$id') { + $document->setAttribute($key, $value); + } + } + + $currentAction = $state[$collectionId][$docId]['action']; + if ($currentAction !== 'create' && $currentAction !== 'upsert') { + $state[$collectionId][$docId]['action'] = 'update'; + } + } + } + } + break; + + case 'bulkUpsert': + if (\is_array($data)) { + foreach ($data as $doc) { + if ($doc instanceof Document) { + $doc = $doc->getArrayCopy(); + } + + $docId = $doc['$id'] ?? null; + if (!$docId) { + continue; + } + + if (isset($state[$collectionId][$docId])) { + $existingDocument = $state[$collectionId][$docId]['document']; + foreach ($doc as $key => $value) { + $existingDocument->setAttribute($key, $value); + } + } else { + $state[$collectionId][$docId] = [ + 'action' => 'upsert', + 'document' => new Document($doc), + 'exists' => true + ]; + } + } + } + break; + + case 'bulkDelete': + if (isset($data['queries'])) { + $queries = Query::parseQueries($data['queries'] ?? []); + $filters = $this->extractFilters($queries); + + foreach ($state[$collectionId] ?? [] as $docId => $entry) { + if (!$entry['exists']) { + continue; + } + + $document = $entry['document']; + if ($this->documentMatchesFilters($document, $filters)) { + $state[$collectionId][$docId] = [ + 'action' => 'delete', + 'exists' => false + ]; + } + } + } + break; + } + } + + return $state; + } + + /** + * Apply projection (select) semantics from queries to a document + * + * @param Document $doc Document to apply projection to + * @param array $queries Query array that may contain select queries + * @return Document Projected document + */ + private function applyProjection(Document $doc, array $queries): Document + { + if (empty($queries)) { + return $doc; + } + + $selections = []; + foreach ($queries as $query) { + if ($query->getMethod() === Query::TYPE_SELECT) { + $values = $query->getValues(); + foreach ($values as $value) { + // Skip relationship selections (containing '.') + if (!\str_contains($value, '.')) { + $selections[] = $value; + } + } + } + } + + if (empty($selections) || \in_array('*', $selections)) { + return $doc; + } + + // Create a new document with only selected attributes + $projected = new Document(); + + // Always preserve internal attributes + $projected->setAttribute('$id', $doc->getId()); + $projected->setAttribute('$collection', $doc->getCollection()); + $projected->setAttribute('$createdAt', $doc->getCreatedAt()); + $projected->setAttribute('$updatedAt', $doc->getUpdatedAt()); + if ($doc->offsetExists('$permissions')) { + $projected->setAttribute('$permissions', $doc->getPermissions()); + } + + // Add selected attributes + foreach ($selections as $attribute) { + if ($doc->offsetExists($attribute)) { + $projected->setAttribute($attribute, $doc->getAttribute($attribute)); + } + } + + return $projected; + } + + /** + * Extract only filter queries from a query array + * + * @param array $queries Query array + * @return array Filtered queries + */ + private function extractFilters(array $queries): array + { + $filters = []; + foreach ($queries as $query) { + $method = $query->getMethod(); + if (!\in_array($method, [ + Query::TYPE_LIMIT, + Query::TYPE_OFFSET, + Query::TYPE_CURSOR_AFTER, + Query::TYPE_CURSOR_BEFORE, + Query::TYPE_SELECT, + Query::TYPE_ORDER_ASC, + Query::TYPE_ORDER_DESC + ])) { + $filters[] = $query; + } + } + return $filters; + } + + /** + * Check if a document matches filter queries + * + * @param Document $doc Document to check + * @param array $filters Pre-filtered Query filters (use extractFilters first) + * @return bool True if document matches all filters + */ + private function documentMatchesFilters(Document $doc, array $filters): bool + { + if (empty($filters)) { + return true; + } + + foreach ($filters as $filter) { + $attribute = $filter->getAttribute(); + $values = $filter->getValues(); + $docValue = $doc->getAttribute($attribute); + + switch ($filter->getMethod()) { + case Query::TYPE_EQUAL: + if (!\in_array($docValue, $values)) { + return false; + } + break; + + case Query::TYPE_NOT_EQUAL: + if (\in_array($docValue, $values)) { + return false; + } + break; + + case Query::TYPE_CONTAINS: + $matches = false; + foreach ($values as $value) { + if (\is_array($docValue) && \in_array($value, $docValue)) { + $matches = true; + break; + } + } + if (!$matches) { + return false; + } + break; + + case Query::TYPE_STARTS_WITH: + $matches = false; + foreach ($values as $value) { + if (\is_string($docValue) && \str_starts_with($docValue, $value)) { + $matches = true; + break; + } + } + if (!$matches) { + return false; + } + break; + + case Query::TYPE_ENDS_WITH: + $matches = false; + foreach ($values as $value) { + if (\is_string($docValue) && \str_ends_with($docValue, $value)) { + $matches = true; + break; + } + } + if (!$matches) { + return false; + } + break; + + case Query::TYPE_GREATER: + if (!($docValue > $values[0])) { + return false; + } + break; + + case Query::TYPE_GREATER_EQUAL: + if (!($docValue >= $values[0])) { + return false; + } + break; + + case Query::TYPE_LESSER: + if (!($docValue < $values[0])) { + return false; + } + break; + + case Query::TYPE_LESSER_EQUAL: + if (!($docValue <= $values[0])) { + return false; + } + break; + + case Query::TYPE_IS_NULL: + if (!\is_null($docValue)) { + return false; + } + break; + + case Query::TYPE_IS_NOT_NULL: + if (\is_null($docValue)) { + return false; + } + break; + + case Query::TYPE_BETWEEN: + if (!($docValue >= $values[0] && $docValue <= $values[1])) { + return false; + } + break; + } + } + + return true; + } +} diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index 52282ad7af..6f8744568a 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -36,334 +36,346 @@ class Exception extends \Exception */ /** General */ - public const GENERAL_UNKNOWN = 'general_unknown'; - public const GENERAL_MOCK = 'general_mock'; - public const GENERAL_ACCESS_FORBIDDEN = 'general_access_forbidden'; - public const GENERAL_RESOURCE_BLOCKED = 'general_resource_blocked'; - public const GENERAL_UNKNOWN_ORIGIN = 'general_unknown_origin'; - public const GENERAL_API_DISABLED = 'general_api_disabled'; - public const GENERAL_SERVICE_DISABLED = 'general_service_disabled'; - public const GENERAL_UNAUTHORIZED_SCOPE = 'general_unauthorized_scope'; - public const GENERAL_RATE_LIMIT_EXCEEDED = 'general_rate_limit_exceeded'; - 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_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'; - public const GENERAL_SERVER_ERROR = 'general_server_error'; - public const GENERAL_PROTOCOL_UNSUPPORTED = 'general_protocol_unsupported'; - public const GENERAL_CODES_DISABLED = 'general_codes_disabled'; - public const GENERAL_USAGE_DISABLED = 'general_usage_disabled'; - public const GENERAL_NOT_IMPLEMENTED = 'general_not_implemented'; - public const GENERAL_INVALID_EMAIL = 'general_invalid_email'; - public const GENERAL_INVALID_PHONE = 'general_invalid_phone'; - public const GENERAL_REGION_ACCESS_DENIED = 'general_region_access_denied'; - public const GENERAL_BAD_REQUEST = 'general_bad_request'; + public const string GENERAL_UNKNOWN = 'general_unknown'; + public const string GENERAL_MOCK = 'general_mock'; + public const string GENERAL_ACCESS_FORBIDDEN = 'general_access_forbidden'; + public const string GENERAL_RESOURCE_BLOCKED = 'general_resource_blocked'; + public const string GENERAL_UNKNOWN_ORIGIN = 'general_unknown_origin'; + public const string GENERAL_API_DISABLED = 'general_api_disabled'; + public const string GENERAL_SERVICE_DISABLED = 'general_service_disabled'; + public const string GENERAL_UNAUTHORIZED_SCOPE = 'general_unauthorized_scope'; + public const string GENERAL_RATE_LIMIT_EXCEEDED = 'general_rate_limit_exceeded'; + public const string GENERAL_SMTP_DISABLED = 'general_smtp_disabled'; + public const string GENERAL_PHONE_DISABLED = 'general_phone_disabled'; + public const string GENERAL_ARGUMENT_INVALID = 'general_argument_invalid'; + public const string GENERAL_COLUMN_QUERY_LIMIT_EXCEEDED = 'general_column_query_limit_exceeded'; + public const string GENERAL_ATTRIBUTE_QUERY_LIMIT_EXCEEDED = 'general_attribute_query_limit_exceeded'; + public const string GENERAL_QUERY_INVALID = 'general_query_invalid'; + public const string GENERAL_ROUTE_NOT_FOUND = 'general_route_not_found'; + public const string GENERAL_CURSOR_NOT_FOUND = 'general_cursor_not_found'; + public const string GENERAL_SERVER_ERROR = 'general_server_error'; + public const string GENERAL_PROTOCOL_UNSUPPORTED = 'general_protocol_unsupported'; + public const string GENERAL_CODES_DISABLED = 'general_codes_disabled'; + public const string GENERAL_USAGE_DISABLED = 'general_usage_disabled'; + public const string GENERAL_NOT_IMPLEMENTED = 'general_not_implemented'; + public const string GENERAL_INVALID_EMAIL = 'general_invalid_email'; + public const string GENERAL_INVALID_PHONE = 'general_invalid_phone'; + public const string GENERAL_REGION_ACCESS_DENIED = 'general_region_access_denied'; + public const string GENERAL_BAD_REQUEST = 'general_bad_request'; /** Users */ - public const USER_COUNT_EXCEEDED = 'user_count_exceeded'; - public const USER_CONSOLE_COUNT_EXCEEDED = 'user_console_count_exceeded'; - public const USER_JWT_INVALID = 'user_jwt_invalid'; - public const USER_ALREADY_EXISTS = 'user_already_exists'; - public const USER_BLOCKED = 'user_blocked'; - public const USER_INVALID_TOKEN = 'user_invalid_token'; - public const USER_PASSWORD_RESET_REQUIRED = 'user_password_reset_required'; - public const USER_EMAIL_NOT_WHITELISTED = 'user_email_not_whitelisted'; - public const USER_IP_NOT_WHITELISTED = 'user_ip_not_whitelisted'; - public const USER_INVALID_CODE = 'user_invalid_code'; - public const USER_INVALID_CREDENTIALS = 'user_invalid_credentials'; - public const USER_ANONYMOUS_CONSOLE_PROHIBITED = 'user_anonymous_console_prohibited'; - public const USER_SESSION_ALREADY_EXISTS = 'user_session_already_exists'; - public const USER_NOT_FOUND = 'user_not_found'; - public const USER_PASSWORD_RECENTLY_USED = 'password_recently_used'; - public const USER_PASSWORD_PERSONAL_DATA = 'password_personal_data'; - public const USER_EMAIL_ALREADY_EXISTS = 'user_email_already_exists'; - public const USER_PASSWORD_MISMATCH = 'user_password_mismatch'; - public const USER_SESSION_NOT_FOUND = 'user_session_not_found'; - public const USER_IDENTITY_NOT_FOUND = 'user_identity_not_found'; - public const USER_UNAUTHORIZED = 'user_unauthorized'; - public const USER_AUTH_METHOD_UNSUPPORTED = 'user_auth_method_unsupported'; - public const USER_PHONE_ALREADY_EXISTS = 'user_phone_already_exists'; - public const USER_PHONE_NOT_FOUND = 'user_phone_not_found'; - public const USER_PHONE_NOT_VERIFIED = 'user_phone_not_verified'; - public const USER_EMAIL_NOT_FOUND = 'user_email_not_found'; - public const USER_EMAIL_NOT_VERIFIED = 'user_email_not_verified'; - public const USER_MISSING_ID = 'user_missing_id'; - public const USER_MORE_FACTORS_REQUIRED = 'user_more_factors_required'; - public const USER_INVALID_CHALLENGE = 'user_invalid_challenge'; - public const USER_AUTHENTICATOR_NOT_FOUND = 'user_authenticator_not_found'; - public const USER_AUTHENTICATOR_ALREADY_VERIFIED = 'user_authenticator_already_verified'; - public const USER_RECOVERY_CODES_ALREADY_EXISTS = 'user_recovery_codes_already_exists'; - public const USER_RECOVERY_CODES_NOT_FOUND = 'user_recovery_codes_not_found'; - public const USER_CHALLENGE_REQUIRED = 'user_challenge_required'; - public const USER_OAUTH2_BAD_REQUEST = 'user_oauth2_bad_request'; - public const USER_OAUTH2_UNAUTHORIZED = 'user_oauth2_unauthorized'; - public const USER_OAUTH2_PROVIDER_ERROR = 'user_oauth2_provider_error'; - public const USER_EMAIL_ALREADY_VERIFIED = 'user_email_already_verified'; - public const USER_PHONE_ALREADY_VERIFIED = 'user_phone_already_verified'; - public const USER_DELETION_PROHIBITED = 'user_deletion_prohibited'; - public const USER_TARGET_NOT_FOUND = 'user_target_not_found'; - public const USER_TARGET_ALREADY_EXISTS = 'user_target_already_exists'; - public const USER_API_KEY_AND_SESSION_SET = 'user_key_and_session_set'; + public const string USER_COUNT_EXCEEDED = 'user_count_exceeded'; + public const string USER_CONSOLE_COUNT_EXCEEDED = 'user_console_count_exceeded'; + public const string USER_JWT_INVALID = 'user_jwt_invalid'; + public const string USER_ALREADY_EXISTS = 'user_already_exists'; + public const string USER_BLOCKED = 'user_blocked'; + public const string USER_INVALID_TOKEN = 'user_invalid_token'; + public const string USER_PASSWORD_RESET_REQUIRED = 'user_password_reset_required'; + public const string USER_EMAIL_NOT_WHITELISTED = 'user_email_not_whitelisted'; + public const string USER_IP_NOT_WHITELISTED = 'user_ip_not_whitelisted'; + public const string USER_INVALID_CODE = 'user_invalid_code'; + public const string USER_INVALID_CREDENTIALS = 'user_invalid_credentials'; + public const string USER_ANONYMOUS_CONSOLE_PROHIBITED = 'user_anonymous_console_prohibited'; + public const string USER_SESSION_ALREADY_EXISTS = 'user_session_already_exists'; + public const string USER_NOT_FOUND = 'user_not_found'; + public const string USER_PASSWORD_RECENTLY_USED = 'password_recently_used'; + public const string USER_PASSWORD_PERSONAL_DATA = 'password_personal_data'; + public const string USER_EMAIL_ALREADY_EXISTS = 'user_email_already_exists'; + public const string USER_PASSWORD_MISMATCH = 'user_password_mismatch'; + public const string USER_SESSION_NOT_FOUND = 'user_session_not_found'; + public const string USER_IDENTITY_NOT_FOUND = 'user_identity_not_found'; + public const string USER_UNAUTHORIZED = 'user_unauthorized'; + public const string USER_AUTH_METHOD_UNSUPPORTED = 'user_auth_method_unsupported'; + public const string USER_PHONE_ALREADY_EXISTS = 'user_phone_already_exists'; + public const string USER_PHONE_NOT_FOUND = 'user_phone_not_found'; + public const string USER_PHONE_NOT_VERIFIED = 'user_phone_not_verified'; + public const string USER_EMAIL_NOT_FOUND = 'user_email_not_found'; + public const string USER_EMAIL_NOT_VERIFIED = 'user_email_not_verified'; + public const string USER_MISSING_ID = 'user_missing_id'; + public const string USER_MORE_FACTORS_REQUIRED = 'user_more_factors_required'; + public const string USER_INVALID_CHALLENGE = 'user_invalid_challenge'; + public const string USER_AUTHENTICATOR_NOT_FOUND = 'user_authenticator_not_found'; + public const string USER_AUTHENTICATOR_ALREADY_VERIFIED = 'user_authenticator_already_verified'; + public const string USER_RECOVERY_CODES_ALREADY_EXISTS = 'user_recovery_codes_already_exists'; + public const string USER_RECOVERY_CODES_NOT_FOUND = 'user_recovery_codes_not_found'; + public const string USER_CHALLENGE_REQUIRED = 'user_challenge_required'; + public const string USER_OAUTH2_BAD_REQUEST = 'user_oauth2_bad_request'; + public const string USER_OAUTH2_UNAUTHORIZED = 'user_oauth2_unauthorized'; + public const string USER_OAUTH2_PROVIDER_ERROR = 'user_oauth2_provider_error'; + public const string USER_EMAIL_ALREADY_VERIFIED = 'user_email_already_verified'; + public const string USER_PHONE_ALREADY_VERIFIED = 'user_phone_already_verified'; + public const string USER_DELETION_PROHIBITED = 'user_deletion_prohibited'; + public const string USER_TARGET_NOT_FOUND = 'user_target_not_found'; + public const string USER_TARGET_ALREADY_EXISTS = 'user_target_already_exists'; + public const string USER_API_KEY_AND_SESSION_SET = 'user_key_and_session_set'; - public const API_KEY_EXPIRED = 'api_key_expired'; + public const string API_KEY_EXPIRED = 'api_key_expired'; /** Teams */ - public const TEAM_NOT_FOUND = 'team_not_found'; - public const TEAM_INVITE_NOT_FOUND = 'team_invite_not_found'; - public const TEAM_INVALID_SECRET = 'team_invalid_secret'; - public const TEAM_MEMBERSHIP_MISMATCH = 'team_membership_mismatch'; - public const TEAM_INVITE_MISMATCH = 'team_invite_mismatch'; - public const TEAM_ALREADY_EXISTS = 'team_already_exists'; + public const string TEAM_NOT_FOUND = 'team_not_found'; + public const string TEAM_INVITE_NOT_FOUND = 'team_invite_not_found'; + public const string TEAM_INVALID_SECRET = 'team_invalid_secret'; + public const string TEAM_MEMBERSHIP_MISMATCH = 'team_membership_mismatch'; + public const string TEAM_INVITE_MISMATCH = 'team_invite_mismatch'; + public const string TEAM_ALREADY_EXISTS = 'team_already_exists'; /** Console */ - public const RESOURCE_ALREADY_EXISTS = 'resource_already_exists'; + public const string RESOURCE_ALREADY_EXISTS = 'resource_already_exists'; /** Membership */ - public const MEMBERSHIP_NOT_FOUND = 'membership_not_found'; - public const MEMBERSHIP_ALREADY_CONFIRMED = 'membership_already_confirmed'; - public const MEMBERSHIP_DELETION_PROHIBITED = 'membership_deletion_prohibited'; - public const MEMBERSHIP_DOWNGRADE_PROHIBITED = 'membership_downgrade_prohibited'; + public const string MEMBERSHIP_NOT_FOUND = 'membership_not_found'; + public const string MEMBERSHIP_ALREADY_CONFIRMED = 'membership_already_confirmed'; + public const string MEMBERSHIP_DELETION_PROHIBITED = 'membership_deletion_prohibited'; + public const string MEMBERSHIP_DOWNGRADE_PROHIBITED = 'membership_downgrade_prohibited'; /** Avatars */ - public const AVATAR_SET_NOT_FOUND = 'avatar_set_not_found'; - public const AVATAR_NOT_FOUND = 'avatar_not_found'; - public const AVATAR_IMAGE_NOT_FOUND = 'avatar_image_not_found'; - public const AVATAR_REMOTE_URL_FAILED = 'avatar_remote_url_failed'; - public const AVATAR_ICON_NOT_FOUND = 'avatar_icon_not_found'; - public const AVATAR_SVG_SANITIZATION_FAILED = 'avatar_svg_sanitization_failed'; + public const string AVATAR_SET_NOT_FOUND = 'avatar_set_not_found'; + public const string AVATAR_NOT_FOUND = 'avatar_not_found'; + public const string AVATAR_IMAGE_NOT_FOUND = 'avatar_image_not_found'; + public const string AVATAR_REMOTE_URL_FAILED = 'avatar_remote_url_failed'; + public const string AVATAR_ICON_NOT_FOUND = 'avatar_icon_not_found'; + public const string AVATAR_SVG_SANITIZATION_FAILED = 'avatar_svg_sanitization_failed'; /** Storage */ - public const STORAGE_FILE_ALREADY_EXISTS = 'storage_file_already_exists'; - public const STORAGE_FILE_NOT_FOUND = 'storage_file_not_found'; - public const STORAGE_DEVICE_NOT_FOUND = 'storage_device_not_found'; - public const STORAGE_FILE_EMPTY = 'storage_file_empty'; - public const STORAGE_FILE_TYPE_UNSUPPORTED = 'storage_file_type_unsupported'; - public const STORAGE_INVALID_FILE_SIZE = 'storage_invalid_file_size'; - public const STORAGE_INVALID_FILE = 'storage_invalid_file'; - public const STORAGE_BUCKET_ALREADY_EXISTS = 'storage_bucket_already_exists'; - public const STORAGE_BUCKET_NOT_FOUND = 'storage_bucket_not_found'; - public const STORAGE_INVALID_CONTENT_RANGE = 'storage_invalid_content_range'; - public const STORAGE_INVALID_RANGE = 'storage_invalid_range'; - public const STORAGE_INVALID_APPWRITE_ID = 'storage_invalid_appwrite_id'; - public const STORAGE_FILE_NOT_PUBLIC = 'storage_file_not_public'; + public const string STORAGE_FILE_ALREADY_EXISTS = 'storage_file_already_exists'; + public const string STORAGE_FILE_NOT_FOUND = 'storage_file_not_found'; + public const string STORAGE_DEVICE_NOT_FOUND = 'storage_device_not_found'; + public const string STORAGE_FILE_EMPTY = 'storage_file_empty'; + public const string STORAGE_FILE_TYPE_UNSUPPORTED = 'storage_file_type_unsupported'; + public const string STORAGE_INVALID_FILE_SIZE = 'storage_invalid_file_size'; + public const string STORAGE_INVALID_FILE = 'storage_invalid_file'; + public const string STORAGE_BUCKET_ALREADY_EXISTS = 'storage_bucket_already_exists'; + public const string STORAGE_BUCKET_NOT_FOUND = 'storage_bucket_not_found'; + public const string STORAGE_INVALID_CONTENT_RANGE = 'storage_invalid_content_range'; + public const string STORAGE_INVALID_RANGE = 'storage_invalid_range'; + public const string STORAGE_INVALID_APPWRITE_ID = 'storage_invalid_appwrite_id'; + public const string STORAGE_FILE_NOT_PUBLIC = 'storage_file_not_public'; /** VCS */ - public const INSTALLATION_NOT_FOUND = 'installation_not_found'; - public const PROVIDER_REPOSITORY_NOT_FOUND = 'provider_repository_not_found'; - public const REPOSITORY_NOT_FOUND = 'repository_not_found'; - public const PROVIDER_CONTRIBUTION_CONFLICT = 'provider_contribution_conflict'; - public const GENERAL_PROVIDER_FAILURE = 'general_provider_failure'; + public const string INSTALLATION_NOT_FOUND = 'installation_not_found'; + public const string PROVIDER_REPOSITORY_NOT_FOUND = 'provider_repository_not_found'; + public const string REPOSITORY_NOT_FOUND = 'repository_not_found'; + public const string PROVIDER_CONTRIBUTION_CONFLICT = 'provider_contribution_conflict'; + public const string GENERAL_PROVIDER_FAILURE = 'general_provider_failure'; /** Sites */ - public const SITE_NOT_FOUND = 'site_not_found'; - public const SITE_TEMPLATE_NOT_FOUND = 'site_template_not_found'; + public const string SITE_NOT_FOUND = 'site_not_found'; + public const string SITE_TEMPLATE_NOT_FOUND = 'site_template_not_found'; /** Functions */ - public const FUNCTION_NOT_FOUND = 'function_not_found'; - public const FUNCTION_RUNTIME_UNSUPPORTED = 'function_runtime_unsupported'; - public const FUNCTION_ENTRYPOINT_MISSING = 'function_entrypoint_missing'; - public const FUNCTION_SYNCHRONOUS_TIMEOUT = 'function_synchronous_timeout'; - public const FUNCTION_TEMPLATE_NOT_FOUND = 'function_template_not_found'; - public const FUNCTION_RUNTIME_NOT_DETECTED = 'function_runtime_not_detected'; - public const FUNCTION_EXECUTE_PERMISSION_MISSING = 'function_execute_permission_missing'; + public const string FUNCTION_NOT_FOUND = 'function_not_found'; + public const string FUNCTION_ALREADY_EXISTS = 'function_already_exists'; + public const string FUNCTION_RUNTIME_UNSUPPORTED = 'function_runtime_unsupported'; + public const string FUNCTION_ENTRYPOINT_MISSING = 'function_entrypoint_missing'; + public const string FUNCTION_SYNCHRONOUS_TIMEOUT = 'function_synchronous_timeout'; + public const string FUNCTION_TEMPLATE_NOT_FOUND = 'function_template_not_found'; + public const string FUNCTION_RUNTIME_NOT_DETECTED = 'function_runtime_not_detected'; + public const string FUNCTION_EXECUTE_PERMISSION_MISSING = 'function_execute_permission_missing'; /** Deployments */ - public const DEPLOYMENT_NOT_FOUND = 'deployment_not_found'; + public const string DEPLOYMENT_NOT_FOUND = 'deployment_not_found'; /** Builds */ - public const BUILD_NOT_FOUND = 'build_not_found'; - public const BUILD_NOT_READY = 'build_not_ready'; - public const BUILD_IN_PROGRESS = 'build_in_progress'; - public const BUILD_ALREADY_COMPLETED = 'build_already_completed'; - public const BUILD_CANCELED = 'build_canceled'; - public const BUILD_FAILED = 'build_failed'; + public const string BUILD_NOT_FOUND = 'build_not_found'; + public const string BUILD_NOT_READY = 'build_not_ready'; + public const string BUILD_IN_PROGRESS = 'build_in_progress'; + public const string BUILD_ALREADY_COMPLETED = 'build_already_completed'; + public const string BUILD_CANCELED = 'build_canceled'; + public const string BUILD_FAILED = 'build_failed'; /** Execution */ - public const EXECUTION_NOT_FOUND = 'execution_not_found'; - public const EXECUTION_IN_PROGRESS = 'execution_in_progress'; + public const string EXECUTION_NOT_FOUND = 'execution_not_found'; + public const string EXECUTION_IN_PROGRESS = 'execution_in_progress'; /** Log */ - public const LOG_NOT_FOUND = 'log_not_found'; + public const string LOG_NOT_FOUND = 'log_not_found'; /** Databases */ - public const DATABASE_NOT_FOUND = 'database_not_found'; - public const DATABASE_ALREADY_EXISTS = 'database_already_exists'; - public const DATABASE_TIMEOUT = 'database_timeout'; - public const DATABASE_QUERY_ORDER_NULL = 'database_query_order_null'; + public const string DATABASE_NOT_FOUND = 'database_not_found'; + public const string DATABASE_ALREADY_EXISTS = 'database_already_exists'; + public const string DATABASE_TIMEOUT = 'database_timeout'; + public const string DATABASE_QUERY_ORDER_NULL = 'database_query_order_null'; /** Collections */ - public const COLLECTION_NOT_FOUND = 'collection_not_found'; - public const COLLECTION_ALREADY_EXISTS = 'collection_already_exists'; - public const COLLECTION_LIMIT_EXCEEDED = 'collection_limit_exceeded'; + public const string COLLECTION_NOT_FOUND = 'collection_not_found'; + public const string COLLECTION_ALREADY_EXISTS = 'collection_already_exists'; + public const string 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 string TABLE_NOT_FOUND = 'table_not_found'; + public const string TABLE_ALREADY_EXISTS = 'table_already_exists'; + public const string TABLE_LIMIT_EXCEEDED = 'table_limit_exceeded'; /** Documents */ - public const DOCUMENT_NOT_FOUND = 'document_not_found'; - public const DOCUMENT_INVALID_STRUCTURE = 'document_invalid_structure'; - public const DOCUMENT_MISSING_DATA = 'document_missing_data'; - public const DOCUMENT_MISSING_PAYLOAD = 'document_missing_payload'; - public const DOCUMENT_ALREADY_EXISTS = 'document_already_exists'; - public const DOCUMENT_UPDATE_CONFLICT = 'document_update_conflict'; - public const DOCUMENT_DELETE_RESTRICTED = 'document_delete_restricted'; + public const string DOCUMENT_NOT_FOUND = 'document_not_found'; + public const string DOCUMENT_INVALID_STRUCTURE = 'document_invalid_structure'; + public const string DOCUMENT_MISSING_DATA = 'document_missing_data'; + public const string DOCUMENT_MISSING_PAYLOAD = 'document_missing_payload'; + public const string DOCUMENT_ALREADY_EXISTS = 'document_already_exists'; + public const string DOCUMENT_UPDATE_CONFLICT = 'document_update_conflict'; + public const string 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 string ROW_NOT_FOUND = 'row_not_found'; + public const string ROW_INVALID_STRUCTURE = 'row_invalid_structure'; + public const string ROW_MISSING_DATA = 'row_missing_data'; + public const string ROW_MISSING_PAYLOAD = 'row_missing_payload'; + public const string ROW_ALREADY_EXISTS = 'row_already_exists'; + public const string ROW_UPDATE_CONFLICT = 'row_update_conflict'; + public const string ROW_DELETE_RESTRICTED = 'row_delete_restricted'; /** Attributes */ - public const ATTRIBUTE_NOT_FOUND = 'attribute_not_found'; - public const ATTRIBUTE_UNKNOWN = 'attribute_unknown'; - public const ATTRIBUTE_NOT_AVAILABLE = 'attribute_not_available'; - public const ATTRIBUTE_FORMAT_UNSUPPORTED = 'attribute_format_unsupported'; - public const ATTRIBUTE_DEFAULT_UNSUPPORTED = 'attribute_default_unsupported'; - public const ATTRIBUTE_ALREADY_EXISTS = 'attribute_already_exists'; - public const ATTRIBUTE_LIMIT_EXCEEDED = 'attribute_limit_exceeded'; - public const ATTRIBUTE_VALUE_INVALID = 'attribute_value_invalid'; - public const ATTRIBUTE_TYPE_INVALID = 'attribute_type_invalid'; - public const ATTRIBUTE_INVALID_RESIZE = 'attribute_invalid_resize'; + public const string ATTRIBUTE_NOT_FOUND = 'attribute_not_found'; + public const string ATTRIBUTE_UNKNOWN = 'attribute_unknown'; + public const string ATTRIBUTE_NOT_AVAILABLE = 'attribute_not_available'; + public const string ATTRIBUTE_FORMAT_UNSUPPORTED = 'attribute_format_unsupported'; + public const string ATTRIBUTE_DEFAULT_UNSUPPORTED = 'attribute_default_unsupported'; + public const string ATTRIBUTE_ALREADY_EXISTS = 'attribute_already_exists'; + public const string ATTRIBUTE_LIMIT_EXCEEDED = 'attribute_limit_exceeded'; + public const string ATTRIBUTE_VALUE_INVALID = 'attribute_value_invalid'; + public const string ATTRIBUTE_TYPE_INVALID = 'attribute_type_invalid'; + public const string ATTRIBUTE_INVALID_RESIZE = 'attribute_invalid_resize'; public const ATTRIBUTE_TYPE_NOT_SUPPORTED = 'ATTRIBUTE_TYPE_NOT_SUPPORTED'; /** 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 string COLUMN_NOT_FOUND = 'column_not_found'; + public const string COLUMN_UNKNOWN = 'column_unknown'; + public const string COLUMN_NOT_AVAILABLE = 'column_not_available'; + public const string COLUMN_FORMAT_UNSUPPORTED = 'column_format_unsupported'; + public const string COLUMN_DEFAULT_UNSUPPORTED = 'column_default_unsupported'; + public const string COLUMN_ALREADY_EXISTS = 'column_already_exists'; + public const string COLUMN_LIMIT_EXCEEDED = 'column_limit_exceeded'; + public const string COLUMN_VALUE_INVALID = 'column_value_invalid'; + public const string COLUMN_TYPE_INVALID = 'column_type_invalid'; + public const string COLUMN_INVALID_RESIZE = 'column_invalid_resize'; public const COLUMN_TYPE_NOT_SUPPORTED = 'COLUMN_TYPE_NOT_SUPPORTED'; /** Relationship */ - public const RELATIONSHIP_VALUE_INVALID = 'relationship_value_invalid'; + public const string RELATIONSHIP_VALUE_INVALID = 'relationship_value_invalid'; /** Indexes */ - public const INDEX_NOT_FOUND = 'index_not_found'; - public const INDEX_LIMIT_EXCEEDED = 'index_limit_exceeded'; - public const INDEX_ALREADY_EXISTS = 'index_already_exists'; - public const INDEX_INVALID = 'index_invalid'; - public const INDEX_DEPENDENCY = 'index_dependency'; + public const string INDEX_NOT_FOUND = 'index_not_found'; + public const string INDEX_LIMIT_EXCEEDED = 'index_limit_exceeded'; + public const string INDEX_ALREADY_EXISTS = 'index_already_exists'; + public const string INDEX_INVALID = 'index_invalid'; + public const string INDEX_DEPENDENCY = 'index_dependency'; /** Column Indexes */ - public const COLUMN_INDEX_NOT_FOUND = 'column_index_not_found'; - public const COLUMN_INDEX_LIMIT_EXCEEDED = 'column_index_limit_exceeded'; - public const COLUMN_INDEX_ALREADY_EXISTS = 'column_index_already_exists'; - public const COLUMN_INDEX_INVALID = 'column_index_invalid'; - public const COLUMN_INDEX_DEPENDENCY = 'column_index_dependency'; + public const string COLUMN_INDEX_NOT_FOUND = 'column_index_not_found'; + public const string COLUMN_INDEX_LIMIT_EXCEEDED = 'column_index_limit_exceeded'; + public const string COLUMN_INDEX_ALREADY_EXISTS = 'column_index_already_exists'; + public const string COLUMN_INDEX_INVALID = 'column_index_invalid'; + public const string COLUMN_INDEX_DEPENDENCY = 'column_index_dependency'; + + /** Transactions */ + public const string TRANSACTION_NOT_FOUND = 'transaction_not_found'; + public const string TRANSACTION_ALREADY_EXISTS = 'transaction_already_exists'; + public const string TRANSACTION_INVALID = 'transaction_invalid'; + public const string TRANSACTION_FAILED = 'transaction_failed'; + public const string TRANSACTION_EXPIRED = 'transaction_expired'; + public const string TRANSACTION_CONFLICT = 'transaction_conflict'; + public const string TRANSACTION_LIMIT_EXCEEDED = 'transaction_limit_exceeded'; + public const string TRANSACTION_NOT_READY = 'transaction_not_ready'; + /** Projects */ - public const PROJECT_NOT_FOUND = 'project_not_found'; - public const PROJECT_PROVIDER_DISABLED = 'project_provider_disabled'; - public const PROJECT_PROVIDER_UNSUPPORTED = 'project_provider_unsupported'; - public const PROJECT_ALREADY_EXISTS = 'project_already_exists'; - public const PROJECT_INVALID_SUCCESS_URL = 'project_invalid_success_url'; - public const PROJECT_INVALID_FAILURE_URL = 'project_invalid_failure_url'; - public const PROJECT_RESERVED_PROJECT = 'project_reserved_project'; - public const PROJECT_KEY_EXPIRED = 'project_key_expired'; + public const string PROJECT_NOT_FOUND = 'project_not_found'; + public const string PROJECT_PROVIDER_DISABLED = 'project_provider_disabled'; + public const string PROJECT_PROVIDER_UNSUPPORTED = 'project_provider_unsupported'; + public const string PROJECT_ALREADY_EXISTS = 'project_already_exists'; + public const string PROJECT_INVALID_SUCCESS_URL = 'project_invalid_success_url'; + public const string PROJECT_INVALID_FAILURE_URL = 'project_invalid_failure_url'; + public const string PROJECT_RESERVED_PROJECT = 'project_reserved_project'; + public const string PROJECT_KEY_EXPIRED = 'project_key_expired'; - public const PROJECT_SMTP_CONFIG_INVALID = 'project_smtp_config_invalid'; + public const string PROJECT_SMTP_CONFIG_INVALID = 'project_smtp_config_invalid'; - public const PROJECT_TEMPLATE_DEFAULT_DELETION = 'project_template_default_deletion'; + public const string PROJECT_TEMPLATE_DEFAULT_DELETION = 'project_template_default_deletion'; - public const PROJECT_REGION_UNSUPPORTED = 'project_region_unsupported'; + public const string PROJECT_REGION_UNSUPPORTED = 'project_region_unsupported'; /** Webhooks */ - public const WEBHOOK_NOT_FOUND = 'webhook_not_found'; + public const string WEBHOOK_NOT_FOUND = 'webhook_not_found'; /** Router */ - public const ROUTER_HOST_NOT_FOUND = 'router_host_not_found'; - public const ROUTER_DOMAIN_NOT_CONFIGURED = 'router_domain_not_configured'; + public const string ROUTER_HOST_NOT_FOUND = 'router_host_not_found'; + public const string ROUTER_DOMAIN_NOT_CONFIGURED = 'router_domain_not_configured'; /** Proxy */ - public const RULE_RESOURCE_NOT_FOUND = 'rule_resource_not_found'; - public const RULE_NOT_FOUND = 'rule_not_found'; - public const RULE_ALREADY_EXISTS = 'rule_already_exists'; - public const RULE_VERIFICATION_FAILED = 'rule_verification_failed'; + public const string RULE_RESOURCE_NOT_FOUND = 'rule_resource_not_found'; + public const string RULE_NOT_FOUND = 'rule_not_found'; + public const string RULE_ALREADY_EXISTS = 'rule_already_exists'; + public const string RULE_VERIFICATION_FAILED = 'rule_verification_failed'; /** Keys */ - public const KEY_NOT_FOUND = 'key_not_found'; + public const string KEY_NOT_FOUND = 'key_not_found'; /** Variables */ - public const VARIABLE_NOT_FOUND = 'variable_not_found'; - public const VARIABLE_ALREADY_EXISTS = 'variable_already_exists'; - public const VARIABLE_CANNOT_UNSET_SECRET = 'variable_cannot_unset_secret'; + public const string VARIABLE_NOT_FOUND = 'variable_not_found'; + public const string VARIABLE_ALREADY_EXISTS = 'variable_already_exists'; + public const string VARIABLE_CANNOT_UNSET_SECRET = 'variable_cannot_unset_secret'; /** Platform */ - public const PLATFORM_NOT_FOUND = 'platform_not_found'; + public const string PLATFORM_NOT_FOUND = 'platform_not_found'; /** GraphqQL */ - public const GRAPHQL_NO_QUERY = 'graphql_no_query'; - public const GRAPHQL_TOO_MANY_QUERIES = 'graphql_too_many_queries'; + public const string GRAPHQL_NO_QUERY = 'graphql_no_query'; + public const string GRAPHQL_TOO_MANY_QUERIES = 'graphql_too_many_queries'; /** Migrations */ - public const MIGRATION_NOT_FOUND = 'migration_not_found'; - public const MIGRATION_ALREADY_EXISTS = 'migration_already_exists'; - public const MIGRATION_IN_PROGRESS = 'migration_in_progress'; - public const MIGRATION_PROVIDER_ERROR = 'migration_provider_error'; + public const string MIGRATION_NOT_FOUND = 'migration_not_found'; + 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'; /** Realtime */ - public const REALTIME_MESSAGE_FORMAT_INVALID = 'realtime_message_format_invalid'; - public const REALTIME_TOO_MANY_MESSAGES = 'realtime_too_many_messages'; - public const REALTIME_POLICY_VIOLATION = 'realtime_policy_violation'; + public const string REALTIME_MESSAGE_FORMAT_INVALID = 'realtime_message_format_invalid'; + public const string REALTIME_TOO_MANY_MESSAGES = 'realtime_too_many_messages'; + public const string REALTIME_POLICY_VIOLATION = 'realtime_policy_violation'; /** Health */ - public const HEALTH_QUEUE_SIZE_EXCEEDED = 'health_queue_size_exceeded'; - public const HEALTH_CERTIFICATE_EXPIRED = 'health_certificate_expired'; - public const HEALTH_INVALID_HOST = 'health_invalid_host'; + public const string HEALTH_QUEUE_SIZE_EXCEEDED = 'health_queue_size_exceeded'; + public const string HEALTH_CERTIFICATE_EXPIRED = 'health_certificate_expired'; + public const string HEALTH_INVALID_HOST = 'health_invalid_host'; /** Provider */ - public const PROVIDER_NOT_FOUND = 'provider_not_found'; - public const PROVIDER_ALREADY_EXISTS = 'provider_already_exists'; - public const PROVIDER_INCORRECT_TYPE = 'provider_incorrect_type'; - public const PROVIDER_MISSING_CREDENTIALS = 'provider_missing_credentials'; + public const string PROVIDER_NOT_FOUND = 'provider_not_found'; + public const string PROVIDER_ALREADY_EXISTS = 'provider_already_exists'; + public const string PROVIDER_INCORRECT_TYPE = 'provider_incorrect_type'; + public const string PROVIDER_MISSING_CREDENTIALS = 'provider_missing_credentials'; /** Topic */ - public const TOPIC_NOT_FOUND = 'topic_not_found'; - public const TOPIC_ALREADY_EXISTS = 'topic_already_exists'; + public const string TOPIC_NOT_FOUND = 'topic_not_found'; + public const string TOPIC_ALREADY_EXISTS = 'topic_already_exists'; /** Subscriber */ - public const SUBSCRIBER_NOT_FOUND = 'subscriber_not_found'; - public const SUBSCRIBER_ALREADY_EXISTS = 'subscriber_already_exists'; + public const string SUBSCRIBER_NOT_FOUND = 'subscriber_not_found'; + public const string SUBSCRIBER_ALREADY_EXISTS = 'subscriber_already_exists'; /** Message */ - public const MESSAGE_NOT_FOUND = 'message_not_found'; - public const MESSAGE_MISSING_TARGET = 'message_missing_target'; - public const MESSAGE_ALREADY_SENT = 'message_already_sent'; - public const MESSAGE_ALREADY_PROCESSING = 'message_already_processing'; - public const MESSAGE_ALREADY_FAILED = 'message_already_failed'; - public const MESSAGE_ALREADY_SCHEDULED = 'message_already_scheduled'; - public const MESSAGE_TARGET_NOT_EMAIL = 'message_target_not_email'; - public const MESSAGE_TARGET_NOT_SMS = 'message_target_not_sms'; - public const MESSAGE_TARGET_NOT_PUSH = 'message_target_not_push'; - public const MESSAGE_MISSING_SCHEDULE = 'message_missing_schedule'; + public const string MESSAGE_NOT_FOUND = 'message_not_found'; + public const string MESSAGE_MISSING_TARGET = 'message_missing_target'; + public const string MESSAGE_ALREADY_SENT = 'message_already_sent'; + public const string MESSAGE_ALREADY_PROCESSING = 'message_already_processing'; + public const string MESSAGE_ALREADY_FAILED = 'message_already_failed'; + public const string MESSAGE_ALREADY_SCHEDULED = 'message_already_scheduled'; + public const string MESSAGE_TARGET_NOT_EMAIL = 'message_target_not_email'; + public const string MESSAGE_TARGET_NOT_SMS = 'message_target_not_sms'; + public const string MESSAGE_TARGET_NOT_PUSH = 'message_target_not_push'; + public const string MESSAGE_MISSING_SCHEDULE = 'message_missing_schedule'; /** Targets */ - public const TARGET_PROVIDER_INVALID_TYPE = 'target_provider_invalid_type'; + public const string TARGET_PROVIDER_INVALID_TYPE = 'target_provider_invalid_type'; /** Schedules */ - public const SCHEDULE_NOT_FOUND = 'schedule_not_found'; + public const string SCHEDULE_NOT_FOUND = 'schedule_not_found'; /** Tokens */ - public const TOKEN_NOT_FOUND = 'token_not_found'; - public const TOKEN_EXPIRED = 'token_expired'; - public const TOKEN_RESOURCE_TYPE_INVALID = 'token_resource_type_invalid'; + public const string TOKEN_NOT_FOUND = 'token_not_found'; + public const string TOKEN_EXPIRED = 'token_expired'; + public const string TOKEN_RESOURCE_TYPE_INVALID = 'token_resource_type_invalid'; protected string $type = ''; protected array $errors = []; @@ -371,8 +383,13 @@ class Exception extends \Exception private array $ctas = []; private ?string $view = null; - public function __construct(string $type = Exception::GENERAL_UNKNOWN, string $message = null, int|string $code = null, \Throwable $previous = null, ?string $view = null) - { + public function __construct( + string $type = Exception::GENERAL_UNKNOWN, + string $message = null, + int|string $code = null, + \Throwable $previous = null, + ?string $view = null + ) { $this->errors = Config::getParam('errors'); $this->type = $type; $this->view = $view; @@ -381,7 +398,7 @@ class Exception extends \Exception // Mark string errors like HY001 from PDO as 500 errors if (\is_string($this->code)) { if (\is_numeric($this->code)) { - $this->code = (int) $this->code; + $this->code = (int)$this->code; } else { $this->code = 500; } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Action.php index 0939376c49..b22119fad1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Action.php @@ -53,7 +53,7 @@ abstract class Action extends UtopiaAction /** * Get the SDK group name for the current action. */ - protected function getSdkGroup(): string + protected function getSDKGroup(): string { return $this->isCollectionsAPI() ? 'collections' : 'tables'; } @@ -61,7 +61,7 @@ abstract class Action extends UtopiaAction /** * Get the SDK namespace for the current action. */ - protected function getSdkNamespace(): string + protected function getSDKNamespace(): string { return $this->isCollectionsAPI() ? 'databases' : 'tablesDB'; } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php index 22a90d2653..48124e2a11 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php @@ -66,7 +66,7 @@ abstract class Action extends UtopiaAction * * Can be used for XList operations as well! */ - protected function getSdkGroup(): string + protected function getSDKGroup(): string { return $this->isCollectionsAPI() ? 'attributes' : 'columns'; } @@ -74,7 +74,7 @@ abstract class Action extends UtopiaAction /** * Get the SDK namespace for the current action. */ - protected function getSdkNamespace(): string + protected function getSDKNamespace(): string { return $this->isCollectionsAPI() ? 'databases' : 'tablesDB'; } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php index 6c4be252a0..6c8e5dcf3d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Create.php @@ -42,8 +42,8 @@ class Create extends Action ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/create-boolean-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php index 752e8c6c59..d4724ea551 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Boolean/Update.php @@ -42,8 +42,8 @@ class Update extends Action ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/update-boolean-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php index 5d5b8fe4bf..1f2098e7af 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php @@ -43,8 +43,8 @@ class Create extends Action ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/create-datetime-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php index e1d1d40f75..cb4d0d924b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php @@ -43,8 +43,8 @@ class Update extends Action ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/update-datetime-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php index 8dec7530bf..eb51044323 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php @@ -43,8 +43,8 @@ class Delete extends Action ->label('audits.event', 'attribute.delete') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/delete-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php index bc58ca10af..cbfd66e4d9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php @@ -43,8 +43,8 @@ class Create extends Action ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/create-email-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php index 53300725d7..2446722f7a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php @@ -43,8 +43,8 @@ class Update extends Action ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/update-email-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php index cd22e87d1c..98ed83861d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Create.php @@ -45,8 +45,8 @@ class Create extends Action ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/create-enum-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php index 951e43effe..23dc807360 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php @@ -44,8 +44,8 @@ class Update extends Action ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/update-enum-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php index 2a8253c22c..83deb92edc 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Create.php @@ -45,8 +45,8 @@ class Create extends Action ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/create-float-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php index 327a766cee..7f295a1a94 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php @@ -43,8 +43,8 @@ class Update extends Action ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/update-float-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php index 28ee584778..91fa3582f7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Get.php @@ -47,8 +47,8 @@ class Get extends Action ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/get-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php index aa699b4a49..6e6264466c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php @@ -43,8 +43,8 @@ class Create extends Action ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/create-ip-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php index f61cf21732..6cedf10760 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php @@ -43,8 +43,8 @@ class Update extends Action ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/update-ip-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php index 81a11b0471..090d63c403 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Create.php @@ -45,8 +45,8 @@ class Create extends Action ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/create-integer-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php index 11cfb24943..b6ae79bd8a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php @@ -43,8 +43,8 @@ class Update extends Action ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/update-integer-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php index 4eb3345823..f691fc29cf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php @@ -44,8 +44,8 @@ class Create extends Action ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/create-line-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php index 8fcb867923..52f04ba5bc 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php @@ -43,8 +43,8 @@ class Update extends Action ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/update-line-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php index 47c88497ba..aae715ba1e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php @@ -44,8 +44,8 @@ class Create extends Action ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/create-point-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php index bffe802927..73964ab461 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php @@ -43,8 +43,8 @@ class Update extends Action ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/update-point-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php index 6cc74254ae..6fbbd46d2c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php @@ -44,8 +44,8 @@ class Create extends Action ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/create-polygon-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php index d78bfa8ef0..23eb06f45d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php @@ -43,8 +43,8 @@ class Update extends Action ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/update-polygon-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php index a062816329..75471b826c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php @@ -45,8 +45,8 @@ class Create extends Action ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/create-relationship-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php index c19c4ff046..897cbd434f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php @@ -41,8 +41,8 @@ class Update extends Action ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/update-relationship-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php index 592aa8ee93..1527c4d1d9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php @@ -47,8 +47,8 @@ class Create extends Action ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/create-string-attribute.md', auth: [AuthType::KEY], @@ -95,7 +95,7 @@ class Create extends Action array $plan ): void { if (!App::isDevelopment() && $encrypt && !empty($plan) && !($plan['databasesAllowEncrypt'] ?? false)) { - throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Encrypted string ' . $this->getSdkGroup() . ' are not available on your plan. Please upgrade to create encrypted string ' . $this->getSdkGroup() . '.'); + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Encrypted string ' . $this->getSDKGroup() . ' are not available on your plan. Please upgrade to create encrypted string ' . $this->getSDKGroup() . '.'); } if ($encrypt && $size < APP_DATABASE_ENCRYPT_SIZE_MIN) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php index 03efac1430..8614dfb202 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php @@ -45,8 +45,8 @@ class Update extends Action ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/update-string-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php index 39153b3cb8..ce0175966b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php @@ -43,8 +43,8 @@ class Create extends Action ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/create-url-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php index 7ace4d0683..7ba12ad98a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php @@ -43,8 +43,8 @@ class Update extends Action ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/update-url-attribute.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php index 1852290f76..6daa180df9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php @@ -41,8 +41,8 @@ class XList extends Action ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/list-attributes.md', auth: [AuthType::KEY], @@ -141,7 +141,7 @@ class XList extends Action $response->dynamic(new Document([ 'total' => $total, - $this->getSdkGroup() => $attributes, + $this->getSDKGroup() => $attributes, ]), $this->getResponseModel()); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php index e06dae89bb..b810ce602f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php @@ -52,7 +52,7 @@ class Create extends Action ->label('audits.resource', 'database/{request.databaseId}/collection/{response.$id}') ->label('sdk', new Method( namespace: 'databases', - group: $this->getSdkGroup(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/create-collection.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php index d20570fb43..d124a47289 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php @@ -42,7 +42,7 @@ class Delete extends Action ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( namespace: 'databases', - group: $this->getSdkGroup(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/delete-collection.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php index e05e588201..3da89f352c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php @@ -76,7 +76,7 @@ abstract class Action extends AppwriteAction * * Can be used for XList operations as well! */ - protected function getSdkGroup(): string + protected function getSDKGroup(): string { return $this->isCollectionsAPI() ? 'documents' : 'rows'; } @@ -84,7 +84,7 @@ abstract class Action extends AppwriteAction /** * Get the SDK namespace for the current action. */ - protected function getSdkNamespace(): string + protected function getSDKNamespace(): string { return $this->isCollectionsAPI() ? 'databases' : 'tablesDB'; } @@ -205,6 +205,31 @@ abstract class Action extends AppwriteAction return $this->isCollectionsAPI() ? 'collection' : 'table'; } + /** + * Get the correct attribute/column key for increment/decrement operations. + */ + protected function getAttributeKey(): string + { + return $this->isCollectionsAPI() ? 'attribute' : 'column'; + } + + /** + * Get the key used in ID parameters (e.g., 'collectionId' or 'tableId'). + */ + protected function getGroupId(): string + { + return $this->getCollectionsEventsContext() . 'Id'; + } + + /** + * Get the resource ID key for the current action. + */ + protected function getResourceId(): string + { + $resource = $this->isCollectionsAPI() ? 'document' : 'row'; + return $resource . 'Id'; + } + /** * Remove configured removable attributes from a document. * Used for relationship path handling to remove API-specific attributes. diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php index 289dee5a8d..0b3d0e9fb4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Decrement.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Attribute; +use Appwrite\Auth\Auth; use Appwrite\Event\Event; use Appwrite\Event\StatsUsage; use Appwrite\Extend\Exception; @@ -14,10 +15,12 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use InvalidArgumentException; use Utopia\Database\Database; +use Utopia\Database\Document; use Utopia\Database\Exception\Conflict as ConflictException; use Utopia\Database\Exception\Limit as LimitException; use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Exception\Type as TypeException; +use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; @@ -52,8 +55,8 @@ class Decrement extends Action ->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(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/decrement-document-attribute.md', auth: [AuthType::SESSION, AuthType::JWT, AuthType::ADMIN, AuthType::KEY], @@ -75,15 +78,20 @@ class Decrement extends Action ->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('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('queueForEvents') ->inject('queueForStatsUsage') + ->inject('plan') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $min, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage): 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, StatsUsage $queueForStatsUsage, array $plan): void { + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); @@ -94,6 +102,70 @@ class Decrement extends Action throw new Exception($this->getParentNotFoundException()); } + // Handle transaction staging + if ($transactionId !== null) { + $transaction = ($isAPIKey || $isPrivilegedUser) + ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + : $dbForProject->getDocument('transactions', $transactionId); + if ($transaction->isEmpty() || $transaction->getAttribute('status', '') !== 'pending') { + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid or non‑pending transaction'); + } + + $now = new \DateTime(); + $expiresAt = new \DateTime($transaction->getAttribute('expiresAt', 'now')); + if ($now > $expiresAt) { + throw new Exception(Exception::TRANSACTION_EXPIRED); + } + + // Enforce max operations per transaction + $maxBatch = $plan['databasesTransactionSize'] ?? APP_LIMIT_DATABASE_TRANSACTION; + $existing = $transaction->getAttribute('operations', 0); + if (($existing + 1) > $maxBatch) { + throw new Exception( + Exception::TRANSACTION_LIMIT_EXCEEDED, + 'Transaction already has ' . $existing . ' operations, adding 1 would exceed the maximum of ' . $maxBatch + ); + } + + // Stage the operation in transaction logs + $staged = new Document([ + '$id' => ID::unique(), + 'databaseInternalId' => $database->getSequence(), + 'collectionInternalId' => $collection->getSequence(), + 'transactionInternalId' => $transaction->getSequence(), + 'documentId' => $documentId, + 'action' => 'decrement', + 'data' => [ + $this->getAttributeKey() => $attribute, + 'value' => $value, + 'min' => $min, + ], + ]); + + $dbForProject->withTransaction(function () use ($dbForProject, $transactionId, $staged) { + $dbForProject->createDocument('transactionLogs', $staged); + $dbForProject->increaseDocumentAttribute( + 'transactions', + $transactionId, + 'operations', + 1 + ); + }); + + // Return successful response without actually decrementing + $groupId = $this->getGroupId(); + $mockDocument = new Document([ + '$id' => $documentId, + '$' . $groupId => $collectionId, + '$databaseId' => $databaseId, + $attribute => $value, + ]); + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_OK) + ->dynamic($mockDocument, $this->getResponseModel()); + return; + } + try { $document = $dbForProject->decreaseDocumentAttribute( collection: 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), @@ -107,9 +179,9 @@ class Decrement extends Action } catch (NotFoundException) { throw new Exception($this->getStructureNotFoundException()); } catch (LimitException) { - throw new Exception($this->getLimitException(), $this->getSdkNamespace() . ' "' . $attribute . '" has reached the minimum value of ' . $min); + throw new Exception($this->getLimitException(), $this->getSDKNamespace() . ' "' . $attribute . '" has reached the minimum value of ' . $min); } catch (TypeException) { - throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID, $this->getSdkNamespace() . ' "' . $attribute . '" is not a number'); + throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID, $this->getSDKNamespace() . ' "' . $attribute . '" is not a number'); } catch (InvalidArgumentException $e) { throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, $e->getMessage()); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php index fe8bd2d225..ef64099fa8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Attribute/Increment.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents\Attribute; +use Appwrite\Auth\Auth; use Appwrite\Event\Event; use Appwrite\Event\StatsUsage; use Appwrite\Extend\Exception; @@ -14,10 +15,12 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use InvalidArgumentException; use Utopia\Database\Database; +use Utopia\Database\Document; use Utopia\Database\Exception\Conflict as ConflictException; use Utopia\Database\Exception\Limit as LimitException; use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Exception\Type as TypeException; +use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; @@ -52,8 +55,8 @@ class Increment extends Action ->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(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/increment-document-attribute.md', auth: [AuthType::SESSION, AuthType::JWT, AuthType::ADMIN, AuthType::KEY], @@ -75,15 +78,20 @@ class Increment extends Action ->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('queueForEvents') ->inject('queueForStatsUsage') + ->inject('plan') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $max, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage): 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, StatsUsage $queueForStatsUsage, array $plan): void { + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); @@ -94,6 +102,70 @@ class Increment extends Action throw new Exception($this->getParentNotFoundException()); } + // Handle transaction staging + if ($transactionId !== null) { + $transaction = ($isAPIKey || $isPrivilegedUser) + ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + : $dbForProject->getDocument('transactions', $transactionId); + if ($transaction->isEmpty() || $transaction->getAttribute('status', '') !== 'pending') { + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid or non‑pending transaction'); + } + + $now = new \DateTime(); + $expiresAt = new \DateTime($transaction->getAttribute('expiresAt', 'now')); + if ($now > $expiresAt) { + throw new Exception(Exception::TRANSACTION_EXPIRED); + } + + // Enforce max operations per transaction + $maxBatch = $plan['databasesTransactionSize'] ?? APP_LIMIT_DATABASE_TRANSACTION; + $existing = $transaction->getAttribute('operations', 0); + if (($existing + 1) > $maxBatch) { + throw new Exception( + Exception::TRANSACTION_LIMIT_EXCEEDED, + 'Transaction already has ' . $existing . ' operations, adding 1 would exceed the maximum of ' . $maxBatch + ); + } + + // Stage the operation in transaction logs + $staged = new Document([ + '$id' => ID::unique(), + 'databaseInternalId' => $database->getSequence(), + 'collectionInternalId' => $collection->getSequence(), + 'transactionInternalId' => $transaction->getSequence(), + 'documentId' => $documentId, + 'action' => 'increment', + 'data' => [ + $this->getAttributeKey() => $attribute, + 'value' => $value, + 'max' => $max, + ], + ]); + + $dbForProject->withTransaction(function () use ($dbForProject, $transactionId, $staged) { + $dbForProject->createDocument('transactionLogs', $staged); + $dbForProject->increaseDocumentAttribute( + 'transactions', + $transactionId, + 'operations', + 1 + ); + }); + + // Return successful response without actually incrementing + $groupId = $this->getGroupId(); + $mockDocument = new Document([ + '$id' => $documentId, + '$' . $groupId => $collectionId, + '$databaseId' => $databaseId, + $attribute => $value, + ]); + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_OK) + ->dynamic($mockDocument, $this->getResponseModel()); + return; + } + try { $document = $dbForProject->increaseDocumentAttribute( collection: 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), @@ -107,9 +179,9 @@ class Increment extends Action } catch (NotFoundException) { throw new Exception($this->getStructureNotFoundException()); } catch (LimitException) { - throw new Exception($this->getLimitException(), $this->getSdkNamespace() . ' "' . $attribute . '" has reached the maximum value of ' . $max); + throw new Exception($this->getLimitException(), $this->getSDKNamespace() . ' "' . $attribute . '" has reached the maximum value of ' . $max); } catch (TypeException) { - throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID, $this->getSdkNamespace() . ' "' . $attribute . '" is not a number'); + throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID, $this->getSDKNamespace() . ' "' . $attribute . '" is not a number'); } catch (InvalidArgumentException $e) { throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, $e->getMessage()); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Delete.php index 3467a9d11c..4b1251e016 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Delete.php @@ -17,6 +17,7 @@ use Utopia\Database\Document; use Utopia\Database\Exception\Conflict as ConflictException; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Exception\Restricted as RestrictedException; +use Utopia\Database\Helpers\ID; use Utopia\Database\Query; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -50,8 +51,8 @@ class Delete extends Action ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT) ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/delete-documents.md', auth: [AuthType::ADMIN, AuthType::KEY], @@ -70,6 +71,7 @@ class Delete extends Action ->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('queueForStatsUsage') @@ -81,7 +83,7 @@ class Delete extends Action ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, Event $queueForEvents, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan): void + public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, Event $queueForEvents, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan): void { $database = $dbForProject->getDocument('databases', $databaseId); if ($database->isEmpty()) { @@ -99,15 +101,63 @@ class Delete extends Action ); if ($hasRelationships) { - throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Bulk delete is not supported for ' . $this->getSdkNamespace() . ' with relationship attributes'); + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Bulk delete is not supported for ' . $this->getSDKNamespace() . ' with relationship attributes'); } + $originalQueries = $queries; + try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } + // Handle transaction staging + if ($transactionId !== null) { + $transaction = $dbForProject->getDocument('transactions', $transactionId); + if ($transaction->isEmpty() || $transaction->getAttribute('status', '') !== 'pending') { + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid or non‑pending transaction'); + } + + // Enforce max operations per transaction + $maxBatch = $plan['databasesTransactionSize'] ?? APP_LIMIT_DATABASE_TRANSACTION; + $existing = $transaction->getAttribute('operations', 0); + if (($existing + 1) > $maxBatch) { + throw new Exception( + Exception::TRANSACTION_LIMIT_EXCEEDED, + 'Transaction already has ' . $existing . ' operations, adding 1 would exceed the maximum of ' . $maxBatch + ); + } + + // Stage the operation in transaction logs + $staged = new Document([ + '$id' => ID::unique(), + 'databaseInternalId' => $database->getSequence(), + 'collectionInternalId' => $collection->getSequence(), + 'transactionInternalId' => $transaction->getSequence(), + 'action' => 'bulkDelete', + 'data' => [ + 'queries' => $originalQueries, + ], + ]); + + $dbForProject->withTransaction(function () use ($dbForProject, $transactionId, $staged) { + $dbForProject->createDocument('transactionLogs', $staged); + $dbForProject->increaseDocumentAttribute( + 'transactions', + $transactionId, + 'operations', + ); + }); + + // Return successful response without actually deleting documents + $response->dynamic(new Document([ + $this->getSDKGroup() => [], + 'total' => 0, // Can't predict how many would be deleted + ]), $this->getResponseModel()); + return; + } + $documents = []; try { @@ -139,7 +189,7 @@ class Delete extends Action $response->dynamic(new Document([ 'total' => $modified, - $this->getSdkGroup() => $documents, + $this->getSDKGroup() => $documents, ]), $this->getResponseModel()); $this->triggerBulk( diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Update.php index 65bd255d32..e0d053b976 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Update.php @@ -18,6 +18,7 @@ use Utopia\Database\Exception\Conflict as ConflictException; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Exception\Relationship as RelationshipException; use Utopia\Database\Exception\Structure as StructureException; +use Utopia\Database\Helpers\ID; use Utopia\Database\Query; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; @@ -53,8 +54,8 @@ class Update extends Action ->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(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/update-documents.md', auth: [AuthType::ADMIN, AuthType::KEY], @@ -74,6 +75,7 @@ class Update extends Action ->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('queueForStatsUsage') @@ -85,7 +87,7 @@ class Update extends Action ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string|array $data, array $queries, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, Event $queueForEvents, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan): void + public function action(string $databaseId, string $collectionId, string|array $data, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, Event $queueForEvents, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan): void { $data = \is_string($data) ? \json_decode($data, true) @@ -111,16 +113,18 @@ class Update extends Action ); if ($hasRelationships) { - throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Bulk update is not supported for ' . $this->getSdkNamespace() . ' with relationship attributes'); + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Bulk update is not supported for ' . $this->getSDKNamespace() . ' with relationship attributes'); } + $originalQueries = $queries; + try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - if ($data['$permissions']) { + if (isset($data['$permissions'])) { $validator = new Permissions(); if (!$validator->isValid($data['$permissions'])) { throw new Exception(Exception::GENERAL_BAD_REQUEST, $validator->getDescription()); @@ -129,6 +133,53 @@ class Update extends Action $data = $this->removeReadonlyAttributes($data, privileged: true); + // Handle transaction staging + if ($transactionId !== null) { + $transaction = $dbForProject->getDocument('transactions', $transactionId); + if ($transaction->isEmpty() || $transaction->getAttribute('status', '') !== 'pending') { + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid or non‑pending transaction'); + } + + // Enforce max operations per transaction + $maxBatch = $plan['databasesTransactionSize'] ?? APP_LIMIT_DATABASE_TRANSACTION; + $existing = $transaction->getAttribute('operations', 0); + if (($existing + 1) > $maxBatch) { + throw new Exception( + Exception::TRANSACTION_LIMIT_EXCEEDED, + 'Transaction already has ' . $existing . ' operations, adding 1 would exceed the maximum of ' . $maxBatch + ); + } + + // Stage the operation in transaction logs + $staged = new Document([ + '$id' => ID::unique(), + 'databaseInternalId' => $database->getSequence(), + 'collectionInternalId' => $collection->getSequence(), + 'transactionInternalId' => $transaction->getSequence(), + 'action' => 'bulkUpdate', + 'data' => [ + 'data' => $data, + 'queries' => $originalQueries, + ], + ]); + + $dbForProject->withTransaction(function () use ($dbForProject, $transactionId, $staged) { + $dbForProject->createDocument('transactionLogs', $staged); + $dbForProject->increaseDocumentAttribute( + 'transactions', + $transactionId, + 'operations', + ); + }); + + // Return successful response without actually updating documents + $response->dynamic(new Document([ + $this->getSDKGroup() => [], + 'total' => 0, // Can't predict how many would be updated + ]), $this->getResponseModel()); + return; + } + $documents = []; try { @@ -165,7 +216,7 @@ class Update extends Action $response->dynamic(new Document([ 'total' => $modified, - $this->getSdkGroup() => $documents + $this->getSDKGroup() => $documents ]), $this->getResponseModel()); $this->triggerBulk( diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php index 03e4450f68..a2156484a8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php @@ -18,6 +18,7 @@ use Utopia\Database\Exception\Conflict as ConflictException; use Utopia\Database\Exception\Duplicate as DuplicateException; use Utopia\Database\Exception\Relationship as RelationshipException; use Utopia\Database\Exception\Structure as StructureException; +use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; @@ -51,8 +52,8 @@ class Upsert extends Action ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) ->label('sdk', [ new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/upsert-documents.md', auth: [AuthType::ADMIN, AuthType::KEY], @@ -72,6 +73,7 @@ class Upsert extends Action ->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('queueForStatsUsage') @@ -83,7 +85,7 @@ class Upsert extends Action ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $documents, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, Event $queueForEvents, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan): void + public function action(string $databaseId, string $collectionId, array $documents, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, Event $queueForEvents, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan): void { $database = $dbForProject->getDocument('databases', $databaseId); if ($database->isEmpty()) { @@ -101,7 +103,7 @@ class Upsert extends Action ); if ($hasRelationships) { - throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Bulk upsert is not supported for ' . $this->getSdkNamespace() . ' with relationship attributes'); + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Bulk upsert is not supported for ' . $this->getSDKNamespace() . ' with relationship attributes'); } foreach ($documents as $key => $document) { @@ -109,6 +111,52 @@ class Upsert extends Action $documents[$key] = new Document($document); } + // Handle transaction staging + if ($transactionId !== null) { + $transaction = $dbForProject->getDocument('transactions', $transactionId); + if ($transaction->isEmpty() || $transaction->getAttribute('status', '') !== 'pending') { + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid or non‑pending transaction'); + } + + // Enforce max operations per transaction + $maxBatch = $plan['databasesTransactionSize'] ?? APP_LIMIT_DATABASE_TRANSACTION; + $existing = $transaction->getAttribute('operations', 0); + if (($existing + 1) > $maxBatch) { + throw new Exception( + Exception::TRANSACTION_LIMIT_EXCEEDED, + 'Transaction already has ' . $existing . ' operations, adding 1 would exceed the maximum of ' . $maxBatch + ); + } + + // Stage the operations in transaction logs + $staged = new Document([ + '$id' => ID::unique(), + 'databaseInternalId' => $database->getSequence(), + 'collectionInternalId' => $collection->getSequence(), + 'transactionInternalId' => $transaction->getSequence(), + 'action' => 'bulkUpsert', + 'data' => $documents, + ]); + + $dbForProject->withTransaction(function () use ($dbForProject, $transactionId, $staged) { + $dbForProject->createDocument('transactionLogs', $staged); + $dbForProject->increaseDocumentAttribute( + 'transactions', + $transactionId, + 'operations', + 1 + ); + }); + + // Return successful response without actually upserting documents + $response->dynamic(new Document([ + $this->getSDKGroup() => [], + 'total' => \count($documents), + ]), $this->getResponseModel()); + + return; + } + $upserted = []; try { @@ -144,7 +192,7 @@ class Upsert extends Action $response->dynamic(new Document([ 'total' => $modified, - $this->getSdkGroup() => $upserted + $this->getSDKGroup() => $upserted ]), $this->getResponseModel()); $this->triggerBulk( diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php index a8af1eda86..521190d3dc 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php @@ -63,8 +63,8 @@ class Create extends Action ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) ->label('sdk', [ new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), desc: 'Create document', description: '/docs/references/databases/create-document.md', @@ -82,6 +82,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), ], deprecated: new Deprecated( since: '1.8.0', @@ -89,8 +90,8 @@ class Create extends Action ), ), new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: $this->getBulkActionName(self::getName()), desc: 'Create documents', description: '/docs/references/databases/create-documents.md', @@ -106,6 +107,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), ], deprecated: new Deprecated( since: '1.8.0', @@ -119,6 +121,7 @@ class Create extends Action ->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('user') @@ -127,9 +130,10 @@ class Create extends Action ->inject('queueForRealtime') ->inject('queueForFunctions') ->inject('queueForWebhooks') + ->inject('plan') ->callback($this->action(...)); } - public function action(string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, ?array $documents, UtopiaResponse $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks): 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, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan): void { $data = \is_string($data) ? \json_decode($data, true) @@ -144,7 +148,7 @@ class Create extends Action } if (!empty($data) && !empty($documents)) { // Both single and bulk documents provided - throw new Exception(Exception::GENERAL_BAD_REQUEST, 'You can only send one of the following parameters: data, ' . $this->getSdkGroup()); + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'You can only send one of the following parameters: data, ' . $this->getSDKGroup()); } if (!empty($data) && empty($documentId)) { // Single document provided without document ID @@ -157,12 +161,12 @@ class Create extends Action $documentId = $this->isCollectionsAPI() ? 'documentId' : 'rowId'; throw new Exception( Exception::GENERAL_BAD_REQUEST, - "Param \"$documentId\" is not allowed when creating multiple " . $this->getSdkGroup() . ', set "$id" on each instead.' + "Param \"$documentId\" is not allowed when creating multiple " . $this->getSDKGroup() . ', set "$id" on each instead.' ); } if (!empty($documents) && !empty($permissions)) { // Bulk documents provided with permissions - throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Param "permissions" is disallowed when creating multiple ' . $this->getSdkGroup() . ', set "$permissions" on each instead'); + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Param "permissions" is disallowed when creating multiple ' . $this->getSDKGroup() . ', set "$permissions" on each instead'); } $isBulk = true; @@ -196,7 +200,7 @@ class Create extends Action ); if ($isBulk && $hasRelationships) { - throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Bulk create is not supported for ' . $this->getSdkNamespace() .' with relationship ' . $this->getStructureContext()); + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Bulk create is not supported for ' . $this->getSDKNamespace() .' with relationship ' . $this->getStructureContext()); } $setPermissions = function (Document $document, ?array $permissions) use ($user, $isAPIKey, $isPrivilegedUser, $isBulk) { @@ -361,6 +365,74 @@ class Create extends Action return $document; }, $documents); + // Handle transaction staging + if ($transactionId !== null) { + $transaction = ($isAPIKey || $isPrivilegedUser) + ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + : $dbForProject->getDocument('transactions', $transactionId); + if ($transaction->isEmpty()) { + throw new Exception(Exception::TRANSACTION_NOT_FOUND); + } + if ($transaction->getAttribute('status', '') !== 'pending') { + throw new Exception(Exception::TRANSACTION_NOT_READY); + } + + $now = new \DateTime(); + $expiresAt = new \DateTime($transaction->getAttribute('expiresAt', 'now')); + if ($now > $expiresAt) { + throw new Exception(Exception::TRANSACTION_EXPIRED); + } + + // Enforce max operations per transaction + $maxBatch = $plan['databasesTransactionSize'] ?? APP_LIMIT_DATABASE_TRANSACTION; + $existing = $transaction->getAttribute('operations', 0); + if (($existing + 1) > $maxBatch) { + throw new Exception( + Exception::TRANSACTION_LIMIT_EXCEEDED, + 'Transaction already has ' . $existing . ' operations, adding 1 would exceed the maximum of ' . $maxBatch + ); + } + + $staged = new Document([ + '$id' => ID::unique(), + 'databaseInternalId' => $database->getSequence(), + 'collectionInternalId' => $collection->getSequence(), + 'transactionInternalId' => $transaction->getSequence(), + 'documentId' => $isBulk ? null : $documentId, + 'action' => $isBulk ? 'bulkCreate' : 'create', + 'data' => $isBulk ? $documents : $documents[0], + ]); + + $dbForProject->withTransaction(function () use ($dbForProject, $transactionId, $staged) { + $dbForProject->createDocument('transactionLogs', $staged); + $dbForProject->increaseDocumentAttribute( + 'transactions', + $transactionId, + 'operations', + ); + }); + + // Return successful response without actually creating documents + if ($isBulk) { + $response->dynamic(new Document([ + $this->getSDKGroup() => [], + 'total' => \count($documents), + ]), $this->getBulkResponseModel()); + } else { + $groupId = $this->getGroupId(); + $mockDocument = new Document([ + '$id' => $documents[0]['$id'] ?? $documentId, + '$' . $groupId => $collectionId, + '$databaseId' => $databaseId, + ...$documents[0] + ]); + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_CREATED) + ->dynamic($mockDocument, $this->getResponseModel()); + } + return; + } + try { $dbForProject->withPreserveDates( fn () => $dbForProject->createDocuments( @@ -405,7 +477,7 @@ class Create extends Action if ($isBulk) { $response->dynamic(new Document([ 'total' => count($documents), - $this->getSdkGroup() => $documents + $this->getSDKGroup() => $documents ]), $this->getBulkResponseModel()); $this->triggerBulk( diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php index f34b4630c2..a4cef59e5f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Delete.php @@ -3,6 +3,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents; use Appwrite\Auth\Auth; +use Appwrite\Databases\TransactionState; use Appwrite\Event\Event; use Appwrite\Event\StatsUsage; use Appwrite\Extend\Exception; @@ -13,8 +14,10 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; +use Utopia\Database\Document; use Utopia\Database\Exception\Conflict as ConflictException; use Utopia\Database\Exception\Restricted as RestrictedException; +use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -51,8 +54,8 @@ class Delete extends Action ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT) ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/delete-document.md', auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], @@ -71,16 +74,30 @@ class Delete extends Action ->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('queueForEvents') ->inject('queueForStatsUsage') + ->inject('transactionState') + ->inject('plan') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage): void - { + public function action( + string $databaseId, + string $collectionId, + string $documentId, + ?string $transactionId, + ?\DateTime $requestTimestamp, + UtopiaResponse $response, + Database $dbForProject, + Event $queueForEvents, + StatsUsage $queueForStatsUsage, + TransactionState $transactionState, + array $plan + ): void { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); $isAPIKey = Auth::isAppUser(Authorization::getRoles()); @@ -97,12 +114,73 @@ class Delete extends Action } // Read permission should not be required for delete - $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); + $collectionTableId = 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(); + + if ($transactionId !== null) { + // Use transaction-aware document retrieval to see changes from same transaction + $document = $transactionState->getDocument($collectionTableId, $documentId, $transactionId); + } else { + $document = Authorization::skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); + } if ($document->isEmpty()) { throw new Exception($this->getNotFoundException()); } + // Handle transaction staging + if ($transactionId !== null) { + $transaction = ($isAPIKey || $isPrivilegedUser) + ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + : $dbForProject->getDocument('transactions', $transactionId); + if ($transaction->isEmpty()) { + throw new Exception(Exception::TRANSACTION_NOT_FOUND); + } + if ($transaction->getAttribute('status', '') !== 'pending') { + throw new Exception(Exception::TRANSACTION_NOT_READY); + } + + $now = new \DateTime(); + $expiresAt = new \DateTime($transaction->getAttribute('expiresAt', 'now')); + if ($now > $expiresAt) { + throw new Exception(Exception::TRANSACTION_EXPIRED); + } + + // Enforce max operations per transaction + $maxBatch = $plan['databasesTransactionSize'] ?? APP_LIMIT_DATABASE_TRANSACTION; + $existing = $transaction->getAttribute('operations', 0); + if (($existing + 1) > $maxBatch) { + throw new Exception( + Exception::TRANSACTION_LIMIT_EXCEEDED, + 'Transaction already has ' . $existing . ' operations, adding 1 would exceed the maximum of ' . $maxBatch + ); + } + + // Stage the operation in transaction logs + $staged = new Document([ + '$id' => ID::unique(), + 'databaseInternalId' => $database->getSequence(), + 'collectionInternalId' => $collection->getSequence(), + 'transactionInternalId' => $transaction->getSequence(), + 'documentId' => $documentId, + 'action' => 'delete', + 'data' => [], + ]); + + $dbForProject->withTransaction(function () use ($dbForProject, $transactionId, $staged) { + $dbForProject->createDocument('transactionLogs', $staged); + $dbForProject->increaseDocumentAttribute( + 'transactions', + $transactionId, + 'operations', + 1 + ); + }); + + // Return successful response without actually deleting document + $response->noContent(); + return; + } + try { $dbForProject->withRequestTimestamp($requestTimestamp, function () use ($dbForProject, $database, $collection, $documentId) { $dbForProject->deleteDocument( diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php index 7f621fb33a..3d8cd9198c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Get.php @@ -3,6 +3,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents; use Appwrite\Auth\Auth; +use Appwrite\Databases\TransactionState; use Appwrite\Event\StatsUsage; use Appwrite\Extend\Exception; use Appwrite\SDK\AuthType; @@ -42,8 +43,8 @@ class Get extends Action ->label('scope', 'documents.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/get-document.md', auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], @@ -63,13 +64,15 @@ class Get extends Action ->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('queueForStatsUsage') + ->inject('transactionState') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage): void + public function action(string $databaseId, string $collectionId, string $documentId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState): void { $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -93,13 +96,17 @@ class Get extends Action try { $selects = Query::groupByType($queries)['selections'] ?? []; + $collectionTableId = 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(); - if (! empty($selects)) { + // Use transaction-aware document retrieval if transactionId is provided + if ($transactionId !== null) { + $document = $transactionState->getDocument($collectionTableId, $documentId, $transactionId, $queries); + } elseif (! empty($selects)) { // has selects, allow relationship on documents! - $document = $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId, $queries); + $document = $dbForProject->getDocument($collectionTableId, $documentId, $queries); } else { // has no selects, disable relationship looping on documents! - $document = $dbForProject->skipRelationships(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId, $queries)); + $document = $dbForProject->skipRelationships(fn () => $dbForProject->getDocument($collectionTableId, $documentId, $queries)); } } catch (QueryException $e) { throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php index ed9378f644..241b0c4ede 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Logs/XList.php @@ -48,7 +48,7 @@ class XList extends Action ->label('scope', 'documents.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), + namespace: $this->getSDKNamespace(), group: 'logs', name: self::getName(), description: '/docs/references/databases/get-document-logs.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php index e510aeb089..552c51a5fb 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php @@ -3,6 +3,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents; use Appwrite\Auth\Auth; +use Appwrite\Databases\TransactionState; use Appwrite\Event\Event; use Appwrite\Event\StatsUsage; use Appwrite\Extend\Exception; @@ -55,8 +56,8 @@ class Update extends Action ->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(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/update-document.md', auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], @@ -77,17 +78,19 @@ class Update extends Action ->param('documentId', '', new UID(), 'Document ID.') ->param('data', [], new JSON(), 'Document data as JSON object. Include only attribute 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('queueForEvents') ->inject('queueForStatsUsage') + ->inject('transactionState') + ->inject('plan') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, UtopiaResponse $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage): 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, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan): void { - $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array if (empty($data) && \is_null($permissions)) { @@ -111,7 +114,14 @@ class Update extends Action // Read permission should not be required for update /** @var Document $document */ - $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); + $collectionTableId = 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(); + + if ($transactionId !== null) { + // Use transaction-aware document retrieval to see changes from same transaction + $document = $transactionState->getDocument($collectionTableId, $documentId, $transactionId); + } else { + $document = Authorization::skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); + } if ($document->isEmpty()) { throw new Exception($this->getNotFoundException()); @@ -231,6 +241,72 @@ class Update extends Action ->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) { + $transaction = ($isAPIKey || $isPrivilegedUser) + ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + : $dbForProject->getDocument('transactions', $transactionId); + if ($transaction->isEmpty()) { + throw new Exception(Exception::TRANSACTION_NOT_FOUND); + } + if ($transaction->getAttribute('status', '') !== 'pending') { + throw new Exception(Exception::TRANSACTION_NOT_READY); + } + + $now = new \DateTime(); + $expiresAt = new \DateTime($transaction->getAttribute('expiresAt', 'now')); + if ($now > $expiresAt) { + throw new Exception(Exception::TRANSACTION_EXPIRED); + } + + // Enforce max operations per transaction + $maxBatch = $plan['databasesTransactionSize'] ?? APP_LIMIT_DATABASE_TRANSACTION; + $existing = $transaction->getAttribute('operations', 0); + if (($existing + 1) > $maxBatch) { + throw new Exception( + Exception::TRANSACTION_LIMIT_EXCEEDED, + 'Transaction already has ' . $existing . ' operations, adding 1 would exceed the maximum of ' . $maxBatch + ); + } + + // Stage the operation in transaction logs + $staged = new Document([ + '$id' => ID::unique(), + 'databaseInternalId' => $database->getSequence(), + 'collectionInternalId' => $collection->getSequence(), + 'transactionInternalId' => $transaction->getSequence(), + 'documentId' => $documentId, + 'action' => 'update', + 'data' => $data, + ]); + + $dbForProject->withTransaction(function () use ($dbForProject, $transactionId, $staged) { + $dbForProject->createDocument('transactionLogs', $staged); + $dbForProject->increaseDocumentAttribute( + 'transactions', + $transactionId, + 'operations', + 1 + ); + }); + + // Return successful response without actually updating document + $groupId = $this->getGroupId(); + $mockDocument = new Document([ + '$id' => $documentId, + '$' . $groupId => $collectionId, + '$databaseId' => $databaseId, + ...$document->getArrayCopy(), + ...$data + ]); + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_OK) + ->dynamic($mockDocument, $this->getResponseModel()); + return; + } + + try { $document = $dbForProject->withRequestTimestamp( $requestTimestamp, diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php index 23fbf205dc..f113a99c7a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php @@ -3,6 +3,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents; use Appwrite\Auth\Auth; +use Appwrite\Databases\TransactionState; use Appwrite\Event\Event; use Appwrite\Event\StatsUsage; use Appwrite\Extend\Exception; @@ -57,8 +58,8 @@ class Upsert extends Action ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) ->label('sdk', [ new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/upsert-document.md', auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], @@ -80,16 +81,19 @@ class Upsert extends Action ->param('documentId', '', new CustomId(), 'Document ID.') ->param('data', [], new JSON(), 'Document data as JSON object. Include all required attributes of the document to be created or updated.') ->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('queueForEvents') ->inject('queueForStatsUsage') + ->inject('transactionState') + ->inject('plan') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, UtopiaResponse $response, Document $user, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage): 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, StatsUsage $queueForStatsUsage, TransactionState $transactionState, array $plan): void { $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array @@ -122,9 +126,16 @@ class Upsert extends Action $permissions = Permission::aggregate($permissions, $allowedPermissions); + $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)) { - $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); + if ($transactionId !== null) { + // Use transaction-aware document retrieval to see changes from same transaction + $oldDocument = $transactionState->getDocument($collectionTableId, $documentId, $transactionId); + } else { + $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); + } if ($oldDocument->isEmpty()) { if (!empty($user->getId())) { $defaultPermissions = []; @@ -240,6 +251,69 @@ class Upsert extends Action ->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) { + $transaction = ($isAPIKey || $isPrivilegedUser) + ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + : $dbForProject->getDocument('transactions', $transactionId); + if ($transaction->isEmpty()) { + throw new Exception(Exception::TRANSACTION_NOT_FOUND); + } + if ($transaction->getAttribute('status', '') !== 'pending') { + throw new Exception(Exception::TRANSACTION_NOT_READY); + } + + $now = new \DateTime(); + $expiresAt = new \DateTime($transaction->getAttribute('expiresAt', 'now')); + if ($now > $expiresAt) { + throw new Exception(Exception::TRANSACTION_EXPIRED); + } + + // Enforce max operations per transaction + $maxBatch = $plan['databasesTransactionSize'] ?? APP_LIMIT_DATABASE_TRANSACTION; + $existing = $transaction->getAttribute('operations', 0); + if (($existing + 1) > $maxBatch) { + throw new Exception( + Exception::TRANSACTION_LIMIT_EXCEEDED, + 'Transaction already has ' . $existing . ' operations, adding 1 would exceed the maximum of ' . $maxBatch + ); + } + + // Stage the operation in transaction logs + $staged = new Document([ + '$id' => ID::unique(), + 'databaseInternalId' => $database->getSequence(), + 'collectionInternalId' => $collection->getSequence(), + 'transactionInternalId' => $transaction->getSequence(), + 'documentId' => $documentId, + 'action' => 'upsert', + 'data' => $data, + ]); + + $dbForProject->withTransaction(function () use ($dbForProject, $transactionId, $staged) { + $dbForProject->createDocument('transactionLogs', $staged); + $dbForProject->increaseDocumentAttribute( + 'transactions', + $transactionId, + 'operations', + 1 + ); + }); + + // Return successful response without actually upserting document + $groupId = $this->getGroupId(); + $mockDocument = new Document([ + '$id' => $documentId, + '$' . $groupId => $collectionId, + '$databaseId' => $databaseId, + ...$data + ]); + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_CREATED) + ->dynamic($mockDocument, $this->getResponseModel()); + return; + } + $upserted = []; try { $dbForProject->withPreserveDates(function () use (&$upserted, $dbForProject, $database, $collection, $newDocument) { @@ -264,7 +338,12 @@ class Upsert extends Action $collectionsCache = []; if (empty($upserted[0])) { - $upserted[0] = $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId); + if ($transactionId !== null) { + // For transactions, get the document with transaction changes applied + $upserted[0] = $transactionState->getDocument($collectionTableId, $documentId, $transactionId); + } else { + $upserted[0] = $dbForProject->getDocument($collectionTableId, $documentId); + } } $document = $upserted[0]; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php index 546cbeddd4..a30fed47ed 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php @@ -3,6 +3,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documents; use Appwrite\Auth\Auth; +use Appwrite\Databases\TransactionState; use Appwrite\Event\StatsUsage; use Appwrite\Extend\Exception; use Appwrite\SDK\AuthType; @@ -45,8 +46,8 @@ class XList extends Action ->label('scope', 'documents.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/list-documents.md', auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], @@ -65,13 +66,15 @@ class XList extends Action ->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) ->inject('response') ->inject('dbForProject') ->inject('queueForStatsUsage') + ->inject('transactionState') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage): void + public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState): void { $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -121,17 +124,22 @@ class XList extends Action try { $selectQueries = Query::groupByType($queries)['selections'] ?? []; + $collectionTableId = 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(); - if (! empty($selectQueries)) { + // Use transaction-aware document retrieval if transactionId is provided + if ($transactionId !== null) { + $documents = $transactionState->listDocuments($collectionTableId, $transactionId, $queries); + $total = $transactionState->countDocuments($collectionTableId, $transactionId, $queries); + } elseif (! empty($selectQueries)) { // has selects, allow relationship on documents - $documents = $dbForProject->find('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $queries); + $documents = $dbForProject->find($collectionTableId, $queries); + $total = $dbForProject->count($collectionTableId, $queries, APP_LIMIT_COUNT); } else { // has no selects, disable relationship loading on documents /* @type Document[] $documents */ - $documents = $dbForProject->skipRelationships(fn () => $dbForProject->find('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $queries)); + $documents = $dbForProject->skipRelationships(fn () => $dbForProject->find($collectionTableId, $queries)); + $total = $dbForProject->count($collectionTableId, $queries, APP_LIMIT_COUNT); } - - $total = $dbForProject->count('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $queries, APP_LIMIT_COUNT); } catch (OrderException $e) { $documents = $this->isCollectionsAPI() ? 'documents' : 'rows'; $attribute = $this->isCollectionsAPI() ? 'attribute' : 'column'; @@ -161,7 +169,7 @@ class XList extends Action $response->dynamic(new Document([ 'total' => $total, // rows or documents - $this->getSdkGroup() => $documents, + $this->getSDKGroup() => $documents, ]), $this->getResponseModel()); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php index af4b6bf733..89739570c7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php @@ -37,7 +37,7 @@ class Get extends Action ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: 'databases', - group: $this->getSdkGroup(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/get-collection.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php index f136fdd29b..400d716e41 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Action.php @@ -52,7 +52,7 @@ abstract class Action extends UtopiaAction /** * Get the SDK group name for the current action. */ - final protected function getSdkGroup(): string + final protected function getSDKGroup(): string { return 'indexes'; } @@ -60,7 +60,7 @@ abstract class Action extends UtopiaAction /** * Get the SDK namespace for the current action. */ - final protected function getSdkNamespace(): string + final protected function getSDKNamespace(): string { return $this->isCollectionsAPI() ? 'databases' : 'tablesDB'; } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php index 733259f091..0c6ef8bb23 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Create.php @@ -51,8 +51,8 @@ class Create extends Action ->label('audits.event', 'index.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/create-index.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php index 9ba4c98046..2bccfdfb52 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Delete.php @@ -46,8 +46,8 @@ class Delete extends Action ->label('audits.event', 'index.delete') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/delete-index.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php index 9e05cc79c7..3d118d1922 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/Get.php @@ -37,8 +37,8 @@ class Get extends Action ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/get-index.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php index c0aa9457e7..60e52f883a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php @@ -42,8 +42,8 @@ class XList extends Action ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/list-indexes.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php index fefc5ba5a0..b202120bad 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Logs/XList.php @@ -49,7 +49,7 @@ class XList extends Action ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: 'databases', - group: $this->getSdkGroup(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/get-collection-logs.md', auth: [AuthType::ADMIN], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php index 5bf740d7d1..49870002ce 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php @@ -45,7 +45,7 @@ class Update extends Action ->label('audits.resource', 'database/{request.databaseId}/collections/{request.collectionId}') ->label('sdk', new Method( namespace: 'databases', - group: $this->getSdkGroup(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/update-collection.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php index f2f7a2233a..b4cc5470d9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php @@ -44,7 +44,7 @@ class XList extends Action ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( namespace: 'databases', - group: $this->getSdkGroup(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/databases/list-collections.md', auth: [AuthType::KEY], @@ -121,7 +121,7 @@ class XList extends Action $response->dynamic(new Document([ 'total' => $total, - $this->getSdkGroup() => $collections, + $this->getSDKGroup() => $collections, ]), $this->getResponseModel()); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Action.php new file mode 100644 index 0000000000..8915ae6141 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Action.php @@ -0,0 +1,66 @@ +context = TABLES; + } + return parent::setHttpPath($path); + } + + /** + * Get the current API context. + */ + protected function getContext(): string + { + return $this->context; + } + + /** + * Determine if the current action is for the Collections API. + */ + protected function isCollectionsAPI(): bool + { + return $this->getContext() === COLLECTIONS; + } + + /** + * Get the key used in event parameters (e.g., 'collectionId' or 'tableId'). + */ + protected function getGroupId(): string + { + return $this->getContext() . 'Id'; + } + + /** + * Get the resource type for the current action (either 'document' or 'row'). + */ + protected function getResource(): string + { + return $this->isCollectionsAPI() ? 'document' : 'row'; + } + + /** + * Get the resource ID key for the current action. + */ + protected function getResourceId(): string + { + return $this->getResource() . 'Id'; + } + + protected function getAttributeKey(): string + { + return $this->isCollectionsAPI() ? 'attribute' : 'column'; + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php new file mode 100644 index 0000000000..c4c5bf8b51 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php @@ -0,0 +1,88 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/transactions') + ->desc('Create transaction') + ->groups(['api', 'database', 'transactions']) + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: 'transactions', + name: 'createTransaction', + description: '/docs/references/databases/create-transaction.md', + auth: [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') + ->callback($this->action(...)); + } + + public function action(int $ttl, UtopiaResponse $response, Database $dbForProject, Document $user): void + { + $permissions = []; + if (!empty($user->getId())) { + $allowedPermissions = [ + Database::PERMISSION_READ, + Database::PERMISSION_UPDATE, + Database::PERMISSION_DELETE, + ]; + + foreach ($allowedPermissions as $permission) { + $permissions[] = (new Permission($permission, 'user', $user->getId()))->toString(); + } + } + + $transaction = Authorization::skip(fn () => $dbForProject->createDocument('transactions', new Document([ + '$id' => ID::unique(), + '$permissions' => $permissions, + 'status' => 'pending', + 'operations' => 0, + 'expiresAt' => DateTime::addSeconds(new \DateTime(), $ttl), + ]))); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_CREATED) + ->dynamic($transaction, UtopiaResponse::MODEL_TRANSACTION); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Delete.php new file mode 100644 index 0000000000..a5d2562572 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Delete.php @@ -0,0 +1,74 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) + ->setHttpPath('/v1/databases/transactions/:transactionId') + ->desc('Delete transaction') + ->groups(['api', 'database', 'transactions']) + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: 'transactions', + name: 'deleteTransaction', + description: '/docs/references/databases/delete-transaction.md', + auth: [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(...)); + } + + public function action(string $transactionId, UtopiaResponse $response, Database $dbForProject, DeleteEvent $queueForDeletes): void + { + $transaction = $dbForProject->getDocument('transactions', $transactionId); + + if ($transaction->isEmpty()) { + throw new Exception(Exception::TRANSACTION_NOT_FOUND); + } + + $dbForProject->deleteDocument('transactions', $transactionId); + + $queueForDeletes + ->setType(DELETE_TYPE_DOCUMENT) + ->setDocument($transaction); + + $response->noContent(); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Get.php new file mode 100644 index 0000000000..1d4d22baa1 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Get.php @@ -0,0 +1,68 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/transactions/:transactionId') + ->desc('Get transaction') + ->groups(['api', 'database', 'transactions']) + ->label('scope', 'rows.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: 'transactions', + name: 'getTransaction', + description: '/docs/references/databases/get-transaction.md', + auth: [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(...)); + } + + public function action(string $transactionId, UtopiaResponse $response, Database $dbForProject): void + { + $transaction = $dbForProject->getDocument('transactions', $transactionId); + + if ($transaction->isEmpty()) { + throw new Exception(Exception::TRANSACTION_NOT_FOUND); + } + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_OK) + ->dynamic($transaction, UtopiaResponse::MODEL_TRANSACTION); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php new file mode 100644 index 0000000000..bd94c1c7eb --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php @@ -0,0 +1,247 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/databases/transactions/:transactionId/operations') + ->desc('Create operations') + ->groups(['api', 'database', 'transactions']) + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: 'transactions', + name: 'createOperations', + description: '/docs/references/databases/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: 'legacy')), 'Array of staged operations.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('transactionState') + ->inject('plan') + ->callback($this->action(...)); + } + + public function action(string $transactionId, array $operations, UtopiaResponse $response, Database $dbForProject, TransactionState $transactionState, array $plan): void + { + if (empty($operations)) { + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Operations array cannot be empty'); + } + + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + + // API keys and admins can read any transaction, regular users need permissions + $transaction = ($isAPIKey || $isPrivilegedUser) + ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + : $dbForProject->getDocument('transactions', $transactionId); + if ($transaction->isEmpty()) { + throw new Exception(Exception::TRANSACTION_NOT_FOUND); + } + if ($transaction->getAttribute('status', '') !== 'pending') { + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid or non‑pending transaction'); + } + + $now = new \DateTime(); + $expiresAt = new \DateTime($transaction->getAttribute('expiresAt', 'now')); + if ($now > $expiresAt) { + throw new Exception(Exception::TRANSACTION_EXPIRED); + } + + $maxBatch = $plan['databasesTransactionSize'] ?? APP_LIMIT_DATABASE_TRANSACTION; + $existing = $transaction->getAttribute('operations', 0); + + if (($existing + \count($operations)) > $maxBatch) { + throw new Exception( + Exception::TRANSACTION_LIMIT_EXCEEDED, + 'Transaction already has ' . $existing . ' operations, adding ' . \count($operations) . ' would exceed the maximum of ' . $maxBatch + ); + } + + $databases = $collections = $staged = $dependants = []; + foreach ($operations as $operation) { + if (!$isAPIKey && !$isPrivilegedUser && \in_array($operation['action'], [ + 'bulkCreate', + 'bulkUpdate', + 'bulkUpsert', + 'bulkDelete' + ])) { + throw new Exception(Exception::USER_UNAUTHORIZED); + } + + $database = $databases[$operation['databaseId']] ??= Authorization::skip(fn () => $dbForProject->getDocument('databases', $operation['databaseId'])); + if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = $collections[$operation[$this->getGroupId()]] ??= + Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $operation[$this->getGroupId()])); + + if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + if (\in_array($operation['action'], ['bulkCreate', 'bulkUpdate', 'bulkUpsert', 'bulkDelete'])) { + $hasRelationships = \array_filter( + $collection->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + if ($hasRelationships) { + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Bulk operations are not supported for ' . $this->getGroupId() . ' with relationship attributes'); + } + } + + // For update, upsert, delete, increment, decrement, check document existence first + $document = null; + if (\in_array($operation['action'], ['update', 'delete', 'upsert', 'increment', 'decrement'])) { + $documentId = $operation[$this->getResourceId()] ?? null; + if (empty($documentId)) { + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Document ID is required for ' . $operation['action'] . ' operations'); + } + + $collectionKey = 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(); + $isDependant = isset($dependants[$collectionKey][$documentId]); + + $document = $transactionState->getDocument($collectionKey, $documentId, $transactionId); + if ($document->isEmpty() && !$isDependant && $operation['action'] !== 'upsert') { + throw new Exception(Exception::DOCUMENT_NOT_FOUND); + } + } + + // Bulk operations skip permission validation entirely (API key/admin only, already checked above) + if (!\in_array($operation['action'], ['bulkCreate', 'bulkUpdate', 'bulkUpsert', 'bulkDelete'])) { + $permissionType = match ($operation['action']) { + 'create' => Database::PERMISSION_CREATE, + 'update', 'increment', 'decrement' => Database::PERMISSION_UPDATE, + 'delete' => Database::PERMISSION_DELETE, + 'upsert' => ($document && !$document->isEmpty()) ? Database::PERMISSION_UPDATE : Database::PERMISSION_CREATE, + default => throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid action: ' . $operation['action']) + }; + + // For individual operations, enforce permissions unless using API key/admin + if (!$isAPIKey && !$isPrivilegedUser) { + $documentSecurity = $collection->getAttribute('documentSecurity', false); + $validator = new Authorization($permissionType); + $collectionValid = $validator->isValid($collection->getPermissionsByType($permissionType)); + $documentValid = false; + if ($document !== null && !$document->isEmpty() && $documentSecurity) { + if ($permissionType === Database::PERMISSION_UPDATE) { + $documentValid = $validator->isValid($document->getUpdate()); + } elseif ($permissionType === Database::PERMISSION_DELETE) { + $documentValid = $validator->isValid($document->getDelete()); + } + } + + if ($permissionType === Database::PERMISSION_CREATE || !$documentSecurity) { + if (!$collectionValid) { + throw new Exception(Exception::USER_UNAUTHORIZED); + } + } else { + if (!$collectionValid && !$documentValid) { + throw new Exception(Exception::USER_UNAUTHORIZED); + } + } + + // Users can only set permissions for roles they have + if (isset($operation['data']['$permissions'])) { + $permissions = $operation['data']['$permissions']; + $roles = Authorization::getRoles(); + foreach (Database::PERMISSIONS as $type) { + foreach ($permissions as $permission) { + $permission = Permission::parse($permission); + if ($permission->getPermission() != $type) { + continue; + } + $role = (new Role( + $permission->getRole(), + $permission->getIdentifier(), + $permission->getDimension() + ))->toString(); + if (!Authorization::isRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); + } + } + } + } + } + } + + $staged[] = new Document([ + '$id' => ID::unique(), + 'databaseInternalId' => $database->getSequence(), + 'collectionInternalId' => $collection->getSequence(), + 'transactionInternalId' => $transaction->getSequence(), + 'documentId' => $operation[$this->getResourceId()] ?? null, + 'action' => $operation['action'], + 'data' => $operation['data'] ?? [], + ]); + + // Track create operations for dependent update/increment/decrement/delete operations in same batch + if ($operation['action'] === 'create') { + $collectionKey = 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(); + $documentId = $operation[$this->getResourceId()] ?? null; + if ($documentId) { + $dependants[$collectionKey][$documentId] = true; + } + } + } + + $transaction = Authorization::skip(fn () => $dbForProject->withTransaction(function () use ($dbForProject, $transactionId, $staged, $existing, $operations) { + $dbForProject->createDocuments('transactionLogs', $staged); + return $dbForProject->increaseDocumentAttribute( + 'transactions', + $transactionId, + 'operations', + \count($operations) + ); + })); + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_CREATED) + ->dynamic($transaction, UtopiaResponse::MODEL_TRANSACTION); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php new file mode 100644 index 0000000000..6e2bd63827 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php @@ -0,0 +1,878 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/databases/transactions/:transactionId') + ->desc('Update transaction') + ->groups(['api', 'database', 'transactions']) + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: 'transactions', + name: 'updateTransaction', + description: '/docs/references/databases/update-transaction.md', + auth: [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('response') + ->inject('dbForProject') + ->inject('user') + ->inject('transactionState') + ->inject('queueForDeletes') + ->inject('queueForEvents') + ->inject('queueForStatsUsage') + ->inject('queueForRealtime') + ->inject('queueForFunctions') + ->inject('queueForWebhooks') + ->callback($this->action(...)); + } + + /** + * @param string $transactionId + * @param bool $commit + * @param bool $rollback + * @param UtopiaResponse $response + * @param Database $dbForProject + * @param Document $user + * @param TransactionState $transactionState + * @param Delete $queueForDeletes + * @param Event $queueForEvents + * @param StatsUsage $queueForStatsUsage + * @param Event $queueForRealtime + * @param Event $queueForFunctions + * @param Event $queueForWebhooks + * @return void + * @throws ConflictException + * @throws Exception + * @throws \Throwable + * @throws \Utopia\Database\Exception + * @throws Authorization + * @throws Structure + * @throws \Utopia\Exception + */ + public function action(string $transactionId, bool $commit, bool $rollback, UtopiaResponse $response, Database $dbForProject, Document $user, TransactionState $transactionState, Delete $queueForDeletes, Event $queueForEvents, StatsUsage $queueForStatsUsage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks): void + { + if (!$commit && !$rollback) { + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Either commit or rollback must be true'); + } + if ($commit && $rollback) { + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Cannot commit and rollback at the same time'); + } + + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + + $transaction = ($isAPIKey || $isPrivilegedUser) + ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + : $dbForProject->getDocument('transactions', $transactionId); + if ($transaction->isEmpty()) { + throw new Exception(Exception::TRANSACTION_NOT_FOUND); + } + if ($transaction->getAttribute('status', '') !== 'pending') { + throw new Exception(Exception::TRANSACTION_NOT_READY); + } + + $now = new \DateTime(); + $expiresAt = new \DateTime($transaction->getAttribute('expiresAt', 'now')); + if ($now > $expiresAt) { + throw new Exception(Exception::TRANSACTION_EXPIRED); + } + + if ($commit) { + + $operations = []; + $totalOperations = 0; + $databaseOperations = []; + + try { + $dbForProject->withTransaction(function () use ($dbForProject, $transactionState, $queueForDeletes, $transactionId, &$transaction, &$operations, &$totalOperations, &$databaseOperations, $queueForEvents, $queueForStatsUsage, $queueForRealtime, $queueForFunctions, $queueForWebhooks) { + Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + 'status' => 'committing', + ]))); + + $operations = Authorization::skip(fn () => $dbForProject->find('transactionLogs', [ + Query::equal('transactionInternalId', [$transaction->getSequence()]), + Query::orderAsc(), + Query::limit(PHP_INT_MAX), + ])); + + $state = []; + + foreach ($operations as $operation) { + $databaseInternalId = $operation['databaseInternalId']; + $collectionInternalId = $operation['collectionInternalId']; + $collectionId = "database_{$databaseInternalId}_collection_{$collectionInternalId}"; + $documentId = $operation['documentId']; + $createdAt = new \DateTime($operation['$createdAt']); + $action = $operation['action']; + $data = $operation['data']; + + if ($action === 'delete' && $documentId && empty($data)) { + $doc = $dbForProject->getDocument($collectionId, $documentId); + if (!$doc->isEmpty()) { + $operation['data'] = $doc->getArrayCopy(); + $data = $operation['data']; + } + } + + if (!\in_array($action, ['bulkCreate', 'bulkUpdate', 'bulkUpsert', 'bulkDelete'])) { + $totalOperations++; + $databaseOperations[$databaseInternalId] = ($databaseOperations[$databaseInternalId] ?? 0) + 1; + } + + if ($data instanceof Document) { + $data = $data->getArrayCopy(); + } + + switch ($action) { + case 'create': + $this->handleCreateOperation($dbForProject, $collectionId, $documentId, $data, $createdAt, $state); + break; + case 'update': + $this->handleUpdateOperation($dbForProject, $collectionId, $documentId, $data, $createdAt, $state); + break; + case 'upsert': + $this->handleUpsertOperation($dbForProject, $collectionId, $documentId, $data, $createdAt, $state); + break; + case 'delete': + $this->handleDeleteOperation($dbForProject, $collectionId, $documentId, $createdAt, $state); + break; + case 'increment': + $this->handleIncrementOperation($dbForProject, $collectionId, $documentId, $data, $createdAt, $state); + break; + case 'decrement': + $this->handleDecrementOperation($dbForProject, $collectionId, $documentId, $data, $createdAt, $state); + break; + case 'bulkCreate': + $count = $this->handleBulkCreateOperation($dbForProject, $collectionId, $data, $createdAt, $state); + $totalOperations += $count; + $databaseOperations[$databaseInternalId] = ($databaseOperations[$databaseInternalId] ?? 0) + $count; + break; + case 'bulkUpdate': + $count = $this->handleBulkUpdateOperation($dbForProject, $transactionState, $collectionId, $data, $createdAt, $state); + $totalOperations += $count; + $databaseOperations[$databaseInternalId] = ($databaseOperations[$databaseInternalId] ?? 0) + $count; + break; + case 'bulkUpsert': + $count = $this->handleBulkUpsertOperation($dbForProject, $transactionState, $collectionId, $data, $createdAt, $state); + $totalOperations += $count; + $databaseOperations[$databaseInternalId] = ($databaseOperations[$databaseInternalId] ?? 0) + $count; + break; + case 'bulkDelete': + $count = $this->handleBulkDeleteOperation($dbForProject, $transactionState, $collectionId, $data, $createdAt, $state); + $totalOperations += $count; + $databaseOperations[$databaseInternalId] = ($databaseOperations[$databaseInternalId] ?? 0) + $count; + break; + } + } + + $transaction = Authorization::skip(fn () => $dbForProject->updateDocument( + 'transactions', + $transactionId, + new Document(['status' => 'committed']) + )); + + $queueForDeletes + ->setType(DELETE_TYPE_DOCUMENT) + ->setDocument($transaction); + }); + + } catch (NotFoundException $e) { + Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + 'status' => 'failed', + ]))); + throw new Exception(Exception::DOCUMENT_NOT_FOUND, previous: $e); + } catch (DuplicateException|ConflictException $e) { + Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + 'status' => 'failed', + ]))); + throw new Exception(Exception::TRANSACTION_CONFLICT, previous: $e); + } catch (StructureException $e) { + Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + 'status' => 'failed', + ]))); + throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage()); + } catch (LimitException $e) { + Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + 'status' => 'failed', + ]))); + throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, $e->getMessage()); + } catch (TransactionException $e) { + Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + 'status' => 'failed', + ]))); + throw new Exception(Exception::TRANSACTION_FAILED, $e->getMessage()); + } catch (QueryException $e) { + Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + 'status' => 'failed', + ]))); + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } + + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, $totalOperations); + + foreach ($databaseOperations as $sequence => $count) { + $queueForStatsUsage->addMetric( + str_replace('{databaseInternalId}', $sequence, METRIC_DATABASE_ID_OPERATIONS_WRITES), + $count + ); + } + + foreach ($operations as $operation) { + $databaseInternalId = $operation['databaseInternalId']; + $collectionInternalId = $operation['collectionInternalId']; + $collectionId = "database_{$databaseInternalId}_collection_{$collectionInternalId}"; + $action = $operation['action']; + $documentId = $operation['documentId']; + $data = $operation['data']; + + if ($data instanceof Document) { + $data = $data->getArrayCopy(); + } + + $database = Authorization::skip(fn () => $dbForProject->findOne('databases', [ + Query::equal('$sequence', [$databaseInternalId]) + ])); + + $collection = Authorization::skip(fn () => $dbForProject->findOne('database_' . $databaseInternalId, [ + Query::equal('$sequence', [$collectionInternalId]) + ])); + + $groupId = $this->getGroupId(); + $resourceId = $this->getResourceId(); + $contextKey = $this->getContext(); + $resource = $this->getResource(); + $resourcePlural = $resource . 's'; + + $queueForEvents + ->setParam('databaseId', $database->getId()) + ->setContext('database', $database) + ->setParam('collectionId', $collection->getId()) + ->setParam('tableId', $collection->getId()) + ->setContext($contextKey, $collection); + + $eventAction = ''; + $documentsToTrigger = []; + + switch ($action) { + case 'create': + $eventAction = 'create'; + $docId = $documentId ?? $data['$id'] ?? null; + if ($docId) { + $doc = $dbForProject->getDocument($collectionId, $docId); + if (!$doc->isEmpty()) { + $documentsToTrigger[] = $doc; + } + } + break; + case 'update': + case 'increment': + case 'decrement': + $eventAction = 'update'; + if ($documentId) { + $doc = $dbForProject->getDocument($collectionId, $documentId); + if (!$doc->isEmpty()) { + $documentsToTrigger[] = $doc; + } + } + break; + case 'delete': + $eventAction = 'delete'; + if ($documentId && !empty($data)) { + $documentsToTrigger[] = new Document(array_merge($data, ['$id' => $documentId])); + } + break; + case 'upsert': + $eventAction = 'update'; + $docId = $documentId ?? $data['$id'] ?? null; + if ($docId) { + $doc = $dbForProject->getDocument($collectionId, $docId); + if (!$doc->isEmpty()) { + $documentsToTrigger[] = $doc; + } + } + break; + case 'bulkCreate': + case 'bulkUpdate': + case 'bulkUpsert': + case 'bulkDelete': + break; + } + + $eventString = "databases.[databaseId].{$contextKey}s.[{$groupId}].{$resourcePlural}.[{$resourceId}]." . $eventAction; + + $queueForEvents->setEvent($eventString); + + foreach ($documentsToTrigger as $doc) { + $payload = $doc->getArrayCopy(); + $payload['$tableId'] = $collection->getId(); + $payload['$collectionId'] = $collection->getId(); + + $queueForEvents + ->setParam('documentId', $doc->getId()) + ->setParam('rowId', $doc->getId()) + ->setPayload($payload); + + $queueForRealtime->from($queueForEvents)->trigger(); + $queueForFunctions->from($queueForEvents)->trigger(); + $queueForWebhooks->from($queueForEvents)->trigger(); + } + + $queueForEvents->reset(); + $queueForRealtime->reset(); + $queueForFunctions->reset(); + $queueForWebhooks->reset(); + } + } + + if ($rollback) { + $transaction = Authorization::skip(fn () => $dbForProject->updateDocument( + 'transactions', + $transactionId, + new Document(['status' => 'failed']) + )); + + $queueForDeletes + ->setType(DELETE_TYPE_DOCUMENT) + ->setDocument($transaction); + } + + $response + ->setStatusCode(SwooleResponse::STATUS_CODE_OK) + ->dynamic($transaction, UtopiaResponse::MODEL_TRANSACTION); + } + + /** + * Handle create operation + * + * @param Database $dbForProject + * @param string $collectionId + * @param string|null $documentId + * @param array $data + * @param \DateTime $createdAt + * @param array &$state + * @return void + * @throws \Utopia\Database\Exception + */ + private function handleCreateOperation( + Database $dbForProject, + string $collectionId, + ?string $documentId, + array $data, + \DateTime $createdAt, + array &$state + ): void { + if ($documentId && !isset($data['$id'])) { + $data['$id'] = $documentId; + } + $dbForProject->withRequestTimestamp($createdAt, function () use ($dbForProject, $collectionId, $data, &$state) { + $doc = $dbForProject->createDocument( + $collectionId, + new Document($data), + ); + $state[$collectionId][$doc->getId()] = $doc; + }); + } + + /** + * Handle update operation + * + * @param Database $dbForProject + * @param string $collectionId + * @param string $documentId + * @param array $data + * @param \DateTime $createdAt + * @param array &$state + * @return void + * @throws ConflictException + * @throws \Utopia\Database\Exception + */ + private function handleUpdateOperation( + Database $dbForProject, + string $collectionId, + string $documentId, + array $data, + \DateTime $createdAt, + array &$state + ): void { + $dependent = isset($state[$collectionId][$documentId]); + + if ($dependent) { + $state[$collectionId][$documentId] = $dbForProject->updateDocument( + $collectionId, + $documentId, + new Document($data), + ); + return; + } + + $dbForProject->withRequestTimestamp($createdAt, function () use ($dbForProject, $collectionId, $documentId, $data, &$state) { + $document = $dbForProject->updateDocument( + $collectionId, + $documentId, + new Document($data), + ); + if ($document->isEmpty()) { + throw new NotFoundException(''); + } + $state[$collectionId][$documentId] = $document; + }); + } + + /** + * Handle upsert operation + * + * @param Database $dbForProject + * @param string $collectionId + * @param string|null $documentId + * @param array $data + * @param \DateTime $createdAt + * @param array &$state + * @return void + * @throws \Utopia\Database\Exception + */ + private function handleUpsertOperation( + Database $dbForProject, + string $collectionId, + ?string $documentId, + array $data, + \DateTime $createdAt, + array &$state + ): void { + $dependent = isset($state[$collectionId][$documentId]); + + if ($dependent) { + // Merge partial upsert data with full document from transaction state + $existingDoc = $state[$collectionId][$documentId]; + foreach ($data as $key => $value) { + if ($key !== '$id') { + $existingDoc->setAttribute($key, $value); + } + } + + $state[$collectionId][$documentId] = $dbForProject->upsertDocument( + $collectionId, + $existingDoc, + ); + return; + } + + $dbForProject->withRequestTimestamp($createdAt, function () use ($dbForProject, $collectionId, $data, &$state) { + $doc = $dbForProject->upsertDocument( + $collectionId, + new Document($data), + ); + $state[$collectionId][$doc->getId()] = $doc; + }); + } + + /** + * Handle delete operation + * + * @param Database $dbForProject + * @param string $collectionId + * @param string $documentId + * @param \DateTime $createdAt + * @param array &$state + * @return void + * @throws \Utopia\Database\Exception + * @throws NotFoundException + */ + private function handleDeleteOperation( + Database $dbForProject, + string $collectionId, + string $documentId, + \DateTime $createdAt, + array &$state + ): void { + $dependent = isset($state[$collectionId][$documentId]); + + if ($dependent) { + $dbForProject->deleteDocument($collectionId, $documentId); + unset($state[$collectionId][$documentId]); + return; + } + + $dbForProject->withRequestTimestamp($createdAt, function () use ($dbForProject, $collectionId, $documentId, &$state) { + $deleted = $dbForProject->deleteDocument($collectionId, $documentId); + if (!$deleted) { + throw new NotFoundException(''); + } + if (isset($state[$collectionId][$documentId])) { + unset($state[$collectionId][$documentId]); + } + }); + } + + /** + * Get the attribute/column name from data, with fallback for cross-API compatibility + * + * @param array $data The operation data + * @return string The attribute/column name + */ + private function getAttributeNameFromData(array $data): string + { + $expectedKey = $this->getAttributeKey(); + if (isset($data[$expectedKey])) { + return $data[$expectedKey]; + } + + // Try the opposite key for cross-API compatibility + $fallbackKey = $expectedKey === 'attribute' ? 'column' : 'attribute'; + if (isset($data[$fallbackKey])) { + return $data[$fallbackKey]; + } + + return ''; + } + + /** + * Handle increment operation + * + * @param Database $dbForProject + * @param string $collectionId + * @param string $documentId + * @param array $data + * @param \DateTime $createdAt + * @param array &$state + * @return void + * @throws ConflictException + * @throws \Utopia\Database\Exception + */ + private function handleIncrementOperation( + Database $dbForProject, + string $collectionId, + string $documentId, + array $data, + \DateTime $createdAt, + array &$state + ): void { + $dependent = isset($state[$collectionId][$documentId]); + $attribute = $this->getAttributeNameFromData($data); + + if ($dependent) { + $state[$collectionId][$documentId] = $dbForProject->increaseDocumentAttribute( + collection: $collectionId, + id: $documentId, + attribute: $attribute, + value: $data['value'] ?? 1, + max: $data['max'] ?? null + ); + return; + } + + $dbForProject->withRequestTimestamp($createdAt, function () use ($dbForProject, $collectionId, $documentId, $data, &$state, $attribute) { + $state[$collectionId][$documentId] = $dbForProject->increaseDocumentAttribute( + collection: $collectionId, + id: $documentId, + attribute: $attribute, + value: $data['value'] ?? 1, + max: $data['max'] ?? null + ); + }); + } + + /** + * Handle decrement operation + * + * @param Database $dbForProject + * @param string $collectionId + * @param string $documentId + * @param array $data + * @param \DateTime $createdAt + * @param array &$state + * @return void + * @throws ConflictException + * @throws \Utopia\Database\Exception + */ + private function handleDecrementOperation( + Database $dbForProject, + string $collectionId, + string $documentId, + array $data, + \DateTime $createdAt, + array &$state + ): void { + $dependent = isset($state[$collectionId][$documentId]); + $attribute = $this->getAttributeNameFromData($data); + + if ($dependent) { + $state[$collectionId][$documentId] = $dbForProject->decreaseDocumentAttribute( + collection: $collectionId, + id: $documentId, + attribute: $attribute, + value: $data['value'] ?? 1, + min: $data['min'] ?? null + ); + return; + } + + $dbForProject->withRequestTimestamp($createdAt, function () use ($dbForProject, $collectionId, $documentId, $data, &$state, $attribute) { + $state[$collectionId][$documentId] = $dbForProject->decreaseDocumentAttribute( + collection: $collectionId, + id: $documentId, + attribute: $attribute, + value: $data['value'] ?? 1, + min: $data['min'] ?? null + ); + }); + } + + /** + * Handle bulk create operation + * + * @param Database $dbForProject + * @param string $collectionId + * @param array $data + * @param \DateTime $createdAt + * @param array &$state + * @return int Number of documents created + * @throws \Utopia\Database\Exception + */ + private function handleBulkCreateOperation( + Database $dbForProject, + string $collectionId, + array $data, + \DateTime $createdAt, + array &$state + ): int { + $count = 0; + $dbForProject->withRequestTimestamp($createdAt, function () use ($dbForProject, $collectionId, $data, &$state, &$count) { + $documents = \array_map(function ($doc) { + return $doc instanceof Document ? $doc : new Document($doc); + }, $data); + + $count = $dbForProject->createDocuments( + $collectionId, + $documents, + onNext: function (Document $document) use (&$state, $collectionId) { + $state[$collectionId][$document->getId()] = $document; + } + ); + }); + return $count; + } + + /** + * Handle bulk update operation with manual timestamp checking + * + * @param Database $dbForProject + * @param TransactionState $transactionState + * @param string $collectionId + * @param array $data + * @param \DateTime $createdAt + * @param array &$state + * @return int Number of documents updated + * @throws \Utopia\Database\Exception + * @throws \Utopia\Database\Exception\Query + * @throws ConflictException + */ + private function handleBulkUpdateOperation( + Database $dbForProject, + TransactionState $transactionState, + string $collectionId, + array $data, + \DateTime $createdAt, + array &$state + ): int { + $queries = Query::parseQueries($data['queries'] ?? []); + $updateData = new Document($data['data']); + + $dependentDocs = []; + + $transactionState->applyBulkUpdateToState($collectionId, $updateData, $queries, $state); + + // Clone the document before passing to updateDocuments to prevent mutation + // The database layer mutates the input document, which would corrupt transaction state + $count = $dbForProject->updateDocuments( + $collectionId, + clone $updateData, + $queries, + onNext: function (Document $updated, Document $old) use (&$state, $collectionId, $createdAt, &$dependentDocs) { + $dependent = isset($state[$collectionId][$updated->getId()]); + + if ($dependent) { + $dependentDocs[] = $updated->getId(); + } else { + $oldUpdatedAt = new \DateTime($old->getUpdatedAt()); + if ($oldUpdatedAt > $createdAt) { + throw new ConflictException('Document was updated after the request timestamp'); + } + $state[$collectionId][$updated->getId()] = $updated; + } + } + ); + + // Re-write dependent documents from state to database to fix partial updates + if (!empty($dependentDocs)) { + $documentsToRewrite = []; + foreach ($dependentDocs as $docId) { + if (isset($state[$collectionId][$docId])) { + $documentsToRewrite[] = $state[$collectionId][$docId]; + } + } + + if (!empty($documentsToRewrite)) { + $dbForProject->upsertDocuments( + $collectionId, + $documentsToRewrite, + onNext: function (Document $upserted) use (&$state, $collectionId) { + $state[$collectionId][$upserted->getId()] = $upserted; + } + ); + } + } + + return $count; + } + + /** + * Handle bulk upsert operation with manual timestamp checking + * + * @param Database $dbForProject + * @param TransactionState $transactionState + * @param string $collectionId + * @param array $data + * @param \DateTime $createdAt + * @param array &$state + * @return int Number of documents upserted + * @throws ConflictException + * @throws \Utopia\Database\Exception + */ + private function handleBulkUpsertOperation( + Database $dbForProject, + TransactionState $transactionState, + string $collectionId, + array $data, + \DateTime $createdAt, + array &$state + ): int { + $documents = \array_map(function ($doc) { + return $doc instanceof Document ? $doc : new Document($doc); + }, $data); + + $mergedDocuments = $transactionState->applyBulkUpsertToState($collectionId, $documents, $state); + + $count = $dbForProject->upsertDocuments( + $collectionId, + $mergedDocuments, + onNext: function (Document $upserted, ?Document $old) use (&$state, $collectionId, $createdAt) { + if ($old !== null) { + $dependent = isset($state[$collectionId][$upserted->getId()]); + + if (!$dependent) { + $oldUpdatedAt = new \DateTime($old->getUpdatedAt()); + if ($oldUpdatedAt > $createdAt) { + throw new ConflictException('Document was updated after the request timestamp'); + } + } + } + + $state[$collectionId][$upserted->getId()] = $upserted; + } + ); + + return $count; + } + + /** + * Handle bulk delete operation with manual timestamp checking + * + * @param Database $dbForProject + * @param TransactionState $transactionState + * @param string $collectionId + * @param array $data + * @param \DateTime $createdAt + * @param array &$state + * @return int Number of documents deleted + * @throws \Utopia\Database\Exception\Query + * @throws ConflictException + * @throws \Utopia\Database\Exception + */ + private function handleBulkDeleteOperation( + Database $dbForProject, + TransactionState $transactionState, + string $collectionId, + array $data, + \DateTime $createdAt, + array &$state + ): int { + $queries = Query::parseQueries($data['queries'] ?? []); + + $count = $dbForProject->deleteDocuments( + $collectionId, + $queries, + onNext: function (Document $deleted, Document $old) use (&$state, $collectionId, $createdAt) { + $dependent = isset($state[$collectionId][$deleted->getId()]); + + if (!$dependent) { + $oldUpdatedAt = new \DateTime($old->getUpdatedAt()); + if ($oldUpdatedAt > $createdAt) { + throw new ConflictException('Document was updated after the transaction operation'); + } + } + + if (isset($state[$collectionId][$deleted->getId()])) { + unset($state[$collectionId][$deleted->getId()]); + } + } + ); + + $transactionState->applyBulkDeleteToState($collectionId, $queries, $state); + + return $count; + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/XList.php new file mode 100644 index 0000000000..33c66b90c7 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/XList.php @@ -0,0 +1,72 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/databases/transactions') + ->desc('List transactions') + ->groups(['api', 'database', 'transactions']) + ->label('scope', 'rows.read') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + group: 'transactions', + name: 'listTransactions', + description: '/docs/references/databases/list-transactions.md', + auth: [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(...)); + } + + public function action(array $queries, UtopiaResponse $response, Database $dbForProject): void + { + try { + $queries = Query::parseQueries($queries); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } + + $response->dynamic(new Document([ + 'transactions' => $dbForProject->find('transactions', $queries), + 'total' => $dbForProject->count('transactions', $queries), + ]), UtopiaResponse::MODEL_TRANSACTION_LIST); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Create.php index bb4bef35e8..039964b2c6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Create.php @@ -37,8 +37,8 @@ class Create extends BooleanCreate ->label('audits.event', 'column.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/create-boolean-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Update.php index 2d8789e394..7df901a1cc 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Boolean/Update.php @@ -39,8 +39,8 @@ class Update extends BooleanUpdate ->label('audits.event', 'column.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/update-boolean-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Create.php index 9598278ffc..db5a3059f1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Create.php @@ -39,8 +39,8 @@ class Create extends DatetimeCreate ->label('audits.event', 'column.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/create-datetime-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Update.php index d7b5ec2448..151422af75 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Datetime/Update.php @@ -41,8 +41,8 @@ class Update extends DatetimeUpdate ->label('audits.event', 'column.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/update-datetime-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Delete.php index 50a148ce19..26f4ffa898 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Delete.php @@ -38,8 +38,8 @@ class Delete extends AttributesDelete ->label('audits.event', 'column.delete') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/delete-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Create.php index e28a216fff..3a8d492e4e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Create.php @@ -38,8 +38,8 @@ class Create extends EmailCreate ->label('audits.event', 'column.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/create-email-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Update.php index 0fb856acb9..4d32489357 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Email/Update.php @@ -40,8 +40,8 @@ class Update extends EmailUpdate ->label('audits.event', 'column.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/update-email-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Create.php index 5b9d89c7e9..68dc2f8e08 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Create.php @@ -40,8 +40,8 @@ class Create extends EnumCreate ->label('audits.event', 'column.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/create-enum-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Update.php index 0c00e3f268..3b611a5fde 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Enum/Update.php @@ -42,8 +42,8 @@ class Update extends EnumUpdate ->label('audits.event', 'column.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/update-enum-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Create.php index 5967b00196..9fe6987cab 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Create.php @@ -38,8 +38,8 @@ class Create extends FloatCreate ->label('audits.event', 'column.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/create-float-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Update.php index 9486b3a75c..023e2e834e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Float/Update.php @@ -40,8 +40,8 @@ class Update extends FloatUpdate ->label('audits.event', 'column.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/update-float-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Get.php index d536a7aaf2..c20ef58a39 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Get.php @@ -44,8 +44,8 @@ class Get extends AttributesGet ->label('scope', ['tables.read', 'collections.read']) ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/get-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Create.php index 325a9382e5..81ca8da81f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Create.php @@ -38,8 +38,8 @@ class Create extends IPCreate ->label('audits.event', 'column.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/create-ip-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Update.php index b9e6368307..0db95b0206 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/IP/Update.php @@ -40,8 +40,8 @@ class Update extends IPUpdate ->label('audits.event', 'column.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/update-ip-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php index bd6fec3f53..dfca51a6c5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Create.php @@ -38,8 +38,8 @@ class Create extends IntegerCreate ->label('audits.event', 'column.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/create-integer-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php index be92811d1b..a1568d069b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php @@ -40,8 +40,8 @@ class Update extends IntegerUpdate ->label('audits.event', 'column.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/update-integer-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php index 9903ad3a7e..4aa173707b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Create.php @@ -40,8 +40,8 @@ class Create extends LineCreate ->label('audits.event', 'column.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/create-line-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Update.php index 04b514afb8..d3823445a2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Line/Update.php @@ -41,8 +41,8 @@ class Update extends LineUpdate ->label('audits.event', 'column.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/update-line-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php index ed95e4629c..b8ae563def 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Create.php @@ -40,8 +40,8 @@ class Create extends PointCreate ->label('audits.event', 'column.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/create-point-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php index f29e5bb27a..3c855e137c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php @@ -41,8 +41,8 @@ class Update extends PointUpdate ->label('audits.event', 'column.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/update-point-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php index c50c5acd5c..e0a2cf32cd 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Create.php @@ -40,8 +40,8 @@ class Create extends PolygonCreate ->label('audits.event', 'column.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/create-polygon-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php index 9f689717c3..866bbaf8b0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php @@ -41,8 +41,8 @@ class Update extends PolygonUpdate ->label('audits.event', 'column.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/update-polygon-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Create.php index b6f9663f77..0a6c76d8c5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Create.php @@ -39,8 +39,8 @@ class Create extends RelationshipCreate ->label('audits.event', 'column.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/create-relationship-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Update.php index 421e11af91..b645454be1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Update.php @@ -39,8 +39,8 @@ class Update extends RelationshipUpdate ->label('audits.event', 'column.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/update-relationship-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Create.php index efe7dd513f..6fe9fd679c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Create.php @@ -40,8 +40,8 @@ class Create extends StringCreate ->label('audits.event', 'column.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/create-string-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php index 7ba813aedd..5ec9b78dda 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php @@ -42,8 +42,8 @@ class Update extends StringUpdate ->label('audits.event', 'column.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/update-string-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Create.php index bc53ad5250..99ec36b721 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Create.php @@ -38,8 +38,8 @@ class Create extends URLCreate ->label('audits.event', 'column.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/create-url-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php index 36bd7dc054..51168b0383 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php @@ -40,8 +40,8 @@ class Update extends URLUpdate ->label('audits.event', 'column.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/update-url-column.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php index ca41bb024d..13bf3257e3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php @@ -33,8 +33,8 @@ class XList extends AttributesXList ->label('scope', ['tables.read', 'collections.read']) ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/list-columns.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php index 3965e12a74..4f62200d7c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php @@ -40,7 +40,7 @@ class Create extends CollectionCreate ->label('audits.event', 'table.create') ->label('audits.resource', 'database/{request.databaseId}/table/{response.$id}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), + namespace: $this->getSDKNamespace(), group: 'tables', name: self::getName(), description: '/docs/references/tablesdb/create-table.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Delete.php index 9bfdf42cef..de068d5b29 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Delete.php @@ -36,7 +36,7 @@ class Delete extends CollectionDelete ->label('audits.event', 'table.delete') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), + namespace: $this->getSDKNamespace(), group: 'tables', name: self::getName(), description: '/docs/references/tablesdb/delete-table.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Get.php index a7d33478f7..be6ec5d9e7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Get.php @@ -33,7 +33,7 @@ class Get extends CollectionGet ->label('scope', ['tables.read', 'collections.read']) ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), + namespace: $this->getSDKNamespace(), group: 'tables', name: self::getName(), description: '/docs/references/tablesdb/get-table.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Create.php index fdbe91f5f7..3802ee32b8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Create.php @@ -42,8 +42,8 @@ class Create extends IndexCreate ->label('audits.event', 'index.create') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + 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', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Delete.php index ec05c92a64..57ab466ee8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Delete.php @@ -41,8 +41,8 @@ class Delete extends IndexDelete ->label('audits.event', 'index.delete') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: 'deleteIndex', // getName needs to be different from parent action to avoid conflict in path name description: '/docs/references/tablesdb/delete-index.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Get.php index 907b396072..271d842631 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Get.php @@ -34,8 +34,8 @@ class Get extends IndexGet ->label('scope', ['tables.read', 'collections.read']) ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: 'getIndex', // getName needs to be different from parent action to avoid conflict in path name description: '/docs/references/tablesdb/get-index.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php index 835e543d07..041b4aa70c 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php @@ -34,8 +34,8 @@ class XList extends IndexXList ->label('scope', ['tables.read', 'collections.read']) ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: 'listIndexes', // getName needs to be different from parent action to avoid conflict in path name description: '/docs/references/tablesdb/list-indexes.md', auth: [AuthType::KEY], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php index 6d386df4f6..0680649544 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Logs/XList.php @@ -30,8 +30,8 @@ class XList extends CollectionLogXList ->label('scope', ['tables.read', 'collections.read']) ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/get-table-logs.md', auth: [AuthType::ADMIN], diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Delete.php index a99316394a..86e9a48f63 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Delete.php @@ -40,8 +40,8 @@ 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(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/delete-rows.md', auth: [AuthType::ADMIN, AuthType::KEY], @@ -56,6 +56,7 @@ class Delete extends DocumentsDelete ->param('databaseId', '', new UID(), 'Database ID.') ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/references/cloud/server-dart/tablesDB#createTable).') ->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('queueForStatsUsage') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Update.php index 13778b9474..5005ab4f41 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Update.php @@ -41,8 +41,8 @@ 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(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/update-rows.md', auth: [AuthType::ADMIN, AuthType::KEY], @@ -58,6 +58,7 @@ class Update extends DocumentsUpdate ->param('tableId', '', new UID(), 'Table ID.') ->param('data', [], new JSON(), 'Row data as JSON object. Include only column 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('queueForStatsUsage') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Upsert.php index 26c5c8030c..d0a1f08003 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Bulk/Upsert.php @@ -41,8 +41,8 @@ class Upsert extends DocumentsUpsert ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) ->label('sdk', [ new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/upsert-rows.md', auth: [AuthType::ADMIN, AuthType::KEY], @@ -58,6 +58,7 @@ class Upsert extends DocumentsUpsert ->param('databaseId', '', new UID(), 'Database ID.') ->param('tableId', '', new UID(), 'Table ID.') ->param('rows', [], fn (array $plan) => new ArrayList(new JSON(), $plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH), 'Array of row data as JSON objects. May contain partial rows.', false, ['plan']) + ->param('transactionId', null, new UID(), 'Transaction ID for staging the operation.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForStatsUsage') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Decrement.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Decrement.php index 46e9c8d6af..d42cf5e9eb 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Decrement.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Decrement.php @@ -41,8 +41,8 @@ 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(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/decrement-row-column.md', auth: [AuthType::SESSION, AuthType::JWT, AuthType::ADMIN, AuthType::KEY], @@ -60,10 +60,12 @@ class Decrement extends DecrementDocumentAttribute ->param('column', '', new Key(), 'Column key.') ->param('value', 1, new Numeric(), 'Value to increment the column by. The value must be a number.', true) ->param('min', null, new Numeric(), 'Minimum value for the column. 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('queueForEvents') ->inject('queueForStatsUsage') + ->inject('plan') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Increment.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Increment.php index d921e9b8be..c58e16c8e3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Increment.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Column/Increment.php @@ -41,8 +41,8 @@ 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(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/increment-row-column.md', auth: [AuthType::SESSION, AuthType::JWT, AuthType::ADMIN, AuthType::KEY], @@ -60,10 +60,12 @@ class Increment extends IncrementDocumentAttribute ->param('column', '', new Key(), 'Column key.') ->param('value', 1, new Numeric(), 'Value to increment the column by. The value must be a number.', true) ->param('max', null, new Numeric(), 'Maximum value for the column. 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('queueForEvents') ->inject('queueForStatsUsage') + ->inject('plan') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Create.php index a39d9adbda..bfc832f2b5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Create.php @@ -50,8 +50,8 @@ class Create extends DocumentCreate ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) ->label('sdk', [ new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), desc: 'Create row', description: '/docs/references/tablesdb/create-row.md', @@ -69,11 +69,12 @@ class Create extends DocumentCreate new Parameter('rowId', optional: false), new Parameter('data', optional: false), new Parameter('permissions', optional: true), + new Parameter('transactionId', optional: true), ] ), new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: $this->getBulkActionName(self::getName()), desc: 'Create rows', description: '/docs/references/tablesdb/create-rows.md', @@ -89,6 +90,7 @@ class Create extends DocumentCreate new Parameter('databaseId', optional: false), new Parameter('tableId', optional: false), new Parameter('rows', optional: false), + new Parameter('transactionId', optional: true), ] ) ]) @@ -98,6 +100,7 @@ class Create extends DocumentCreate ->param('data', [], new JSON(), 'Row 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('rows', [], fn (array $plan) => new ArrayList(new JSON(), $plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH), 'Array of rows data as JSON objects.', true, ['plan']) + ->param('transactionId', null, new UID(), 'Transaction ID for staging the operation.', true) ->inject('response') ->inject('dbForProject') ->inject('user') @@ -106,6 +109,7 @@ class Create extends DocumentCreate ->inject('queueForRealtime') ->inject('queueForFunctions') ->inject('queueForWebhooks') + ->inject('plan') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Delete.php index 72f4ef3d94..687b1c8c11 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Delete.php @@ -45,8 +45,8 @@ 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(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/delete-row.md', auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], @@ -61,11 +61,14 @@ class Delete extends DocumentDelete ->param('databaseId', '', new UID(), 'Database ID.') ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/references/cloud/server-dart/tablesDB#createTable).') ->param('rowId', '', new UID(), 'Row ID.') + ->param('transactionId', null, new UID(), 'Transaction ID for staging the operation.', true) ->inject('requestTimestamp') ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') ->inject('queueForStatsUsage') + ->inject('transactionState') + ->inject('plan') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Get.php index faf1584d0d..f8b70516b6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Get.php @@ -35,8 +35,8 @@ class Get extends DocumentGet ->label('scope', ['rows.read', 'documents.read']) ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/get-row.md', auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], @@ -52,9 +52,11 @@ class Get extends DocumentGet ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/references/cloud/server-dart/tablesDB#createTable).') ->param('rowId', '', new UID(), 'Row 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('queueForStatsUsage') + ->inject('transactionState') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php index a80249070b..5f1efa2953 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Logs/XList.php @@ -30,7 +30,7 @@ class XList extends DocumentLogXList ->label('scope', ['rows.read', 'documents.read']) ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), + namespace: $this->getSDKNamespace(), group: 'logs', name: self::getName(), description: '/docs/references/tablesdb/get-row-logs.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Update.php index b0e321b262..cb1d5888cf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Update.php @@ -42,8 +42,8 @@ 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(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/update-row.md', auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], @@ -60,11 +60,14 @@ class Update extends DocumentUpdate ->param('rowId', '', new UID(), 'Row ID.') ->param('data', [], new JSON(), 'Row data as JSON object. Include only columns 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('queueForEvents') ->inject('queueForStatsUsage') + ->inject('transactionState') + ->inject('plan') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php index c2695379e3..0bc373cc93 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/Upsert.php @@ -43,8 +43,8 @@ class Upsert extends DocumentUpsert ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) ->label('sdk', [ new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/upsert-row.md', auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], @@ -62,12 +62,15 @@ class Upsert extends DocumentUpsert ->param('rowId', '', new UID(), 'Row ID.') ->param('data', [], new JSON(), 'Row data as JSON object. Include all required columns of the row 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('queueForEvents') ->inject('queueForStatsUsage') + ->inject('transactionState') + ->inject('plan') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php index 00953a1d04..8c96997ea5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php @@ -35,8 +35,8 @@ class XList extends DocumentXList ->label('scope', ['rows.read', 'documents.read']) ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), - group: $this->getSdkGroup(), + namespace: $this->getSDKNamespace(), + group: $this->getSDKGroup(), name: self::getName(), description: '/docs/references/tablesdb/list-rows.md', auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], @@ -51,9 +51,11 @@ class XList extends DocumentXList ->param('databaseId', '', new UID(), 'Database ID.') ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the TablesDB service [server integration](https://appwrite.io/docs/products/databases/tables#create-table).') ->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('queueForStatsUsage') + ->inject('transactionState') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php index 0fcdf319d2..8424b37a6d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php @@ -39,7 +39,7 @@ class Update extends CollectionUpdate ->label('audits.event', 'table.update') ->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}') ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), + namespace: $this->getSDKNamespace(), group: 'tables', name: self::getName(), description: '/docs/references/tablesdb/update-table.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Usage/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Usage/Get.php index 87f720e689..0fb44ee94a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Usage/Get.php @@ -34,7 +34,7 @@ class Get extends CollectionUsageGet ->label('scope', ['tables.read', 'collections.read']) ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), + namespace: $this->getSDKNamespace(), group: null, name: self::getName(), description: '/docs/references/tablesdb/get-table-usage.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php index d9a92e41b1..a47a972371 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php @@ -35,7 +35,7 @@ class XList extends CollectionXList ->label('scope', ['tables.read', 'collections.read']) ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('sdk', new Method( - namespace: $this->getSdkNamespace(), + namespace: $this->getSDKNamespace(), group: 'tables', name: self::getName(), description: '/docs/references/tablesdb/list-tables.md', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Create.php new file mode 100644 index 0000000000..bc79b86ca3 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Create.php @@ -0,0 +1,55 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/tablesdb/transactions') + ->desc('Create transaction') + ->groups(['api', 'database', 'transactions']) + ->label('scope', ['documents.write', 'rows.write']) + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'tablesDB', + group: 'transactions', + name: 'createTransaction', + description: '/docs/references/tablesdb/create-transaction.md', + auth: [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') + ->callback($this->action(...)); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Delete.php new file mode 100644 index 0000000000..6f92a1b10b --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Delete.php @@ -0,0 +1,55 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_DELETE) + ->setHttpPath('/v1/tablesdb/transactions/:transactionId') + ->desc('Delete transaction') + ->groups(['api', 'database', 'transactions']) + ->label('scope', ['documents.write', 'rows.write']) + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'tablesDB', + group: 'transactions', + name: 'deleteTransaction', + description: '/docs/references/tablesdb/delete-transaction.md', + auth: [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(...)); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Get.php new file mode 100644 index 0000000000..ab7925c916 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Get.php @@ -0,0 +1,54 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/tablesdb/transactions/:transactionId') + ->desc('Get transaction') + ->groups(['api', 'database', 'transactions']) + ->label('scope', ['documents.read', 'rows.read']) + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'tablesDB', + group: 'transactions', + name: 'getTransaction', + description: '/docs/references/tablesdb/get-transaction.md', + auth: [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(...)); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Operations/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Operations/Create.php new file mode 100644 index 0000000000..5a98f22f37 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Operations/Create.php @@ -0,0 +1,59 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/tablesdb/transactions/:transactionId/operations') + ->desc('Create operations') + ->groups(['api', 'database', 'transactions']) + ->label('scope', ['documents.write', 'rows.write']) + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'tablesDB', + group: 'transactions', + name: 'createOperations', + description: '/docs/references/tablesdb/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: 'tablesdb')), 'Array of staged operations.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('transactionState') + ->inject('plan') + ->callback($this->action(...)); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Update.php new file mode 100644 index 0000000000..4d55af93a4 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/Update.php @@ -0,0 +1,65 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/tablesdb/transactions/:transactionId') + ->desc('Update transaction') + ->groups(['api', 'database', 'transactions']) + ->label('scope', ['documents.write', 'rows.write']) + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'tablesDB', + group: 'transactions', + name: 'updateTransaction', + description: '/docs/references/tablesdb/update-transaction.md', + auth: [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('response') + ->inject('dbForProject') + ->inject('user') + ->inject('transactionState') + ->inject('queueForDeletes') + ->inject('queueForEvents') + ->inject('queueForStatsUsage') + ->inject('queueForRealtime') + ->inject('queueForFunctions') + ->inject('queueForWebhooks') + ->callback($this->action(...)); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/XList.php new file mode 100644 index 0000000000..9a9c22a1a8 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Transactions/XList.php @@ -0,0 +1,54 @@ +setHttpMethod(self::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/tablesdb/transactions') + ->desc('List transactions') + ->groups(['api', 'database', 'transactions']) + ->label('scope', ['documents.read', 'rows.read']) + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('sdk', new Method( + namespace: 'tablesDB', + group: 'transactions', + name: 'listTransactions', + description: '/docs/references/tablesdb/list-transactions.md', + auth: [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(...)); + } +} diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Http.php b/src/Appwrite/Platform/Modules/Databases/Services/Http.php index ccd9dfd140..f683f537bc 100644 --- a/src/Appwrite/Platform/Modules/Databases/Services/Http.php +++ b/src/Appwrite/Platform/Modules/Databases/Services/Http.php @@ -3,9 +3,8 @@ namespace Appwrite\Platform\Modules\Databases\Services; use Appwrite\Platform\Modules\Databases\Http\Init\Timeout; -use Appwrite\Platform\Modules\Databases\Services\Registry\Collections as CollectionsRegistry; -use Appwrite\Platform\Modules\Databases\Services\Registry\Databases as DatabasesRegistry; -use Appwrite\Platform\Modules\Databases\Services\Registry\Tables as TablesRegistry; +use Appwrite\Platform\Modules\Databases\Services\Registry\Legacy as LegacyRegistry; +use Appwrite\Platform\Modules\Databases\Services\Registry\TablesDB as TablesDBRegistry; use Utopia\Platform\Service; class Http extends Service @@ -17,9 +16,8 @@ class Http extends Service $this->addAction(Timeout::getName(), new Timeout()); foreach ([ - DatabasesRegistry::class, - CollectionsRegistry::class, - TablesRegistry::class, + LegacyRegistry::class, + TablesDBRegistry::class, ] as $registrar) { new $registrar($this); } diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Databases.php b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Databases.php deleted file mode 100644 index 81c9174253..0000000000 --- a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Databases.php +++ /dev/null @@ -1,31 +0,0 @@ -addAction(CreateDatabase::getName(), new CreateDatabase()); - $service->addAction(GetDatabase::getName(), new GetDatabase()); - $service->addAction(UpdateDatabase::getName(), new UpdateDatabase()); - $service->addAction(DeleteDatabase::getName(), new DeleteDatabase()); - $service->addAction(ListDatabases::getName(), new ListDatabases()); - $service->addAction(ListDatabaseLogs::getName(), new ListDatabaseLogs()); - $service->addAction(GetDatabaseUsage::getName(), new GetDatabaseUsage()); - $service->addAction(ListDatabaseUsage::getName(), new ListDatabaseUsage()); - } -} diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Legacy.php similarity index 81% rename from src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php rename to src/Appwrite/Platform/Modules/Databases/Services/Registry/Legacy.php index 404f784611..7de95da255 100644 --- a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Collections.php +++ b/src/Appwrite/Platform/Modules/Databases/Services/Registry/Legacy.php @@ -54,6 +54,20 @@ use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Logs\XList as use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Update as UpdateCollection; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Usage\Get as GetCollectionUsage; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\XList as ListCollections; +use Appwrite\Platform\Modules\Databases\Http\Databases\Create as CreateDatabase; +use Appwrite\Platform\Modules\Databases\Http\Databases\Delete as DeleteDatabase; +use Appwrite\Platform\Modules\Databases\Http\Databases\Get as GetDatabase; +use Appwrite\Platform\Modules\Databases\Http\Databases\Logs\XList as ListDatabaseLogs; +use Appwrite\Platform\Modules\Databases\Http\Databases\Transactions\Create as CreateTransaction; +use Appwrite\Platform\Modules\Databases\Http\Databases\Transactions\Delete as DeleteTransaction; +use Appwrite\Platform\Modules\Databases\Http\Databases\Transactions\Get as GetTransaction; +use Appwrite\Platform\Modules\Databases\Http\Databases\Transactions\Operations\Create as CreateOperations; +use Appwrite\Platform\Modules\Databases\Http\Databases\Transactions\Update as UpdateTransaction; +use Appwrite\Platform\Modules\Databases\Http\Databases\Transactions\XList as ListTransactions; +use Appwrite\Platform\Modules\Databases\Http\Databases\Update as UpdateDatabase; +use Appwrite\Platform\Modules\Databases\Http\Databases\Usage\Get as GetDatabaseUsage; +use Appwrite\Platform\Modules\Databases\Http\Databases\Usage\XList as ListDatabaseUsage; +use Appwrite\Platform\Modules\Databases\Http\Databases\XList as ListDatabases; use Utopia\Platform\Service; /** @@ -64,15 +78,30 @@ use Utopia\Platform\Service; * - Documents * - Attributes * - Indexes + * - Transactions */ -class Collections extends Base +class Legacy extends Base { protected function register(Service $service): void { + $this->registerDatabaseActions($service); $this->registerCollectionActions($service); $this->registerDocumentActions($service); $this->registerAttributeActions($service); $this->registerIndexActions($service); + $this->registerTransactionActions($service); + } + + public function registerDatabaseActions(Service $service): void + { + $service->addAction(CreateDatabase::getName(), new CreateDatabase()); + $service->addAction(GetDatabase::getName(), new GetDatabase()); + $service->addAction(UpdateDatabase::getName(), new UpdateDatabase()); + $service->addAction(DeleteDatabase::getName(), new DeleteDatabase()); + $service->addAction(ListDatabases::getName(), new ListDatabases()); + $service->addAction(ListDatabaseLogs::getName(), new ListDatabaseLogs()); + $service->addAction(GetDatabaseUsage::getName(), new GetDatabaseUsage()); + $service->addAction(ListDatabaseUsage::getName(), new ListDatabaseUsage()); } private function registerCollectionActions(Service $service): void @@ -170,4 +199,14 @@ class Collections extends Base $service->addAction(DeleteIndex::getName(), new DeleteIndex()); $service->addAction(ListIndexes::getName(), new ListIndexes()); } + + private function registerTransactionActions(Service $service): void + { + $service->addAction(CreateTransaction::getName(), new CreateTransaction()); + $service->addAction(GetTransaction::getName(), new GetTransaction()); + $service->addAction(UpdateTransaction::getName(), new UpdateTransaction()); + $service->addAction(DeleteTransaction::getName(), new DeleteTransaction()); + $service->addAction(ListTransactions::getName(), new ListTransactions()); + $service->addAction(CreateOperations::getName(), new CreateOperations()); + } } diff --git a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php b/src/Appwrite/Platform/Modules/Databases/Services/Registry/TablesDB.php similarity index 90% rename from src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php rename to src/Appwrite/Platform/Modules/Databases/Services/Registry/TablesDB.php index d570745148..4a02ac684e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Services/Registry/Tables.php +++ b/src/Appwrite/Platform/Modules/Databases/Services/Registry/TablesDB.php @@ -57,6 +57,12 @@ use Appwrite\Platform\Modules\Databases\Http\TablesDB\Tables\Rows\XList as ListR use Appwrite\Platform\Modules\Databases\Http\TablesDB\Tables\Update as UpdateTable; use Appwrite\Platform\Modules\Databases\Http\TablesDB\Tables\Usage\Get as GetTableUsage; use Appwrite\Platform\Modules\Databases\Http\TablesDB\Tables\XList as ListTables; +use Appwrite\Platform\Modules\Databases\Http\TablesDB\Transactions\Create as CreateTransaction; +use Appwrite\Platform\Modules\Databases\Http\TablesDB\Transactions\Delete as DeleteTransaction; +use Appwrite\Platform\Modules\Databases\Http\TablesDB\Transactions\Get as GetTransaction; +use Appwrite\Platform\Modules\Databases\Http\TablesDB\Transactions\Operations\Create as CreateOperations; +use Appwrite\Platform\Modules\Databases\Http\TablesDB\Transactions\Update as UpdateTransaction; +use Appwrite\Platform\Modules\Databases\Http\TablesDB\Transactions\XList as ListTransactions; use Appwrite\Platform\Modules\Databases\Http\TablesDB\Update as UpdateTablesDatabase; use Appwrite\Platform\Modules\Databases\Http\TablesDB\Usage\Get as GetTablesDatabaseUsage; use Appwrite\Platform\Modules\Databases\Http\TablesDB\Usage\XList as ListTablesDatabaseUsage; @@ -72,7 +78,7 @@ use Utopia\Platform\Service; * - Columns * - Column-Indexes */ -class Tables extends Base +class TablesDB extends Base { protected function register(Service $service): void { @@ -81,6 +87,7 @@ class Tables extends Base $this->registerColumnActions($service); $this->registerIndexActions($service); $this->registerRowActions($service); + $this->registerTransactionActions($service); } private function registerDatabaseActions(Service $service): void @@ -188,4 +195,14 @@ class Tables extends Base $service->addAction(IncrementRowColumn::getName(), new IncrementRowColumn()); $service->addAction(DecrementRowColumn::getName(), new DecrementRowColumn()); } + + private function registerTransactionActions(Service $service): void + { + $service->addAction(CreateTransaction::getName(), new CreateTransaction()); + $service->addAction(GetTransaction::getName(), new GetTransaction()); + $service->addAction(UpdateTransaction::getName(), new UpdateTransaction()); + $service->addAction(DeleteTransaction::getName(), new DeleteTransaction()); + $service->addAction(ListTransactions::getName(), new ListTransactions()); + $service->addAction(CreateOperations::getName(), new CreateOperations()); + } } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php index c7638bf3f7..6a4fafb132 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php @@ -23,6 +23,7 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; +use Utopia\Database\Exception\Duplicate as DuplicateException; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; @@ -200,36 +201,40 @@ class Create extends Action throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'When connecting to VCS (Version Control System), you need to provide "installationId" and "providerBranch".'); } - $function = $dbForProject->createDocument('functions', new Document([ - '$id' => $functionId, - 'execute' => $execute, - 'enabled' => $enabled, - 'live' => true, - 'logging' => $logging, - 'name' => $name, - 'runtime' => $runtime, - 'deploymentInternalId' => '', - 'deploymentId' => '', - 'events' => $events, - 'schedule' => $schedule, - 'scheduleInternalId' => '', - 'scheduleId' => '', - 'timeout' => $timeout, - 'entrypoint' => $entrypoint, - 'commands' => $commands, - 'scopes' => $scopes, - 'search' => implode(' ', [$functionId, $name, $runtime]), - 'version' => 'v5', - 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getSequence(), - 'providerRepositoryId' => $providerRepositoryId, - 'repositoryId' => '', - 'repositoryInternalId' => '', - 'providerBranch' => $providerBranch, - 'providerRootDirectory' => $providerRootDirectory, - 'providerSilentMode' => $providerSilentMode, - 'specification' => $specification - ])); + try { + $function = $dbForProject->createDocument('functions', new Document([ + '$id' => $functionId, + 'execute' => $execute, + 'enabled' => $enabled, + 'live' => true, + 'logging' => $logging, + 'name' => $name, + 'runtime' => $runtime, + 'deploymentInternalId' => '', + 'deploymentId' => '', + 'events' => $events, + 'schedule' => $schedule, + 'scheduleInternalId' => '', + 'scheduleId' => '', + 'timeout' => $timeout, + 'entrypoint' => $entrypoint, + 'commands' => $commands, + 'scopes' => $scopes, + 'search' => implode(' ', [$functionId, $name, $runtime]), + 'version' => 'v5', + 'installationId' => $installation->getId(), + 'installationInternalId' => $installation->getSequence(), + 'providerRepositoryId' => $providerRepositoryId, + 'repositoryId' => '', + 'repositoryInternalId' => '', + 'providerBranch' => $providerBranch, + 'providerRootDirectory' => $providerRootDirectory, + 'providerSilentMode' => $providerSilentMode, + 'specification' => $specification + ])); + } catch (DuplicateException) { + throw new Exception(Exception::FUNCTION_ALREADY_EXISTS); + } $schedule = Authorization::skip( fn () => $dbForPlatform->createDocument('schedules', new Document([ diff --git a/src/Appwrite/Platform/Tasks/SDKs.php b/src/Appwrite/Platform/Tasks/SDKs.php index 87c70d214b..2fb15c5f7d 100644 --- a/src/Appwrite/Platform/Tasks/SDKs.php +++ b/src/Appwrite/Platform/Tasks/SDKs.php @@ -280,6 +280,25 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND continue; } + // Check if the latest commit on the target branch already has a release + $latestCommitCommand = 'gh api repos/' . $repoName . '/commits/' . $releaseTarget . ' --jq ".sha" 2>/dev/null'; + $latestCommitSha = trim(\shell_exec($latestCommitCommand) ?? ''); + + if (!empty($latestCommitSha)) { + $latestReleaseTagCommand = 'gh api repos/' . $repoName . '/releases --jq ".[0] | .tag_name" 2>/dev/null'; + $latestReleaseTag = trim(\shell_exec($latestReleaseTagCommand) ?? ''); + + if (!empty($latestReleaseTag)) { + $tagCommitCommand = 'gh api repos/' . $repoName . '/git/ref/tags/' . $latestReleaseTag . ' --jq ".object.sha" 2>/dev/null'; + $tagCommitSha = trim(\shell_exec($tagCommitCommand) ?? ''); + + if (!empty($tagCommitSha) && $latestCommitSha === $tagCommitSha) { + Console::warning("Latest commit on {$releaseTarget} already has a release ({$latestReleaseTag}) for {$language['name']} SDK, skipping to avoid empty release..."); + continue; + } + } + } + $previousVersion = ''; $tagListCommand = 'gh release list --repo "' . $repoName . '" --limit 1 --json tagName --jq ".[0].tagName" 2>&1'; $previousVersion = trim(\shell_exec($tagListCommand) ?? ''); diff --git a/src/Appwrite/Platform/Tasks/ScheduleBase.php b/src/Appwrite/Platform/Tasks/ScheduleBase.php index 5cd25b09b4..e9a0e1d333 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleBase.php +++ b/src/Appwrite/Platform/Tasks/ScheduleBase.php @@ -49,6 +49,7 @@ abstract class ScheduleBase extends Action ->inject('publisherMigrations') ->inject('publisherFunctions') ->inject('publisherMessaging') + ->inject('isResourceBlocked') ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('telemetry') @@ -71,7 +72,7 @@ abstract class ScheduleBase extends Action * 2. Create timer that sync all changes from 'schedules' collection to local copy. Only reading changes thanks to 'resourceUpdatedAt' attribute * 3. Create timer that prepares coroutines for soon-to-execute schedules. When it's ready, coroutine sleeps until exact time before sending request to worker. */ - public function action(BrokerPool $publisher, BrokerPool $publisherMigrations, BrokerPool $publisherFunctions, BrokerPool $publisherMessaging, Database $dbForPlatform, callable $getProjectDB, Telemetry $telemetry): void + public function action(BrokerPool $publisher, BrokerPool $publisherMigrations, BrokerPool $publisherFunctions, BrokerPool $publisherMessaging, callable $isResourceBlocked, Database $dbForPlatform, callable $getProjectDB, Telemetry $telemetry): void { Console::title(\ucfirst(static::getSupportedResource()) . ' scheduler V1'); Console::success(APP_NAME . ' ' . \ucfirst(static::getSupportedResource()) . ' scheduler v1 has started'); @@ -88,16 +89,16 @@ abstract class ScheduleBase extends Action // start with "0" to load all active documents. $lastSyncUpdate = "0"; - $this->collectSchedules($dbForPlatform, $getProjectDB, $lastSyncUpdate); + $this->collectSchedules($dbForPlatform, $getProjectDB, $lastSyncUpdate, $isResourceBlocked); Console::success("Starting timers at " . DateTime::now()); /** * The timer synchronize $schedules copy with database collection. */ - Timer::tick(static::UPDATE_TIMER * 1000, function () use ($dbForPlatform, $getProjectDB, &$lastSyncUpdate) { + Timer::tick(static::UPDATE_TIMER * 1000, function () use ($dbForPlatform, $getProjectDB, &$lastSyncUpdate, $isResourceBlocked) { $time = DateTime::now(); Console::log("Sync tick: Running at $time"); - $this->collectSchedules($dbForPlatform, $getProjectDB, $lastSyncUpdate); + $this->collectSchedules($dbForPlatform, $getProjectDB, $lastSyncUpdate, $isResourceBlocked); }); while (true) { @@ -112,7 +113,7 @@ abstract class ScheduleBase extends Action } } - private function collectSchedules(Database $dbForPlatform, callable $getProjectDB, string &$lastSyncUpdate): void + private function collectSchedules(Database $dbForPlatform, callable $getProjectDB, string &$lastSyncUpdate, callable $isResourceBlocked): void { // If we haven't synced yet, load all active schedules $initialLoad = $lastSyncUpdate === "0"; @@ -178,34 +179,40 @@ abstract class ScheduleBase extends Action $paginationQueries[] = Query::greaterThanEqual('resourceUpdatedAt', $lastSyncUpdate); } - $results = $dbForPlatform->find('schedules', $paginationQueries); + $collectionId = static::getCollectionId(); + $schedules = $dbForPlatform->find('schedules', $paginationQueries); + $sum = count($schedules); + $total += $sum; - $sum = count($results); - $total = $total + $sum; + foreach ($schedules as $schedule) { + $existing = $this->schedules[$schedule->getSequence()] ?? null; + $updated = strtotime($existing['resourceUpdatedAt'] ?? '0') !== strtotime($schedule['resourceUpdatedAt'] ?? '0'); - foreach ($results as $document) { - $localDocument = $this->schedules[$document->getSequence()] ?? null; - - if ($localDocument !== null) { - if (!$document['active']) { - Console::info("Removing: {$document['resourceType']}::{$document['resourceId']}"); - unset($this->schedules[$document->getSequence()]); - } elseif (strtotime($localDocument['resourceUpdatedAt']) !== strtotime($document['resourceUpdatedAt'])) { - Console::info("Updating: {$document['resourceType']}::{$document['resourceId']}"); - $this->schedules[$document->getSequence()] = $getSchedule($document); - } - } else { + if ($existing === null || $updated) { try { - $this->schedules[$document->getSequence()] = $getSchedule($document); + $candidate = $getSchedule($schedule); } catch (\Throwable $th) { - $collectionId = static::getCollectionId(); - Console::error("Failed to load schedule for project {$document['projectId']} {$collectionId} {$document['resourceId']}"); + Console::error("Failed to load schedule for project {$schedule['projectId']} {$collectionId} {$schedule['resourceId']}"); Console::error($th->getMessage()); + continue; } + + if (!$candidate['active']) { + unset($this->schedules[$schedule->getSequence()]); + continue; + } + + if ($isResourceBlocked($candidate['project'], $collectionId, $candidate['resourceId'])) { + unset($this->schedules[$schedule->getSequence()]); + continue; + } + + Console::info("Updating: {$schedule['resourceType']}::{$schedule['resourceId']}"); + $this->schedules[$schedule->getSequence()] = $candidate; } } - $latestDocument = \end($results); + $latestDocument = \end($schedules); } $lastSyncUpdate = $time; diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index a07d0b3cbe..331a2668a3 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -93,7 +93,7 @@ class Deletes extends Action throw new Exception('Missing payload'); } - $type = $payload['type'] ?? ''; + $type = $payload['type'] ?? ''; $datetime = $payload['datetime'] ?? null; $hourlyUsageRetentionDatetime = $payload['hourlyUsageRetentionDatetime'] ?? null; $resource = $payload['resource'] ?? null; @@ -130,6 +130,9 @@ class Deletes extends Action case DELETE_TYPE_RULES: $this->deleteRule($dbForPlatform, $document, $certificates); break; + case DELETE_TYPE_TRANSACTION: + $this->deleteTransactionLogs($getProjectDB, $document, $project); + break; default: Console::error('No lazy delete operation available for document of type: ' . $document->getCollection()); break; @@ -182,6 +185,7 @@ class Deletes extends Action $this->deleteAuditLogs($project, $getProjectDB, $auditRetention); $this->deleteUsageStats($project, $getProjectDB, $getLogsDB, $hourlyUsageRetentionDatetime); $this->deleteExpiredSessions($project, $getProjectDB); + $this->deleteExpiredTransactions($project, $getProjectDB); break; default: throw new \Exception('No delete operation for type: ' . \strval($type)); @@ -305,9 +309,9 @@ class Deletes extends Action * @param Document $project * @param callable $getProjectDB * @param string $resource + * @param string|null $resourceType * @return void * @throws Authorization - * @param string|null $resourceType * @throws Exception */ private function deleteCacheByResource(Document $project, callable $getProjectDB, string $resource, string $resourceType = null): void @@ -395,7 +399,7 @@ class Deletes extends Action */ private function deleteUsageStats(Document $project, callable $getProjectDB, callable $getLogsDB, string $hourlyUsageRetentionDatetime): void { - /** @var Database $dbForProject*/ + /** @var Database $dbForProject */ $dbForProject = $getProjectDB($project); $selects = [...$this->selects, 'time']; @@ -410,7 +414,7 @@ class Deletes extends Action ], $dbForProject); if ($project->getId() !== 'console') { - /** @var Database $dbForLogs*/ + /** @var Database $dbForLogs */ $dbForLogs = call_user_func($getLogsDB, $project); // Delete Usage stats from logsDB @@ -452,16 +456,16 @@ class Deletes extends Action } /** - * @param Database $dbForPlatform - * @param Document $document - * @return void - * @throws Authorization - * @throws DatabaseException - * @throws Conflict - * @throws Restricted - * @throws Structure - * @throws Exception - */ + * @param Database $dbForPlatform + * @param Document $document + * @return void + * @throws Authorization + * @throws DatabaseException + * @throws Conflict + * @throws Restricted + * @throws Structure + * @throws Exception + */ protected function deleteProjectsByTeam(Database $dbForPlatform, callable $getProjectDB, CertificatesAdapter $certificates, Document $document): void { @@ -539,7 +543,7 @@ class Deletes extends Action ); } } catch (Throwable $e) { - Console::error('Error deleting '.$collection->getId().' '.$e->getMessage()); + Console::error('Error deleting ' . $collection->getId() . ' ' . $e->getMessage()); } }); @@ -1117,9 +1121,6 @@ class Deletes extends Action ): void { $start = \microtime(true); - $deleteBatchSize = Database::DELETE_BATCH_SIZE; - $deleteBatchSize = 500; // TODO: Set right value in DB library after investigation - /** * deleteDocuments uses a cursor, we need to add a unique order by field or use default */ @@ -1127,11 +1128,10 @@ class Deletes extends Action $count = $database->deleteDocuments( $collection, $queries, - $deleteBatchSize, - $callback + onNext: $callback ); } catch (Throwable $th) { - $tenant = $database->getSharedTables() ? 'Tenant:'.$database->getTenant() : ''; + $tenant = $database->getSharedTables() ? 'Tenant:' . $database->getTenant() : ''; Console::error("Failed to delete documents for collection:{$database->getNamespace()}_{$collection} {$tenant} :{$th->getMessage()}"); return; } @@ -1299,4 +1299,48 @@ class Deletes extends Action ); } } + + private function deleteTransactionLogs(callable $getProjectDB, Document $document, Document $project): void + { + $dbForProject = $getProjectDB($project); + $transactionId = $document->getId(); + $transactionInternalId = $document->getSequence(); + + try { + $dbForProject->deleteDocuments('transactionLogs', [ + Query::equal('transactionInternalId', [$transactionInternalId]), + ]); + Console::info("Transaction logs for transaction {$transactionId} deleted."); + } catch (Throwable $th) { + Console::error("Failed to delete transaction logs for transaction {$transactionId}: " . $th->getMessage()); + } + } + + private function deleteExpiredTransactions(Document $project, callable $getProjectDB): void + { + $dbForProject = $getProjectDB($project); + $transactionInternalIds = []; + + try { + $dbForProject->deleteDocuments('transactions', [ + Query::lessThan('expiresAt', DateTime::format(new \DateTime())), + ], onNext: function (Document $transaction) use ($dbForProject, $project, &$transactionInternalIds) { + $transactionInternalIds[] = $transaction->getSequence(); + }, onError: function (Throwable $th) use ($project) { + // Swallow errors to avoid breaking the cleanup process + }); + } catch (Throwable $th) { + Console::error("Failed to find expired transactions for project {$project->getId()}: " . $th->getMessage()); + } + + if (empty($transactionInternalIds)) { + return; + } + + $dbForProject->deleteDocuments('transactionLogs', [ + Query::equal('transactionInternalId', $transactionInternalIds), + ], onError: function (Throwable $th) use ($project) { + // Swallow errors to avoid breaking the cleanup process + }); + } } diff --git a/src/Appwrite/Platform/Workers/StatsUsage.php b/src/Appwrite/Platform/Workers/StatsUsage.php index 4da63b6ae3..4916d0e177 100644 --- a/src/Appwrite/Platform/Workers/StatsUsage.php +++ b/src/Appwrite/Platform/Workers/StatsUsage.php @@ -18,24 +18,24 @@ class StatsUsage extends Action /** * In memory per project metrics calculation */ - private array $stats = []; - private int $lastTriggeredTime = 0; - private int $keys = 0; - private const INFINITY_PERIOD = '_inf_'; - private const BATCH_SIZE_DEVELOPMENT = 1; - private const BATCH_SIZE_PRODUCTION = 10_000; + protected array $stats = []; + protected int $lastTriggeredTime = 0; + protected int $keys = 0; + protected const INFINITY_PERIOD = '_inf_'; + protected const BATCH_SIZE_DEVELOPMENT = 1; + protected const BATCH_SIZE_PRODUCTION = 10_000; /** * Stats for batch write separated per project * @var array */ - private array $projects = []; + protected array $projects = []; /** * Array of stat documents to batch write to logsDB * @var array */ - private array $statDocuments = []; + protected array $statDocuments = []; protected Registry $register; @@ -101,7 +101,7 @@ class StatsUsage extends Action return 'stats-usage'; } - private function getBatchSize(): int + protected function getBatchSize(): int { return System::getEnv('_APP_ENV', 'development') === 'development' ? self::BATCH_SIZE_DEVELOPMENT @@ -195,7 +195,7 @@ class StatsUsage extends Action * @param callable(): Database $getProjectDB * @return void */ - private function reduce(Document $project, Document $document, array &$metrics, callable $getProjectDB): void + protected function reduce(Document $project, Document $document, array &$metrics, callable $getProjectDB): void { $dbForProject = $getProjectDB($project); @@ -435,6 +435,7 @@ class StatsUsage extends Action return $cmp; } + unset($this->projects[$sequence]); // Period ASC $cmp = strcmp($a['period'], $b['period']); if ($cmp !== 0) { diff --git a/src/Appwrite/SDK/Response.php b/src/Appwrite/SDK/Response.php index e87813024b..2b034691a8 100644 --- a/src/Appwrite/SDK/Response.php +++ b/src/Appwrite/SDK/Response.php @@ -2,12 +2,11 @@ namespace Appwrite\SDK; -class Response +readonly class Response { /** * @param int $code * @param string|array $model - * @param string $description */ public function __construct( private int $code, diff --git a/src/Appwrite/SDK/Specification/Format/OpenAPI3.php b/src/Appwrite/SDK/Specification/Format/OpenAPI3.php index 2380f03920..38613313db 100644 --- a/src/Appwrite/SDK/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/SDK/Specification/Format/OpenAPI3.php @@ -8,6 +8,7 @@ use Appwrite\SDK\MethodType; use Appwrite\SDK\Response; use Appwrite\SDK\Specification\Format; use Appwrite\Template\Template; +use Appwrite\Utopia\Database\Validator\Operation; use Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response\Model\Any; use Utopia\Database\Database; @@ -397,7 +398,37 @@ class OpenAPI3 extends Format $validator = $validator->getValidator(); } - switch ((!empty($validator)) ? \get_class($validator) : '') { + $class = !empty($validator) + ? \get_class($validator) + : ''; + + $base = !empty($class) + ? \get_parent_class($class) + : ''; + + switch ($base) { + case 'Appwrite\Utopia\Database\Validator\Queries\Base': + $class = $base; + break; + } + + if ($class === 'Utopia\Validator\AnyOf') { + $validator = $param['validator']->getValidators()[0]; + $class = \get_class($validator); + } + + $array = false; + if ($class === 'Utopia\Validator\ArrayList') { + $array = true; + $subclass = \get_class($validator->getValidator()); + switch ($subclass) { + case 'Appwrite\Utopia\Database\Validator\Operation': + $class = $subclass; + break; + } + } + + switch ($class) { case 'Utopia\Database\Validator\UID': case 'Utopia\Validator\Text': $node['schema']['type'] = $validator->getType(); @@ -419,6 +450,20 @@ class OpenAPI3 extends Format $node['schema']['format'] = 'datetime'; $node['schema']['x-example'] = Model::TYPE_DATETIME_EXAMPLE; break; + case 'Utopia\Database\Validator\Spatial': + /** @var Spatial $validator */ + $node['schema']['type'] = 'array'; + $node['schema']['items'] = [ + 'oneOf' => [ + ['type' => 'array'] + ] + ]; + $node['schema']['x-example'] = match ($validator->getSpatialType()) { + Database::VAR_POINT => '[1, 2]', + Database::VAR_LINESTRING => '[[1, 2], [3, 4], [5, 6]]', + Database::VAR_POLYGON => '[[[1, 2], [3, 4], [5, 6], [1, 2]]]', + }; + break; case 'Appwrite\Network\Validator\Email': $node['schema']['type'] = $validator->getType(); $node['schema']['format'] = 'email'; @@ -450,20 +495,7 @@ class OpenAPI3 extends Format 'type' => $validator->getValidator()->getType(), ]; break; - case 'Utopia\Database\Validator\Spatial': - /** @var Spatial $validator */ - $node['schema']['type'] = 'array'; - $node['schema']['items'] = [ - 'oneOf' => [ - ['type' => 'array'] - ] - ]; - $node['schema']['x-example'] = match ($validator->getSpatialType()) { - Database::VAR_POINT => '[1, 2]', - Database::VAR_LINESTRING => '[[1, 2], [3, 4], [5, 6]]', - Database::VAR_POLYGON => '[[[1, 2], [3, 4], [5, 6], [1, 2]]]', - }; - break; + case 'Appwrite\Utopia\Database\Validator\Queries\Base': case 'Appwrite\Utopia\Database\Validator\Queries\Columns': case 'Appwrite\Utopia\Database\Validator\Queries\Attributes': case 'Appwrite\Utopia\Database\Validator\Queries\Buckets': @@ -557,8 +589,7 @@ class OpenAPI3 extends Format break; } } - - if ($allowed) { + if ($allowed && $validator->getType() === 'string') { $node['schema']['enum'] = $validator->getList(); $node['schema']['x-enum-name'] = $this->getRequestEnumName($sdk->getNamespace() ?? '', $methodName, $name); $node['schema']['x-enum-keys'] = $this->getRequestEnumKeys($sdk->getNamespace() ?? '', $methodName, $name); @@ -569,7 +600,35 @@ class OpenAPI3 extends Format break; case 'Appwrite\Utopia\Database\Validator\CompoundUID': $node['schema']['type'] = $validator->getType(); - $node['schema']['x-example'] = '[ID1:ID2]'; + $node['schema']['x-example'] = ''; + break; + case 'Appwrite\Utopia\Database\Validator\Operation': + if ($array) { + $validator = $validator->getValidator(); + } + + /** @var Operation $validator */ + $collectionIdKey = $validator->getCollectionIdKey(); + $documentIdKey = $validator->getDocumentIdKey(); + if ($array) { + $node['schema']['type'] = 'array'; + $node['schema']['items'] = ['type' => 'object']; + } else { + $node['schema']['type'] = 'object'; + } + $example = [ + 'action' => 'create', + 'databaseId' => '', + $collectionIdKey => '<'.\strtoupper(Template::fromCamelCaseToSnake($collectionIdKey)).'>', + $documentIdKey => '<'.\strtoupper(Template::fromCamelCaseToSnake($documentIdKey)).'>', + 'data' => [ + 'name' => 'Walter O\'Brien', + ], + ]; + if ($array) { + $example = [$example]; + } + $node['schema']['x-example'] = \str_replace("\n", "\n\t", \json_encode($example, JSON_PRETTY_PRINT)); break; default: $node['schema']['type'] = 'string'; diff --git a/src/Appwrite/SDK/Specification/Format/Swagger2.php b/src/Appwrite/SDK/Specification/Format/Swagger2.php index ed1217d86c..d497369b9a 100644 --- a/src/Appwrite/SDK/Specification/Format/Swagger2.php +++ b/src/Appwrite/SDK/Specification/Format/Swagger2.php @@ -8,6 +8,7 @@ use Appwrite\SDK\MethodType; use Appwrite\SDK\Response; use Appwrite\SDK\Specification\Format; use Appwrite\Template\Template; +use Appwrite\Utopia\Database\Validator\Operation; use Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response\Model\Any; use Utopia\Database\Database; @@ -423,6 +424,17 @@ class Swagger2 extends Format $class = \get_class($validator); } + $array = false; + if ($class === 'Utopia\Validator\ArrayList') { + $array = true; + $subclass = \get_class($validator->getValidator()); + switch ($subclass) { + case 'Appwrite\Utopia\Database\Validator\Operation': + $class = $subclass; + break; + } + } + switch ($class) { case 'Utopia\Validator\Text': case 'Utopia\Database\Validator\UID': @@ -445,6 +457,20 @@ class Swagger2 extends Format $node['format'] = 'datetime'; $node['x-example'] = Model::TYPE_DATETIME_EXAMPLE; break; + case 'Utopia\Database\Validator\Spatial': + /** @var Spatial $validator */ + $node['type'] = 'array'; + $node['schema']['items'] = [ + 'oneOf' => [ + ['type' => 'array'] + ] + ]; + $node['x-example'] = match ($validator->getSpatialType()) { + Database::VAR_POINT => '[1, 2]', + Database::VAR_LINESTRING => '[[1, 2], [3, 4], [5, 6]]', + Database::VAR_POLYGON => '[[[1, 2], [3, 4], [5, 6], [1, 2]]]', + }; + break; case 'Appwrite\Network\Validator\Email': $node['type'] = $validator->getType(); $node['format'] = 'email'; @@ -465,20 +491,6 @@ class Swagger2 extends Format 'type' => $validator->getValidator()->getType(), ]; break; - case 'Utopia\Database\Validator\Spatial': - /** @var Spatial $validator */ - $node['type'] = 'array'; - $node['schema']['items'] = [ - 'oneOf' => [ - ['type' => 'array'] - ] - ]; - $node['x-example'] = match ($validator->getSpatialType()) { - Database::VAR_POINT => '[1, 2]', - Database::VAR_LINESTRING => '[[1, 2], [3, 4], [5, 6]]', - Database::VAR_POLYGON => '[[[1, 2], [3, 4], [5, 6], [1, 2]]]', - }; - break; case 'Utopia\Validator\JSON': case 'Utopia\Validator\Mock': case 'Utopia\Validator\Assoc': @@ -563,20 +575,47 @@ class Swagger2 extends Format break; } } - if ($allowed && $validator->getType() === 'string') { $node['enum'] = $validator->getList(); $node['x-enum-name'] = $this->getRequestEnumName($namespace, $methodName, $name); $node['x-enum-keys'] = $this->getRequestEnumKeys($namespace, $methodName, $name); } - if ($validator->getType() === 'integer') { $node['format'] = 'int32'; } break; case 'Appwrite\Utopia\Database\Validator\CompoundUID': $node['type'] = $validator->getType(); - $node['x-example'] = '[ID1:ID2]'; + $node['x-example'] = ''; + break; + case 'Appwrite\Utopia\Database\Validator\Operation': + if ($array) { + $validator = $validator->getValidator(); + } + + /** @var Operation $validator */ + $collectionIdKey = $validator->getCollectionIdKey(); + $documentIdKey = $validator->getDocumentIdKey(); + if ($array) { + $node['type'] = 'array'; + $node['collectionFormat'] = 'multi'; + $node['items'] = ['type' => 'object']; + } else { + $node['type'] = 'object'; + } + $example = [ + 'action' => 'create', + 'databaseId' => '', + $collectionIdKey => '<'.\strtoupper(Template::fromCamelCaseToSnake($collectionIdKey)).'>', + $documentIdKey => '<'.\strtoupper(Template::fromCamelCaseToSnake($documentIdKey)).'>', + 'data' => [ + 'name' => 'Walter O\'Brien', + ], + ]; + if ($array) { + $example = [$example]; + } + $node['x-example'] = \str_replace("\n", "\n\t", \json_encode($example, JSON_PRETTY_PRINT)); break; default: $node['type'] = 'string'; diff --git a/src/Appwrite/Utopia/Database/Validator/Operation.php b/src/Appwrite/Utopia/Database/Validator/Operation.php new file mode 100644 index 0000000000..e6884ac677 --- /dev/null +++ b/src/Appwrite/Utopia/Database/Validator/Operation.php @@ -0,0 +1,219 @@ + */ + private array $required = [ + 'databaseId', + 'action', + ]; + + /** @var array */ + private array $requiresDocumentId = [ + 'create' => true, + 'update' => true, + 'upsert' => true, + 'delete' => true, + 'increment' => true, + 'decrement' => true, + ]; + + /** @var array */ + private array $requiresData = [ + 'create' => true, + 'update' => true, + 'upsert' => true, + 'delete' => false, // Delete doesn't need data + 'increment' => true, + 'decrement' => true, + 'bulkCreate' => true, + 'bulkUpdate' => true, + 'bulkUpsert' => true, + 'bulkDelete' => true, + ]; + + /** @var array */ + private array $actions = [ + 'create' => true, + 'update' => true, + 'upsert' => true, + 'delete' => true, + 'increment' => true, + 'decrement' => true, + 'bulkCreate' => true, + 'bulkUpdate' => true, + 'bulkUpsert' => true, + 'bulkDelete' => true, + ]; + + private string $collectionIdName = ''; + private string $documentIdName = ''; + + public function __construct(private readonly string $type) + { + switch ($this->type) { + case 'legacy': + $this->collectionIdName = 'collectionId'; + $this->documentIdName = 'documentId'; + break; + case 'tablesdb': + $this->collectionIdName = 'tableId'; + $this->documentIdName = 'rowId'; + break; + default: + throw new \InvalidArgumentException('Invalid type provided.'); + } + + $this->required[] = $this->collectionIdName; + } + + public function getDescription(): string + { + return $this->description; + } + + public function getCollectionIdKey(): string + { + return $this->collectionIdName; + } + + public function getDocumentIdKey(): string + { + return $this->documentIdName; + } + + public function isArray(): bool + { + return true; + } + + /** + * @param mixed $value + */ + public function isValid($value): bool + { + // Must be array‑like + if (!\is_array($value)) { + $this->description = 'Value must be an array'; + return false; + } + + // Mandatory keys + foreach ($this->required as $key) { + if (!\array_key_exists($key, $value)) { + $this->description = "Missing required key: {$key}"; + return false; + } + } + + // Required keys must be non‑empty + foreach ($this->required as $key) { + if (!\is_string($value[$key]) || \trim($value[$key]) === '') { + $this->description = "Key '{$key}' must be a non‑empty string"; + return false; + } + } + + // Validate action + if (!isset($this->actions[$value['action']])) { + $this->description = "Key 'action' must be one of: " . \implode(', ', array_keys($this->actions)); + return false; + } + + // If action requires documentId, it must be present + $actionRequiresDocumentId = ($this->requiresDocumentId[$value['action']] ?? false) === true; + if ($actionRequiresDocumentId && !\array_key_exists($this->documentIdName, $value)) { + $this->description = "Key '$this->documentIdName' is required for action '{$value['action']}'"; + return false; + } + + if (\array_key_exists($this->documentIdName, $value)) { + if (!\is_string($value[$this->documentIdName]) || \trim($value[$this->documentIdName]) === '') { + $this->description = "Key '$this->documentIdName' must be a non-empty string"; + return false; + } + } + + // Data validation - only required for certain actions + if (isset($this->requiresData[$value['action']]) && $this->requiresData[$value['action']]) { + // Data is required for this action + if (!\array_key_exists('data', $value)) { + $this->description = "Missing required key: data"; + return false; + } + if (!\is_array($value['data'])) { + $this->description = "Key 'data' must be an array"; + return false; + } + } elseif (\array_key_exists('data', $value)) { + // Data is optional but if provided, must be an array + if (!\is_array($value['data'])) { + $this->description = "Key 'data' must be an array"; + return false; + } + } + + // Bulk operation specific validations + $action = $value['action']; + + // BulkUpdate and BulkDelete require queries + if (\in_array($action, ['bulkUpdate', 'bulkDelete'])) { + if (!\array_key_exists('data', $value) || !\is_array($value['data'])) { + $this->description = "Key 'data' must be an array for {$action}"; + return false; + } + if (!\array_key_exists('queries', $value['data'])) { + $this->description = "Key 'queries' is required in data for {$action}"; + return false; + } + if (!\is_array($value['data']['queries'])) { + $this->description = "Key 'queries' must be an array for {$action}"; + return false; + } + } + + // BulkUpdate requires both queries and data + if ($action === 'bulkUpdate') { + if (!\array_key_exists('data', $value['data'])) { + $this->description = "Key 'data' is required in data for {$action}"; + return false; + } + if (!\is_array($value['data']['data'])) { + $this->description = "Key 'data.data' must be an array for {$action}"; + return false; + } + } + + // Increment and Decrement require specific keys + if (\in_array($action, ['increment', 'decrement'])) { + if (!\array_key_exists('data', $value) || !\is_array($value['data'])) { + $this->description = "Key 'data' must be an array for {$action}"; + return false; + } + // Get the attribute key name based on type + $attributeKey = $this->type === 'tablesdb' ? 'column' : 'attribute'; + if (!\array_key_exists($attributeKey, $value['data'])) { + $this->description = "Key '{$attributeKey}' is required in data for {$action}"; + return false; + } + // Validate 'value' is numeric if provided (defaults to 1 if omitted) + if (\array_key_exists('value', $value['data']) && !\is_numeric($value['data']['value'])) { + $this->description = "Key 'value' must be a numeric value for {$action}"; + return false; + } + } + + return true; + } + + public function getType(): string + { + return self::TYPE_OBJECT; + } +} diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Transactions.php b/src/Appwrite/Utopia/Database/Validator/Queries/Transactions.php new file mode 100644 index 0000000000..b49494c0af --- /dev/null +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Transactions.php @@ -0,0 +1,17 @@ + */ + public const array ALLOWED_ATTRIBUTES = [ + 'status', + 'expiresAt', + ]; + + public function __construct() + { + parent::__construct('transactions', self::ALLOWED_ATTRIBUTES); + } +} diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 67fc83b9fd..b391f0ea72 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -126,6 +126,7 @@ use Appwrite\Utopia\Response\Model\TemplateSMS; use Appwrite\Utopia\Response\Model\TemplateVariable; use Appwrite\Utopia\Response\Model\Token; use Appwrite\Utopia\Response\Model\Topic; +use Appwrite\Utopia\Response\Model\Transaction; use Appwrite\Utopia\Response\Model\UsageBuckets; use Appwrite\Utopia\Response\Model\UsageCollection; use Appwrite\Utopia\Response\Model\UsageDatabase; @@ -230,6 +231,10 @@ class Response extends SwooleResponse public const MODEL_COLUMN_LINE = 'columnLine'; public const MODEL_COLUMN_POLYGON = 'columnPolygon'; + // Transactions + public const MODEL_TRANSACTION = 'transaction'; + public const MODEL_TRANSACTION_LIST = 'transactionList'; + // Users public const MODEL_ACCOUNT = 'account'; public const MODEL_USER = 'user'; @@ -478,6 +483,7 @@ class Response extends SwooleResponse ->setModel(new BaseList('Topic list', self::MODEL_TOPIC_LIST, 'topics', self::MODEL_TOPIC)) ->setModel(new BaseList('Subscriber list', self::MODEL_SUBSCRIBER_LIST, 'subscribers', self::MODEL_SUBSCRIBER)) ->setModel(new BaseList('Target list', self::MODEL_TARGET_LIST, 'targets', self::MODEL_TARGET)) + ->setModel(new BaseList('Transaction List', self::MODEL_TRANSACTION_LIST, 'transactions', self::MODEL_TRANSACTION)) ->setModel(new BaseList('Migrations List', self::MODEL_MIGRATION_LIST, 'migrations', self::MODEL_MIGRATION)) ->setModel(new BaseList('Migrations Firebase Projects List', self::MODEL_MIGRATION_FIREBASE_PROJECT_LIST, 'projects', self::MODEL_MIGRATION_FIREBASE_PROJECT)) ->setModel(new BaseList('Specifications List', self::MODEL_SPECIFICATION_LIST, 'specifications', self::MODEL_SPECIFICATION)) @@ -610,6 +616,7 @@ class Response extends SwooleResponse ->setModel(new Provider()) ->setModel(new Message()) ->setModel(new Topic()) + ->setModel(new Transaction()) ->setModel(new Subscriber()) ->setModel(new Target()) ->setModel(new Migration()) diff --git a/src/Appwrite/Utopia/Response/Model/Document.php b/src/Appwrite/Utopia/Response/Model/Document.php index 5bad504a63..f9766c895c 100644 --- a/src/Appwrite/Utopia/Response/Model/Document.php +++ b/src/Appwrite/Utopia/Response/Model/Document.php @@ -82,7 +82,10 @@ class Document extends Any { $document->removeAttribute('$collection'); $document->removeAttribute('$tenant'); - $document->setAttribute('$sequence', (int)$document->getAttribute('$sequence', 0)); + + if (!$document->isEmpty()) { + $document->setAttribute('$sequence', (int)$document->getAttribute('$sequence', 0)); + } foreach ($document->getAttributes() as $attribute) { if (\is_array($attribute)) { diff --git a/src/Appwrite/Utopia/Response/Model/Transaction.php b/src/Appwrite/Utopia/Response/Model/Transaction.php new file mode 100644 index 0000000000..aae2a9b572 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/Transaction.php @@ -0,0 +1,60 @@ +addRule('$id', [ + 'type' => self::TYPE_STRING, + 'description' => 'Transaction ID.', + 'default' => '', + 'example' => '259125845563242502', + ]) + ->addRule('$createdAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Transaction creation time in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('$updatedAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Transaction update date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('status', [ + 'type' => self::TYPE_STRING, + 'description' => 'Current status of the transaction. One of: pending, committing, committed, rolled_back, failed.', + 'default' => 'pending', + 'example' => 'pending', + ]) + ->addRule('operations', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Number of operations in the transaction.', + 'default' => 0, + 'example' => 5, + ]) + ->addRule('expiresAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Expiration time in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]); + } + + public function getName(): string + { + return 'Transaction'; + } + + public function getType(): string + { + return Response::MODEL_TRANSACTION; + } +} diff --git a/tests/e2e/Services/Databases/Legacy/DatabasesPermissionsGuestTest.php b/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php similarity index 99% rename from tests/e2e/Services/Databases/Legacy/DatabasesPermissionsGuestTest.php rename to tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php index abeef6c222..6496aa285a 100644 --- a/tests/e2e/Services/Databases/Legacy/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php @@ -1,6 +1,6 @@ client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'AtomicityTestDB' + ]); + + $this->assertEquals(201, $database['headers']['status-code']); + $databaseId = $database['body']['$id']; + + // Create collection with unique constraint + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'AtomicityTest', + 'documentSecurity' => false, + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Add unique attribute + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'email', + 'size' => 256, + 'required' => true, + ]); + + // Add unique index + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'unique_email', + 'type' => Database::INDEX_UNIQUE, + 'attributes' => ['email'] + ]); + + sleep(3); + + // Create first document outside transaction + $doc1 = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'documentId' => ID::unique(), + 'data' => [ + 'email' => 'existing@example.com' + ] + ]); + + $this->assertEquals(201, $doc1['headers']['status-code']); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(201, $transaction['headers']['status-code'], 'Transaction creation should succeed. Response: ' . json_encode($transaction)); + $this->assertArrayHasKey('$id', $transaction['body'], 'Transaction response should have $id. Response body: ' . json_encode($transaction['body'])); + $transactionId = $transaction['body']['$id']; + + // Add operations - second one will fail due to unique constraint + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'create', + 'documentId' => ID::unique(), + 'data' => [ + 'email' => 'newuser@example.com' // This should succeed + ] + ], + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'create', + 'documentId' => ID::unique(), + 'data' => [ + 'email' => 'existing@example.com' // This will fail - duplicate + ] + ], + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'create', + 'documentId' => ID::unique(), + 'data' => [ + 'email' => 'anotheruser@example.com' // This should not be created due to atomicity + ] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code'], 'Add operations failed. Response: ' . json_encode($response['body'])); + + // Attempt to commit - should fail due to unique constraint violation + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + if ($response['headers']['status-code'] === 200) { + // If transaction succeeded, all documents should be created + $documents = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + // Should have 4 documents total (1 original + 3 from transaction) + // But since we have a unique constraint violation, this might fail + $this->assertGreaterThanOrEqual(1, $documents['body']['total']); + } else { + $this->assertEquals(409, $response['headers']['status-code']); // Conflict error + + // Verify NO new documents were created (atomicity) + $documents = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(1, $documents['body']['total']); // Only the original document + $this->assertEquals('existing@example.com', $documents['body']['documents'][0]['email']); + } + } + + /** + * Test consistency - schema validation and constraints + */ + public function testConsistency(): void + { + // Create database + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'ConsistencyTestDB' + ]); + + $this->assertEquals(201, $database['headers']['status-code']); + $databaseId = $database['body']['$id']; + + // Create collection with required fields and constraints + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'ConsistencyTest', + 'documentSecurity' => false, + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Add required string attribute + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'required_field', + 'size' => 256, + 'required' => true, + ]); + + // Add integer attribute with min/max constraints + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'age', + 'required' => true, + 'min' => 18, + 'max' => 100 + ]); + + sleep(3); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $transactionId = $transaction['body']['$id']; + + // Add operations with both valid and invalid data + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'create', + 'documentId' => ID::unique(), + 'data' => [ + 'required_field' => 'Valid User', + 'age' => 25 // Valid age + ] + ], + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'create', + 'documentId' => ID::unique(), + 'data' => [ + 'required_field' => 'Too Young User', + 'age' => 10 // Below minimum - will fail constraint + ] + ], + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'create', + 'documentId' => ID::unique(), + 'data' => [ + 'required_field' => 'Another Valid User', + 'age' => 30 // Valid but should not be created due to transaction failure + ] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Attempt to commit - should fail due to constraint violation + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertContains($response['headers']['status-code'], [400, 500], 'Transaction commit should fail due to validation. Response: ' . json_encode($response['body'])); + + // Verify no documents were created + $documents = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(0, $documents['body']['total']); + } + + /** + * Test isolation - concurrent transactions on same data + */ + public function testIsolation(): void + { + // Create database + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'IsolationTestDB' + ]); + + $this->assertEquals(201, $database['headers']['status-code']); + $databaseId = $database['body']['$id']; + + // Create collection + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'IsolationTest', + 'documentSecurity' => false, + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Add counter attribute + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'counter', + 'required' => true, + 'min' => 0, + 'max' => 1000000 + ]); + + sleep(2); + + // Create initial document with counter + $doc = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'documentId' => 'shared_counter', + 'data' => [ + 'counter' => 0 + ] + ]); + + $this->assertEquals(201, $doc['headers']['status-code']); + + // Create first transaction + $transaction1 = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(201, $transaction1['headers']['status-code'], 'Transaction 1 creation should succeed'); + $this->assertArrayHasKey('$id', $transaction1['body'], 'Transaction 1 response should have $id'); + $transactionId1 = $transaction1['body']['$id']; + + // Create second transaction + $transaction2 = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(201, $transaction2['headers']['status-code'], 'Transaction 2 creation should succeed'); + $this->assertArrayHasKey('$id', $transaction2['body'], 'Transaction 2 response should have $id'); + $transactionId2 = $transaction2['body']['$id']; + + // Transaction 1: Increment counter by 10 + $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId1}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'documentId' => 'shared_counter', + 'action' => 'increment', + 'data' => [ + 'attribute' => 'counter', + 'value' => 10 + ] + ] + ] + ]); + + // Transaction 2: Increment counter by 5 + $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId2}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'documentId' => 'shared_counter', + 'action' => 'increment', + 'data' => [ + 'attribute' => 'counter', + 'value' => 5 + ] + ] + ] + ]); + + // Commit first transaction + $response1 = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId1}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response1['headers']['status-code']); + + // Commit second transaction + $response2 = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId2}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response2['headers']['status-code']); + + // Check final value - both increments should be applied + $document = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/shared_counter", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + // Both increments should be applied: 0 + 10 + 5 = 15 + $this->assertEquals(15, $document['body']['counter']); + } + + /** + * Test durability - committed data persists + */ + public function testDurability(): void + { + // Create database + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'DurabilityTestDB' + ]); + + $this->assertEquals(201, $database['headers']['status-code']); + $databaseId = $database['body']['$id']; + + // Create collection + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'DurabilityTest', + 'documentSecurity' => false, + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Add attribute + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'data', + 'size' => 256, + 'required' => true, + ]); + + sleep(2); + + // Create and commit transaction with multiple operations + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(201, $transaction['headers']['status-code'], 'Transaction creation should succeed'); + $this->assertArrayHasKey('$id', $transaction['body'], 'Transaction response should have $id'); + $transactionId = $transaction['body']['$id']; + + // Add multiple operations + $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'create', + 'documentId' => 'durable_doc_1', + 'data' => [ + 'data' => 'Important data 1' + ] + ], + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'create', + 'documentId' => 'durable_doc_2', + 'data' => [ + 'data' => 'Important data 2' + ] + ], + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'update', + 'documentId' => 'durable_doc_1', + 'data' => [ + 'data' => 'Updated important data 1' + ] + ] + ] + ]); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code'], 'Commit should succeed. Response: ' . json_encode($response['body'])); + $this->assertEquals('committed', $response['body']['status']); + + // List all documents to see what was created + $allDocs = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertGreaterThan(0, $allDocs['body']['total'], 'Should have created documents. Found: ' . json_encode($allDocs['body'])); + + // Verify documents exist and have correct data + $document1 = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/durable_doc_1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $document1['headers']['status-code']); + $this->assertEquals('Updated important data 1', $document1['body']['data']); + + $document2 = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/durable_doc_2", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $document2['headers']['status-code']); + $this->assertEquals('Important data 2', $document2['body']['data']); + + // Further update outside transaction to ensure persistence + $update = $this->client->call(Client::METHOD_PATCH, "/databases/{$databaseId}/collections/{$collectionId}/documents/durable_doc_1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'data' => 'Modified outside transaction' + ] + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + // Verify the update persisted + $document1 = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/durable_doc_1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals('Modified outside transaction', $document1['body']['data']); + + // List all documents to verify total count + $documents = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(2, $documents['body']['total']); + } +} diff --git a/tests/e2e/Services/Databases/Legacy/Transactions/TransactionsBase.php b/tests/e2e/Services/Databases/Legacy/Transactions/TransactionsBase.php new file mode 100644 index 0000000000..0f85de0ff5 --- /dev/null +++ b/tests/e2e/Services/Databases/Legacy/Transactions/TransactionsBase.php @@ -0,0 +1,4661 @@ +client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'TransactionTestDatabase' + ]); + + $this->assertEquals(201, $database['headers']['status-code']); + $databaseId = $database['body']['$id']; + + // Test creating a transaction with default TTL + $response = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertArrayHasKey('$id', $response['body']); + $this->assertArrayHasKey('status', $response['body']); + $this->assertArrayHasKey('operations', $response['body']); + $this->assertArrayHasKey('expiresAt', $response['body']); + $this->assertEquals('pending', $response['body']['status']); + $this->assertEquals(0, $response['body']['operations']); + + $transactionId1 = $response['body']['$id']; + + // Test creating a transaction with custom TTL + $response = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'ttl' => 900 + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertEquals('pending', $response['body']['status']); + + $expiresAt = new \DateTime($response['body']['expiresAt']); + $now = new \DateTime(); + $diff = $expiresAt->getTimestamp() - $now->getTimestamp(); + $this->assertGreaterThan(800, $diff); + $this->assertLessThan(1000, $diff); + + $transactionId2 = $response['body']['$id']; + + // Test invalid TTL values + $response = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'ttl' => 30 // Below minimum + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'ttl' => 4000 // Above maximum + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + } + + /** + * Test adding operations to a transaction + */ + public function testCreateOperations(): void + { + // Create database first + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'TransactionOperationsTestDB' + ]); + + $this->assertEquals(201, $database['headers']['status-code']); + $databaseId = $database['body']['$id']; + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + $transactionId = $transaction['body']['$id']; + + // Create a collection for testing + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'TransactionOperationsTest', + 'documentSecurity' => false, + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $this->assertEquals(201, $collection['headers']['status-code']); + $collectionId = $collection['body']['$id']; + + // Add attributes + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->assertEquals(202, $attribute['headers']['status-code']); + + // Wait for attribute to be created + sleep(2); + + // Add valid operations + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'create', + 'documentId' => 'doc1', + 'data' => [ + 'name' => 'Test Document 1' + ] + ], + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'create', + 'documentId' => 'doc2', + 'data' => [ + 'name' => 'Test Document 2' + ] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertEquals(2, $response['body']['operations']); + + // Test adding more operations + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'update', + 'documentId' => 'doc1', + 'data' => [ + 'name' => 'Updated Document 1' + ] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertEquals(3, $response['body']['operations']); + + // Test invalid database ID + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => 'invalid_database', + 'collectionId' => $collectionId, + 'action' => 'create', + 'documentId' => ID::unique(), + 'data' => ['name' => 'Test'] + ] + ] + ]); + + $this->assertEquals(404, $response['headers']['status-code'], 'Invalid database should return 404. Got: ' . json_encode($response['body'])); + + // Test invalid collection ID + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'collectionId' => 'invalid_collection', + 'action' => 'create', + 'documentId' => ID::unique(), + 'data' => ['name' => 'Test'] + ] + ] + ]); + + $this->assertEquals(404, $response['headers']['status-code']); + } + + /** + * Test committing a transaction + */ + public function testCommit(): void + { + // Create database first + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'TransactionCommitTestDB' + ]); + + $this->assertEquals(201, $database['headers']['status-code']); + $databaseId = $database['body']['$id']; + + // Create collection + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'TransactionCommitTest', + 'documentSecurity' => false, + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $this->assertEquals(201, $collection['headers']['status-code']); + $collectionId = $collection['body']['$id']; + + // Add attributes + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->assertEquals(202, $attribute['headers']['status-code']); + sleep(2); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + $transactionId = $transaction['body']['$id']; + + // Add operations + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'create', + 'documentId' => 'doc1', + 'data' => [ + 'name' => 'Test Document 1' + ] + ], + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'create', + 'documentId' => 'doc2', + 'data' => [ + 'name' => 'Test Document 2' + ] + ], + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'update', + 'documentId' => 'doc1', + 'data' => [ + 'name' => 'Updated Document 1' + ] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertEquals(3, $response['body']['operations']); + + // Commit the transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('committed', $response['body']['status']); + + // Verify documents were created + $documents = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $documents['headers']['status-code']); + $this->assertEquals(2, $documents['body']['total']); + + // Verify the update was applied + $doc1Found = false; + foreach ($documents['body']['documents'] as $doc) { + if ($doc['$id'] === 'doc1') { + $this->assertEquals('Updated Document 1', $doc['name']); + $doc1Found = true; + } + } + $this->assertTrue($doc1Found, 'Document doc1 should exist with updated name'); + + // Test committing already committed transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + } + + /** + * Test rolling back a transaction + */ + public function testRollback(): void + { + // Create database first + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'TransactionRollbackTestDB' + ]); + + $this->assertEquals(201, $database['headers']['status-code']); + $databaseId = $database['body']['$id']; + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + $transactionId = $transaction['body']['$id']; + + // Create a collection for rollback test + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'TransactionRollbackTest', + 'documentSecurity' => false, + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Add attribute + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'value', + 'size' => 256, + 'required' => true, + ]); + + sleep(2); + + // Add operations + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'create', + 'documentId' => 'rollback_doc', + 'data' => [ + 'value' => 'Should not exist' + ] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Rollback the transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rollback' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('failed', $response['body']['status']); + + // Verify no documents were created + $documents = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $documents['headers']['status-code']); + $this->assertEquals(0, $documents['body']['total']); + } + + /** + * Test transaction expiration + */ + public function testTransactionExpiration(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'ExpirationTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Create attribute + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'data', + 'size' => 256, + 'required' => false, + ]); + + sleep(2); + + // Create transaction with minimum TTL (60 seconds) + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'ttl' => 60 + ]); + + $this->assertEquals(201, $transaction['headers']['status-code']); + $transactionId = $transaction['body']['$id']; + + // Add operation + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'create', + 'documentId' => ID::unique(), + 'data' => ['data' => 'Should expire'] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Verify transaction was created with correct expiration + $txnDetails = $this->client->call(Client::METHOD_GET, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(200, $txnDetails['headers']['status-code']); + $this->assertEquals('pending', $txnDetails['body']['status']); + + // Verify expiration time is approximately 60 seconds from now + $expiresAt = new \DateTime($txnDetails['body']['expiresAt']); + $now = new \DateTime(); + $diff = $expiresAt->getTimestamp() - $now->getTimestamp(); + $this->assertGreaterThan(55, $diff); + $this->assertLessThan(65, $diff); + } + + /** + * Test maximum operations per transaction + */ + public function testTransactionSizeLimit(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'SizeLimitTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [Permission::create(Role::any())], + ]); + + $collectionId = $collection['body']['$id']; + + // Create attribute + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'value', + 'size' => 256, + 'required' => false, + ]); + + sleep(2); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Try to add operations exceeding the limit (assuming limit is 100) + // We'll add 50 operations twice to test incremental limit + $operations = []; + for ($i = 0; $i < 50; $i++) { + $operations[] = [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'create', + 'documentId' => 'doc_' . $i, + 'data' => ['value' => 'Test ' . $i] + ]; + } + + // First batch should succeed + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => $operations + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertEquals(50, $response['body']['operations']); + + // Second batch of 50 more operations + $operations = []; + for ($i = 50; $i < 100; $i++) { + $operations[] = [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'documentId' => 'doc_' . $i, + 'action' => 'create', + 'data' => ['value' => 'Test ' . $i] + ]; + } + + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => $operations + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertEquals(100, $response['body']['operations']); + + // Try to add one more operation - should fail + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'create', + 'documentId' => 'doc_overflow', + 'data' => ['value' => 'This should fail'] + ] + ] + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + } + + /** + * Test concurrent transactions with conflicting operations + */ + public function testConcurrentTransactionConflicts(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'ConflictTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Create attribute + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/integer", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'counter', + 'required' => true, + 'min' => 0, + 'max' => 1000000, + ]); + + sleep(2); + + // Create initial document + $doc = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => 'shared_doc', + 'data' => ['counter' => 100] + ]); + + $this->assertEquals(201, $doc['headers']['status-code']); + + // Create two transactions + $txn1 = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $txn2 = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId1 = $txn1['body']['$id']; + $transactionId2 = $txn2['body']['$id']; + + // Both transactions try to update the same document + $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId1}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'update', + 'documentId' => 'shared_doc', + 'data' => ['counter' => 200] + ] + ] + ]); + + $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId2}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'update', + 'documentId' => 'shared_doc', + 'data' => ['counter' => 300] + ] + ] + ]); + + // Commit first transaction + $response1 = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId1}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response1['headers']['status-code']); + + // Commit second transaction - should fail with conflict + $response2 = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId2}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(409, $response2['headers']['status-code']); // Conflict + + // Verify the document has the value from first transaction + $doc = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/shared_doc", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $doc['body']['counter']); + } + + /** + * Test deleting a document that's being updated in a transaction + */ + public function testDeleteDocumentDuringTransaction(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'DeleteConflictDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Create attribute + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'data', + 'size' => 256, + 'required' => false, + ]); + + sleep(2); + + // Create document + $doc = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => 'target_doc', + 'data' => ['data' => 'Original'] + ]); + + $this->assertEquals(201, $doc['headers']['status-code']); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Add update operation to transaction + $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'update', + 'documentId' => 'target_doc', + 'data' => ['data' => 'Updated in transaction'] + ] + ] + ]); + + // Delete the document outside of transaction + $response = $this->client->call(Client::METHOD_DELETE, "/databases/{$databaseId}/collections/{$collectionId}/documents/target_doc", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(204, $response['headers']['status-code']); + + // Try to commit transaction - should fail because document no longer exists + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(404, $response['headers']['status-code']); // Conflict + } + + /** + * Test bulk operations in transactions + */ + public function testBulkOperations(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkOpsDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Create attributes + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'category', + 'size' => 256, + 'required' => true, + ]); + + sleep(3); + + // Create some initial documents + for ($i = 1; $i <= 5; $i++) { + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => 'existing_' . $i, + 'data' => [ + 'name' => 'Existing ' . $i, + 'category' => 'old' + ] + ]); + } + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Add bulk operations + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + // Bulk create + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'bulkCreate', + 'data' => [ + ['$id' => 'bulk_1', 'name' => 'Bulk 1', 'category' => 'new'], + ['$id' => 'bulk_2', 'name' => 'Bulk 2', 'category' => 'new'], + ['$id' => 'bulk_3', 'name' => 'Bulk 3', 'category' => 'new'], + ] + ], + // Bulk update + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'bulkUpdate', + 'data' => [ + 'queries' => [Query::equal('category', ['old'])->toString()], + 'data' => ['category' => 'updated'] + ] + ], + // Bulk delete + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'bulkDelete', + 'data' => [ + 'queries' => [Query::equal('name', ['Existing 5'])->toString()] + ] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Verify results + $documents = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + // Should have 7 documents (5 existing - 1 deleted + 3 new) + $this->assertEquals(7, $documents['body']['total']); + + // Check categories were updated + $oldCategoryCount = 0; + $updatedCategoryCount = 0; + $newCategoryCount = 0; + + foreach ($documents['body']['documents'] as $doc) { + switch ($doc['category']) { + case 'old': + $oldCategoryCount++; + break; + case 'updated': + $updatedCategoryCount++; + break; + case 'new': + $newCategoryCount++; + break; + } + } + + $this->assertEquals(0, $oldCategoryCount); + $this->assertEquals(4, $updatedCategoryCount); // 4 existing docs updated + $this->assertEquals(3, $newCategoryCount); // 3 new docs + } + + /** + * Test transaction with mixed success and failure operations + */ + public function testPartialFailureRollback(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'PartialFailureDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Create attributes with constraints + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'email', + 'size' => 256, + 'required' => true, + ]); + + sleep(2); + + // Create unique index on email + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/indexes", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'unique_email', + 'type' => 'unique', + 'attributes' => ['email'], + ]); + + sleep(2); + + // Create an existing document + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => ID::unique(), + 'data' => ['email' => 'existing@example.com'] + ]); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Add operations - mix of valid and invalid + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'create', + 'documentId' => ID::unique(), + 'data' => ['email' => 'valid1@example.com'] // Valid + ], + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'create', + 'documentId' => ID::unique(), + 'data' => ['email' => 'valid2@example.com'] // Valid + ], + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'create', + 'documentId' => ID::unique(), + 'data' => ['email' => 'existing@example.com'] // Will fail - duplicate + ], + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'create', + 'documentId' => ID::unique(), + 'data' => ['email' => 'valid3@example.com'] // Would be valid but should rollback + ], + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Try to commit - should fail and rollback all operations + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(409, $response['headers']['status-code']); // Conflict due to duplicate + + // Verify NO new documents were created (atomicity) + $documents = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(1, $documents['body']['total']); // Only the original document + $this->assertEquals('existing@example.com', $documents['body']['documents'][0]['email']); + } + + /** + * Test double commit/rollback attempts + */ + public function testDoubleCommitRollback(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'DoubleCommitDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [Permission::create(Role::any())], + ]); + + $collectionId = $collection['body']['$id']; + + // Create attribute + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'data', + 'size' => 256, + 'required' => false, + ]); + + sleep(2); + + // Test double commit + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Add operation + $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'create', + 'documentId' => ID::unique(), + 'data' => ['data' => 'Test'] + ] + ] + ]); + + // First commit + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Second commit attempt - should fail + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(400, $response['headers']['status-code']); // Bad request - already committed + + // Test double rollback + $transaction2 = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId2 = $transaction2['body']['$id']; + + // First rollback + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId2}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rollback' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Second rollback attempt - should fail + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId2}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rollback' => true + ]); + + $this->assertEquals(400, $response['headers']['status-code']); // Bad request - already rolled back + } + + /** + * Test operations on non-existent documents + */ + public function testOperationsOnNonExistentDocuments(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'NonExistentDocDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Create attribute + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'data', + 'size' => 256, + 'required' => false, + ]); + + sleep(2); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Try to update non-existent document - should fail at staging time with early validation + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'update', + 'documentId' => 'non_existent_doc', + 'data' => ['data' => 'Should fail'] + ] + ] + ]); + + $this->assertEquals(404, $response['headers']['status-code']); // Document not found at staging time + + // Test delete non-existent document - should also fail at staging time with early validation + $transaction2 = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId2 = $transaction2['body']['$id']; + + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId2}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'delete', + 'documentId' => 'non_existent_doc', + 'data' => [] + ] + ] + ]); + + $this->assertEquals(404, $response['headers']['status-code']); // Document not found at staging time + } + + /** + * Test createDocument with transactionId via normal route + */ + public function testCreateDocument(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'WriteRoutesTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'TestCollection', + 'documentSecurity' => false, + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Create attributes + $attributes = [ + ['key' => 'name', 'type' => 'string', 'size' => 256, 'required' => true], + ['key' => 'counter', 'type' => 'integer', 'required' => false, 'min' => 0, 'max' => 10000], + ['key' => 'category', 'type' => 'string', 'size' => 256, 'required' => false], + ['key' => 'data', 'type' => 'string', 'size' => 256, 'required' => false], + ]; + + foreach ($attributes as $attr) { + $type = $attr['type']; + unset($attr['type']); + + $response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/{$type}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), $attr); + + $this->assertEquals(202, $response['headers']['status-code']); + } + + sleep(3); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + $transactionId = $transaction['body']['$id']; + + // Create document via normal route with transactionId + $response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => 'doc_from_route', + 'data' => [ + 'name' => 'Created via normal route', + 'counter' => 100, + 'category' => 'test' + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Document should not exist outside transaction yet + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/doc_from_route", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Document should now exist + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/doc_from_route", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('Created via normal route', $response['body']['name']); + } + + /** + * Test updateDocument with transactionId via normal route + */ + public function testUpdateDocument(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'UpdateRouteTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Create attributes + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/integer", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'counter', + 'required' => false, + 'min' => 0, + 'max' => 10000, + ]); + + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'category', + 'size' => 256, + 'required' => false, + ]); + + sleep(3); + + // Create document outside transaction + $doc = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => 'doc_to_update', + 'data' => [ + 'name' => 'Original name', + 'counter' => 50, + 'category' => 'original' + ] + ]); + + $this->assertEquals(201, $doc['headers']['status-code']); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Update document via normal route with transactionId + $response = $this->client->call(Client::METHOD_PATCH, "/databases/{$databaseId}/collections/{$collectionId}/documents/doc_to_update", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'data' => [ + 'name' => 'Updated via normal route', + 'counter' => 150, + 'category' => 'updated' + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Document should still have original values outside transaction + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/doc_to_update", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals('Original name', $response['body']['name']); + $this->assertEquals(50, $response['body']['counter']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Document should now have updated values + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/doc_to_update", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals('Updated via normal route', $response['body']['name']); + $this->assertEquals(150, $response['body']['counter']); + } + + /** + * Test upsertDocument with transactionId via normal route + */ + public function testUpsertDocument(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'UpsertRouteTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Create attributes + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/integer", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'counter', + 'required' => false, + 'min' => 0, + 'max' => 10000, + ]); + + sleep(3); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Upsert document (create) via normal route with transactionId + $response = $this->client->call(Client::METHOD_PUT, "/databases/{$databaseId}/collections/{$collectionId}/documents/doc_upsert", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => 'doc_upsert', + 'data' => [ + 'name' => 'Created by upsert', + 'counter' => 25 + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Document should not exist outside transaction yet + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/doc_upsert", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code']); + + // Upsert same document (update) in same transaction + $response = $this->client->call(Client::METHOD_PUT, "/databases/{$databaseId}/collections/{$collectionId}/documents/doc_upsert", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => 'doc_upsert', + 'data' => [ + 'name' => 'Updated by upsert', + 'counter' => 75 + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(201, $response['headers']['status-code']); // Upsert in transaction returns 201 + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Document should now exist with updated values + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/doc_upsert", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('Updated by upsert', $response['body']['name']); + $this->assertEquals(75, $response['body']['counter']); + } + + /** + * Test deleteDocument with transactionId via normal route + */ + public function testDeleteDocument(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'DeleteRouteTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Create attribute + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + sleep(2); + + // Create document outside transaction + $doc = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => 'doc_to_delete', + 'data' => ['name' => 'Will be deleted'] + ]); + + $this->assertEquals(201, $doc['headers']['status-code']); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Delete document via normal route with transactionId + $response = $this->client->call(Client::METHOD_DELETE, "/databases/{$databaseId}/collections/{$collectionId}/documents/doc_to_delete", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'transactionId' => $transactionId + ]); + + $this->assertEquals(204, $response['headers']['status-code']); + + // Document should still exist outside transaction + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/doc_to_delete", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Document should no longer exist + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/doc_to_delete", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code']); + } + + /** + * Test bulkCreate with transactionId via normal route + */ + public function testBulkCreate(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkCreateTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Create attributes + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'category', + 'size' => 256, + 'required' => false, + ]); + + sleep(3); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Bulk create via normal route with transactionId + $response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documents' => [ + [ + '$id' => 'bulk_create_1', + 'name' => 'Bulk created 1', + 'category' => 'bulk_created' + ], + [ + '$id' => 'bulk_create_2', + 'name' => 'Bulk created 2', + 'category' => 'bulk_created' + ], + [ + '$id' => 'bulk_create_3', + 'name' => 'Bulk created 3', + 'category' => 'bulk_created' + ] + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); // Bulk operations return 200 + + // Documents should not exist outside transaction yet + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [Query::equal('category', ['bulk_created'])->toString()] + ]); + + $this->assertEquals(0, $response['body']['total']); + + // Individual document check + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/bulk_create_1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Documents should now exist + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [Query::equal('category', ['bulk_created'])->toString()] + ]); + + $this->assertEquals(3, $response['body']['total']); + + // Verify individual documents + for ($i = 1; $i <= 3; $i++) { + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/bulk_create_{$i}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals("Bulk created {$i}", $response['body']['name']); + $this->assertEquals('bulk_created', $response['body']['category']); + } + } + + /** + * Test bulkUpdate with transactionId via normal route + */ + public function testBulkUpdate(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkUpdateTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Create attributes + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'category', + 'size' => 256, + 'required' => false, + ]); + + sleep(3); + + // Create documents for bulk testing + for ($i = 1; $i <= 3; $i++) { + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => 'bulk_update_' . $i, + 'data' => [ + 'name' => 'Bulk doc ' . $i, + 'category' => 'bulk_test' + ] + ]); + } + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Bulk update via normal route with transactionId + $response = $this->client->call(Client::METHOD_PATCH, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'queries' => [Query::equal('category', ['bulk_test'])->toString()], + 'data' => ['category' => 'bulk_updated'], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Documents should still have original category outside transaction + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [Query::equal('category', ['bulk_test'])->toString()] + ]); + + $this->assertEquals(3, $response['body']['total']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Documents should now have updated category + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [Query::equal('category', ['bulk_updated'])->toString()] + ]); + + $this->assertEquals(3, $response['body']['total']); + } + + /** + * Test bulkUpsert with transactionId via normal route + */ + public function testBulkUpsert(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkUpsertTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Create attributes + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/integer", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'counter', + 'required' => false, + 'min' => 0, + 'max' => 10000, + ]); + + sleep(3); + + // Create one document outside transaction + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => 'bulk_upsert_existing', + 'data' => [ + 'name' => 'Existing doc', + 'counter' => 10 + ] + ]); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Bulk upsert via normal route with transactionId (updates existing, creates new) + $response = $this->client->call(Client::METHOD_PUT, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documents' => [ + [ + '$id' => 'bulk_upsert_existing', + 'name' => 'Updated existing', + 'counter' => 20 + ], + [ + '$id' => 'bulk_upsert_new', + 'name' => 'New doc', + 'counter' => 30 + ] + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Original document should be unchanged, new document shouldn't exist outside transaction + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/bulk_upsert_existing", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals('Existing doc', $response['body']['name']); + $this->assertEquals(10, $response['body']['counter']); + + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/bulk_upsert_new", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Check both documents exist with updated values + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/bulk_upsert_existing", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals('Updated existing', $response['body']['name']); + $this->assertEquals(20, $response['body']['counter']); + + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/bulk_upsert_new", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals('New doc', $response['body']['name']); + $this->assertEquals(30, $response['body']['counter']); + } + + /** + * Test bulkDelete with transactionId via normal route + */ + public function testBulkDelete(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkDeleteTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Create attributes + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'category', + 'size' => 256, + 'required' => false, + ]); + + sleep(3); + + // Create documents for bulk testing + for ($i = 1; $i <= 3; $i++) { + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => 'bulk_delete_' . $i, + 'data' => [ + 'name' => 'Delete doc ' . $i, + 'category' => 'bulk_delete_test' + ] + ]); + } + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Bulk delete via normal route with transactionId + $response = $this->client->call(Client::METHOD_DELETE, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'queries' => [Query::equal('category', ['bulk_delete_test'])->toString()], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); // Bulk delete with transaction returns 200 + + // Documents should still exist outside transaction + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [Query::equal('category', ['bulk_delete_test'])->toString()] + ]); + + $this->assertEquals(3, $response['body']['total']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Documents should now be deleted + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [Query::equal('category', ['bulk_delete_test'])->toString()] + ]); + + $this->assertEquals(0, $response['body']['total']); + } + + /** + * Test multiple single route operations in one transaction + */ + public function testMixedSingleOperations(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'MultipleSingleRoutesDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Create attributes + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'status', + 'size' => 256, + 'required' => false, + ]); + + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/integer", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'priority', + 'required' => false, + 'min' => 1, + 'max' => 10, + ]); + + sleep(3); + + // Create an existing document outside transaction for testing + $existingDoc = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => 'existing_doc', + 'data' => [ + 'name' => 'Existing Document', + 'status' => 'active', + 'priority' => 5 + ] + ]); + + $this->assertEquals(201, $existingDoc['headers']['status-code']); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + $this->assertEquals(201, $transaction['headers']['status-code']); + + // 1. Create new document via normal route with transactionId + $response1 = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => 'new_doc_1', + 'data' => [ + 'name' => 'New Document 1', + 'status' => 'pending', + 'priority' => 1 + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(201, $response1['headers']['status-code']); + + // 2. Create another document via normal route with transactionId + $response2 = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => 'new_doc_2', + 'data' => [ + 'name' => 'New Document 2', + 'status' => 'pending', + 'priority' => 2 + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(201, $response2['headers']['status-code']); + + // 3. Update existing document via normal route with transactionId + $response3 = $this->client->call(Client::METHOD_PATCH, "/databases/{$databaseId}/collections/{$collectionId}/documents/existing_doc", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'data' => [ + 'status' => 'updated', + 'priority' => 10 + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response3['headers']['status-code']); + + // 4. Update the first new document (created in same transaction) + $response4 = $this->client->call(Client::METHOD_PATCH, "/databases/{$databaseId}/collections/{$collectionId}/documents/new_doc_1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'data' => [ + 'status' => 'active', + 'priority' => 8 + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response4['headers']['status-code']); + + // 5. Delete the second new document (created in same transaction) + $response5 = $this->client->call(Client::METHOD_DELETE, "/databases/{$databaseId}/collections/{$collectionId}/documents/new_doc_2", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'transactionId' => $transactionId + ]); + + $this->assertEquals(204, $response5['headers']['status-code']); + + // 6. Upsert a new document via normal route with transactionId + $response6 = $this->client->call(Client::METHOD_PUT, "/databases/{$databaseId}/collections/{$collectionId}/documents/upserted_doc", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => 'upserted_doc', + 'data' => [ + 'name' => 'Upserted Document', + 'status' => 'new', + 'priority' => 3 + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(201, $response6['headers']['status-code']); + + // Check transaction has correct number of operations + $txnDetails = $this->client->call(Client::METHOD_GET, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(200, $txnDetails['headers']['status-code']); + $this->assertEquals(6, $txnDetails['body']['operations']); // 6 operations total + + // Verify nothing exists outside transaction yet + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/new_doc_1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/upserted_doc", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code']); + + // Existing doc should still have original values + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/existing_doc", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals('active', $response['body']['status']); + $this->assertEquals(5, $response['body']['priority']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('committed', $response['body']['status']); + + // Verify final state after commit + // new_doc_1 should exist with updated values + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/new_doc_1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('New Document 1', $response['body']['name']); + $this->assertEquals('active', $response['body']['status']); + $this->assertEquals(8, $response['body']['priority']); + + // new_doc_2 should not exist (was deleted in transaction) + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/new_doc_2", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code']); + + // existing_doc should have updated values + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/existing_doc", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals('updated', $response['body']['status']); + $this->assertEquals(10, $response['body']['priority']); + + // upserted_doc should exist + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/upserted_doc", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('Upserted Document', $response['body']['name']); + $this->assertEquals('new', $response['body']['status']); + $this->assertEquals(3, $response['body']['priority']); + + // Verify total document count + $documents = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(3, $documents['body']['total']); // existing_doc, new_doc_1, upserted_doc + } + + /** + * Test mixed operations with transactions + */ + public function testMixedOperations(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'MixedOpsTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Create attribute + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + sleep(2); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Add operation via Operations\Add endpoint + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'create', + 'documentId' => 'mixed_doc1', + 'data' => ['name' => 'Via Operations Add'] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertEquals(1, $response['body']['operations']); + + // Add operation via normal route with transactionId + $response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => 'mixed_doc2', + 'data' => ['name' => 'Via normal route'], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Check transaction now has 2 operations + $txnDetails = $this->client->call(Client::METHOD_GET, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(2, $txnDetails['body']['operations']); + + // Both documents shouldn't exist yet + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/mixed_doc1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/mixed_doc2", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Both documents should now exist + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/mixed_doc1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('Via Operations Add', $response['body']['name']); + + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/mixed_doc2", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('Via normal route', $response['body']['name']); + } + + /** + * Test bulk update with queries that should match documents created in the same transaction + */ + public function testBulkUpdateWithTransactionAwareQueries(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkTxnAwareDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Create attributes + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/integer", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'age', + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'status', + 'size' => 256, + 'required' => true, + ]); + + sleep(3); // Wait for attributes to be created + + // Create some existing documents + for ($i = 1; $i <= 3; $i++) { + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => 'existing_' . $i, + 'data' => [ + 'name' => 'Existing ' . $i, + 'age' => 20 + $i, + 'status' => 'inactive' + ] + ]); + } + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Step 1: Create new documents with age > 25 in transaction + $response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => 'txn_doc_1', + 'data' => [ + 'name' => 'Transaction Doc 1', + 'age' => 30, + 'status' => 'inactive' + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => 'txn_doc_2', + 'data' => [ + 'name' => 'Transaction Doc 2', + 'age' => 35, + 'status' => 'inactive' + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Step 2: Bulk update all documents with age > 25 to have status 'active' + // This should match both existing_3 (age=23 doesn't match, age=24 doesn't match, but existing documents have age 21,22,23) + // Wait, let me fix the ages - existing docs have ages 21, 22, 23, so only txn docs should match + $response = $this->client->call(Client::METHOD_PATCH, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'data' => [ + 'status' => 'active' + ], + 'queries' => [Query::greaterThan('age', 25)->toString()], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Verify that documents created in the transaction were updated by the bulk update + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/txn_doc_1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('active', $response['body']['status'], 'Document created in transaction should be updated by bulk update query'); + + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/txn_doc_2", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('active', $response['body']['status'], 'Document created in transaction should be updated by bulk update query'); + + // Verify existing documents were not affected + for ($i = 1; $i <= 3; $i++) { + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/existing_{$i}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('inactive', $response['body']['status'], "Existing document {$i} should remain inactive (age <= 25)"); + } + } + + /** + * Test bulk update with queries that should match documents updated in the same transaction + */ + public function testBulkUpdateMatchingUpdatedDocuments(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkUpdateTxnDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Create attributes + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'category', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'priority', + 'size' => 256, + 'required' => true, + ]); + + sleep(3); // Wait for attributes to be created + + // Create existing documents + for ($i = 1; $i <= 4; $i++) { + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => 'doc_' . $i, + 'data' => [ + 'name' => 'Document ' . $i, + 'category' => 'normal', + 'priority' => 'low' + ] + ]); + } + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Step 1: Update some documents to have category 'special' in transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/{$databaseId}/collections/{$collectionId}/documents/doc_1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'data' => [ + 'category' => 'special' + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_PATCH, "/databases/{$databaseId}/collections/{$collectionId}/documents/doc_2", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'data' => [ + 'category' => 'special' + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Step 2: Bulk update all documents with category 'special' to have priority 'high' + // This should match the documents we just updated in the transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'data' => [ + 'priority' => 'high' + ], + 'queries' => [Query::equal('category', ['special'])->toString()], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Verify that the updated documents were matched by bulk update + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/doc_1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('special', $response['body']['category']); + $this->assertEquals('high', $response['body']['priority'], 'Document updated in transaction should be matched by bulk update query'); + + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/doc_2", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('special', $response['body']['category']); + $this->assertEquals('high', $response['body']['priority'], 'Document updated in transaction should be matched by bulk update query'); + + // Verify other documents were not affected + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/doc_3", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('normal', $response['body']['category']); + $this->assertEquals('low', $response['body']['priority']); + } + + /** + * Test bulk delete with queries that should match documents created in the same transaction + */ + public function testBulkDeleteMatchingCreatedDocuments(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkDeleteTxnDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Create attributes + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'type', + 'size' => 256, + 'required' => true, + ]); + + sleep(3); // Wait for attributes to be created + + // Create existing documents + for ($i = 1; $i <= 3; $i++) { + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => 'existing_' . $i, + 'data' => [ + 'name' => 'Existing ' . $i, + 'type' => 'permanent' + ] + ]); + } + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Step 1: Create temporary documents in transaction + $response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => 'temp_1', + 'data' => [ + 'name' => 'Temporary 1', + 'type' => 'temporary' + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => 'temp_2', + 'data' => [ + 'name' => 'Temporary 2', + 'type' => 'temporary' + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Step 2: Bulk delete all documents with type 'temporary' + // This should delete the documents we just created in the transaction + $response = $this->client->call(Client::METHOD_DELETE, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'queries' => [Query::equal('type', ['temporary'])->toString()], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Verify temporary documents were deleted (should not exist) + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/temp_1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code'], 'Temporary document created and deleted in transaction should not exist'); + + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/temp_2", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code'], 'Temporary document created and deleted in transaction should not exist'); + + // Verify existing documents were not affected + for ($i = 1; $i <= 3; $i++) { + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/existing_{$i}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code'], "Permanent document {$i} should still exist"); + $this->assertEquals('permanent', $response['body']['type']); + } + } + + /** + * Test bulk delete with queries that should match documents updated in the same transaction + */ + public function testBulkDeleteMatchingUpdatedDocuments(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkDeleteUpdateTxnDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Create attributes + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'status', + 'size' => 256, + 'required' => true, + ]); + + sleep(3); // Wait for attributes to be created + + // Create existing documents + for ($i = 1; $i <= 5; $i++) { + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => 'doc_' . $i, + 'data' => [ + 'name' => 'Document ' . $i, + 'status' => 'active' + ] + ]); + } + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Step 1: Mark some documents for deletion by updating their status + $response = $this->client->call(Client::METHOD_PATCH, "/databases/{$databaseId}/collections/{$collectionId}/documents/doc_2", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'data' => [ + 'status' => 'marked_for_deletion' + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_PATCH, "/databases/{$databaseId}/collections/{$collectionId}/documents/doc_4", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'data' => [ + 'status' => 'marked_for_deletion' + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Step 2: Bulk delete all documents with status 'marked_for_deletion' + // This should delete the documents we just updated in the transaction + $response = $this->client->call(Client::METHOD_DELETE, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'queries' => [Query::equal('status', ['marked_for_deletion'])->toString()], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Verify marked documents were deleted + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/doc_2", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code'], 'Document marked for deletion should have been deleted'); + + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/doc_4", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code'], 'Document marked for deletion should have been deleted'); + + // Verify other documents still exist + foreach ([1, 3, 5] as $i) { + $response = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/doc_{$i}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code'], "Document {$i} should still exist"); + $this->assertEquals('active', $response['body']['status']); + } + } + + /** + * Test increment and decrement operations in transaction + */ + public function testIncrementDecrementOperations(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'IncrementDecrementTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'CounterCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Add integer attributes + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/integer", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'counter', + 'required' => false, + 'default' => 0, + ]); + + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/integer", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'score', + 'required' => false, + 'default' => 100, + ]); + + sleep(2); + + // Create initial document + $doc = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'documentId' => 'counter_doc', + 'data' => [ + 'counter' => 10, + 'score' => 50 + ] + ]); + + $this->assertEquals(201, $doc['headers']['status-code']); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Add increment and decrement operations + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'increment', + 'documentId' => 'counter_doc', + 'data' => [ + 'attribute' => 'counter', + 'value' => 5, + ] + ], + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'decrement', + 'documentId' => 'counter_doc', + 'data' => [ + 'attribute' => 'score', + 'value' => 20, + ] + ], + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'increment', + 'documentId' => 'counter_doc', + 'data' => [ + 'attribute' => 'counter', + 'value' => 3, + 'max' => 20 + ] + ], + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'decrement', + 'documentId' => 'counter_doc', + 'data' => [ + 'attribute' => 'score', + 'value' => 30, + 'min' => 0 + ] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Verify final values + $doc = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/counter_doc", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $doc['headers']['status-code']); + // counter: 10 + 5 + 3 = 18 (capped at 20 max) + $this->assertEquals(18, $doc['body']['counter']); + // score: 50 - 20 - 100 = -70, but min is 0 + $this->assertEquals(0, $doc['body']['score']); + } + + /** + * Test individual increment/decrement endpoints with transactions for Legacy Collections API + * This test ensures that: + * 1. Transaction logs store the correct attribute key ('attribute' for Collections API) + * 2. Mock responses return the correct ID keys ('$collectionId' not '$tableId') + */ + public function testIncrementDecrementEndpointsWithTransaction(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'IncrDecrEndpointTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'AccountsCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Add balance attribute + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/integer", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'balance', + 'required' => false, + 'default' => 0, + ]); + + sleep(2); + + // Create initial documents + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'documentId' => 'joe', + 'data' => ['balance' => 100] + ]); + + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'documentId' => 'jane', + 'data' => ['balance' => 50] + ]); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + $transactionId = $transaction['body']['$id']; + + // Test: Decrement using individual endpoint - should store 'attribute' not 'column' in transaction log + $decrementResponse = $this->client->call( + Client::METHOD_PATCH, + "/databases/{$databaseId}/collections/{$collectionId}/documents/joe/balance/decrement", + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), + [ + 'transactionId' => $transactionId, + 'value' => 50, + 'min' => 0, + ] + ); + + // Test: Response should return '$collectionId' not '$tableId' for Collections API + $this->assertEquals(200, $decrementResponse['headers']['status-code']); + $this->assertArrayHasKey('$collectionId', $decrementResponse['body'], 'Response should contain $collectionId for Collections API'); + $this->assertArrayNotHasKey('$tableId', $decrementResponse['body'], 'Response should not contain $tableId for Collections API'); + $this->assertEquals($collectionId, $decrementResponse['body']['$collectionId']); + + // Test increment endpoint + $incrementResponse = $this->client->call( + Client::METHOD_PATCH, + "/databases/{$databaseId}/collections/{$collectionId}/documents/jane/balance/increment", + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), + [ + 'transactionId' => $transactionId, + 'value' => 50, + ] + ); + + $this->assertEquals(200, $incrementResponse['headers']['status-code']); + $this->assertArrayHasKey('$collectionId', $incrementResponse['body'], 'Response should contain $collectionId for Collections API'); + $this->assertArrayNotHasKey('$tableId', $incrementResponse['body'], 'Response should not contain $tableId for Collections API'); + $this->assertEquals($collectionId, $incrementResponse['body']['$collectionId']); + + // Commit transaction - this will fail if transaction log has 'column' instead of 'attribute' + $commitResponse = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'commit' => true + ]); + + $this->assertEquals(200, $commitResponse['headers']['status-code'], 'Transaction commit should succeed'); + + // Verify final values + $joe = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/joe", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $jane = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents/jane", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $joe['headers']['status-code']); + $this->assertEquals(50, $joe['body']['balance'], 'Joe should have 100 - 50 = 50'); + + $this->assertEquals(200, $jane['headers']['status-code']); + $this->assertEquals(100, $jane['body']['balance'], 'Jane should have 50 + 50 = 100'); + } + + /** + * Test bulk update operations in transaction + */ + public function testBulkUpdateOperations(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkUpdateTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'BulkUpdateCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Add attributes + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'status', + 'size' => 50, + 'required' => false, + ]); + + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'category', + 'size' => 50, + 'required' => false, + ]); + + sleep(2); + + // Create initial documents + for ($i = 1; $i <= 5; $i++) { + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'documentId' => "doc_{$i}", + 'data' => [ + 'status' => 'pending', + 'category' => $i % 2 === 0 ? 'even' : 'odd' + ] + ]); + } + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Add bulk update operations + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'bulkUpdate', + 'data' => [ + 'queries' => [ + Query::equal('category', ['even'])->toString() + ], + 'data' => [ + 'status' => 'approved' + ] + ] + ], + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'bulkUpdate', + 'data' => [ + 'queries' => [ + Query::equal('category', ['odd'])->toString() + ], + 'data' => [ + 'status' => 'rejected' + ] + ] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Verify updates + $docs = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + foreach ($docs['body']['documents'] as $doc) { + if ($doc['category'] === 'even') { + $this->assertEquals('approved', $doc['status']); + } else { + $this->assertEquals('rejected', $doc['status']); + } + } + } + + /** + * Test bulk upsert operations in transaction + */ + public function testBulkUpsertOperations(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkUpsertTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'BulkUpsertCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Add attributes + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 100, + 'required' => false, + ]); + + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/integer", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'value', + 'required' => false, + ]); + + sleep(2); + + // Create some initial documents + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'documentId' => 'existing_1', + 'data' => [ + 'name' => 'Existing Document 1', + 'value' => 10 + ] + ]); + + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'documentId' => 'existing_2', + 'data' => [ + 'name' => 'Existing Document 2', + 'value' => 20 + ] + ]); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Add bulk upsert operations + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'bulkUpsert', + 'data' => [ + [ + '$id' => 'existing_1', + 'name' => 'Updated Document 1', + 'value' => 100 + ], + [ + '$id' => 'new_1', + 'name' => 'New Document 1', + 'value' => 30 + ], + [ + '$id' => 'new_2', + 'name' => 'New Document 2', + 'value' => 40 + ] + ] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Verify results + $docs = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(4, $docs['body']['total']); + + $docMap = []; + foreach ($docs['body']['documents'] as $doc) { + $docMap[$doc['$id']] = $doc; + } + + // Verify updated document + $this->assertEquals('Updated Document 1', $docMap['existing_1']['name']); + $this->assertEquals(100, $docMap['existing_1']['value']); + + // Verify unchanged document + $this->assertEquals('Existing Document 2', $docMap['existing_2']['name']); + $this->assertEquals(20, $docMap['existing_2']['value']); + + // Verify new documents + $this->assertEquals('New Document 1', $docMap['new_1']['name']); + $this->assertEquals(30, $docMap['new_1']['value']); + $this->assertEquals('New Document 2', $docMap['new_2']['name']); + $this->assertEquals(40, $docMap['new_2']['value']); + } + + /** + * Test bulk delete operations in transaction + */ + public function testBulkDeleteOperations(): void + { + // Create database and collection + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkDeleteTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'BulkDeleteCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Add attributes + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'type', + 'size' => 50, + 'required' => false, + ]); + + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/attributes/integer", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'priority', + 'required' => false, + ]); + + sleep(2); + + // Create initial documents + for ($i = 1; $i <= 10; $i++) { + $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'documentId' => "doc_{$i}", + 'data' => [ + 'type' => $i <= 5 ? 'temp' : 'permanent', + 'priority' => $i + ] + ]); + } + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Add bulk delete operations + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'bulkDelete', + 'data' => [ + 'queries' => [ + Query::equal('type', ['temp'])->toString() + ] + ] + ], + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'action' => 'bulkDelete', + 'data' => [ + 'queries' => [ + Query::greaterThan('priority', 8)->toString() + ] + ] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Verify deletions + $docs = $this->client->call(Client::METHOD_GET, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + // Should have deleted docs 1-5 (temp) and docs 9-10 (priority > 8) + // Remaining should be docs 6-8 + $this->assertEquals(3, $docs['body']['total']); + + $remainingIds = array_map(fn ($doc) => $doc['$id'], $docs['body']['documents']); + sort($remainingIds); + $this->assertEquals(['doc_6', 'doc_7', 'doc_8'], $remainingIds); + } + + /** + * Test validation for invalid operation inputs + */ + public function testCreateOperationsValidation(): void + { + // Create database and collection for testing + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'ValidationTestDatabase' + ]); + + $this->assertEquals(201, $database['headers']['status-code']); + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'ValidationTest', + 'documentSecurity' => false, + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $this->assertEquals(201, $collection['headers']['status-code']); + $collectionId = $collection['body']['$id']; + + // Add required attribute + $attribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->assertEquals(202, $attribute['headers']['status-code']); + + // Wait for attribute to be ready + sleep(2); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + $transactionId = $transaction['body']['$id']; + + // Test 1: Invalid action type + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'action' => 'invalidAction', + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'documentId' => ID::unique(), + 'data' => ['name' => 'Test'] + ] + ] + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // Test 2: Missing required action field + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'documentId' => ID::unique(), + 'data' => ['name' => 'Test'] + ] + ] + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // Test 3: Missing required databaseId field + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'action' => 'create', + 'collectionId' => $collectionId, + 'documentId' => ID::unique(), + 'data' => ['name' => 'Test'] + ] + ] + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // Test 4: Missing documentId for create operation + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'action' => 'create', + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'data' => ['name' => 'Test'] + ] + ] + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // Test 5: Missing data for create operation + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'action' => 'create', + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'documentId' => ID::unique() + ] + ] + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // Test 6: BulkCreate with non-array data + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'action' => 'bulkCreate', + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'data' => 'not an array' + ] + ] + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // Test 7: BulkUpdate with missing queries + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'action' => 'bulkUpdate', + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'data' => [ + 'data' => ['name' => 'Updated'] + ] + ] + ] + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // Test 8: Empty operations array + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [] + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // Test 9: Operations not an array + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => 'not an array' + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + } + + /** + * Test validation for committing/rolling back transactions + */ + public function testCommitRollbackValidation(): void + { + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + $transactionId = $transaction['body']['$id']; + + // Test 1: Missing both commit and rollback + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), []); + + $this->assertEquals(400, $response['headers']['status-code']); + + // Test 2: Both commit and rollback set to true + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true, + 'rollback' => true + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // Test 3: Invalid transaction ID + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/invalid_id", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(404, $response['headers']['status-code']); + + // Commit the transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Test 4: Attempt to commit already committed transaction + $response = $this->client->call(Client::METHOD_PATCH, "/databases/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + } + + /** + * Test validation for non-existent resources + */ + public function testNonExistentResources(): void + { + // Create database and transaction + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'ResourceTestDatabase' + ]); + + $this->assertEquals(201, $database['headers']['status-code']); + $databaseId = $database['body']['$id']; + + $transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + $transactionId = $transaction['body']['$id']; + + // Test 1: Non-existent database + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'action' => 'create', + 'databaseId' => 'nonExistentDatabase', + 'collectionId' => 'someCollection', + 'documentId' => ID::unique(), + 'data' => ['name' => 'Test'] + ] + ] + ]); + + $this->assertEquals(404, $response['headers']['status-code']); + + // Test 2: Non-existent collection + $response = $this->client->call(Client::METHOD_POST, "/databases/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'action' => 'create', + 'databaseId' => $databaseId, + 'collectionId' => 'nonExistentCollection', + 'documentId' => ID::unique(), + 'data' => ['name' => 'Test'] + ] + ] + ]); + + $this->assertEquals(404, $response['headers']['status-code']); + } +} diff --git a/tests/e2e/Services/Databases/Legacy/Transactions/TransactionsConsoleClientTest.php b/tests/e2e/Services/Databases/Legacy/Transactions/TransactionsConsoleClientTest.php new file mode 100644 index 0000000000..ef6e9d15d0 --- /dev/null +++ b/tests/e2e/Services/Databases/Legacy/Transactions/TransactionsConsoleClientTest.php @@ -0,0 +1,14 @@ +client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'AtomicityTestDB' + ]); + + $this->assertEquals(201, $database['headers']['status-code']); + $databaseId = $database['body']['$id']; + + // Create table with unique constraint + $table = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'AtomicityTest', + 'rowSecurity' => false, + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Add unique column + $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'email', + 'size' => 256, + 'required' => true, + ]); + + // Add unique index + $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'unique_email', + 'type' => Database::INDEX_UNIQUE, + 'columns' => ['email'] + ]); + + sleep(3); + + // Create first row outside transaction + $doc1 = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => ID::unique(), + 'data' => [ + 'email' => 'existing@example.com' + ] + ]); + + $this->assertEquals(201, $doc1['headers']['status-code']); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(201, $transaction['headers']['status-code'], 'Transaction creation should succeed. Response: ' . json_encode($transaction)); + $this->assertArrayHasKey('$id', $transaction['body'], 'Transaction response should have $id. Response body: ' . json_encode($transaction['body'])); + $transactionId = $transaction['body']['$id']; + + // Add operations - second one will fail due to unique constraint + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => ID::unique(), + 'data' => [ + 'email' => 'newuser@example.com' // This should succeed + ] + ], + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => ID::unique(), + 'data' => [ + 'email' => 'existing@example.com' // This will fail - duplicate + ] + ], + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => ID::unique(), + 'data' => [ + 'email' => 'anotheruser@example.com' // This should not be created due to atomicity + ] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code'], 'Add operations failed. Response: ' . json_encode($response['body'])); + + // Attempt to commit - should fail due to unique constraint violation + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + if ($response['headers']['status-code'] === 200) { + // If transaction succeeded, all rows should be created + $rows = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + // Should have 4 rows total (1 original + 3 from transaction) + // But since we have a unique constraint violation, this might fail + $this->assertGreaterThanOrEqual(1, $rows['body']['total']); + } else { + $this->assertEquals(409, $response['headers']['status-code']); // Conflict error + + // Verify NO new rows were created (atomicity) + $rows = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(1, $rows['body']['total']); // Only the original row + $this->assertEquals('existing@example.com', $rows['body']['rows'][0]['email']); + } + } + + /** + * Test consistency - schema validation and constraints + */ + public function testConsistency(): void + { + // Create database + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'ConsistencyTestDB' + ]); + + $this->assertEquals(201, $database['headers']['status-code']); + $databaseId = $database['body']['$id']; + + // Create table with required fields and constraints + $table = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'ConsistencyTest', + 'rowSecurity' => false, + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Add required string column + $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'required_field', + 'size' => 256, + 'required' => true, + ]); + + // Add integer column with min/max constraints + $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/integer', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'age', + 'required' => true, + 'min' => 18, + 'max' => 100 + ]); + + sleep(3); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $transactionId = $transaction['body']['$id']; + + // Add operations with both valid and invalid data + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => ID::unique(), + 'data' => [ + 'required_field' => 'Valid User', + 'age' => 25 // Valid age + ] + ], + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => ID::unique(), + 'data' => [ + 'required_field' => 'Too Young User', + 'age' => 10 // Below minimum - will fail constraint + ] + ], + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => ID::unique(), + 'data' => [ + 'required_field' => 'Another Valid User', + 'age' => 30 // Valid but should not be created due to transaction failure + ] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Attempt to commit - should fail due to constraint violation + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertContains($response['headers']['status-code'], [400, 500], 'Transaction commit should fail due to validation. Response: ' . json_encode($response['body'])); + + // Verify no rows were created + $rows = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(0, $rows['body']['total']); + } + + /** + * Test isolation - concurrent transactions on same data + */ + public function testIsolation(): void + { + // Create database + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'IsolationTestDB' + ]); + + $this->assertEquals(201, $database['headers']['status-code']); + $databaseId = $database['body']['$id']; + + // Create table + $table = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'IsolationTest', + 'rowSecurity' => false, + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Add counter column + $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/integer', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'counter', + 'required' => true, + 'min' => 0, + 'max' => 1000000 + ]); + + sleep(2); + + // Create initial row with counter + $doc = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => 'shared_counter', + 'data' => [ + 'counter' => 0 + ] + ]); + + $this->assertEquals(201, $doc['headers']['status-code']); + + // Create first transaction + $transaction1 = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(201, $transaction1['headers']['status-code'], 'Transaction 1 creation should succeed'); + $this->assertArrayHasKey('$id', $transaction1['body'], 'Transaction 1 response should have $id'); + $transactionId1 = $transaction1['body']['$id']; + + // Create second transaction + $transaction2 = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(201, $transaction2['headers']['status-code'], 'Transaction 2 creation should succeed'); + $this->assertArrayHasKey('$id', $transaction2['body'], 'Transaction 2 response should have $id'); + $transactionId2 = $transaction2['body']['$id']; + + // Transaction 1: Increment counter by 10 + $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId1}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'rowId' => 'shared_counter', + 'action' => 'increment', + 'data' => [ + 'column' => 'counter', + 'value' => 10 + ] + ] + ] + ]); + + // Transaction 2: Increment counter by 5 + $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId2}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'rowId' => 'shared_counter', + 'action' => 'increment', + 'data' => [ + 'column' => 'counter', + 'value' => 5 + ] + ] + ] + ]); + + // Commit first transaction + $response1 = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId1}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response1['headers']['status-code']); + + // Commit second transaction + $response2 = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId2}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response2['headers']['status-code']); + + // Check final value - both increments should be applied + $row = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/shared_counter", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + // Both increments should be applied: 0 + 10 + 5 = 15 + $this->assertEquals(15, $row['body']['counter']); + } + + /** + * Test durability - committed data persists + */ + public function testDurability(): void + { + // Create database + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'DurabilityTestDB' + ]); + + $this->assertEquals(201, $database['headers']['status-code']); + $databaseId = $database['body']['$id']; + + // Create table + $table = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'DurabilityTest', + 'rowSecurity' => false, + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Add column + $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'data', + 'size' => 256, + 'required' => true, + ]); + + sleep(2); + + // Create and commit transaction with multiple operations + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(201, $transaction['headers']['status-code'], 'Transaction creation should succeed'); + $this->assertArrayHasKey('$id', $transaction['body'], 'Transaction response should have $id'); + $transactionId = $transaction['body']['$id']; + + // Add multiple operations + $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => 'durable_doc_1', + 'data' => [ + 'data' => 'Important data 1' + ] + ], + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => 'durable_doc_2', + 'data' => [ + 'data' => 'Important data 2' + ] + ], + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'update', + 'rowId' => 'durable_doc_1', + 'data' => [ + 'data' => 'Updated important data 1' + ] + ] + ] + ]); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code'], 'Commit should succeed. Response: ' . json_encode($response['body'])); + $this->assertEquals('committed', $response['body']['status']); + + // List all rows to see what was created + $allDocs = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertGreaterThan(0, $allDocs['body']['total'], 'Should have created rows. Found: ' . json_encode($allDocs['body'])); + + // Verify rows exist and have correct data + $row1 = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/durable_doc_1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $row1['headers']['status-code']); + $this->assertEquals('Updated important data 1', $row1['body']['data']); + + $row2 = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/durable_doc_2", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $row2['headers']['status-code']); + $this->assertEquals('Important data 2', $row2['body']['data']); + + // Further update outside transaction to ensure persistence + $update = $this->client->call(Client::METHOD_PATCH, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/durable_doc_1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'data' => 'Modified outside transaction' + ] + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + // Verify the update persisted + $row1 = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/durable_doc_1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals('Modified outside transaction', $row1['body']['data']); + + // List all rows to verify total count + $rows = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(2, $rows['body']['total']); + } +} diff --git a/tests/e2e/Services/Databases/TablesDB/Transactions/PermissionsBase.php b/tests/e2e/Services/Databases/TablesDB/Transactions/PermissionsBase.php new file mode 100644 index 0000000000..a1082256ee --- /dev/null +++ b/tests/e2e/Services/Databases/TablesDB/Transactions/PermissionsBase.php @@ -0,0 +1,1216 @@ +client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'PermissionsTestDB' + ]); + + $this->assertEquals(201, $database['headers']['status-code']); + $this->permissionsDatabase = $database['body']['$id']; + } + + /** + * Test collection-level create permission check on staging + */ + public function testCollectionCreatePermissionDenied(): void + { + // Create a collection with no create permission for current user + $collection = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => 'permTest1', + 'name' => 'Permission Test 1', + 'permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'rowSecurity' => false, + ]); + + $this->assertEquals(201, $collection['headers']['status-code']); + + $attribute = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables/' . $collection['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'title', + 'size' => 255, + 'required' => true, + ]); + + $this->assertEquals(202, $attribute['headers']['status-code']); + sleep(2); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + + // Try to stage a create operation without permission, should fail + $staged = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions/' . $transaction['body']['$id'] . '/operations', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'operations' => [[ + 'action' => 'create', + 'databaseId' => $this->permissionsDatabase, + 'tableId' => $collection['body']['$id'], + 'rowId' => 'testDoc1', + 'data' => ['title' => 'Test Document'], + ]] + ]); + + // This should fail with 401 Unauthorized + if ($staged['headers']['status-code'] !== 401) { + echo "\nDEBUG - Actual response code: " . $staged['headers']['status-code'] . "\n"; + echo "DEBUG - Response body: " . json_encode($staged['body'], JSON_PRETTY_PRINT) . "\n"; + } + $this->assertEquals(401, $staged['headers']['status-code']); + } + + /** + * Test collection-level update permission check on staging + */ + public function testCollectionUpdatePermissionDenied(): void + { + // Create a collection with create but no update permission + $collection = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => 'permTest2', + 'name' => 'Permission Test 2', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::delete(Role::any()), + ], + 'rowSecurity' => false, + ]); + + $this->assertEquals(201, $collection['headers']['status-code']); + + $attribute = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables/' . $collection['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'title', + 'size' => 255, + 'required' => true, + ]); + + $this->assertEquals(202, $attribute['headers']['status-code']); + sleep(2); + + // Create a document first with API key + $doc = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables/' . $collection['body']['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'testDoc2', + 'data' => ['title' => 'Original Title'], + ]); + + $this->assertEquals(201, $doc['headers']['status-code']); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + + // Try to stage an update operation without permission, should fail + $staged = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions/' . $transaction['body']['$id'] . '/operations', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'operations' => [[ + 'action' => 'update', + 'databaseId' => $this->permissionsDatabase, + 'tableId' => $collection['body']['$id'], + 'rowId' => 'testDoc2', + 'data' => ['title' => 'Updated Title'], + ]] + ]); + + // This should fail with 401 Unauthorized + $this->assertEquals(401, $staged['headers']['status-code']); + } + + /** + * Test collection-level delete permission check on staging + */ + public function testCollectionDeletePermissionDenied(): void + { + // Create a collection with create, read but no delete permission + $collection = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => 'permTest3', + 'name' => 'Permission Test 3', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + 'rowSecurity' => false, + ]); + + $this->assertEquals(201, $collection['headers']['status-code']); + + $attribute = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables/' . $collection['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'title', + 'size' => 255, + 'required' => true, + ]); + + $this->assertEquals(202, $attribute['headers']['status-code']); + sleep(2); + + $doc = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables/' . $collection['body']['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'testDoc3', + 'data' => ['title' => 'To Be Deleted'], + ]); + + $this->assertEquals(201, $doc['headers']['status-code']); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + + // Try to stage a delete operation without permission, should fail + $staged = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions/' . $transaction['body']['$id'] . '/operations', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'operations' => [[ + 'action' => 'delete', + 'databaseId' => $this->permissionsDatabase, + 'tableId' => $collection['body']['$id'], + 'rowId' => 'testDoc3', + 'data' => [], + ]] + ]); + + // This should fail with 401 Unauthorized + $this->assertEquals(401, $staged['headers']['status-code']); + } + + /** + * Test document-level update permission grants access when rowSecurity is enabled + * Collection has no update permission, but document does, should succeed + */ + public function testDocumentLevelUpdatePermissionGranted(): void + { + // Create collection with rowSecurity enabled but no update permission at collection level + $collection = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => 'permTest4', + 'name' => 'Permission Test 4', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + ], + 'rowSecurity' => true, + ]); + + $this->assertEquals(201, $collection['headers']['status-code']); + + $attribute = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables/' . $collection['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'title', + 'size' => 255, + 'required' => true, + ]); + + $this->assertEquals(202, $attribute['headers']['status-code']); + sleep(2); + + // Create a document with update permission at document level + $doc = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables/' . $collection['body']['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'testDoc4', + 'data' => ['title' => 'Protected Document'], + 'permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $this->assertEquals(201, $doc['headers']['status-code']); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + + // Stage an update, should succeed because document has update permission + $staged = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions/' . $transaction['body']['$id'] . '/operations', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'operations' => [[ + 'action' => 'update', + 'databaseId' => $this->permissionsDatabase, + 'tableId' => $collection['body']['$id'], + 'rowId' => 'testDoc4', + 'data' => ['title' => 'Trying to Update'], + ]] + ]); + + // This should succeed with 201 because document has update permission + $this->assertEquals(201, $staged['headers']['status-code']); + } + + /** + * Test document-level delete permission grants access when rowSecurity is enabled + * Collection has no delete permission, but document does, should succeed + */ + public function testDocumentLevelDeletePermissionGranted(): void + { + // Create collection with rowSecurity enabled but no delete permission at collection level + $collection = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => 'permTest5', + 'name' => 'Permission Test 5', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + 'rowSecurity' => true, + ]); + + $this->assertEquals(201, $collection['headers']['status-code']); + + $attribute = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables/' . $collection['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'title', + 'size' => 255, + 'required' => true, + ]); + + $this->assertEquals(202, $attribute['headers']['status-code']); + sleep(2); + + // Create a document with delete permission at document level + $doc = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables/' . $collection['body']['$id'] . '/rows', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'testDoc5', + 'data' => ['title' => 'Can Delete Me'], + 'permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $this->assertEquals(201, $doc['headers']['status-code']); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + + // Stage a delete should succeed because document has delete permission + $staged = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions/' . $transaction['body']['$id'] . '/operations', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'operations' => [[ + 'action' => 'delete', + 'databaseId' => $this->permissionsDatabase, + 'tableId' => $collection['body']['$id'], + 'rowId' => 'testDoc5', + 'data' => [], + ]] + ]); + + // This should succeed with 201 because document has DELETE permission + $this->assertEquals(201, $staged['headers']['status-code']); + } + + /** + * Test that users cannot set permissions for roles they don't have + */ + public function testCannotSetUnauthorizedRolePermissions(): void + { + // Create a collection + $collection = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => 'permTest6', + 'name' => 'Permission Test 6', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'rowSecurity' => true, + ]); + + $this->assertEquals(201, $collection['headers']['status-code']); + + // Add attribute + $attribute = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables/' . $collection['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'title', + 'size' => 255, + 'required' => true, + ]); + + $this->assertEquals(202, $attribute['headers']['status-code']); + sleep(2); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + + // Try to stage a create with team permissions, current user is not in team + $staged = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions/' . $transaction['body']['$id'] . '/operations', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'operations' => [[ + 'action' => 'create', + 'databaseId' => $this->permissionsDatabase, + 'tableId' => $collection['body']['$id'], + 'rowId' => 'testDoc6', + 'data' => [ + 'title' => 'Admin Only Doc', + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::team('adminTeam')), + ], + ], + ]] + ]); + + // This should fail with 401 Unauthorized, cannot set permissions for roles you don't have + $this->assertEquals(401, $staged['headers']['status-code']); + $this->assertStringContainsString('Permissions must be one of', $staged['body']['message']); + } + + /** + * Test successful staging when user has the required permissions + */ + public function testSuccessfulStagingWithProperPermissions(): void + { + $collection = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => 'permTest7', + 'name' => 'Permission Test 7', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'rowSecurity' => true, + ]); + + $this->assertEquals(201, $collection['headers']['status-code']); + + $attribute = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables/' . $collection['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'title', + 'size' => 255, + 'required' => true, + ]); + + $this->assertEquals(202, $attribute['headers']['status-code']); + sleep(2); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + + // Stage a create with permissions for current user's roles, should succeed + $staged = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions/' . $transaction['body']['$id'] . '/operations', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'operations' => [[ + 'action' => 'create', + 'databaseId' => $this->permissionsDatabase, + 'tableId' => $collection['body']['$id'], + 'rowId' => 'testDoc7', + 'data' => [ + 'title' => 'Valid Document', + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::user($this->getUser()['$id'])), + ], + ], + ]] + ]); + + // This should succeed + $this->assertEquals(201, $staged['headers']['status-code']); + $this->assertEquals(1, $staged['body']['operations']); + } + + /** + * Test that non-existent documents cannot be updated in transactions + */ + public function testCannotUpdateNonExistentDocument(): void + { + // Create a collection + $collection = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => 'permTest8', + 'name' => 'Permission Test 8', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'rowSecurity' => false, + ]); + + $this->assertEquals(201, $collection['headers']['status-code']); + + $attribute = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables/' . $collection['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'title', + 'size' => 255, + 'required' => true, + ]); + + $this->assertEquals(202, $attribute['headers']['status-code']); + sleep(2); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + + // Try to update a document that doesn't exist - should fail + $staged = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions/' . $transaction['body']['$id'] . '/operations', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'operations' => [[ + 'action' => 'update', + 'databaseId' => $this->permissionsDatabase, + 'tableId' => $collection['body']['$id'], + 'rowId' => 'nonExistentDoc', + 'data' => ['title' => 'Trying to Update'], + ]] + ]); + + // This should fail with 404 Not Found + $this->assertEquals(404, $staged['headers']['status-code']); + } + + /** + * Test that non-existent documents cannot be deleted in transactions + */ + public function testCannotDeleteNonExistentDocument(): void + { + // Create a collection + $collection = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => 'permTest9', + 'name' => 'Permission Test 9', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'rowSecurity' => false, + ]); + + $this->assertEquals(201, $collection['headers']['status-code']); + + $attribute = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables/' . $collection['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'title', + 'size' => 255, + 'required' => true, + ]); + + $this->assertEquals(202, $attribute['headers']['status-code']); + sleep(2); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + + // Try to delete a document that doesn't exist, should fail + $staged = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions/' . $transaction['body']['$id'] . '/operations', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'operations' => [[ + 'action' => 'delete', + 'databaseId' => $this->permissionsDatabase, + 'tableId' => $collection['body']['$id'], + 'rowId' => 'nonExistentDoc', + 'data' => [], + ]] + ]); + + // This should fail with 404 Not Found + $this->assertEquals(404, $staged['headers']['status-code']); + } + + /** + * Test that a document created in one batch can be updated in a subsequent batch within the same transaction + * This validates the transactionState->getDocument() fix for cross-batch dependencies + */ + public function testCanUpdateDocumentCreatedInPreviousBatch(): void + { + $collection = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => 'permTest10', + 'name' => 'Permission Test 10', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'rowSecurity' => false, + ]); + + $this->assertEquals(201, $collection['headers']['status-code']); + + $attribute = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables/' . $collection['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'title', + 'size' => 255, + 'required' => true, + ]); + + $this->assertEquals(202, $attribute['headers']['status-code']); + sleep(2); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + + // Batch 1: Create a document + $batch1 = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions/' . $transaction['body']['$id'] . '/operations', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'operations' => [[ + 'action' => 'create', + 'databaseId' => $this->permissionsDatabase, + 'tableId' => $collection['body']['$id'], + 'rowId' => 'crossBatchDoc', + 'data' => [ + 'title' => 'Initial Title', + ], + ]] + ]); + + $this->assertEquals(201, $batch1['headers']['status-code']); + $this->assertEquals(1, $batch1['body']['operations']); + + // Batch 2: Update the document created in batch 1 + $batch2 = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions/' . $transaction['body']['$id'] . '/operations', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'operations' => [[ + 'action' => 'update', + 'databaseId' => $this->permissionsDatabase, + 'tableId' => $collection['body']['$id'], + 'rowId' => 'crossBatchDoc', + 'data' => [ + 'title' => 'Updated Title', + ], + ]] + ]); + + // This should succeed with 201 because transactionState finds the staged document from batch 1 + $this->assertEquals(201, $batch2['headers']['status-code']); + $this->assertEquals(2, $batch2['body']['operations']); + + // Batch 3: Delete the same document + $batch3 = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions/' . $transaction['body']['$id'] . '/operations', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'operations' => [[ + 'action' => 'delete', + 'databaseId' => $this->permissionsDatabase, + 'tableId' => $collection['body']['$id'], + 'rowId' => 'crossBatchDoc', + 'data' => [], + ]] + ]); + + // This should also succeed with 201 + $this->assertEquals(201, $batch3['headers']['status-code']); + $this->assertEquals(3, $batch3['body']['operations']); + + // Rollback to clean up + $rollback = $this->client->call(Client::METHOD_PATCH, '/tablesdb/transactions/' . $transaction['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rollback' => true, + ]); + + $this->assertEquals(200, $rollback['headers']['status-code']); + } + + /** + * Test that one user cannot read another user's transaction + */ + public function testUserCannotReadAnotherUsersTransaction(): void + { + // Create user 1 (fresh) and their transaction + $user1 = $this->getUser(true); + $user1Headers = [ + 'origin' => 'http://localhost', + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], + ]; + + $transaction1 = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $user1Headers)); + + $this->assertEquals(201, $transaction1['headers']['status-code']); + $transactionId1 = $transaction1['body']['$id']; + + // Create user 2 (fresh) + $user2 = $this->getUser(true); // Fresh user + $user2Headers = [ + 'origin' => 'http://localhost', + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + ]; + + // User 2 tries to read User 1's transaction - should fail + $readAttempt = $this->client->call(Client::METHOD_GET, '/tablesdb/transactions/' . $transactionId1, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $user2Headers)); + + // This should fail with 404 Not Found (transaction doesn't exist for this user) + $this->assertEquals(404, $readAttempt['headers']['status-code']); + + // Verify User 1 can still read their own transaction + $readOwn = $this->client->call(Client::METHOD_GET, '/tablesdb/transactions/' . $transactionId1, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $user1Headers)); + + $this->assertEquals(200, $readOwn['headers']['status-code']); + $this->assertEquals($transactionId1, $readOwn['body']['$id']); + } + + /** + * Test that one user cannot list another user's transactions + */ + public function testUserCannotListAnotherUsersTransactions(): void + { + // Create user 1 (fresh) with transactions + $user1 = $this->getUser(true); + $user1Headers = [ + 'origin' => 'http://localhost', + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], + ]; + + $transaction1 = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $user1Headers)); + + $this->assertEquals(201, $transaction1['headers']['status-code']); + + $transaction2 = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $user1Headers)); + + $this->assertEquals(201, $transaction2['headers']['status-code']); + + // Create user 2 (fresh) with their own transaction + $user2 = $this->getUser(true); // Fresh user + $user2Headers = [ + 'origin' => 'http://localhost', + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + ]; + + $transaction3 = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $user2Headers)); + + $this->assertEquals(201, $transaction3['headers']['status-code']); + + // User 2 lists transactions - should only see their own + $listUser2 = $this->client->call(Client::METHOD_GET, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $user2Headers)); + + $this->assertEquals(200, $listUser2['headers']['status-code']); + $this->assertEquals(1, $listUser2['body']['total']); + $this->assertEquals($transaction3['body']['$id'], $listUser2['body']['transactions'][0]['$id']); + + // User 1 lists transactions - should only see their own (2 transactions) + $listUser1 = $this->client->call(Client::METHOD_GET, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $user1Headers)); + + $this->assertEquals(200, $listUser1['headers']['status-code']); + $this->assertEquals(2, $listUser1['body']['total']); + + // Verify neither of user1's transactions appear in user2's list + $user2TransactionIds = array_column($listUser2['body']['transactions'], '$id'); + $this->assertNotContains($transaction1['body']['$id'], $user2TransactionIds); + $this->assertNotContains($transaction2['body']['$id'], $user2TransactionIds); + } + + /** + * Test that one user cannot update another user's transaction + */ + public function testUserCannotUpdateAnotherUsersTransaction(): void + { + // Create user 1 (fresh) and their transaction + $user1 = $this->getUser(true); + $user1Headers = [ + 'origin' => 'http://localhost', + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], + ]; + + $transaction1 = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $user1Headers)); + + $this->assertEquals(201, $transaction1['headers']['status-code']); + $transactionId1 = $transaction1['body']['$id']; + + // Create user 2 (fresh) + $user2 = $this->getUser(true); // Fresh user + $user2Headers = [ + 'origin' => 'http://localhost', + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + ]; + + // User 2 tries to commit User 1's transaction - should fail + $commitAttempt = $this->client->call(Client::METHOD_PATCH, '/tablesdb/transactions/' . $transactionId1, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $user2Headers), [ + 'commit' => true, + ]); + + // This should fail with 404 Not Found + $this->assertEquals(404, $commitAttempt['headers']['status-code']); + + // User 2 tries to rollback User 1's transaction - should also fail + $rollbackAttempt = $this->client->call(Client::METHOD_PATCH, '/tablesdb/transactions/' . $transactionId1, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $user2Headers), [ + 'rollback' => true, + ]); + + // This should also fail with 404 Not Found + $this->assertEquals(404, $rollbackAttempt['headers']['status-code']); + + // Verify User 1 can still commit their own transaction + $commitOwn = $this->client->call(Client::METHOD_PATCH, '/tablesdb/transactions/' . $transactionId1, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $user1Headers), [ + 'commit' => true, + ]); + + $this->assertEquals(200, $commitOwn['headers']['status-code']); + } + + /** + * Test that one user cannot delete another user's transaction + */ + public function testUserCannotDeleteAnotherUsersTransaction(): void + { + // Create user 1 (fresh) and their transaction + $user1 = $this->getUser(true); + $user1Headers = [ + 'origin' => 'http://localhost', + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], + ]; + + $transaction1 = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $user1Headers)); + + $this->assertEquals(201, $transaction1['headers']['status-code']); + $transactionId1 = $transaction1['body']['$id']; + + // Create user 2 (fresh) + $user2 = $this->getUser(true); // Fresh user + $user2Headers = [ + 'origin' => 'http://localhost', + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + ]; + + // User 2 tries to delete User 1's transaction - should fail + $deleteAttempt = $this->client->call(Client::METHOD_DELETE, '/tablesdb/transactions/' . $transactionId1, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $user2Headers)); + + // This should fail with 404 Not Found + $this->assertEquals(404, $deleteAttempt['headers']['status-code']); + + // Verify User 1 can still access their transaction + $readOwn = $this->client->call(Client::METHOD_GET, '/tablesdb/transactions/' . $transactionId1, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $user1Headers)); + + $this->assertEquals(200, $readOwn['headers']['status-code']); + + // User 1 can delete their own transaction + $deleteOwn = $this->client->call(Client::METHOD_DELETE, '/tablesdb/transactions/' . $transactionId1, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $user1Headers)); + + $this->assertEquals(204, $deleteOwn['headers']['status-code']); + } + + /** + * Test that one user cannot add operations to another user's transaction + */ + public function testUserCannotAddOperationsToAnotherUsersTransaction(): void + { + // Create a collection for testing + $collection = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => 'permTest11', + 'name' => 'Permission Test 11', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'rowSecurity' => false, + ]); + + $this->assertEquals(201, $collection['headers']['status-code']); + + $attribute = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $this->permissionsDatabase . '/tables/' . $collection['body']['$id'] . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'title', + 'size' => 255, + 'required' => true, + ]); + + $this->assertEquals(202, $attribute['headers']['status-code']); + sleep(2); + + // Create user 1 (fresh) and their transaction + $user1 = $this->getUser(true); + $user1Headers = [ + 'origin' => 'http://localhost', + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user1['session'], + ]; + + $transaction1 = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $user1Headers)); + + $this->assertEquals(201, $transaction1['headers']['status-code']); + $transactionId1 = $transaction1['body']['$id']; + + // Create user 2 (fresh) + $user2 = $this->getUser(true); // Fresh user + $user2Headers = [ + 'origin' => 'http://localhost', + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user2['session'], + ]; + + // User 2 tries to add operations to User 1's transaction - should fail + $operationAttempt = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions/' . $transactionId1 . '/operations', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $user2Headers), [ + 'operations' => [[ + 'action' => 'create', + 'databaseId' => $this->permissionsDatabase, + 'tableId' => $collection['body']['$id'], + 'rowId' => 'maliciousDoc', + 'data' => ['title' => 'Malicious Document'], + ]] + ]); + + // This should fail with 404 Not Found + $this->assertEquals(404, $operationAttempt['headers']['status-code']); + + // Verify User 1 can still add operations to their own transaction + $operationOwn = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions/' . $transactionId1 . '/operations', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $user1Headers), [ + 'operations' => [[ + 'action' => 'create', + 'databaseId' => $this->permissionsDatabase, + 'tableId' => $collection['body']['$id'], + 'rowId' => 'legitimateDoc', + 'data' => ['title' => 'Legitimate Document'], + ]] + ]); + + $this->assertEquals(201, $operationOwn['headers']['status-code']); + $this->assertEquals(1, $operationOwn['body']['operations']); + } + + /** + * Test that an authenticated user can successfully list their own transactions + */ + public function testAuthenticatedUserCanListTheirOwnTransactions(): void + { + // Create an authenticated user + $user = $this->getUser(); + $userHeaders = [ + 'origin' => 'http://localhost', + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user['session'], + ]; + + // Create multiple transactions for this user + $transactionIds = []; + for ($i = 0; $i < 3; $i++) { + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $userHeaders)); + + $this->assertEquals(201, $transaction['headers']['status-code']); + $this->assertNotEmpty($transaction['body']['$id']); + $transactionIds[] = $transaction['body']['$id']; + } + + // List transactions + $list = $this->client->call(Client::METHOD_GET, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $userHeaders)); + + $this->assertEquals(200, $list['headers']['status-code']); + $this->assertGreaterThanOrEqual(3, $list['body']['total']); + $this->assertIsArray($list['body']['transactions']); + $this->assertGreaterThanOrEqual(3, count($list['body']['transactions'])); + + // Verify all created transactions are in the list + $listedIds = array_column($list['body']['transactions'], '$id'); + foreach ($transactionIds as $transactionId) { + $this->assertContains($transactionId, $listedIds); + } + + // Verify transaction structure + foreach ($list['body']['transactions'] as $transaction) { + $this->assertArrayHasKey('$id', $transaction); + $this->assertArrayHasKey('$createdAt', $transaction); + $this->assertArrayHasKey('$updatedAt', $transaction); + $this->assertArrayHasKey('status', $transaction); + $this->assertArrayHasKey('operations', $transaction); + } + } + + /** + * Test that an authenticated user can successfully delete their own transaction + */ + public function testAuthenticatedUserCanDeleteTheirOwnTransaction(): void + { + // Create an authenticated user + $user = $this->getUser(); + $userHeaders = [ + 'origin' => 'http://localhost', + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $user['session'], + ]; + + // Create a transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $userHeaders)); + + $this->assertEquals(201, $transaction['headers']['status-code']); + $transactionId = $transaction['body']['$id']; + + // Verify transaction exists by reading it + $read = $this->client->call(Client::METHOD_GET, '/tablesdb/transactions/' . $transactionId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $userHeaders)); + + $this->assertEquals(200, $read['headers']['status-code']); + $this->assertEquals($transactionId, $read['body']['$id']); + + // Delete the transaction + $delete = $this->client->call(Client::METHOD_DELETE, '/tablesdb/transactions/' . $transactionId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $userHeaders)); + + $this->assertEquals(204, $delete['headers']['status-code']); + + // Verify transaction is deleted by trying to read it again + $readAfterDelete = $this->client->call(Client::METHOD_GET, '/tablesdb/transactions/' . $transactionId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $userHeaders)); + + $this->assertEquals(404, $readAfterDelete['headers']['status-code']); + + // Create another transaction and verify it can also be deleted + $transaction2 = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $userHeaders)); + + $this->assertEquals(201, $transaction2['headers']['status-code']); + $transactionId2 = $transaction2['body']['$id']; + + $delete2 = $this->client->call(Client::METHOD_DELETE, '/tablesdb/transactions/' . $transactionId2, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $userHeaders)); + + $this->assertEquals(204, $delete2['headers']['status-code']); + } +} diff --git a/tests/e2e/Services/Databases/TablesDB/Transactions/PermissionsCustomClientTest.php b/tests/e2e/Services/Databases/TablesDB/Transactions/PermissionsCustomClientTest.php new file mode 100644 index 0000000000..fa33aea7b6 --- /dev/null +++ b/tests/e2e/Services/Databases/TablesDB/Transactions/PermissionsCustomClientTest.php @@ -0,0 +1,14 @@ +client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'TransactionTestDatabase' + ]); + + $this->assertEquals(201, $database['headers']['status-code']); + $databaseId = $database['body']['$id']; + + // Test creating a transaction with default TTL + $response = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertArrayHasKey('$id', $response['body']); + $this->assertArrayHasKey('status', $response['body']); + $this->assertArrayHasKey('operations', $response['body']); + $this->assertArrayHasKey('expiresAt', $response['body']); + $this->assertEquals('pending', $response['body']['status']); + $this->assertEquals(0, $response['body']['operations']); + + $transactionId1 = $response['body']['$id']; + + // Test creating a transaction with custom TTL + $response = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'ttl' => 900 + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertEquals('pending', $response['body']['status']); + + $expiresAt = new \DateTime($response['body']['expiresAt']); + $now = new \DateTime(); + $diff = $expiresAt->getTimestamp() - $now->getTimestamp(); + $this->assertGreaterThan(800, $diff); + $this->assertLessThan(1000, $diff); + + $transactionId2 = $response['body']['$id']; + + // Test invalid TTL values + $response = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'ttl' => 30 // Below minimum + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'ttl' => 4000 // Above maximum + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + } + + /** + * Test adding operations to a transaction + */ + public function testCreateOperations(): void + { + // Create database first + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'TransactionOperationsTestDB' + ]); + + $this->assertEquals(201, $database['headers']['status-code']); + $databaseId = $database['body']['$id']; + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + $transactionId = $transaction['body']['$id']; + + // Create a table for testing + $table = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TransactionOperationsTest', + 'rowSecurity' => false, + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $this->assertEquals(201, $table['headers']['status-code']); + $tableId = $table['body']['$id']; + + // Add columns + $column = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->assertEquals(202, $column['headers']['status-code']); + + // Wait for column to be created + sleep(2); + + // Add valid operations + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => 'doc1', + 'data' => [ + 'name' => 'Test Document 1' + ] + ], + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => 'doc2', + 'data' => [ + 'name' => 'Test Document 2' + ] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertEquals(2, $response['body']['operations']); + + // Test adding more operations + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'update', + 'rowId' => 'doc1', + 'data' => [ + 'name' => 'Updated Document 1' + ] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertEquals(3, $response['body']['operations']); + + // Test invalid database ID + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => 'invalid_database', + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => ID::unique(), + 'data' => ['name' => 'Test'] + ] + ] + ]); + + $this->assertEquals(404, $response['headers']['status-code'], 'Invalid database should return 404. Got: ' . json_encode($response['body'])); + + // Test invalid table ID + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => 'invalid_table', + 'action' => 'create', + 'rowId' => ID::unique(), + 'data' => ['name' => 'Test'] + ] + ] + ]); + + $this->assertEquals(404, $response['headers']['status-code']); + } + + /** + * Test committing a transaction + */ + public function testCommit(): void + { + // Create database first + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'TransactionCommitTestDB' + ]); + + $this->assertEquals(201, $database['headers']['status-code']); + $databaseId = $database['body']['$id']; + + // Create table + $table = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TransactionCommitTest', + 'rowSecurity' => false, + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $this->assertEquals(201, $table['headers']['status-code']); + $tableId = $table['body']['$id']; + + // Add columns + $column = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->assertEquals(202, $column['headers']['status-code']); + sleep(2); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + $transactionId = $transaction['body']['$id']; + + // Add operations + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => 'doc1', + 'data' => [ + 'name' => 'Test Document 1' + ] + ], + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => 'doc2', + 'data' => [ + 'name' => 'Test Document 2' + ] + ], + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'update', + 'rowId' => 'doc1', + 'data' => [ + 'name' => 'Updated Document 1' + ] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertEquals(3, $response['body']['operations']); + + // Commit the transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('committed', $response['body']['status']); + + // Verify rows were created + $rows = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(2, $rows['body']['total']); + + // Verify the update was applied + $doc1Found = false; + foreach ($rows['body']['rows'] as $doc) { + if ($doc['$id'] === 'doc1') { + $this->assertEquals('Updated Document 1', $doc['name']); + $doc1Found = true; + } + } + $this->assertTrue($doc1Found, 'Document doc1 should exist with updated name'); + + // Test committing already committed transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + } + + /** + * Test rolling back a transaction + */ + public function testRollback(): void + { + // Create database first + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'TransactionRollbackTestDB' + ]); + + $this->assertEquals(201, $database['headers']['status-code']); + $databaseId = $database['body']['$id']; + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + $transactionId = $transaction['body']['$id']; + + // Create a table for rollback test + $table = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TransactionRollbackTest', + 'rowSecurity' => false, + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Add column + $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'value', + 'size' => 256, + 'required' => true, + ]); + + sleep(2); + + // Add operations + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => 'rollback_doc', + 'data' => [ + 'value' => 'Should not exist' + ] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Rollback the transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rollback' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('failed', $response['body']['status']); + + // Verify no rows were created + $rows = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $rows['headers']['status-code']); + $this->assertEquals(0, $rows['body']['total']); + } + + /** + * Test transaction expiration + */ + public function testTransactionExpiration(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'ExpirationTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Create column + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'data', + 'size' => 256, + 'required' => false, + ]); + + sleep(2); + + // Create transaction with minimum TTL (60 seconds) + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'ttl' => 60 + ]); + + $this->assertEquals(201, $transaction['headers']['status-code']); + $transactionId = $transaction['body']['$id']; + + // Add operation + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => ID::unique(), + 'data' => ['data' => 'Should expire'] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Verify transaction was created with correct expiration + $txnDetails = $this->client->call(Client::METHOD_GET, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(200, $txnDetails['headers']['status-code']); + $this->assertEquals('pending', $txnDetails['body']['status']); + + // Verify expiration time is approximately 60 seconds from now + $expiresAt = new \DateTime($txnDetails['body']['expiresAt']); + $now = new \DateTime(); + $diff = $expiresAt->getTimestamp() - $now->getTimestamp(); + $this->assertGreaterThan(55, $diff); + $this->assertLessThan(65, $diff); + } + + /** + * Test maximum operations per transaction + */ + public function testTransactionSizeLimit(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'SizeLimitTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [Permission::create(Role::any())], + ]); + + $tableId = $table['body']['$id']; + + // Create column + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'value', + 'size' => 256, + 'required' => false, + ]); + + sleep(2); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Try to add operations exceeding the limit (assuming limit is 100) + // We'll add 50 operations twice to test incremental limit + $operations = []; + for ($i = 0; $i < 50; $i++) { + $operations[] = [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => 'doc_' . $i, + 'data' => ['value' => 'Test ' . $i] + ]; + } + + // First batch should succeed + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => $operations + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertEquals(50, $response['body']['operations']); + + // Second batch of 50 more operations + $operations = []; + for ($i = 50; $i < 100; $i++) { + $operations[] = [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'rowId' => 'doc_' . $i, + 'action' => 'create', + 'data' => ['value' => 'Test ' . $i] + ]; + } + + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => $operations + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertEquals(100, $response['body']['operations']); + + // Try to add one more operation - should fail + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => 'doc_overflow', + 'data' => ['value' => 'This should fail'] + ] + ] + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + } + + /** + * Test concurrent transactions with conflicting operations + */ + public function testConcurrentTransactionConflicts(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'ConflictTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Create column + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/integer", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'counter', + 'required' => true, + 'min' => 0, + 'max' => 1000000, + ]); + + sleep(2); + + // Create initial row + $doc = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'shared_doc', + 'data' => ['counter' => 100] + ]); + + $this->assertEquals(201, $doc['headers']['status-code']); + + // Create two transactions + $txn1 = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $txn2 = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId1 = $txn1['body']['$id']; + $transactionId2 = $txn2['body']['$id']; + + // Both transactions try to update the same row + $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId1}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'update', + 'rowId' => 'shared_doc', + 'data' => ['counter' => 200] + ] + ] + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId2}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'update', + 'rowId' => 'shared_doc', + 'data' => ['counter' => 300] + ] + ] + ]); + + // Commit first transaction + $response1 = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId1}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response1['headers']['status-code']); + + // Commit second transaction - should fail with conflict + $response2 = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId2}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(409, $response2['headers']['status-code']); // Conflict + + // Verify the row has the value from first transaction + $doc = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/shared_doc", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $doc['body']['counter']); + } + + /** + * Test deleting a row that's being updated in a transaction + */ + public function testDeleteDocumentDuringTransaction(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'DeleteConflictDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Create column + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'data', + 'size' => 256, + 'required' => false, + ]); + + sleep(2); + + // Create row + $doc = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'target_doc', + 'data' => ['data' => 'Original'] + ]); + + $this->assertEquals(201, $doc['headers']['status-code']); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Add update operation to transaction + $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'update', + 'rowId' => 'target_doc', + 'data' => ['data' => 'Updated in transaction'] + ] + ] + ]); + + // Delete the row outside of transaction + $response = $this->client->call(Client::METHOD_DELETE, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/target_doc", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(204, $response['headers']['status-code']); + + // Try to commit transaction - should fail because row no longer exists + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(404, $response['headers']['status-code']); + } + + /** + * Test bulk operations in transactions + */ + public function testBulkOperations(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkOpsDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Create columns + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'category', + 'size' => 256, + 'required' => true, + ]); + + sleep(3); + + // Create some initial rows + for ($i = 1; $i <= 5; $i++) { + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'existing_' . $i, + 'data' => [ + 'name' => 'Existing ' . $i, + 'category' => 'old' + ] + ]); + } + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Add bulk operations + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + // Bulk create + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'bulkCreate', + 'data' => [ + ['$id' => 'bulk_1', 'name' => 'Bulk 1', 'category' => 'new'], + ['$id' => 'bulk_2', 'name' => 'Bulk 2', 'category' => 'new'], + ['$id' => 'bulk_3', 'name' => 'Bulk 3', 'category' => 'new'], + ] + ], + // Bulk update + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'bulkUpdate', + 'data' => [ + 'queries' => [Query::equal('category', ['old'])->toString()], + 'data' => ['category' => 'updated'] + ] + ], + // Bulk delete + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'bulkDelete', + 'data' => [ + 'queries' => [Query::equal('name', ['Existing 5'])->toString()] + ] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Verify results + $rows = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + // Should have 7 rows (5 existing - 1 deleted + 3 new) + $this->assertEquals(7, $rows['body']['total']); + + // Check categories were updated + $oldCategoryCount = 0; + $updatedCategoryCount = 0; + $newCategoryCount = 0; + + foreach ($rows['body']['rows'] as $doc) { + switch ($doc['category']) { + case 'old': + $oldCategoryCount++; + break; + case 'updated': + $updatedCategoryCount++; + break; + case 'new': + $newCategoryCount++; + break; + } + } + + $this->assertEquals(0, $oldCategoryCount); + $this->assertEquals(4, $updatedCategoryCount); // 4 existing docs updated + $this->assertEquals(3, $newCategoryCount); // 3 new docs + } + + /** + * Test transaction with mixed success and failure operations + */ + public function testPartialFailureRollback(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'PartialFailureDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Create columns with constraints + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'email', + 'size' => 256, + 'required' => true, + ]); + + sleep(2); + + // Create unique index on email + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/indexes", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'unique_email', + 'type' => 'unique', + 'columns' => ['email'], + ]); + + sleep(2); + + // Create an existing row + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => ID::unique(), + 'data' => ['email' => 'existing@example.com'] + ]); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Add operations - mix of valid and invalid + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => ID::unique(), + 'data' => ['email' => 'valid1@example.com'] // Valid + ], + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => ID::unique(), + 'data' => ['email' => 'valid2@example.com'] // Valid + ], + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => ID::unique(), + 'data' => ['email' => 'existing@example.com'] // Will fail - duplicate + ], + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => ID::unique(), + 'data' => ['email' => 'valid3@example.com'] // Would be valid but should rollback + ], + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Try to commit - should fail and rollback all operations + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(409, $response['headers']['status-code']); // Conflict due to duplicate + + // Verify NO new rows were created (atomicity) + $rows = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(1, $rows['body']['total']); // Only the original row + $this->assertEquals('existing@example.com', $rows['body']['rows'][0]['email']); + } + + /** + * Test double commit/rollback attempts + */ + public function testDoubleCommitRollback(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'DoubleCommitDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [Permission::create(Role::any())], + ]); + + $tableId = $table['body']['$id']; + + // Create column + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'data', + 'size' => 256, + 'required' => false, + ]); + + sleep(2); + + // Test double commit + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Add operation + $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => ID::unique(), + 'data' => ['data' => 'Test'] + ] + ] + ]); + + // First commit + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Second commit attempt - should fail + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(400, $response['headers']['status-code']); // Bad request - already committed + + // Test double rollback + $transaction2 = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId2 = $transaction2['body']['$id']; + + // First rollback + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId2}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rollback' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Second rollback attempt - should fail + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId2}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rollback' => true + ]); + + $this->assertEquals(400, $response['headers']['status-code']); // Bad request - already rolled back + } + + /** + * Test operations on non-existent rows + */ + public function testOperationsOnNonExistentDocuments(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'NonExistentDocDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Create column + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'data', + 'size' => 256, + 'required' => false, + ]); + + sleep(2); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Try to update non-existent row - should fail at staging time with early validation + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'update', + 'rowId' => 'non_existent_doc', + 'data' => ['data' => 'Should fail'] + ] + ] + ]); + + $this->assertEquals(404, $response['headers']['status-code']); // Document not found at staging time + + // Test delete non-existent row - should also fail at staging time with early validation + $transaction2 = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId2 = $transaction2['body']['$id']; + + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId2}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'delete', + 'rowId' => 'non_existent_doc', + 'data' => [] + ] + ] + ]); + + $this->assertEquals(404, $response['headers']['status-code']); // Document not found at staging time + } + + /** + * Test createDocument with transactionId via normal route + */ + public function testCreateDocument(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'WriteRoutesTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestCollection', + 'rowSecurity' => false, + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Create columns + $columns = [ + ['key' => 'name', 'type' => 'string', 'size' => 256, 'required' => true], + ['key' => 'counter', 'type' => 'integer', 'required' => false, 'min' => 0, 'max' => 10000], + ['key' => 'category', 'type' => 'string', 'size' => 256, 'required' => false], + ['key' => 'data', 'type' => 'string', 'size' => 256, 'required' => false], + ]; + + foreach ($columns as $attr) { + $type = $attr['type']; + unset($attr['type']); + + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/{$type}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), $attr); + + $this->assertEquals(202, $response['headers']['status-code']); + } + + sleep(3); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + $transactionId = $transaction['body']['$id']; + + // Create row via normal route with transactionId + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'doc_from_route', + 'data' => [ + 'name' => 'Created via normal route', + 'counter' => 100, + 'category' => 'test' + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Document should not exist outside transaction yet + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/doc_from_route", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Document should now exist + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/doc_from_route", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('Created via normal route', $response['body']['name']); + } + + /** + * Test updateDocument with transactionId via normal route + */ + public function testUpdateDocument(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'UpdateRouteTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Create columns + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/integer", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'counter', + 'required' => false, + 'min' => 0, + 'max' => 10000, + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'category', + 'size' => 256, + 'required' => false, + ]); + + sleep(3); + + // Create row outside transaction + $doc = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'doc_to_update', + 'data' => [ + 'name' => 'Original name', + 'counter' => 50, + 'category' => 'original' + ] + ]); + + $this->assertEquals(201, $doc['headers']['status-code']); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Update row via normal route with transactionId + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/doc_to_update", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'data' => [ + 'name' => 'Updated via normal route', + 'counter' => 150, + 'category' => 'updated' + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Document should still have original values outside transaction + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/doc_to_update", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals('Original name', $response['body']['name']); + $this->assertEquals(50, $response['body']['counter']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Document should now have updated values + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/doc_to_update", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals('Updated via normal route', $response['body']['name']); + $this->assertEquals(150, $response['body']['counter']); + } + + /** + * Test upsertDocument with transactionId via normal route + */ + public function testUpsertDocument(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'UpsertRouteTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Create columns + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/integer", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'counter', + 'required' => false, + 'min' => 0, + 'max' => 10000, + ]); + + sleep(3); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Upsert row (create) via normal route with transactionId + $response = $this->client->call(Client::METHOD_PUT, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/doc_upsert", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'doc_upsert', + 'data' => [ + 'name' => 'Created by upsert', + 'counter' => 25 + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Document should not exist outside transaction yet + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/doc_upsert", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code']); + + // Upsert same row (update) in same transaction + $response = $this->client->call(Client::METHOD_PUT, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/doc_upsert", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'doc_upsert', + 'data' => [ + 'name' => 'Updated by upsert', + 'counter' => 75 + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(201, $response['headers']['status-code']); // Upsert in transaction returns 201 + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Document should now exist with updated values + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/doc_upsert", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('Updated by upsert', $response['body']['name']); + $this->assertEquals(75, $response['body']['counter']); + } + + /** + * Test deleteDocument with transactionId via normal route + */ + public function testDeleteDocument(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'DeleteRouteTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Create column + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + sleep(2); + + // Create row outside transaction + $doc = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'doc_to_delete', + 'data' => ['name' => 'Will be deleted'] + ]); + + $this->assertEquals(201, $doc['headers']['status-code']); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Delete row via normal route with transactionId + $response = $this->client->call(Client::METHOD_DELETE, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/doc_to_delete", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'transactionId' => $transactionId + ]); + + $this->assertEquals(204, $response['headers']['status-code']); + + // Document should still exist outside transaction + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/doc_to_delete", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Document should no longer exist + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/doc_to_delete", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code']); + } + + /** + * Test bulkCreate with transactionId via normal route + */ + public function testBulkCreate(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkCreateTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Create columns + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'category', + 'size' => 256, + 'required' => false, + ]); + + sleep(3); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Bulk create via normal route with transactionId + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rows' => [ + [ + '$id' => 'bulk_create_1', + 'name' => 'Bulk created 1', + 'category' => 'bulk_created' + ], + [ + '$id' => 'bulk_create_2', + 'name' => 'Bulk created 2', + 'category' => 'bulk_created' + ], + [ + '$id' => 'bulk_create_3', + 'name' => 'Bulk created 3', + 'category' => 'bulk_created' + ] + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); // Bulk operations return 200 + + // Documents should not exist outside transaction yet + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [Query::equal('category', ['bulk_created'])->toString()] + ]); + + $this->assertEquals(0, $response['body']['total']); + + // Individual row check + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/bulk_create_1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Documents should now exist + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [Query::equal('category', ['bulk_created'])->toString()] + ]); + + $this->assertEquals(3, $response['body']['total']); + + // Verify individual rows + for ($i = 1; $i <= 3; $i++) { + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/bulk_create_{$i}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals("Bulk created {$i}", $response['body']['name']); + $this->assertEquals('bulk_created', $response['body']['category']); + } + } + + /** + * Test bulkUpdate with transactionId via normal route + */ + public function testBulkUpdate(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkUpdateTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Create columns + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'category', + 'size' => 256, + 'required' => false, + ]); + + sleep(3); + + // Create rows for bulk testing + for ($i = 1; $i <= 3; $i++) { + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'bulk_update_' . $i, + 'data' => [ + 'name' => 'Bulk doc ' . $i, + 'category' => 'bulk_test' + ] + ]); + } + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Bulk update via normal route with transactionId + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'queries' => [Query::equal('category', ['bulk_test'])->toString()], + 'data' => ['category' => 'bulk_updated'], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Documents should still have original category outside transaction + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [Query::equal('category', ['bulk_test'])->toString()] + ]); + + $this->assertEquals(3, $response['body']['total']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Documents should now have updated category + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [Query::equal('category', ['bulk_updated'])->toString()] + ]); + + $this->assertEquals(3, $response['body']['total']); + } + + /** + * Test bulkUpsert with transactionId via normal route + */ + public function testBulkUpsert(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkUpsertTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Create columns + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/integer", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'counter', + 'required' => false, + 'min' => 0, + 'max' => 10000, + ]); + + sleep(3); + + // Create one row outside transaction + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'bulk_upsert_existing', + 'data' => [ + 'name' => 'Existing doc', + 'counter' => 10 + ] + ]); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Bulk upsert via normal route with transactionId (updates existing, creates new) + $response = $this->client->call(Client::METHOD_PUT, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rows' => [ + [ + '$id' => 'bulk_upsert_existing', + 'name' => 'Updated existing', + 'counter' => 20 + ], + [ + '$id' => 'bulk_upsert_new', + 'name' => 'New doc', + 'counter' => 30 + ] + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Original row should be unchanged, new row shouldn't exist outside transaction + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/bulk_upsert_existing", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals('Existing doc', $response['body']['name']); + $this->assertEquals(10, $response['body']['counter']); + + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/bulk_upsert_new", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Check both rows exist with updated values + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/bulk_upsert_existing", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals('Updated existing', $response['body']['name']); + $this->assertEquals(20, $response['body']['counter']); + + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/bulk_upsert_new", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals('New doc', $response['body']['name']); + $this->assertEquals(30, $response['body']['counter']); + } + + /** + * Test bulkDelete with transactionId via normal route + */ + public function testBulkDelete(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkDeleteTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Create columns + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'category', + 'size' => 256, + 'required' => false, + ]); + + sleep(3); + + // Create rows for bulk testing + for ($i = 1; $i <= 3; $i++) { + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'bulk_delete_' . $i, + 'data' => [ + 'name' => 'Delete doc ' . $i, + 'category' => 'bulk_delete_test' + ] + ]); + } + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Bulk delete via normal route with transactionId + $response = $this->client->call(Client::METHOD_DELETE, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'queries' => [Query::equal('category', ['bulk_delete_test'])->toString()], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); // Bulk delete with transaction returns 200 + + // Documents should still exist outside transaction + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [Query::equal('category', ['bulk_delete_test'])->toString()] + ]); + + $this->assertEquals(3, $response['body']['total']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Documents should now be deleted + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [Query::equal('category', ['bulk_delete_test'])->toString()] + ]); + + $this->assertEquals(0, $response['body']['total']); + } + + /** + * Test multiple single route operations in one transaction + */ + public function testMixedSingleOperations(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'MultipleSingleRoutesDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Create columns + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'status', + 'size' => 256, + 'required' => false, + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/integer", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'priority', + 'required' => false, + 'min' => 1, + 'max' => 10, + ]); + + sleep(3); + + // Create an existing row outside transaction for testing + $existingDoc = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'existing_doc', + 'data' => [ + 'name' => 'Existing Document', + 'status' => 'active', + 'priority' => 5 + ] + ]); + + $this->assertEquals(201, $existingDoc['headers']['status-code']); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + $this->assertEquals(201, $transaction['headers']['status-code']); + + // 1. Create new row via normal route with transactionId + $response1 = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'new_doc_1', + 'data' => [ + 'name' => 'New Document 1', + 'status' => 'pending', + 'priority' => 1 + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(201, $response1['headers']['status-code']); + + // 2. Create another row via normal route with transactionId + $response2 = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'new_doc_2', + 'data' => [ + 'name' => 'New Document 2', + 'status' => 'pending', + 'priority' => 2 + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(201, $response2['headers']['status-code']); + + // 3. Update existing row via normal route with transactionId + $response3 = $this->client->call(Client::METHOD_PATCH, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/existing_doc", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'data' => [ + 'status' => 'updated', + 'priority' => 10 + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response3['headers']['status-code']); + + // 4. Update the first new row (created in same transaction) + $response4 = $this->client->call(Client::METHOD_PATCH, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/new_doc_1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'data' => [ + 'status' => 'active', + 'priority' => 8 + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response4['headers']['status-code']); + + // 5. Delete the second new row (created in same transaction) + $response5 = $this->client->call(Client::METHOD_DELETE, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/new_doc_2", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'transactionId' => $transactionId + ]); + + $this->assertEquals(204, $response5['headers']['status-code']); + + // 6. Upsert a new row via normal route with transactionId + $response6 = $this->client->call(Client::METHOD_PUT, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/upserted_doc", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'upserted_doc', + 'data' => [ + 'name' => 'Upserted Document', + 'status' => 'new', + 'priority' => 3 + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(201, $response6['headers']['status-code']); + + // Check transaction has correct number of operations + $txnDetails = $this->client->call(Client::METHOD_GET, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(200, $txnDetails['headers']['status-code']); + $this->assertEquals(6, $txnDetails['body']['operations']); // 6 operations total + + // Verify nothing exists outside transaction yet + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/new_doc_1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/upserted_doc", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code']); + + // Existing doc should still have original values + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/existing_doc", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals('active', $response['body']['status']); + $this->assertEquals(5, $response['body']['priority']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('committed', $response['body']['status']); + + // Verify final state after commit + // new_doc_1 should exist with updated values + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/new_doc_1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('New Document 1', $response['body']['name']); + $this->assertEquals('active', $response['body']['status']); + $this->assertEquals(8, $response['body']['priority']); + + // new_doc_2 should not exist (was deleted in transaction) + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/new_doc_2", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code']); + + // existing_doc should have updated values + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/existing_doc", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals('updated', $response['body']['status']); + $this->assertEquals(10, $response['body']['priority']); + + // upserted_doc should exist + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/upserted_doc", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('Upserted Document', $response['body']['name']); + $this->assertEquals('new', $response['body']['status']); + $this->assertEquals(3, $response['body']['priority']); + + // Verify total row count + $rows = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(3, $rows['body']['total']); // existing_doc, new_doc_1, upserted_doc + } + + /** + * Test mixed operations with transactions + */ + public function testMixedOperations(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'MixedOpsTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Create column + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + sleep(2); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Add operation via Operations\Add endpoint + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => 'mixed_doc1', + 'data' => ['name' => 'Via Operations Add'] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertEquals(1, $response['body']['operations']); + + // Add operation via normal route with transactionId + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'mixed_doc2', + 'data' => ['name' => 'Via normal route'], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Check transaction now has 2 operations + $txnDetails = $this->client->call(Client::METHOD_GET, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertEquals(2, $txnDetails['body']['operations']); + + // Both rows shouldn't exist yet + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/mixed_doc1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/mixed_doc2", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Both rows should now exist + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/mixed_doc1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('Via Operations Add', $response['body']['name']); + + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/mixed_doc2", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('Via normal route', $response['body']['name']); + } + + /** + * Test bulk update with queries that should match rows created in the same transaction + */ + public function testBulkUpdateWithTransactionAwareQueries(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkTxnAwareDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Create columns + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/integer", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'age', + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'status', + 'size' => 256, + 'required' => true, + ]); + + sleep(3); // Wait for columns to be created + + // Create some existing rows + for ($i = 1; $i <= 3; $i++) { + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'existing_' . $i, + 'data' => [ + 'name' => 'Existing ' . $i, + 'age' => 20 + $i, + 'status' => 'inactive' + ] + ]); + } + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Step 1: Create new rows with age > 25 in transaction + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'txn_doc_1', + 'data' => [ + 'name' => 'Transaction Doc 1', + 'age' => 30, + 'status' => 'inactive' + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'txn_doc_2', + 'data' => [ + 'name' => 'Transaction Doc 2', + 'age' => 35, + 'status' => 'inactive' + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Step 2: Bulk update all rows with age > 25 to have status 'active' + // This should match both existing_3 (age=23 doesn't match, age=24 doesn't match, but existing rows have age 21,22,23) + // Wait, let me fix the ages - existing docs have ages 21, 22, 23, so only txn docs should match + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'data' => [ + 'status' => 'active' + ], + 'queries' => [Query::greaterThan('age', 25)->toString()], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Verify that rows created in the transaction were updated by the bulk update + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/txn_doc_1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('active', $response['body']['status'], 'Document created in transaction should be updated by bulk update query'); + + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/txn_doc_2", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('active', $response['body']['status'], 'Document created in transaction should be updated by bulk update query'); + + // Verify existing rows were not affected + for ($i = 1; $i <= 3; $i++) { + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/existing_{$i}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('inactive', $response['body']['status'], "Existing row {$i} should remain inactive (age <= 25)"); + } + } + + /** + * Test bulk update with queries that should match rows updated in the same transaction + */ + public function testBulkUpdateMatchingUpdatedDocuments(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkUpdateTxnDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Create columns + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'category', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'priority', + 'size' => 256, + 'required' => true, + ]); + + sleep(3); // Wait for columns to be created + + // Create existing rows + for ($i = 1; $i <= 4; $i++) { + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'doc_' . $i, + 'data' => [ + 'name' => 'Document ' . $i, + 'category' => 'normal', + 'priority' => 'low' + ] + ]); + } + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Step 1: Update some rows to have category 'special' in transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/doc_1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'data' => [ + 'category' => 'special' + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/doc_2", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'data' => [ + 'category' => 'special' + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Step 2: Bulk update all rows with category 'special' to have priority 'high' + // This should match the rows we just updated in the transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'data' => [ + 'priority' => 'high' + ], + 'queries' => [Query::equal('category', ['special'])->toString()], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Verify that the updated rows were matched by bulk update + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/doc_1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('special', $response['body']['category']); + $this->assertEquals('high', $response['body']['priority'], 'Document updated in transaction should be matched by bulk update query'); + + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/doc_2", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('special', $response['body']['category']); + $this->assertEquals('high', $response['body']['priority'], 'Document updated in transaction should be matched by bulk update query'); + + // Verify other rows were not affected + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/doc_3", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('normal', $response['body']['category']); + $this->assertEquals('low', $response['body']['priority']); + } + + /** + * Test bulk delete with queries that should match rows created in the same transaction + */ + public function testBulkDeleteMatchingCreatedDocuments(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkDeleteTxnDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Create columns + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'type', + 'size' => 256, + 'required' => true, + ]); + + sleep(3); // Wait for columns to be created + + // Create existing rows + for ($i = 1; $i <= 3; $i++) { + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'existing_' . $i, + 'data' => [ + 'name' => 'Existing ' . $i, + 'type' => 'permanent' + ] + ]); + } + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Step 1: Create temporary rows in transaction + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'temp_1', + 'data' => [ + 'name' => 'Temporary 1', + 'type' => 'temporary' + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'temp_2', + 'data' => [ + 'name' => 'Temporary 2', + 'type' => 'temporary' + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Step 2: Bulk delete all rows with type 'temporary' + // This should delete the rows we just created in the transaction + $response = $this->client->call(Client::METHOD_DELETE, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'queries' => [Query::equal('type', ['temporary'])->toString()], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Verify temporary rows were deleted (should not exist) + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/temp_1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code'], 'Temporary row created and deleted in transaction should not exist'); + + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/temp_2", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code'], 'Temporary row created and deleted in transaction should not exist'); + + // Verify existing rows were not affected + for ($i = 1; $i <= 3; $i++) { + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/existing_{$i}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code'], "Permanent row {$i} should still exist"); + $this->assertEquals('permanent', $response['body']['type']); + } + } + + /** + * Test bulk delete with queries that should match rows updated in the same transaction + */ + public function testBulkDeleteMatchingUpdatedDocuments(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkDeleteUpdateTxnDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Create columns + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'status', + 'size' => 256, + 'required' => true, + ]); + + sleep(3); // Wait for columns to be created + + // Create existing rows + for ($i = 1; $i <= 5; $i++) { + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'doc_' . $i, + 'data' => [ + 'name' => 'Document ' . $i, + 'status' => 'active' + ] + ]); + } + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Step 1: Mark some rows for deletion by updating their status + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/doc_2", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'data' => [ + 'status' => 'marked_for_deletion' + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/doc_4", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'data' => [ + 'status' => 'marked_for_deletion' + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Step 2: Bulk delete all rows with status 'marked_for_deletion' + // This should delete the rows we just updated in the transaction + $response = $this->client->call(Client::METHOD_DELETE, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'queries' => [Query::equal('status', ['marked_for_deletion'])->toString()], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Verify marked rows were deleted + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/doc_2", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code'], 'Document marked for deletion should have been deleted'); + + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/doc_4", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(404, $response['headers']['status-code'], 'Document marked for deletion should have been deleted'); + + // Verify other rows still exist + foreach ([1, 3, 5] as $i) { + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/doc_{$i}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code'], "Document {$i} should still exist"); + $this->assertEquals('active', $response['body']['status']); + } + } + + /** + * Test increment and decrement operations in transaction + */ + public function testIncrementDecrementOperations(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'IncrementDecrementTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'CounterTable', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Add integer columns + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/integer", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'counter', + 'required' => false, + 'default' => 0, + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/integer", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'score', + 'required' => false, + 'default' => 100, + ]); + + sleep(2); + + // Create initial row + $row = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => 'counter_row', + 'data' => [ + 'counter' => 10, + 'score' => 50 + ] + ]); + + $this->assertEquals(201, $row['headers']['status-code']); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Add increment and decrement operations + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'increment', + 'rowId' => 'counter_row', + 'data' => [ + 'column' => 'counter', + 'value' => 5, + ] + ], + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'decrement', + 'rowId' => 'counter_row', + 'data' => [ + 'column' => 'score', + 'value' => 20, + ] + ], + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'increment', + 'rowId' => 'counter_row', + 'data' => [ + 'column' => 'counter', + 'value' => 3, + 'max' => 20 + ] + ], + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'decrement', + 'rowId' => 'counter_row', + 'data' => [ + 'column' => 'score', + 'value' => 30, + 'min' => 0 + ] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Verify final values + $row = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/counter_row", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $row['headers']['status-code']); + // counter: 10 + 5 + 3 = 18 (capped at 20 max) + $this->assertEquals(18, $row['body']['counter']); + // score: 50 - 20 - 100 = -70, but min is 0 + $this->assertEquals(0, $row['body']['score']); + } + + /** + * Test increment followed by update (read-your-writes) + * This test ensures that after an increment operation, subsequent operations + * in the same transaction can see the incremented value in the transaction state. + */ + public function testIncrementThenUpdate(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'IncrementUpdateTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'CounterTable', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Add columns + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/integer", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'counter', + 'required' => false, + 'default' => 0, + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'status', + 'size' => 50, + 'required' => false, + ]); + + sleep(2); + + // Create initial row + $row = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => 'test_row', + 'data' => [ + 'counter' => 10, + 'status' => 'initial' + ] + ]); + + $this->assertEquals(201, $row['headers']['status-code']); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Add operations: increment then update + // The update operation needs to see the document in transaction state + // to properly merge the changes + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'increment', + 'rowId' => 'test_row', + 'data' => [ + 'column' => 'counter', + 'value' => 5, + ] + ], + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'update', + 'rowId' => 'test_row', + 'data' => [ + 'status' => 'updated' + ] + ], + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Verify final values - both increment and update should be applied + $row = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/test_row", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $row['headers']['status-code']); + $this->assertEquals(15, $row['body']['counter'], 'Counter should be incremented: 10 + 5 = 15'); + $this->assertEquals('updated', $row['body']['status'], 'Status should be updated'); + } + + /** + * Test individual increment/decrement endpoints with transactions + * This test ensures that: + * 1. Transaction logs store the correct attribute key ('column' for TablesDB) + * 2. Mock responses return the correct ID keys ('$tableId' not '$collectionId') + */ + public function testIncrementDecrementEndpointsWithTransaction(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'IncrDecrEndpointTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'AccountsTable', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Add balance column + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/integer", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'balance', + 'required' => false, + 'default' => 0, + ]); + + sleep(2); + + // Create initial rows + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => 'joe', + 'data' => ['balance' => 100] + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => 'jane', + 'data' => ['balance' => 50] + ]); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + $transactionId = $transaction['body']['$id']; + + // Test Bug 1: Decrement using individual endpoint - should store 'column' not 'attribute' in transaction log + $decrementResponse = $this->client->call( + Client::METHOD_PATCH, + "/tablesdb/{$databaseId}/tables/{$tableId}/rows/joe/balance/decrement", + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), + [ + 'transactionId' => $transactionId, + 'value' => 50, + 'min' => 0, + ] + ); + + // Test Bug 2: Response should return '$tableId' not '$collectionId' + $this->assertEquals(200, $decrementResponse['headers']['status-code']); + $this->assertArrayHasKey('$tableId', $decrementResponse['body'], 'Response should contain $tableId for TablesDB API'); + $this->assertArrayNotHasKey('$collectionId', $decrementResponse['body'], 'Response should not contain $collectionId for TablesDB API'); + $this->assertEquals($tableId, $decrementResponse['body']['$tableId']); + + // Test increment endpoint + $incrementResponse = $this->client->call( + Client::METHOD_PATCH, + "/tablesdb/{$databaseId}/tables/{$tableId}/rows/jane/balance/increment", + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), + [ + 'transactionId' => $transactionId, + 'value' => 50, + ] + ); + + $this->assertEquals(200, $incrementResponse['headers']['status-code']); + $this->assertArrayHasKey('$tableId', $incrementResponse['body'], 'Response should contain $tableId for TablesDB API'); + $this->assertArrayNotHasKey('$collectionId', $incrementResponse['body'], 'Response should not contain $collectionId for TablesDB API'); + $this->assertEquals($tableId, $incrementResponse['body']['$tableId']); + + // Commit transaction - this will fail if transaction log has 'attribute' instead of 'column' + $commitResponse = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'commit' => true + ]); + + $this->assertEquals(200, $commitResponse['headers']['status-code'], 'Transaction commit should succeed'); + + // Verify final values + $joe = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/joe", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $jane = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/jane", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $joe['headers']['status-code']); + $this->assertEquals(50, $joe['body']['balance'], 'Joe should have 100 - 50 = 50'); + + $this->assertEquals(200, $jane['headers']['status-code']); + $this->assertEquals(100, $jane['body']['balance'], 'Jane should have 50 + 50 = 100'); + } + + /** + * Test cross-API compatibility: stage operations via TablesDB, commit via Collections API + * This ensures fallback logic works when APIs are mixed + */ + public function testCrossAPIIncrementDecrement(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'CrossAPITestDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'CrossAPITable', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Add balance column + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/integer", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'balance', + 'required' => false, + 'default' => 0, + ]); + + sleep(2); + + // Create initial row + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => 'test', + 'data' => ['balance' => 100] + ]); + + // Create transaction using TablesDB API + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Stage operations using TablesDB API (will store 'column' key) + $this->client->call( + Client::METHOD_PATCH, + "/tablesdb/{$databaseId}/tables/{$tableId}/rows/test/balance/decrement", + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), + [ + 'transactionId' => $transactionId, + 'value' => 30, + ] + ); + + // Commit using Collections API (expects 'attribute' key but should fallback to 'column') + $commitResponse = $this->client->call( + Client::METHOD_PATCH, + "/databases/transactions/{$transactionId}", + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), + [ + 'commit' => true + ] + ); + + $this->assertEquals(200, $commitResponse['headers']['status-code'], 'Cross-API commit should succeed'); + + // Verify final value + $row = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/test", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $row['headers']['status-code']); + $this->assertEquals(70, $row['body']['balance'], 'Balance should be 100 - 30 = 70'); + } + + public function testBulkUpdateWithDependentDocuments(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkUpdateDependentDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestTable', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Add columns + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'status', + 'size' => 50, + 'required' => false, + ]); + + sleep(2); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Create a document, then bulk update it - this triggers the state structure bug + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => 'doc1', + 'data' => [ + 'status' => 'pending' + ] + ], + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'bulkUpdate', + 'data' => [ + 'queries' => [], + 'data' => [ + 'status' => 'approved' + ] + ] + ], + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code'], 'Bulk update should succeed on dependent documents'); + + // Verify the document was updated + $row = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/doc1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $row['headers']['status-code']); + $this->assertEquals('approved', $row['body']['status']); + } + + /** + * Test bulk delete with dependent documents (Bug #2 regression test) + */ + public function testBulkDeleteWithDependentDocuments(): void + { + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkDeleteDependentDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestTable', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 50, + 'required' => false, + ]); + + sleep(2); + + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Create then bulk delete + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => 'doc1', + 'data' => [ + 'name' => 'Test' + ] + ], + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'bulkDelete', + 'data' => [ + 'queries' => [], + ] + ], + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code'], 'Bulk delete should succeed on dependent documents'); + + // Verify document was deleted + $rows = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(0, $rows['body']['total']); + } + + /** + * Test bulk upsert with dependent documents (Bug #3 regression test) + */ + public function testBulkUpsertWithDependentDocuments(): void + { + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkUpsertDependentDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestTable', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'status', + 'size' => 50, + 'required' => false, + ]); + + sleep(2); + + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Create then bulk upsert same document + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'create', + 'rowId' => 'doc1', + 'data' => [ + 'status' => 'pending' + ] + ], + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'bulkUpsert', + 'data' => [ + [ + '$id' => 'doc1', + 'status' => 'approved' + ] + ] + ], + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code'], 'Bulk upsert should succeed on dependent documents'); + + $row = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/doc1", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $row['headers']['status-code']); + $this->assertEquals('approved', $row['body']['status']); + } + + /** + * Test bulk update operations in transaction + */ + public function testBulkUpdateOperations(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkUpdateTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'BulkUpdateTable', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Add columns + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'status', + 'size' => 50, + 'required' => false, + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'category', + 'size' => 50, + 'required' => false, + ]); + + sleep(2); + + // Create initial rows + for ($i = 1; $i <= 5; $i++) { + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => "row_{$i}", + 'data' => [ + 'status' => 'pending', + 'category' => $i % 2 === 0 ? 'even' : 'odd' + ] + ]); + } + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Add bulk update operations + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'bulkUpdate', + 'data' => [ + 'queries' => [ + Query::equal('category', ['even'])->toString() + ], + 'data' => [ + 'status' => 'approved' + ] + ] + ], + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'bulkUpdate', + 'data' => [ + 'queries' => [ + Query::equal('category', ['odd'])->toString() + ], + 'data' => [ + 'status' => 'rejected' + ] + ] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Verify updates + $rows = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + foreach ($rows['body']['rows'] as $row) { + if ($row['category'] === 'even') { + $this->assertEquals('approved', $row['status']); + } else { + $this->assertEquals('rejected', $row['status']); + } + } + } + + /** + * Test bulk upsert operations in transaction + */ + public function testBulkUpsertOperations(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkUpsertTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'BulkUpsertTable', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Add columns + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 100, + 'required' => false, + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/integer", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'value', + 'required' => false, + ]); + + sleep(2); + + // Create some initial rows + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => 'existing_1', + 'data' => [ + 'name' => 'Existing Row 1', + 'value' => 10 + ] + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => 'existing_2', + 'data' => [ + 'name' => 'Existing Row 2', + 'value' => 20 + ] + ]); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Add bulk upsert operations + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'bulkUpsert', + 'data' => [ + [ + '$id' => 'existing_1', + 'name' => 'Updated Row 1', + 'value' => 100 + ], + [ + '$id' => 'new_1', + 'name' => 'New Row 1', + 'value' => 30 + ], + [ + '$id' => 'new_2', + 'name' => 'New Row 2', + 'value' => 40 + ] + ] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Verify results + $rows = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(4, $rows['body']['total']); + + $rowMap = []; + foreach ($rows['body']['rows'] as $row) { + $rowMap[$row['$id']] = $row; + } + + // Verify updated row + $this->assertEquals('Updated Row 1', $rowMap['existing_1']['name']); + $this->assertEquals(100, $rowMap['existing_1']['value']); + + // Verify unchanged row + $this->assertEquals('Existing Row 2', $rowMap['existing_2']['name']); + $this->assertEquals(20, $rowMap['existing_2']['value']); + + // Verify new rows + $this->assertEquals('New Row 1', $rowMap['new_1']['name']); + $this->assertEquals(30, $rowMap['new_1']['value']); + $this->assertEquals('New Row 2', $rowMap['new_2']['name']); + $this->assertEquals(40, $rowMap['new_2']['value']); + } + + /** + * Test bulk delete operations in transaction + */ + public function testBulkDeleteOperations(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkDeleteTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'BulkDeleteTable', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Add columns + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'type', + 'size' => 50, + 'required' => false, + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/integer", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'priority', + 'required' => false, + ]); + + sleep(2); + + // Create initial rows + for ($i = 1; $i <= 10; $i++) { + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rowId' => "row_{$i}", + 'data' => [ + 'type' => $i <= 5 ? 'temp' : 'permanent', + 'priority' => $i + ] + ]); + } + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Add bulk delete operations + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'bulkDelete', + 'data' => [ + 'queries' => [ + Query::equal('type', ['temp'])->toString() + ] + ] + ], + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'action' => 'bulkDelete', + 'data' => [ + 'queries' => [ + Query::greaterThan('priority', 8)->toString() + ] + ] + ] + ] + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Verify deletions + $rows = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + // Should have deleted rows 1-5 (temp) and rows 9-10 (priority > 8) + // Remaining should be rows 6-8 + $this->assertEquals(3, $rows['body']['total']); + + $remainingIds = array_map(fn ($row) => $row['$id'], $rows['body']['rows']); + sort($remainingIds); + $this->assertEquals(['row_6', 'row_7', 'row_8'], $remainingIds); + } + + /** + * Test validation for invalid operation inputs + */ + public function testCreateOperationsValidation(): void + { + // Create database and table for testing + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'ValidationTestDatabase' + ]); + + $this->assertEquals(201, $database['headers']['status-code']); + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'ValidationTest', + 'rowSecurity' => false, + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $this->assertEquals(201, $table['headers']['status-code']); + $tableId = $table['body']['$id']; + + // Add required column + $column = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->assertEquals(202, $column['headers']['status-code']); + + // Wait for column to be ready + sleep(2); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + $transactionId = $transaction['body']['$id']; + + // Test 1: Invalid action type + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'action' => 'invalidAction', + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'rowId' => ID::unique(), + 'data' => ['name' => 'Test'] + ] + ] + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // Test 2: Missing required action field + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'rowId' => ID::unique(), + 'data' => ['name' => 'Test'] + ] + ] + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // Test 3: Missing required databaseId field + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'action' => 'create', + 'tableId' => $tableId, + 'rowId' => ID::unique(), + 'data' => ['name' => 'Test'] + ] + ] + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // Test 4: Missing required tableId field + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'action' => 'create', + 'databaseId' => $databaseId, + 'rowId' => ID::unique(), + 'data' => ['name' => 'Test'] + ] + ] + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // Test 5: Missing rowId for create operation + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'action' => 'create', + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'data' => ['name' => 'Test'] + ] + ] + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // Test 6: Missing data for create operation + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'action' => 'create', + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'rowId' => ID::unique() + ] + ] + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // Test 7: BulkCreate with non-array data + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'action' => 'bulkCreate', + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'data' => 'not an array' + ] + ] + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // Test 8: BulkUpdate with missing queries + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'action' => 'bulkUpdate', + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'data' => [ + 'data' => ['name' => 'Updated'] + ] + ] + ] + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // Test 9: BulkUpdate with invalid query format + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'action' => 'bulkUpdate', + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'data' => [ + 'queries' => 'not an array', + 'data' => ['name' => 'Updated'] + ] + ] + ] + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // Test 10: BulkDelete with missing queries + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'action' => 'bulkDelete', + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'data' => [] + ] + ] + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // Test 11: Increment with missing attribute + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'action' => 'increment', + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'rowId' => ID::unique(), + 'data' => ['value' => 1] + ] + ] + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // Test 12: Decrement with invalid value type + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'action' => 'decrement', + 'databaseId' => $databaseId, + 'tableId' => $tableId, + 'rowId' => ID::unique(), + 'data' => [ + 'attribute' => 'counter', + 'value' => 'not a number' + ] + ] + ] + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // Test 13: Empty operations array + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [] + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // Test 14: Operations not an array + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => 'not an array' + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + } + + /** + * Test validation for committing/rolling back transactions + */ + public function testCommitRollbackValidation(): void + { + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + $transactionId = $transaction['body']['$id']; + + // Test 1: Missing both commit and rollback + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), []); + + $this->assertEquals(400, $response['headers']['status-code']); + + // Test 2: Both commit and rollback set to true + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true, + 'rollback' => true + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // Test 3: Invalid transaction ID + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/invalid_id", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(404, $response['headers']['status-code']); + + // Commit the transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Test 4: Attempt to commit already committed transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + } + + /** + * Test validation for non-existent resources + */ + public function testNonExistentResources(): void + { + // Create database and transaction + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'ResourceTestDatabase' + ]); + + $this->assertEquals(201, $database['headers']['status-code']); + $databaseId = $database['body']['$id']; + + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(201, $transaction['headers']['status-code']); + $transactionId = $transaction['body']['$id']; + + // Test 1: Non-existent database + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'action' => 'create', + 'databaseId' => 'nonExistentDatabase', + 'tableId' => 'someTable', + 'rowId' => ID::unique(), + 'data' => ['name' => 'Test'] + ] + ] + ]); + + $this->assertEquals(404, $response['headers']['status-code']); + + // Test 2: Non-existent table + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/transactions/{$transactionId}/operations", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'operations' => [ + [ + 'action' => 'create', + 'databaseId' => $databaseId, + 'tableId' => 'nonExistentTable', + 'rowId' => ID::unique(), + 'data' => ['name' => 'Test'] + ] + ] + ]); + + $this->assertEquals(404, $response['headers']['status-code']); + } + + /** + * Test that bulkUpdate can match documents created in the same transaction + * This tests the fix for the bug where applyBulkUpdateToState was treating + * state entries as Documents instead of arrays with 'document' keys + */ + public function testBulkUpdateMatchesCreatedDocsInSameTransaction(): void + { + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'BulkUpdateStateDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestTable', + 'permissions' => [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'status', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'flag', + 'size' => 256, + 'required' => false, + ]); + + sleep(3); + + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // Create 3 documents with status='pending' in transaction + $docIds = []; + for ($i = 1; $i <= 3; $i++) { + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => 'test_' . $i, + 'data' => [ + 'status' => 'pending' + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $docIds[] = $response['body']['$id']; + } + + // Bulk update all documents with status='pending' to add flag='processed' + // This should match all 3 documents created above in the same transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'data' => [ + 'flag' => 'processed' + ], + 'queries' => [Query::equal('status', ['pending'])->toString()], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Verify all 3 documents have the flag set + foreach ($docIds as $docId) { + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/{$docId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('pending', $response['body']['status']); + $this->assertEquals('processed', $response['body']['flag'], 'Bulk update should have matched document created in same transaction'); + } + } + + /** + * Test upsert with auto-generated ID followed by update + * This tests that the transaction state properly stores the document under its actual ID, + * not under null when the ID is auto-generated + */ + public function testUpsertAutoIdThenUpdate(): void + { + // Create database and table + $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'UpsertAutoIDTestDB' + ]); + + $databaseId = $database['body']['$id']; + + $table = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'tableId' => ID::unique(), + 'name' => 'TestCollection', + 'permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + $tableId = $table['body']['$id']; + + // Create columns + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/string", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/columns/integer", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'counter', + 'required' => false, + 'min' => 0, + 'max' => 10000, + ]); + + sleep(3); + + // Create transaction + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $transactionId = $transaction['body']['$id']; + + // First create a document in the transaction + $response = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$tableId}/rows", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'rowId' => ID::unique(), + 'data' => [ + 'name' => 'Initial document', + 'counter' => 5 + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $docId = $response['body']['$id']; + + // Now upsert the same document using ID::unique() in the path + // The database will recognize it exists and update it, generating a new auto ID if needed + // This tests that handleUpsertOperation properly captures the actual document ID + $response = $this->client->call(Client::METHOD_PUT, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/{$docId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'data' => [ + 'name' => 'Upserted in transaction', + 'counter' => 10 + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // Now try to update the same document again in the same transaction + // This verifies that the upsert properly stored the document under its actual ID in state + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/{$docId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'data' => [ + 'name' => 'Updated after upsert', + 'counter' => 20 + ], + 'transactionId' => $transactionId + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Commit transaction + $response = $this->client->call(Client::METHOD_PATCH, "/tablesdb/transactions/{$transactionId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'commit' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + // Verify the document has the final updated values + $response = $this->client->call(Client::METHOD_GET, "/tablesdb/{$databaseId}/tables/{$tableId}/rows/{$docId}", array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('Updated after upsert', $response['body']['name']); + $this->assertEquals(20, $response['body']['counter']); + } +} diff --git a/tests/e2e/Services/Databases/TablesDB/Transactions/TransactionsConsoleClientTest.php b/tests/e2e/Services/Databases/TablesDB/Transactions/TransactionsConsoleClientTest.php new file mode 100644 index 0000000000..2159390fa2 --- /dev/null +++ b/tests/e2e/Services/Databases/TablesDB/Transactions/TransactionsConsoleClientTest.php @@ -0,0 +1,14 @@ + 10, ]); $this->assertEquals(401, $function['headers']['status-code']); + + + /** + * Test for DUPLICATE functionId + */ + $functionId = $this->setupFunction([ + 'functionId' => ID::unique(), + 'name' => 'Test', + 'execute' => [Role::user($this->getUser()['$id'])->toString()], + 'runtime' => 'node-22', + 'entrypoint' => 'index.js', + 'events' => [ + 'users.*.create', + 'users.*.delete', + ], + 'timeout' => 10, + ]); + + $response = $this->client->call(Client::METHOD_POST, '/functions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'functionId' => $functionId, + 'name' => 'Test', + 'execute' => [Role::user($this->getUser()['$id'])->toString()], + 'runtime' => 'node-22', + 'entrypoint' => 'index.js', + 'events' => [ + 'users.*.create', + 'users.*.delete', + ], + 'timeout' => 10, + ]); + $this->assertEquals(409, $response['headers']['status-code']); } public function testCreateExecution() diff --git a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php index e44c1170a3..c6a1686864 100644 --- a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php @@ -28,7 +28,7 @@ class RealtimeCustomClientTest extends Scope $userId = $user['$id'] ?? ''; $session = $user['session'] ?? ''; - $headers = [ + $headers = [ 'origin' => 'http://localhost', 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session ]; @@ -2514,6 +2514,464 @@ class RealtimeCustomClientTest extends Scope $client->close(); } + public function testChannelDatabaseTransaction() + { + $user = $this->getUser(); + $session = $user['session'] ?? ''; + $projectId = $this->getProject()['$id']; + + $client = $this->getWebsocket(['documents'], [ + 'origin' => 'http://localhost', + 'cookie' => 'a_session_' . $projectId . '=' . $session + ]); + + $response = json_decode($client->receive(), true); + + $this->assertArrayHasKey('type', $response); + $this->assertEquals('connected', $response['type']); + + /** + * Setup Database and Collection + */ + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'Transactions DB', + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'Test Collection', + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + ], + 'documentSecurity' => true, + ]); + + $collectionId = $collection['body']['$id']; + + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + sleep(2); + + /** + * Test Transaction Create with Single Document + */ + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'ttl' => 3600 // 1 hour + ]); + + $this->assertEquals(201, $transaction['headers']['status-code'], 'Failed to create transaction: ' . json_encode($transaction['body'])); + $this->assertNotEmpty($transaction['body']['$id']); + + $transactionId = $transaction['body']['$id']; + $documentId = ID::unique(); + + $operationsResponse = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions/' . $transactionId . '/operations', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $collectionId, + 'rowId' => $documentId, + 'action' => 'create', + 'data' => [ + 'name' => 'Transaction Document', + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ], + ] + ] + ]); + + $this->assertEquals(201, $operationsResponse['headers']['status-code'], 'Failed to add operations: ' . json_encode($operationsResponse['body'])); + + // Commit transaction + $commitResponse = $this->client->call(Client::METHOD_PATCH, '/tablesdb/transactions/' . $transactionId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'commit' => true + ]); + + $this->assertEquals(200, $commitResponse['headers']['status-code'], 'Failed to commit transaction: ' . json_encode($commitResponse['body'])); + + $response = json_decode($client->receive(), true); + + $this->assertArrayHasKey('type', $response); + $this->assertArrayHasKey('data', $response); + $this->assertEquals('event', $response['type']); + $this->assertNotEmpty($response['data']); + $this->assertArrayHasKey('timestamp', $response['data']); + $this->assertContains('documents', $response['data']['channels']); + $this->assertContains("databases.{$databaseId}.tables.{$collectionId}.rows.{$documentId}.create", $response['data']['events']); + $this->assertNotEmpty($response['data']['payload']); + $this->assertEquals('Transaction Document', $response['data']['payload']['name']); + + /** + * Test Transaction Update + */ + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'ttl' => 3600 + ]); + + $transactionId = $transaction['body']['$id']; + + $this->client->call(Client::METHOD_POST, '/tablesdb/transactions/' . $transactionId . '/operations', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $collectionId, + 'rowId' => $documentId, + 'action' => 'update', + 'data' => [ + 'name' => 'Updated Transaction Document', + ], + ] + ] + ]); + + $this->client->call(Client::METHOD_PATCH, '/tablesdb/transactions/' . $transactionId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'commit' => true + ]); + + $response = json_decode($client->receive(), true); + + $this->assertArrayHasKey('type', $response); + $this->assertEquals('event', $response['type']); + $this->assertContains("databases.{$databaseId}.tables.{$collectionId}.rows.{$documentId}.update", $response['data']['events']); + $this->assertEquals('Updated Transaction Document', $response['data']['payload']['name']); + + /** + * Test Transaction Delete + */ + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'ttl' => 3600 + ]); + + $transactionId = $transaction['body']['$id']; + + $this->client->call(Client::METHOD_POST, '/tablesdb/transactions/' . $transactionId . '/operations', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $collectionId, + 'rowId' => $documentId, + 'action' => 'delete', + ] + ] + ]); + + $this->client->call(Client::METHOD_PATCH, '/tablesdb/transactions/' . $transactionId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'commit' => true + ]); + + $response = json_decode($client->receive(), true); + + $this->assertArrayHasKey('type', $response); + $this->assertEquals('event', $response['type']); + $this->assertContains("databases.{$databaseId}.tables.{$collectionId}.rows.{$documentId}.delete", $response['data']['events']); + + $client->close(); + } + + public function testChannelDatabaseTransactionMultipleOperations() + { + $user = $this->getUser(); + $session = $user['session'] ?? ''; + $projectId = $this->getProject()['$id']; + + $client = $this->getWebsocket(['documents'], [ + 'origin' => 'http://localhost', + 'cookie' => 'a_session_' . $projectId . '=' . $session + ]); + + $response = json_decode($client->receive(), true); + $this->assertEquals('connected', $response['type']); + + /** + * Setup Database and Collection + */ + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'Multi-Op DB', + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'Test Collection', + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + ], + 'documentSecurity' => true, + ]); + + $collectionId = $collection['body']['$id']; + + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + sleep(2); + + /** + * Test Multiple Operations in Single Transaction + */ + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'ttl' => 3600 + ]); + + $transactionId = $transaction['body']['$id']; + $documentId1 = ID::unique(); + $documentId2 = ID::unique(); + $documentId3 = ID::unique(); + + $this->client->call(Client::METHOD_POST, '/tablesdb/transactions/' . $transactionId . '/operations', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $collectionId, + 'rowId' => $documentId1, + 'action' => 'create', + 'data' => [ + 'name' => 'Doc 1', + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ], + ], + [ + 'databaseId' => $databaseId, + 'tableId' => $collectionId, + 'rowId' => $documentId2, + 'action' => 'create', + 'data' => [ + 'name' => 'Doc 2', + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ], + ], + [ + 'databaseId' => $databaseId, + 'tableId' => $collectionId, + 'rowId' => $documentId3, + 'action' => 'create', + 'data' => [ + 'name' => 'Doc 3', + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + ], + ] + ] + ]); + + $this->client->call(Client::METHOD_PATCH, '/tablesdb/transactions/' . $transactionId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'commit' => true + ]); + + // Should receive 3 events, one for each document + $response1 = json_decode($client->receive(), true); + $response2 = json_decode($client->receive(), true); + $response3 = json_decode($client->receive(), true); + + $this->assertEquals('event', $response1['type']); + $this->assertEquals('event', $response2['type']); + $this->assertEquals('event', $response3['type']); + + $receivedDocIds = [ + $response1['data']['payload']['$id'], + $response2['data']['payload']['$id'], + $response3['data']['payload']['$id'], + ]; + + $this->assertContains($documentId1, $receivedDocIds); + $this->assertContains($documentId2, $receivedDocIds); + $this->assertContains($documentId3, $receivedDocIds); + + $client->close(); + } + + public function testChannelDatabaseTransactionRollback() + { + $user = $this->getUser(); + $session = $user['session'] ?? ''; + $projectId = $this->getProject()['$id']; + + $client = $this->getWebsocket(['documents'], [ + 'origin' => 'http://localhost', + 'cookie' => 'a_session_' . $projectId . '=' . $session + ]); + + $response = json_decode($client->receive(), true); + $this->assertEquals('connected', $response['type']); + + /** + * Setup Database and Collection + */ + $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'databaseId' => ID::unique(), + 'name' => 'Rollback DB', + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'Test Collection', + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + ], + 'documentSecurity' => true, + ]); + + $collectionId = $collection['body']['$id']; + + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + sleep(2); + + /** + * Test Transaction Rollback - Should NOT trigger realtime events + */ + $transaction = $this->client->call(Client::METHOD_POST, '/tablesdb/transactions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'ttl' => 3600 + ]); + + $transactionId = $transaction['body']['$id']; + $documentId = ID::unique(); + + $this->client->call(Client::METHOD_POST, '/tablesdb/transactions/' . $transactionId . '/operations', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'operations' => [ + [ + 'databaseId' => $databaseId, + 'tableId' => $collectionId, + 'rowId' => $documentId, + 'action' => 'create', + 'data' => ['name' => 'Rollback Document'], + ] + ] + ]); + + // Rollback transaction + $this->client->call(Client::METHOD_PATCH, '/tablesdb/transactions/' . $transactionId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'rollback' => true + ]); + + // Wait a bit to ensure no event is received + sleep(1); + + try { + $client->receive(1); // 1 second timeout + $this->fail('Should not receive any event after rollback'); + } catch (TimeoutException $e) { + // Expected - no event should be triggered + $this->assertTrue(true); + } + + $client->close(); + } + public function testRelationshipPayloadHidesRelatedDoc() { $user = $this->getUser(); @@ -2616,7 +3074,7 @@ class RealtimeCustomClientTest extends Scope 'x-appwrite-project' => $projectId, ], $this->getHeaders()), [ 'documentId' => ID::unique(), - 'data' => [ 'name' => 'L2' ], + 'data' => ['name' => 'L2'], 'permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -2630,7 +3088,7 @@ class RealtimeCustomClientTest extends Scope 'x-appwrite-project' => $projectId, ], $this->getHeaders()), [ 'documentId' => ID::unique(), - 'data' => [ 'name' => 'L1' ], + 'data' => ['name' => 'L1'], 'permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()),