Merge remote-tracking branch 'upstream/1.8.x' into spatial-type-attributes

This commit is contained in:
ArnabChatterjee20k 2025-09-02 23:04:12 +05:30
commit b01f146b1c
31 changed files with 368 additions and 219 deletions

View file

@ -5146,7 +5146,7 @@
]
},
"put": {
"summary": "Create or update a document",
"summary": "Upsert a document",
"operationId": "databasesUpsertDocument",
"tags": [
"databases"
@ -5881,7 +5881,7 @@
},
"method": {
"type": "string",
"description": "HTTP method of execution. Default value is GET.",
"description": "HTTP method of execution. Default value is POST.",
"x-example": "GET",
"enum": [
"GET",
@ -5889,7 +5889,8 @@
"PUT",
"PATCH",
"DELETE",
"OPTIONS"
"OPTIONS",
"HEAD"
],
"x-enum-name": "ExecutionMethod",
"x-enum-keys": []
@ -7624,7 +7625,7 @@
}
],
"description": "Create a new Row. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/create-row.md"
"demo": "tablesdb\/create-row.md"
}
],
"auth": {
@ -7799,7 +7800,7 @@
]
},
"put": {
"summary": "Create or update a row",
"summary": "Upsert a row",
"operationId": "tablesDBUpsertRow",
"tags": [
"tablesDB"
@ -7866,7 +7867,7 @@
}
],
"description": "Create or update a Row. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/upsert-row.md"
"demo": "tablesdb\/upsert-row.md"
}
],
"auth": {

View file

@ -8940,7 +8940,7 @@
}
},
"put": {
"summary": "Create or update documents",
"summary": "Upsert documents",
"operationId": "databasesUpsertDocuments",
"tags": [
"databases"
@ -9360,7 +9360,7 @@
]
},
"put": {
"summary": "Create or update a document",
"summary": "Upsert a document",
"operationId": "databasesUpsertDocument",
"tags": [
"databases"
@ -12791,7 +12791,7 @@
},
"method": {
"type": "string",
"description": "HTTP method of execution. Default value is GET.",
"description": "HTTP method of execution. Default value is POST.",
"x-example": "GET",
"enum": [
"GET",
@ -12799,7 +12799,8 @@
"PUT",
"PATCH",
"DELETE",
"OPTIONS"
"OPTIONS",
"HEAD"
],
"x-enum-name": "ExecutionMethod",
"x-enum-keys": []
@ -32188,7 +32189,7 @@
}
],
"description": "List usage metrics and statistics for all databases in the project. You can view the total number of databases, tables, rows, and storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.",
"demo": "tables-db\/list-usage.md"
"demo": "tablesdb\/list-usage.md"
}
],
"auth": {
@ -32445,7 +32446,7 @@
"deprecated": false,
"x-appwrite": {
"method": "listTables",
"group": null,
"group": "tables",
"weight": 382,
"cookies": false,
"type": "",
@ -32531,7 +32532,7 @@
"deprecated": false,
"x-appwrite": {
"method": "createTable",
"group": null,
"group": "tables",
"weight": 378,
"cookies": false,
"type": "",
@ -32638,7 +32639,7 @@
"deprecated": false,
"x-appwrite": {
"method": "getTable",
"group": null,
"group": "tables",
"weight": 379,
"cookies": false,
"type": "",
@ -32710,7 +32711,7 @@
"deprecated": false,
"x-appwrite": {
"method": "updateTable",
"group": null,
"group": "tables",
"weight": 380,
"cookies": false,
"type": "",
@ -32812,7 +32813,7 @@
"deprecated": false,
"x-appwrite": {
"method": "deleteTable",
"group": null,
"group": "tables",
"weight": 381,
"cookies": false,
"type": "",
@ -36081,7 +36082,7 @@
}
],
"description": "Create a new Row. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/create-row.md"
"demo": "tablesdb\/create-row.md"
},
{
"name": "createRows",
@ -36107,7 +36108,7 @@
}
],
"description": "Create new Rows. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/create-rows.md"
"demo": "tablesdb\/create-rows.md"
}
],
"auth": {
@ -36182,7 +36183,7 @@
}
},
"put": {
"summary": "Create or update rows",
"summary": "Upsert rows",
"operationId": "tablesDBUpsertRows",
"tags": [
"tablesDB"
@ -36246,7 +36247,7 @@
}
],
"description": "Create or update Rows. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.\n",
"demo": "tables-db\/upsert-rows.md"
"demo": "tablesdb\/upsert-rows.md"
}
],
"auth": {
@ -36594,7 +36595,7 @@
]
},
"put": {
"summary": "Create or update a row",
"summary": "Upsert a row",
"operationId": "tablesDBUpsertRow",
"tags": [
"tablesDB"
@ -36661,7 +36662,7 @@
}
],
"description": "Create or update a Row. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/upsert-row.md"
"demo": "tablesdb\/upsert-row.md"
}
],
"auth": {
@ -37409,7 +37410,7 @@
}
],
"description": "Get usage metrics and statistics for a database. You can view the total number of tables, rows, and storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.",
"demo": "tables-db\/get-usage.md"
"demo": "tablesdb\/get-usage.md"
}
],
"auth": {

View file

@ -8416,7 +8416,7 @@
}
},
"put": {
"summary": "Create or update documents",
"summary": "Upsert documents",
"operationId": "databasesUpsertDocuments",
"tags": [
"databases"
@ -8842,7 +8842,7 @@
]
},
"put": {
"summary": "Create or update a document",
"summary": "Upsert a document",
"operationId": "databasesUpsertDocument",
"tags": [
"databases"
@ -11576,7 +11576,7 @@
},
"method": {
"type": "string",
"description": "HTTP method of execution. Default value is GET.",
"description": "HTTP method of execution. Default value is POST.",
"x-example": "GET",
"enum": [
"GET",
@ -11584,7 +11584,8 @@
"PUT",
"PATCH",
"DELETE",
"OPTIONS"
"OPTIONS",
"HEAD"
],
"x-enum-name": "ExecutionMethod",
"x-enum-keys": []
@ -22852,7 +22853,7 @@
"deprecated": false,
"x-appwrite": {
"method": "listTables",
"group": null,
"group": "tables",
"weight": 382,
"cookies": false,
"type": "",
@ -22939,7 +22940,7 @@
"deprecated": false,
"x-appwrite": {
"method": "createTable",
"group": null,
"group": "tables",
"weight": 378,
"cookies": false,
"type": "",
@ -23047,7 +23048,7 @@
"deprecated": false,
"x-appwrite": {
"method": "getTable",
"group": null,
"group": "tables",
"weight": 379,
"cookies": false,
"type": "",
@ -23120,7 +23121,7 @@
"deprecated": false,
"x-appwrite": {
"method": "updateTable",
"group": null,
"group": "tables",
"weight": 380,
"cookies": false,
"type": "",
@ -23223,7 +23224,7 @@
"deprecated": false,
"x-appwrite": {
"method": "deleteTable",
"group": null,
"group": "tables",
"weight": 381,
"cookies": false,
"type": "",
@ -26437,7 +26438,7 @@
}
],
"description": "Create a new Row. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/create-row.md"
"demo": "tablesdb\/create-row.md"
},
{
"name": "createRows",
@ -26464,7 +26465,7 @@
}
],
"description": "Create new Rows. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/create-rows.md"
"demo": "tablesdb\/create-rows.md"
}
],
"auth": {
@ -26541,7 +26542,7 @@
}
},
"put": {
"summary": "Create or update rows",
"summary": "Upsert rows",
"operationId": "tablesDBUpsertRows",
"tags": [
"tablesDB"
@ -26606,7 +26607,7 @@
}
],
"description": "Create or update Rows. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.\n",
"demo": "tables-db\/upsert-rows.md"
"demo": "tablesdb\/upsert-rows.md"
}
],
"auth": {
@ -26959,7 +26960,7 @@
]
},
"put": {
"summary": "Create or update a row",
"summary": "Upsert a row",
"operationId": "tablesDBUpsertRow",
"tags": [
"tablesDB"
@ -27027,7 +27028,7 @@
}
],
"description": "Create or update a Row. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/upsert-row.md"
"demo": "tablesdb\/upsert-row.md"
}
],
"auth": {

View file

@ -5146,7 +5146,7 @@
]
},
"put": {
"summary": "Create or update a document",
"summary": "Upsert a document",
"operationId": "databasesUpsertDocument",
"tags": [
"databases"
@ -5881,7 +5881,7 @@
},
"method": {
"type": "string",
"description": "HTTP method of execution. Default value is GET.",
"description": "HTTP method of execution. Default value is POST.",
"x-example": "GET",
"enum": [
"GET",
@ -5889,7 +5889,8 @@
"PUT",
"PATCH",
"DELETE",
"OPTIONS"
"OPTIONS",
"HEAD"
],
"x-enum-name": "ExecutionMethod",
"x-enum-keys": []
@ -7624,7 +7625,7 @@
}
],
"description": "Create a new Row. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/create-row.md"
"demo": "tablesdb\/create-row.md"
}
],
"auth": {
@ -7799,7 +7800,7 @@
]
},
"put": {
"summary": "Create or update a row",
"summary": "Upsert a row",
"operationId": "tablesDBUpsertRow",
"tags": [
"tablesDB"
@ -7866,7 +7867,7 @@
}
],
"description": "Create or update a Row. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/upsert-row.md"
"demo": "tablesdb\/upsert-row.md"
}
],
"auth": {

View file

@ -8940,7 +8940,7 @@
}
},
"put": {
"summary": "Create or update documents",
"summary": "Upsert documents",
"operationId": "databasesUpsertDocuments",
"tags": [
"databases"
@ -9360,7 +9360,7 @@
]
},
"put": {
"summary": "Create or update a document",
"summary": "Upsert a document",
"operationId": "databasesUpsertDocument",
"tags": [
"databases"
@ -12791,7 +12791,7 @@
},
"method": {
"type": "string",
"description": "HTTP method of execution. Default value is GET.",
"description": "HTTP method of execution. Default value is POST.",
"x-example": "GET",
"enum": [
"GET",
@ -12799,7 +12799,8 @@
"PUT",
"PATCH",
"DELETE",
"OPTIONS"
"OPTIONS",
"HEAD"
],
"x-enum-name": "ExecutionMethod",
"x-enum-keys": []
@ -32188,7 +32189,7 @@
}
],
"description": "List usage metrics and statistics for all databases in the project. You can view the total number of databases, tables, rows, and storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.",
"demo": "tables-db\/list-usage.md"
"demo": "tablesdb\/list-usage.md"
}
],
"auth": {
@ -32445,7 +32446,7 @@
"deprecated": false,
"x-appwrite": {
"method": "listTables",
"group": null,
"group": "tables",
"weight": 382,
"cookies": false,
"type": "",
@ -32531,7 +32532,7 @@
"deprecated": false,
"x-appwrite": {
"method": "createTable",
"group": null,
"group": "tables",
"weight": 378,
"cookies": false,
"type": "",
@ -32638,7 +32639,7 @@
"deprecated": false,
"x-appwrite": {
"method": "getTable",
"group": null,
"group": "tables",
"weight": 379,
"cookies": false,
"type": "",
@ -32710,7 +32711,7 @@
"deprecated": false,
"x-appwrite": {
"method": "updateTable",
"group": null,
"group": "tables",
"weight": 380,
"cookies": false,
"type": "",
@ -32812,7 +32813,7 @@
"deprecated": false,
"x-appwrite": {
"method": "deleteTable",
"group": null,
"group": "tables",
"weight": 381,
"cookies": false,
"type": "",
@ -36081,7 +36082,7 @@
}
],
"description": "Create a new Row. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/create-row.md"
"demo": "tablesdb\/create-row.md"
},
{
"name": "createRows",
@ -36107,7 +36108,7 @@
}
],
"description": "Create new Rows. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/create-rows.md"
"demo": "tablesdb\/create-rows.md"
}
],
"auth": {
@ -36182,7 +36183,7 @@
}
},
"put": {
"summary": "Create or update rows",
"summary": "Upsert rows",
"operationId": "tablesDBUpsertRows",
"tags": [
"tablesDB"
@ -36246,7 +36247,7 @@
}
],
"description": "Create or update Rows. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.\n",
"demo": "tables-db\/upsert-rows.md"
"demo": "tablesdb\/upsert-rows.md"
}
],
"auth": {
@ -36594,7 +36595,7 @@
]
},
"put": {
"summary": "Create or update a row",
"summary": "Upsert a row",
"operationId": "tablesDBUpsertRow",
"tags": [
"tablesDB"
@ -36661,7 +36662,7 @@
}
],
"description": "Create or update a Row. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/upsert-row.md"
"demo": "tablesdb\/upsert-row.md"
}
],
"auth": {
@ -37409,7 +37410,7 @@
}
],
"description": "Get usage metrics and statistics for a database. You can view the total number of tables, rows, and storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.",
"demo": "tables-db\/get-usage.md"
"demo": "tablesdb\/get-usage.md"
}
],
"auth": {

View file

@ -8416,7 +8416,7 @@
}
},
"put": {
"summary": "Create or update documents",
"summary": "Upsert documents",
"operationId": "databasesUpsertDocuments",
"tags": [
"databases"
@ -8842,7 +8842,7 @@
]
},
"put": {
"summary": "Create or update a document",
"summary": "Upsert a document",
"operationId": "databasesUpsertDocument",
"tags": [
"databases"
@ -11576,7 +11576,7 @@
},
"method": {
"type": "string",
"description": "HTTP method of execution. Default value is GET.",
"description": "HTTP method of execution. Default value is POST.",
"x-example": "GET",
"enum": [
"GET",
@ -11584,7 +11584,8 @@
"PUT",
"PATCH",
"DELETE",
"OPTIONS"
"OPTIONS",
"HEAD"
],
"x-enum-name": "ExecutionMethod",
"x-enum-keys": []
@ -22852,7 +22853,7 @@
"deprecated": false,
"x-appwrite": {
"method": "listTables",
"group": null,
"group": "tables",
"weight": 382,
"cookies": false,
"type": "",
@ -22939,7 +22940,7 @@
"deprecated": false,
"x-appwrite": {
"method": "createTable",
"group": null,
"group": "tables",
"weight": 378,
"cookies": false,
"type": "",
@ -23047,7 +23048,7 @@
"deprecated": false,
"x-appwrite": {
"method": "getTable",
"group": null,
"group": "tables",
"weight": 379,
"cookies": false,
"type": "",
@ -23120,7 +23121,7 @@
"deprecated": false,
"x-appwrite": {
"method": "updateTable",
"group": null,
"group": "tables",
"weight": 380,
"cookies": false,
"type": "",
@ -23223,7 +23224,7 @@
"deprecated": false,
"x-appwrite": {
"method": "deleteTable",
"group": null,
"group": "tables",
"weight": 381,
"cookies": false,
"type": "",
@ -26437,7 +26438,7 @@
}
],
"description": "Create a new Row. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/create-row.md"
"demo": "tablesdb\/create-row.md"
},
{
"name": "createRows",
@ -26464,7 +26465,7 @@
}
],
"description": "Create new Rows. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/create-rows.md"
"demo": "tablesdb\/create-rows.md"
}
],
"auth": {
@ -26541,7 +26542,7 @@
}
},
"put": {
"summary": "Create or update rows",
"summary": "Upsert rows",
"operationId": "tablesDBUpsertRows",
"tags": [
"tablesDB"
@ -26606,7 +26607,7 @@
}
],
"description": "Create or update Rows. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.\n",
"demo": "tables-db\/upsert-rows.md"
"demo": "tablesdb\/upsert-rows.md"
}
],
"auth": {
@ -26959,7 +26960,7 @@
]
},
"put": {
"summary": "Create or update a row",
"summary": "Upsert a row",
"operationId": "tablesDBUpsertRow",
"tags": [
"tablesDB"
@ -27027,7 +27028,7 @@
}
],
"description": "Create or update a Row. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/upsert-row.md"
"demo": "tablesdb\/upsert-row.md"
}
],
"auth": {

View file

@ -5273,7 +5273,7 @@
]
},
"put": {
"summary": "Create or update a document",
"summary": "Upsert a document",
"operationId": "databasesUpsertDocument",
"consumes": [
"application\/json"
@ -5978,7 +5978,7 @@
},
"method": {
"type": "string",
"description": "HTTP method of execution. Default value is GET.",
"description": "HTTP method of execution. Default value is POST.",
"default": "POST",
"x-example": "GET",
"enum": [
@ -5987,7 +5987,8 @@
"PUT",
"PATCH",
"DELETE",
"OPTIONS"
"OPTIONS",
"HEAD"
],
"x-enum-name": "ExecutionMethod",
"x-enum-keys": []
@ -7701,7 +7702,7 @@
}
],
"description": "Create a new Row. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/create-row.md"
"demo": "tablesdb\/create-row.md"
}
],
"auth": {
@ -7866,7 +7867,7 @@
]
},
"put": {
"summary": "Create or update a row",
"summary": "Upsert a row",
"operationId": "tablesDBUpsertRow",
"consumes": [
"application\/json"
@ -7934,7 +7935,7 @@
}
],
"description": "Create or update a Row. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/upsert-row.md"
"demo": "tablesdb\/upsert-row.md"
}
],
"auth": {

View file

@ -9058,7 +9058,7 @@
]
},
"put": {
"summary": "Create or update documents",
"summary": "Upsert documents",
"operationId": "databasesUpsertDocuments",
"consumes": [
"application\/json"
@ -9462,7 +9462,7 @@
]
},
"put": {
"summary": "Create or update a document",
"summary": "Upsert a document",
"operationId": "databasesUpsertDocument",
"consumes": [
"application\/json"
@ -12836,7 +12836,7 @@
},
"method": {
"type": "string",
"description": "HTTP method of execution. Default value is GET.",
"description": "HTTP method of execution. Default value is POST.",
"default": "POST",
"x-example": "GET",
"enum": [
@ -12845,7 +12845,8 @@
"PUT",
"PATCH",
"DELETE",
"OPTIONS"
"OPTIONS",
"HEAD"
],
"x-enum-name": "ExecutionMethod",
"x-enum-keys": []
@ -32372,7 +32373,7 @@
}
],
"description": "List usage metrics and statistics for all databases in the project. You can view the total number of databases, tables, rows, and storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.",
"demo": "tables-db\/list-usage.md"
"demo": "tablesdb\/list-usage.md"
}
],
"auth": {
@ -32627,7 +32628,7 @@
"deprecated": false,
"x-appwrite": {
"method": "listTables",
"group": null,
"group": "tables",
"weight": 382,
"cookies": false,
"type": "",
@ -32710,7 +32711,7 @@
"deprecated": false,
"x-appwrite": {
"method": "createTable",
"group": null,
"group": "tables",
"weight": 378,
"cookies": false,
"type": "",
@ -32818,7 +32819,7 @@
"deprecated": false,
"x-appwrite": {
"method": "getTable",
"group": null,
"group": "tables",
"weight": 379,
"cookies": false,
"type": "",
@ -32888,7 +32889,7 @@
"deprecated": false,
"x-appwrite": {
"method": "updateTable",
"group": null,
"group": "tables",
"weight": 380,
"cookies": false,
"type": "",
@ -32992,7 +32993,7 @@
"deprecated": false,
"x-appwrite": {
"method": "deleteTable",
"group": null,
"group": "tables",
"weight": 381,
"cookies": false,
"type": "",
@ -36206,7 +36207,7 @@
}
],
"description": "Create a new Row. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/create-row.md"
"demo": "tablesdb\/create-row.md"
},
{
"name": "createRows",
@ -36232,7 +36233,7 @@
}
],
"description": "Create new Rows. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/create-rows.md"
"demo": "tablesdb\/create-rows.md"
}
],
"auth": {
@ -36305,7 +36306,7 @@
]
},
"put": {
"summary": "Create or update rows",
"summary": "Upsert rows",
"operationId": "tablesDBUpsertRows",
"consumes": [
"application\/json"
@ -36371,7 +36372,7 @@
}
],
"description": "Create or update Rows. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.\n",
"demo": "tables-db\/upsert-rows.md"
"demo": "tablesdb\/upsert-rows.md"
}
],
"auth": {
@ -36701,7 +36702,7 @@
]
},
"put": {
"summary": "Create or update a row",
"summary": "Upsert a row",
"operationId": "tablesDBUpsertRow",
"consumes": [
"application\/json"
@ -36769,7 +36770,7 @@
}
],
"description": "Create or update a Row. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/upsert-row.md"
"demo": "tablesdb\/upsert-row.md"
}
],
"auth": {
@ -37476,7 +37477,7 @@
}
],
"description": "Get usage metrics and statistics for a database. You can view the total number of tables, rows, and storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.",
"demo": "tables-db\/get-usage.md"
"demo": "tablesdb\/get-usage.md"
}
],
"auth": {

View file

@ -8524,7 +8524,7 @@
]
},
"put": {
"summary": "Create or update documents",
"summary": "Upsert documents",
"operationId": "databasesUpsertDocuments",
"consumes": [
"application\/json"
@ -8934,7 +8934,7 @@
]
},
"put": {
"summary": "Create or update a document",
"summary": "Upsert a document",
"operationId": "databasesUpsertDocument",
"consumes": [
"application\/json"
@ -11646,7 +11646,7 @@
},
"method": {
"type": "string",
"description": "HTTP method of execution. Default value is GET.",
"description": "HTTP method of execution. Default value is POST.",
"default": "POST",
"x-example": "GET",
"enum": [
@ -11655,7 +11655,8 @@
"PUT",
"PATCH",
"DELETE",
"OPTIONS"
"OPTIONS",
"HEAD"
],
"x-enum-name": "ExecutionMethod",
"x-enum-keys": []
@ -23089,7 +23090,7 @@
"deprecated": false,
"x-appwrite": {
"method": "listTables",
"group": null,
"group": "tables",
"weight": 382,
"cookies": false,
"type": "",
@ -23173,7 +23174,7 @@
"deprecated": false,
"x-appwrite": {
"method": "createTable",
"group": null,
"group": "tables",
"weight": 378,
"cookies": false,
"type": "",
@ -23282,7 +23283,7 @@
"deprecated": false,
"x-appwrite": {
"method": "getTable",
"group": null,
"group": "tables",
"weight": 379,
"cookies": false,
"type": "",
@ -23353,7 +23354,7 @@
"deprecated": false,
"x-appwrite": {
"method": "updateTable",
"group": null,
"group": "tables",
"weight": 380,
"cookies": false,
"type": "",
@ -23458,7 +23459,7 @@
"deprecated": false,
"x-appwrite": {
"method": "deleteTable",
"group": null,
"group": "tables",
"weight": 381,
"cookies": false,
"type": "",
@ -26622,7 +26623,7 @@
}
],
"description": "Create a new Row. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/create-row.md"
"demo": "tablesdb\/create-row.md"
},
{
"name": "createRows",
@ -26649,7 +26650,7 @@
}
],
"description": "Create new Rows. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/create-rows.md"
"demo": "tablesdb\/create-rows.md"
}
],
"auth": {
@ -26724,7 +26725,7 @@
]
},
"put": {
"summary": "Create or update rows",
"summary": "Upsert rows",
"operationId": "tablesDBUpsertRows",
"consumes": [
"application\/json"
@ -26791,7 +26792,7 @@
}
],
"description": "Create or update Rows. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.\n",
"demo": "tables-db\/upsert-rows.md"
"demo": "tablesdb\/upsert-rows.md"
}
],
"auth": {
@ -27126,7 +27127,7 @@
]
},
"put": {
"summary": "Create or update a row",
"summary": "Upsert a row",
"operationId": "tablesDBUpsertRow",
"consumes": [
"application\/json"
@ -27195,7 +27196,7 @@
}
],
"description": "Create or update a Row. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/upsert-row.md"
"demo": "tablesdb\/upsert-row.md"
}
],
"auth": {

View file

@ -5273,7 +5273,7 @@
]
},
"put": {
"summary": "Create or update a document",
"summary": "Upsert a document",
"operationId": "databasesUpsertDocument",
"consumes": [
"application\/json"
@ -5978,7 +5978,7 @@
},
"method": {
"type": "string",
"description": "HTTP method of execution. Default value is GET.",
"description": "HTTP method of execution. Default value is POST.",
"default": "POST",
"x-example": "GET",
"enum": [
@ -5987,7 +5987,8 @@
"PUT",
"PATCH",
"DELETE",
"OPTIONS"
"OPTIONS",
"HEAD"
],
"x-enum-name": "ExecutionMethod",
"x-enum-keys": []
@ -7701,7 +7702,7 @@
}
],
"description": "Create a new Row. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/create-row.md"
"demo": "tablesdb\/create-row.md"
}
],
"auth": {
@ -7866,7 +7867,7 @@
]
},
"put": {
"summary": "Create or update a row",
"summary": "Upsert a row",
"operationId": "tablesDBUpsertRow",
"consumes": [
"application\/json"
@ -7934,7 +7935,7 @@
}
],
"description": "Create or update a Row. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/upsert-row.md"
"demo": "tablesdb\/upsert-row.md"
}
],
"auth": {

View file

@ -9058,7 +9058,7 @@
]
},
"put": {
"summary": "Create or update documents",
"summary": "Upsert documents",
"operationId": "databasesUpsertDocuments",
"consumes": [
"application\/json"
@ -9462,7 +9462,7 @@
]
},
"put": {
"summary": "Create or update a document",
"summary": "Upsert a document",
"operationId": "databasesUpsertDocument",
"consumes": [
"application\/json"
@ -12836,7 +12836,7 @@
},
"method": {
"type": "string",
"description": "HTTP method of execution. Default value is GET.",
"description": "HTTP method of execution. Default value is POST.",
"default": "POST",
"x-example": "GET",
"enum": [
@ -12845,7 +12845,8 @@
"PUT",
"PATCH",
"DELETE",
"OPTIONS"
"OPTIONS",
"HEAD"
],
"x-enum-name": "ExecutionMethod",
"x-enum-keys": []
@ -32372,7 +32373,7 @@
}
],
"description": "List usage metrics and statistics for all databases in the project. You can view the total number of databases, tables, rows, and storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.",
"demo": "tables-db\/list-usage.md"
"demo": "tablesdb\/list-usage.md"
}
],
"auth": {
@ -32627,7 +32628,7 @@
"deprecated": false,
"x-appwrite": {
"method": "listTables",
"group": null,
"group": "tables",
"weight": 382,
"cookies": false,
"type": "",
@ -32710,7 +32711,7 @@
"deprecated": false,
"x-appwrite": {
"method": "createTable",
"group": null,
"group": "tables",
"weight": 378,
"cookies": false,
"type": "",
@ -32818,7 +32819,7 @@
"deprecated": false,
"x-appwrite": {
"method": "getTable",
"group": null,
"group": "tables",
"weight": 379,
"cookies": false,
"type": "",
@ -32888,7 +32889,7 @@
"deprecated": false,
"x-appwrite": {
"method": "updateTable",
"group": null,
"group": "tables",
"weight": 380,
"cookies": false,
"type": "",
@ -32992,7 +32993,7 @@
"deprecated": false,
"x-appwrite": {
"method": "deleteTable",
"group": null,
"group": "tables",
"weight": 381,
"cookies": false,
"type": "",
@ -36206,7 +36207,7 @@
}
],
"description": "Create a new Row. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/create-row.md"
"demo": "tablesdb\/create-row.md"
},
{
"name": "createRows",
@ -36232,7 +36233,7 @@
}
],
"description": "Create new Rows. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/create-rows.md"
"demo": "tablesdb\/create-rows.md"
}
],
"auth": {
@ -36305,7 +36306,7 @@
]
},
"put": {
"summary": "Create or update rows",
"summary": "Upsert rows",
"operationId": "tablesDBUpsertRows",
"consumes": [
"application\/json"
@ -36371,7 +36372,7 @@
}
],
"description": "Create or update Rows. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.\n",
"demo": "tables-db\/upsert-rows.md"
"demo": "tablesdb\/upsert-rows.md"
}
],
"auth": {
@ -36701,7 +36702,7 @@
]
},
"put": {
"summary": "Create or update a row",
"summary": "Upsert a row",
"operationId": "tablesDBUpsertRow",
"consumes": [
"application\/json"
@ -36769,7 +36770,7 @@
}
],
"description": "Create or update a Row. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/upsert-row.md"
"demo": "tablesdb\/upsert-row.md"
}
],
"auth": {
@ -37476,7 +37477,7 @@
}
],
"description": "Get usage metrics and statistics for a database. You can view the total number of tables, rows, and storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.",
"demo": "tables-db\/get-usage.md"
"demo": "tablesdb\/get-usage.md"
}
],
"auth": {

View file

@ -8524,7 +8524,7 @@
]
},
"put": {
"summary": "Create or update documents",
"summary": "Upsert documents",
"operationId": "databasesUpsertDocuments",
"consumes": [
"application\/json"
@ -8934,7 +8934,7 @@
]
},
"put": {
"summary": "Create or update a document",
"summary": "Upsert a document",
"operationId": "databasesUpsertDocument",
"consumes": [
"application\/json"
@ -11646,7 +11646,7 @@
},
"method": {
"type": "string",
"description": "HTTP method of execution. Default value is GET.",
"description": "HTTP method of execution. Default value is POST.",
"default": "POST",
"x-example": "GET",
"enum": [
@ -11655,7 +11655,8 @@
"PUT",
"PATCH",
"DELETE",
"OPTIONS"
"OPTIONS",
"HEAD"
],
"x-enum-name": "ExecutionMethod",
"x-enum-keys": []
@ -23089,7 +23090,7 @@
"deprecated": false,
"x-appwrite": {
"method": "listTables",
"group": null,
"group": "tables",
"weight": 382,
"cookies": false,
"type": "",
@ -23173,7 +23174,7 @@
"deprecated": false,
"x-appwrite": {
"method": "createTable",
"group": null,
"group": "tables",
"weight": 378,
"cookies": false,
"type": "",
@ -23282,7 +23283,7 @@
"deprecated": false,
"x-appwrite": {
"method": "getTable",
"group": null,
"group": "tables",
"weight": 379,
"cookies": false,
"type": "",
@ -23353,7 +23354,7 @@
"deprecated": false,
"x-appwrite": {
"method": "updateTable",
"group": null,
"group": "tables",
"weight": 380,
"cookies": false,
"type": "",
@ -23458,7 +23459,7 @@
"deprecated": false,
"x-appwrite": {
"method": "deleteTable",
"group": null,
"group": "tables",
"weight": 381,
"cookies": false,
"type": "",
@ -26622,7 +26623,7 @@
}
],
"description": "Create a new Row. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/create-row.md"
"demo": "tablesdb\/create-row.md"
},
{
"name": "createRows",
@ -26649,7 +26650,7 @@
}
],
"description": "Create new Rows. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/create-rows.md"
"demo": "tablesdb\/create-rows.md"
}
],
"auth": {
@ -26724,7 +26725,7 @@
]
},
"put": {
"summary": "Create or update rows",
"summary": "Upsert rows",
"operationId": "tablesDBUpsertRows",
"consumes": [
"application\/json"
@ -26791,7 +26792,7 @@
}
],
"description": "Create or update Rows. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.\n",
"demo": "tables-db\/upsert-rows.md"
"demo": "tablesdb\/upsert-rows.md"
}
],
"auth": {
@ -27126,7 +27127,7 @@
]
},
"put": {
"summary": "Create or update a row",
"summary": "Upsert a row",
"operationId": "tablesDBUpsertRow",
"consumes": [
"application\/json"
@ -27195,7 +27196,7 @@
}
],
"description": "Create or update a Row. Before using this route, you should create a new table resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/tablesdb#tablesDBCreateTable) API or directly from your database console.",
"demo": "tables-db\/upsert-row.md"
"demo": "tablesdb\/upsert-row.md"
}
],
"auth": {

View file

@ -810,12 +810,6 @@ App::shutdown()
}
if (!empty($queueForDatabase->getType())) {
Console::info("Triggering database event: \n" . \json_encode([
'projectId' => $project->getId(),
'databaseId' => $queueForDatabase->getDatabase()?->getId(),
'tableId' => $queueForDatabase->getTable()?->getId() ?? $queueForDatabase->getCollection()?->getId(),
'rowId' => $queueForDatabase->getRow()?->getId() ?? $queueForDatabase->getDocument()?->getId(),
]));
$queueForDatabase->trigger();
}

12
composer.lock generated
View file

@ -3638,16 +3638,16 @@
},
{
"name": "utopia-php/database",
"version": "1.3.0",
"version": "1.2.3",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/database.git",
"reference": "06ffa2b1c977f5451200a1ee82a500be1390a789"
"reference": "8a536fead840d9da6ee819fe6b80e0f047997f69"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/database/zipball/06ffa2b1c977f5451200a1ee82a500be1390a789",
"reference": "06ffa2b1c977f5451200a1ee82a500be1390a789",
"url": "https://api.github.com/repos/utopia-php/database/zipball/8a536fead840d9da6ee819fe6b80e0f047997f69",
"reference": "8a536fead840d9da6ee819fe6b80e0f047997f69",
"shasum": ""
},
"require": {
@ -3688,9 +3688,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/database/issues",
"source": "https://github.com/utopia-php/database/tree/1.3.0"
"source": "https://github.com/utopia-php/database/tree/1.2.3"
},
"time": "2025-09-02T16:20:02+00:00"
"time": "2025-08-27T11:47:04+00:00"
},
{
"name": "utopia-php/detector",

View file

@ -85,4 +85,11 @@ class StatsUsage extends Event
}),
];
}
public function reset(): Event
{
$this->metrics = [];
parent::reset();
return $this;
}
}

View file

@ -39,7 +39,7 @@ class Upsert extends Action
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_PUT)
->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/documents')
->desc('Create or update documents')
->desc('Upsert documents')
->groups(['api', 'database'])
->label('scope', 'documents.write')
->label('resourceType', RESOURCE_TYPE_DATABASES)

View file

@ -45,7 +45,7 @@ class Upsert extends Action
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_PUT)
->setHttpPath('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId')
->desc('Create or update a document')
->desc('Upsert a document')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].upsert')
->label('scope', 'documents.write')

View file

@ -41,7 +41,7 @@ class Create extends CollectionCreate
->label('audits.resource', 'database/{request.databaseId}/table/{response.$id}')
->label('sdk', new Method(
namespace: $this->getSdkNamespace(),
group: null,
group: 'tables',
name: self::getName(),
description: '/docs/references/tablesdb/create-table.md',
auth: [AuthType::KEY],

View file

@ -37,7 +37,7 @@ class Delete extends CollectionDelete
->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}')
->label('sdk', new Method(
namespace: $this->getSdkNamespace(),
group: null,
group: 'tables',
name: self::getName(),
description: '/docs/references/tablesdb/delete-table.md',
auth: [AuthType::KEY],

View file

@ -34,7 +34,7 @@ class Get extends CollectionGet
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: $this->getSdkNamespace(),
group: null,
group: 'tables',
name: self::getName(),
description: '/docs/references/tablesdb/get-table.md',
auth: [AuthType::KEY],

View file

@ -30,7 +30,7 @@ class Upsert extends DocumentsUpsert
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_PUT)
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/rows')
->desc('Create or update rows')
->desc('Upsert rows')
->groups(['api', 'database'])
->label('scope', ['rows.write', 'documents.write'])
->label('resourceType', RESOURCE_TYPE_DATABASES)

View file

@ -31,7 +31,7 @@ class Upsert extends DocumentUpsert
$this
->setHttpMethod(self::HTTP_REQUEST_METHOD_PUT)
->setHttpPath('/v1/tablesdb/:databaseId/tables/:tableId/rows/:rowId')
->desc('Create or update a row')
->desc('Upsert a row')
->groups(['api', 'database'])
->label('event', 'databases.[databaseId].tables.[tableId].rows.[rowId].upsert')
->label('scope', ['rows.write', 'documents.write'])

View file

@ -40,7 +40,7 @@ class Update extends CollectionUpdate
->label('audits.resource', 'database/{request.databaseId}/table/{request.tableId}')
->label('sdk', new Method(
namespace: $this->getSdkNamespace(),
group: null,
group: 'tables',
name: self::getName(),
description: '/docs/references/tablesdb/update-table.md',
auth: [AuthType::KEY],

View file

@ -36,7 +36,7 @@ class XList extends CollectionXList
->label('resourceType', RESOURCE_TYPE_DATABASES)
->label('sdk', new Method(
namespace: $this->getSdkNamespace(),
group: null,
group: 'tables',
name: self::getName(),
description: '/docs/references/tablesdb/list-tables.md',
auth: [AuthType::KEY],

View file

@ -64,14 +64,6 @@ class Databases extends Action
$collection = new Document($payload['table'] ?? $payload['collection'] ?? []);
$database = new Document($payload['database'] ?? []);
Console::info("Processing database operation: \n" . \json_encode([
'type' => $type,
'projectId' => $project->getId(),
'databaseId' => $database->getId(),
'collectionId' => $collection->getId(),
'documentId' => $document->getId(),
], JSON_PRETTY_PRINT));
$log->addTag('projectId', $project->getId());
$log->addTag('type', $type);

View file

@ -80,7 +80,7 @@ class Create extends Base
->param('body', '', new Text(10485760, 0), 'HTTP body of execution. Default value is empty string.', true)
->param('async', false, new Boolean(true), 'Execute code in the background. Default value is false.', true)
->param('path', '/', new Text(2048), 'HTTP path of execution. Path can include query params. Default value is /', true)
->param('method', 'POST', new Whitelist(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], true), 'HTTP method of execution. Default value is POST.', true)
->param('method', 'POST', new Whitelist(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD'], true), 'HTTP method of execution. Default value is POST.', true)
->param('headers', [], new AnyOf([new Assoc(), new Text(65535)], AnyOf::TYPE_MIXED), 'HTTP headers of execution. Defaults to empty.', true)
->param('scheduledAt', null, new Text(100), 'Scheduled execution time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future with precision in minutes.', true)
->inject('response')

View file

@ -4,6 +4,7 @@ namespace Appwrite\Platform\Workers;
use Ahc\Jwt\JWT;
use Appwrite\Event\Realtime;
use Appwrite\Event\StatsUsage;
use Exception;
use Utopia\CLI\Console;
use Utopia\Config\Config;
@ -13,9 +14,14 @@ use Utopia\Database\Exception\Authorization;
use Utopia\Database\Exception\Conflict;
use Utopia\Database\Exception\Restricted;
use Utopia\Database\Exception\Structure;
use Utopia\Database\Validator\Authorization as AuthorizationValidator;
use Utopia\Migration\Destination;
use Utopia\Migration\Destinations\Appwrite as DestinationAppwrite;
use Utopia\Migration\Exception as MigrationException;
use Utopia\Migration\Resource;
use Utopia\Migration\Resources\Database\Database as ResourceDatabase;
use Utopia\Migration\Resources\Database\Row as ResourceRow;
use Utopia\Migration\Resources\Database\Table as ResourceTable;
use Utopia\Migration\Source;
use Utopia\Migration\Sources\Appwrite as SourceAppwrite;
use Utopia\Migration\Sources\CSV;
@ -45,6 +51,7 @@ class Migrations extends Action
*/
protected array $sourceReport = [];
private string $source;
/**
* @var callable
*/
@ -69,13 +76,14 @@ class Migrations extends Action
->inject('logError')
->inject('queueForRealtime')
->inject('deviceForImports')
->inject('queueForStatsUsage')
->callback($this->action(...));
}
/**
* @throws Exception
*/
public function action(Message $message, Document $project, Database $dbForProject, Database $dbForPlatform, callable $logError, Realtime $queueForRealtime, Device $deviceForImports): void
public function action(Message $message, Document $project, Database $dbForProject, Database $dbForPlatform, callable $logError, Realtime $queueForRealtime, Device $deviceForImports, StatsUsage $queueForStatsUsage): void
{
$payload = $message->getPayload() ?? [];
$this->deviceForImports = $deviceForImports;
@ -103,7 +111,7 @@ class Migrations extends Action
return;
}
$this->processMigration($migration, $queueForRealtime);
$this->processMigration($migration, $queueForRealtime, $queueForStatsUsage);
}
/**
@ -267,7 +275,7 @@ class Migrations extends Action
* @throws \Utopia\Database\Exception
* @throws Exception
*/
protected function processMigration(Document $migration, Realtime $queueForRealtime): void
protected function processMigration(Document $migration, Realtime $queueForRealtime, StatsUsage $queueForStatsUsage): void
{
$project = $this->project;
$projectDocument = $this->dbForPlatform->getDocument('projects', $project->getId());
@ -301,6 +309,7 @@ class Migrations extends Action
$destination
);
$aggregatedResources = [];
/** Start Transfer */
if (empty($source->getErrors())) {
$migration->setAttribute('stage', 'migrating');
@ -308,9 +317,40 @@ class Migrations extends Action
$transfer->run(
$migration->getAttribute('resources'),
function () use ($migration, $transfer, $projectDocument, $queueForRealtime) {
function ($resources) use ($migration, $transfer, $projectDocument, $queueForRealtime, &$aggregatedResources) {
$migration->setAttribute('resourceData', json_encode($transfer->getCache()));
$migration->setAttribute('statusCounters', json_encode($transfer->getStatusCounters()));
if (!empty($resources)) {
/**
* @var Resource $resource
*/
$resource = $resources[0];
$count = count($resources);
$databaseId = null;
$tableId = null;
switch ($resource->getName()) {
case ResourceTable::getName():
/** @var ResourceTable $resource */
$databaseId = $resource->getDatabase()->getSequence();
break;
case ResourceRow::getName():
/** @var ResourceRow $resource */
$table = $resource->getTable();
$databaseId = $table->getDatabase()->getSequence();
$tableId = $table->getSequence();
break;
default:
break;
}
$aggregatedResources[] = [
'name' => $resource->getName(),
'count' => $count,
'databaseId' => $databaseId,
'tableId' => $tableId
];
}
$this->updateMigrationDocument($migration, $projectDocument, $queueForRealtime);
},
$migration->getAttribute('resourceId'),
@ -412,9 +452,71 @@ class Migrations extends Action
}
if ($migration->getAttribute('status', '') === 'completed') {
foreach ($aggregatedResources as $resource) {
$this->processMigrationResourceStats(
$resource,
$queueForStatsUsage,
$projectDocument,
$migration->getAttribute('source'),
$migration->getAttribute('resourceId')
);
}
$destination?->success();
$source?->success();
}
}
}
private function processMigrationResourceStats(array $resources, StatsUsage $queueForStatsUsage, Document $projectDocument, string $source, ?string $resourceId)
{
$resourceName = $resources['name'];
$count = $resources['count'];
$databaseInternalId = $resources['databaseId'];
$tableInternalId = $resources['tableId'];
if ($source === CSV::getName()) {
[$databaseId, $tableId] = explode(':', $resourceId);
$database = AuthorizationValidator::skip(fn () => $this->dbForProject->getDocument('databases', $databaseId));
$table = AuthorizationValidator::skip(fn () => $this->dbForProject->getDocument('database_' . $database->getSequence(), $tableId));
$databaseInternalId = (int) $database->getSequence();
$tableInternalId = (int) $table->getSequence();
}
switch ($resourceName) {
case ResourceDatabase::getName():
$queueForStatsUsage->addMetric(METRIC_DATABASES, $count);
break;
case ResourceTable::getName():
$queueForStatsUsage
->addMetric(METRIC_COLLECTIONS, $count)
->addMetric(
str_replace('{databaseInternalId}', $databaseInternalId, METRIC_DATABASE_ID_COLLECTIONS),
$count
);
break;
case ResourceRow::getName():
$queueForStatsUsage
->addMetric(
str_replace(
['{databaseInternalId}','{collectionInternalId}'],
[$databaseInternalId, $tableInternalId],
METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS
),
$count
)
->addMetric(
str_replace('{databaseInternalId}', $databaseInternalId, METRIC_DATABASE_ID_DOCUMENTS),
$count
);
break;
default:
break;
}
$queueForStatsUsage->setProject($projectDocument)->trigger();
$queueForStatsUsage->reset();
}
}

View file

@ -221,7 +221,7 @@ class OpenAPI3 extends Format
'required' => [],
'responses' => [],
'description' => ($desc) ? \file_get_contents($desc) : '',
'demo' => Template::fromCamelCaseToDash($namespace) . '/' . Template::fromCamelCaseToDash($methodObj->getMethodName()) . '.md',
'demo' => \strtolower($namespace) . '/' . Template::fromCamelCaseToDash($methodObj->getMethodName()) . '.md',
];
// add deprecation only if method has it!

View file

@ -230,7 +230,7 @@ class Swagger2 extends Format
'required' => [],
'responses' => [],
'description' => ($desc) ? \file_get_contents($desc) : '',
'demo' => Template::fromCamelCaseToDash($namespace) . '/' . Template::fromCamelCaseToDash($methodObj->getMethodName()) . '.md',
'demo' => \strtolower($namespace) . '/' . Template::fromCamelCaseToDash($methodObj->getMethodName()) . '.md',
];
// add deprecation only if method has it!

View file

@ -32,59 +32,67 @@ class V20 extends Filter
*/
protected function manageSelectQueries(array $content): array
{
$hasWildcard = false;
if (!isset($content['queries'])) {
$hasWildcard = true;
// only query, make it json encoded!
$content['queries'] = [Query::select(['*'])->toString()];
$content['queries'] = [];
}
// Handle case where queries is an array but empty
if (\is_array($content['queries'])) {
$content['queries'] = \array_filter($content['queries'], function ($q) {
if (\is_object($q) && empty((array)$q)) {
return false;
}
if (\is_string($q) && \trim($q) === '') {
return false;
}
if (empty($q)) {
return false;
}
return true;
});
}
try {
$parsed = Query::parseQueries($content['queries']);
} catch (QueryException) {
// don't crash!
return $content;
}
$selections = Query::groupByType($parsed)['selections'] ?? [];
// If there are no select queries at all, add wildcard
if (empty($selections)) {
$hasWildcard = true;
$parsed[] = Query::select(['*']);
} elseif (!$hasWildcard) {
// check if any select includes a wildcard as we added one above
// Check if we need to add wildcard + relationships
// This happens when:
// 1. No select queries exist, OR
// 2. A wildcard select exists
$needsRelationships = empty($selections);
if (!$needsRelationships) {
foreach ($selections as $select) {
if (\in_array('*', $select->getValues(), true)) {
$hasWildcard = true;
$needsRelationships = true;
break;
}
}
}
/**
* Add `keys.*` for all model types!
* Add wildcard and relationship selects for backward compatibility
*/
if ($hasWildcard) {
if ($needsRelationships) {
$relatedKeys = $this->getRelatedCollectionKeys();
$selects = \array_values(\array_unique(\array_merge(['*'], $relatedKeys)));
if (! empty($relatedKeys)) {
$selects = \array_values(\array_unique(\array_merge(['*'], $relatedKeys)));
// Remove any existing select queries
$parsed = \array_filter(
$parsed,
fn ($query) => $query->getMethod() !== Query::TYPE_SELECT
);
// remove previous select queries
$parsed = \array_filter(
$parsed,
fn ($query) => $query->getMethod() !== Query::TYPE_SELECT
);
// add wildcard + relationship(s) selects
$parsed[] = Query::select($selects);
}
// Add wildcard + relationship(s) selects
$parsed[] = Query::select($selects);
}
$resolvedQueries = [];
foreach ($parsed as $query) {
// make em json encoded!
$resolvedQueries[] = $query->toString();
}
@ -95,12 +103,15 @@ class V20 extends Filter
/**
* Returns all relationship attribute keys in `key.*` format for use with `Query::select`.
* Recursively includes nested relationships up to 3 levels deep.
* Prevents infinite loops by tracking all visited collections in the current path.
*/
private function getRelatedCollectionKeys(
?string $databaseId = null,
?string $collectionId = null,
?string $prefix = null,
int $depth = 1,
array $visited = []
): array {
$databaseId ??= $this->getParamValue('databaseId');
$collectionId ??= $this->getParamValue('collectionId');
@ -113,6 +124,13 @@ class V20 extends Filter
return [];
}
// Check if we've already visited this collection in the current path to prevent cycles
if (in_array($collectionId, $visited)) {
return [];
}
$visited[] = $collectionId;
$dbForProject = $this->getDbForProject();
if ($dbForProject === null) {
return [];
@ -144,20 +162,24 @@ class V20 extends Filter
$key = $attr['key'];
$fullKey = $prefix ? $prefix . '.' . $key : $key;
$relatedCollectionId = $attr['relatedCollection'] ?? null;
// Skip this relationship entirely if it points to an already visited collection
if ($relatedCollectionId && in_array($relatedCollectionId, $visited)) {
continue;
}
// Add the wildcard select for this relationship
$relationshipKeys[] = $fullKey . '.*';
// Get the related collection for nested relationships
$relatedCollectionId = $attr['relatedCollection'] ?? null;
// Continue recursively if we have a related collection
if ($relatedCollectionId) {
// Recursively get nested relationship keys
$nestedKeys = $this->getRelatedCollectionKeys(
$databaseId,
$relatedCollectionId,
$fullKey,
$depth + 1,
$visited
);
$relationshipKeys = \array_merge($relationshipKeys, $nestedKeys);

View file

@ -925,6 +925,26 @@ class FunctionsCustomServerTest extends Scope
$executionId = $execution['body']['$id'] ?? '';
/** Test create execution with HEAD method */
$execution = $this->createExecution($data['functionId'], [
'async' => 'false',
'method' => 'HEAD',
]);
$this->assertEquals(201, $execution['headers']['status-code']);
$this->assertEquals('completed', $execution['body']['status']);
$this->assertEquals(200, $execution['body']['responseStatusCode']);
$this->assertIsArray($execution['body']['responseHeaders']);
$this->assertEmpty($execution['body']['responseBody']); // For HEAD requests, response body is empty
/** Delete execution */
$execution = $this->client->call(Client::METHOD_DELETE, '/functions/' . $data['functionId'] . '/executions/' . $execution['body']['$id'], array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), []);
$this->assertEquals(204, $execution['headers']['status-code']);
/** Test create execution with 400 status code */
$execution = $this->createExecution($data['functionId'], [
'async' => 'false',
'path' => '/?code=400'
@ -934,11 +954,11 @@ class FunctionsCustomServerTest extends Scope
$this->assertEquals('completed', $execution['body']['status']);
$this->assertEquals(400, $execution['body']['responseStatusCode']);
/** Delete execution */
$execution = $this->client->call(Client::METHOD_DELETE, '/functions/' . $data['functionId'] . '/executions/' . $execution['body']['$id'], array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), []);
$this->assertEquals(204, $execution['headers']['status-code']);
return array_merge($data, ['executionId' => $executionId]);