From 1c8cc6fc92d2948439b0ef3a494c61ce48a12aa1 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 1 May 2026 12:40:22 +1200 Subject: [PATCH] feat(insights): add response models Adds the Insight, InsightCta, and InsightCtaResult response models and registers their model identifiers on the Response class so endpoints can serialise insights consistently across the SDK surface. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/Appwrite/Utopia/Response.php | 6 + .../Utopia/Response/Model/Insight.php | 125 ++++++++++++++++++ .../Utopia/Response/Model/InsightCta.php | 48 +++++++ .../Response/Model/InsightCtaResult.php | 54 ++++++++ 4 files changed, 233 insertions(+) create mode 100644 src/Appwrite/Utopia/Response/Model/Insight.php create mode 100644 src/Appwrite/Utopia/Response/Model/InsightCta.php create mode 100644 src/Appwrite/Utopia/Response/Model/InsightCtaResult.php diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 899cdc086a..dc2c54d4a5 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -330,6 +330,12 @@ class Response extends SwooleResponse public const MODEL_HEALTH_CERTIFICATE = 'healthCertificate'; public const MODEL_HEALTH_STATUS_LIST = 'healthStatusList'; + // Insights + public const MODEL_INSIGHT = 'insight'; + public const MODEL_INSIGHT_LIST = 'insightList'; + public const MODEL_INSIGHT_CTA = 'insightCta'; + public const MODEL_INSIGHT_CTA_RESULT = 'insightCtaResult'; + // Console public const MODEL_CONSOLE_VARIABLES = 'consoleVariables'; public const MODEL_CONSOLE_OAUTH2_PROVIDER_PARAMETER = 'consoleOAuth2ProviderParameter'; diff --git a/src/Appwrite/Utopia/Response/Model/Insight.php b/src/Appwrite/Utopia/Response/Model/Insight.php new file mode 100644 index 0000000000..1c567f8c72 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/Insight.php @@ -0,0 +1,125 @@ +addRule('$id', [ + 'type' => self::TYPE_STRING, + 'description' => 'Insight ID.', + 'default' => '', + 'example' => '5e5ea5c16897e', + ]) + ->addRule('$createdAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Insight creation date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('$updatedAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Insight update date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('$permissions', [ + 'type' => self::TYPE_STRING, + 'description' => 'Insight permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', + 'default' => [], + 'example' => ['read("any")'], + 'array' => true, + ]) + ->addRule('type', [ + 'type' => self::TYPE_STRING, + 'description' => 'Insight type. One of databaseIndex, databasePerformance, sitePerformance, siteAccessibility, siteSeo, functionPerformance.', + 'default' => '', + 'example' => 'databaseIndex', + ]) + ->addRule('severity', [ + 'type' => self::TYPE_STRING, + 'description' => 'Insight severity. One of info, warning, critical.', + 'default' => 'info', + 'example' => 'warning', + ]) + ->addRule('resourceType', [ + 'type' => self::TYPE_STRING, + 'description' => 'Type of the resource the insight is about. Plural noun, e.g. databases, sites, functions.', + 'default' => '', + 'example' => 'databases', + ]) + ->addRule('resourceId', [ + 'type' => self::TYPE_STRING, + 'description' => 'ID of the resource the insight is about.', + 'default' => '', + 'example' => 'main', + ]) + ->addRule('resourceInternalId', [ + 'type' => self::TYPE_STRING, + 'description' => 'Internal ID of the resource the insight is about.', + 'default' => '', + 'example' => '5e5ea5c16897e', + ]) + ->addRule('title', [ + 'type' => self::TYPE_STRING, + 'description' => 'Insight title.', + 'default' => '', + 'example' => 'Missing index on collection orders', + ]) + ->addRule('summary', [ + 'type' => self::TYPE_STRING, + 'description' => 'Short markdown summary describing the insight.', + 'default' => '', + 'example' => 'Queries against `orders.status` are scanning the full collection.', + ]) + ->addRule('payload', [ + 'type' => self::TYPE_JSON, + 'description' => 'Type-specific structured payload for the insight.', + 'default' => new \stdClass(), + 'example' => ['databaseId' => 'main', 'collectionId' => 'orders'], + ]) + ->addRule('ctas', [ + 'type' => Response::MODEL_INSIGHT_CTA, + 'description' => 'List of call-to-action buttons attached to this insight.', + 'default' => [], + 'example' => [], + 'array' => true, + ]) + ->addRule('analyzedAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Time the insight was analyzed in ISO 8601 format.', + 'default' => null, + 'example' => self::TYPE_DATETIME_EXAMPLE, + 'required' => false, + ]) + ->addRule('dismissedAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Time the insight was dismissed in ISO 8601 format. Empty when not dismissed.', + 'default' => null, + 'example' => self::TYPE_DATETIME_EXAMPLE, + 'required' => false, + ]) + ->addRule('dismissedBy', [ + 'type' => self::TYPE_STRING, + 'description' => 'User ID that dismissed the insight. Empty when not dismissed.', + 'default' => '', + 'example' => '5e5ea5c16897e', + 'required' => false, + ]); + } + + public function getName(): string + { + return 'Insight'; + } + + public function getType(): string + { + return Response::MODEL_INSIGHT; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/InsightCta.php b/src/Appwrite/Utopia/Response/Model/InsightCta.php new file mode 100644 index 0000000000..ac35363043 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/InsightCta.php @@ -0,0 +1,48 @@ +addRule('id', [ + 'type' => self::TYPE_STRING, + 'description' => 'CTA identifier, unique within the parent insight.', + 'default' => '', + 'example' => 'createIndex', + ]) + ->addRule('label', [ + 'type' => self::TYPE_STRING, + 'description' => 'Human-readable label for the CTA, used in UI.', + 'default' => '', + 'example' => 'Create missing index', + ]) + ->addRule('action', [ + 'type' => self::TYPE_STRING, + 'description' => 'Registered server-side action name to execute when this CTA is triggered.', + 'default' => '', + 'example' => 'databases.createIndex', + ]) + ->addRule('params', [ + 'type' => self::TYPE_JSON, + 'description' => 'Parameter map passed to the action when this CTA is triggered.', + 'default' => new \stdClass(), + 'example' => ['databaseId' => 'main', 'collectionId' => 'orders', 'key' => '_idx_status'], + ]); + } + + public function getName(): string + { + return 'InsightCta'; + } + + public function getType(): string + { + return Response::MODEL_INSIGHT_CTA; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/InsightCtaResult.php b/src/Appwrite/Utopia/Response/Model/InsightCtaResult.php new file mode 100644 index 0000000000..a6fe9addca --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/InsightCtaResult.php @@ -0,0 +1,54 @@ +addRule('insightId', [ + 'type' => self::TYPE_STRING, + 'description' => 'ID of the insight the CTA was triggered against.', + 'default' => '', + 'example' => '5e5ea5c16897e', + ]) + ->addRule('ctaId', [ + 'type' => self::TYPE_STRING, + 'description' => 'ID of the CTA that was triggered.', + 'default' => '', + 'example' => 'createIndex', + ]) + ->addRule('action', [ + 'type' => self::TYPE_STRING, + 'description' => 'Registered server-side action that was executed.', + 'default' => '', + 'example' => 'databases.createIndex', + ]) + ->addRule('status', [ + 'type' => self::TYPE_STRING, + 'description' => 'Outcome of the CTA execution. One of succeeded, failed.', + 'default' => 'succeeded', + 'example' => 'succeeded', + ]) + ->addRule('result', [ + 'type' => self::TYPE_JSON, + 'description' => 'Action-specific result data. May reference the resource that was created or updated.', + 'default' => new \stdClass(), + 'example' => ['indexId' => '_idx_status'], + ]); + } + + public function getName(): string + { + return 'InsightCtaResult'; + } + + public function getType(): string + { + return Response::MODEL_INSIGHT_CTA_RESULT; + } +}