Merge branch '1.6.x' into pla-1849

This commit is contained in:
Chirag Aggarwal 2025-05-10 08:30:50 +00:00
commit 28fe6f34de
109 changed files with 8388 additions and 152407 deletions

2
.env
View file

@ -82,7 +82,7 @@ _APP_EXECUTOR_SECRET=your-secret-key
_APP_EXECUTOR_HOST=http://proxy/v1
_APP_FUNCTIONS_RUNTIMES=php-8.0,node-18.0,python-3.9,ruby-3.1
_APP_MAINTENANCE_INTERVAL=86400
_APP_MAINTENANCE_DELAY=
_APP_MAINTENANCE_START_TIME=12:00
_APP_MAINTENANCE_RETENTION_CACHE=2592000
_APP_MAINTENANCE_RETENTION_EXECUTION=1209600
_APP_MAINTENANCE_RETENTION_ABUSE=86400

View file

@ -245,7 +245,7 @@ return [
[
'key' => 'nodejs',
'name' => 'Node.js',
'version' => '16.0.0',
'version' => '16.1.0-rc.1',
'url' => 'https://github.com/appwrite/sdk-for-node',
'package' => 'https://www.npmjs.com/package/node-appwrite',
'enabled' => true,
@ -263,7 +263,7 @@ return [
[
'key' => 'deno',
'name' => 'Deno',
'version' => '14.0.0',
'version' => '14.1.0-rc.1',
'url' => 'https://github.com/appwrite/sdk-for-deno',
'package' => 'https://deno.land/x/appwrite',
'enabled' => true,
@ -281,7 +281,7 @@ return [
[
'key' => 'php',
'name' => 'PHP',
'version' => '14.0.0',
'version' => '14.1.0-rc.1',
'url' => 'https://github.com/appwrite/sdk-for-php',
'package' => 'https://packagist.org/packages/appwrite/appwrite',
'enabled' => true,
@ -299,7 +299,7 @@ return [
[
'key' => 'python',
'name' => 'Python',
'version' => '10.0.0',
'version' => '10.1.0-rc.1',
'url' => 'https://github.com/appwrite/sdk-for-python',
'package' => 'https://pypi.org/project/appwrite/',
'enabled' => true,
@ -317,7 +317,7 @@ return [
[
'key' => 'ruby',
'name' => 'Ruby',
'version' => '15.0.0',
'version' => '15.1.0-rc.1',
'url' => 'https://github.com/appwrite/sdk-for-ruby',
'package' => 'https://rubygems.org/gems/appwrite',
'enabled' => true,
@ -335,7 +335,7 @@ return [
[
'key' => 'go',
'name' => 'Go',
'version' => '0.5.0',
'version' => '0.6.0-rc.1',
'url' => 'https://github.com/appwrite/sdk-for-go',
'package' => 'https://github.com/appwrite/sdk-for-go',
'enabled' => true,
@ -353,7 +353,7 @@ return [
[
'key' => 'dotnet',
'name' => '.NET',
'version' => '0.12.0',
'version' => '0.13.0-rc.1',
'url' => 'https://github.com/appwrite/sdk-for-dotnet',
'package' => 'https://www.nuget.org/packages/Appwrite',
'enabled' => true,
@ -371,7 +371,7 @@ return [
[
'key' => 'dart',
'name' => 'Dart',
'version' => '15.0.0',
'version' => '15.1.0-rc.1',
'url' => 'https://github.com/appwrite/sdk-for-dart',
'package' => 'https://pub.dev/packages/dart_appwrite',
'enabled' => true,
@ -389,7 +389,7 @@ return [
[
'key' => 'kotlin',
'name' => 'Kotlin',
'version' => '8.0.0',
'version' => '8.1.0-rc.1',
'url' => 'https://github.com/appwrite/sdk-for-kotlin',
'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-kotlin',
'enabled' => true,
@ -411,7 +411,7 @@ return [
[
'key' => 'swift',
'name' => 'Swift',
'version' => '9.0.0',
'version' => '9.1.0-rc.1',
'url' => 'https://github.com/appwrite/sdk-for-swift',
'package' => 'https://github.com/appwrite/sdk-for-swift',
'enabled' => true,

View file

@ -65,9 +65,6 @@ return [
'tests' => false,
'optional' => true,
'icon' => '/images/services/databases.png',
'globalAttributes' => [
'databaseId'
]
],
'locale' => [
'key' => 'locale',

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -2646,7 +2646,10 @@
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-email.md",
"rate-limit": 10,
"rate-time": 3600,
"rate-key": "url:{url},email:{param-email}",
"rate-key": [
"url:{url},email:{param-email}",
"url:{url},ip:{ip}"
],
"scope": "sessions.write",
"platforms": [
"server",
@ -4427,7 +4430,7 @@
"tags": [
"databases"
],
"description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.\n",
"description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.",
"responses": {
"201": {
"description": "Document",
@ -4459,6 +4462,51 @@
"server"
],
"packaging": false,
"methods": [
{
"name": "createDocument",
"parameters": [
"databaseId",
"collectionId",
"documentId",
"data",
"permissions"
],
"required": [
"databaseId",
"collectionId",
"documentId",
"data"
],
"responses": [
{
"code": 201,
"model": "#\/components\/schemas\/document"
}
],
"description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console."
},
{
"name": "createDocuments",
"parameters": [
"databaseId",
"collectionId",
"documents"
],
"required": [
"databaseId",
"collectionId",
"documents"
],
"responses": [
{
"code": 201,
"model": "#\/components\/schemas\/documentList"
}
],
"description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.\n"
}
],
"auth": {
"Project": []
}
@ -4515,12 +4563,16 @@
"items": {
"type": "string"
}
},
"documents": {
"type": "array",
"description": "Array of documents data as JSON objects.",
"x-example": null,
"items": {
"type": "object"
}
}
},
"required": [
"documentId",
"data"
]
}
}
}
}
@ -4744,7 +4796,7 @@
"x-appwrite": {
"method": "deleteDocument",
"group": "documents",
"weight": 113,
"weight": 115,
"cookies": false,
"type": "",
"deprecated": false,
@ -4828,7 +4880,7 @@
"x-appwrite": {
"method": "listExecutions",
"group": "executions",
"weight": 305,
"weight": 308,
"cookies": false,
"type": "",
"deprecated": false,
@ -4914,7 +4966,7 @@
"x-appwrite": {
"method": "createExecution",
"group": "executions",
"weight": 304,
"weight": 307,
"cookies": false,
"type": "",
"deprecated": false,
@ -5029,7 +5081,7 @@
"x-appwrite": {
"method": "getExecution",
"group": "executions",
"weight": 306,
"weight": 309,
"cookies": false,
"type": "",
"deprecated": false,
@ -5103,7 +5155,7 @@
"x-appwrite": {
"method": "query",
"group": "graphql",
"weight": 330,
"weight": 333,
"cookies": false,
"type": "graphql",
"deprecated": false,
@ -5155,7 +5207,7 @@
"x-appwrite": {
"method": "mutation",
"group": "graphql",
"weight": 329,
"weight": 332,
"cookies": false,
"type": "graphql",
"deprecated": false,
@ -5207,7 +5259,7 @@
"x-appwrite": {
"method": "get",
"group": null,
"weight": 117,
"weight": 120,
"cookies": false,
"type": "",
"deprecated": false,
@ -5259,7 +5311,7 @@
"x-appwrite": {
"method": "listCodes",
"group": null,
"weight": 118,
"weight": 121,
"cookies": false,
"type": "",
"deprecated": false,
@ -5311,7 +5363,7 @@
"x-appwrite": {
"method": "listContinents",
"group": null,
"weight": 122,
"weight": 125,
"cookies": false,
"type": "",
"deprecated": false,
@ -5363,7 +5415,7 @@
"x-appwrite": {
"method": "listCountries",
"group": null,
"weight": 119,
"weight": 122,
"cookies": false,
"type": "",
"deprecated": false,
@ -5415,7 +5467,7 @@
"x-appwrite": {
"method": "listCountriesEU",
"group": null,
"weight": 120,
"weight": 123,
"cookies": false,
"type": "",
"deprecated": false,
@ -5467,7 +5519,7 @@
"x-appwrite": {
"method": "listCountriesPhones",
"group": null,
"weight": 121,
"weight": 124,
"cookies": false,
"type": "",
"deprecated": false,
@ -5519,7 +5571,7 @@
"x-appwrite": {
"method": "listCurrencies",
"group": null,
"weight": 123,
"weight": 126,
"cookies": false,
"type": "",
"deprecated": false,
@ -5571,7 +5623,7 @@
"x-appwrite": {
"method": "listLanguages",
"group": null,
"weight": 124,
"weight": 127,
"cookies": false,
"type": "",
"deprecated": false,
@ -5623,7 +5675,7 @@
"x-appwrite": {
"method": "createSubscriber",
"group": "subscribers",
"weight": 375,
"weight": 378,
"cookies": false,
"type": "",
"deprecated": false,
@ -5706,7 +5758,7 @@
"x-appwrite": {
"method": "deleteSubscriber",
"group": "subscribers",
"weight": 379,
"weight": 382,
"cookies": false,
"type": "",
"deprecated": false,
@ -5781,7 +5833,7 @@
"x-appwrite": {
"method": "listFiles",
"group": "files",
"weight": 207,
"weight": 210,
"cookies": false,
"type": "",
"deprecated": false,
@ -5867,7 +5919,7 @@
"x-appwrite": {
"method": "createFile",
"group": "files",
"weight": 206,
"weight": 209,
"cookies": false,
"type": "upload",
"deprecated": false,
@ -5965,7 +6017,7 @@
"x-appwrite": {
"method": "getFile",
"group": "files",
"weight": 208,
"weight": 211,
"cookies": false,
"type": "",
"deprecated": false,
@ -6037,7 +6089,7 @@
"x-appwrite": {
"method": "updateFile",
"group": "files",
"weight": 213,
"weight": 216,
"cookies": false,
"type": "",
"deprecated": false,
@ -6126,7 +6178,7 @@
"x-appwrite": {
"method": "deleteFile",
"group": "files",
"weight": 214,
"weight": 217,
"cookies": false,
"type": "",
"deprecated": false,
@ -6193,7 +6245,7 @@
"x-appwrite": {
"method": "getFileDownload",
"group": "files",
"weight": 210,
"weight": 213,
"cookies": false,
"type": "location",
"deprecated": false,
@ -6260,7 +6312,7 @@
"x-appwrite": {
"method": "getFilePreview",
"group": "files",
"weight": 209,
"weight": 212,
"cookies": false,
"type": "location",
"deprecated": false,
@ -6477,7 +6529,7 @@
"x-appwrite": {
"method": "getFileView",
"group": "files",
"weight": 211,
"weight": 214,
"cookies": false,
"type": "location",
"deprecated": false,
@ -6551,7 +6603,7 @@
"x-appwrite": {
"method": "list",
"group": "teams",
"weight": 218,
"weight": 221,
"cookies": false,
"type": "",
"deprecated": false,
@ -6627,7 +6679,7 @@
"x-appwrite": {
"method": "create",
"group": "teams",
"weight": 217,
"weight": 220,
"cookies": false,
"type": "",
"deprecated": false,
@ -6712,7 +6764,7 @@
"x-appwrite": {
"method": "get",
"group": "teams",
"weight": 219,
"weight": 222,
"cookies": false,
"type": "",
"deprecated": false,
@ -6774,7 +6826,7 @@
"x-appwrite": {
"method": "updateName",
"group": "teams",
"weight": 221,
"weight": 224,
"cookies": false,
"type": "",
"deprecated": false,
@ -6848,7 +6900,7 @@
"x-appwrite": {
"method": "delete",
"group": "teams",
"weight": 223,
"weight": 226,
"cookies": false,
"type": "",
"deprecated": false,
@ -6912,7 +6964,7 @@
"x-appwrite": {
"method": "listMemberships",
"group": "memberships",
"weight": 225,
"weight": 228,
"cookies": false,
"type": "",
"deprecated": false,
@ -6998,7 +7050,7 @@
"x-appwrite": {
"method": "createMembership",
"group": "memberships",
"weight": 224,
"weight": 227,
"cookies": false,
"type": "",
"deprecated": false,
@ -7109,7 +7161,7 @@
"x-appwrite": {
"method": "getMembership",
"group": "memberships",
"weight": 226,
"weight": 229,
"cookies": false,
"type": "",
"deprecated": false,
@ -7181,7 +7233,7 @@
"x-appwrite": {
"method": "updateMembership",
"group": "memberships",
"weight": 227,
"weight": 230,
"cookies": false,
"type": "",
"deprecated": false,
@ -7268,7 +7320,7 @@
"x-appwrite": {
"method": "deleteMembership",
"group": "memberships",
"weight": 229,
"weight": 232,
"cookies": false,
"type": "",
"deprecated": false,
@ -7342,7 +7394,7 @@
"x-appwrite": {
"method": "updateMembershipStatus",
"group": "memberships",
"weight": 228,
"weight": 231,
"cookies": false,
"type": "",
"deprecated": false,
@ -7440,7 +7492,7 @@
"x-appwrite": {
"method": "getPrefs",
"group": "teams",
"weight": 220,
"weight": 223,
"cookies": false,
"type": "",
"deprecated": false,
@ -7501,7 +7553,7 @@
"x-appwrite": {
"method": "updatePrefs",
"group": "teams",
"weight": 222,
"weight": 225,
"cookies": false,
"type": "",
"deprecated": false,
@ -7564,85 +7616,67 @@
"tags": [
{
"name": "account",
"description": "The Account service allows you to authenticate and manage a user account.",
"x-globalAttributes": []
"description": "The Account service allows you to authenticate and manage a user account."
},
{
"name": "avatars",
"description": "The Avatars service aims to help you complete everyday tasks related to your app image, icons, and avatars.",
"x-globalAttributes": []
"description": "The Avatars service aims to help you complete everyday tasks related to your app image, icons, and avatars."
},
{
"name": "databases",
"description": "The Databases service allows you to create structured collections of documents, query and filter lists of documents",
"x-globalAttributes": [
"databaseId"
]
"description": "The Databases service allows you to create structured collections of documents, query and filter lists of documents"
},
{
"name": "locale",
"description": "The Locale service allows you to customize your app based on your users' location.",
"x-globalAttributes": []
"description": "The Locale service allows you to customize your app based on your users' location."
},
{
"name": "health",
"description": "The Health service allows you to both validate and monitor your Appwrite server's health.",
"x-globalAttributes": []
"description": "The Health service allows you to both validate and monitor your Appwrite server's health."
},
{
"name": "projects",
"description": "The Project service allows you to manage all the projects in your Appwrite server.",
"x-globalAttributes": []
"description": "The Project service allows you to manage all the projects in your Appwrite server."
},
{
"name": "project",
"description": "The Project service allows you to manage all the projects in your Appwrite server.",
"x-globalAttributes": []
"description": "The Project service allows you to manage all the projects in your Appwrite server."
},
{
"name": "storage",
"description": "The Storage service allows you to manage your project files.",
"x-globalAttributes": []
"description": "The Storage service allows you to manage your project files."
},
{
"name": "teams",
"description": "The Teams service allows you to group users of your project and to enable them to share read and write access to your project resources",
"x-globalAttributes": []
"description": "The Teams service allows you to group users of your project and to enable them to share read and write access to your project resources"
},
{
"name": "users",
"description": "The Users service allows you to manage your project users.",
"x-globalAttributes": []
"description": "The Users service allows you to manage your project users."
},
{
"name": "functions",
"description": "The Functions Service allows you view, create and manage your Cloud Functions.",
"x-globalAttributes": []
"description": "The Functions Service allows you view, create and manage your Cloud Functions."
},
{
"name": "proxy",
"description": "The Proxy Service allows you to configure actions for your domains beyond DNS configuration.",
"x-globalAttributes": []
"description": "The Proxy Service allows you to configure actions for your domains beyond DNS configuration."
},
{
"name": "graphql",
"description": "The GraphQL API allows you to query and mutate your Appwrite server using GraphQL.",
"x-globalAttributes": []
"description": "The GraphQL API allows you to query and mutate your Appwrite server using GraphQL."
},
{
"name": "console",
"description": "The Console service allows you to interact with console relevant informations.",
"x-globalAttributes": []
"description": "The Console service allows you to interact with console relevant informations."
},
{
"name": "migrations",
"description": "The Migrations service allows you to migrate third-party data to your Appwrite project.",
"x-globalAttributes": []
"description": "The Migrations service allows you to migrate third-party data to your Appwrite project."
},
{
"name": "messaging",
"description": "The Messaging service allows you to send messages to any provider type (SMTP, push notification, SMS, etc.).",
"x-globalAttributes": []
"description": "The Messaging service allows you to send messages to any provider type (SMTP, push notification, SMS, etc.)."
}
],
"components": {

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -2646,7 +2646,10 @@
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-email.md",
"rate-limit": 10,
"rate-time": 3600,
"rate-key": "url:{url},email:{param-email}",
"rate-key": [
"url:{url},email:{param-email}",
"url:{url},ip:{ip}"
],
"scope": "sessions.write",
"platforms": [
"server",
@ -4427,7 +4430,7 @@
"tags": [
"databases"
],
"description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.\n",
"description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.",
"responses": {
"201": {
"description": "Document",
@ -4459,6 +4462,51 @@
"server"
],
"packaging": false,
"methods": [
{
"name": "createDocument",
"parameters": [
"databaseId",
"collectionId",
"documentId",
"data",
"permissions"
],
"required": [
"databaseId",
"collectionId",
"documentId",
"data"
],
"responses": [
{
"code": 201,
"model": "#\/components\/schemas\/document"
}
],
"description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console."
},
{
"name": "createDocuments",
"parameters": [
"databaseId",
"collectionId",
"documents"
],
"required": [
"databaseId",
"collectionId",
"documents"
],
"responses": [
{
"code": 201,
"model": "#\/components\/schemas\/documentList"
}
],
"description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.\n"
}
],
"auth": {
"Project": []
}
@ -4515,12 +4563,16 @@
"items": {
"type": "string"
}
},
"documents": {
"type": "array",
"description": "Array of documents data as JSON objects.",
"x-example": null,
"items": {
"type": "object"
}
}
},
"required": [
"documentId",
"data"
]
}
}
}
}
@ -4744,7 +4796,7 @@
"x-appwrite": {
"method": "deleteDocument",
"group": "documents",
"weight": 113,
"weight": 115,
"cookies": false,
"type": "",
"deprecated": false,
@ -4828,7 +4880,7 @@
"x-appwrite": {
"method": "listExecutions",
"group": "executions",
"weight": 305,
"weight": 308,
"cookies": false,
"type": "",
"deprecated": false,
@ -4914,7 +4966,7 @@
"x-appwrite": {
"method": "createExecution",
"group": "executions",
"weight": 304,
"weight": 307,
"cookies": false,
"type": "",
"deprecated": false,
@ -5029,7 +5081,7 @@
"x-appwrite": {
"method": "getExecution",
"group": "executions",
"weight": 306,
"weight": 309,
"cookies": false,
"type": "",
"deprecated": false,
@ -5103,7 +5155,7 @@
"x-appwrite": {
"method": "query",
"group": "graphql",
"weight": 330,
"weight": 333,
"cookies": false,
"type": "graphql",
"deprecated": false,
@ -5155,7 +5207,7 @@
"x-appwrite": {
"method": "mutation",
"group": "graphql",
"weight": 329,
"weight": 332,
"cookies": false,
"type": "graphql",
"deprecated": false,
@ -5207,7 +5259,7 @@
"x-appwrite": {
"method": "get",
"group": null,
"weight": 117,
"weight": 120,
"cookies": false,
"type": "",
"deprecated": false,
@ -5259,7 +5311,7 @@
"x-appwrite": {
"method": "listCodes",
"group": null,
"weight": 118,
"weight": 121,
"cookies": false,
"type": "",
"deprecated": false,
@ -5311,7 +5363,7 @@
"x-appwrite": {
"method": "listContinents",
"group": null,
"weight": 122,
"weight": 125,
"cookies": false,
"type": "",
"deprecated": false,
@ -5363,7 +5415,7 @@
"x-appwrite": {
"method": "listCountries",
"group": null,
"weight": 119,
"weight": 122,
"cookies": false,
"type": "",
"deprecated": false,
@ -5415,7 +5467,7 @@
"x-appwrite": {
"method": "listCountriesEU",
"group": null,
"weight": 120,
"weight": 123,
"cookies": false,
"type": "",
"deprecated": false,
@ -5467,7 +5519,7 @@
"x-appwrite": {
"method": "listCountriesPhones",
"group": null,
"weight": 121,
"weight": 124,
"cookies": false,
"type": "",
"deprecated": false,
@ -5519,7 +5571,7 @@
"x-appwrite": {
"method": "listCurrencies",
"group": null,
"weight": 123,
"weight": 126,
"cookies": false,
"type": "",
"deprecated": false,
@ -5571,7 +5623,7 @@
"x-appwrite": {
"method": "listLanguages",
"group": null,
"weight": 124,
"weight": 127,
"cookies": false,
"type": "",
"deprecated": false,
@ -5623,7 +5675,7 @@
"x-appwrite": {
"method": "createSubscriber",
"group": "subscribers",
"weight": 375,
"weight": 378,
"cookies": false,
"type": "",
"deprecated": false,
@ -5706,7 +5758,7 @@
"x-appwrite": {
"method": "deleteSubscriber",
"group": "subscribers",
"weight": 379,
"weight": 382,
"cookies": false,
"type": "",
"deprecated": false,
@ -5781,7 +5833,7 @@
"x-appwrite": {
"method": "listFiles",
"group": "files",
"weight": 207,
"weight": 210,
"cookies": false,
"type": "",
"deprecated": false,
@ -5867,7 +5919,7 @@
"x-appwrite": {
"method": "createFile",
"group": "files",
"weight": 206,
"weight": 209,
"cookies": false,
"type": "upload",
"deprecated": false,
@ -5965,7 +6017,7 @@
"x-appwrite": {
"method": "getFile",
"group": "files",
"weight": 208,
"weight": 211,
"cookies": false,
"type": "",
"deprecated": false,
@ -6037,7 +6089,7 @@
"x-appwrite": {
"method": "updateFile",
"group": "files",
"weight": 213,
"weight": 216,
"cookies": false,
"type": "",
"deprecated": false,
@ -6126,7 +6178,7 @@
"x-appwrite": {
"method": "deleteFile",
"group": "files",
"weight": 214,
"weight": 217,
"cookies": false,
"type": "",
"deprecated": false,
@ -6193,7 +6245,7 @@
"x-appwrite": {
"method": "getFileDownload",
"group": "files",
"weight": 210,
"weight": 213,
"cookies": false,
"type": "location",
"deprecated": false,
@ -6260,7 +6312,7 @@
"x-appwrite": {
"method": "getFilePreview",
"group": "files",
"weight": 209,
"weight": 212,
"cookies": false,
"type": "location",
"deprecated": false,
@ -6477,7 +6529,7 @@
"x-appwrite": {
"method": "getFileView",
"group": "files",
"weight": 211,
"weight": 214,
"cookies": false,
"type": "location",
"deprecated": false,
@ -6551,7 +6603,7 @@
"x-appwrite": {
"method": "list",
"group": "teams",
"weight": 218,
"weight": 221,
"cookies": false,
"type": "",
"deprecated": false,
@ -6627,7 +6679,7 @@
"x-appwrite": {
"method": "create",
"group": "teams",
"weight": 217,
"weight": 220,
"cookies": false,
"type": "",
"deprecated": false,
@ -6712,7 +6764,7 @@
"x-appwrite": {
"method": "get",
"group": "teams",
"weight": 219,
"weight": 222,
"cookies": false,
"type": "",
"deprecated": false,
@ -6774,7 +6826,7 @@
"x-appwrite": {
"method": "updateName",
"group": "teams",
"weight": 221,
"weight": 224,
"cookies": false,
"type": "",
"deprecated": false,
@ -6848,7 +6900,7 @@
"x-appwrite": {
"method": "delete",
"group": "teams",
"weight": 223,
"weight": 226,
"cookies": false,
"type": "",
"deprecated": false,
@ -6912,7 +6964,7 @@
"x-appwrite": {
"method": "listMemberships",
"group": "memberships",
"weight": 225,
"weight": 228,
"cookies": false,
"type": "",
"deprecated": false,
@ -6998,7 +7050,7 @@
"x-appwrite": {
"method": "createMembership",
"group": "memberships",
"weight": 224,
"weight": 227,
"cookies": false,
"type": "",
"deprecated": false,
@ -7109,7 +7161,7 @@
"x-appwrite": {
"method": "getMembership",
"group": "memberships",
"weight": 226,
"weight": 229,
"cookies": false,
"type": "",
"deprecated": false,
@ -7181,7 +7233,7 @@
"x-appwrite": {
"method": "updateMembership",
"group": "memberships",
"weight": 227,
"weight": 230,
"cookies": false,
"type": "",
"deprecated": false,
@ -7268,7 +7320,7 @@
"x-appwrite": {
"method": "deleteMembership",
"group": "memberships",
"weight": 229,
"weight": 232,
"cookies": false,
"type": "",
"deprecated": false,
@ -7342,7 +7394,7 @@
"x-appwrite": {
"method": "updateMembershipStatus",
"group": "memberships",
"weight": 228,
"weight": 231,
"cookies": false,
"type": "",
"deprecated": false,
@ -7440,7 +7492,7 @@
"x-appwrite": {
"method": "getPrefs",
"group": "teams",
"weight": 220,
"weight": 223,
"cookies": false,
"type": "",
"deprecated": false,
@ -7501,7 +7553,7 @@
"x-appwrite": {
"method": "updatePrefs",
"group": "teams",
"weight": 222,
"weight": 225,
"cookies": false,
"type": "",
"deprecated": false,
@ -7564,85 +7616,67 @@
"tags": [
{
"name": "account",
"description": "The Account service allows you to authenticate and manage a user account.",
"x-globalAttributes": []
"description": "The Account service allows you to authenticate and manage a user account."
},
{
"name": "avatars",
"description": "The Avatars service aims to help you complete everyday tasks related to your app image, icons, and avatars.",
"x-globalAttributes": []
"description": "The Avatars service aims to help you complete everyday tasks related to your app image, icons, and avatars."
},
{
"name": "databases",
"description": "The Databases service allows you to create structured collections of documents, query and filter lists of documents",
"x-globalAttributes": [
"databaseId"
]
"description": "The Databases service allows you to create structured collections of documents, query and filter lists of documents"
},
{
"name": "locale",
"description": "The Locale service allows you to customize your app based on your users' location.",
"x-globalAttributes": []
"description": "The Locale service allows you to customize your app based on your users' location."
},
{
"name": "health",
"description": "The Health service allows you to both validate and monitor your Appwrite server's health.",
"x-globalAttributes": []
"description": "The Health service allows you to both validate and monitor your Appwrite server's health."
},
{
"name": "projects",
"description": "The Project service allows you to manage all the projects in your Appwrite server.",
"x-globalAttributes": []
"description": "The Project service allows you to manage all the projects in your Appwrite server."
},
{
"name": "project",
"description": "The Project service allows you to manage all the projects in your Appwrite server.",
"x-globalAttributes": []
"description": "The Project service allows you to manage all the projects in your Appwrite server."
},
{
"name": "storage",
"description": "The Storage service allows you to manage your project files.",
"x-globalAttributes": []
"description": "The Storage service allows you to manage your project files."
},
{
"name": "teams",
"description": "The Teams service allows you to group users of your project and to enable them to share read and write access to your project resources",
"x-globalAttributes": []
"description": "The Teams service allows you to group users of your project and to enable them to share read and write access to your project resources"
},
{
"name": "users",
"description": "The Users service allows you to manage your project users.",
"x-globalAttributes": []
"description": "The Users service allows you to manage your project users."
},
{
"name": "functions",
"description": "The Functions Service allows you view, create and manage your Cloud Functions.",
"x-globalAttributes": []
"description": "The Functions Service allows you view, create and manage your Cloud Functions."
},
{
"name": "proxy",
"description": "The Proxy Service allows you to configure actions for your domains beyond DNS configuration.",
"x-globalAttributes": []
"description": "The Proxy Service allows you to configure actions for your domains beyond DNS configuration."
},
{
"name": "graphql",
"description": "The GraphQL API allows you to query and mutate your Appwrite server using GraphQL.",
"x-globalAttributes": []
"description": "The GraphQL API allows you to query and mutate your Appwrite server using GraphQL."
},
{
"name": "console",
"description": "The Console service allows you to interact with console relevant informations.",
"x-globalAttributes": []
"description": "The Console service allows you to interact with console relevant informations."
},
{
"name": "migrations",
"description": "The Migrations service allows you to migrate third-party data to your Appwrite project.",
"x-globalAttributes": []
"description": "The Migrations service allows you to migrate third-party data to your Appwrite project."
},
{
"name": "messaging",
"description": "The Messaging service allows you to send messages to any provider type (SMTP, push notification, SMS, etc.).",
"x-globalAttributes": []
"description": "The Messaging service allows you to send messages to any provider type (SMTP, push notification, SMS, etc.)."
}
],
"components": {

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -2765,7 +2765,10 @@
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-email.md",
"rate-limit": 10,
"rate-time": 3600,
"rate-key": "url:{url},email:{param-email}",
"rate-key": [
"url:{url},email:{param-email}",
"url:{url},ip:{ip}"
],
"scope": "sessions.write",
"platforms": [
"server",
@ -4571,7 +4574,7 @@
"tags": [
"databases"
],
"description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.\n",
"description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.",
"responses": {
"201": {
"description": "Document",
@ -4599,6 +4602,51 @@
"server"
],
"packaging": false,
"methods": [
{
"name": "createDocument",
"parameters": [
"databaseId",
"collectionId",
"documentId",
"data",
"permissions"
],
"required": [
"databaseId",
"collectionId",
"documentId",
"data"
],
"responses": [
{
"code": 201,
"model": "#\/definitions\/document"
}
],
"description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console."
},
{
"name": "createDocuments",
"parameters": [
"databaseId",
"collectionId",
"documents"
],
"required": [
"databaseId",
"collectionId",
"documents"
],
"responses": [
{
"code": 201,
"model": "#\/definitions\/documentList"
}
],
"description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.\n"
}
],
"auth": {
"Project": []
}
@ -4636,13 +4684,13 @@
"documentId": {
"type": "string",
"description": "Document ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.",
"default": null,
"default": "",
"x-example": "<DOCUMENT_ID>"
},
"data": {
"type": "object",
"description": "Document data as JSON object.",
"default": {},
"default": [],
"x-example": "{}"
},
"permissions": {
@ -4653,12 +4701,17 @@
"items": {
"type": "string"
}
},
"documents": {
"type": "array",
"description": "Array of documents data as JSON objects.",
"default": [],
"x-example": null,
"items": {
"type": "object"
}
}
},
"required": [
"documentId",
"data"
]
}
}
}
]
@ -4874,7 +4927,7 @@
"x-appwrite": {
"method": "deleteDocument",
"group": "documents",
"weight": 113,
"weight": 115,
"cookies": false,
"type": "",
"deprecated": false,
@ -4952,7 +5005,7 @@
"x-appwrite": {
"method": "listExecutions",
"group": "executions",
"weight": 305,
"weight": 308,
"cookies": false,
"type": "",
"deprecated": false,
@ -5035,7 +5088,7 @@
"x-appwrite": {
"method": "createExecution",
"group": "executions",
"weight": 304,
"weight": 307,
"cookies": false,
"type": "",
"deprecated": false,
@ -5152,7 +5205,7 @@
"x-appwrite": {
"method": "getExecution",
"group": "executions",
"weight": 306,
"weight": 309,
"cookies": false,
"type": "",
"deprecated": false,
@ -5224,7 +5277,7 @@
"x-appwrite": {
"method": "query",
"group": "graphql",
"weight": 330,
"weight": 333,
"cookies": false,
"type": "graphql",
"deprecated": false,
@ -5298,7 +5351,7 @@
"x-appwrite": {
"method": "mutation",
"group": "graphql",
"weight": 329,
"weight": 332,
"cookies": false,
"type": "graphql",
"deprecated": false,
@ -5370,7 +5423,7 @@
"x-appwrite": {
"method": "get",
"group": null,
"weight": 117,
"weight": 120,
"cookies": false,
"type": "",
"deprecated": false,
@ -5422,7 +5475,7 @@
"x-appwrite": {
"method": "listCodes",
"group": null,
"weight": 118,
"weight": 121,
"cookies": false,
"type": "",
"deprecated": false,
@ -5474,7 +5527,7 @@
"x-appwrite": {
"method": "listContinents",
"group": null,
"weight": 122,
"weight": 125,
"cookies": false,
"type": "",
"deprecated": false,
@ -5526,7 +5579,7 @@
"x-appwrite": {
"method": "listCountries",
"group": null,
"weight": 119,
"weight": 122,
"cookies": false,
"type": "",
"deprecated": false,
@ -5578,7 +5631,7 @@
"x-appwrite": {
"method": "listCountriesEU",
"group": null,
"weight": 120,
"weight": 123,
"cookies": false,
"type": "",
"deprecated": false,
@ -5630,7 +5683,7 @@
"x-appwrite": {
"method": "listCountriesPhones",
"group": null,
"weight": 121,
"weight": 124,
"cookies": false,
"type": "",
"deprecated": false,
@ -5682,7 +5735,7 @@
"x-appwrite": {
"method": "listCurrencies",
"group": null,
"weight": 123,
"weight": 126,
"cookies": false,
"type": "",
"deprecated": false,
@ -5734,7 +5787,7 @@
"x-appwrite": {
"method": "listLanguages",
"group": null,
"weight": 124,
"weight": 127,
"cookies": false,
"type": "",
"deprecated": false,
@ -5788,7 +5841,7 @@
"x-appwrite": {
"method": "createSubscriber",
"group": "subscribers",
"weight": 375,
"weight": 378,
"cookies": false,
"type": "",
"deprecated": false,
@ -5873,7 +5926,7 @@
"x-appwrite": {
"method": "deleteSubscriber",
"group": "subscribers",
"weight": 379,
"weight": 382,
"cookies": false,
"type": "",
"deprecated": false,
@ -5944,7 +5997,7 @@
"x-appwrite": {
"method": "listFiles",
"group": "files",
"weight": 207,
"weight": 210,
"cookies": false,
"type": "",
"deprecated": false,
@ -6027,7 +6080,7 @@
"x-appwrite": {
"method": "createFile",
"group": "files",
"weight": 206,
"weight": 209,
"cookies": false,
"type": "upload",
"deprecated": false,
@ -6117,7 +6170,7 @@
"x-appwrite": {
"method": "getFile",
"group": "files",
"weight": 208,
"weight": 211,
"cookies": false,
"type": "",
"deprecated": false,
@ -6187,7 +6240,7 @@
"x-appwrite": {
"method": "updateFile",
"group": "files",
"weight": 213,
"weight": 216,
"cookies": false,
"type": "",
"deprecated": false,
@ -6276,7 +6329,7 @@
"x-appwrite": {
"method": "deleteFile",
"group": "files",
"weight": 214,
"weight": 217,
"cookies": false,
"type": "",
"deprecated": false,
@ -6346,7 +6399,7 @@
"x-appwrite": {
"method": "getFileDownload",
"group": "files",
"weight": 210,
"weight": 213,
"cookies": false,
"type": "location",
"deprecated": false,
@ -6416,7 +6469,7 @@
"x-appwrite": {
"method": "getFilePreview",
"group": "files",
"weight": 209,
"weight": 212,
"cookies": false,
"type": "location",
"deprecated": false,
@ -6614,7 +6667,7 @@
"x-appwrite": {
"method": "getFileView",
"group": "files",
"weight": 211,
"weight": 214,
"cookies": false,
"type": "location",
"deprecated": false,
@ -6684,7 +6737,7 @@
"x-appwrite": {
"method": "list",
"group": "teams",
"weight": 218,
"weight": 221,
"cookies": false,
"type": "",
"deprecated": false,
@ -6759,7 +6812,7 @@
"x-appwrite": {
"method": "create",
"group": "teams",
"weight": 217,
"weight": 220,
"cookies": false,
"type": "",
"deprecated": false,
@ -6849,7 +6902,7 @@
"x-appwrite": {
"method": "get",
"group": "teams",
"weight": 219,
"weight": 222,
"cookies": false,
"type": "",
"deprecated": false,
@ -6911,7 +6964,7 @@
"x-appwrite": {
"method": "updateName",
"group": "teams",
"weight": 221,
"weight": 224,
"cookies": false,
"type": "",
"deprecated": false,
@ -6986,7 +7039,7 @@
"x-appwrite": {
"method": "delete",
"group": "teams",
"weight": 223,
"weight": 226,
"cookies": false,
"type": "",
"deprecated": false,
@ -7048,7 +7101,7 @@
"x-appwrite": {
"method": "listMemberships",
"group": "memberships",
"weight": 225,
"weight": 228,
"cookies": false,
"type": "",
"deprecated": false,
@ -7131,7 +7184,7 @@
"x-appwrite": {
"method": "createMembership",
"group": "memberships",
"weight": 224,
"weight": 227,
"cookies": false,
"type": "",
"deprecated": false,
@ -7244,7 +7297,7 @@
"x-appwrite": {
"method": "getMembership",
"group": "memberships",
"weight": 226,
"weight": 229,
"cookies": false,
"type": "",
"deprecated": false,
@ -7314,7 +7367,7 @@
"x-appwrite": {
"method": "updateMembership",
"group": "memberships",
"weight": 227,
"weight": 230,
"cookies": false,
"type": "",
"deprecated": false,
@ -7400,7 +7453,7 @@
"x-appwrite": {
"method": "deleteMembership",
"group": "memberships",
"weight": 229,
"weight": 232,
"cookies": false,
"type": "",
"deprecated": false,
@ -7472,7 +7525,7 @@
"x-appwrite": {
"method": "updateMembershipStatus",
"group": "memberships",
"weight": 228,
"weight": 231,
"cookies": false,
"type": "",
"deprecated": false,
@ -7566,7 +7619,7 @@
"x-appwrite": {
"method": "getPrefs",
"group": "teams",
"weight": 220,
"weight": 223,
"cookies": false,
"type": "",
"deprecated": false,
@ -7627,7 +7680,7 @@
"x-appwrite": {
"method": "updatePrefs",
"group": "teams",
"weight": 222,
"weight": 225,
"cookies": false,
"type": "",
"deprecated": false,
@ -7687,85 +7740,67 @@
"tags": [
{
"name": "account",
"description": "The Account service allows you to authenticate and manage a user account.",
"x-globalAttributes": []
"description": "The Account service allows you to authenticate and manage a user account."
},
{
"name": "avatars",
"description": "The Avatars service aims to help you complete everyday tasks related to your app image, icons, and avatars.",
"x-globalAttributes": []
"description": "The Avatars service aims to help you complete everyday tasks related to your app image, icons, and avatars."
},
{
"name": "databases",
"description": "The Databases service allows you to create structured collections of documents, query and filter lists of documents",
"x-globalAttributes": [
"databaseId"
]
"description": "The Databases service allows you to create structured collections of documents, query and filter lists of documents"
},
{
"name": "locale",
"description": "The Locale service allows you to customize your app based on your users' location.",
"x-globalAttributes": []
"description": "The Locale service allows you to customize your app based on your users' location."
},
{
"name": "health",
"description": "The Health service allows you to both validate and monitor your Appwrite server's health.",
"x-globalAttributes": []
"description": "The Health service allows you to both validate and monitor your Appwrite server's health."
},
{
"name": "projects",
"description": "The Project service allows you to manage all the projects in your Appwrite server.",
"x-globalAttributes": []
"description": "The Project service allows you to manage all the projects in your Appwrite server."
},
{
"name": "project",
"description": "The Project service allows you to manage all the projects in your Appwrite server.",
"x-globalAttributes": []
"description": "The Project service allows you to manage all the projects in your Appwrite server."
},
{
"name": "storage",
"description": "The Storage service allows you to manage your project files.",
"x-globalAttributes": []
"description": "The Storage service allows you to manage your project files."
},
{
"name": "teams",
"description": "The Teams service allows you to group users of your project and to enable them to share read and write access to your project resources",
"x-globalAttributes": []
"description": "The Teams service allows you to group users of your project and to enable them to share read and write access to your project resources"
},
{
"name": "users",
"description": "The Users service allows you to manage your project users.",
"x-globalAttributes": []
"description": "The Users service allows you to manage your project users."
},
{
"name": "functions",
"description": "The Functions Service allows you view, create and manage your Cloud Functions.",
"x-globalAttributes": []
"description": "The Functions Service allows you view, create and manage your Cloud Functions."
},
{
"name": "proxy",
"description": "The Proxy Service allows you to configure actions for your domains beyond DNS configuration.",
"x-globalAttributes": []
"description": "The Proxy Service allows you to configure actions for your domains beyond DNS configuration."
},
{
"name": "graphql",
"description": "The GraphQL API allows you to query and mutate your Appwrite server using GraphQL.",
"x-globalAttributes": []
"description": "The GraphQL API allows you to query and mutate your Appwrite server using GraphQL."
},
{
"name": "console",
"description": "The Console service allows you to interact with console relevant informations.",
"x-globalAttributes": []
"description": "The Console service allows you to interact with console relevant informations."
},
{
"name": "migrations",
"description": "The Migrations service allows you to migrate third-party data to your Appwrite project.",
"x-globalAttributes": []
"description": "The Migrations service allows you to migrate third-party data to your Appwrite project."
},
{
"name": "messaging",
"description": "The Messaging service allows you to send messages to any provider type (SMTP, push notification, SMS, etc.).",
"x-globalAttributes": []
"description": "The Messaging service allows you to send messages to any provider type (SMTP, push notification, SMS, etc.)."
}
],
"definitions": {

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -2765,7 +2765,10 @@
"edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-email.md",
"rate-limit": 10,
"rate-time": 3600,
"rate-key": "url:{url},email:{param-email}",
"rate-key": [
"url:{url},email:{param-email}",
"url:{url},ip:{ip}"
],
"scope": "sessions.write",
"platforms": [
"server",
@ -4571,7 +4574,7 @@
"tags": [
"databases"
],
"description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.\n",
"description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.",
"responses": {
"201": {
"description": "Document",
@ -4599,6 +4602,51 @@
"server"
],
"packaging": false,
"methods": [
{
"name": "createDocument",
"parameters": [
"databaseId",
"collectionId",
"documentId",
"data",
"permissions"
],
"required": [
"databaseId",
"collectionId",
"documentId",
"data"
],
"responses": [
{
"code": 201,
"model": "#\/definitions\/document"
}
],
"description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console."
},
{
"name": "createDocuments",
"parameters": [
"databaseId",
"collectionId",
"documents"
],
"required": [
"databaseId",
"collectionId",
"documents"
],
"responses": [
{
"code": 201,
"model": "#\/definitions\/documentList"
}
],
"description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.\n"
}
],
"auth": {
"Project": []
}
@ -4636,13 +4684,13 @@
"documentId": {
"type": "string",
"description": "Document ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.",
"default": null,
"default": "",
"x-example": "<DOCUMENT_ID>"
},
"data": {
"type": "object",
"description": "Document data as JSON object.",
"default": {},
"default": [],
"x-example": "{}"
},
"permissions": {
@ -4653,12 +4701,17 @@
"items": {
"type": "string"
}
},
"documents": {
"type": "array",
"description": "Array of documents data as JSON objects.",
"default": [],
"x-example": null,
"items": {
"type": "object"
}
}
},
"required": [
"documentId",
"data"
]
}
}
}
]
@ -4874,7 +4927,7 @@
"x-appwrite": {
"method": "deleteDocument",
"group": "documents",
"weight": 113,
"weight": 115,
"cookies": false,
"type": "",
"deprecated": false,
@ -4952,7 +5005,7 @@
"x-appwrite": {
"method": "listExecutions",
"group": "executions",
"weight": 305,
"weight": 308,
"cookies": false,
"type": "",
"deprecated": false,
@ -5035,7 +5088,7 @@
"x-appwrite": {
"method": "createExecution",
"group": "executions",
"weight": 304,
"weight": 307,
"cookies": false,
"type": "",
"deprecated": false,
@ -5152,7 +5205,7 @@
"x-appwrite": {
"method": "getExecution",
"group": "executions",
"weight": 306,
"weight": 309,
"cookies": false,
"type": "",
"deprecated": false,
@ -5224,7 +5277,7 @@
"x-appwrite": {
"method": "query",
"group": "graphql",
"weight": 330,
"weight": 333,
"cookies": false,
"type": "graphql",
"deprecated": false,
@ -5298,7 +5351,7 @@
"x-appwrite": {
"method": "mutation",
"group": "graphql",
"weight": 329,
"weight": 332,
"cookies": false,
"type": "graphql",
"deprecated": false,
@ -5370,7 +5423,7 @@
"x-appwrite": {
"method": "get",
"group": null,
"weight": 117,
"weight": 120,
"cookies": false,
"type": "",
"deprecated": false,
@ -5422,7 +5475,7 @@
"x-appwrite": {
"method": "listCodes",
"group": null,
"weight": 118,
"weight": 121,
"cookies": false,
"type": "",
"deprecated": false,
@ -5474,7 +5527,7 @@
"x-appwrite": {
"method": "listContinents",
"group": null,
"weight": 122,
"weight": 125,
"cookies": false,
"type": "",
"deprecated": false,
@ -5526,7 +5579,7 @@
"x-appwrite": {
"method": "listCountries",
"group": null,
"weight": 119,
"weight": 122,
"cookies": false,
"type": "",
"deprecated": false,
@ -5578,7 +5631,7 @@
"x-appwrite": {
"method": "listCountriesEU",
"group": null,
"weight": 120,
"weight": 123,
"cookies": false,
"type": "",
"deprecated": false,
@ -5630,7 +5683,7 @@
"x-appwrite": {
"method": "listCountriesPhones",
"group": null,
"weight": 121,
"weight": 124,
"cookies": false,
"type": "",
"deprecated": false,
@ -5682,7 +5735,7 @@
"x-appwrite": {
"method": "listCurrencies",
"group": null,
"weight": 123,
"weight": 126,
"cookies": false,
"type": "",
"deprecated": false,
@ -5734,7 +5787,7 @@
"x-appwrite": {
"method": "listLanguages",
"group": null,
"weight": 124,
"weight": 127,
"cookies": false,
"type": "",
"deprecated": false,
@ -5788,7 +5841,7 @@
"x-appwrite": {
"method": "createSubscriber",
"group": "subscribers",
"weight": 375,
"weight": 378,
"cookies": false,
"type": "",
"deprecated": false,
@ -5873,7 +5926,7 @@
"x-appwrite": {
"method": "deleteSubscriber",
"group": "subscribers",
"weight": 379,
"weight": 382,
"cookies": false,
"type": "",
"deprecated": false,
@ -5944,7 +5997,7 @@
"x-appwrite": {
"method": "listFiles",
"group": "files",
"weight": 207,
"weight": 210,
"cookies": false,
"type": "",
"deprecated": false,
@ -6027,7 +6080,7 @@
"x-appwrite": {
"method": "createFile",
"group": "files",
"weight": 206,
"weight": 209,
"cookies": false,
"type": "upload",
"deprecated": false,
@ -6117,7 +6170,7 @@
"x-appwrite": {
"method": "getFile",
"group": "files",
"weight": 208,
"weight": 211,
"cookies": false,
"type": "",
"deprecated": false,
@ -6187,7 +6240,7 @@
"x-appwrite": {
"method": "updateFile",
"group": "files",
"weight": 213,
"weight": 216,
"cookies": false,
"type": "",
"deprecated": false,
@ -6276,7 +6329,7 @@
"x-appwrite": {
"method": "deleteFile",
"group": "files",
"weight": 214,
"weight": 217,
"cookies": false,
"type": "",
"deprecated": false,
@ -6346,7 +6399,7 @@
"x-appwrite": {
"method": "getFileDownload",
"group": "files",
"weight": 210,
"weight": 213,
"cookies": false,
"type": "location",
"deprecated": false,
@ -6416,7 +6469,7 @@
"x-appwrite": {
"method": "getFilePreview",
"group": "files",
"weight": 209,
"weight": 212,
"cookies": false,
"type": "location",
"deprecated": false,
@ -6614,7 +6667,7 @@
"x-appwrite": {
"method": "getFileView",
"group": "files",
"weight": 211,
"weight": 214,
"cookies": false,
"type": "location",
"deprecated": false,
@ -6684,7 +6737,7 @@
"x-appwrite": {
"method": "list",
"group": "teams",
"weight": 218,
"weight": 221,
"cookies": false,
"type": "",
"deprecated": false,
@ -6759,7 +6812,7 @@
"x-appwrite": {
"method": "create",
"group": "teams",
"weight": 217,
"weight": 220,
"cookies": false,
"type": "",
"deprecated": false,
@ -6849,7 +6902,7 @@
"x-appwrite": {
"method": "get",
"group": "teams",
"weight": 219,
"weight": 222,
"cookies": false,
"type": "",
"deprecated": false,
@ -6911,7 +6964,7 @@
"x-appwrite": {
"method": "updateName",
"group": "teams",
"weight": 221,
"weight": 224,
"cookies": false,
"type": "",
"deprecated": false,
@ -6986,7 +7039,7 @@
"x-appwrite": {
"method": "delete",
"group": "teams",
"weight": 223,
"weight": 226,
"cookies": false,
"type": "",
"deprecated": false,
@ -7048,7 +7101,7 @@
"x-appwrite": {
"method": "listMemberships",
"group": "memberships",
"weight": 225,
"weight": 228,
"cookies": false,
"type": "",
"deprecated": false,
@ -7131,7 +7184,7 @@
"x-appwrite": {
"method": "createMembership",
"group": "memberships",
"weight": 224,
"weight": 227,
"cookies": false,
"type": "",
"deprecated": false,
@ -7244,7 +7297,7 @@
"x-appwrite": {
"method": "getMembership",
"group": "memberships",
"weight": 226,
"weight": 229,
"cookies": false,
"type": "",
"deprecated": false,
@ -7314,7 +7367,7 @@
"x-appwrite": {
"method": "updateMembership",
"group": "memberships",
"weight": 227,
"weight": 230,
"cookies": false,
"type": "",
"deprecated": false,
@ -7400,7 +7453,7 @@
"x-appwrite": {
"method": "deleteMembership",
"group": "memberships",
"weight": 229,
"weight": 232,
"cookies": false,
"type": "",
"deprecated": false,
@ -7472,7 +7525,7 @@
"x-appwrite": {
"method": "updateMembershipStatus",
"group": "memberships",
"weight": 228,
"weight": 231,
"cookies": false,
"type": "",
"deprecated": false,
@ -7566,7 +7619,7 @@
"x-appwrite": {
"method": "getPrefs",
"group": "teams",
"weight": 220,
"weight": 223,
"cookies": false,
"type": "",
"deprecated": false,
@ -7627,7 +7680,7 @@
"x-appwrite": {
"method": "updatePrefs",
"group": "teams",
"weight": 222,
"weight": 225,
"cookies": false,
"type": "",
"deprecated": false,
@ -7687,85 +7740,67 @@
"tags": [
{
"name": "account",
"description": "The Account service allows you to authenticate and manage a user account.",
"x-globalAttributes": []
"description": "The Account service allows you to authenticate and manage a user account."
},
{
"name": "avatars",
"description": "The Avatars service aims to help you complete everyday tasks related to your app image, icons, and avatars.",
"x-globalAttributes": []
"description": "The Avatars service aims to help you complete everyday tasks related to your app image, icons, and avatars."
},
{
"name": "databases",
"description": "The Databases service allows you to create structured collections of documents, query and filter lists of documents",
"x-globalAttributes": [
"databaseId"
]
"description": "The Databases service allows you to create structured collections of documents, query and filter lists of documents"
},
{
"name": "locale",
"description": "The Locale service allows you to customize your app based on your users' location.",
"x-globalAttributes": []
"description": "The Locale service allows you to customize your app based on your users' location."
},
{
"name": "health",
"description": "The Health service allows you to both validate and monitor your Appwrite server's health.",
"x-globalAttributes": []
"description": "The Health service allows you to both validate and monitor your Appwrite server's health."
},
{
"name": "projects",
"description": "The Project service allows you to manage all the projects in your Appwrite server.",
"x-globalAttributes": []
"description": "The Project service allows you to manage all the projects in your Appwrite server."
},
{
"name": "project",
"description": "The Project service allows you to manage all the projects in your Appwrite server.",
"x-globalAttributes": []
"description": "The Project service allows you to manage all the projects in your Appwrite server."
},
{
"name": "storage",
"description": "The Storage service allows you to manage your project files.",
"x-globalAttributes": []
"description": "The Storage service allows you to manage your project files."
},
{
"name": "teams",
"description": "The Teams service allows you to group users of your project and to enable them to share read and write access to your project resources",
"x-globalAttributes": []
"description": "The Teams service allows you to group users of your project and to enable them to share read and write access to your project resources"
},
{
"name": "users",
"description": "The Users service allows you to manage your project users.",
"x-globalAttributes": []
"description": "The Users service allows you to manage your project users."
},
{
"name": "functions",
"description": "The Functions Service allows you view, create and manage your Cloud Functions.",
"x-globalAttributes": []
"description": "The Functions Service allows you view, create and manage your Cloud Functions."
},
{
"name": "proxy",
"description": "The Proxy Service allows you to configure actions for your domains beyond DNS configuration.",
"x-globalAttributes": []
"description": "The Proxy Service allows you to configure actions for your domains beyond DNS configuration."
},
{
"name": "graphql",
"description": "The GraphQL API allows you to query and mutate your Appwrite server using GraphQL.",
"x-globalAttributes": []
"description": "The GraphQL API allows you to query and mutate your Appwrite server using GraphQL."
},
{
"name": "console",
"description": "The Console service allows you to interact with console relevant informations.",
"x-globalAttributes": []
"description": "The Console service allows you to interact with console relevant informations."
},
{
"name": "migrations",
"description": "The Migrations service allows you to migrate third-party data to your Appwrite project.",
"x-globalAttributes": []
"description": "The Migrations service allows you to migrate third-party data to your Appwrite project."
},
{
"name": "messaging",
"description": "The Messaging service allows you to send messages to any provider type (SMTP, push notification, SMS, etc.).",
"x-globalAttributes": []
"description": "The Messaging service allows you to send messages to any provider type (SMTP, push notification, SMS, etc.)."
}
],
"definitions": {

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1030,13 +1030,22 @@ return [
],
[
'name' => '_APP_MAINTENANCE_DELAY',
'description' => 'Delay value containing the number of seconds that the Appwrite maintenance process should wait before executing system cleanups and optimizations. The default value is 0 seconds.',
'description' => 'Deprecated with 1.6.2 use _APP_MAINTENANCE_START_TIME instead to run the maintenance at a specific time per day.',
'introduction' => '1.5.0',
'default' => '0',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_MAINTENANCE_START_TIME',
'description' => 'The time of day (in 24-hour format) when the maintenance process should start. The default value is 00:00.',
'introduction' => '1.6.2',
'default' => '00:00',
'required' => false,
'question' => '',
'filter' => ''
],
[
'name' => '_APP_MAINTENANCE_RETENTION_CACHE',
'description' => 'The maximum duration (in seconds) upto which to retain cached files. The default value is 2592000 seconds (30 days).',

View file

@ -719,9 +719,7 @@ App::delete('/v1/account/sessions/:sessionId')
continue;
}
$dbForProject->withRequestTimestamp($requestTimestamp, function () use ($dbForProject, $session) {
return $dbForProject->deleteDocument('sessions', $session->getId());
});
$dbForProject->deleteDocument('sessions', $session->getId());
unset($sessions[$key]);
@ -2001,6 +1999,7 @@ App::post('/v1/account/tokens/magic-url')
$senderEmail = System::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM);
$senderName = System::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server');
$replyTo = "";
if ($smtpEnabled) {
@ -2769,7 +2768,7 @@ App::patch('/v1/account/name')
$user->setAttribute('name', $name);
$user = $dbForProject->withRequestTimestamp($requestTimestamp, fn () => $dbForProject->updateDocument('users', $user->getId(), $user));
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
$queueForEvents->setParam('userId', $user->getId());
@ -2844,7 +2843,7 @@ App::patch('/v1/account/password')
->setAttribute('hash', Auth::DEFAULT_ALGO)
->setAttribute('hashOptions', Auth::DEFAULT_ALGO_OPTIONS);
$user = $dbForProject->withRequestTimestamp($requestTimestamp, fn () => $dbForProject->updateDocument('users', $user->getId(), $user));
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
$queueForEvents->setParam('userId', $user->getId());
@ -2929,7 +2928,7 @@ App::patch('/v1/account/email')
}
try {
$user = $dbForProject->withRequestTimestamp($requestTimestamp, fn () => $dbForProject->updateDocument('users', $user->getId(), $user));
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
/**
* @var Document $oldTarget
*/
@ -3015,7 +3014,7 @@ App::patch('/v1/account/phone')
}
try {
$user = $dbForProject->withRequestTimestamp($requestTimestamp, fn () => $dbForProject->updateDocument('users', $user->getId(), $user));
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
/**
* @var Document $oldTarget
*/
@ -3065,7 +3064,7 @@ App::patch('/v1/account/prefs')
$user->setAttribute('prefs', $prefs);
$user = $dbForProject->withRequestTimestamp($requestTimestamp, fn () => $dbForProject->updateDocument('users', $user->getId(), $user));
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
$queueForEvents->setParam('userId', $user->getId());
@ -3103,7 +3102,7 @@ App::patch('/v1/account/status')
$user->setAttribute('status', false);
$user = $dbForProject->withRequestTimestamp($requestTimestamp, fn () => $dbForProject->updateDocument('users', $user->getId(), $user));
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
$queueForEvents
->setParam('userId', $user->getId())
@ -3867,7 +3866,7 @@ App::patch('/v1/account/mfa')
$user->setAttribute('mfa', $mfa);
$user = $dbForProject->withRequestTimestamp($requestTimestamp, fn () => $dbForProject->updateDocument('users', $user->getId(), $user));
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
if ($mfa) {
$factors = $session->getAttribute('factors', []);

View file

@ -10,6 +10,7 @@ use Appwrite\Network\Validator\Email;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Parameter;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Database\Validator\CustomId;
use Appwrite\Utopia\Database\Validator\Queries\Attributes;
@ -35,6 +36,7 @@ use Utopia\Database\Exception\Order as OrderException;
use Utopia\Database\Exception\Query as QueryException;
use Utopia\Database\Exception\Restricted as RestrictedException;
use Utopia\Database\Exception\Structure as StructureException;
use Utopia\Database\Exception\Timeout as TimeoutException;
use Utopia\Database\Exception\Truncate as TruncateException;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
@ -3170,7 +3172,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
->alias('/v1/database/collections/:collectionId/documents', ['databaseId' => 'default'])
->desc('Create document')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].create')
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'document.create')
@ -3180,6 +3181,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label(
'sdk',
// Using multiple methods to abstract the complexity for SDK users
[
new Method(
namespace: 'databases',
@ -3193,90 +3195,158 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
model: Response::MODEL_DOCUMENT,
)
],
contentType: ContentType::JSON
contentType: ContentType::JSON,
parameters: [
new Parameter('databaseId', optional: false),
new Parameter('collectionId', optional: false),
new Parameter('documentId', optional: false),
new Parameter('data', optional: false),
new Parameter('permissions', optional: true),
]
),
new Method(
namespace: 'databases',
group: 'documents',
name: 'createDocuments',
description: '/docs/references/databases/create-documents.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_CREATED,
model: Response::MODEL_DOCUMENT_LIST,
)
],
contentType: ContentType::JSON,
parameters: [
new Parameter('databaseId', optional: false),
new Parameter('collectionId', optional: false),
new Parameter('documents', optional: false),
]
)
]
)
->param('databaseId', '', new UID(), 'Database ID.')
->param('documentId', '', new CustomId(), 'Document ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->param('documentId', '', new CustomId(), 'Document ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.', true)
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection). Make sure to define attributes before creating documents.')
->param('data', [], new JSON(), 'Document data as JSON object.')
->param('data', [], new JSON(), 'Document data as JSON object.', 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, 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'])
->inject('response')
->inject('dbForProject')
->inject('user')
->inject('queueForEvents')
->inject('queueForStatsUsage')
->action(function (string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, Response $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage) {
->action(function (string $databaseId, ?string $documentId, string $collectionId, string|array|null $data, ?array $permissions, ?array $documents, Response $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage) {
$data = \is_string($data)
? \json_decode($data, true)
: $data;
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
if (empty($data)) {
/**
* Determine which internal path to call, single or bulk
*/
if (empty($data) && empty($documents)) {
// No single or bulk documents provided
throw new Exception(Exception::DOCUMENT_MISSING_DATA);
}
if (isset($data['$id'])) {
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, '$id is not allowed for creating new documents, try update instead');
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, documents');
}
if (!empty($data) && empty($documentId)) {
// Single document provided without document ID
throw new Exception(Exception::DOCUMENT_MISSING_DATA, 'Document ID is required when creating a single document');
}
if (!empty($documents) && !empty($documentId)) {
// Bulk documents provided with document ID
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Param "documentId" is disallowed when creating multiple documents, set "$id" in each document 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 documents, set "$permissions" in each document instead');
}
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
$isBulk = true;
if (!empty($data)) {
// Single document provided, convert to single item array
// But remember that it was single to respond with a single document
$isBulk = false;
$documents = [$data];
}
$isAPIKey = Auth::isAppUser(Authorization::getRoles());
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
throw new Exception(Exception::DATABASE_NOT_FOUND);
}
$collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId));
if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
throw new Exception(Exception::COLLECTION_NOT_FOUND);
}
$allowedPermissions = [
Database::PERMISSION_READ,
Database::PERMISSION_UPDATE,
Database::PERMISSION_DELETE,
];
$hasRelationships = \array_filter(
$collection->getAttribute('attributes', []),
fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP
);
// Map aggregate permissions to into the set of individual permissions they represent.
$permissions = Permission::aggregate($permissions, $allowedPermissions);
// Add permissions for current the user if none were provided.
if (\is_null($permissions)) {
$permissions = [];
if (!empty($user->getId())) {
foreach ($allowedPermissions as $permission) {
$permissions[] = (new Permission($permission, 'user', $user->getId()))->toString();
}
}
if ($isBulk && $hasRelationships) {
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Bulk create is not supported for collections with relationship attributes');
}
// Users can only manage their own roles, API keys and Admin users can manage any
if (!$isAPIKey && !$isPrivilegedUser) {
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(', ', Authorization::getRoles()) . ')');
$setPermissions = function (Document $document, ?array $permissions) use ($user, $isAPIKey, $isPrivilegedUser, $isBulk) {
$allowedPermissions = [
Database::PERMISSION_READ,
Database::PERMISSION_UPDATE,
Database::PERMISSION_DELETE,
];
// If bulk, we need to validate permissions explicitly per document
if ($isBulk) {
$permissions = $document['$permissions'] ?? null;
if (!empty($permissions)) {
$validator = new Permissions();
if (!$validator->isValid($permissions)) {
throw new Exception(Exception::GENERAL_BAD_REQUEST, $validator->getDescription());
}
}
}
}
$data['$collection'] = $collection->getId(); // Adding this param to make API easier for developers
$data['$id'] = $documentId == 'unique()' ? ID::unique() : $documentId;
$data['$permissions'] = $permissions;
$document = new Document($data);
$permissions = Permission::aggregate($permissions, $allowedPermissions);
// Add permissions for current the user if none were provided.
if (\is_null($permissions)) {
$permissions = [];
if (!empty($user->getId())) {
foreach ($allowedPermissions as $permission) {
$permissions[] = (new Permission($permission, 'user', $user->getId()))->toString();
}
}
}
// Users can only manage their own roles, API keys and Admin users can manage any
if (!$isAPIKey && !$isPrivilegedUser) {
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(', ', Authorization::getRoles()) . ')');
}
}
}
}
$document->setAttribute('$permissions', $permissions);
};
$operations = 0;
@ -3362,21 +3432,57 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
}
};
$checkPermissions($collection, $document, Database::PERMISSION_CREATE);
$documents = \array_map(function ($document) use ($collection, $permissions, $checkPermissions, $isBulk, $documentId, $setPermissions) {
$document['$collection'] = $collection->getId();
// Determine the source ID depending on whether it's a bulk operation.
$sourceId = $isBulk
? ($document['$id'] ?? ID::unique())
: $documentId;
// If bulk, we need to validate ID explicitly
if ($isBulk) {
$validator = new CustomId();
if (!$validator->isValid($sourceId)) {
throw new Exception(Exception::GENERAL_BAD_REQUEST, $validator->getDescription());
}
}
// Assign a unique ID if needed, otherwise use the provided ID.
$document['$id'] = $sourceId === 'unique()' ? ID::unique() : $sourceId;
$document = new Document($document);
$setPermissions($document, $permissions);
$checkPermissions($collection, $document, Database::PERMISSION_CREATE);
return $document;
}, $documents);
try {
$document = $dbForProject->createDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $document);
$dbForProject->createDocuments(
'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(),
$documents
);
} catch (StructureException $e) {
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage());
} catch (DuplicateException $e) {
} catch (DuplicateException) {
throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS);
} catch (NotFoundException $e) {
} catch (NotFoundException) {
throw new Exception(Exception::COLLECTION_NOT_FOUND);
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
} catch (TimeoutException) {
throw new Exception(Exception::DATABASE_TIMEOUT);
}
$queueForEvents
->setParam('databaseId', $databaseId)
->setParam('collectionId', $collection->getId())
->setContext('collection', $collection)
->setContext('database', $database);
// Add $collectionId and $databaseId for all documents
$processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) {
$document->removeAttribute('$collection');
$document->setAttribute('$databaseId', $database->getId());
$document->setAttribute('$collectionId', $collection->getId());
@ -3408,33 +3514,33 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
}
};
$processDocument($collection, $document);
foreach ($documents as $document) {
$processDocument($collection, $document);
}
$queueForStatsUsage
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1))
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations); // per collection
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $operations))
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); // per collection
$response->addHeader('X-Debug-Operations', $operations);
$response->setStatusCode(Response::STATUS_CODE_CREATED);
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
->dynamic($document, Response::MODEL_DOCUMENT);
if ($isBulk) {
$response->dynamic(new Document([
'total' => count($documents),
'documents' => $documents
]), Response::MODEL_DOCUMENT_LIST);
$relationships = \array_map(
fn ($document) => $document->getAttribute('key'),
\array_filter(
$collection->getAttribute('attributes', []),
fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP
)
);
return;
}
$queueForEvents
->setParam('databaseId', $databaseId)
->setParam('collectionId', $collection->getId())
->setParam('documentId', $document->getId())
->setContext('collection', $collection)
->setContext('database', $database)
->setPayload($response->getPayload(), sensitive: $relationships);
->setParam('documentId', $documents[0]->getId())
->setEvent('databases.[databaseId].collections.[collectionId].documents.[documentId].create');
$response->dynamic(
$documents[0],
Response::MODEL_DOCUMENT
);
});
App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
@ -3526,7 +3632,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
$operations++;
$document->removeAttribute('$collection');
$document->setAttribute('$databaseId', $database->getId());
$document->setAttribute('$collectionId', $collection->getId());
@ -3579,10 +3684,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
}
$queueForStatsUsage
->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1))
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations);
$response->addHeader('X-Debug-Operations', $operations);
->addMetric(METRIC_DATABASES_OPERATIONS_READS, \max(1, $operations))
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), \max(1, $operations));
$select = \array_reduce($queries, function ($result, $query) {
return $result || ($query->getMethod() === Query::TYPE_SELECT);
@ -3721,10 +3824,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
$processDocument($collection, $document);
$queueForStatsUsage
->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1))
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations);
$response->addHeader('X-Debug-Operations', $operations);
->addMetric(METRIC_DATABASES_OPERATIONS_READS, \max(1, $operations))
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), \max(1, $operations));
$response->dynamic($document, Response::MODEL_DOCUMENT);
});
@ -3881,7 +3982,6 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
->inject('queueForEvents')
->inject('queueForStatsUsage')
->action(function (string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage) {
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
if (empty($data) && \is_null($permissions)) {
@ -3898,7 +3998,6 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
}
$collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId));
if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) {
throw new Exception(Exception::COLLECTION_NOT_FOUND);
}
@ -4021,19 +4120,14 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
$setCollection($collection, $newDocument);
$queueForStatsUsage
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1))
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations);
$response->addHeader('X-Debug-Operations', $operations);
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $operations))
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations));
try {
$document = $dbForProject->withRequestTimestamp(
$requestTimestamp,
fn () => $dbForProject->updateDocument(
'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(),
$document->getId(),
$newDocument
)
$document = $dbForProject->updateDocument(
'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(),
$document->getId(),
$newDocument
);
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
@ -4080,8 +4174,6 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
$processDocument($collection, $document);
$response->dynamic($document, Response::MODEL_DOCUMENT);
$relationships = \array_map(
fn ($document) => $document->getAttribute('key'),
\array_filter(
@ -4097,6 +4189,202 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
->setContext('collection', $collection)
->setContext('database', $database)
->setPayload($response->getPayload(), sensitive: $relationships);
$response->dynamic($document, Response::MODEL_DOCUMENT);
});
App::patch('/v1/databases/:databaseId/collections/:collectionId/documents')
->desc('Update documents')
->groups(['api', 'database'])
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'documents.update')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}')
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: 'databases',
group: 'documents',
name: 'updateDocuments',
description: '/docs/references/databases/update-documents.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
model: Response::MODEL_DOCUMENT_LIST,
)
],
contentType: ContentType::JSON
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('data', [], new JSON(), 'Document data as JSON object. Include only attribute and value pairs to be updated.', true)
->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true)
->inject('requestTimestamp')
->inject('response')
->inject('dbForProject')
->inject('queueForStatsUsage')
->inject('plan')
->action(function (string $databaseId, string $collectionId, string|array $data, array $queries, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, StatsUsage $queueForStatsUsage, array $plan) {
$data = \is_string($data)
? \json_decode($data, true)
: $data;
if (empty($data)) {
throw new Exception(Exception::DOCUMENT_MISSING_PAYLOAD);
}
$database = $dbForProject->getDocument('databases', $databaseId);
if ($database->isEmpty()) {
throw new Exception(Exception::DATABASE_NOT_FOUND);
}
$collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId);
if ($collection->isEmpty()) {
throw new Exception(Exception::COLLECTION_NOT_FOUND);
}
$hasRelationships = \array_filter(
$collection->getAttribute('attributes', []),
fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP
);
if ($hasRelationships) {
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Bulk update is not supported for collections with relationship attributes');
}
try {
$queries = Query::parseQueries($queries);
} catch (QueryException $e) {
throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage());
}
if ($data['$permissions']) {
$validator = new Permissions();
if (!$validator->isValid($data['$permissions'])) {
throw new Exception(Exception::GENERAL_BAD_REQUEST, $validator->getDescription());
}
}
$documents = [];
try {
$modified = $dbForProject->updateDocuments(
'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(),
new Document($data),
$queries,
onNext: function (Document $document) use ($plan, &$documents) {
if (\count($documents) < ($plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH)) {
$documents[] = $document;
}
},
);
} catch (StructureException $e) {
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage());
} catch (NotFoundException) {
throw new Exception(Exception::COLLECTION_NOT_FOUND);
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
} catch (TimeoutException) {
throw new Exception(Exception::DATABASE_TIMEOUT);
}
foreach ($documents as $document) {
$document->setAttribute('$databaseId', $database->getId());
$document->setAttribute('$collectionId', $collection->getId());
}
$queueForStatsUsage
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $modified))
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified));
$response->dynamic(new Document([
'total' => $modified,
'documents' => $documents
]), Response::MODEL_DOCUMENT_LIST);
});
App::put('/v1/databases/:databaseId/collections/:collectionId/documents')
->desc('Create or update documents')
->groups(['api', 'database'])
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'documents.upsert')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}')
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: 'databases',
group: 'documents',
name: 'upsertDocuments',
description: '/docs/references/databases/upsert-documents.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
model: Response::MODEL_DOCUMENT_LIST,
)
],
contentType: ContentType::JSON
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID.')
->param('documents', [], fn (array $plan) => new ArrayList(new JSON(), $plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH), 'Array of document data as JSON objects. May contain partial documents.', true, ['plan'])
->inject('response')
->inject('dbForProject')
->inject('queueForStatsUsage')
->inject('plan')
->action(function (string $databaseId, string $collectionId, array $documents, Response $response, Database $dbForProject, StatsUsage $queueForStatsUsage, array $plan) {
$database = $dbForProject->getDocument('databases', $databaseId);
if ($database->isEmpty()) {
throw new Exception(Exception::DATABASE_NOT_FOUND);
}
$collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId);
if ($collection->isEmpty()) {
throw new Exception(Exception::COLLECTION_NOT_FOUND);
}
$hasRelationships = \array_filter(
$collection->getAttribute('attributes', []),
fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP
);
if ($hasRelationships) {
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Bulk upsert is not supported for collections with relationship attributes');
}
foreach ($documents as $key => $document) {
$documents[$key] = new Document($document);
}
$upserted = [];
$modified = $dbForProject->createOrUpdateDocuments(
'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(),
$documents,
onNext: function (Document $document) use ($plan, &$upserted) {
if (\count($upserted) < ($plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH)) {
$upserted[] = $document;
}
},
);
foreach ($upserted as $document) {
$document->setAttribute('$databaseId', $database->getId());
$document->setAttribute('$collectionId', $collection->getId());
}
$queueForStatsUsage
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $modified))
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified));
$response->dynamic(new Document([
'total' => $modified,
'documents' => $upserted
]), Response::MODEL_DOCUMENT_LIST);
});
App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId')
@ -4157,18 +4445,20 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu
}
try {
$dbForProject->withRequestTimestamp($requestTimestamp, function () use ($dbForProject, $database, $collection, $documentId) {
$dbForProject->deleteDocument(
'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(),
$documentId
);
});
$dbForProject->deleteDocument(
'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(),
$documentId
);
} catch (NotFoundException $e) {
throw new Exception(Exception::COLLECTION_NOT_FOUND);
}
$operations = 0;
// Add $collectionId and $databaseId for all documents
$processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) {
$processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations) {
$operations++;
$document->setAttribute('$databaseId', $database->getId());
$document->setAttribute('$collectionId', $collection->getId());
@ -4203,10 +4493,8 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu
$processDocument($collection, $document);
$queueForStatsUsage
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1)
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1); // per collection
$response->addHeader('X-Debug-Operations', 1);
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $operations))
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations));
$relationships = \array_map(
fn ($document) => $document->getAttribute('key'),
@ -4227,6 +4515,99 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu
$response->noContent();
});
App::delete('/v1/databases/:databaseId/collections/:collectionId/documents')
->desc('Delete documents')
->groups(['api', 'database'])
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('audits.event', 'documents.delete')
->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}')
->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}')
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT)
->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT)
->label('sdk', new Method(
namespace: 'databases',
group: 'documents',
name: 'deleteDocuments',
description: '/docs/references/databases/delete-documents.md',
auth: [AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
model: Response::MODEL_DOCUMENT_LIST,
)
],
contentType: ContentType::JSON
))
->param('databaseId', '', new UID(), 'Database ID.')
->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).')
->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true)
->inject('requestTimestamp')
->inject('response')
->inject('dbForProject')
->inject('queueForStatsUsage')
->inject('plan')
->action(function (string $databaseId, string $collectionId, array $queries, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, StatsUsage $queueForStatsUsage, array $plan) {
$database = $dbForProject->getDocument('databases', $databaseId);
if ($database->isEmpty()) {
throw new Exception(Exception::DATABASE_NOT_FOUND);
}
$collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId);
if ($collection->isEmpty()) {
throw new Exception(Exception::COLLECTION_NOT_FOUND);
}
$hasRelationships = \array_filter(
$collection->getAttribute('attributes', []),
fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP
);
if ($hasRelationships) {
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Bulk delete is not supported for collections with relationship attributes');
}
try {
$queries = Query::parseQueries($queries);
} catch (QueryException $e) {
throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage());
}
$documents = [];
try {
$modified = $dbForProject->deleteDocuments(
'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(),
$queries,
onNext: function (Document $document) use ($plan, &$documents) {
if (\count($documents) < ($plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH)) {
$documents[] = $document;
}
},
);
} catch (NotFoundException) {
throw new Exception(Exception::COLLECTION_NOT_FOUND);
} catch (AuthorizationException) {
throw new Exception(Exception::USER_UNAUTHORIZED);
} catch (TimeoutException) {
throw new Exception(Exception::DATABASE_TIMEOUT);
}
foreach ($documents as $document) {
$document->setAttribute('$databaseId', $database->getId());
$document->setAttribute('$collectionId', $collection->getId());
}
$queueForStatsUsage
->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $modified))
->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified));
$response->dynamic(new Document([
'total' => $modified,
'documents' => $documents,
]), Response::MODEL_DOCUMENT_LIST);
});
App::get('/v1/databases/usage')
->desc('Get databases usage stats')
->groups(['api', 'database', 'usage'])
@ -4512,7 +4893,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage')
$response->dynamic(new Document([
'range' => $range,
'documentsTotal' => $usage[$metrics[0]]['total'],
'documents' => $usage[$metrics[0]]['data'],
'documentsTotal' => $usage[$metrics[0]]['total'],
'documents' => $usage[$metrics[0]]['data'],
]), Response::MODEL_USAGE_COLLECTION);
});

View file

@ -1285,7 +1285,7 @@ App::post('/v1/functions/:functionId/deployments')
],
type: MethodType::UPLOAD,
packaging: true,
requestType: 'multipart/form-data',
requestType: ContentType::MULTIPART,
))
->param('functionId', '', new UID(), 'Function ID.')
->param('entrypoint', null, new Text(1028), 'Entrypoint File.', true)
@ -1899,7 +1899,6 @@ App::post('/v1/functions/:functionId/executions')
)
],
contentType: ContentType::MULTIPART,
requestType: 'application/json',
))
->param('functionId', '', new UID(), 'Function ID.')
->param('body', '', new Text(10485760, 0), 'HTTP body of execution. Default value is empty string.', true)

View file

@ -401,15 +401,15 @@ App::post('/v1/storage/buckets/:bucketId/files')
group: 'files',
name: 'createFile',
description: '/docs/references/storage/create-file.md',
type: MethodType::UPLOAD,
auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT],
requestType: 'multipart/form-data',
responses: [
new SDKResponse(
code: Response::STATUS_CODE_CREATED,
model: Response::MODEL_FILE,
)
]
],
type: MethodType::UPLOAD,
requestType: ContentType::MULTIPART
))
->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).')
->param('fileId', '', new CustomId(), 'File ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')

View file

@ -322,9 +322,7 @@ App::put('/v1/teams/:teamId')
->setAttribute('name', $name)
->setAttribute('search', implode(' ', [$teamId, $name]));
$team = $dbForProject->withRequestTimestamp($requestTimestamp, function () use ($dbForProject, $team) {
return $dbForProject->updateDocument('teams', $team->getId(), $team);
});
$team = $dbForProject->updateDocument('teams', $team->getId(), $team);
$queueForEvents->setParam('teamId', $team->getId());

View file

@ -144,7 +144,6 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
)
],
contentType: ContentType::MULTIPART,
requestType: 'application/json',
));
} else {
/** @var Method $method */

View file

@ -92,8 +92,20 @@ $eventDatabaseListener = function (Document $project, Document $document, Respon
$usageDatabaseListener = function (string $event, Document $document, StatsUsage $queueForStatsUsage) {
$value = 1;
if ($event === Database::EVENT_DOCUMENT_DELETE) {
$value = -1;
switch ($event) {
case Database::EVENT_DOCUMENT_DELETE:
$value = -1;
break;
case Database::EVENT_DOCUMENTS_DELETE:
$value = -1 * $document->getAttribute('modified', 0);
break;
case Database::EVENT_DOCUMENTS_CREATE:
$value = $document->getAttribute('modified', 0);
break;
case Database::EVENT_DOCUMENTS_UPSERT:
$value = $document->getAttribute('created', 0);
break;
}
switch (true) {
@ -328,6 +340,8 @@ App::init()
*/
$method = $route->getLabel('sdk', false);
// Take the first method if there's more than one,
// namespace can not differ between methods on the same route
if (\is_array($method)) {
$method = $method[0];
}
@ -511,6 +525,9 @@ App::init()
$dbForProject
->on(Database::EVENT_DOCUMENT_CREATE, 'calculate-usage', fn ($event, $document) => $usageDatabaseListener($event, $document, $queueForStatsUsage))
->on(Database::EVENT_DOCUMENT_DELETE, 'calculate-usage', fn ($event, $document) => $usageDatabaseListener($event, $document, $queueForStatsUsage))
->on(Database::EVENT_DOCUMENTS_CREATE, 'calculate-usage', fn ($event, $document) => $usageDatabaseListener($event, $document, $queueForStatsUsage))
->on(Database::EVENT_DOCUMENTS_DELETE, 'calculate-usage', fn ($event, $document) => $usageDatabaseListener($event, $document, $queueForStatsUsage))
->on(Database::EVENT_DOCUMENTS_UPSERT, 'calculate-usage', fn ($event, $document) => $usageDatabaseListener($event, $document, $queueForStatsUsage))
->on(Database::EVENT_DOCUMENT_CREATE, 'create-trigger-events', fn ($event, $document) => $eventDatabaseListener(
$project,
$document,

View file

@ -496,7 +496,7 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool
});
// Fetch domains every `DOMAIN_SYNC_TIMER` seconds and update in the memory
$http->on('Task', function () use ($register, $domains) {
$http->on(Constant::EVENT_TASK, function () use ($register, $domains) {
$lastSyncUpdate = null;
$pools = $register->get('pools');
App::setResource('pools', fn () => $pools);

View file

@ -26,6 +26,7 @@ const APP_LIMIT_SUBSCRIBERS_SUBQUERY = 1_000_000;
const APP_LIMIT_WRITE_RATE_DEFAULT = 60; // Default maximum write rate per rate period
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_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

View file

@ -144,6 +144,7 @@ $image = $this->getParam('image', '');
- _APP_LOGGING_CONFIG
- _APP_MAINTENANCE_INTERVAL
- _APP_MAINTENANCE_DELAY
- _APP_MAINTENANCE_START_TIME
- _APP_MAINTENANCE_RETENTION_EXECUTION
- _APP_MAINTENANCE_RETENTION_CACHE
- _APP_MAINTENANCE_RETENTION_ABUSE

View file

@ -30,7 +30,7 @@
}
},
"require": {
"php": ">=8.0.0",
"php": ">=8.3.0",
"ext-curl": "*",
"ext-imagick": "*",
"ext-mbstring": "*",
@ -51,7 +51,7 @@
"utopia-php/cache": "0.13.*",
"utopia-php/cli": "0.15.*",
"utopia-php/config": "0.2.*",
"utopia-php/database": "0.67.*",
"utopia-php/database": "0.68.*",
"utopia-php/domains": "0.5.*",
"utopia-php/dsn": "0.2.1",
"utopia-php/framework": "0.33.*",
@ -99,8 +99,8 @@
"php": "8.3"
},
"allow-plugins": {
"php-http/discovery": false,
"tbachert/spi": false
"php-http/discovery": true,
"tbachert/spi": true
}
}
}

66
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "49b9828ae72763d2a398358c28cebdd5",
"content-hash": "a5c4c6b723423bc6cb3a7344ab071b43",
"packages": [
{
"name": "adhocore/jwt",
@ -1179,16 +1179,16 @@
},
{
"name": "open-telemetry/context",
"version": "1.2.0",
"version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/opentelemetry-php/context.git",
"reference": "5f553042b951d3fedf47925852c380159dfca801"
"reference": "1eb2b837ee9362db064a6b65d5ecce15a9f9f020"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/opentelemetry-php/context/zipball/5f553042b951d3fedf47925852c380159dfca801",
"reference": "5f553042b951d3fedf47925852c380159dfca801",
"url": "https://api.github.com/repos/opentelemetry-php/context/zipball/1eb2b837ee9362db064a6b65d5ecce15a9f9f020",
"reference": "1eb2b837ee9362db064a6b65d5ecce15a9f9f020",
"shasum": ""
},
"require": {
@ -1234,7 +1234,7 @@
"issues": "https://github.com/open-telemetry/opentelemetry-php/issues",
"source": "https://github.com/open-telemetry/opentelemetry-php"
},
"time": "2025-05-02T01:57:57+00:00"
"time": "2025-05-07T23:36:50+00:00"
},
{
"name": "open-telemetry/exporter-otlp",
@ -3301,16 +3301,16 @@
},
{
"name": "utopia-php/cache",
"version": "0.13.0",
"version": "0.13.1",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/cache.git",
"reference": "dee01dec33a211644d60f6cfa56b1b8176d3fae3"
"reference": "97220cb3b3822b166ee016d1646e2ae2815dc540"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/cache/zipball/dee01dec33a211644d60f6cfa56b1b8176d3fae3",
"reference": "dee01dec33a211644d60f6cfa56b1b8176d3fae3",
"url": "https://api.github.com/repos/utopia-php/cache/zipball/97220cb3b3822b166ee016d1646e2ae2815dc540",
"reference": "97220cb3b3822b166ee016d1646e2ae2815dc540",
"shasum": ""
},
"require": {
@ -3347,9 +3347,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/cache/issues",
"source": "https://github.com/utopia-php/cache/tree/0.13.0"
"source": "https://github.com/utopia-php/cache/tree/0.13.1"
},
"time": "2025-04-17T04:20:26+00:00"
"time": "2025-05-09T14:43:52+00:00"
},
{
"name": "utopia-php/cli",
@ -3499,16 +3499,16 @@
},
{
"name": "utopia-php/database",
"version": "0.67.2",
"version": "0.68.1",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/database.git",
"reference": "cd55117beab0025fd0d3f945a5a004125600982c"
"reference": "72b2e2c0b875028f7d9dd755f6d4524b693c6507"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/database/zipball/cd55117beab0025fd0d3f945a5a004125600982c",
"reference": "cd55117beab0025fd0d3f945a5a004125600982c",
"url": "https://api.github.com/repos/utopia-php/database/zipball/72b2e2c0b875028f7d9dd755f6d4524b693c6507",
"reference": "72b2e2c0b875028f7d9dd755f6d4524b693c6507",
"shasum": ""
},
"require": {
@ -3549,9 +3549,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/database/issues",
"source": "https://github.com/utopia-php/database/tree/0.67.2"
"source": "https://github.com/utopia-php/database/tree/0.68.1"
},
"time": "2025-05-06T12:11:58+00:00"
"time": "2025-05-09T10:08:53+00:00"
},
{
"name": "utopia-php/domains",
@ -4595,16 +4595,16 @@
},
{
"name": "utopia-php/websocket",
"version": "0.3.0",
"version": "0.3.1",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/websocket.git",
"reference": "629e53640b108eab43c7cc9ab375efade8622d43"
"reference": "77004ba9f66a0ab6eb840a85b2af332fca8f6bd9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/websocket/zipball/629e53640b108eab43c7cc9ab375efade8622d43",
"reference": "629e53640b108eab43c7cc9ab375efade8622d43",
"url": "https://api.github.com/repos/utopia-php/websocket/zipball/77004ba9f66a0ab6eb840a85b2af332fca8f6bd9",
"reference": "77004ba9f66a0ab6eb840a85b2af332fca8f6bd9",
"shasum": ""
},
"require": {
@ -4638,9 +4638,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/websocket/issues",
"source": "https://github.com/utopia-php/websocket/tree/0.3.0"
"source": "https://github.com/utopia-php/websocket/tree/0.3.1"
},
"time": "2025-03-28T01:11:13+00:00"
"time": "2025-05-09T12:57:42+00:00"
},
{
"name": "webmozart/assert",
@ -5043,16 +5043,16 @@
},
{
"name": "laravel/pint",
"version": "v1.22.0",
"version": "v1.22.1",
"source": {
"type": "git",
"url": "https://github.com/laravel/pint.git",
"reference": "7ddfaa6523a675fae5c4123ee38fc6bfb8ee4f36"
"reference": "941d1927c5ca420c22710e98420287169c7bcaf7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/pint/zipball/7ddfaa6523a675fae5c4123ee38fc6bfb8ee4f36",
"reference": "7ddfaa6523a675fae5c4123ee38fc6bfb8ee4f36",
"url": "https://api.github.com/repos/laravel/pint/zipball/941d1927c5ca420c22710e98420287169c7bcaf7",
"reference": "941d1927c5ca420c22710e98420287169c7bcaf7",
"shasum": ""
},
"require": {
@ -5064,11 +5064,11 @@
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.75.0",
"illuminate/view": "^11.44.2",
"larastan/larastan": "^3.3.1",
"illuminate/view": "^11.44.7",
"larastan/larastan": "^3.4.0",
"laravel-zero/framework": "^11.36.1",
"mockery/mockery": "^1.6.12",
"nunomaduro/termwind": "^2.3",
"nunomaduro/termwind": "^2.3.1",
"pestphp/pest": "^2.36.0"
},
"bin": [
@ -5105,7 +5105,7 @@
"issues": "https://github.com/laravel/pint/issues",
"source": "https://github.com/laravel/pint"
},
"time": "2025-04-08T22:11:45+00:00"
"time": "2025-05-08T08:38:12+00:00"
},
{
"name": "matthiasmullie/minify",
@ -8140,7 +8140,7 @@
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=8.0.0",
"php": ">=8.3.0",
"ext-curl": "*",
"ext-imagick": "*",
"ext-mbstring": "*",

View file

@ -732,7 +732,7 @@ services:
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
- _APP_MAINTENANCE_RETENTION_SCHEDULES
- _APP_MAINTENANCE_DELAY
- _APP_MAINTENANCE_START_TIME
- _APP_DATABASE_SHARED_TABLES
appwrite-task-stats-resources:

View file

@ -0,0 +1,14 @@
import 'package:dart_appwrite/dart_appwrite.dart';
Client client = Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setSession(''); // The user session to authenticate with
Databases databases = Databases(client);
DocumentList result = await databases.createDocuments(
databaseId: '<DATABASE_ID>',
collectionId: '<COLLECTION_ID>',
documents: [],
);

View file

@ -0,0 +1,14 @@
import 'package:dart_appwrite/dart_appwrite.dart';
Client client = Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setKey('<YOUR_API_KEY>'); // Your secret API key
Databases databases = Databases(client);
await databases.deleteDocuments(
databaseId: '<DATABASE_ID>',
collectionId: '<COLLECTION_ID>',
queries: [], // (optional)
);

View file

@ -0,0 +1,15 @@
import 'package:dart_appwrite/dart_appwrite.dart';
Client client = Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setKey('<YOUR_API_KEY>'); // Your secret API key
Databases databases = Databases(client);
DocumentList result = await databases.updateDocuments(
databaseId: '<DATABASE_ID>',
collectionId: '<COLLECTION_ID>',
data: {}, // (optional)
queries: [], // (optional)
);

View file

@ -0,0 +1,14 @@
import 'package:dart_appwrite/dart_appwrite.dart';
Client client = Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setKey('<YOUR_API_KEY>'); // Your secret API key
Databases databases = Databases(client);
DocumentList result = await databases.upsertDocuments(
databaseId: '<DATABASE_ID>',
collectionId: '<COLLECTION_ID>',
documents: [], // (optional)
);

View file

@ -0,0 +1,14 @@
import { Client, Databases } from "https://deno.land/x/appwrite/mod.ts";
const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setSession(''); // The user session to authenticate with
const databases = new Databases(client);
const response = await databases.createDocuments(
'<DATABASE_ID>', // databaseId
'<COLLECTION_ID>', // collectionId
[] // documents
);

View file

@ -0,0 +1,14 @@
import { Client, Databases } from "https://deno.land/x/appwrite/mod.ts";
const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setKey('<YOUR_API_KEY>'); // Your secret API key
const databases = new Databases(client);
const response = await databases.deleteDocuments(
'<DATABASE_ID>', // databaseId
'<COLLECTION_ID>', // collectionId
[] // queries (optional)
);

View file

@ -0,0 +1,15 @@
import { Client, Databases } from "https://deno.land/x/appwrite/mod.ts";
const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setKey('<YOUR_API_KEY>'); // Your secret API key
const databases = new Databases(client);
const response = await databases.updateDocuments(
'<DATABASE_ID>', // databaseId
'<COLLECTION_ID>', // collectionId
{}, // data (optional)
[] // queries (optional)
);

View file

@ -0,0 +1,14 @@
import { Client, Databases } from "https://deno.land/x/appwrite/mod.ts";
const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setKey('<YOUR_API_KEY>'); // Your secret API key
const databases = new Databases(client);
const response = await databases.upsertDocuments(
'<DATABASE_ID>', // databaseId
'<COLLECTION_ID>', // collectionId
[] // documents (optional)
);

View file

@ -0,0 +1,16 @@
using Appwrite;
using Appwrite.Models;
using Appwrite.Services;
Client client = new Client()
.SetEndPoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("<YOUR_PROJECT_ID>") // Your project ID
.SetSession(""); // The user session to authenticate with
Databases databases = new Databases(client);
DocumentList result = await databases.CreateDocuments(
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
documents: new List<object>()
);

View file

@ -0,0 +1,16 @@
using Appwrite;
using Appwrite.Models;
using Appwrite.Services;
Client client = new Client()
.SetEndPoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("<YOUR_PROJECT_ID>") // Your project ID
.SetKey("<YOUR_API_KEY>"); // Your secret API key
Databases databases = new Databases(client);
await databases.DeleteDocuments(
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
queries: new List<string>() // optional
);

View file

@ -0,0 +1,17 @@
using Appwrite;
using Appwrite.Models;
using Appwrite.Services;
Client client = new Client()
.SetEndPoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("<YOUR_PROJECT_ID>") // Your project ID
.SetKey("<YOUR_API_KEY>"); // Your secret API key
Databases databases = new Databases(client);
DocumentList result = await databases.UpdateDocuments(
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
data: [object], // optional
queries: new List<string>() // optional
);

View file

@ -0,0 +1,16 @@
using Appwrite;
using Appwrite.Models;
using Appwrite.Services;
Client client = new Client()
.SetEndPoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("<YOUR_PROJECT_ID>") // Your project ID
.SetKey("<YOUR_API_KEY>"); // Your secret API key
Databases databases = new Databases(client);
DocumentList result = await databases.UpsertDocuments(
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
documents: new List<object>() // optional
);

View file

@ -0,0 +1,28 @@
package main
import (
"fmt"
"github.com/appwrite/sdk-for-go/client"
"github.com/appwrite/sdk-for-go/databases"
)
func main() {
client := client.NewClient()
client.SetEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
client.SetProject("<YOUR_PROJECT_ID>") // Your project ID
client.SetSession("") // The user session to authenticate with
service := databases.NewDatabases(client)
response, error := service.CreateDocuments(
"<DATABASE_ID>",
"<COLLECTION_ID>",
[]interface{}{},
)
if error != nil {
panic(error)
}
fmt.Println(response)
}

View file

@ -0,0 +1,28 @@
package main
import (
"fmt"
"github.com/appwrite/sdk-for-go/client"
"github.com/appwrite/sdk-for-go/databases"
)
func main() {
client := client.NewClient()
client.SetEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
client.SetProject("<YOUR_PROJECT_ID>") // Your project ID
client.SetKey("<YOUR_API_KEY>") // Your secret API key
service := databases.NewDatabases(client)
response, error := service.DeleteDocuments(
"<DATABASE_ID>",
"<COLLECTION_ID>",
databases.WithDeleteDocumentsQueries([]interface{}{}),
)
if error != nil {
panic(error)
}
fmt.Println(response)
}

View file

@ -0,0 +1,29 @@
package main
import (
"fmt"
"github.com/appwrite/sdk-for-go/client"
"github.com/appwrite/sdk-for-go/databases"
)
func main() {
client := client.NewClient()
client.SetEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
client.SetProject("<YOUR_PROJECT_ID>") // Your project ID
client.SetKey("<YOUR_API_KEY>") // Your secret API key
service := databases.NewDatabases(client)
response, error := service.UpdateDocuments(
"<DATABASE_ID>",
"<COLLECTION_ID>",
databases.WithUpdateDocumentsData(map[string]interface{}{}),
databases.WithUpdateDocumentsQueries([]interface{}{}),
)
if error != nil {
panic(error)
}
fmt.Println(response)
}

View file

@ -0,0 +1,28 @@
package main
import (
"fmt"
"github.com/appwrite/sdk-for-go/client"
"github.com/appwrite/sdk-for-go/databases"
)
func main() {
client := client.NewClient()
client.SetEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
client.SetProject("<YOUR_PROJECT_ID>") // Your project ID
client.SetKey("<YOUR_API_KEY>") // Your secret API key
service := databases.NewDatabases(client)
response, error := service.UpsertDocuments(
"<DATABASE_ID>",
"<COLLECTION_ID>",
databases.WithUpsertDocumentsDocuments([]interface{}{}),
)
if error != nil {
panic(error)
}
fmt.Println(response)
}

View file

@ -0,0 +1,18 @@
mutation {
databasesCreateDocuments(
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
documents: []
) {
total
documents {
_id
_collectionId
_databaseId
_createdAt
_updatedAt
_permissions
data
}
}
}

View file

@ -0,0 +1,18 @@
mutation {
databasesDeleteDocuments(
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
queries: []
) {
total
documents {
_id
_collectionId
_databaseId
_createdAt
_updatedAt
_permissions
data
}
}
}

View file

@ -0,0 +1,19 @@
mutation {
databasesUpdateDocuments(
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
data: "{}",
queries: []
) {
total
documents {
_id
_collectionId
_databaseId
_createdAt
_updatedAt
_permissions
data
}
}
}

View file

@ -0,0 +1,18 @@
mutation {
databasesUpsertDocuments(
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
documents: []
) {
total
documents {
_id
_collectionId
_databaseId
_createdAt
_updatedAt
_permissions
data
}
}
}

View file

@ -0,0 +1,25 @@
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Databases;
Client client = new Client()
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setSession(""); // The user session to authenticate with
Databases databases = new Databases(client);
databases.createDocuments(
"<DATABASE_ID>", // databaseId
"<COLLECTION_ID>", // collectionId
listOf(), // documents
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);

View file

@ -0,0 +1,25 @@
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Databases;
Client client = new Client()
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setKey("<YOUR_API_KEY>"); // Your secret API key
Databases databases = new Databases(client);
databases.deleteDocuments(
"<DATABASE_ID>", // databaseId
"<COLLECTION_ID>", // collectionId
listOf(), // queries (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);

View file

@ -0,0 +1,26 @@
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Databases;
Client client = new Client()
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setKey("<YOUR_API_KEY>"); // Your secret API key
Databases databases = new Databases(client);
databases.updateDocuments(
"<DATABASE_ID>", // databaseId
"<COLLECTION_ID>", // collectionId
mapOf( "a" to "b" ), // data (optional)
listOf(), // queries (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);

View file

@ -0,0 +1,25 @@
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Databases;
Client client = new Client()
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setKey("<YOUR_API_KEY>"); // Your secret API key
Databases databases = new Databases(client);
databases.upsertDocuments(
"<DATABASE_ID>", // databaseId
"<COLLECTION_ID>", // collectionId
listOf(), // documents (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);

View file

@ -0,0 +1,16 @@
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.Databases
val client = Client()
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setSession("") // The user session to authenticate with
val databases = Databases(client)
val response = databases.createDocuments(
databaseId = "<DATABASE_ID>",
collectionId = "<COLLECTION_ID>",
documents = listOf()
)

View file

@ -0,0 +1,16 @@
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.Databases
val client = Client()
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setKey("<YOUR_API_KEY>") // Your secret API key
val databases = Databases(client)
val response = databases.deleteDocuments(
databaseId = "<DATABASE_ID>",
collectionId = "<COLLECTION_ID>",
queries = listOf() // optional
)

View file

@ -0,0 +1,17 @@
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.Databases
val client = Client()
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setKey("<YOUR_API_KEY>") // Your secret API key
val databases = Databases(client)
val response = databases.updateDocuments(
databaseId = "<DATABASE_ID>",
collectionId = "<COLLECTION_ID>",
data = mapOf( "a" to "b" ), // optional
queries = listOf() // optional
)

View file

@ -0,0 +1,16 @@
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.Databases
val client = Client()
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setKey("<YOUR_API_KEY>") // Your secret API key
val databases = Databases(client)
val response = databases.upsertDocuments(
databaseId = "<DATABASE_ID>",
collectionId = "<COLLECTION_ID>",
documents = listOf() // optional
)

View file

@ -0,0 +1,14 @@
const sdk = require('node-appwrite');
const client = new sdk.Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setSession(''); // The user session to authenticate with
const databases = new sdk.Databases(client);
const result = await databases.createDocuments(
'<DATABASE_ID>', // databaseId
'<COLLECTION_ID>', // collectionId
[] // documents
);

View file

@ -0,0 +1,14 @@
const sdk = require('node-appwrite');
const client = new sdk.Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setKey('<YOUR_API_KEY>'); // Your secret API key
const databases = new sdk.Databases(client);
const result = await databases.deleteDocuments(
'<DATABASE_ID>', // databaseId
'<COLLECTION_ID>', // collectionId
[] // queries (optional)
);

View file

@ -0,0 +1,15 @@
const sdk = require('node-appwrite');
const client = new sdk.Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setKey('<YOUR_API_KEY>'); // Your secret API key
const databases = new sdk.Databases(client);
const result = await databases.updateDocuments(
'<DATABASE_ID>', // databaseId
'<COLLECTION_ID>', // collectionId
{}, // data (optional)
[] // queries (optional)
);

View file

@ -0,0 +1,14 @@
const sdk = require('node-appwrite');
const client = new sdk.Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setKey('<YOUR_API_KEY>'); // Your secret API key
const databases = new sdk.Databases(client);
const result = await databases.upsertDocuments(
'<DATABASE_ID>', // databaseId
'<COLLECTION_ID>', // collectionId
[] // documents (optional)
);

View file

@ -0,0 +1,17 @@
<?php
use Appwrite\Client;
use Appwrite\Services\Databases;
$client = (new Client())
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
->setProject('<YOUR_PROJECT_ID>') // Your project ID
->setSession(''); // The user session to authenticate with
$databases = new Databases($client);
$result = $databases->createDocuments(
databaseId: '<DATABASE_ID>',
collectionId: '<COLLECTION_ID>',
documents: []
);

View file

@ -0,0 +1,17 @@
<?php
use Appwrite\Client;
use Appwrite\Services\Databases;
$client = (new Client())
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
->setProject('<YOUR_PROJECT_ID>') // Your project ID
->setKey('<YOUR_API_KEY>'); // Your secret API key
$databases = new Databases($client);
$result = $databases->deleteDocuments(
databaseId: '<DATABASE_ID>',
collectionId: '<COLLECTION_ID>',
queries: [] // optional
);

View file

@ -0,0 +1,18 @@
<?php
use Appwrite\Client;
use Appwrite\Services\Databases;
$client = (new Client())
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
->setProject('<YOUR_PROJECT_ID>') // Your project ID
->setKey('<YOUR_API_KEY>'); // Your secret API key
$databases = new Databases($client);
$result = $databases->updateDocuments(
databaseId: '<DATABASE_ID>',
collectionId: '<COLLECTION_ID>',
data: [], // optional
queries: [] // optional
);

View file

@ -0,0 +1,17 @@
<?php
use Appwrite\Client;
use Appwrite\Services\Databases;
$client = (new Client())
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
->setProject('<YOUR_PROJECT_ID>') // Your project ID
->setKey('<YOUR_API_KEY>'); // Your secret API key
$databases = new Databases($client);
$result = $databases->upsertDocuments(
databaseId: '<DATABASE_ID>',
collectionId: '<COLLECTION_ID>',
documents: [] // optional
);

View file

@ -0,0 +1,15 @@
from appwrite.client import Client
from appwrite.services.databases import Databases
client = Client()
client.set_endpoint('https://<REGION>.cloud.appwrite.io/v1') # Your API Endpoint
client.set_project('<YOUR_PROJECT_ID>') # Your project ID
client.set_session('') # The user session to authenticate with
databases = Databases(client)
result = databases.create_documents(
database_id = '<DATABASE_ID>',
collection_id = '<COLLECTION_ID>',
documents = []
)

View file

@ -0,0 +1,15 @@
from appwrite.client import Client
from appwrite.services.databases import Databases
client = Client()
client.set_endpoint('https://<REGION>.cloud.appwrite.io/v1') # Your API Endpoint
client.set_project('<YOUR_PROJECT_ID>') # Your project ID
client.set_key('<YOUR_API_KEY>') # Your secret API key
databases = Databases(client)
result = databases.delete_documents(
database_id = '<DATABASE_ID>',
collection_id = '<COLLECTION_ID>',
queries = [] # optional
)

View file

@ -0,0 +1,16 @@
from appwrite.client import Client
from appwrite.services.databases import Databases
client = Client()
client.set_endpoint('https://<REGION>.cloud.appwrite.io/v1') # Your API Endpoint
client.set_project('<YOUR_PROJECT_ID>') # Your project ID
client.set_key('<YOUR_API_KEY>') # Your secret API key
databases = Databases(client)
result = databases.update_documents(
database_id = '<DATABASE_ID>',
collection_id = '<COLLECTION_ID>',
data = {}, # optional
queries = [] # optional
)

View file

@ -0,0 +1,15 @@
from appwrite.client import Client
from appwrite.services.databases import Databases
client = Client()
client.set_endpoint('https://<REGION>.cloud.appwrite.io/v1') # Your API Endpoint
client.set_project('<YOUR_PROJECT_ID>') # Your project ID
client.set_key('<YOUR_API_KEY>') # Your secret API key
databases = Databases(client)
result = databases.upsert_documents(
database_id = '<DATABASE_ID>',
collection_id = '<COLLECTION_ID>',
documents = [] # optional
)

View file

@ -0,0 +1,12 @@
POST /v1/databases/{databaseId}/collections/{collectionId}/documents HTTP/1.1
Host: cloud.appwrite.io
Content-Type: application/json
X-Appwrite-Response-Format: 1.6.0
X-Appwrite-Project: <YOUR_PROJECT_ID>
X-Appwrite-Session:
X-Appwrite-Key: <YOUR_API_KEY>
X-Appwrite-JWT: <YOUR_JWT>
{
"documents": []
}

View file

@ -0,0 +1,10 @@
DELETE /v1/databases/{databaseId}/collections/{collectionId}/documents HTTP/1.1
Host: cloud.appwrite.io
Content-Type: application/json
X-Appwrite-Response-Format: 1.6.0
X-Appwrite-Project: <YOUR_PROJECT_ID>
X-Appwrite-Key: <YOUR_API_KEY>
{
"queries": []
}

View file

@ -0,0 +1,11 @@
PATCH /v1/databases/{databaseId}/collections/{collectionId}/documents HTTP/1.1
Host: cloud.appwrite.io
Content-Type: application/json
X-Appwrite-Response-Format: 1.6.0
X-Appwrite-Project: <YOUR_PROJECT_ID>
X-Appwrite-Key: <YOUR_API_KEY>
{
"data": {},
"queries": []
}

View file

@ -0,0 +1,10 @@
PUT /v1/databases/{databaseId}/collections/{collectionId}/documents HTTP/1.1
Host: cloud.appwrite.io
Content-Type: application/json
X-Appwrite-Response-Format: 1.6.0
X-Appwrite-Project: <YOUR_PROJECT_ID>
X-Appwrite-Key: <YOUR_API_KEY>
{
"documents": []
}

View file

@ -0,0 +1,16 @@
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://<REGION>.cloud.appwrite.io/v1') # Your API Endpoint
.set_project('<YOUR_PROJECT_ID>') # Your project ID
.set_session('') # The user session to authenticate with
databases = Databases.new(client)
result = databases.create_documents(
database_id: '<DATABASE_ID>',
collection_id: '<COLLECTION_ID>',
documents: []
)

View file

@ -0,0 +1,16 @@
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://<REGION>.cloud.appwrite.io/v1') # Your API Endpoint
.set_project('<YOUR_PROJECT_ID>') # Your project ID
.set_key('<YOUR_API_KEY>') # Your secret API key
databases = Databases.new(client)
result = databases.delete_documents(
database_id: '<DATABASE_ID>',
collection_id: '<COLLECTION_ID>',
queries: [] # optional
)

View file

@ -0,0 +1,17 @@
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://<REGION>.cloud.appwrite.io/v1') # Your API Endpoint
.set_project('<YOUR_PROJECT_ID>') # Your project ID
.set_key('<YOUR_API_KEY>') # Your secret API key
databases = Databases.new(client)
result = databases.update_documents(
database_id: '<DATABASE_ID>',
collection_id: '<COLLECTION_ID>',
data: {}, # optional
queries: [] # optional
)

View file

@ -0,0 +1,16 @@
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://<REGION>.cloud.appwrite.io/v1') # Your API Endpoint
.set_project('<YOUR_PROJECT_ID>') # Your project ID
.set_key('<YOUR_API_KEY>') # Your secret API key
databases = Databases.new(client)
result = databases.upsert_documents(
database_id: '<DATABASE_ID>',
collection_id: '<COLLECTION_ID>',
documents: [] # optional
)

View file

@ -0,0 +1,15 @@
import Appwrite
let client = Client()
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setSession("") // The user session to authenticate with
let databases = Databases(client)
let documentList = try await databases.createDocuments(
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
documents: []
)

View file

@ -0,0 +1,15 @@
import Appwrite
let client = Client()
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setKey("<YOUR_API_KEY>") // Your secret API key
let databases = Databases(client)
let documentList = try await databases.deleteDocuments(
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
queries: [] // optional
)

View file

@ -0,0 +1,16 @@
import Appwrite
let client = Client()
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setKey("<YOUR_API_KEY>") // Your secret API key
let databases = Databases(client)
let documentList = try await databases.updateDocuments(
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
data: [:], // optional
queries: [] // optional
)

View file

@ -0,0 +1,15 @@
import Appwrite
let client = Client()
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setKey("<YOUR_API_KEY>") // Your secret API key
let databases = Databases(client)
let documentList = try await databases.upsertDocuments(
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
documents: [] // optional
)

View file

@ -1 +1 @@
Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection) API or directly from your database console.
Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection) API or directly from your database console.

View file

@ -0,0 +1 @@
Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection) API or directly from your database console.

View file

@ -0,0 +1 @@
Bulk delete documents using queries, if no queries are passed then all documents are deleted.

View file

@ -0,0 +1 @@
Update all documents that match your queries, if no queries are submitted then all documents are updated. You can pass only specific fields to be updated.

View file

@ -0,0 +1 @@
Create or update Documents. Before using this route, you should create a new collection resource using either a [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection) API or directly from your database console.

View file

@ -85,13 +85,19 @@ App::post('/v1/account/create')
```php
App::post('/v1/account/jwt')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION])
->label('sdk.namespace', 'account')
->label('sdk.method', 'createJWT')
->label('sdk.description', '/docs/references/account/create-jwt.md')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_JWT)
->label('sdk', new Method(
namespace: 'account',
name: 'createJWT',
description: '/docs/references/account/create-jwt.md',
auth: [],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_CREATED,
model: Response::MODEL_JWT,
)
],
responseType: ResponseType::JSON,
))
```
#### Cache

View file

@ -117,13 +117,19 @@ class Mapper
$list = false;
foreach ($route->getParams() as $name => $parameter) {
$methodParameters = $method->getParameters();
$sdkParameters = $method->getParameters();
if (!empty($methodParameters)) {
if (!array_key_exists($name, $methodParameters)) {
if (!empty($sdkParameters)) {
$sdkMethodParameters = [];
foreach ($sdkParameters as $sdkParameter) {
$sdkMethodParameters[$sdkParameter->getName()] = $sdkParameter;
}
if (!\array_key_exists($name, $sdkMethodParameters)) {
continue;
}
$optional = $methodParameters[$name]['optional'];
$optional = $sdkMethodParameters[$name]->getOptional();
} else {
$optional = $parameter['optional'];
}

View file

@ -35,12 +35,27 @@ class Maintenance extends Action
Console::title('Maintenance V1');
Console::success(APP_NAME . ' maintenance process v1 has started');
// # of days in seconds (1 day = 86400s)
$interval = (int) System::getEnv('_APP_MAINTENANCE_INTERVAL', '86400');
$delay = (int) System::getEnv('_APP_MAINTENANCE_DELAY', '0');
$interval = (int) System::getEnv('_APP_MAINTENANCE_INTERVAL', '86400'); // 1 day
$usageStatsRetentionHourly = (int) System::getEnv('_APP_MAINTENANCE_RETENTION_USAGE_HOURLY', '8640000'); //100 days
$cacheRetention = (int) System::getEnv('_APP_MAINTENANCE_RETENTION_CACHE', '2592000'); // 30 days
$schedulesDeletionRetention = (int) System::getEnv('_APP_MAINTENANCE_RETENTION_SCHEDULES', '86400'); // 1 Day
$jobInitTime = System::getEnv('_APP_MAINTENANCE_START_TIME', '00:00'); // (hour:minutes)
$now = new \DateTime();
$now->setTimezone(new \DateTimeZone(date_default_timezone_get()));
$next = new \DateTime($now->format("Y-m-d $jobInitTime"));
$next->setTimezone(new \DateTimeZone(date_default_timezone_get()));
$delay = $next->getTimestamp() - $now->getTimestamp();
/**
* If time passed for the target day.
*/
if ($delay <= 0) {
$next->add(\DateInterval::createFromDateString('1 days'));
$delay = $next->getTimestamp() - $now->getTimestamp();
}
Console::info('Setting loop start time to ' . $next->format("Y-m-d H:i:s.v") . '. Delaying for ' . $delay . ' seconds.');
Console::loop(function () use ($interval, $cacheRetention, $schedulesDeletionRetention, $usageStatsRetentionHourly, $dbForPlatform, $console, $queueForDeletes, $queueForCertificates) {
$time = DateTime::now();

View file

@ -3,6 +3,7 @@
namespace Appwrite\Platform\Tasks;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Specification\Format\OpenAPI3;
use Appwrite\SDK\Specification\Format\Swagger2;
use Appwrite\SDK\Specification\Specification;
@ -19,7 +20,6 @@ use Utopia\Config\Config;
use Utopia\Database\Adapter\MySQL;
use Utopia\Database\Database;
use Utopia\Platform\Action;
use Utopia\Registry\Registry;
use Utopia\Request as UtopiaRequest;
use Utopia\Response as UtopiaResponse;
use Utopia\System\System;
@ -49,11 +49,10 @@ class Specs extends Action
->desc('Generate Appwrite API specifications')
->param('version', 'latest', new Text(16), 'Spec version', true)
->param('mode', 'normal', new WhiteList(['normal', 'mocks']), 'Spec Mode', true)
->inject('register')
->callback(fn (string $version, string $mode, Registry $register) => $this->action($version, $mode, $register));
->callback($this->action(...));
}
public function action(string $version, string $mode, Registry $register): void
public function action(string $version, string $mode): void
{
$appRoutes = App::getRoutes();
$response = $this->getResponse();
@ -194,7 +193,7 @@ class Specs extends Action
}
foreach ($sdks as $sdk) {
/** @var \Appwrite\SDK\Method $sdks */
/** @var Method $sdk */
$hide = $sdk->isHidden();
if ($hide === true || (\is_array($hide) && \in_array($platform, $hide))) {
@ -262,7 +261,6 @@ class Specs extends Action
$services[] = [
'name' => $service['key'] ?? '',
'description' => $service['subtitle'] ?? '',
'x-globalAttributes' => $service['globalAttributes'] ?? [],
];
}
@ -274,7 +272,15 @@ class Specs extends Action
}
}
$arguments = [new App('UTC'), $services, $routes, $models, $keys[$platform], $authCounts[$platform] ?? 0];
$arguments = [
new App('UTC'),
$services,
$routes,
$models,
$keys[$platform],
$authCounts[$platform] ?? 0
];
foreach (['swagger2', 'open-api3'] as $format) {
$formatInstance = match ($format) {
'swagger2' => new Swagger2(...$arguments),

View file

@ -21,16 +21,14 @@ class Method
* @param string $description
* @param array<AuthType> $auth
* @param array<SDKResponse> $responses
* @param ContentType $responseType
* @param MethodType|null $methodType
* @param ContentType $contentType
* @param MethodType|null $type
* @param bool $deprecated
* @param array|bool $hide
* @param bool $packaging
* @param string $requestType
* @param array $parameters
* @param ContentType $requestType
* @param array<Parameter> $parameters
* @param array $additionalParameters
*
* @throws \Exception
*/
public function __construct(
protected string $namespace,
@ -44,7 +42,7 @@ class Method
protected bool $deprecated = false,
protected array|bool $hide = false,
protected bool $packaging = false,
protected string $requestType = 'application/json',
protected ContentType $requestType = ContentType::JSON,
protected array $parameters = [],
protected array $additionalParameters = []
) {
@ -53,7 +51,6 @@ class Method
$this->validateDesc($description);
foreach ($responses as $response) {
/** @var SDKResponse $response */
$this->validateResponseModel($response->getModel());
$this->validateNoContent($response);
}
@ -191,11 +188,14 @@ class Method
return $this->packaging;
}
public function getRequestType(): string
public function getRequestType(): ContentType
{
return $this->requestType;
}
/**
* @return array<Parameter>
*/
public function getParameters(): array
{
return $this->parameters;
@ -274,7 +274,7 @@ class Method
return $this;
}
public function setRequestType(string $requestType): self
public function setRequestType(ContentType $requestType): self
{
$this->requestType = $requestType;
return $this;

View file

@ -0,0 +1,79 @@
<?php
namespace Appwrite\SDK;
use Utopia\Validator;
class Parameter
{
/**
* @param string $name
* @param string $description
* @param mixed|null $default
* @param Validator|callable|null $validator
* @param bool $optional
*/
public function __construct(
protected string $name,
protected string $description = '',
protected mixed $default = null,
protected mixed $validator = null,
protected bool $optional = false,
) {
}
public function getName(): string
{
return $this->name;
}
public function setName(string $name): static
{
$this->name = $name;
return $this;
}
public function getDescription(): string
{
return $this->description;
}
public function setDescription(string $description): static
{
$this->description = $description;
return $this;
}
public function getDefault(): mixed
{
return $this->default;
}
public function setDefault(mixed $default): static
{
$this->default = $default;
return $this;
}
public function getValidator(): mixed
{
return $this->validator;
}
public function setValidator(mixed $validator): static
{
$this->validator = $validator;
return $this;
}
public function getOptional(): bool
{
return $this->optional;
}
public function setOptional(bool $optional): static
{
$this->optional = $optional;
return $this;
}
}

View file

@ -12,12 +12,12 @@ abstract class Format
protected App $app;
/**
* @var Route[]
* @var array<Route>
*/
protected array $routes;
/**
* @var Model[]
* @var array<Model>
*/
protected array $models;
@ -415,4 +415,24 @@ abstract class Format
}
return $values;
}
protected function getNestedModels(Model $model, array &$usedModels): void
{
foreach ($model->getRules() as $rule) {
if (!in_array($model->getType(), $usedModels)) {
continue;
}
$types = (array)$rule['type'];
foreach ($types as $ruleType) {
if (!in_array($ruleType, ['string', 'integer', 'boolean', 'json', 'float'])) {
$usedModels[] = $ruleType;
foreach ($this->models as $m) {
if ($m->getType() === $ruleType) {
$this->getNestedModels($m, $usedModels);
}
}
}
}
}
}
}

View file

@ -3,7 +3,9 @@
namespace Appwrite\SDK\Specification\Format;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\Method;
use Appwrite\SDK\MethodType;
use Appwrite\SDK\Response;
use Appwrite\SDK\Specification\Format;
use Appwrite\Template\Template;
use Appwrite\Utopia\Response\Model;
@ -22,41 +24,6 @@ class OpenAPI3 extends Format
return 'Open API 3';
}
protected function getNestedModels(Model $model, array &$usedModels): void
{
foreach ($model->getRules() as $rule) {
if (!in_array($model->getType(), $usedModels)) {
continue;
}
if (\is_array($rule['type'])) {
foreach ($rule['type'] as $ruleType) {
if (!in_array($ruleType, ['string', 'integer', 'boolean', 'json', 'float', 'double'])) {
$usedModels[] = $ruleType;
foreach ($this->models as $m) {
if ($m->getType() === $ruleType) {
$this->getNestedModels($m, $usedModels);
continue;
}
}
}
}
} else {
if (!in_array($rule['type'], ['string', 'integer', 'boolean', 'json', 'float', 'double'])) {
$usedModels[] = $rule['type'];
foreach ($this->models as $m) {
if ($m->getType() === $rule['type']) {
$this->getNestedModels($m, $usedModels);
continue;
}
}
}
}
}
}
public function parse(): array
{
/**
@ -133,22 +100,20 @@ class OpenAPI3 extends Format
}
$additionalMethods = null;
if (is_array($sdk)) {
$mainSdk = array_shift($sdk);
if (\is_array($sdk)) {
$additionalMethods = $sdk;
$sdk = $mainSdk;
$sdk = $sdk[0];
}
/**
* @var \Appwrite\SDK\Method $sdk
* @var Method $sdk
*/
$consumes = [$sdk->getRequestType()];
$consumes = [$sdk->getRequestType()->value];
$method = $sdk->getMethodName() ?? \uniqid();
if (!empty($method) && is_array($method)) {
$method = array_keys($method)[0];
if (!empty($method) && \is_array($method)) {
$method = \array_keys($method)[0];
}
$desc = $sdk->getDescriptionFilePath();
@ -161,10 +126,8 @@ class OpenAPI3 extends Format
case AuthType::SESSION:
$sdkPlatforms[] = APP_PLATFORM_CLIENT;
break;
case AuthType::KEY:
$sdkPlatforms[] = APP_PLATFORM_SERVER;
break;
case AuthType::JWT:
case AuthType::KEY:
$sdkPlatforms[] = APP_PLATFORM_SERVER;
break;
case AuthType::ADMIN:
@ -206,39 +169,47 @@ class OpenAPI3 extends Format
if (!empty($additionalMethods)) {
$temp['x-appwrite']['additional-methods'] = [];
$temp['x-appwrite']['methods'] = [];
foreach ($additionalMethods as $method) {
/** @var \Appwrite\SDK\Method $method */
/** @var Method $method */
$desc = $method->getDescriptionFilePath();
$additionalMethod = [
'name' => $method->getMethodName(),
'parameters' => [],
'required' => [],
'responses' => []
'responses' => [],
'description' => ($desc) ? \file_get_contents($desc) : '',
];
foreach ($method->getParameters() as $name => $param) {
$additionalMethod['parameters'][] = $name;
foreach ($method->getParameters() as $parameter) {
$additionalMethod['parameters'][] = $parameter->getName();
if (!$param['optional']) {
$additionalMethod['required'][] = $name;
if (!$parameter->getOptional()) {
$additionalMethod['required'][] = $parameter->getName();
}
}
foreach ($method->getResponses() as $response) {
/** @var \Appwrite\SDK\Response $response */
$additionalMethod['responses'][] = [
'code' => $response->getCode(),
'model' => '#/components/schemas/' . $response->getModel()
];
if (\is_array($response->getModel())) {
$additionalMethod['responses'][] = [
'code' => $response->getCode(),
'model' => \array_map(fn ($m) => '#/components/schemas/' . $m, $response->getModel())
];
} else {
$additionalMethod['responses'][] = [
'code' => $response->getCode(),
'model' => '#/components/schemas/' . $response->getModel()
];
}
}
$temp['x-appwrite']['additional-methods'][] = $additionalMethod;
$temp['x-appwrite']['methods'][] = $additionalMethod;
}
}
// Handle response models
foreach ($sdk->getResponses() as $response) {
/** @var \Appwrite\SDK\Response $response */
/** @var Response $response */
$model = $response->getModel();
foreach ($this->models as $value) {
@ -306,11 +277,11 @@ class OpenAPI3 extends Format
}
}
if ((!empty($scope))) { // && 'public' != $scope
if ((!empty($scope))) {
$securities = ['Project' => []];
foreach ($sdk->getAuth() as $security) {
/** @var \Appwrite\SDK\AuthType $security */
/** @var AuthType $security */
if (array_key_exists($security->value, $this->keys)) {
$securities[$security->value] = [];
}

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