Merge branch '1.6.x' into chore-request-response-filter-tests

This commit is contained in:
Khushboo Verma 2024-10-03 15:55:21 +05:30
commit d037ced578
37 changed files with 1501 additions and 267 deletions

View file

@ -4109,13 +4109,24 @@ $projectCollections = array_merge([
'$id' => ID::custom('source'), '$id' => ID::custom('source'),
'type' => Database::VAR_STRING, 'type' => Database::VAR_STRING,
'format' => '', 'format' => '',
'size' => 8192, 'size' => 8192, // reduce size
'signed' => true, 'signed' => true,
'required' => true, 'required' => true,
'default' => null, 'default' => null,
'array' => false, 'array' => false,
'filters' => [], 'filters' => [],
], ],
[
'$id' => ID::custom('destination'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => false, // make true after patch script
'default' => null,
'array' => false,
'filters' => [],
],
[ [
'$id' => ID::custom('credentials'), '$id' => ID::custom('credentials'),
'type' => Database::VAR_STRING, 'type' => Database::VAR_STRING,
@ -4138,6 +4149,28 @@ $projectCollections = array_merge([
'array' => true, 'array' => true,
'filters' => [], 'filters' => [],
], ],
[
'$id' => ID::custom('resourceId'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('resourceType'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[ [
'$id' => ID::custom('statusCounters'), '$id' => ID::custom('statusCounters'),
'type' => Database::VAR_STRING, 'type' => Database::VAR_STRING,

View file

@ -1,9 +1,5 @@
<?php <?php
const APP_PLATFORM_SERVER = 'server';
const APP_PLATFORM_CLIENT = 'client';
const APP_PLATFORM_CONSOLE = 'console';
return [ return [
APP_PLATFORM_CLIENT => [ APP_PLATFORM_CLIENT => [
'key' => APP_PLATFORM_CLIENT, 'key' => APP_PLATFORM_CLIENT,

View file

@ -75,7 +75,7 @@ $admins = [
'topics.write', 'topics.write',
'topics.read', 'topics.read',
'subscribers.write', 'subscribers.write',
'subscribers.read' 'subscribers.read',
]; ];
return [ return [

View file

@ -32948,6 +32948,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"size": { "size": {
"type": "integer", "type": "integer",
"description": "Attribute size.", "description": "Attribute size.",
@ -32967,6 +32977,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"size" "size"
] ]
}, },
@ -33005,6 +33017,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"min": { "min": {
"type": "integer", "type": "integer",
"description": "Minimum value to enforce for new documents.", "description": "Minimum value to enforce for new documents.",
@ -33032,7 +33054,9 @@
"type", "type",
"status", "status",
"error", "error",
"required" "required",
"$createdAt",
"$updatedAt"
] ]
}, },
"attributeFloat": { "attributeFloat": {
@ -33070,6 +33094,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"min": { "min": {
"type": "number", "type": "number",
"description": "Minimum value to enforce for new documents.", "description": "Minimum value to enforce for new documents.",
@ -33097,7 +33131,9 @@
"type", "type",
"status", "status",
"error", "error",
"required" "required",
"$createdAt",
"$updatedAt"
] ]
}, },
"attributeBoolean": { "attributeBoolean": {
@ -33135,6 +33171,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"default": { "default": {
"type": "boolean", "type": "boolean",
"description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "description": "Default value for attribute when not provided. Cannot be set when attribute is required.",
@ -33147,7 +33193,9 @@
"type", "type",
"status", "status",
"error", "error",
"required" "required",
"$createdAt",
"$updatedAt"
] ]
}, },
"attributeEmail": { "attributeEmail": {
@ -33185,6 +33233,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "String format.", "description": "String format.",
@ -33203,6 +33261,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -33241,6 +33301,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"elements": { "elements": {
"type": "array", "type": "array",
"description": "Array of elements in enumerated type.", "description": "Array of elements in enumerated type.",
@ -33267,6 +33337,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"elements", "elements",
"format" "format"
] ]
@ -33306,6 +33378,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "String format.", "description": "String format.",
@ -33324,6 +33406,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -33362,6 +33446,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "String format.", "description": "String format.",
@ -33380,6 +33474,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -33418,6 +33514,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "ISO 8601 format.", "description": "ISO 8601 format.",
@ -33436,6 +33542,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -33474,6 +33582,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"relatedCollection": { "relatedCollection": {
"type": "string", "type": "string",
"description": "The ID of the related collection.", "description": "The ID of the related collection.",
@ -33511,6 +33629,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"relatedCollection", "relatedCollection",
"relationType", "relationType",
"twoWay", "twoWay",
@ -33559,6 +33679,16 @@
}, },
"x-example": [], "x-example": [],
"nullable": true "nullable": true
},
"$createdAt": {
"type": "string",
"description": "Index creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Index update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
} }
}, },
"required": [ "required": [
@ -33566,7 +33696,9 @@
"type", "type",
"status", "status",
"error", "error",
"attributes" "attributes",
"$createdAt",
"$updatedAt"
] ]
}, },
"document": { "document": {

View file

@ -23678,6 +23678,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"size": { "size": {
"type": "integer", "type": "integer",
"description": "Attribute size.", "description": "Attribute size.",
@ -23697,6 +23707,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"size" "size"
] ]
}, },
@ -23735,6 +23747,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"min": { "min": {
"type": "integer", "type": "integer",
"description": "Minimum value to enforce for new documents.", "description": "Minimum value to enforce for new documents.",
@ -23762,7 +23784,9 @@
"type", "type",
"status", "status",
"error", "error",
"required" "required",
"$createdAt",
"$updatedAt"
] ]
}, },
"attributeFloat": { "attributeFloat": {
@ -23800,6 +23824,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"min": { "min": {
"type": "number", "type": "number",
"description": "Minimum value to enforce for new documents.", "description": "Minimum value to enforce for new documents.",
@ -23827,7 +23861,9 @@
"type", "type",
"status", "status",
"error", "error",
"required" "required",
"$createdAt",
"$updatedAt"
] ]
}, },
"attributeBoolean": { "attributeBoolean": {
@ -23865,6 +23901,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"default": { "default": {
"type": "boolean", "type": "boolean",
"description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "description": "Default value for attribute when not provided. Cannot be set when attribute is required.",
@ -23877,7 +23923,9 @@
"type", "type",
"status", "status",
"error", "error",
"required" "required",
"$createdAt",
"$updatedAt"
] ]
}, },
"attributeEmail": { "attributeEmail": {
@ -23915,6 +23963,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "String format.", "description": "String format.",
@ -23933,6 +23991,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -23971,6 +24031,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"elements": { "elements": {
"type": "array", "type": "array",
"description": "Array of elements in enumerated type.", "description": "Array of elements in enumerated type.",
@ -23997,6 +24067,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"elements", "elements",
"format" "format"
] ]
@ -24036,6 +24108,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "String format.", "description": "String format.",
@ -24054,6 +24136,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -24092,6 +24176,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "String format.", "description": "String format.",
@ -24110,6 +24204,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -24148,6 +24244,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "ISO 8601 format.", "description": "ISO 8601 format.",
@ -24166,6 +24272,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -24204,6 +24312,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"relatedCollection": { "relatedCollection": {
"type": "string", "type": "string",
"description": "The ID of the related collection.", "description": "The ID of the related collection.",
@ -24241,6 +24359,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"relatedCollection", "relatedCollection",
"relationType", "relationType",
"twoWay", "twoWay",
@ -24289,6 +24409,16 @@
}, },
"x-example": [], "x-example": [],
"nullable": true "nullable": true
},
"$createdAt": {
"type": "string",
"description": "Index creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Index update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
} }
}, },
"required": [ "required": [
@ -24296,7 +24426,9 @@
"type", "type",
"status", "status",
"error", "error",
"attributes" "attributes",
"$createdAt",
"$updatedAt"
] ]
}, },
"document": { "document": {

View file

@ -32948,6 +32948,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"size": { "size": {
"type": "integer", "type": "integer",
"description": "Attribute size.", "description": "Attribute size.",
@ -32967,6 +32977,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"size" "size"
] ]
}, },
@ -33005,6 +33017,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"min": { "min": {
"type": "integer", "type": "integer",
"description": "Minimum value to enforce for new documents.", "description": "Minimum value to enforce for new documents.",
@ -33032,7 +33054,9 @@
"type", "type",
"status", "status",
"error", "error",
"required" "required",
"$createdAt",
"$updatedAt"
] ]
}, },
"attributeFloat": { "attributeFloat": {
@ -33070,6 +33094,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"min": { "min": {
"type": "number", "type": "number",
"description": "Minimum value to enforce for new documents.", "description": "Minimum value to enforce for new documents.",
@ -33097,7 +33131,9 @@
"type", "type",
"status", "status",
"error", "error",
"required" "required",
"$createdAt",
"$updatedAt"
] ]
}, },
"attributeBoolean": { "attributeBoolean": {
@ -33135,6 +33171,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"default": { "default": {
"type": "boolean", "type": "boolean",
"description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "description": "Default value for attribute when not provided. Cannot be set when attribute is required.",
@ -33147,7 +33193,9 @@
"type", "type",
"status", "status",
"error", "error",
"required" "required",
"$createdAt",
"$updatedAt"
] ]
}, },
"attributeEmail": { "attributeEmail": {
@ -33185,6 +33233,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "String format.", "description": "String format.",
@ -33203,6 +33261,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -33241,6 +33301,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"elements": { "elements": {
"type": "array", "type": "array",
"description": "Array of elements in enumerated type.", "description": "Array of elements in enumerated type.",
@ -33267,6 +33337,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"elements", "elements",
"format" "format"
] ]
@ -33306,6 +33378,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "String format.", "description": "String format.",
@ -33324,6 +33406,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -33362,6 +33446,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "String format.", "description": "String format.",
@ -33380,6 +33474,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -33418,6 +33514,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "ISO 8601 format.", "description": "ISO 8601 format.",
@ -33436,6 +33542,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -33474,6 +33582,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"relatedCollection": { "relatedCollection": {
"type": "string", "type": "string",
"description": "The ID of the related collection.", "description": "The ID of the related collection.",
@ -33511,6 +33629,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"relatedCollection", "relatedCollection",
"relationType", "relationType",
"twoWay", "twoWay",
@ -33559,6 +33679,16 @@
}, },
"x-example": [], "x-example": [],
"nullable": true "nullable": true
},
"$createdAt": {
"type": "string",
"description": "Index creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Index update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
} }
}, },
"required": [ "required": [
@ -33566,7 +33696,9 @@
"type", "type",
"status", "status",
"error", "error",
"attributes" "attributes",
"$createdAt",
"$updatedAt"
] ]
}, },
"document": { "document": {

View file

@ -23678,6 +23678,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"size": { "size": {
"type": "integer", "type": "integer",
"description": "Attribute size.", "description": "Attribute size.",
@ -23697,6 +23707,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"size" "size"
] ]
}, },
@ -23735,6 +23747,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"min": { "min": {
"type": "integer", "type": "integer",
"description": "Minimum value to enforce for new documents.", "description": "Minimum value to enforce for new documents.",
@ -23762,7 +23784,9 @@
"type", "type",
"status", "status",
"error", "error",
"required" "required",
"$createdAt",
"$updatedAt"
] ]
}, },
"attributeFloat": { "attributeFloat": {
@ -23800,6 +23824,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"min": { "min": {
"type": "number", "type": "number",
"description": "Minimum value to enforce for new documents.", "description": "Minimum value to enforce for new documents.",
@ -23827,7 +23861,9 @@
"type", "type",
"status", "status",
"error", "error",
"required" "required",
"$createdAt",
"$updatedAt"
] ]
}, },
"attributeBoolean": { "attributeBoolean": {
@ -23865,6 +23901,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"default": { "default": {
"type": "boolean", "type": "boolean",
"description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "description": "Default value for attribute when not provided. Cannot be set when attribute is required.",
@ -23877,7 +23923,9 @@
"type", "type",
"status", "status",
"error", "error",
"required" "required",
"$createdAt",
"$updatedAt"
] ]
}, },
"attributeEmail": { "attributeEmail": {
@ -23915,6 +23963,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "String format.", "description": "String format.",
@ -23933,6 +23991,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -23971,6 +24031,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"elements": { "elements": {
"type": "array", "type": "array",
"description": "Array of elements in enumerated type.", "description": "Array of elements in enumerated type.",
@ -23997,6 +24067,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"elements", "elements",
"format" "format"
] ]
@ -24036,6 +24108,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "String format.", "description": "String format.",
@ -24054,6 +24136,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -24092,6 +24176,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "String format.", "description": "String format.",
@ -24110,6 +24204,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -24148,6 +24244,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "ISO 8601 format.", "description": "ISO 8601 format.",
@ -24166,6 +24272,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -24204,6 +24312,16 @@
"x-example": false, "x-example": false,
"nullable": true "nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"relatedCollection": { "relatedCollection": {
"type": "string", "type": "string",
"description": "The ID of the related collection.", "description": "The ID of the related collection.",
@ -24241,6 +24359,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"relatedCollection", "relatedCollection",
"relationType", "relationType",
"twoWay", "twoWay",
@ -24289,6 +24409,16 @@
}, },
"x-example": [], "x-example": [],
"nullable": true "nullable": true
},
"$createdAt": {
"type": "string",
"description": "Index creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Index update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
} }
}, },
"required": [ "required": [
@ -24296,7 +24426,9 @@
"type", "type",
"status", "status",
"error", "error",
"attributes" "attributes",
"$createdAt",
"$updatedAt"
] ]
}, },
"document": { "document": {

View file

@ -33458,6 +33458,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"size": { "size": {
"type": "integer", "type": "integer",
"description": "Attribute size.", "description": "Attribute size.",
@ -33477,6 +33487,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"size" "size"
] ]
}, },
@ -33515,6 +33527,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"min": { "min": {
"type": "integer", "type": "integer",
"description": "Minimum value to enforce for new documents.", "description": "Minimum value to enforce for new documents.",
@ -33542,7 +33564,9 @@
"type", "type",
"status", "status",
"error", "error",
"required" "required",
"$createdAt",
"$updatedAt"
] ]
}, },
"attributeFloat": { "attributeFloat": {
@ -33580,6 +33604,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"min": { "min": {
"type": "number", "type": "number",
"description": "Minimum value to enforce for new documents.", "description": "Minimum value to enforce for new documents.",
@ -33607,7 +33641,9 @@
"type", "type",
"status", "status",
"error", "error",
"required" "required",
"$createdAt",
"$updatedAt"
] ]
}, },
"attributeBoolean": { "attributeBoolean": {
@ -33645,6 +33681,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"default": { "default": {
"type": "boolean", "type": "boolean",
"description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "description": "Default value for attribute when not provided. Cannot be set when attribute is required.",
@ -33657,7 +33703,9 @@
"type", "type",
"status", "status",
"error", "error",
"required" "required",
"$createdAt",
"$updatedAt"
] ]
}, },
"attributeEmail": { "attributeEmail": {
@ -33695,6 +33743,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "String format.", "description": "String format.",
@ -33713,6 +33771,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -33751,6 +33811,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"elements": { "elements": {
"type": "array", "type": "array",
"description": "Array of elements in enumerated type.", "description": "Array of elements in enumerated type.",
@ -33777,6 +33847,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"elements", "elements",
"format" "format"
] ]
@ -33816,6 +33888,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "String format.", "description": "String format.",
@ -33834,6 +33916,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -33872,6 +33956,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "String format.", "description": "String format.",
@ -33890,6 +33984,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -33928,6 +34024,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "ISO 8601 format.", "description": "ISO 8601 format.",
@ -33946,6 +34052,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -33984,6 +34092,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"relatedCollection": { "relatedCollection": {
"type": "string", "type": "string",
"description": "The ID of the related collection.", "description": "The ID of the related collection.",
@ -34021,6 +34139,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"relatedCollection", "relatedCollection",
"relationType", "relationType",
"twoWay", "twoWay",
@ -34069,6 +34189,16 @@
}, },
"x-example": [], "x-example": [],
"x-nullable": true "x-nullable": true
},
"$createdAt": {
"type": "string",
"description": "Index creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Index update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
} }
}, },
"required": [ "required": [
@ -34076,7 +34206,9 @@
"type", "type",
"status", "status",
"error", "error",
"attributes" "attributes",
"$createdAt",
"$updatedAt"
] ]
}, },
"document": { "document": {

View file

@ -24167,6 +24167,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"size": { "size": {
"type": "integer", "type": "integer",
"description": "Attribute size.", "description": "Attribute size.",
@ -24186,6 +24196,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"size" "size"
] ]
}, },
@ -24224,6 +24236,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"min": { "min": {
"type": "integer", "type": "integer",
"description": "Minimum value to enforce for new documents.", "description": "Minimum value to enforce for new documents.",
@ -24251,7 +24273,9 @@
"type", "type",
"status", "status",
"error", "error",
"required" "required",
"$createdAt",
"$updatedAt"
] ]
}, },
"attributeFloat": { "attributeFloat": {
@ -24289,6 +24313,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"min": { "min": {
"type": "number", "type": "number",
"description": "Minimum value to enforce for new documents.", "description": "Minimum value to enforce for new documents.",
@ -24316,7 +24350,9 @@
"type", "type",
"status", "status",
"error", "error",
"required" "required",
"$createdAt",
"$updatedAt"
] ]
}, },
"attributeBoolean": { "attributeBoolean": {
@ -24354,6 +24390,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"default": { "default": {
"type": "boolean", "type": "boolean",
"description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "description": "Default value for attribute when not provided. Cannot be set when attribute is required.",
@ -24366,7 +24412,9 @@
"type", "type",
"status", "status",
"error", "error",
"required" "required",
"$createdAt",
"$updatedAt"
] ]
}, },
"attributeEmail": { "attributeEmail": {
@ -24404,6 +24452,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "String format.", "description": "String format.",
@ -24422,6 +24480,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -24460,6 +24520,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"elements": { "elements": {
"type": "array", "type": "array",
"description": "Array of elements in enumerated type.", "description": "Array of elements in enumerated type.",
@ -24486,6 +24556,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"elements", "elements",
"format" "format"
] ]
@ -24525,6 +24597,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "String format.", "description": "String format.",
@ -24543,6 +24625,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -24581,6 +24665,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "String format.", "description": "String format.",
@ -24599,6 +24693,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -24637,6 +24733,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "ISO 8601 format.", "description": "ISO 8601 format.",
@ -24655,6 +24761,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -24693,6 +24801,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"relatedCollection": { "relatedCollection": {
"type": "string", "type": "string",
"description": "The ID of the related collection.", "description": "The ID of the related collection.",
@ -24730,6 +24848,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"relatedCollection", "relatedCollection",
"relationType", "relationType",
"twoWay", "twoWay",
@ -24778,6 +24898,16 @@
}, },
"x-example": [], "x-example": [],
"x-nullable": true "x-nullable": true
},
"$createdAt": {
"type": "string",
"description": "Index creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Index update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
} }
}, },
"required": [ "required": [
@ -24785,7 +24915,9 @@
"type", "type",
"status", "status",
"error", "error",
"attributes" "attributes",
"$createdAt",
"$updatedAt"
] ]
}, },
"document": { "document": {

View file

@ -33458,6 +33458,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"size": { "size": {
"type": "integer", "type": "integer",
"description": "Attribute size.", "description": "Attribute size.",
@ -33477,6 +33487,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"size" "size"
] ]
}, },
@ -33515,6 +33527,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"min": { "min": {
"type": "integer", "type": "integer",
"description": "Minimum value to enforce for new documents.", "description": "Minimum value to enforce for new documents.",
@ -33542,7 +33564,9 @@
"type", "type",
"status", "status",
"error", "error",
"required" "required",
"$createdAt",
"$updatedAt"
] ]
}, },
"attributeFloat": { "attributeFloat": {
@ -33580,6 +33604,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"min": { "min": {
"type": "number", "type": "number",
"description": "Minimum value to enforce for new documents.", "description": "Minimum value to enforce for new documents.",
@ -33607,7 +33641,9 @@
"type", "type",
"status", "status",
"error", "error",
"required" "required",
"$createdAt",
"$updatedAt"
] ]
}, },
"attributeBoolean": { "attributeBoolean": {
@ -33645,6 +33681,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"default": { "default": {
"type": "boolean", "type": "boolean",
"description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "description": "Default value for attribute when not provided. Cannot be set when attribute is required.",
@ -33657,7 +33703,9 @@
"type", "type",
"status", "status",
"error", "error",
"required" "required",
"$createdAt",
"$updatedAt"
] ]
}, },
"attributeEmail": { "attributeEmail": {
@ -33695,6 +33743,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "String format.", "description": "String format.",
@ -33713,6 +33771,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -33751,6 +33811,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"elements": { "elements": {
"type": "array", "type": "array",
"description": "Array of elements in enumerated type.", "description": "Array of elements in enumerated type.",
@ -33777,6 +33847,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"elements", "elements",
"format" "format"
] ]
@ -33816,6 +33888,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "String format.", "description": "String format.",
@ -33834,6 +33916,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -33872,6 +33956,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "String format.", "description": "String format.",
@ -33890,6 +33984,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -33928,6 +34024,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "ISO 8601 format.", "description": "ISO 8601 format.",
@ -33946,6 +34052,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -33984,6 +34092,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"relatedCollection": { "relatedCollection": {
"type": "string", "type": "string",
"description": "The ID of the related collection.", "description": "The ID of the related collection.",
@ -34021,6 +34139,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"relatedCollection", "relatedCollection",
"relationType", "relationType",
"twoWay", "twoWay",
@ -34069,6 +34189,16 @@
}, },
"x-example": [], "x-example": [],
"x-nullable": true "x-nullable": true
},
"$createdAt": {
"type": "string",
"description": "Index creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Index update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
} }
}, },
"required": [ "required": [
@ -34076,7 +34206,9 @@
"type", "type",
"status", "status",
"error", "error",
"attributes" "attributes",
"$createdAt",
"$updatedAt"
] ]
}, },
"document": { "document": {

View file

@ -24167,6 +24167,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"size": { "size": {
"type": "integer", "type": "integer",
"description": "Attribute size.", "description": "Attribute size.",
@ -24186,6 +24196,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"size" "size"
] ]
}, },
@ -24224,6 +24236,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"min": { "min": {
"type": "integer", "type": "integer",
"description": "Minimum value to enforce for new documents.", "description": "Minimum value to enforce for new documents.",
@ -24251,7 +24273,9 @@
"type", "type",
"status", "status",
"error", "error",
"required" "required",
"$createdAt",
"$updatedAt"
] ]
}, },
"attributeFloat": { "attributeFloat": {
@ -24289,6 +24313,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"min": { "min": {
"type": "number", "type": "number",
"description": "Minimum value to enforce for new documents.", "description": "Minimum value to enforce for new documents.",
@ -24316,7 +24350,9 @@
"type", "type",
"status", "status",
"error", "error",
"required" "required",
"$createdAt",
"$updatedAt"
] ]
}, },
"attributeBoolean": { "attributeBoolean": {
@ -24354,6 +24390,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"default": { "default": {
"type": "boolean", "type": "boolean",
"description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "description": "Default value for attribute when not provided. Cannot be set when attribute is required.",
@ -24366,7 +24412,9 @@
"type", "type",
"status", "status",
"error", "error",
"required" "required",
"$createdAt",
"$updatedAt"
] ]
}, },
"attributeEmail": { "attributeEmail": {
@ -24404,6 +24452,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "String format.", "description": "String format.",
@ -24422,6 +24480,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -24460,6 +24520,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"elements": { "elements": {
"type": "array", "type": "array",
"description": "Array of elements in enumerated type.", "description": "Array of elements in enumerated type.",
@ -24486,6 +24556,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"elements", "elements",
"format" "format"
] ]
@ -24525,6 +24597,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "String format.", "description": "String format.",
@ -24543,6 +24625,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -24581,6 +24665,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "String format.", "description": "String format.",
@ -24599,6 +24693,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -24637,6 +24733,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"format": { "format": {
"type": "string", "type": "string",
"description": "ISO 8601 format.", "description": "ISO 8601 format.",
@ -24655,6 +24761,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"format" "format"
] ]
}, },
@ -24693,6 +24801,16 @@
"x-example": false, "x-example": false,
"x-nullable": true "x-nullable": true
}, },
"$createdAt": {
"type": "string",
"description": "Attribute creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Attribute update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"relatedCollection": { "relatedCollection": {
"type": "string", "type": "string",
"description": "The ID of the related collection.", "description": "The ID of the related collection.",
@ -24730,6 +24848,8 @@
"status", "status",
"error", "error",
"required", "required",
"$createdAt",
"$updatedAt",
"relatedCollection", "relatedCollection",
"relationType", "relationType",
"twoWay", "twoWay",
@ -24778,6 +24898,16 @@
}, },
"x-example": [], "x-example": [],
"x-nullable": true "x-nullable": true
},
"$createdAt": {
"type": "string",
"description": "Index creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"$updatedAt": {
"type": "string",
"description": "Index update date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
} }
}, },
"required": [ "required": [
@ -24785,7 +24915,9 @@
"type", "type",
"status", "status",
"error", "error",
"attributes" "attributes",
"$createdAt",
"$updatedAt"
] ]
}, },
"document": { "document": {

View file

@ -2509,7 +2509,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes')
'required' => true, 'required' => true,
'array' => false, 'array' => false,
'default' => null, 'default' => null,
'size' => 36 'size' => Database::LENGTH_KEY
]; ];
$oldAttributes[] = [ $oldAttributes[] = [

View file

@ -60,6 +60,7 @@ App::post('/v1/migrations/appwrite')
'status' => 'pending', 'status' => 'pending',
'stage' => 'init', 'stage' => 'init',
'source' => Appwrite::getName(), 'source' => Appwrite::getName(),
'destination' => Appwrite::getName(),
'credentials' => [ 'credentials' => [
'endpoint' => $endpoint, 'endpoint' => $endpoint,
'projectId' => $projectId, 'projectId' => $projectId,
@ -164,6 +165,7 @@ App::post('/v1/migrations/firebase/oauth')
'status' => 'pending', 'status' => 'pending',
'stage' => 'init', 'stage' => 'init',
'source' => Firebase::getName(), 'source' => Firebase::getName(),
'destination' => Appwrite::getName(),
'credentials' => [ 'credentials' => [
'serviceAccount' => json_encode($serviceAccount), 'serviceAccount' => json_encode($serviceAccount),
], ],
@ -224,6 +226,7 @@ App::post('/v1/migrations/firebase')
'status' => 'pending', 'status' => 'pending',
'stage' => 'init', 'stage' => 'init',
'source' => Firebase::getName(), 'source' => Firebase::getName(),
'destination' => Appwrite::getName(),
'credentials' => [ 'credentials' => [
'serviceAccount' => $serviceAccount, 'serviceAccount' => $serviceAccount,
], ],
@ -279,6 +282,7 @@ App::post('/v1/migrations/supabase')
'status' => 'pending', 'status' => 'pending',
'stage' => 'init', 'stage' => 'init',
'source' => Supabase::getName(), 'source' => Supabase::getName(),
'destination' => Appwrite::getName(),
'credentials' => [ 'credentials' => [
'endpoint' => $endpoint, 'endpoint' => $endpoint,
'apiKey' => $apiKey, 'apiKey' => $apiKey,
@ -340,6 +344,7 @@ App::post('/v1/migrations/nhost')
'status' => 'pending', 'status' => 'pending',
'stage' => 'init', 'stage' => 'init',
'source' => NHost::getName(), 'source' => NHost::getName(),
'destination' => Appwrite::getName(),
'credentials' => [ 'credentials' => [
'subdomain' => $subdomain, 'subdomain' => $subdomain,
'region' => $region, 'region' => $region,

View file

@ -923,6 +923,7 @@ App::delete('/v1/projects/:projectId')
} }
$queueForDeletes $queueForDeletes
->setProject($project)
->setType(DELETE_TYPE_DOCUMENT) ->setType(DELETE_TYPE_DOCUMENT)
->setDocument($project); ->setDocument($project);

View file

@ -152,6 +152,9 @@ const APP_HOSTNAME_INTERNAL = 'appwrite';
const APP_FUNCTION_SPECIFICATION_DEFAULT = Specification::S_05VCPU_512MB; const APP_FUNCTION_SPECIFICATION_DEFAULT = Specification::S_05VCPU_512MB;
const APP_FUNCTION_CPUS_DEFAULT = 0.5; const APP_FUNCTION_CPUS_DEFAULT = 0.5;
const APP_FUNCTION_MEMORY_DEFAULT = 512; const APP_FUNCTION_MEMORY_DEFAULT = 512;
const APP_PLATFORM_SERVER = 'server';
const APP_PLATFORM_CLIENT = 'client';
const APP_PLATFORM_CONSOLE = 'console';
// Database Reconnect // Database Reconnect
const DATABASE_RECONNECT_SLEEP = 2; const DATABASE_RECONNECT_SLEEP = 2;
@ -1520,9 +1523,9 @@ App::setResource('deviceForBuilds', function ($project) {
return getDevice(APP_STORAGE_BUILDS . '/app-' . $project->getId()); return getDevice(APP_STORAGE_BUILDS . '/app-' . $project->getId());
}, ['project']); }, ['project']);
function getDevice($root): Device function getDevice(string $root, string $connection = ''): Device
{ {
$connection = System::getEnv('_APP_CONNECTIONS_STORAGE', ''); $connection = !empty($connection) ? $connection : System::getEnv('_APP_CONNECTIONS_STORAGE', '');
if (!empty($connection)) { if (!empty($connection)) {
$acl = 'private'; $acl = 'private';

View file

@ -40,7 +40,7 @@ require_once __DIR__ . '/init.php';
Runtime::enableCoroutine(SWOOLE_HOOK_ALL); Runtime::enableCoroutine(SWOOLE_HOOK_ALL);
// Allows overriding // Allows overriding
if (!function_exists("getConsoleDB")) { if (!function_exists('getConsoleDB')) {
function getConsoleDB(): Database function getConsoleDB(): Database
{ {
global $register; global $register;
@ -66,7 +66,7 @@ if (!function_exists("getConsoleDB")) {
} }
// Allows overriding // Allows overriding
if (!function_exists("getProjectDB")) { if (!function_exists('getProjectDB')) {
function getProjectDB(Document $project): Database function getProjectDB(Document $project): Database
{ {
global $register; global $register;
@ -113,7 +113,7 @@ if (!function_exists("getProjectDB")) {
} }
// Allows overriding // Allows overriding
if (!function_exists("getCache")) { if (!function_exists('getCache')) {
function getCache(): Cache function getCache(): Cache
{ {
global $register; global $register;
@ -135,7 +135,14 @@ if (!function_exists("getCache")) {
} }
} }
$realtime = new Realtime(); if (!function_exists('getRealtime')) {
function getRealtime(): Realtime
{
return new Realtime();
}
}
$realtime = getRealtime();
/** /**
* Table for statistics across all workers. * Table for statistics across all workers.

View file

@ -58,7 +58,7 @@ Server::setResource('project', function (Message $message, Database $dbForConsol
$payload = $message->getPayload() ?? []; $payload = $message->getPayload() ?? [];
$project = new Document($payload['project'] ?? []); $project = new Document($payload['project'] ?? []);
if ($project->getId() === 'console') { if ($project->getId() === 'console' || $project->isEmpty() || ! empty($project->getInternalId())) {
return $project; return $project;
} }

View file

@ -60,7 +60,7 @@
"utopia-php/locale": "0.4.*", "utopia-php/locale": "0.4.*",
"utopia-php/logger": "0.6.*", "utopia-php/logger": "0.6.*",
"utopia-php/messaging": "0.12.*", "utopia-php/messaging": "0.12.*",
"utopia-php/migration": "0.5.*", "utopia-php/migration": "0.6.*",
"utopia-php/orchestration": "0.9.*", "utopia-php/orchestration": "0.9.*",
"utopia-php/platform": "0.7.*", "utopia-php/platform": "0.7.*",
"utopia-php/pools": "0.5.*", "utopia-php/pools": "0.5.*",

49
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "66e31af1f7d0d1617694a1c5a975f887", "content-hash": "1884e3a2966762c4a955842426b64f6c",
"packages": [ "packages": [
{ {
"name": "adhocore/jwt", "name": "adhocore/jwt",
@ -65,16 +65,16 @@
}, },
{ {
"name": "appwrite/appwrite", "name": "appwrite/appwrite",
"version": "10.1.0", "version": "11.1.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/appwrite/sdk-for-php.git", "url": "https://github.com/appwrite/sdk-for-php.git",
"reference": "da579af70723cfc117b5af84375bdef117e27312" "reference": "1d043f543acdb17b9fdb440b1b2dd208e400bad3"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/appwrite/sdk-for-php/zipball/da579af70723cfc117b5af84375bdef117e27312", "url": "https://api.github.com/repos/appwrite/sdk-for-php/zipball/1d043f543acdb17b9fdb440b1b2dd208e400bad3",
"reference": "da579af70723cfc117b5af84375bdef117e27312", "reference": "1d043f543acdb17b9fdb440b1b2dd208e400bad3",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -83,7 +83,8 @@
"php": ">=7.1.0" "php": ">=7.1.0"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "3.7.35" "mockery/mockery": "^1.6.6",
"phpunit/phpunit": "^10"
}, },
"type": "library", "type": "library",
"autoload": { "autoload": {
@ -99,10 +100,10 @@
"support": { "support": {
"email": "team@appwrite.io", "email": "team@appwrite.io",
"issues": "https://github.com/appwrite/sdk-for-php/issues", "issues": "https://github.com/appwrite/sdk-for-php/issues",
"source": "https://github.com/appwrite/sdk-for-php/tree/10.1.0", "source": "https://github.com/appwrite/sdk-for-php/tree/11.1.0",
"url": "https://appwrite.io/support" "url": "https://appwrite.io/support"
}, },
"time": "2023-11-20T09:56:12+00:00" "time": "2024-06-26T07:03:23+00:00"
}, },
{ {
"name": "appwrite/php-clamav", "name": "appwrite/php-clamav",
@ -2174,27 +2175,35 @@
}, },
{ {
"name": "utopia-php/migration", "name": "utopia-php/migration",
"version": "0.5.3", "version": "0.6.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/utopia-php/migration.git", "url": "https://github.com/utopia-php/migration.git",
"reference": "b30e7834da69e25084b0c8e9ba29e4a7b54c6eb6" "reference": "e43ef283f1386084e11d1ffe093fb6c6d7a6ce6c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/utopia-php/migration/zipball/b30e7834da69e25084b0c8e9ba29e4a7b54c6eb6", "url": "https://api.github.com/repos/utopia-php/migration/zipball/e43ef283f1386084e11d1ffe093fb6c6d7a6ce6c",
"reference": "b30e7834da69e25084b0c8e9ba29e4a7b54c6eb6", "reference": "e43ef283f1386084e11d1ffe093fb6c6d7a6ce6c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"appwrite/appwrite": "10.1.0", "appwrite/appwrite": "11.1.*",
"php": "8.*" "ext-curl": "*",
"ext-openssl": "*",
"php": "8.3.*",
"utopia-php/database": "0.53.*",
"utopia-php/dsn": "0.2.*",
"utopia-php/framework": "0.33.*",
"utopia-php/storage": "0.18.*"
}, },
"require-dev": { "require-dev": {
"laravel/pint": "1.*", "ext-pdo": "*",
"phpunit/phpunit": "9.*", "laravel/pint": "1.17.*",
"utopia-php/cli": "^0.18.0", "phpstan/phpstan": "1.11.*",
"vlucas/phpdotenv": "5.*" "phpunit/phpunit": "11.2.*",
"utopia-php/cli": "0.16.*",
"vlucas/phpdotenv": "5.6.*"
}, },
"type": "library", "type": "library",
"autoload": { "autoload": {
@ -2216,9 +2225,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/utopia-php/migration/issues", "issues": "https://github.com/utopia-php/migration/issues",
"source": "https://github.com/utopia-php/migration/tree/0.5.3" "source": "https://github.com/utopia-php/migration/tree/0.6.4"
}, },
"time": "2024-09-10T10:45:18+00:00" "time": "2024-10-02T15:16:36+00:00"
}, },
{ {
"name": "utopia-php/mongo", "name": "utopia-php/mongo",

View file

@ -81,7 +81,7 @@ class Migration extends Event
return $client->enqueue([ return $client->enqueue([
'project' => $this->project, 'project' => $this->project,
'user' => $this->user, 'user' => $this->user,
'migration' => $this->migration 'migration' => $this->migration,
]); ]);
} }
} }

View file

@ -243,7 +243,11 @@ class Realtime extends Adapter
* @param string $event * @param string $event
* @param Document $payload * @param Document $payload
* @param Document|null $project * @param Document|null $project
* @param Document|null $database
* @param Document|null $collection
* @param Document|null $bucket
* @return array * @return array
* @throws \Exception
*/ */
public static function fromPayload(string $event, Document $payload, Document $project = null, Document $database = null, Document $collection = null, Document $bucket = null): array public static function fromPayload(string $event, Document $payload, Document $project = null, Document $database = null, Document $collection = null, Document $bucket = null): array
{ {
@ -262,6 +266,7 @@ class Realtime extends Adapter
break; break;
case 'rules': case 'rules':
$channels[] = 'console'; $channels[] = 'console';
$channels[] = 'projects.' . $project->getId();
$projectId = 'console'; $projectId = 'console';
$roles = [Role::team($project->getAttribute('teamId'))->toString()]; $roles = [Role::team($project->getAttribute('teamId'))->toString()];
break; break;
@ -280,6 +285,7 @@ class Realtime extends Adapter
case 'databases': case 'databases':
if (in_array($parts[4] ?? [], ['attributes', 'indexes'])) { if (in_array($parts[4] ?? [], ['attributes', 'indexes'])) {
$channels[] = 'console'; $channels[] = 'console';
$channels[] = 'projects.' . $project->getId();
$projectId = 'console'; $projectId = 'console';
$roles = [Role::team($project->getAttribute('teamId'))->toString()]; $roles = [Role::team($project->getAttribute('teamId'))->toString()];
} elseif (($parts[4] ?? '') === 'documents') { } elseif (($parts[4] ?? '') === 'documents') {
@ -319,6 +325,7 @@ class Realtime extends Adapter
if ($parts[2] === 'executions') { if ($parts[2] === 'executions') {
if (!empty($payload->getRead())) { if (!empty($payload->getRead())) {
$channels[] = 'console'; $channels[] = 'console';
$channels[] = 'projects.' . $project->getId();
$channels[] = 'executions'; $channels[] = 'executions';
$channels[] = 'executions.' . $payload->getId(); $channels[] = 'executions.' . $payload->getId();
$channels[] = 'functions.' . $payload->getAttribute('functionId'); $channels[] = 'functions.' . $payload->getAttribute('functionId');
@ -326,6 +333,7 @@ class Realtime extends Adapter
} }
} elseif ($parts[2] === 'deployments') { } elseif ($parts[2] === 'deployments') {
$channels[] = 'console'; $channels[] = 'console';
$channels[] = 'projects.' . $project->getId();
$projectId = 'console'; $projectId = 'console';
$roles = [Role::team($project->getAttribute('teamId'))->toString()]; $roles = [Role::team($project->getAttribute('teamId'))->toString()];
} }
@ -333,6 +341,7 @@ class Realtime extends Adapter
break; break;
case 'migrations': case 'migrations':
$channels[] = 'console'; $channels[] = 'console';
$channels[] = 'projects.' . $project->getId();
$projectId = 'console'; $projectId = 'console';
$roles = [Role::team($project->getAttribute('teamId'))->toString()]; $roles = [Role::team($project->getAttribute('teamId'))->toString()];
break; break;

View file

@ -49,12 +49,7 @@ class Maintenance extends Action
$this->foreachProject($dbForConsole, function (Document $project) use ($queueForDeletes, $usageStatsRetentionHourly) { $this->foreachProject($dbForConsole, function (Document $project) use ($queueForDeletes, $usageStatsRetentionHourly) {
$queueForDeletes->setProject($project); $queueForDeletes->setProject($project);
$this->notifyDeleteTargets($queueForDeletes); $this->notifyProjects($queueForDeletes, $usageStatsRetentionHourly);
$this->notifyDeleteExecutionLogs($queueForDeletes);
$this->notifyDeleteAbuseLogs($queueForDeletes);
$this->notifyDeleteAuditLogs($queueForDeletes);
$this->notifyDeleteUsageStats($usageStatsRetentionHourly, $queueForDeletes);
$this->notifyDeleteExpiredSessions($queueForDeletes);
}); });
$this->notifyDeleteConnections($queueForDeletes); $this->notifyDeleteConnections($queueForDeletes);
@ -64,6 +59,19 @@ class Maintenance extends Action
}, $interval, $delay); }, $interval, $delay);
} }
/**
* Hook to allow sub-classes to extend project-level maintenance functionality.
*/
protected function notifyProjects(Delete $queueForDeletes, int $usageStatsRetentionHourly): void
{
$this->notifyDeleteTargets($queueForDeletes);
$this->notifyDeleteExecutionLogs($queueForDeletes);
$this->notifyDeleteAbuseLogs($queueForDeletes);
$this->notifyDeleteAuditLogs($queueForDeletes);
$this->notifyDeleteUsageStats($usageStatsRetentionHourly, $queueForDeletes);
$this->notifyDeleteExpiredSessions($queueForDeletes);
}
protected function foreachProject(Database $dbForConsole, callable $callback): void protected function foreachProject(Database $dbForConsole, callable $callback): void
{ {
// TODO: @Meldiron name of this method no longer matches. It does not delete, and it gives whole document // TODO: @Meldiron name of this method no longer matches. It does not delete, and it gives whole document

View file

@ -24,11 +24,8 @@ abstract class ScheduleBase extends Action
abstract public static function getName(): string; abstract public static function getName(): string;
abstract public static function getSupportedResource(): string; abstract public static function getSupportedResource(): string;
abstract public static function getCollectionId(): string;
abstract protected function enqueueResources( abstract protected function enqueueResources(Group $pools, Database $dbForConsole, callable $getProjectDB): void;
Group $pools,
Database $dbForConsole
);
public function __construct() public function __construct()
{ {
@ -62,14 +59,8 @@ abstract class ScheduleBase extends Action
$getSchedule = function (Document $schedule) use ($dbForConsole, $getProjectDB): array { $getSchedule = function (Document $schedule) use ($dbForConsole, $getProjectDB): array {
$project = $dbForConsole->getDocument('projects', $schedule->getAttribute('projectId')); $project = $dbForConsole->getDocument('projects', $schedule->getAttribute('projectId'));
$collectionId = match ($schedule->getAttribute('resourceType')) {
'function' => 'functions',
'message' => 'messages',
'execution' => 'executions'
};
$resource = $getProjectDB($project)->getDocument( $resource = $getProjectDB($project)->getDocument(
$collectionId, static::getCollectionId(),
$schedule->getAttribute('resourceId') $schedule->getAttribute('resourceId')
); );
@ -113,12 +104,7 @@ abstract class ScheduleBase extends Action
try { try {
$this->schedules[$document->getInternalId()] = $getSchedule($document); $this->schedules[$document->getInternalId()] = $getSchedule($document);
} catch (\Throwable $th) { } catch (\Throwable $th) {
$collectionId = match ($document->getAttribute('resourceType')) { $collectionId = static::getCollectionId();
'function' => 'functions',
'message' => 'messages',
'execution' => 'executions'
};
Console::error("Failed to load schedule for project {$document['projectId']} {$collectionId} {$document['resourceId']}"); Console::error("Failed to load schedule for project {$document['projectId']} {$collectionId} {$document['resourceId']}");
Console::error($th->getMessage()); Console::error($th->getMessage());
} }
@ -133,7 +119,7 @@ abstract class ScheduleBase extends Action
Console::success("Starting timers at " . DateTime::now()); Console::success("Starting timers at " . DateTime::now());
run(function () use ($dbForConsole, &$lastSyncUpdate, $getSchedule, $pools) { run(function () use ($dbForConsole, &$lastSyncUpdate, $getSchedule, $pools, $getProjectDB) {
/** /**
* The timer synchronize $schedules copy with database collection. * The timer synchronize $schedules copy with database collection.
*/ */
@ -172,10 +158,10 @@ abstract class ScheduleBase extends Action
$new = \strtotime($document['resourceUpdatedAt']); $new = \strtotime($document['resourceUpdatedAt']);
if (!$document['active']) { if (!$document['active']) {
Console::info("Removing: {$document['resourceId']}"); Console::info("Removing: {$document['resourceType']}::{$document['resourceId']}");
unset($this->schedules[$document->getInternalId()]); unset($this->schedules[$document->getInternalId()]);
} elseif ($new !== $org) { } elseif ($new !== $org) {
Console::info("Updating: {$document['resourceId']}"); Console::info("Updating: {$document['resourceType']}::{$document['resourceId']}");
$this->schedules[$document->getInternalId()] = $getSchedule($document); $this->schedules[$document->getInternalId()] = $getSchedule($document);
} }
} }
@ -193,10 +179,10 @@ abstract class ScheduleBase extends Action
Timer::tick( Timer::tick(
static::ENQUEUE_TIMER * 1000, static::ENQUEUE_TIMER * 1000,
fn () => $this->enqueueResources($pools, $dbForConsole) fn () => $this->enqueueResources($pools, $dbForConsole, $getProjectDB)
); );
$this->enqueueResources($pools, $dbForConsole); $this->enqueueResources($pools, $dbForConsole, $getProjectDB);
}); });
} }
} }

View file

@ -22,7 +22,12 @@ class ScheduleExecutions extends ScheduleBase
return 'execution'; return 'execution';
} }
protected function enqueueResources(Group $pools, Database $dbForConsole): void public static function getCollectionId(): string
{
return 'executions';
}
protected function enqueueResources(Group $pools, Database $dbForConsole, callable $getProjectDB): void
{ {
$queue = $pools->get('queue')->pop(); $queue = $pools->get('queue')->pop();
$connection = $queue->getResource(); $connection = $queue->getResource();

View file

@ -26,7 +26,12 @@ class ScheduleFunctions extends ScheduleBase
return 'function'; return 'function';
} }
protected function enqueueResources(Group $pools, Database $dbForConsole): void public static function getCollectionId(): string
{
return 'functions';
}
protected function enqueueResources(Group $pools, Database $dbForConsole, callable $getProjectDB): void
{ {
$timerStart = \microtime(true); $timerStart = \microtime(true);
$time = DateTime::now(); $time = DateTime::now();

View file

@ -21,7 +21,12 @@ class ScheduleMessages extends ScheduleBase
return 'message'; return 'message';
} }
protected function enqueueResources(Group $pools, Database $dbForConsole): void public static function getCollectionId(): string
{
return 'messages';
}
protected function enqueueResources(Group $pools, Database $dbForConsole, callable $getProjectDB): void
{ {
foreach ($this->schedules as $schedule) { foreach ($this->schedules as $schedule) {
if (!$schedule['active']) { if (!$schedule['active']) {

View file

@ -5,9 +5,11 @@ namespace Appwrite\Platform\Tasks;
use Appwrite\Specification\Format\OpenAPI3; use Appwrite\Specification\Format\OpenAPI3;
use Appwrite\Specification\Format\Swagger2; use Appwrite\Specification\Format\Swagger2;
use Appwrite\Specification\Specification; use Appwrite\Specification\Specification;
use Appwrite\Utopia\Response; use Appwrite\Utopia\Request as AppwriteRequest;
use Appwrite\Utopia\Response as AppwriteResponse;
use Exception; use Exception;
use Swoole\Http\Response as HttpResponse; use Swoole\Http\Request as SwooleRequest;
use Swoole\Http\Response as SwooleResponse;
use Utopia\App; use Utopia\App;
use Utopia\Cache\Adapter\None; use Utopia\Cache\Adapter\None;
use Utopia\Cache\Cache; use Utopia\Cache\Cache;
@ -17,7 +19,8 @@ use Utopia\Database\Adapter\MySQL;
use Utopia\Database\Database; use Utopia\Database\Database;
use Utopia\Platform\Action; use Utopia\Platform\Action;
use Utopia\Registry\Registry; use Utopia\Registry\Registry;
use Utopia\Request; use Utopia\Request as UtopiaRequest;
use Utopia\Response as UtopiaResponse;
use Utopia\System\System; use Utopia\System\System;
use Utopia\Validator\Text; use Utopia\Validator\Text;
use Utopia\Validator\WhiteList; use Utopia\Validator\WhiteList;
@ -29,6 +32,16 @@ class Specs extends Action
return 'specs'; return 'specs';
} }
public function getRequest(): UtopiaRequest
{
return new AppwriteRequest(new SwooleRequest());
}
public function getResponse(): UtopiaResponse
{
return new AppwriteResponse(new SwooleResponse());
}
public function __construct() public function __construct()
{ {
$this $this
@ -42,11 +55,11 @@ class Specs extends Action
public function action(string $version, string $mode, Registry $register): void public function action(string $version, string $mode, Registry $register): void
{ {
$appRoutes = App::getRoutes(); $appRoutes = App::getRoutes();
$response = new Response(new HttpResponse()); $response = $this->getResponse();
$mocks = ($mode === 'mocks'); $mocks = ($mode === 'mocks');
// Mock dependencies // Mock dependencies
App::setResource('request', fn () => new Request()); App::setResource('request', fn () => $this->getRequest());
App::setResource('response', fn () => $response); App::setResource('response', fn () => $response);
App::setResource('dbForConsole', fn () => new Database(new MySQL(''), new Cache(new None()))); App::setResource('dbForConsole', fn () => new Database(new MySQL(''), new Cache(new None())));
App::setResource('dbForProject', fn () => new Database(new MySQL(''), new Cache(new None()))); App::setResource('dbForProject', fn () => new Database(new MySQL(''), new Cache(new None())));
@ -183,10 +196,8 @@ class Specs extends Action
case APP_AUTH_TYPE_SESSION: case APP_AUTH_TYPE_SESSION:
$sdkPlatforms[] = APP_PLATFORM_CLIENT; $sdkPlatforms[] = APP_PLATFORM_CLIENT;
break; break;
case APP_AUTH_TYPE_KEY:
$sdkPlatforms[] = APP_PLATFORM_SERVER;
break;
case APP_AUTH_TYPE_JWT: case APP_AUTH_TYPE_JWT:
case APP_AUTH_TYPE_KEY:
$sdkPlatforms[] = APP_PLATFORM_SERVER; $sdkPlatforms[] = APP_PLATFORM_SERVER;
break; break;
case APP_AUTH_TYPE_ADMIN: case APP_AUTH_TYPE_ADMIN:

View file

@ -480,6 +480,7 @@ class Deletes extends Action
private function deleteProject(Database $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, Document $document): void private function deleteProject(Database $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, Document $document): void
{ {
$projectInternalId = $document->getInternalId(); $projectInternalId = $document->getInternalId();
$projectId = $document->getId();
try { try {
$dsn = new DSN($document->getAttribute('database', 'console')); $dsn = new DSN($document->getAttribute('database', 'console'));
@ -568,6 +569,11 @@ class Deletes extends Action
Query::equal('projectInternalId', [$projectInternalId]), Query::equal('projectInternalId', [$projectInternalId]),
], $dbForConsole); ], $dbForConsole);
// Delete Schedules (No projectInternalId in this collection)
$this->deleteByGroup('schedules', [
Query::equal('projectId', [$projectId]),
], $dbForConsole);
// Delete metadata table // Delete metadata table
if ($dsn->getHost() !== System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { if ($dsn->getHost() !== System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) {
$dbForProject->deleteCollection('_metadata'); $dbForProject->deleteCollection('_metadata');
@ -966,7 +972,7 @@ class Deletes extends Action
* @return void * @return void
* @throws Exception * @throws Exception
*/ */
private function deleteByGroup(string $collection, array $queries, Database $database, callable $callback = null): void protected function deleteByGroup(string $collection, array $queries, Database $database, callable $callback = null): void
{ {
$count = 0; $count = 0;
$chunk = 0; $chunk = 0;
@ -1008,7 +1014,7 @@ class Deletes extends Action
* @return void * @return void
* @throws Exception * @throws Exception
*/ */
private function listByGroup(string $collection, array $queries, Database $database, callable $callback = null): void protected function listByGroup(string $collection, array $queries, Database $database, callable $callback = null): void
{ {
$count = 0; $count = 0;
$chunk = 0; $chunk = 0;

View file

@ -587,7 +587,8 @@ class Functions extends Action
$target = Realtime::fromPayload( $target = Realtime::fromPayload(
// Pass first, most verbose event pattern // Pass first, most verbose event pattern
event: $allEvents[0], event: $allEvents[0],
payload: $execution payload: $execution,
project: $project
); );
Realtime::send( Realtime::send(
projectId: 'console', projectId: 'console',

View file

@ -8,6 +8,7 @@ use Appwrite\Permission;
use Appwrite\Role; use Appwrite\Role;
use Exception; use Exception;
use Utopia\CLI\Console; use Utopia\CLI\Console;
use Utopia\Config\Config;
use Utopia\Database\Database; use Utopia\Database\Database;
use Utopia\Database\Document; use Utopia\Database\Document;
use Utopia\Database\Exception\Authorization; use Utopia\Database\Exception\Authorization;
@ -16,11 +17,11 @@ use Utopia\Database\Exception\Restricted;
use Utopia\Database\Exception\Structure; use Utopia\Database\Exception\Structure;
use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\ID;
use Utopia\Logger\Log; use Utopia\Logger\Log;
use Utopia\Logger\Log\Breadcrumb; use Utopia\Migration\Destination;
use Utopia\Migration\Destinations\Appwrite as DestinationsAppwrite; use Utopia\Migration\Destinations\Appwrite as DestinationAppwrite;
use Utopia\Migration\Exception as MigrationException; use Utopia\Migration\Exception as MigrationException;
use Utopia\Migration\Source; use Utopia\Migration\Source;
use Utopia\Migration\Sources\Appwrite; use Utopia\Migration\Sources\Appwrite as SourceAppwrite;
use Utopia\Migration\Sources\Firebase; use Utopia\Migration\Sources\Firebase;
use Utopia\Migration\Sources\NHost; use Utopia\Migration\Sources\NHost;
use Utopia\Migration\Sources\Supabase; use Utopia\Migration\Sources\Supabase;
@ -30,8 +31,11 @@ use Utopia\Queue\Message;
class Migrations extends Action class Migrations extends Action
{ {
private ?Database $dbForProject = null; protected Database $dbForProject;
private ?Database $dbForConsole = null;
protected Database $dbForConsole;
protected Document $project;
public static function getName(): string public static function getName(): string
{ {
@ -53,11 +57,6 @@ class Migrations extends Action
} }
/** /**
* @param Message $message
* @param Database $dbForProject
* @param Database $dbForConsole
* @param Log $log
* @return void
* @throws Exception * @throws Exception
*/ */
public function action(Message $message, Database $dbForProject, Database $dbForConsole, Log $log): void public function action(Message $message, Database $dbForProject, Database $dbForConsole, Log $log): void
@ -78,6 +77,7 @@ class Migrations extends Action
$this->dbForProject = $dbForProject; $this->dbForProject = $dbForProject;
$this->dbForConsole = $dbForConsole; $this->dbForConsole = $dbForConsole;
$this->project = $project;
/** /**
* Handle Event execution. * Handle Event execution.
@ -89,17 +89,17 @@ class Migrations extends Action
$log->addTag('migrationId', $migration->getId()); $log->addTag('migrationId', $migration->getId());
$log->addTag('projectId', $project->getId()); $log->addTag('projectId', $project->getId());
$this->processMigration($project, $migration, $log); $this->processMigration($migration, $log);
} }
/** /**
* @param string $source
* @param array $credentials
* @return Source
* @throws Exception * @throws Exception
*/ */
protected function processSource(string $source, array $credentials): Source protected function processSource(Document $migration): Source
{ {
$source = $migration->getAttribute('source');
$credentials = $migration->getAttribute('credentials');
return match ($source) { return match ($source) {
Firebase::getName() => new Firebase( Firebase::getName() => new Firebase(
json_decode($credentials['serviceAccount'], true), json_decode($credentials['serviceAccount'], true),
@ -122,11 +122,35 @@ class Migrations extends Action
$credentials['password'], $credentials['password'],
$credentials['port'], $credentials['port'],
), ),
Appwrite::getName() => new Appwrite($credentials['projectId'], str_starts_with($credentials['endpoint'], 'http://localhost/v1') ? 'http://appwrite/v1' : $credentials['endpoint'], $credentials['apiKey']), SourceAppwrite::getName() => new SourceAppwrite(
$credentials['projectId'],
$credentials['endpoint'],
$credentials['apiKey'],
),
default => throw new \Exception('Invalid source type'), default => throw new \Exception('Invalid source type'),
}; };
} }
/**
* @throws Exception
*/
protected function processDestination(Document $migration): Destination
{
$destination = $migration->getAttribute('destination');
$credentials = $migration->getAttribute('credentials');
return match ($destination) {
DestinationAppwrite::getName() => new DestinationAppwrite(
$credentials['projectId'],
$credentials['endpoint'],
$credentials['apiKey'],
$this->dbForProject,
Config::getParam('collections', [])['databases']['collections'],
),
default => throw new \Exception('Invalid destination type'),
};
}
/** /**
* @throws Authorization * @throws Authorization
* @throws Structure * @throws Structure
@ -167,8 +191,6 @@ class Migrations extends Action
} }
/** /**
* @param Document $apiKey
* @return void
* @throws \Utopia\Database\Exception * @throws \Utopia\Database\Exception
* @throws Authorization * @throws Authorization
* @throws Conflict * @throws Conflict
@ -181,8 +203,6 @@ class Migrations extends Action
} }
/** /**
* @param Document $project
* @return Document
* @throws Authorization * @throws Authorization
* @throws Structure * @throws Structure
* @throws \Utopia\Database\Exception * @throws \Utopia\Database\Exception
@ -233,99 +253,116 @@ class Migrations extends Action
} }
/** /**
* @param Document $project
* @param Document $migration
* @param Log $log
* @return void
* @throws Authorization * @throws Authorization
* @throws Conflict * @throws Conflict
* @throws Restricted * @throws Restricted
* @throws Structure * @throws Structure
* @throws \Utopia\Database\Exception * @throws \Utopia\Database\Exception
* @throws Exception
*/ */
protected function processMigration(Document $project, Document $migration, Log $log): void protected function processMigration(Document $migration, Log $log): void
{ {
/** $project = $this->project;
* @var Document $migrationDocument
* @var Transfer $transfer
*/
$migrationDocument = null;
$transfer = null;
$projectDocument = $this->dbForConsole->getDocument('projects', $project->getId()); $projectDocument = $this->dbForConsole->getDocument('projects', $project->getId());
$tempAPIKey = $this->generateAPIKey($projectDocument); $tempAPIKey = $this->generateAPIKey($projectDocument);
$transfer = $source = $destination = null;
try { try {
$migrationDocument = $this->dbForProject->getDocument('migrations', $migration->getId()); $migration = $this->dbForProject->getDocument('migrations', $migration->getId());
$migrationDocument->setAttribute('stage', 'processing');
$migrationDocument->setAttribute('status', 'processing');
$log->addBreadcrumb(new Breadcrumb("debug", "migration", "Migration hit stage 'processing'", \microtime(true)));
$this->updateMigrationDocument($migrationDocument, $projectDocument);
$log->addTag('type', $migrationDocument->getAttribute('source')); if (
$migration->getAttribute('source') === SourceAppwrite::getName() ||
$migration->getAttribute('destination') === DestinationAppwrite::getName()
) {
$credentials = $migration->getAttribute('credentials', []);
$source = $this->processSource($migrationDocument->getAttribute('source'), $migrationDocument->getAttribute('credentials')); $credentials['projectId'] = $credentials['projectId'] ?? $projectDocument->getId();
$credentials['endpoint'] = $credentials['endpoint'] ?? 'http://appwrite/v1';
$credentials['apiKey'] = $credentials['apiKey'] ?? $tempAPIKey['secret'];
$migration->setAttribute('credentials', $credentials);
}
$migration->setAttribute('stage', 'processing');
$migration->setAttribute('status', 'processing');
$this->updateMigrationDocument($migration, $projectDocument);
$log->addTag('type', $migration->getAttribute('source'));
$source = $this->processSource($migration);
$destination = $this->processDestination($migration);
$source->report(); $source->report();
$destination = new DestinationsAppwrite(
$projectDocument->getId(),
'http://appwrite/v1',
$tempAPIKey['secret'],
);
$transfer = new Transfer( $transfer = new Transfer(
$source, $source,
$destination $destination
); );
/** Start Transfer */ /** Start Transfer */
$migrationDocument->setAttribute('stage', 'migrating'); $migration->setAttribute('stage', 'migrating');
$log->addBreadcrumb(new Breadcrumb("debug", "migration", "Migration hit stage 'migrating'", \microtime(true))); $this->updateMigrationDocument($migration, $projectDocument);
$this->updateMigrationDocument($migrationDocument, $projectDocument);
$transfer->run($migrationDocument->getAttribute('resources'), function () use ($migrationDocument, $transfer, $projectDocument) {
$migrationDocument->setAttribute('resourceData', json_encode($transfer->getCache()));
$migrationDocument->setAttribute('statusCounters', json_encode($transfer->getStatusCounters()));
$this->updateMigrationDocument($migrationDocument, $projectDocument); $transfer->run(
}); $migration->getAttribute('resources'),
function () use ($migration, $transfer, $projectDocument) {
$migration->setAttribute('resourceData', json_encode($transfer->getCache()));
$migration->setAttribute('statusCounters', json_encode($transfer->getStatusCounters()));
$this->updateMigrationDocument($migration, $projectDocument);
},
$migration->getAttribute('resourceId'),
$migration->getAttribute('resourceType')
);
$destination->shutDown();
$source->shutDown();
$sourceErrors = $source->getErrors(); $sourceErrors = $source->getErrors();
$destinationErrors = $destination->getErrors(); $destinationErrors = $destination->getErrors();
if (!empty($sourceErrors) || !empty($destinationErrors)) { if (! empty($sourceErrors) || ! empty($destinationErrors)) {
$migrationDocument->setAttribute('status', 'failed'); $migration->setAttribute('status', 'failed');
$migrationDocument->setAttribute('stage', 'finished'); $migration->setAttribute('stage', 'finished');
$log->addBreadcrumb(new Breadcrumb("debug", "migration", "Migration hit stage 'finished' and failed", \microtime(true)));
$errorMessages = []; $errorMessages = [];
foreach ($sourceErrors as $error) { foreach ($sourceErrors as $error) {
/** @var MigrationException $error */ /** @var $sourceErrors $error */
$errorMessages[] = "Error occurred while fetching '{$error->getResourceGroup()}:{$error->getResourceId()}' from source with message: '{$error->getMessage()}'"; $message = "Error occurred while fetching '{$error->getResourceName()}:{$error->getResourceId()}' from source with message: '{$error->getMessage()}'";
if ($error->getPrevious()) {
$message .= " Message: ".$error->getPrevious()->getMessage() . " File: ".$error->getPrevious()->getFile() . " Line: ".$error->getPrevious()->getLine();
}
$errorMessages[] = $message;
} }
foreach ($destinationErrors as $error) { foreach ($destinationErrors as $error) {
$message = "Error occurred while pushing '{$error->getResourceName()}:{$error->getResourceId()}' to destination with message: '{$error->getMessage()}'";
if ($error->getPrevious()) {
$message .= " Message: ".$error->getPrevious()->getMessage() . " File: ".$error->getPrevious()->getFile() . " Line: ".$error->getPrevious()->getLine();
}
/** @var MigrationException $error */ /** @var MigrationException $error */
$errorMessages[] = "Error occurred while pushing '{$error->getResourceGroup()}:{$error->getResourceId()}' to destination with message: '{$error->getMessage()}'"; $errorMessages[] = $message;
} }
$migrationDocument->setAttribute('errors', $errorMessages); $migration->setAttribute('errors', $errorMessages);
$log->addExtra('migrationErrors', json_encode($errorMessages)); $log->addExtra('migrationErrors', json_encode($errorMessages));
$this->updateMigrationDocument($migrationDocument, $projectDocument); $this->updateMigrationDocument($migration, $projectDocument);
return; return;
} }
$migrationDocument->setAttribute('status', 'completed'); $migration->setAttribute('status', 'completed');
$migrationDocument->setAttribute('stage', 'finished'); $migration->setAttribute('stage', 'finished');
$log->addBreadcrumb(new Breadcrumb("debug", "migration", "Migration hit stage 'finished' and succeeded", \microtime(true)));
} catch (\Throwable $th) { } catch (\Throwable $th) {
Console::error($th->getMessage()); Console::error($th->getMessage());
Console::error($th->getTraceAsString());
if ($migrationDocument) { if (! $migration->isEmpty()) {
Console::error($th->getMessage()); $migration->setAttribute('status', 'failed');
Console::error($th->getTraceAsString()); $migration->setAttribute('stage', 'finished');
$migrationDocument->setAttribute('status', 'failed'); $migration->setAttribute('errors', [$th->getMessage()]);
$migrationDocument->setAttribute('stage', 'finished');
$migrationDocument->setAttribute('errors', [$th->getMessage()]);
return; return;
} }
@ -337,26 +374,30 @@ class Migrations extends Action
$errorMessages = []; $errorMessages = [];
foreach ($sourceErrors as $error) { foreach ($sourceErrors as $error) {
/** @var MigrationException $error */ /** @var MigrationException $error */
$errorMessages[] = "Error occurred while fetching '{$error->getResourceGroup()}:{$error->getResourceId()}' from source with message '{$error->getMessage()}'"; $errorMessages[] = "Error occurred while fetching '{$error->getResourceName()}:{$error->getResourceId()}' from source with message '{$error->getMessage()}'";
} }
foreach ($destinationErrors as $error) { foreach ($destinationErrors as $error) {
/** @var MigrationException $error */ /** @var MigrationException $error */
$errorMessages[] = "Error occurred while pushing '{$error->getResourceGroup()}:{$error->getResourceId()}' to destination with message '{$error->getMessage()}'"; $errorMessages[] = "Error occurred while pushing '{$error->getResourceName()}:{$error->getResourceId()}' to destination with message '{$error->getMessage()}'";
} }
$migrationDocument->setAttribute('errors', $errorMessages); $migration->setAttribute('errors', $errorMessages);
$log->addTag('migrationErrors', json_encode($errorMessages)); $log->addTag('migrationErrors', json_encode($errorMessages));
} }
} finally { } finally {
if ($tempAPIKey) { if (! $tempAPIKey->isEmpty()) {
$this->removeAPIKey($tempAPIKey); $this->removeAPIKey($tempAPIKey);
} }
if ($migrationDocument) {
$this->updateMigrationDocument($migrationDocument, $projectDocument);
if ($migrationDocument->getAttribute('status', '') == 'failed') { $this->updateMigrationDocument($migration, $projectDocument);
throw new Exception("Migration failed");
} if ($migration->getAttribute('status', '') === 'failed') {
Console::error('Migration('.$migration->getInternalId().':'.$migration->getId().') failed, Project('.$this->project->getInternalId().':'.$this->project->getId().')');
$destination->error();
$source->error();
throw new Exception('Migration failed');
} }
} }
} }

View file

@ -286,13 +286,26 @@ class Swagger2 extends Format
$validator = $validator->getValidator(); $validator = $validator->getValidator();
} }
$validatorClass = (!empty($validator)) ? \get_class($validator) : ''; $class = !empty($validator)
if ($validatorClass === 'Utopia\Validator\AnyOf') { ? \get_class($validator)
$validator = $param['validator']->getValidators()[0]; : '';
$validatorClass = \get_class($validator);
$base = !empty($class)
? \get_parent_class($class)
: '';
switch ($base) {
case 'Appwrite\Utopia\Database\Validator\Queries\Base':
$class = $base;
break;
} }
switch ($validatorClass) { if ($class === 'Utopia\Validator\AnyOf') {
$validator = $param['validator']->getValidators()[0];
$class = \get_class($validator);
}
switch ($class) {
case 'Utopia\Validator\Text': case 'Utopia\Validator\Text':
case 'Utopia\Database\Validator\UID': case 'Utopia\Database\Validator\UID':
$node['type'] = $validator->getType(); $node['type'] = $validator->getType();
@ -348,29 +361,7 @@ class Swagger2 extends Format
$consumes = ['multipart/form-data']; $consumes = ['multipart/form-data'];
$node['type'] = 'payload'; $node['type'] = 'payload';
break; break;
case 'Appwrite\Utopia\Database\Validator\Queries\Attributes': case 'Appwrite\Utopia\Database\Validator\Queries\Base':
case 'Appwrite\Utopia\Database\Validator\Queries\Buckets':
case 'Appwrite\Utopia\Database\Validator\Queries\Collections':
case 'Appwrite\Utopia\Database\Validator\Queries\Databases':
case 'Appwrite\Utopia\Database\Validator\Queries\Deployments':
case 'Appwrite\Utopia\Database\Validator\Queries\Executions':
case 'Appwrite\Utopia\Database\Validator\Queries\Files':
case 'Appwrite\Utopia\Database\Validator\Queries\Functions':
case 'Appwrite\Utopia\Database\Validator\Queries\Identities':
case 'Appwrite\Utopia\Database\Validator\Queries\Indexes':
case 'Appwrite\Utopia\Database\Validator\Queries\Installations':
case 'Appwrite\Utopia\Database\Validator\Queries\Memberships':
case 'Appwrite\Utopia\Database\Validator\Queries\Messages':
case 'Appwrite\Utopia\Database\Validator\Queries\Migrations':
case 'Appwrite\Utopia\Database\Validator\Queries\Projects':
case 'Appwrite\Utopia\Database\Validator\Queries\Providers':
case 'Appwrite\Utopia\Database\Validator\Queries\Rules':
case 'Appwrite\Utopia\Database\Validator\Queries\Subscribers':
case 'Appwrite\Utopia\Database\Validator\Queries\Targets':
case 'Appwrite\Utopia\Database\Validator\Queries\Teams':
case 'Appwrite\Utopia\Database\Validator\Queries\Topics':
case 'Appwrite\Utopia\Database\Validator\Queries\Users':
case 'Appwrite\Utopia\Database\Validator\Queries\Variables':
case 'Utopia\Database\Validator\Queries': case 'Utopia\Database\Validator\Queries':
case 'Utopia\Database\Validator\Queries\Document': case 'Utopia\Database\Validator\Queries\Document':
case 'Utopia\Database\Validator\Queries\Documents': case 'Utopia\Database\Validator\Queries\Documents':

View file

@ -122,7 +122,11 @@ class Request extends UtopiaRequest
*/ */
public function getHeaders(): array public function getHeaders(): array
{ {
$headers = $this->generateHeaders(); try {
$headers = $this->generateHeaders();
} catch (\Throwable) {
$headers = [];
}
if (empty($this->swoole->cookie)) { if (empty($this->swoole->cookie)) {
return $headers; return $headers;

View file

@ -47,7 +47,18 @@ class Attribute extends Model
'required' => false, 'required' => false,
'example' => false, 'example' => false,
]) ])
; ->addRule('$createdAt', [
'type' => self::TYPE_DATETIME,
'description' => 'Attribute creation date in ISO 8601 format.',
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
])
->addRule('$updatedAt', [
'type' => self::TYPE_DATETIME,
'description' => 'Attribute update date in ISO 8601 format.',
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
]);
} }
public array $conditions = []; public array $conditions = [];

View file

@ -49,13 +49,22 @@ class Index extends Model
'array' => true, 'array' => true,
'required' => false, 'required' => false,
]) ])
; ->addRule('$createdAt', [
'type' => self::TYPE_DATETIME,
'description' => 'Index creation date in ISO 8601 format.',
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
])
->addRule('$updatedAt', [
'type' => self::TYPE_DATETIME,
'description' => 'Index update date in ISO 8601 format.',
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
]);
} }
/** /**
* Get Name * Get Name
*
* @return string
*/ */
public function getName(): string public function getName(): string
{ {
@ -64,8 +73,6 @@ class Index extends Model
/** /**
* Get Collection * Get Collection
*
* @return string
*/ */
public function getType(): string public function getType(): string
{ {

View file

@ -7,25 +7,34 @@ use WebSocket\ConnectionException;
trait RealtimeBase trait RealtimeBase
{ {
private function getWebsocket($channels = [], $headers = [], $projectId = null): WebSocketClient private function getWebsocket(
{ array $channels = [],
array $headers = [],
string $projectId = null
): WebSocketClient {
if (is_null($projectId)) { if (is_null($projectId)) {
$projectId = $this->getProject()['$id']; $projectId = $this->getProject()['$id'];
} }
$headers = array_merge([ $headers = array_merge(
'Origin' => 'appwrite.test' [
], $headers); "Origin" => "appwrite.test",
],
$headers
);
$query = [ $query = [
'project' => $projectId, "project" => $projectId,
'channels' => $channels "channels" => $channels,
]; ];
return new WebSocketClient('ws://appwrite-traefik/v1/realtime?' . http_build_query($query), [ return new WebSocketClient(
'headers' => $headers, "ws://appwrite-traefik/v1/realtime?" . http_build_query($query),
'timeout' => 30, [
]); "headers" => $headers,
"timeout" => 30,
]
);
} }
public function testConnection(): void public function testConnection(): void
@ -33,7 +42,7 @@ trait RealtimeBase
/** /**
* Test for SUCCESS * Test for SUCCESS
*/ */
$client = $this->getWebsocket(['documents']); $client = $this->getWebsocket(["documents"]);
$this->assertNotEmpty($client->receive()); $this->assertNotEmpty($client->receive());
$client->close(); $client->close();
} }
@ -43,11 +52,11 @@ trait RealtimeBase
$client = $this->getWebsocket(); $client = $this->getWebsocket();
$payload = json_decode($client->receive(), true); $payload = json_decode($client->receive(), true);
$this->assertArrayHasKey('type', $payload); $this->assertArrayHasKey("type", $payload);
$this->assertArrayHasKey('data', $payload); $this->assertArrayHasKey("data", $payload);
$this->assertEquals('error', $payload['type']); $this->assertEquals("error", $payload["type"]);
$this->assertEquals(1008, $payload['data']['code']); $this->assertEquals(1008, $payload["data"]["code"]);
$this->assertEquals('Missing channels', $payload['data']['message']); $this->assertEquals("Missing channels", $payload["data"]["message"]);
\usleep(250000); // 250ms \usleep(250000); // 250ms
$this->expectException(ConnectionException::class); // Check if server disconnnected client $this->expectException(ConnectionException::class); // Check if server disconnnected client
$client->close(); $client->close();
@ -55,18 +64,24 @@ trait RealtimeBase
public function testConnectionFailureUnknownProject(): void public function testConnectionFailureUnknownProject(): void
{ {
$client = new WebSocketClient('ws://appwrite-traefik/v1/realtime?project=123', [ $client = new WebSocketClient(
'headers' => [ "ws://appwrite-traefik/v1/realtime?project=123",
'Origin' => 'appwrite.test' [
"headers" => [
"Origin" => "appwrite.test",
],
] ]
]); );
$payload = json_decode($client->receive(), true); $payload = json_decode($client->receive(), true);
$this->assertArrayHasKey('type', $payload); $this->assertArrayHasKey("type", $payload);
$this->assertArrayHasKey('data', $payload); $this->assertArrayHasKey("data", $payload);
$this->assertEquals('error', $payload['type']); $this->assertEquals("error", $payload["type"]);
$this->assertEquals(1008, $payload['data']['code']); $this->assertEquals(1008, $payload["data"]["code"]);
$this->assertEquals('Missing or unknown project ID', $payload['data']['message']); $this->assertEquals(
"Missing or unknown project ID",
$payload["data"]["message"]
);
\usleep(250000); // 250ms \usleep(250000); // 250ms
$this->expectException(ConnectionException::class); // Check if server disconnnected client $this->expectException(ConnectionException::class); // Check if server disconnnected client
$client->close(); $client->close();

View file

@ -18,7 +18,7 @@ class RealtimeConsoleClientTest extends Scope
use ProjectCustom; use ProjectCustom;
use SideConsole; use SideConsole;
public function testManualAuthentication() public function testManualAuthentication(): void
{ {
$user = $this->getUser(); $user = $this->getUser();
$userId = $user['$id'] ?? ''; $userId = $user['$id'] ?? '';
@ -123,7 +123,7 @@ class RealtimeConsoleClientTest extends Scope
$client->close(); $client->close();
} }
public function testAttributes() public function testAttributes(): array
{ {
$user = $this->getUser(); $user = $this->getUser();
$projectId = 'console'; $projectId = 'console';
@ -183,6 +183,7 @@ class RealtimeConsoleClientTest extends Scope
'required' => true, 'required' => true,
]); ]);
$projectId = $this->getProject()['$id'];
$attributeKey = $name['body']['key']; $attributeKey = $name['body']['key'];
$this->assertEquals($name['headers']['status-code'], 202); $this->assertEquals($name['headers']['status-code'], 202);
@ -197,8 +198,9 @@ class RealtimeConsoleClientTest extends Scope
$this->assertEquals('event', $response['type']); $this->assertEquals('event', $response['type']);
$this->assertNotEmpty($response['data']); $this->assertNotEmpty($response['data']);
$this->assertArrayHasKey('timestamp', $response['data']); $this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(1, $response['data']['channels']); $this->assertCount(2, $response['data']['channels']);
$this->assertContains('console', $response['data']['channels']); $this->assertContains('console', $response['data']['channels']);
$this->assertContains("projects.{$projectId}", $response['data']['channels']);
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*.create", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*.create", $response['data']['events']);
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*", $response['data']['events']);
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']);
@ -217,8 +219,9 @@ class RealtimeConsoleClientTest extends Scope
$this->assertEquals('event', $response['type']); $this->assertEquals('event', $response['type']);
$this->assertNotEmpty($response['data']); $this->assertNotEmpty($response['data']);
$this->assertArrayHasKey('timestamp', $response['data']); $this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(1, $response['data']['channels']); $this->assertCount(2, $response['data']['channels']);
$this->assertContains('console', $response['data']['channels']); $this->assertContains('console', $response['data']['channels']);
$this->assertContains("projects.{$projectId}", $response['data']['channels']);
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*.update", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*.update", $response['data']['events']);
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*", $response['data']['events']);
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']);
@ -275,6 +278,8 @@ class RealtimeConsoleClientTest extends Scope
]); ]);
$this->assertEquals($index['headers']['status-code'], 202); $this->assertEquals($index['headers']['status-code'], 202);
$projectId = $this->getProject()['$id'];
$indexKey = $index['body']['key']; $indexKey = $index['body']['key'];
$response = json_decode($client->receive(), true); $response = json_decode($client->receive(), true);
@ -284,8 +289,9 @@ class RealtimeConsoleClientTest extends Scope
$this->assertEquals('event', $response['type']); $this->assertEquals('event', $response['type']);
$this->assertNotEmpty($response['data']); $this->assertNotEmpty($response['data']);
$this->assertArrayHasKey('timestamp', $response['data']); $this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(1, $response['data']['channels']); $this->assertCount(2, $response['data']['channels']);
$this->assertContains('console', $response['data']['channels']); $this->assertContains('console', $response['data']['channels']);
$this->assertContains("projects.{$projectId}", $response['data']['channels']);
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*.create", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*.create", $response['data']['events']);
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*", $response['data']['events']);
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']);
@ -302,8 +308,9 @@ class RealtimeConsoleClientTest extends Scope
$this->assertEquals('event', $response['type']); $this->assertEquals('event', $response['type']);
$this->assertNotEmpty($response['data']); $this->assertNotEmpty($response['data']);
$this->assertArrayHasKey('timestamp', $response['data']); $this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(1, $response['data']['channels']); $this->assertCount(2, $response['data']['channels']);
$this->assertContains('console', $response['data']['channels']); $this->assertContains('console', $response['data']['channels']);
$this->assertContains("projects.{$projectId}", $response['data']['channels']);
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*.update", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*.update", $response['data']['events']);
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*", $response['data']['events']);
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']);
@ -342,6 +349,8 @@ class RealtimeConsoleClientTest extends Scope
$this->assertContains('console', $response['data']['channels']); $this->assertContains('console', $response['data']['channels']);
$this->assertNotEmpty($response['data']['user']); $this->assertNotEmpty($response['data']['user']);
$projectId = $this->getProject()['$id'];
/** /**
* Test Delete Index * Test Delete Index
*/ */
@ -352,6 +361,7 @@ class RealtimeConsoleClientTest extends Scope
], $this->getHeaders())); ], $this->getHeaders()));
$this->assertEquals($attribute['headers']['status-code'], 204); $this->assertEquals($attribute['headers']['status-code'], 204);
$response = json_decode($client->receive(), true); $response = json_decode($client->receive(), true);
$this->assertArrayHasKey('type', $response); $this->assertArrayHasKey('type', $response);
@ -359,8 +369,9 @@ class RealtimeConsoleClientTest extends Scope
$this->assertEquals('event', $response['type']); $this->assertEquals('event', $response['type']);
$this->assertNotEmpty($response['data']); $this->assertNotEmpty($response['data']);
$this->assertArrayHasKey('timestamp', $response['data']); $this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(1, $response['data']['channels']); $this->assertCount(2, $response['data']['channels']);
$this->assertContains('console', $response['data']['channels']); $this->assertContains('console', $response['data']['channels']);
$this->assertContains("projects.{$projectId}", $response['data']['channels']);
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*.update", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*.update", $response['data']['events']);
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*", $response['data']['events']);
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']);
@ -376,8 +387,9 @@ class RealtimeConsoleClientTest extends Scope
$this->assertEquals('event', $response['type']); $this->assertEquals('event', $response['type']);
$this->assertNotEmpty($response['data']); $this->assertNotEmpty($response['data']);
$this->assertArrayHasKey('timestamp', $response['data']); $this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(1, $response['data']['channels']); $this->assertCount(2, $response['data']['channels']);
$this->assertContains('console', $response['data']['channels']); $this->assertContains('console', $response['data']['channels']);
$this->assertContains("projects.{$projectId}", $response['data']['channels']);
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*.delete", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*.delete", $response['data']['events']);
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.indexes.*", $response['data']['events']);
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']);
@ -415,10 +427,12 @@ class RealtimeConsoleClientTest extends Scope
$this->assertContains('console', $response['data']['channels']); $this->assertContains('console', $response['data']['channels']);
$this->assertNotEmpty($response['data']['user']); $this->assertNotEmpty($response['data']['user']);
$attributeKey = 'name';
$projectId = $this->getProject()['$id'];
/** /**
* Test Delete Attribute * Test Delete Attribute
*/ */
$attributeKey = 'name';
$attribute = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['actorsId'] . '/attributes/' . $attributeKey, array_merge([ $attribute = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['actorsId'] . '/attributes/' . $attributeKey, array_merge([
'content-type' => 'application/json', 'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-project' => $this->getProject()['$id'],
@ -432,8 +446,9 @@ class RealtimeConsoleClientTest extends Scope
$this->assertEquals('event', $response['type']); $this->assertEquals('event', $response['type']);
$this->assertNotEmpty($response['data']); $this->assertNotEmpty($response['data']);
$this->assertArrayHasKey('timestamp', $response['data']); $this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(1, $response['data']['channels']); $this->assertCount(2, $response['data']['channels']);
$this->assertContains('console', $response['data']['channels']); $this->assertContains('console', $response['data']['channels']);
$this->assertContains("projects.{$projectId}", $response['data']['channels']);
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*.update", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*.update", $response['data']['events']);
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*", $response['data']['events']);
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']);
@ -449,8 +464,9 @@ class RealtimeConsoleClientTest extends Scope
$this->assertEquals('event', $response['type']); $this->assertEquals('event', $response['type']);
$this->assertNotEmpty($response['data']); $this->assertNotEmpty($response['data']);
$this->assertArrayHasKey('timestamp', $response['data']); $this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(1, $response['data']['channels']); $this->assertCount(2, $response['data']['channels']);
$this->assertContains('console', $response['data']['channels']); $this->assertContains('console', $response['data']['channels']);
$this->assertContains("projects.{$projectId}", $response['data']['channels']);
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*.delete", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*.delete", $response['data']['events']);
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}.attributes.*", $response['data']['events']);
$this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.{$actorsId}", $response['data']['events']);
@ -504,10 +520,10 @@ class RealtimeConsoleClientTest extends Scope
/** /**
* Test Create Deployment * Test Create Deployment
*/ */
$projectId = $this->getProject()['$id'];
$deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', array_merge([ $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', array_merge([
'content-type' => 'multipart/form-data', 'content-type' => 'multipart/form-data',
'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-project' => $projectId,
], $this->getHeaders()), [ ], $this->getHeaders()), [
'entrypoint' => 'index.php', 'entrypoint' => 'index.php',
'code' => $this->packageFunction('php'), 'code' => $this->packageFunction('php'),
@ -523,8 +539,9 @@ class RealtimeConsoleClientTest extends Scope
$this->assertEquals('event', $response['type']); $this->assertEquals('event', $response['type']);
$this->assertNotEmpty($response['data']); $this->assertNotEmpty($response['data']);
$this->assertArrayHasKey('timestamp', $response['data']); $this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(1, $response['data']['channels']); $this->assertCount(2, $response['data']['channels']);
$this->assertContains('console', $response['data']['channels']); $this->assertContains('console', $response['data']['channels']);
$this->assertContains("projects.{$projectId}", $response['data']['channels']);
// $this->assertContains("functions.{$functionId}.deployments.{$deploymentId}.create", $response['data']['events']); TODO @christyjacob4 : enable test once we allow functions.* events // $this->assertContains("functions.{$functionId}.deployments.{$deploymentId}.create", $response['data']['events']); TODO @christyjacob4 : enable test once we allow functions.* events
$this->assertNotEmpty($response['data']['payload']); $this->assertNotEmpty($response['data']['payload']);

View file

@ -1334,8 +1334,9 @@ class RealtimeCustomClientTest extends Scope
$this->assertEquals('event', $response['type']); $this->assertEquals('event', $response['type']);
$this->assertNotEmpty($response['data']); $this->assertNotEmpty($response['data']);
$this->assertArrayHasKey('timestamp', $response['data']); $this->assertArrayHasKey('timestamp', $response['data']);
$this->assertCount(4, $response['data']['channels']); $this->assertCount(5, $response['data']['channels']);
$this->assertContains('console', $response['data']['channels']); $this->assertContains('console', $response['data']['channels']);
$this->assertContains("projects.{$this->getProject()['$id']}", $response['data']['channels']);
$this->assertContains('executions', $response['data']['channels']); $this->assertContains('executions', $response['data']['channels']);
$this->assertContains("executions.{$executionId}", $response['data']['channels']); $this->assertContains("executions.{$executionId}", $response['data']['channels']);
$this->assertContains("functions.{$functionId}", $response['data']['channels']); $this->assertContains("functions.{$functionId}", $response['data']['channels']);
@ -1356,8 +1357,9 @@ class RealtimeCustomClientTest extends Scope
$this->assertEquals('event', $responseUpdate['type']); $this->assertEquals('event', $responseUpdate['type']);
$this->assertNotEmpty($responseUpdate['data']); $this->assertNotEmpty($responseUpdate['data']);
$this->assertArrayHasKey('timestamp', $responseUpdate['data']); $this->assertArrayHasKey('timestamp', $responseUpdate['data']);
$this->assertCount(4, $responseUpdate['data']['channels']); $this->assertCount(5, $responseUpdate['data']['channels']);
$this->assertContains('console', $responseUpdate['data']['channels']); $this->assertContains('console', $responseUpdate['data']['channels']);
$this->assertContains("projects.{$this->getProject()['$id']}", $response['data']['channels']);
$this->assertContains('executions', $responseUpdate['data']['channels']); $this->assertContains('executions', $responseUpdate['data']['channels']);
$this->assertContains("executions.{$executionId}", $responseUpdate['data']['channels']); $this->assertContains("executions.{$executionId}", $responseUpdate['data']['channels']);
$this->assertContains("functions.{$functionId}", $responseUpdate['data']['channels']); $this->assertContains("functions.{$functionId}", $responseUpdate['data']['channels']);