mirror of
https://github.com/appwrite/appwrite
synced 2026-05-23 08:58:35 +00:00
Merge pull request #9065 from appwrite/feat-bulk-operations
Feat bulk operations
This commit is contained in:
commit
932ed94b8c
104 changed files with 8345 additions and 152389 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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', []);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.')
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
||||
|
|
|
|||
|
|
@ -144,7 +144,6 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
|||
)
|
||||
],
|
||||
contentType: ContentType::MULTIPART,
|
||||
requestType: 'application/json',
|
||||
));
|
||||
} else {
|
||||
/** @var Method $method */
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
42
composer.lock
generated
42
composer.lock
generated
|
|
@ -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",
|
||||
|
|
@ -3499,16 +3499,16 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/database",
|
||||
"version": "0.67.2",
|
||||
"version": "0.68.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/database.git",
|
||||
"reference": "cd55117beab0025fd0d3f945a5a004125600982c"
|
||||
"reference": "f9c2b6b4e7a17f0890d3fb6238b03dae6b2670ad"
|
||||
},
|
||||
"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/f9c2b6b4e7a17f0890d3fb6238b03dae6b2670ad",
|
||||
"reference": "f9c2b6b4e7a17f0890d3fb6238b03dae6b2670ad",
|
||||
"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.0"
|
||||
},
|
||||
"time": "2025-05-06T12:11:58+00:00"
|
||||
"time": "2025-05-08T12:01:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/domains",
|
||||
|
|
@ -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": "*",
|
||||
|
|
|
|||
|
|
@ -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: [],
|
||||
);
|
||||
|
|
@ -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)
|
||||
);
|
||||
|
|
@ -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)
|
||||
);
|
||||
|
|
@ -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)
|
||||
);
|
||||
|
|
@ -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
|
||||
);
|
||||
|
|
@ -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)
|
||||
);
|
||||
|
|
@ -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)
|
||||
);
|
||||
|
|
@ -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)
|
||||
);
|
||||
|
|
@ -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>()
|
||||
);
|
||||
|
|
@ -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
|
||||
);
|
||||
|
|
@ -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
|
||||
);
|
||||
|
|
@ -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
|
||||
);
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
mutation {
|
||||
databasesCreateDocuments(
|
||||
databaseId: "<DATABASE_ID>",
|
||||
collectionId: "<COLLECTION_ID>",
|
||||
documents: []
|
||||
) {
|
||||
total
|
||||
documents {
|
||||
_id
|
||||
_collectionId
|
||||
_databaseId
|
||||
_createdAt
|
||||
_updatedAt
|
||||
_permissions
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
mutation {
|
||||
databasesDeleteDocuments(
|
||||
databaseId: "<DATABASE_ID>",
|
||||
collectionId: "<COLLECTION_ID>",
|
||||
queries: []
|
||||
) {
|
||||
total
|
||||
documents {
|
||||
_id
|
||||
_collectionId
|
||||
_databaseId
|
||||
_createdAt
|
||||
_updatedAt
|
||||
_permissions
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
mutation {
|
||||
databasesUpdateDocuments(
|
||||
databaseId: "<DATABASE_ID>",
|
||||
collectionId: "<COLLECTION_ID>",
|
||||
data: "{}",
|
||||
queries: []
|
||||
) {
|
||||
total
|
||||
documents {
|
||||
_id
|
||||
_collectionId
|
||||
_databaseId
|
||||
_createdAt
|
||||
_updatedAt
|
||||
_permissions
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
mutation {
|
||||
databasesUpsertDocuments(
|
||||
databaseId: "<DATABASE_ID>",
|
||||
collectionId: "<COLLECTION_ID>",
|
||||
documents: []
|
||||
) {
|
||||
total
|
||||
documents {
|
||||
_id
|
||||
_collectionId
|
||||
_databaseId
|
||||
_createdAt
|
||||
_updatedAt
|
||||
_permissions
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -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);
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -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);
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -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);
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -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()
|
||||
)
|
||||
|
|
@ -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
|
||||
)
|
||||
|
|
@ -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
|
||||
)
|
||||
|
|
@ -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
|
||||
)
|
||||
|
|
@ -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
|
||||
);
|
||||
|
|
@ -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)
|
||||
);
|
||||
|
|
@ -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)
|
||||
);
|
||||
|
|
@ -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)
|
||||
);
|
||||
|
|
@ -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: []
|
||||
);
|
||||
|
|
@ -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
|
||||
);
|
||||
|
|
@ -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
|
||||
);
|
||||
|
|
@ -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
|
||||
);
|
||||
|
|
@ -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 = []
|
||||
)
|
||||
|
|
@ -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
|
||||
)
|
||||
|
|
@ -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
|
||||
)
|
||||
|
|
@ -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
|
||||
)
|
||||
|
|
@ -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": []
|
||||
}
|
||||
|
|
@ -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": []
|
||||
}
|
||||
|
|
@ -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": []
|
||||
}
|
||||
|
|
@ -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": []
|
||||
}
|
||||
|
|
@ -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: []
|
||||
)
|
||||
|
|
@ -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
|
||||
)
|
||||
|
|
@ -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
|
||||
)
|
||||
|
|
@ -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
|
||||
)
|
||||
|
|
@ -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: []
|
||||
)
|
||||
|
||||
|
|
@ -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
|
||||
)
|
||||
|
||||
|
|
@ -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
|
||||
)
|
||||
|
||||
|
|
@ -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
|
||||
)
|
||||
|
||||
|
|
@ -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.
|
||||
1
docs/references/databases/create-documents.md
Normal file
1
docs/references/databases/create-documents.md
Normal 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.
|
||||
1
docs/references/databases/delete-documents.md
Normal file
1
docs/references/databases/delete-documents.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
Bulk delete documents using queries, if no queries are passed then all documents are deleted.
|
||||
1
docs/references/databases/update-documents.md
Normal file
1
docs/references/databases/update-documents.md
Normal 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.
|
||||
1
docs/references/databases/upsert-documents.md
Normal file
1
docs/references/databases/upsert-documents.md
Normal 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.
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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'];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
79
src/Appwrite/SDK/Parameter.php
Normal file
79
src/Appwrite/SDK/Parameter.php
Normal 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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] = [];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,16 +3,20 @@
|
|||
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;
|
||||
use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Route;
|
||||
use Utopia\Validator;
|
||||
use Utopia\Validator\ArrayList;
|
||||
use Utopia\Validator\Nullable;
|
||||
use Utopia\Validator\Range;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
class Swagger2 extends Format
|
||||
{
|
||||
|
|
@ -21,41 +25,6 @@ class Swagger2 extends Format
|
|||
return 'Swagger 2';
|
||||
}
|
||||
|
||||
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'])) {
|
||||
$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'])) {
|
||||
$usedModels[] = $rule['type'];
|
||||
|
||||
foreach ($this->models as $m) {
|
||||
if ($m->getType() === $rule['type']) {
|
||||
$this->getNestedModels($m, $usedModels);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function parse(): array
|
||||
{
|
||||
/*
|
||||
|
|
@ -118,11 +87,12 @@ class Swagger2 extends Format
|
|||
$usedModels = [];
|
||||
|
||||
foreach ($this->routes as $route) {
|
||||
/** @var \Utopia\Route $route */
|
||||
/** @var Route $route */
|
||||
$url = \str_replace('/v1', '', $route->getPath());
|
||||
|
||||
$scope = $route->getLabel('scope', '');
|
||||
|
||||
/** @var \Appwrite\SDK\Method $sdk */
|
||||
/** @var Method $sdk */
|
||||
$sdk = $route->getLabel('sdk', false);
|
||||
|
||||
if (empty($sdk)) {
|
||||
|
|
@ -130,16 +100,14 @@ class Swagger2 extends Format
|
|||
}
|
||||
|
||||
$additionalMethods = null;
|
||||
if (is_array($sdk)) {
|
||||
$mainSdk = array_shift($sdk);
|
||||
if (\is_array($sdk)) {
|
||||
$additionalMethods = $sdk;
|
||||
|
||||
$sdk = $mainSdk;
|
||||
$sdk = $sdk[0];
|
||||
}
|
||||
|
||||
$consumes = [];
|
||||
if (strtoupper($route->getMethod()) !== 'GET' && strtoupper($route->getMethod()) !== 'HEAD') {
|
||||
$consumes = [$sdk->getRequestType()];
|
||||
$consumes = [$sdk->getRequestType()->value];
|
||||
}
|
||||
|
||||
$method = $sdk->getMethodName() ?? \uniqid();
|
||||
|
|
@ -158,10 +126,8 @@ class Swagger2 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:
|
||||
|
|
@ -208,41 +174,49 @@ class Swagger2 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' => [],
|
||||
'description' => $method->getDescription(),
|
||||
'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' => '#/definitions/' . $response->getModel()
|
||||
];
|
||||
/** @var Response $response */
|
||||
if (\is_array($response->getModel())) {
|
||||
$additionalMethod['responses'][] = [
|
||||
'code' => $response->getCode(),
|
||||
'model' => \array_map(fn ($m) => '#/definitions/' . $m, $response->getModel())
|
||||
];
|
||||
} else {
|
||||
$additionalMethod['responses'][] = [
|
||||
'code' => $response->getCode(),
|
||||
'model' => '#/definitions/' . $response->getModel()
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$temp['x-appwrite']['additional-methods'][] = $additionalMethod;
|
||||
$temp['x-appwrite']['methods'][] = $additionalMethod;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Responses
|
||||
|
||||
foreach ($sdk->getResponses() as $response) {
|
||||
/** @var \Appwrite\SDK\Response $response */
|
||||
/** @var Response $response */
|
||||
$model = $response->getModel();
|
||||
|
||||
foreach ($this->models as $value) {
|
||||
|
|
@ -337,7 +311,9 @@ class Swagger2 extends Format
|
|||
|
||||
foreach ($parameters as $name => $param) { // Set params
|
||||
/** @var Validator $validator */
|
||||
$validator = (\is_callable($param['validator'])) ? call_user_func_array($param['validator'], $this->app->getResources($param['injections'])) : $param['validator'];
|
||||
$validator = (\is_callable($param['validator']))
|
||||
? ($param['validator'])(...$this->app->getResources($param['injections']))
|
||||
: $param['validator'];
|
||||
|
||||
$node = [
|
||||
'name' => $name,
|
||||
|
|
@ -482,7 +458,7 @@ class Swagger2 extends Format
|
|||
$node['type'] = $validator->getType();
|
||||
break;
|
||||
case 'Utopia\Validator\WhiteList':
|
||||
/** @var \Utopia\Validator\WhiteList $validator */
|
||||
/** @var WhiteList $validator */
|
||||
$node['type'] = $validator->getType();
|
||||
$node['x-example'] = $validator->getList()[0];
|
||||
|
||||
|
|
|
|||
127
tests/benchmarks/bulk-operations/LargeDocumentCreation.js
Normal file
127
tests/benchmarks/bulk-operations/LargeDocumentCreation.js
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
import { check, sleep } from "k6";
|
||||
import http from "k6/http";
|
||||
import { provisionProject, provisionDatabase, cleanup, unique } from "./utils.js";
|
||||
|
||||
const millionRecords = 1_000_000;
|
||||
const batchSize = 10_000;
|
||||
const numBatches = millionRecords / batchSize;
|
||||
|
||||
export function setup() {
|
||||
const resources = provisionProject({
|
||||
endpoint: 'http://localhost/v1',
|
||||
email: 'test@test.com',
|
||||
password: 'password123',
|
||||
name: 'Test User',
|
||||
projectName: 'Large Document Creation Test'
|
||||
});
|
||||
|
||||
const { databaseId, collectionId } = provisionDatabase({
|
||||
endpoint: 'http://localhost/v1',
|
||||
apiHeaders: resources.apiHeaders
|
||||
});
|
||||
|
||||
// Wait to ensure that provisioning is complete
|
||||
sleep(5);
|
||||
|
||||
// Create an index for the collection
|
||||
const index = {
|
||||
key: "name",
|
||||
type: "fulltext",
|
||||
orders: ["ASC"],
|
||||
attributes: ["name", "email"]
|
||||
};
|
||||
|
||||
const indexRes = http.post(`http://localhost/v1/databases/${databaseId}/collections/${collectionId}/indexes`,
|
||||
JSON.stringify(index), {
|
||||
headers: resources.apiHeaders
|
||||
});
|
||||
|
||||
console.log(indexRes.status);
|
||||
|
||||
check(indexRes, {
|
||||
"status is 202": (r) => r.status === 202,
|
||||
});
|
||||
|
||||
console.log(`----- Inserting ${millionRecords} documents in ${numBatches} batches of ${batchSize} -----`);
|
||||
|
||||
const timeStart = new Date();
|
||||
|
||||
const requests = [];
|
||||
for (let i = 0; i < numBatches; i++) {
|
||||
const docs = Array.from({ length: batchSize }, () => ({
|
||||
$id: unique(),
|
||||
name: "bulk_document",
|
||||
age: Math.floor(Math.random() * 100),
|
||||
email: `${unique()}@test.com`,
|
||||
height: Math.random() * 100
|
||||
}));
|
||||
requests.push({
|
||||
method: "POST",
|
||||
url: `http://localhost/v1/databases/${databaseId}/collections/${collectionId}/documents`,
|
||||
body: JSON.stringify({ documents: docs }),
|
||||
params: {
|
||||
headers: resources.apiHeaders,
|
||||
timeout: '300s'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const responses = http.batch(requests);
|
||||
responses.forEach((res, index) => {
|
||||
if (res.status !== 201) {
|
||||
throw new Error(`Batch ${index + 1} failed with status ${res.status}`);
|
||||
}
|
||||
});
|
||||
|
||||
const timeEnd = new Date();
|
||||
const timeTaken = timeEnd - timeStart;
|
||||
console.log(`Created 1 million documents in ${timeTaken} milliseconds`);
|
||||
|
||||
return {
|
||||
databaseId,
|
||||
collectionId,
|
||||
apiHeaders: resources.apiHeaders,
|
||||
resources
|
||||
};
|
||||
}
|
||||
|
||||
export default function (data) {
|
||||
const docs = Array.from({ length: 10000 }, () => ({
|
||||
$id: unique(),
|
||||
name: "performance_document",
|
||||
age: Math.floor(Math.random() * 100),
|
||||
email: `${unique()}@test.com`,
|
||||
height: Math.random() * 100
|
||||
}));
|
||||
|
||||
const payload = JSON.stringify({ documents: docs });
|
||||
const res = http.post(
|
||||
`http://localhost/v1/databases/${data.databaseId}/collections/${data.collectionId}/documents`,
|
||||
payload,
|
||||
{
|
||||
headers: data.apiHeaders,
|
||||
timeout: '300s'
|
||||
}
|
||||
);
|
||||
|
||||
check(res, {
|
||||
"status is 201": (r) => r.status === 201
|
||||
});
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
export function teardown(data) {
|
||||
cleanup(data.resources);
|
||||
}
|
||||
|
||||
export const options = {
|
||||
scenarios: {
|
||||
large_document_creation: {
|
||||
executor: 'per-vu-iterations',
|
||||
vus: 1,
|
||||
iterations: 20,
|
||||
exec: 'default'
|
||||
}
|
||||
}
|
||||
};
|
||||
82
tests/benchmarks/bulk-operations/documentCreation.js
Normal file
82
tests/benchmarks/bulk-operations/documentCreation.js
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
import { check, sleep } from "k6";
|
||||
import http from "k6/http";
|
||||
import { provisionProject, provisionDatabase, cleanup, unique } from "./utils.js";
|
||||
|
||||
const amount = 10_000;
|
||||
|
||||
export function setup() {
|
||||
const resources = provisionProject({
|
||||
endpoint: 'http://localhost/v1',
|
||||
email: 'test@test.com',
|
||||
password: 'password123',
|
||||
name: 'Test User',
|
||||
projectName: 'Bulk Operations Test'
|
||||
});
|
||||
|
||||
const { databaseId, collectionId } = provisionDatabase({
|
||||
endpoint: 'http://localhost/v1',
|
||||
apiHeaders: resources.apiHeaders
|
||||
});
|
||||
|
||||
sleep(3); // Await Attributes to be provisioned
|
||||
|
||||
console.log(`----- Amount of documents: ${amount} -----`);
|
||||
|
||||
return {
|
||||
databaseId,
|
||||
collectionId,
|
||||
apiHeaders: resources.apiHeaders,
|
||||
resources
|
||||
};
|
||||
}
|
||||
|
||||
export function teardown(data) {
|
||||
cleanup(data.resources);
|
||||
}
|
||||
|
||||
let documents = Array(amount).fill({
|
||||
$id: "unique()",
|
||||
name: "asd",
|
||||
});
|
||||
|
||||
documents = documents.map((document) => {
|
||||
return {
|
||||
...document,
|
||||
age: Math.floor(Math.random() * 100),
|
||||
email: `${unique()}@test.com`,
|
||||
height: Math.random() * 100,
|
||||
};
|
||||
});
|
||||
|
||||
export default function (data) {
|
||||
const payload = JSON.stringify({
|
||||
documents,
|
||||
});
|
||||
|
||||
const res = http.post(
|
||||
`http://localhost/v1/databases/${data.databaseId}/collections/${data.collectionId}/documents`,
|
||||
payload,
|
||||
{
|
||||
headers: data.apiHeaders
|
||||
}
|
||||
);
|
||||
|
||||
check(res, {
|
||||
"status is 201": (r) => r.status === 201,
|
||||
});
|
||||
|
||||
return {
|
||||
resources: data.resources
|
||||
};
|
||||
}
|
||||
|
||||
export const options = {
|
||||
scenarios: {
|
||||
bulk_create: {
|
||||
executor: 'per-vu-iterations',
|
||||
vus: 1,
|
||||
iterations: 20,
|
||||
exec: 'default'
|
||||
}
|
||||
}
|
||||
};
|
||||
144
tests/benchmarks/bulk-operations/noisyNeighbor.js
Normal file
144
tests/benchmarks/bulk-operations/noisyNeighbor.js
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
import { check, sleep } from "k6";
|
||||
import http from "k6/http";
|
||||
import { Trend } from "k6/metrics";
|
||||
import { provisionProject, provisionDatabase, cleanup, unique } from "./utils.js";
|
||||
|
||||
// Custom Trend metric for light response time tracking
|
||||
export const lightResponseTime = new Trend("light_response_time", true);
|
||||
|
||||
const BULK_AMOUNT = 100_000; // Heavy operation amount
|
||||
const LIGHT_AMOUNT = 10; // Light operation amount
|
||||
|
||||
export function setup() {
|
||||
// Set up two separate projects - one for bulk operations (noisy neighbor) and one for light operations
|
||||
const heavyResources = provisionProject({
|
||||
endpoint: 'http://localhost/v1',
|
||||
email: 'heavy@test.com',
|
||||
password: 'password123',
|
||||
name: 'Heavy User',
|
||||
projectName: 'Noisy Neighbor - Heavy'
|
||||
});
|
||||
|
||||
const lightResources = provisionProject({
|
||||
endpoint: 'http://localhost/v1',
|
||||
email: 'light@test.com',
|
||||
password: 'password123',
|
||||
name: 'Light User',
|
||||
projectName: 'Noisy Neighbor - Light'
|
||||
});
|
||||
|
||||
// Set up databases for both projects
|
||||
const heavy = provisionDatabase({
|
||||
endpoint: 'http://localhost/v1',
|
||||
apiHeaders: heavyResources.apiHeaders
|
||||
});
|
||||
|
||||
const light = provisionDatabase({
|
||||
endpoint: 'http://localhost/v1',
|
||||
apiHeaders: lightResources.apiHeaders
|
||||
});
|
||||
|
||||
sleep(3); // Await Attributes to be provisioned
|
||||
|
||||
console.log(`----- Heavy operations: ${BULK_AMOUNT} documents | Light operations: ${LIGHT_AMOUNT} document -----`);
|
||||
|
||||
return {
|
||||
heavy: {
|
||||
databaseId: heavy.databaseId,
|
||||
collectionId: heavy.collectionId,
|
||||
apiHeaders: heavyResources.apiHeaders,
|
||||
resources: heavyResources
|
||||
},
|
||||
light: {
|
||||
databaseId: light.databaseId,
|
||||
collectionId: light.collectionId,
|
||||
apiHeaders: lightResources.apiHeaders,
|
||||
resources: lightResources
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function teardown(data) {
|
||||
cleanup(data.heavy.resources);
|
||||
cleanup(data.light.resources);
|
||||
}
|
||||
|
||||
// Create document payloads
|
||||
function createDocuments(amount) {
|
||||
let documents = Array(amount).fill({
|
||||
$id: "unique()",
|
||||
name: "test",
|
||||
});
|
||||
|
||||
return documents.map((document) => ({
|
||||
...document,
|
||||
age: Math.floor(Math.random() * 100),
|
||||
email: `${unique()}@test.com`,
|
||||
height: Math.random() * 100,
|
||||
}));
|
||||
}
|
||||
|
||||
// Heavy operation function
|
||||
export function heavy(data) {
|
||||
const documents = createDocuments(BULK_AMOUNT);
|
||||
const payload = JSON.stringify({ documents });
|
||||
|
||||
const res = http.post(
|
||||
`http://localhost/v1/databases/${data.heavy.databaseId}/collections/${data.heavy.collectionId}/documents`,
|
||||
payload,
|
||||
{
|
||||
headers: data.heavy.apiHeaders
|
||||
}
|
||||
);
|
||||
|
||||
check(res, {
|
||||
"heavy operation status is 201": (r) => r.status === 201,
|
||||
});
|
||||
}
|
||||
|
||||
// Light operation function
|
||||
export function light(data) {
|
||||
const documents = createDocuments(LIGHT_AMOUNT);
|
||||
const payload = JSON.stringify({ documents });
|
||||
|
||||
const startTime = new Date();
|
||||
const res = http.post(
|
||||
`http://localhost/v1/databases/${data.light.databaseId}/collections/${data.light.collectionId}/documents`,
|
||||
payload,
|
||||
{
|
||||
headers: data.light.apiHeaders
|
||||
}
|
||||
);
|
||||
const duration = new Date() - startTime;
|
||||
|
||||
// Record the light operation response time using the custom Trend metric
|
||||
lightResponseTime.add(duration);
|
||||
|
||||
check(res, {
|
||||
"light operation status is 201": (r) => r.status === 201,
|
||||
});
|
||||
}
|
||||
|
||||
export const options = {
|
||||
scenarios: {
|
||||
// Heavy bulk operations running continuously
|
||||
heavy_load: {
|
||||
executor: 'constant-vus',
|
||||
vus: 5,
|
||||
duration: '30s',
|
||||
exec: 'heavy'
|
||||
},
|
||||
// Light operations to measure impact
|
||||
light_operations: {
|
||||
executor: 'constant-arrival-rate',
|
||||
rate: 5,
|
||||
timeUnit: '1s',
|
||||
duration: '30s',
|
||||
preAllocatedVUs: 10,
|
||||
exec: 'light'
|
||||
}
|
||||
},
|
||||
thresholds: {
|
||||
http_req_duration: ['p(95)<2000'], // 95% of requests should complete within 2s
|
||||
}
|
||||
};
|
||||
336
tests/benchmarks/bulk-operations/utils.js
Normal file
336
tests/benchmarks/bulk-operations/utils.js
Normal file
|
|
@ -0,0 +1,336 @@
|
|||
import http from 'k6/http';
|
||||
import { check } from 'k6';
|
||||
|
||||
/**
|
||||
* @typedef {Object} AuthHeaders
|
||||
* @property {string} 'Content-Type' - Content type header
|
||||
* @property {string} 'Cookie' - Session cookie
|
||||
* @property {string} 'X-Appwrite-Project' - Project ID header
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} ApiHeaders
|
||||
* @property {string} 'Content-Type' - Content type header
|
||||
* @property {string} 'X-Appwrite-Project' - Project ID header
|
||||
* @property {string} 'X-Appwrite-Key' - API key header
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} ProvisionedResources
|
||||
* @property {string} userId - The ID of the created user
|
||||
* @property {string} teamId - The ID of the created team
|
||||
* @property {string} projectId - The ID of the created project
|
||||
* @property {string} cookies - Session cookies for authentication
|
||||
* @property {AuthHeaders} headers - Headers for cookie-based authentication
|
||||
* @property {string} apiKey - The API key secret
|
||||
* @property {ApiHeaders} apiHeaders - Headers for API key authentication
|
||||
*/
|
||||
|
||||
function assert(response, checkName, condition) {
|
||||
const result = check(response, {
|
||||
[checkName]: condition
|
||||
});
|
||||
if (!result) {
|
||||
console.error(`Assertion failed: ${checkName}`);
|
||||
console.error(`Response status: ${response.status}`);
|
||||
console.error(`Response body: ${response.body}`);
|
||||
throw new Error(`Assertion failed: ${checkName}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provisions an Appwrite project setup including:
|
||||
* - Account creation
|
||||
* - Session creation
|
||||
* - Team creation
|
||||
* - Project creation
|
||||
* - API Key creation
|
||||
*
|
||||
* @param {Object} config Configuration object
|
||||
* @param {string} config.endpoint Base endpoint URL (e.g., 'http://localhost:80/v1')
|
||||
* @param {string} config.email Email for account creation
|
||||
* @param {string} config.password Password for account creation
|
||||
* @param {string} config.name Name for account creation
|
||||
* @param {string} config.projectName Name for the project
|
||||
* @returns {ProvisionedResources} Object containing all created resource IDs and session information
|
||||
*/
|
||||
export function provisionProject(config) {
|
||||
const {
|
||||
endpoint,
|
||||
email,
|
||||
password,
|
||||
name,
|
||||
projectName,
|
||||
} = config;
|
||||
|
||||
// Step 1: Create Account
|
||||
const accountResponse = http.post(`${endpoint}/account`, JSON.stringify({
|
||||
userId: 'unique()',
|
||||
email,
|
||||
password,
|
||||
name
|
||||
}), {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
});
|
||||
|
||||
assert(accountResponse, 'account created successfully', (r) => r.status === 201 || r.status === 409);
|
||||
|
||||
const userId = accountResponse.json('$id');
|
||||
|
||||
// Step 2: Create Session
|
||||
const sessionResponse = http.post(`${endpoint}/account/sessions/email`, JSON.stringify({
|
||||
email,
|
||||
password
|
||||
}), {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
});
|
||||
|
||||
assert(sessionResponse, 'session created successfully', (r) => r.status === 201);
|
||||
|
||||
// Keep manual control of the cookies to allow for simultaneous requests
|
||||
const jar = http.cookieJar();
|
||||
jar.clear(`${endpoint}`);
|
||||
|
||||
// Extract cookies for subsequent requests
|
||||
const cookies = sessionResponse.headers['Set-Cookie'];
|
||||
|
||||
// Common headers for authenticated requests
|
||||
const authHeaders = {
|
||||
'Content-Type': 'application/json',
|
||||
'Cookie': cookies
|
||||
};
|
||||
|
||||
// Step 3: Create Team
|
||||
const teamResponse = http.post(`${endpoint}/teams`, JSON.stringify({
|
||||
teamId: 'unique()',
|
||||
name: `${projectName} Team`
|
||||
}), {
|
||||
headers: authHeaders
|
||||
});
|
||||
|
||||
assert(teamResponse, 'team created successfully', (r) => r.status === 201);
|
||||
|
||||
const teamId = teamResponse.json('$id');
|
||||
|
||||
// Step 4: Create Project
|
||||
const projectResponse = http.post(`${endpoint}/projects`, JSON.stringify({
|
||||
projectId: 'unique()',
|
||||
name: projectName,
|
||||
teamId: teamId
|
||||
}), {
|
||||
headers: authHeaders
|
||||
});
|
||||
|
||||
assert(projectResponse, 'project created successfully', (r) => r.status === 201);
|
||||
|
||||
const projectId = projectResponse.json('$id');
|
||||
|
||||
// Step 5: Create API Key
|
||||
const apiKeyResponse = http.post(`${endpoint}/projects/${projectId}/keys`, JSON.stringify({
|
||||
name: 'Test API Key',
|
||||
scopes: SCOPES, // All permissions
|
||||
}), {
|
||||
headers: authHeaders
|
||||
});
|
||||
|
||||
assert(apiKeyResponse, 'api key created successfully', (r) => r.status === 201);
|
||||
|
||||
const apiKey = apiKeyResponse.json('secret');
|
||||
|
||||
// Create a new headers object for API key authentication
|
||||
const apiHeaders = {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Appwrite-Project': projectId,
|
||||
'X-Appwrite-Key': apiKey
|
||||
};
|
||||
|
||||
// Return all created resources and session info
|
||||
return {
|
||||
endpoint,
|
||||
userId,
|
||||
teamId,
|
||||
projectId,
|
||||
cookies,
|
||||
headers: authHeaders,
|
||||
apiKey,
|
||||
apiHeaders
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Example usage:
|
||||
*
|
||||
* const config = {
|
||||
* endpoint: 'http://localhost:80/v1',
|
||||
* email: 'test@example.com',
|
||||
* password: 'complex-password',
|
||||
* name: 'Test User',
|
||||
* projectName: 'Test Project'
|
||||
* };
|
||||
*
|
||||
* const resources = provisionProject(config);
|
||||
*/
|
||||
|
||||
const SCOPES = [
|
||||
"sessions.write",
|
||||
"users.read",
|
||||
"users.write",
|
||||
"teams.read",
|
||||
"teams.write",
|
||||
"databases.read",
|
||||
"databases.write",
|
||||
"collections.read",
|
||||
"collections.write",
|
||||
"attributes.read",
|
||||
"attributes.write",
|
||||
"indexes.read",
|
||||
"indexes.write",
|
||||
"documents.read",
|
||||
"documents.write",
|
||||
"files.read",
|
||||
"files.write",
|
||||
"buckets.read",
|
||||
"buckets.write",
|
||||
"functions.read",
|
||||
"functions.write",
|
||||
"execution.read",
|
||||
"execution.write",
|
||||
"targets.read",
|
||||
"targets.write",
|
||||
"providers.read",
|
||||
"providers.write",
|
||||
"messages.read",
|
||||
"messages.write",
|
||||
"topics.read",
|
||||
"topics.write",
|
||||
"subscribers.read",
|
||||
"subscribers.write",
|
||||
"locale.read",
|
||||
"avatars.read",
|
||||
"health.read",
|
||||
"migrations.read",
|
||||
"migrations.write"
|
||||
]
|
||||
|
||||
export function provisionDatabase(config) {
|
||||
const {
|
||||
endpoint,
|
||||
apiHeaders
|
||||
} = config;
|
||||
|
||||
// Create database
|
||||
const databaseResponse = http.post(
|
||||
`${endpoint}/databases`,
|
||||
JSON.stringify({
|
||||
databaseId: 'unique()',
|
||||
name: 'Bulk Test DB'
|
||||
}),
|
||||
{ headers: apiHeaders }
|
||||
);
|
||||
|
||||
assert(databaseResponse, 'database created successfully', (r) => r.status === 201);
|
||||
|
||||
const databaseId = databaseResponse.json('$id');
|
||||
|
||||
// Create collection
|
||||
const collectionResponse = http.post(
|
||||
`${endpoint}/databases/${databaseId}/collections`,
|
||||
JSON.stringify({
|
||||
collectionId: 'unique()',
|
||||
name: 'Bulk Test Collection',
|
||||
permissions: ['read("any")', 'write("any")'],
|
||||
documentSecurity: false
|
||||
}),
|
||||
{ headers: apiHeaders }
|
||||
);
|
||||
|
||||
assert(collectionResponse, 'collection created successfully', (r) => r.status === 201);
|
||||
|
||||
const collectionId = collectionResponse.json('$id');
|
||||
|
||||
// Create name attribute
|
||||
const nameAttributeResponse = http.post(
|
||||
`${endpoint}/databases/${databaseId}/collections/${collectionId}/attributes/string`,
|
||||
JSON.stringify({
|
||||
key: 'name',
|
||||
size: 100,
|
||||
required: false,
|
||||
default: null,
|
||||
array: false,
|
||||
encrypt: false
|
||||
}),
|
||||
{ headers: apiHeaders }
|
||||
);
|
||||
|
||||
assert(nameAttributeResponse, 'name attribute created successfully', (r) => r.status === 202);
|
||||
|
||||
// Create age attribute
|
||||
const ageAttributeResponse = http.post(
|
||||
`${endpoint}/databases/${databaseId}/collections/${collectionId}/attributes/integer`,
|
||||
JSON.stringify({
|
||||
key: 'age',
|
||||
required: false,
|
||||
}),
|
||||
{ headers: apiHeaders }
|
||||
);
|
||||
|
||||
assert(ageAttributeResponse, 'age attribute created successfully', (r) => r.status === 202);
|
||||
|
||||
// Create email attribute
|
||||
const emailAttributeResponse = http.post(
|
||||
`${endpoint}/databases/${databaseId}/collections/${collectionId}/attributes/email`,
|
||||
JSON.stringify({
|
||||
key: 'email',
|
||||
required: false,
|
||||
}),
|
||||
{ headers: apiHeaders }
|
||||
);
|
||||
|
||||
assert(emailAttributeResponse, 'email attribute created successfully', (r) => r.status === 202);
|
||||
|
||||
// Create height attribute
|
||||
const heightAttributeResponse = http.post(
|
||||
`${endpoint}/databases/${databaseId}/collections/${collectionId}/attributes/float`,
|
||||
JSON.stringify({
|
||||
key: 'height',
|
||||
required: false,
|
||||
}),
|
||||
{ headers: apiHeaders }
|
||||
);
|
||||
|
||||
assert(heightAttributeResponse, 'height attribute created successfully', (r) => r.status === 202);
|
||||
|
||||
return {
|
||||
databaseId,
|
||||
collectionId
|
||||
};
|
||||
}
|
||||
|
||||
export function cleanup(config) {
|
||||
const {
|
||||
endpoint,
|
||||
teamId,
|
||||
headers
|
||||
} = config;
|
||||
|
||||
// Delete Organization
|
||||
const organizationResponse = http.del(
|
||||
`${endpoint}/teams/${teamId}`,
|
||||
null,
|
||||
{
|
||||
headers
|
||||
}
|
||||
);
|
||||
|
||||
assert(organizationResponse, 'organization deleted successfully', (r) => r.status === 204);
|
||||
}
|
||||
|
||||
export function unique() {
|
||||
const timestamp = Date.now().toString(36);
|
||||
const randomPart = Math.random().toString(36).substring(2, 15);
|
||||
return `${timestamp}-${randomPart}`;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue