Compare commits

...
18 changed files with 1387 additions and 329 deletions
+94 -4
View File
@@ -6082,9 +6082,8 @@
"operations": {
"type": "array",
"description": "Array of staged operations.",
"x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"<DATABASE_ID>\",\n\t \"collectionId\": \"<COLLECTION_ID>\",\n\t \"documentId\": \"<DOCUMENT_ID>\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]",
"items": {
"type": "object"
"$ref": "#\/components\/schemas\/transactionOperationLegacy"
}
}
}
@@ -9290,9 +9289,8 @@
"operations": {
"type": "array",
"description": "Array of staged operations.",
"x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"<DATABASE_ID>\",\n\t \"tableId\": \"<TABLE_ID>\",\n\t \"rowId\": \"<ROW_ID>\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]",
"items": {
"type": "object"
"$ref": "#\/components\/schemas\/transactionOperationTablesDB"
}
}
}
@@ -14054,6 +14052,98 @@
"identifier": "token",
"expired": false
}
},
"transactionOperationLegacy": {
"description": "Legacy\\TransactionOperation",
"type": "object",
"properties": {
"databaseId": {
"type": "string",
"description": "The ID of the database.",
"x-example": "5e5ea5c16897e"
},
"collectionId": {
"type": "string",
"description": "The ID of the collection.",
"x-example": "5e5ea5c15117e"
},
"documentId": {
"type": "string",
"description": "The ID of the document. Required for update, upsert, delete, increment, and decrement actions.",
"x-example": "5e5ea5c15117e",
"x-nullable": true
},
"action": {
"type": "string",
"description": "The action to perform on the document.",
"x-example": "create"
},
"data": {
"type": "object",
"description": "The data payload for the operation. Structure depends on the action type.",
"x-example": "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}",
"additionalProperties": true,
"x-nullable": true
}
},
"required": [
"databaseId",
"collectionId",
"action"
],
"example": {
"databaseId": "5e5ea5c16897e",
"collectionId": "5e5ea5c15117e",
"documentId": "5e5ea5c15117e",
"action": "create",
"data": "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}"
}
},
"transactionOperationTablesDB": {
"description": "TablesDB\\TransactionOperation",
"type": "object",
"properties": {
"databaseId": {
"type": "string",
"description": "The ID of the database.",
"x-example": "5e5ea5c16897e"
},
"action": {
"type": "string",
"description": "The action to perform on the document.",
"x-example": "create"
},
"data": {
"type": "object",
"description": "The data payload for the operation. Structure depends on the action type.",
"x-example": "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}",
"additionalProperties": true,
"x-nullable": true
},
"tableId": {
"type": "string",
"description": "The ID of the table.",
"x-example": "5e5ea5c15117e"
},
"rowId": {
"type": "string",
"description": "The ID of the row. Required for update, upsert, delete, increment, and decrement actions.",
"x-example": "5e5ea5c15117e",
"x-nullable": true
}
},
"required": [
"databaseId",
"action",
"tableId"
],
"example": {
"databaseId": "5e5ea5c16897e",
"action": "create",
"data": "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}",
"tableId": "5e5ea5c15117e",
"rowId": "5e5ea5c15117e"
}
}
},
"securitySchemes": {
+94 -4
View File
@@ -6493,9 +6493,8 @@
"operations": {
"type": "array",
"description": "Array of staged operations.",
"x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"<DATABASE_ID>\",\n\t \"collectionId\": \"<COLLECTION_ID>\",\n\t \"documentId\": \"<DOCUMENT_ID>\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]",
"items": {
"type": "object"
"$ref": "#\/components\/schemas\/transactionOperationLegacy"
}
}
}
@@ -36037,9 +36036,8 @@
"operations": {
"type": "array",
"description": "Array of staged operations.",
"x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"<DATABASE_ID>\",\n\t \"tableId\": \"<TABLE_ID>\",\n\t \"rowId\": \"<ROW_ID>\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]",
"items": {
"type": "object"
"$ref": "#\/components\/schemas\/transactionOperationTablesDB"
}
}
}
@@ -60898,6 +60896,98 @@
"size": 30000,
"version": "1.4.0"
}
},
"transactionOperationLegacy": {
"description": "Legacy\\TransactionOperation",
"type": "object",
"properties": {
"databaseId": {
"type": "string",
"description": "The ID of the database.",
"x-example": "5e5ea5c16897e"
},
"collectionId": {
"type": "string",
"description": "The ID of the collection.",
"x-example": "5e5ea5c15117e"
},
"documentId": {
"type": "string",
"description": "The ID of the document. Required for update, upsert, delete, increment, and decrement actions.",
"x-example": "5e5ea5c15117e",
"x-nullable": true
},
"action": {
"type": "string",
"description": "The action to perform on the document.",
"x-example": "create"
},
"data": {
"type": "object",
"description": "The data payload for the operation. Structure depends on the action type.",
"x-example": "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}",
"additionalProperties": true,
"x-nullable": true
}
},
"required": [
"databaseId",
"collectionId",
"action"
],
"example": {
"databaseId": "5e5ea5c16897e",
"collectionId": "5e5ea5c15117e",
"documentId": "5e5ea5c15117e",
"action": "create",
"data": "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}"
}
},
"transactionOperationTablesDB": {
"description": "TablesDB\\TransactionOperation",
"type": "object",
"properties": {
"databaseId": {
"type": "string",
"description": "The ID of the database.",
"x-example": "5e5ea5c16897e"
},
"action": {
"type": "string",
"description": "The action to perform on the document.",
"x-example": "create"
},
"data": {
"type": "object",
"description": "The data payload for the operation. Structure depends on the action type.",
"x-example": "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}",
"additionalProperties": true,
"x-nullable": true
},
"tableId": {
"type": "string",
"description": "The ID of the table.",
"x-example": "5e5ea5c15117e"
},
"rowId": {
"type": "string",
"description": "The ID of the row. Required for update, upsert, delete, increment, and decrement actions.",
"x-example": "5e5ea5c15117e",
"x-nullable": true
}
},
"required": [
"databaseId",
"action",
"tableId"
],
"example": {
"databaseId": "5e5ea5c16897e",
"action": "create",
"data": "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}",
"tableId": "5e5ea5c15117e",
"rowId": "5e5ea5c15117e"
}
}
},
"securitySchemes": {
+94 -4
View File
@@ -6049,9 +6049,8 @@
"operations": {
"type": "array",
"description": "Array of staged operations.",
"x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"<DATABASE_ID>\",\n\t \"collectionId\": \"<COLLECTION_ID>\",\n\t \"documentId\": \"<DOCUMENT_ID>\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]",
"items": {
"type": "object"
"$ref": "#\/components\/schemas\/transactionOperationLegacy"
}
}
}
@@ -25958,9 +25957,8 @@
"operations": {
"type": "array",
"description": "Array of staged operations.",
"x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"<DATABASE_ID>\",\n\t \"tableId\": \"<TABLE_ID>\",\n\t \"rowId\": \"<ROW_ID>\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]",
"items": {
"type": "object"
"$ref": "#\/components\/schemas\/transactionOperationTablesDB"
}
}
}
@@ -44891,6 +44889,98 @@
"identifier": "token",
"expired": false
}
},
"transactionOperationLegacy": {
"description": "Legacy\\TransactionOperation",
"type": "object",
"properties": {
"databaseId": {
"type": "string",
"description": "The ID of the database.",
"x-example": "5e5ea5c16897e"
},
"collectionId": {
"type": "string",
"description": "The ID of the collection.",
"x-example": "5e5ea5c15117e"
},
"documentId": {
"type": "string",
"description": "The ID of the document. Required for update, upsert, delete, increment, and decrement actions.",
"x-example": "5e5ea5c15117e",
"x-nullable": true
},
"action": {
"type": "string",
"description": "The action to perform on the document.",
"x-example": "create"
},
"data": {
"type": "object",
"description": "The data payload for the operation. Structure depends on the action type.",
"x-example": "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}",
"additionalProperties": true,
"x-nullable": true
}
},
"required": [
"databaseId",
"collectionId",
"action"
],
"example": {
"databaseId": "5e5ea5c16897e",
"collectionId": "5e5ea5c15117e",
"documentId": "5e5ea5c15117e",
"action": "create",
"data": "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}"
}
},
"transactionOperationTablesDB": {
"description": "TablesDB\\TransactionOperation",
"type": "object",
"properties": {
"databaseId": {
"type": "string",
"description": "The ID of the database.",
"x-example": "5e5ea5c16897e"
},
"action": {
"type": "string",
"description": "The action to perform on the document.",
"x-example": "create"
},
"data": {
"type": "object",
"description": "The data payload for the operation. Structure depends on the action type.",
"x-example": "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}",
"additionalProperties": true,
"x-nullable": true
},
"tableId": {
"type": "string",
"description": "The ID of the table.",
"x-example": "5e5ea5c15117e"
},
"rowId": {
"type": "string",
"description": "The ID of the row. Required for update, upsert, delete, increment, and decrement actions.",
"x-example": "5e5ea5c15117e",
"x-nullable": true
}
},
"required": [
"databaseId",
"action",
"tableId"
],
"example": {
"databaseId": "5e5ea5c16897e",
"action": "create",
"data": "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}",
"tableId": "5e5ea5c15117e",
"rowId": "5e5ea5c15117e"
}
}
},
"securitySchemes": {
+106 -20
View File
@@ -6182,10 +6182,8 @@
"operations": {
"type": "array",
"description": "Array of staged operations.",
"default": [],
"x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"<DATABASE_ID>\",\n\t \"collectionId\": \"<COLLECTION_ID>\",\n\t \"documentId\": \"<DOCUMENT_ID>\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]",
"items": {
"type": "object"
"$ref": "#\/definitions\/transactionOperationLegacy"
}
}
}
@@ -6425,10 +6423,10 @@
"description": "An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"documents": {
"type": "array",
@@ -6684,10 +6682,10 @@
"description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"transactionId": {
"type": "string",
@@ -6800,10 +6798,10 @@
"description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"transactionId": {
"type": "string",
@@ -8462,10 +8460,10 @@
"description": "An array of permission string. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
}
}
}
@@ -9318,10 +9316,8 @@
"operations": {
"type": "array",
"description": "Array of staged operations.",
"default": [],
"x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"<DATABASE_ID>\",\n\t \"tableId\": \"<TABLE_ID>\",\n\t \"rowId\": \"<ROW_ID>\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]",
"items": {
"type": "object"
"$ref": "#\/definitions\/transactionOperationTablesDB"
}
}
}
@@ -9555,10 +9551,10 @@
"description": "An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"rows": {
"type": "array",
@@ -9807,10 +9803,10 @@
"description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"transactionId": {
"type": "string",
@@ -9919,10 +9915,10 @@
"description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"transactionId": {
"type": "string",
@@ -13997,6 +13993,96 @@
"identifier": "token",
"expired": false
}
},
"transactionOperationLegacy": {
"description": "Legacy\\TransactionOperation",
"type": "object",
"properties": {
"databaseId": {
"type": "string",
"description": "The ID of the database.",
"x-example": "5e5ea5c16897e"
},
"collectionId": {
"type": "string",
"description": "The ID of the collection.",
"x-example": "5e5ea5c15117e"
},
"documentId": {
"type": "string",
"description": "The ID of the document. Required for update, upsert, delete, increment, and decrement actions.",
"x-example": "5e5ea5c15117e",
"x-nullable": true
},
"action": {
"type": "string",
"description": "The action to perform on the document.",
"x-example": "create"
},
"data": {
"type": "object",
"additionalProperties": true,
"description": "The data payload for the operation. Structure depends on the action type.",
"x-example": "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}"
}
},
"required": [
"databaseId",
"collectionId",
"action"
],
"example": {
"databaseId": "5e5ea5c16897e",
"collectionId": "5e5ea5c15117e",
"documentId": "5e5ea5c15117e",
"action": "create",
"data": "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}"
}
},
"transactionOperationTablesDB": {
"description": "TablesDB\\TransactionOperation",
"type": "object",
"properties": {
"databaseId": {
"type": "string",
"description": "The ID of the database.",
"x-example": "5e5ea5c16897e"
},
"action": {
"type": "string",
"description": "The action to perform on the document.",
"x-example": "create"
},
"data": {
"type": "object",
"additionalProperties": true,
"description": "The data payload for the operation. Structure depends on the action type.",
"x-example": "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}"
},
"tableId": {
"type": "string",
"description": "The ID of the table.",
"x-example": "5e5ea5c15117e"
},
"rowId": {
"type": "string",
"description": "The ID of the row. Required for update, upsert, delete, increment, and decrement actions.",
"x-example": "5e5ea5c15117e",
"x-nullable": true
}
},
"required": [
"databaseId",
"action",
"tableId"
],
"example": {
"databaseId": "5e5ea5c16897e",
"action": "create",
"data": "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}",
"tableId": "5e5ea5c15117e",
"rowId": "5e5ea5c15117e"
}
}
},
"externalDocs": {
+148 -62
View File
@@ -6611,10 +6611,8 @@
"operations": {
"type": "array",
"description": "Array of staged operations.",
"default": [],
"x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"<DATABASE_ID>\",\n\t \"collectionId\": \"<COLLECTION_ID>\",\n\t \"documentId\": \"<DOCUMENT_ID>\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]",
"items": {
"type": "object"
"$ref": "#\/definitions\/transactionOperationLegacy"
}
}
}
@@ -7193,10 +7191,10 @@
"description": "An array of permissions strings. By default, no user is granted with any permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"documentSecurity": {
"type": "boolean",
@@ -7394,10 +7392,10 @@
"description": "An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"documentSecurity": {
"type": "boolean",
@@ -11034,10 +11032,10 @@
"description": "An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"documents": {
"type": "array",
@@ -11626,10 +11624,10 @@
"description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"transactionId": {
"type": "string",
@@ -11742,10 +11740,10 @@
"description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"transactionId": {
"type": "string",
@@ -17935,30 +17933,30 @@
"description": "List of Topic IDs.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"users": {
"type": "array",
"description": "List of User IDs.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"targets": {
"type": "array",
"description": "List of Targets IDs.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"subject": {
"type": "string",
@@ -17993,20 +17991,20 @@
"description": "Array of target IDs to be added as CC.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"bcc": {
"type": "array",
"description": "Array of target IDs to be added as BCC.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"scheduledAt": {
"type": "string",
@@ -18020,10 +18018,10 @@
"description": "Array of compound ID strings of bucket IDs and file IDs to be attached to the email. They should be formatted as <BUCKET_ID>:<FILE_ID>.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
}
}
}
@@ -18298,30 +18296,30 @@
"description": "List of Topic IDs.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"users": {
"type": "array",
"description": "List of User IDs.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"targets": {
"type": "array",
"description": "List of Targets IDs.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"title": {
"type": "string",
@@ -18763,30 +18761,30 @@
"description": "List of Topic IDs.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"users": {
"type": "array",
"description": "List of User IDs.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"targets": {
"type": "array",
"description": "List of Targets IDs.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"content": {
"type": "string",
@@ -22660,10 +22658,10 @@
"description": "An array of role strings with subscribe permission. By default all users are granted with any subscribe permission. [learn more about roles](https:\/\/appwrite.io\/docs\/permissions#permission-roles). Maximum of 100 roles are allowed, each 64 characters long.",
"default": null,
"x-example": "[\"any\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
}
}
}
@@ -27222,7 +27220,6 @@
"description": "Key scopes list. Maximum of 100 scopes are allowed.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string",
"enum": [
@@ -27284,7 +27281,8 @@
],
"x-enum-name": null,
"x-enum-keys": []
}
},
"x-nullable": true
},
"expire": {
"type": "string",
@@ -27449,7 +27447,6 @@
"description": "Key scopes list. Maximum of 100 events are allowed.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string",
"enum": [
@@ -27511,7 +27508,8 @@
],
"x-enum-name": null,
"x-enum-keys": []
}
},
"x-nullable": true
},
"expire": {
"type": "string",
@@ -34249,10 +34247,10 @@
"description": "An array of permission strings. By default, no user is granted with any permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"fileSecurity": {
"type": "boolean",
@@ -34454,10 +34452,10 @@
"description": "An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"fileSecurity": {
"type": "boolean",
@@ -34913,10 +34911,10 @@
"description": "An array of permission string. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
}
}
}
@@ -36080,10 +36078,8 @@
"operations": {
"type": "array",
"description": "Array of staged operations.",
"default": [],
"x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"<DATABASE_ID>\",\n\t \"tableId\": \"<TABLE_ID>\",\n\t \"rowId\": \"<ROW_ID>\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]",
"items": {
"type": "object"
"$ref": "#\/definitions\/transactionOperationTablesDB"
}
}
}
@@ -36557,10 +36553,10 @@
"description": "An array of permissions strings. By default, no user is granted with any permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"rowSecurity": {
"type": "boolean",
@@ -36756,10 +36752,10 @@
"description": "An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"rowSecurity": {
"type": "boolean",
@@ -40814,10 +40810,10 @@
"description": "An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"rows": {
"type": "array",
@@ -41392,10 +41388,10 @@
"description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"transactionId": {
"type": "string",
@@ -41504,10 +41500,10 @@
"description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"transactionId": {
"type": "string",
@@ -60838,6 +60834,96 @@
"size": 30000,
"version": "1.4.0"
}
},
"transactionOperationLegacy": {
"description": "Legacy\\TransactionOperation",
"type": "object",
"properties": {
"databaseId": {
"type": "string",
"description": "The ID of the database.",
"x-example": "5e5ea5c16897e"
},
"collectionId": {
"type": "string",
"description": "The ID of the collection.",
"x-example": "5e5ea5c15117e"
},
"documentId": {
"type": "string",
"description": "The ID of the document. Required for update, upsert, delete, increment, and decrement actions.",
"x-example": "5e5ea5c15117e",
"x-nullable": true
},
"action": {
"type": "string",
"description": "The action to perform on the document.",
"x-example": "create"
},
"data": {
"type": "object",
"additionalProperties": true,
"description": "The data payload for the operation. Structure depends on the action type.",
"x-example": "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}"
}
},
"required": [
"databaseId",
"collectionId",
"action"
],
"example": {
"databaseId": "5e5ea5c16897e",
"collectionId": "5e5ea5c15117e",
"documentId": "5e5ea5c15117e",
"action": "create",
"data": "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}"
}
},
"transactionOperationTablesDB": {
"description": "TablesDB\\TransactionOperation",
"type": "object",
"properties": {
"databaseId": {
"type": "string",
"description": "The ID of the database.",
"x-example": "5e5ea5c16897e"
},
"action": {
"type": "string",
"description": "The action to perform on the document.",
"x-example": "create"
},
"data": {
"type": "object",
"additionalProperties": true,
"description": "The data payload for the operation. Structure depends on the action type.",
"x-example": "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}"
},
"tableId": {
"type": "string",
"description": "The ID of the table.",
"x-example": "5e5ea5c15117e"
},
"rowId": {
"type": "string",
"description": "The ID of the row. Required for update, upsert, delete, increment, and decrement actions.",
"x-example": "5e5ea5c15117e",
"x-nullable": true
}
},
"required": [
"databaseId",
"action",
"tableId"
],
"example": {
"databaseId": "5e5ea5c16897e",
"action": "create",
"data": "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}",
"tableId": "5e5ea5c15117e",
"rowId": "5e5ea5c15117e"
}
}
},
"externalDocs": {
+144 -58
View File
@@ -6155,10 +6155,8 @@
"operations": {
"type": "array",
"description": "Array of staged operations.",
"default": [],
"x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"<DATABASE_ID>\",\n\t \"collectionId\": \"<COLLECTION_ID>\",\n\t \"documentId\": \"<DOCUMENT_ID>\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]",
"items": {
"type": "object"
"$ref": "#\/definitions\/transactionOperationLegacy"
}
}
}
@@ -6645,10 +6643,10 @@
"description": "An array of permissions strings. By default, no user is granted with any permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"documentSecurity": {
"type": "boolean",
@@ -6848,10 +6846,10 @@
"description": "An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"documentSecurity": {
"type": "boolean",
@@ -10524,10 +10522,10 @@
"description": "An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"documents": {
"type": "array",
@@ -11125,10 +11123,10 @@
"description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"transactionId": {
"type": "string",
@@ -11243,10 +11241,10 @@
"description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"transactionId": {
"type": "string",
@@ -16654,30 +16652,30 @@
"description": "List of Topic IDs.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"users": {
"type": "array",
"description": "List of User IDs.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"targets": {
"type": "array",
"description": "List of Targets IDs.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"subject": {
"type": "string",
@@ -16712,20 +16710,20 @@
"description": "Array of target IDs to be added as CC.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"bcc": {
"type": "array",
"description": "Array of target IDs to be added as BCC.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"scheduledAt": {
"type": "string",
@@ -16739,10 +16737,10 @@
"description": "Array of compound ID strings of bucket IDs and file IDs to be attached to the email. They should be formatted as <BUCKET_ID>:<FILE_ID>.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
}
}
}
@@ -17019,30 +17017,30 @@
"description": "List of Topic IDs.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"users": {
"type": "array",
"description": "List of User IDs.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"targets": {
"type": "array",
"description": "List of Targets IDs.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"title": {
"type": "string",
@@ -17490,30 +17488,30 @@
"description": "List of Topic IDs.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"users": {
"type": "array",
"description": "List of User IDs.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"targets": {
"type": "array",
"description": "List of Targets IDs.",
"default": null,
"x-example": null,
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"content": {
"type": "string",
@@ -21434,10 +21432,10 @@
"description": "An array of role strings with subscribe permission. By default all users are granted with any subscribe permission. [learn more about roles](https:\/\/appwrite.io\/docs\/permissions#permission-roles). Maximum of 100 roles are allowed, each 64 characters long.",
"default": null,
"x-example": "[\"any\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
}
}
}
@@ -24344,10 +24342,10 @@
"description": "An array of permission strings. By default, no user is granted with any permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"fileSecurity": {
"type": "boolean",
@@ -24551,10 +24549,10 @@
"description": "An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"fileSecurity": {
"type": "boolean",
@@ -25019,10 +25017,10 @@
"description": "An array of permission string. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
}
}
}
@@ -26060,10 +26058,8 @@
"operations": {
"type": "array",
"description": "Array of staged operations.",
"default": [],
"x-example": "[\n\t {\n\t \"action\": \"create\",\n\t \"databaseId\": \"<DATABASE_ID>\",\n\t \"tableId\": \"<TABLE_ID>\",\n\t \"rowId\": \"<ROW_ID>\",\n\t \"data\": {\n\t \"name\": \"Walter O'Brien\"\n\t }\n\t }\n\t]",
"items": {
"type": "object"
"$ref": "#\/definitions\/transactionOperationTablesDB"
}
}
}
@@ -26447,10 +26443,10 @@
"description": "An array of permissions strings. By default, no user is granted with any permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"rowSecurity": {
"type": "boolean",
@@ -26648,10 +26644,10 @@
"description": "An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"rowSecurity": {
"type": "boolean",
@@ -30665,10 +30661,10 @@
"description": "An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"rows": {
"type": "array",
@@ -31252,10 +31248,10 @@
"description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"transactionId": {
"type": "string",
@@ -31366,10 +31362,10 @@
"description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).",
"default": null,
"x-example": "[\"read(\"any\")\"]",
"x-nullable": true,
"items": {
"type": "string"
}
},
"x-nullable": true
},
"transactionId": {
"type": "string",
@@ -44827,6 +44823,96 @@
"identifier": "token",
"expired": false
}
},
"transactionOperationLegacy": {
"description": "Legacy\\TransactionOperation",
"type": "object",
"properties": {
"databaseId": {
"type": "string",
"description": "The ID of the database.",
"x-example": "5e5ea5c16897e"
},
"collectionId": {
"type": "string",
"description": "The ID of the collection.",
"x-example": "5e5ea5c15117e"
},
"documentId": {
"type": "string",
"description": "The ID of the document. Required for update, upsert, delete, increment, and decrement actions.",
"x-example": "5e5ea5c15117e",
"x-nullable": true
},
"action": {
"type": "string",
"description": "The action to perform on the document.",
"x-example": "create"
},
"data": {
"type": "object",
"additionalProperties": true,
"description": "The data payload for the operation. Structure depends on the action type.",
"x-example": "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}"
}
},
"required": [
"databaseId",
"collectionId",
"action"
],
"example": {
"databaseId": "5e5ea5c16897e",
"collectionId": "5e5ea5c15117e",
"documentId": "5e5ea5c15117e",
"action": "create",
"data": "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}"
}
},
"transactionOperationTablesDB": {
"description": "TablesDB\\TransactionOperation",
"type": "object",
"properties": {
"databaseId": {
"type": "string",
"description": "The ID of the database.",
"x-example": "5e5ea5c16897e"
},
"action": {
"type": "string",
"description": "The action to perform on the document.",
"x-example": "create"
},
"data": {
"type": "object",
"additionalProperties": true,
"description": "The data payload for the operation. Structure depends on the action type.",
"x-example": "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}"
},
"tableId": {
"type": "string",
"description": "The ID of the table.",
"x-example": "5e5ea5c15117e"
},
"rowId": {
"type": "string",
"description": "The ID of the row. Required for update, upsert, delete, increment, and decrement actions.",
"x-example": "5e5ea5c15117e",
"x-nullable": true
}
},
"required": [
"databaseId",
"action",
"tableId"
],
"example": {
"databaseId": "5e5ea5c16897e",
"action": "create",
"data": "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}",
"tableId": "5e5ea5c15117e",
"rowId": "5e5ea5c15117e"
}
}
},
"externalDocs": {
Generated
+7 -6
View File
@@ -4679,16 +4679,16 @@
},
{
"name": "utopia-php/platform",
"version": "0.7.12",
"version": "0.7.13",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/platform.git",
"reference": "04255de21db75e90b170040f4d1b457ba721e7a5"
"reference": "77a863a920122e2c6a6bc6ee5548d366a3f4c6c7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/platform/zipball/04255de21db75e90b170040f4d1b457ba721e7a5",
"reference": "04255de21db75e90b170040f4d1b457ba721e7a5",
"url": "https://api.github.com/repos/utopia-php/platform/zipball/77a863a920122e2c6a6bc6ee5548d366a3f4c6c7",
"reference": "77a863a920122e2c6a6bc6ee5548d366a3f4c6c7",
"shasum": ""
},
"require": {
@@ -4701,6 +4701,7 @@
},
"require-dev": {
"laravel/pint": "1.*",
"phpstan/phpstan": "2.*",
"phpunit/phpunit": "9.*"
},
"type": "library",
@@ -4723,9 +4724,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/platform/issues",
"source": "https://github.com/utopia-php/platform/tree/0.7.12"
"source": "https://github.com/utopia-php/platform/tree/0.7.13"
},
"time": "2025-09-05T15:53:12+00:00"
"time": "2025-12-08T10:02:40+00:00"
},
{
"name": "utopia-php/pools",
@@ -11,6 +11,7 @@ use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Database\Documents\User;
use Appwrite\Utopia\Database\Validator\Operation;
use Appwrite\Utopia\Request\Model\Database\Legacy\TransactionOperation;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Database;
use Utopia\Database\Document;
@@ -58,7 +59,7 @@ class Create extends Action
contentType: ContentType::JSON
))
->param('transactionId', '', new UID(), 'Transaction ID.')
->param('operations', [], new ArrayList(new Operation(type: 'legacy')), 'Array of staged operations.', true)
->param('operations', [], new ArrayList(new Operation(type: 'legacy')), 'Array of staged operations.', true, model: TransactionOperation::class)
->inject('response')
->inject('dbForProject')
->inject('transactionState')
@@ -8,6 +8,7 @@ use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Database\Validator\Operation;
use Appwrite\Utopia\Request\Model\Database\TablesDB\TransactionOperation;
use Appwrite\Utopia\Response as UtopiaResponse;
use Utopia\Database\Validator\UID;
use Utopia\Swoole\Response as SwooleResponse;
@@ -49,7 +50,7 @@ class Create extends OperationsCreate
contentType: ContentType::JSON
))
->param('transactionId', '', new UID(), 'Transaction ID.')
->param('operations', [], new ArrayList(new Operation(type: 'tablesdb')), 'Array of staged operations.', true)
->param('operations', [], new ArrayList(new Operation(type: 'tablesdb')), 'Array of staged operations.', true, model: TransactionOperation::class)
->inject('response')
->inject('dbForProject')
->inject('transactionState')
+20 -8
View File
@@ -192,7 +192,8 @@ class Specs extends Action
foreach ($platforms as $platform) {
$routes = [];
$models = [];
$requestModels = [];
$responseModels = [];
$services = [];
foreach ($appRoutes as $key => $method) {
@@ -264,9 +265,9 @@ class Specs extends Action
foreach (Config::getParam('services', []) as $service) {
if (
!isset($service['docs']) // Skip service if not part of the public API
|| !isset($service['sdk'])
!isset($service['docs']) // Skip service if not part of the public API
|| !$service['docs']
|| !isset($service['sdk'])
|| !$service['sdk']
) {
continue;
@@ -278,11 +279,21 @@ class Specs extends Action
];
}
$models = $response->getModels();
$responseModels = $response->getModels();
foreach ($models as $key => $value) {
foreach ($responseModels as $key => $value) {
if ($platform !== APP_PLATFORM_CONSOLE && !$value->isPublic()) {
unset($models[$key]);
unset($responseModels[$key]);
}
}
foreach ($routes as $route) {
foreach ($route->getParams() as $param) {
$model = $param['model'] ?? null;
if ($model !== null && \class_exists($model)) {
$instance = new $model();
$requestModels[$instance->getType()] = $instance;
}
}
}
@@ -290,10 +301,11 @@ class Specs extends Action
new App('UTC'),
$services,
$routes,
$models,
$requestModels,
$responseModels,
$keys[$platform],
$authCounts[$platform] ?? 0,
$platforms[$platform]
$platforms[$platform],
];
foreach (['swagger2', 'open-api3'] as $format) {
+32 -26
View File
@@ -2,6 +2,7 @@
namespace Appwrite\SDK\Specification;
use Appwrite\Utopia\Request\Model as RequestModel;
use Appwrite\Utopia\Response\Model;
use Utopia\App;
use Utopia\Config\Config;
@@ -9,22 +10,6 @@ use Utopia\Route;
abstract class Format
{
protected App $app;
/**
* @var array<Route>
*/
protected array $routes;
/**
* @var array<Model>
*/
protected array $models;
protected array $services;
protected array $keys;
protected int $authCount;
protected string $platform;
protected array $params = [
'name' => '',
'description' => '',
@@ -51,15 +36,16 @@ abstract class Format
]
];
public function __construct(App $app, array $services, array $routes, array $models, array $keys, int $authCount, string $platform)
{
$this->app = $app;
$this->services = $services;
$this->routes = $routes;
$this->models = $models;
$this->keys = $keys;
$this->authCount = $authCount;
$this->platform = $platform;
public function __construct(
protected App $app,
protected array $services,
protected array $routes,
protected array $requestModels,
protected array $responseModels,
protected array $keys,
protected int $authCount,
protected string $platform,
) {
}
/**
@@ -740,7 +726,7 @@ abstract class Format
foreach ($types as $ruleType) {
if (!in_array($ruleType, ['string', 'integer', 'boolean', 'json', 'float'])) {
$usedModels[] = $ruleType;
foreach ($this->models as $m) {
foreach ($this->responseModels as $m) {
if ($m->getType() === $ruleType) {
$this->getNestedModels($m, $usedModels);
}
@@ -749,4 +735,24 @@ abstract class Format
}
}
}
protected function getNestedRequestModels(RequestModel $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', 'double', 'datetime', 'payload', 'array', 'enum'])) {
$usedModels[] = $ruleType;
foreach ($this->requestModels as $m) {
if ($m->getType() === $ruleType) {
$this->getNestedRequestModels($m, $usedModels);
}
}
}
}
}
}
}
@@ -9,6 +9,7 @@ use Appwrite\SDK\Response;
use Appwrite\SDK\Specification\Format;
use Appwrite\Template\Template;
use Appwrite\Utopia\Database\Validator\Operation;
use Appwrite\Utopia\Request\Model as RequestModel;
use Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response\Model\Any;
use Utopia\Database\Database;
@@ -91,6 +92,7 @@ class OpenAPI3 extends Format
}
$usedModels = [];
$usedRequestModels = [];
foreach ($this->routes as $route) {
$url = \str_replace('/v1', '', $route->getPath());
@@ -259,7 +261,7 @@ class OpenAPI3 extends Format
if (\is_array($responseModel)) {
foreach ($responseModel as $modelName) {
foreach ($this->models as $value) {
foreach ($this->responseModels as $value) {
if ($value->getType() === $modelName) {
$usedModels[] = $modelName;
break;
@@ -278,7 +280,7 @@ class OpenAPI3 extends Format
// lets not assume stuff here!
if ($response->getCode() !== 204) {
$responseData['model'] = '#/components/schemas/' . $responseModel;
foreach ($this->models as $value) {
foreach ($this->responseModels as $value) {
if ($value->getType() === $responseModel) {
$usedModels[] = $responseModel;
break;
@@ -299,7 +301,7 @@ class OpenAPI3 extends Format
/** @var Response $response */
$model = $response->getModel();
foreach ($this->models as $value) {
foreach ($this->responseModels as $value) {
if (\is_array($model)) {
$model = \array_map(fn ($m) => $m === $value->getType() ? $value : $m, $model);
} else {
@@ -719,37 +721,50 @@ class OpenAPI3 extends Format
$bodyRequired[] = $name;
}
$body['content'][$consumes[0]]['schema']['properties'][$name] = [
'type' => $node['schema']['type'],
'description' => $node['description'],
'x-example' => $node['schema']['x-example'] ?? null
];
$property = &$body['content'][$consumes[0]]['schema']['properties'][$name];
$paramModel = $param['model'] ?? null;
if (isset($node['schema']['enum'])) {
/// If the enum flag is Set, add the enum values to the body
$body['content'][$consumes[0]]['schema']['properties'][$name]['enum'] = $node['schema']['enum'];
$body['content'][$consumes[0]]['schema']['properties'][$name]['x-enum-name'] = $node['schema']['x-enum-name'] ?? null;
$body['content'][$consumes[0]]['schema']['properties'][$name]['x-enum-keys'] = $node['schema']['x-enum-keys'] ?? null;
}
if ($paramModel !== null && \class_exists($paramModel)) {
/** @var RequestModel $requestModelInstance */
$requestModelInstance = new $paramModel();
$requestModelType = $requestModelInstance->getType();
$usedRequestModels[] = $requestModelType;
if ($node['schema']['x-upload-id'] ?? false) {
$body['content'][$consumes[0]]['schema']['properties'][$name]['x-upload-id'] = $node['schema']['x-upload-id'];
}
$property = $array
? ['type' => 'array', 'description' => $node['description'], 'items' => ['$ref' => '#/components/schemas/' . $requestModelType]]
: ['$ref' => '#/components/schemas/' . $requestModelType];
} else {
$property = [
'type' => $node['schema']['type'],
'description' => $node['description'],
'x-example' => $node['schema']['x-example'] ?? null
];
if (isset($node['default'])) {
$body['content'][$consumes[0]]['schema']['properties'][$name]['default'] = $node['default'];
}
if (isset($node['schema']['enum'])) {
$property['enum'] = $node['schema']['enum'];
$property['x-enum-name'] = $node['schema']['x-enum-name'] ?? null;
$property['x-enum-keys'] = $node['schema']['x-enum-keys'] ?? null;
}
if (\array_key_exists('items', $node['schema'])) {
$body['content'][$consumes[0]]['schema']['properties'][$name]['items'] = $node['schema']['items'];
}
if ($node['schema']['x-upload-id'] ?? false) {
$property['x-upload-id'] = $node['schema']['x-upload-id'];
}
if ($node['x-global'] ?? false) {
$body['content'][$consumes[0]]['schema']['properties'][$name]['x-global'] = true;
if (isset($node['default'])) {
$property['default'] = $node['default'];
}
if (\array_key_exists('items', $node['schema'])) {
$property['items'] = $node['schema']['items'];
}
if ($node['x-global'] ?? false) {
$property['x-global'] = true;
}
}
if ($isNullable) {
$body['content'][$consumes[0]]['schema']['properties'][$name]['x-nullable'] = true;
$property['x-nullable'] = true;
}
}
@@ -767,11 +782,11 @@ class OpenAPI3 extends Format
$output['paths'][$url][\strtolower($route->getMethod())] = $temp;
}
foreach ($this->models as $model) {
foreach ($this->responseModels as $model) {
$this->getNestedModels($model, $usedModels);
}
foreach ($this->models as $model) {
foreach ($this->responseModels as $model) {
if (!in_array($model->getType(), $usedModels) && $model->getType() !== 'error') {
continue;
}
@@ -931,6 +946,86 @@ class OpenAPI3 extends Format
$output['components']['schemas'][$model->getType()]['example'] = $examples;
}
// Generate request model schemas
foreach ($this->requestModels as $model) {
$this->getNestedRequestModels($model, $usedRequestModels);
}
foreach ($this->requestModels as $model) {
if (!in_array($model->getType(), $usedRequestModels)) {
continue;
}
$required = $model->getRequired();
$rules = $model->getRules();
$output['components']['schemas'][$model->getType()] = [
'description' => $model->getName(),
'type' => 'object',
];
if (!empty($rules)) {
$output['components']['schemas'][$model->getType()]['properties'] = [];
}
if (!empty($required)) {
$output['components']['schemas'][$model->getType()]['required'] = $required;
}
foreach ($rules as $name => $rule) {
$ruleType = $rule['type'];
$isArray = $rule['array'] ?? false;
[$type, $format] = match ($ruleType) {
'string', 'datetime', 'payload' => ['string', null],
'enum' => ['string', null],
'json' => ['object', null],
'array' => ['array', null],
'integer' => ['integer', 'int32'],
'float' => ['number', 'float'],
'double' => ['number', 'double'],
'boolean' => ['boolean', null],
default => ['object', null],
};
$property = &$output['components']['schemas'][$model->getType()]['properties'][$name];
$property = ['type' => $isArray ? 'array' : $type, 'description' => $rule['description'] ?? '', 'x-example' => $rule['example'] ?? null];
if ($ruleType === 'json') {
$property['additionalProperties'] = true;
}
if ($isArray) {
$property['items'] = ['type' => $type];
if ($format) {
$property['items']['format'] = $format;
}
} elseif ($format) {
$property['format'] = $format;
}
// Handle nested model references
if ($type === 'object' && $ruleType && $ruleType !== 'json') {
$refKey = $isArray ? 'anyOf' : 'oneOf';
$property['items'] = \is_array($ruleType)
? [$refKey => \array_map(fn ($t) => ['$ref' => '#/components/schemas/' . $t], $ruleType)]
: ['$ref' => '#/components/schemas/' . $ruleType];
}
if ($ruleType === 'enum' && !empty($rule['enum'])) {
$target = $isArray ? $property['items'] : $property;
$target['enum'] = \array_values($rule['enum']);
$isArray ? $property['items'] = $target : $property = $target;
}
if (!in_array($name, $required)) {
$property['x-nullable'] = true;
}
}
$output['components']['schemas'][$model->getType()]['example'] = \array_map(fn ($r) => $r['example'] ?? null, $rules);
}
\ksort($output['paths']);
return $output;
@@ -9,6 +9,7 @@ use Appwrite\SDK\Response;
use Appwrite\SDK\Specification\Format;
use Appwrite\Template\Template;
use Appwrite\Utopia\Database\Validator\Operation;
use Appwrite\Utopia\Request\Model as RequestModel;
use Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response\Model\Any;
use Utopia\Database\Database;
@@ -88,6 +89,7 @@ class Swagger2 extends Format
}
$usedModels = [];
$usedRequestModels = [];
foreach ($this->routes as $route) {
/** @var Route $route */
@@ -267,7 +269,7 @@ class Swagger2 extends Format
$responseModel = $response->getModel();
if (\is_array($responseModel)) {
foreach ($responseModel as $modelName) {
foreach ($this->models as $value) {
foreach ($this->responseModels as $value) {
if ($value->getType() === $modelName) {
$usedModels[] = $modelName;
break;
@@ -286,7 +288,7 @@ class Swagger2 extends Format
// lets not assume stuff here!
if ($response->getCode() !== 204) {
$responseData['model'] = '#/definitions/' . $responseModel;
foreach ($this->models as $value) {
foreach ($this->responseModels as $value) {
if ($value->getType() === $responseModel) {
$usedModels[] = $responseModel;
break;
@@ -307,7 +309,7 @@ class Swagger2 extends Format
/** @var Response $response */
$model = $response->getModel();
foreach ($this->models as $value) {
foreach ($this->responseModels as $value) {
if (\is_array($model)) {
$model = \array_map(fn ($m) => $m === $value->getType() ? $value : $m, $model);
} else {
@@ -707,30 +709,43 @@ class Swagger2 extends Format
$bodyRequired[] = $name;
}
$body['schema']['properties'][$name] = [
'type' => $node['type'],
'description' => $node['description'],
'default' => $node['default'] ?? null,
'x-example' => $node['x-example'] ?? null,
];
$property = &$body['schema']['properties'][$name];
$paramModel = $param['model'] ?? null;
if (isset($node['enum'])) {
/// If the enum flag is Set, add the enum values to the body
$body['schema']['properties'][$name]['enum'] = $node['enum'];
$body['schema']['properties'][$name]['x-enum-name'] = $node['x-enum-name'] ?? null;
$body['schema']['properties'][$name]['x-enum-keys'] = $node['x-enum-keys'] ?? null;
}
if ($paramModel !== null && \class_exists($paramModel)) {
/** @var RequestModel $requestModelInstance */
$requestModelInstance = new $paramModel();
$requestModelType = $requestModelInstance->getType();
$usedRequestModels[] = $requestModelType;
if ($node['x-global'] ?? false) {
$body['schema']['properties'][$name]['x-global'] = true;
$property = $array
? ['type' => 'array', 'description' => $node['description'], 'items' => ['$ref' => '#/definitions/' . $requestModelType]]
: ['$ref' => '#/definitions/' . $requestModelType];
} else {
$property = [
'type' => $node['type'],
'description' => $node['description'],
'default' => $node['default'] ?? null,
'x-example' => $node['x-example'] ?? null,
];
if (isset($node['enum'])) {
$property['enum'] = $node['enum'];
$property['x-enum-name'] = $node['x-enum-name'] ?? null;
$property['x-enum-keys'] = $node['x-enum-keys'] ?? null;
}
if ($node['x-global'] ?? false) {
$property['x-global'] = true;
}
if (\array_key_exists('items', $node)) {
$property['items'] = $node['items'];
}
}
if ($isNullable) {
$body['schema']['properties'][$name]['x-nullable'] = true;
}
if (\array_key_exists('items', $node)) {
$body['schema']['properties'][$name]['items'] = $node['items'];
$property['x-nullable'] = true;
}
}
@@ -750,11 +765,11 @@ class Swagger2 extends Format
$output['paths'][$url][\strtolower($route->getMethod())] = $temp;
}
foreach ($this->models as $model) {
foreach ($this->responseModels as $model) {
$this->getNestedModels($model, $usedModels);
}
foreach ($this->models as $model) {
foreach ($this->responseModels as $model) {
if (!in_array($model->getType(), $usedModels)) {
continue;
}
@@ -927,6 +942,89 @@ class Swagger2 extends Format
$output['definitions'][$model->getType()]['example'] = $examples;
}
// Generate request model definitions
foreach ($this->requestModels as $model) {
$this->getNestedRequestModels($model, $usedRequestModels);
}
foreach ($this->requestModels as $model) {
if (!in_array($model->getType(), $usedRequestModels)) {
continue;
}
$required = $model->getRequired();
$rules = $model->getRules();
$output['definitions'][$model->getType()] = [
'description' => $model->getName(),
'type' => 'object',
];
if (!empty($rules)) {
$output['definitions'][$model->getType()]['properties'] = [];
}
if (!empty($required)) {
$output['definitions'][$model->getType()]['required'] = $required;
}
foreach ($rules as $name => $rule) {
$ruleType = $rule['type'];
$isArray = $rule['array'] ?? false;
[$type, $format] = match ($ruleType) {
'string', 'datetime' => ['string', null],
'enum' => ['string', null],
'json' => ['object', null],
'array' => ['array', null],
'integer' => ['integer', 'int32'],
'float' => ['number', 'float'],
'double' => ['number', 'double'],
'boolean' => ['boolean', null],
'payload' => ['payload', null],
default => ['object', null],
};
$property = &$output['definitions'][$model->getType()]['properties'][$name];
if ($ruleType === 'json') {
$property = ['type' => $type, 'additionalProperties' => true, 'description' => $rule['description'] ?? '', 'x-example' => $rule['example'] ?? null];
continue;
}
$property = ['type' => $isArray ? 'array' : $type, 'description' => $rule['description'] ?? '', 'x-example' => $rule['example'] ?? null];
if ($isArray) {
$property['items'] = ['type' => $type];
if ($format) {
$property['items']['format'] = $format;
}
} elseif ($format) {
$property['format'] = $format;
}
// Handle nested model references
if ($type === 'object' && $ruleType && $ruleType !== 'json') {
$refKey = $isArray ? 'x-anyOf' : 'x-oneOf';
$property['items'] = \is_array($ruleType)
? [$refKey => \array_map(fn ($t) => ['$ref' => '#/definitions/' . $t], $ruleType)]
: ['type' => 'object', '$ref' => '#/definitions/' . $ruleType];
}
if ($ruleType === 'enum' && !empty($rule['enum'])) {
$target = $isArray ? $property['items'] : $property;
$target['enum'] = \array_values($rule['enum']);
$isArray ? $property['items'] = $target : $property = $target;
}
if (!in_array($name, $required)) {
$property['x-nullable'] = true;
}
}
$output['definitions'][$model->getType()]['example'] = \array_map(fn ($r) => $r['example'] ?? null, $rules);
}
\ksort($output['paths']);
return $output;
@@ -2,6 +2,8 @@
namespace Appwrite\Utopia\Database\Validator;
use Appwrite\Utopia\Request\Model\Database\Legacy\TransactionOperation as TransactionOperationLegacy;
use Appwrite\Utopia\Request\Model\Database\TablesDB\TransactionOperation as TransactionOperationTablesDB;
use Utopia\Validator;
class Operation extends Validator
@@ -9,10 +11,7 @@ class Operation extends Validator
private string $description = '';
/** @var array<string> */
private array $required = [
'databaseId',
'action',
];
private array $required = [];
/** @var array<string, bool> */
private array $requiresDocumentId = [
@@ -39,38 +38,33 @@ class Operation extends Validator
];
/** @var array<string, bool> */
private array $actions = [
'create' => true,
'update' => true,
'upsert' => true,
'delete' => true,
'increment' => true,
'decrement' => true,
'bulkCreate' => true,
'bulkUpdate' => true,
'bulkUpsert' => true,
'bulkDelete' => true,
];
private array $actions = [];
private string $collectionIdName = '';
private string $documentIdName = '';
public function __construct(private readonly string $type)
{
switch ($this->type) {
case 'legacy':
$this->collectionIdName = 'collectionId';
$this->documentIdName = 'documentId';
break;
case 'tablesdb':
$this->collectionIdName = 'tableId';
$this->documentIdName = 'rowId';
break;
default:
throw new \InvalidArgumentException('Invalid type provided.');
$model = match ($this->type) {
'legacy' => new TransactionOperationLegacy(),
'tablesdb' => new TransactionOperationTablesDB(),
default => throw new \InvalidArgumentException('Invalid type provided.'),
};
// Get required fields from the model
$this->required = $model->getRequired();
// Get valid actions from the model's action rule enum
$rules = $model->getRules();
if (isset($rules['action']['enum'])) {
foreach ($rules['action']['enum'] as $action) {
$this->actions[$action] = true;
}
}
$this->required[] = $this->collectionIdName;
// Set collection/document ID names based on model rules
$this->collectionIdName = isset($rules['tableId']) ? 'tableId' : 'collectionId';
$this->documentIdName = isset($rules['rowId']) ? 'rowId' : 'documentId';
}
public function getDescription(): string
@@ -94,85 +88,70 @@ class Operation extends Validator
}
/**
* @param mixed $value
* @param TransactionOperationLegacy|TransactionOperationTablesDB $value
*/
public function isValid($value): bool
{
// Must be arraylike
if (!\is_array($value)) {
$this->description = 'Value must be an array';
$databaseId = $value->getDatabaseId();
$collectionId = $value->getCollectionId();
$documentId = $value->getDocumentId();
$action = $value->getAction();
$data = $value->getData();
// Validate databaseId is non-empty
if (!\is_string($databaseId) || \trim($databaseId) === '') {
$this->description = "Key 'databaseId' must be a non-empty string";
return false;
}
// Mandatory keys
foreach ($this->required as $key) {
if (!\array_key_exists($key, $value)) {
$this->description = "Missing required key: {$key}";
return false;
}
// Validate collectionId is non-empty
if (!\is_string($collectionId) || \trim($collectionId) === '') {
$this->description = "Key '{$this->collectionIdName}' must be a non-empty string";
return false;
}
// Required keys must be nonempty
foreach ($this->required as $key) {
if (!\is_string($value[$key]) || \trim($value[$key]) === '') {
$this->description = "Key '{$key}' must be a nonempty string";
return false;
}
// Validate action is non-empty
if (!\is_string($action) || \trim($action) === '') {
$this->description = "Key 'action' must be a non-empty string";
return false;
}
// Validate action
if (!isset($this->actions[$value['action']])) {
// Validate action is valid
if (!isset($this->actions[$action])) {
$this->description = "Key 'action' must be one of: " . \implode(', ', array_keys($this->actions));
return false;
}
// If action requires documentId, it must be present
$actionRequiresDocumentId = ($this->requiresDocumentId[$value['action']] ?? false) === true;
if ($actionRequiresDocumentId && !\array_key_exists($this->documentIdName, $value)) {
$this->description = "Key '$this->documentIdName' is required for action '{$value['action']}'";
// If action requires documentId, it must be present and non-empty
$actionRequiresDocumentId = ($this->requiresDocumentId[$action] ?? false) === true;
if ($actionRequiresDocumentId && ($documentId === null || \trim($documentId) === '')) {
$this->description = "Key '{$this->documentIdName}' is required for action '{$action}'";
return false;
}
if (\array_key_exists($this->documentIdName, $value)) {
if (!\is_string($value[$this->documentIdName]) || \trim($value[$this->documentIdName]) === '') {
$this->description = "Key '$this->documentIdName' must be a non-empty string";
return false;
}
// If documentId is provided, it must be non-empty
if ($documentId !== null && \trim($documentId) === '') {
$this->description = "Key '{$this->documentIdName}' must be a non-empty string";
return false;
}
// Data validation - only required for certain actions
if (isset($this->requiresData[$value['action']]) && $this->requiresData[$value['action']]) {
if (isset($this->requiresData[$action]) && $this->requiresData[$action]) {
// Data is required for this action
if (!\array_key_exists('data', $value)) {
if (empty($data)) {
$this->description = "Missing required key: data";
return false;
}
if (!\is_array($value['data'])) {
$this->description = "Key 'data' must be an array";
return false;
}
} elseif (\array_key_exists('data', $value)) {
// Data is optional but if provided, must be an array
if (!\is_array($value['data'])) {
$this->description = "Key 'data' must be an array";
return false;
}
}
// Bulk operation specific validations
$action = $value['action'];
// BulkUpdate and BulkDelete require queries
if (\in_array($action, ['bulkUpdate', 'bulkDelete'])) {
if (!\array_key_exists('data', $value) || !\is_array($value['data'])) {
$this->description = "Key 'data' must be an array for {$action}";
return false;
}
if (!\array_key_exists('queries', $value['data'])) {
if (!\array_key_exists('queries', $data)) {
$this->description = "Key 'queries' is required in data for {$action}";
return false;
}
if (!\is_array($value['data']['queries'])) {
if (!\is_array($data['queries'])) {
$this->description = "Key 'queries' must be an array for {$action}";
return false;
}
@@ -180,11 +159,11 @@ class Operation extends Validator
// BulkUpdate requires both queries and data
if ($action === 'bulkUpdate') {
if (!\array_key_exists('data', $value['data'])) {
if (!\array_key_exists('data', $data)) {
$this->description = "Key 'data' is required in data for {$action}";
return false;
}
if (!\is_array($value['data']['data'])) {
if (!\is_array($data['data'])) {
$this->description = "Key 'data.data' must be an array for {$action}";
return false;
}
@@ -192,18 +171,14 @@ class Operation extends Validator
// Increment and Decrement require specific keys
if (\in_array($action, ['increment', 'decrement'])) {
if (!\array_key_exists('data', $value) || !\is_array($value['data'])) {
$this->description = "Key 'data' must be an array for {$action}";
return false;
}
// Get the attribute key name based on type
$attributeKey = $this->type === 'tablesdb' ? 'column' : 'attribute';
if (!\array_key_exists($attributeKey, $value['data'])) {
if (!\array_key_exists($attributeKey, $data)) {
$this->description = "Key '{$attributeKey}' is required in data for {$action}";
return false;
}
// Validate 'value' is numeric if provided (defaults to 1 if omitted)
if (\array_key_exists('value', $value['data']) && !\is_numeric($value['data']['value'])) {
if (\array_key_exists('value', $data) && !\is_numeric($data['value'])) {
$this->description = "Key 'value' must be a numeric value for {$action}";
return false;
}
+3
View File
@@ -12,6 +12,9 @@ use Utopia\Swoole\Request as UtopiaRequest;
class Request extends UtopiaRequest
{
public const string MODEL_TRANSACTION_OPERATION_LEGACY = 'transactionOperationLegacy';
public const string MODEL_TRANSACTION_OPERATION_TABLESDB = 'transactionOperationTablesDB';
/**
* @var array<Filter>
*/
+97
View File
@@ -0,0 +1,97 @@
<?php
namespace Appwrite\Utopia\Request;
abstract class Model
{
public const TYPE_STRING = 'string';
public const TYPE_INTEGER = 'integer';
public const TYPE_FLOAT = 'double';
public const TYPE_BOOLEAN = 'boolean';
public const TYPE_JSON = 'json';
public const TYPE_DATETIME = 'datetime';
public const TYPE_DATETIME_EXAMPLE = '2020-10-15T06:38:00.000+00:00';
public const TYPE_ARRAY = 'array';
public const TYPE_ENUM = 'enum';
/**
* @var array
*/
protected array $rules = [];
/**
* Get name
*
* @return string
*/
abstract public function getName(): string;
/**
* Get type
*
* @return string
*/
abstract public function getType(): string;
/**
* Get Rules
*
* @return array
*/
public function getRules(): array
{
return $this->rules;
}
/**
* Add a New Rule
* If rule is an array of documents with varying models
*
* @param string $key
* @param array $options
* @return Model
*/
protected function addRule(string $key, array $options): self
{
$this->rules[$key] = array_merge([
'required' => true,
'array' => false,
'description' => '',
'example' => '',
'sensitive' => false,
'readOnly' => false
], $options);
return $this;
}
/**
* Delete an existing Rule
* If rule exists, it will be removed
*
* @param string $key
* @return Model
*/
public function removeRule(string $key): self
{
if (isset($this->rules[$key])) {
unset($this->rules[$key]);
}
return $this;
}
/**
* @return array
*/
public function getRequired(): array
{
$list = [];
foreach ($this->rules as $key => $rule) {
if ($rule['required'] ?? false) {
$list[] = $key;
}
}
return $list;
}
}
@@ -0,0 +1,134 @@
<?php
namespace Appwrite\Utopia\Request\Model\Database\Legacy;
use Appwrite\Utopia\Request;
use Appwrite\Utopia\Request\Model;
/**
* TransactionOperation represents a single operation within a database transaction.
*/
class TransactionOperation extends Model implements \Utopia\Model
{
public function __construct(
private readonly string $databaseId = '',
private readonly string $collectionId = '',
private readonly ?string $documentId = null,
private readonly string $action = '',
private readonly array $data = [],
) {
$this
->addRule('databaseId', [
'type' => self::TYPE_STRING,
'description' => 'The ID of the database.',
'default' => '',
'example' => '5e5ea5c16897e',
])
->addRule('collectionId', [
'type' => self::TYPE_STRING,
'description' => 'The ID of the collection.',
'default' => '',
'example' => '5e5ea5c15117e',
])
->addRule('documentId', [
'type' => self::TYPE_STRING,
'description' => 'The ID of the document. Required for update, upsert, delete, increment, and decrement actions.',
'default' => null,
'example' => '5e5ea5c15117e',
'required' => false,
])
->addRule('action', [
'type' => self::TYPE_STRING,
'description' => 'The action to perform on the document.',
'default' => '',
'example' => 'create',
'enum' => [
'create',
'update',
'upsert',
'delete',
'increment',
'decrement',
'bulkCreate',
'bulkUpdate',
'bulkUpsert',
'bulkDelete',
],
])
->addRule('data', [
'type' => self::TYPE_JSON,
'description' => 'The data payload for the operation. Structure depends on the action type.',
'default' => new \stdClass(),
'example' => '{"name": "John Doe", "email": "john@example.com"}',
'required' => false,
]);
}
public function getName(): string
{
return 'Legacy\TransactionOperation';
}
public function getType(): string
{
return Request::MODEL_TRANSACTION_OPERATION_LEGACY;
}
public function getDatabaseId(): string
{
return $this->databaseId;
}
public function getCollectionId(): string
{
return $this->collectionId;
}
public function getDocumentId(): ?string
{
return $this->documentId;
}
public function getAction(): string
{
return $this->action;
}
public function getData(): array
{
return $this->data;
}
/**
* Convert array to TransactionOperation model.
*
* @param array $value
* @return static
*/
public static function fromArray(array $value): static
{
return new static(
databaseId: $value['databaseId'] ?? '',
collectionId: $value['collectionId'] ?? $value['tableId'] ?? '',
documentId: $value['documentId'] ?? $value['rowId'] ?? null,
action: $value['action'] ?? '',
data: $value['data'] ?? [],
);
}
/**
* Convert the model to an array representation.
*
* @return array<string, mixed>
*/
public function toArray(): array
{
return [
'databaseId' => $this->databaseId,
'collectionId' => $this->collectionId,
'documentId' => $this->documentId,
'action' => $this->action,
'data' => $this->data,
];
}
}
@@ -0,0 +1,107 @@
<?php
namespace Appwrite\Utopia\Request\Model\Database\TablesDB;
use Appwrite\Utopia\Request;
use Appwrite\Utopia\Request\Model\Database\Legacy\TransactionOperation as TransactionOperationLegacy;
/**
* TransactionOperation represents a single operation within a database transaction
* for the TablesDB API.
*
* This model uses tableId/rowId naming convention for SDK generation while internally
* mapping to the canonical collectionId/documentId fields.
*
* @implements \ArrayAccess<string, mixed>
*/
class TransactionOperation extends TransactionOperationLegacy
{
public function __construct(
string $databaseId = '',
string $tableId = '',
?string $rowId = null,
string $action = '',
array $data = [],
) {
parent::__construct(
databaseId: $databaseId,
collectionId: $tableId,
documentId: $rowId,
action: $action,
data: $data,
);
// Override rules with TablesDB naming convention
$this->removeRule('collectionId');
$this->removeRule('documentId');
$this
->addRule('tableId', [
'type' => self::TYPE_STRING,
'description' => 'The ID of the table.',
'default' => '',
'example' => '5e5ea5c15117e',
])
->addRule('rowId', [
'type' => self::TYPE_STRING,
'description' => 'The ID of the row. Required for update, upsert, delete, increment, and decrement actions.',
'default' => null,
'example' => '5e5ea5c15117e',
'required' => false,
]);
}
public function getName(): string
{
return 'TablesDB\TransactionOperation';
}
public function getType(): string
{
return Request::MODEL_TRANSACTION_OPERATION_TABLESDB;
}
public function getTableId(): string
{
return $this->getCollectionId();
}
public function getRowId(): ?string
{
return $this->getDocumentId();
}
/**
* Convert array to TransactionOperation model.
* Supports both TablesDB (tableId/rowId) and legacy (collectionId/documentId) naming conventions.
*
* @param array $value
* @return static
*/
public static function fromArray(array $value): static
{
return new static(
databaseId: $value['databaseId'] ?? '',
tableId: $value['tableId'] ?? $value['collectionId'] ?? '',
rowId: $value['rowId'] ?? $value['documentId'] ?? null,
action: $value['action'] ?? '',
data: $value['data'] ?? [],
);
}
/**
* Convert the model to an array representation using TablesDB naming.
*
* @return array<string, mixed>
*/
public function toArray(): array
{
return [
'databaseId' => $this->getDatabaseId(),
'tableId' => $this->getTableId(),
'rowId' => $this->getRowId(),
'action' => $this->getAction(),
'data' => $this->getData(),
];
}
}