diff --git a/src/Endpoints/EmailEndpoint.php b/src/Endpoints/EmailEndpoint.php index e6058a0..5137e7b 100644 --- a/src/Endpoints/EmailEndpoint.php +++ b/src/Endpoints/EmailEndpoint.php @@ -10,6 +10,7 @@ /** * @phpstan-import-type SendMailRequest from \Lettermint\Types\ApiTypes * @phpstan-import-type SendBatchMailRequest from \Lettermint\Types\ApiTypes + * @phpstan-import-type SandboxResult from \Lettermint\Types\ApiTypes * * @phpstan-type AttachmentPayload array{ * filename: string, @@ -37,7 +38,8 @@ * tag?: string|null, * tags?: list, * settings?: EmailSettings|null, - * headers?: array + * headers?: array, + * sandbox_result?: SandboxResult * } */ class EmailEndpoint extends Endpoint @@ -291,6 +293,18 @@ public function tags(array $tags): self return $this; } + /** + * Select the simulated result for a Sandbox project. + * + * @phpstan-param SandboxResult $result + */ + public function sandboxResult(string $result): self + { + $this->payload['sandbox_result'] = $result; + + return $this; + } + /** * Set per-email settings. * diff --git a/src/Objects/DomainData.php b/src/Objects/DomainData.php index 288e687..a9f1eba 100644 --- a/src/Objects/DomainData.php +++ b/src/Objects/DomainData.php @@ -10,13 +10,13 @@ * @property 'legacy_txt'|'managed_cname' $dkim_mode * @property bool $rotation_ready * @property string|null $status_changed_at - * @property list $dns_records + * @property list<\Lettermint\Objects\DomainDnsRecordData> $dns_records * @property list> $projects * @property string $created_at */ final class DomainData extends Resource { protected static array $casts = [ - 'dns_records' => [DomainDnsRecordData::class], + 'dns_records' => [\Lettermint\Objects\DomainDnsRecordData::class], ]; } diff --git a/src/Objects/MessageData.php b/src/Objects/MessageData.php index b1fc4fc..422acaf 100644 --- a/src/Objects/MessageData.php +++ b/src/Objects/MessageData.php @@ -7,27 +7,30 @@ /** * @property string $id * @property 'inbound'|'outbound' $type - * @property 'scheduled'|'pending'|'queued'|'suppressed'|'processed'|'delivered'|'opened'|'clicked'|'soft_bounced'|'hard_bounced'|'spam_complaint'|'failed'|'blocked'|'policy_rejected'|'unsubscribed'|'canceled' $status + * @property 'scheduled'|'pending'|'queued'|'quarantined'|'suppressed'|'processed'|'delivered'|'opened'|'clicked'|'soft_bounced'|'hard_bounced'|'spam_complaint'|'failed'|'blocked'|'policy_rejected'|'unsubscribed'|'canceled' $status * @property string|null $status_changed_at * @property string|null $scheduled_at * @property string|null $tag + * @property list> $tags * @property string $from_email * @property string|null $from_name * @property list|null $reply_to * @property string|null $subject - * @property list|null $to - * @property list|null $cc - * @property list|null $bcc - * @property list|null $attachments + * @property list<\Lettermint\Objects\MessageRecipientData>|null $to + * @property list<\Lettermint\Objects\MessageRecipientData>|null $cc + * @property list<\Lettermint\Objects\MessageRecipientData>|null $bcc + * @property list<\Lettermint\Objects\MessageAttachmentData>|null $attachments * @property array|null $metadata * @property float|int|null $spam_score - * @property list $spam_symbols + * @property list<\Lettermint\Objects\SpamSymbol> $spam_symbols * @property string $route_id * @property string $created_at + * @property 'live'|'sandbox' $delivery_mode + * @property 'delivered'|'hard_bounced'|'soft_bounced'|'deferred'|'failed'|'suppressed'|'spam_complaint'|'auto_replied'|'opened'|'clicked'|'unsubscribed'|null $sandbox_result */ final class MessageData extends Resource { protected static array $casts = [ - 'spam_symbols' => [SpamSymbol::class], + 'spam_symbols' => [\Lettermint\Objects\SpamSymbol::class], ]; } diff --git a/src/Objects/MessageEventData.php b/src/Objects/MessageEventData.php index 2410b57..1e7972f 100644 --- a/src/Objects/MessageEventData.php +++ b/src/Objects/MessageEventData.php @@ -6,7 +6,9 @@ /** * @property string $message_id - * @property 'scheduled'|'rescheduled'|'canceled'|'released'|'queued'|'processed'|'suppressed'|'delivered'|'auto_replied'|'soft_bounced'|'hard_bounced'|'spam_complaint'|'failed'|'blocked'|'policy_rejected'|'unsubscribed'|'opened'|'clicked'|'inbound_received'|'inbound_queued'|'inbound_spam_blocked'|'inbound_processed'|'inbound_retry' $event + * @property 'scheduled'|'rescheduled'|'canceled'|'released'|'queued'|'processed'|'suppressed'|'delivered'|'auto_replied'|'soft_bounced'|'hard_bounced'|'spam_complaint'|'failed'|'blocked'|'policy_rejected'|'unsubscribed'|'opened'|'clicked'|'inbound_received'|'inbound_queued'|'inbound_spam_blocked'|'inbound_released'|'inbound_processed'|'inbound_retry' $event + * @property string|null $tag + * @property list> $tags * @property array|null $metadata * @property string $timestamp */ diff --git a/src/Objects/MessageListData.php b/src/Objects/MessageListData.php index b23959f..8fe61e0 100644 --- a/src/Objects/MessageListData.php +++ b/src/Objects/MessageListData.php @@ -7,19 +7,22 @@ /** * @property string $id * @property 'inbound'|'outbound' $type - * @property 'scheduled'|'pending'|'queued'|'suppressed'|'processed'|'delivered'|'opened'|'clicked'|'soft_bounced'|'hard_bounced'|'spam_complaint'|'failed'|'blocked'|'policy_rejected'|'unsubscribed'|'canceled' $status + * @property 'scheduled'|'pending'|'queued'|'quarantined'|'suppressed'|'processed'|'delivered'|'opened'|'clicked'|'soft_bounced'|'hard_bounced'|'spam_complaint'|'failed'|'blocked'|'policy_rejected'|'unsubscribed'|'canceled' $status * @property string|null $scheduled_at * @property float|int|null $spam_score * @property string $from_email * @property string|null $from_name * @property string|null $subject - * @property list|null $to - * @property list|null $cc - * @property list|null $bcc + * @property list<\Lettermint\Objects\MessageRecipientData>|null $to + * @property list<\Lettermint\Objects\MessageRecipientData>|null $cc + * @property list<\Lettermint\Objects\MessageRecipientData>|null $bcc * @property list|null $reply_to * @property string|null $tag + * @property list> $tags * @property string|null $status_changed_at * @property string $created_at + * @property 'live'|'sandbox' $delivery_mode + * @property 'delivered'|'hard_bounced'|'soft_bounced'|'deferred'|'failed'|'suppressed'|'spam_complaint'|'auto_replied'|'opened'|'clicked'|'unsubscribed'|null $sandbox_result */ final class MessageListData extends Resource { diff --git a/src/Objects/MessageRecipientData.php b/src/Objects/MessageRecipientData.php index a9d88e3..56d102e 100644 --- a/src/Objects/MessageRecipientData.php +++ b/src/Objects/MessageRecipientData.php @@ -7,6 +7,7 @@ /** * @property string $email * @property string|null $name + * @property 'delivered'|'hard_bounced'|'soft_bounced'|'deferred'|'failed'|'suppressed'|'spam_complaint'|'auto_replied'|'opened'|'clicked'|'unsubscribed'|null $sandbox_result */ final class MessageRecipientData extends Resource { diff --git a/src/Objects/ProjectData.php b/src/Objects/ProjectData.php index d7bec33..d102452 100644 --- a/src/Objects/ProjectData.php +++ b/src/Objects/ProjectData.php @@ -13,18 +13,19 @@ * @property string|null $token_generated_at * @property string|null $token_last_used_at * @property string|null $token_last_used_ip - * @property list $routes + * @property list<\Lettermint\Objects\RouteListData> $routes * @property int $routes_count - * @property list $domains + * @property list<\Lettermint\Objects\DomainData> $domains * @property int $domains_count - * @property MessageStatsData|mixed $last_28_days + * @property \Lettermint\Objects\MessageStatsData|null $last_28_days * @property string $created_at * @property string $updated_at + * @property 'live'|'sandbox' $delivery_mode */ final class ProjectData extends Resource { protected static array $casts = [ - 'routes' => [RouteData::class], - 'domains' => [DomainData::class], + 'routes' => [\Lettermint\Objects\RouteData::class], + 'domains' => [\Lettermint\Objects\DomainData::class], ]; } diff --git a/src/Objects/ProjectListData.php b/src/Objects/ProjectListData.php index 4ed7af1..350409c 100644 --- a/src/Objects/ProjectListData.php +++ b/src/Objects/ProjectListData.php @@ -10,13 +10,13 @@ * @property bool $smtp_enabled * @property int $routes_count * @property int $domains_count - * @property MessageStatsData $last_28_days + * @property \Lettermint\Objects\MessageStatsData $last_28_days * @property string $created_at * @property string $updated_at */ final class ProjectListData extends Resource { protected static array $casts = [ - 'last_28_days' => MessageStatsData::class, + 'last_28_days' => \Lettermint\Objects\MessageStatsData::class, ]; } diff --git a/src/Objects/RescheduleMessageRequest.php b/src/Objects/RescheduleMessageRequest.php new file mode 100644 index 0000000..eeac35f --- /dev/null +++ b/src/Objects/RescheduleMessageRequest.php @@ -0,0 +1,13 @@ +|mixed $settings - * @property ProjectListData $project + * @property array|null $settings + * @property \Lettermint\Objects\ProjectListData $project * @property int $webhooks_count * @property int $suppressed_recipients_count - * @property array|list $statistics + * @property list<\Lettermint\Objects\RouteStatisticData> $statistics * @property string $created_at * @property string $updated_at */ final class RouteData extends Resource { protected static array $casts = [ - 'project' => ProjectData::class, + 'project' => \Lettermint\Objects\ProjectData::class, + 'statistics' => [\Lettermint\Objects\RouteStatisticData::class], ]; } diff --git a/src/Objects/SendMailRequest.php b/src/Objects/SendMailRequest.php index 4efc4d4..4fc8d9c 100644 --- a/src/Objects/SendMailRequest.php +++ b/src/Objects/SendMailRequest.php @@ -7,19 +7,21 @@ /** * @property string $route * @property string $from - * @property string $subject - * @property string $scheduled_at - * @property string|null $tag - * @property string|null $html - * @property string|null $text * @property list $to * @property list $cc * @property list $bcc * @property list $reply_to + * @property string $subject + * @property string $scheduled_at * @property array $headers * @property array $metadata + * @property string|null $tag + * @property list> $tags * @property array|null $settings + * @property string|null $html + * @property string|null $text * @property list> $attachments + * @property 'delivered'|'hard_bounced'|'soft_bounced'|'deferred'|'failed'|'suppressed'|'spam_complaint'|'auto_replied'|'opened'|'clicked'|'unsubscribed' $sandbox_result */ final class SendMailRequest extends Resource { diff --git a/src/Objects/StatsDailyData.php b/src/Objects/StatsDailyData.php index f44765e..e23b310 100644 --- a/src/Objects/StatsDailyData.php +++ b/src/Objects/StatsDailyData.php @@ -12,9 +12,9 @@ * @property int $spam_complaints * @property int|null $opened * @property int|null $clicked - * @property StatsInboundData $inbound - * @property StatsTypeData|mixed $transactional - * @property StatsTypeData|mixed $broadcast + * @property \Lettermint\Objects\StatsInboundData $inbound + * @property \Lettermint\Objects\StatsTypeData|null $transactional + * @property \Lettermint\Objects\StatsTypeData|null $broadcast * @property int|null $observed_opened * @property int|null $human_opened * @property int|null $privacy_opened @@ -25,6 +25,6 @@ final class StatsDailyData extends Resource { protected static array $casts = [ - 'inbound' => StatsInboundData::class, + 'inbound' => \Lettermint\Objects\StatsInboundData::class, ]; } diff --git a/src/Objects/StatsTotalsData.php b/src/Objects/StatsTotalsData.php index de85481..5b45802 100644 --- a/src/Objects/StatsTotalsData.php +++ b/src/Objects/StatsTotalsData.php @@ -11,9 +11,9 @@ * @property int $spam_complaints * @property int|null $opened * @property int|null $clicked - * @property StatsInboundData $inbound - * @property StatsTypeData|mixed $transactional - * @property StatsTypeData|mixed $broadcast + * @property \Lettermint\Objects\StatsInboundData $inbound + * @property \Lettermint\Objects\StatsTypeData|null $transactional + * @property \Lettermint\Objects\StatsTypeData|null $broadcast * @property int|null $observed_opened * @property int|null $human_opened * @property int|null $privacy_opened @@ -24,6 +24,6 @@ final class StatsTotalsData extends Resource { protected static array $casts = [ - 'inbound' => StatsInboundData::class, + 'inbound' => \Lettermint\Objects\StatsInboundData::class, ]; } diff --git a/src/Objects/StoreProjectData.php b/src/Objects/StoreProjectData.php index 92f1378..2fcc9c6 100644 --- a/src/Objects/StoreProjectData.php +++ b/src/Objects/StoreProjectData.php @@ -9,6 +9,7 @@ * @property bool $smtp_enabled * @property 'both'|'transactional'|'broadcast' $initial_routes * @property bool $short_token + * @property 'live'|'sandbox' $delivery_mode */ final class StoreProjectData extends Resource { diff --git a/src/Objects/StoreSuppressionData.php b/src/Objects/StoreSuppressionData.php index a67d6d7..4fffc1f 100644 --- a/src/Objects/StoreSuppressionData.php +++ b/src/Objects/StoreSuppressionData.php @@ -6,11 +6,12 @@ /** * @property string|null $email + * @property list|null $emails * @property 'spam_complaint'|'hard_bounce'|'unsubscribe'|'manual' $reason - * @property 'global'|'team'|'project'|'route' $scope + * @property 'team'|'project'|'route' $scope * @property string|null $route_id * @property string|null $project_id - * @property list|null $emails + * @property 'all'|'broadcast'|null $applies_to */ final class StoreSuppressionData extends Resource { diff --git a/src/Objects/StoreWebhookData.php b/src/Objects/StoreWebhookData.php index b0eed6a..e74896b 100644 --- a/src/Objects/StoreWebhookData.php +++ b/src/Objects/StoreWebhookData.php @@ -5,12 +5,16 @@ use Lettermint\Resource; /** - * @property string $route_id * @property string $name * @property string $url + * @property list<'message.created'|'message.sent'|'message.delivered'|'message.auto_replied'|'message.hard_bounced'|'message.soft_bounced'|'message.spam_complaint'|'message.failed'|'message.suppressed'|'message.unsubscribed'|'message.opened'|'message.clicked'|'message.inbound'|'message.policy_rejected'|'message.scheduled'|'message.rescheduled'|'message.canceled'|'message.released'|'suppression.added'|'suppression.removed'|'webhook.test'> $events * @property bool|null $enabled * @property bool|null $include_machine_events - * @property list<'message.created'|'message.sent'|'message.delivered'|'message.auto_replied'|'message.hard_bounced'|'message.soft_bounced'|'message.spam_complaint'|'message.failed'|'message.suppressed'|'message.unsubscribed'|'message.opened'|'message.clicked'|'message.inbound'|'message.policy_rejected'|'suppression.added'|'suppression.removed'|'webhook.test'> $events + * @property 'team'|'project'|'route'|null $scope + * @property list $project_ids + * @property list $route_ids + * @property string|null $route_id + * @property 'live'|'sandbox'|'both'|null $delivery_mode_filter */ final class StoreWebhookData extends Resource { diff --git a/src/Objects/SuppressedRecipientData.php b/src/Objects/SuppressedRecipientData.php index 40f0949..7c27104 100644 --- a/src/Objects/SuppressedRecipientData.php +++ b/src/Objects/SuppressedRecipientData.php @@ -9,16 +9,14 @@ * @property 'email'|'domain'|'extension' $type * @property string $value * @property 'spam_complaint'|'hard_bounce'|'unsubscribe'|'manual' $reason - * @property 'global'|'team'|'project'|'route' $scope + * @property 'team'|'project'|'route' $scope + * @property 'all'|'broadcast' $applies_to * @property string|null $project_id * @property string|null $route_id - * @property SuppressionSourceMessageData|null $source_message + * @property \Lettermint\Objects\SuppressionSourceMessageData|null $source_message * @property string $created_at - * @property string $updated_at */ final class SuppressedRecipientData extends Resource { - protected static array $casts = [ - 'source_message' => SuppressionSourceMessageData::class, - ]; + // } diff --git a/src/Objects/TeamData.php b/src/Objects/TeamData.php index ca1d1cd..057ca14 100644 --- a/src/Objects/TeamData.php +++ b/src/Objects/TeamData.php @@ -13,7 +13,7 @@ * @property int $tier * @property string|null $verified_at * @property list $features - * @property list $addons + * @property list<\Lettermint\Objects\TeamAddonData> $addons * @property string $created_at * @property int $domains_count * @property int $projects_count @@ -22,6 +22,6 @@ final class TeamData extends Resource { protected static array $casts = [ - 'addons' => [TeamAddonData::class], + 'addons' => [\Lettermint\Objects\TeamAddonData::class], ]; } diff --git a/src/Objects/TeamMemberData.php b/src/Objects/TeamMemberData.php index 640f0b4..d88c314 100644 --- a/src/Objects/TeamMemberData.php +++ b/src/Objects/TeamMemberData.php @@ -9,12 +9,12 @@ * @property string $name * @property string $email * @property array $role - * @property TeamMemberProjectAccessData $project_access + * @property \Lettermint\Objects\TeamMemberProjectAccessData $project_access * @property string|null $joined_at */ final class TeamMemberData extends Resource { protected static array $casts = [ - 'project_access' => TeamMemberProjectAccessData::class, + 'project_access' => \Lettermint\Objects\TeamMemberProjectAccessData::class, ]; } diff --git a/src/Objects/TeamRoleData.php b/src/Objects/TeamRoleData.php index 7eecb14..d4924d1 100644 --- a/src/Objects/TeamRoleData.php +++ b/src/Objects/TeamRoleData.php @@ -8,7 +8,7 @@ * @property string $id * @property string $name * @property 'owner'|'admin'|'member'|null $system_key - * @property list $permissions + * @property list<'team:manage'|'billing:manage'|'security:manage'|'audit:read'|'support:manage'|'members:read'|'members:manage'|'roles:manage'|'team_tokens:read'|'team_tokens:manage'|'team_tokens:rotate'|'team_tokens:revoke'|'projects:create'|'team_suppressions:read'|'team_suppressions:add'|'team_suppressions:remove'|'projects:read'|'projects:manage'|'projects:delete'|'routes:read'|'routes:manage'|'routes:delete'|'domains:read'|'domains:manage'|'domains:delete'|'project_tokens:read'|'project_tokens:manage'|'project_tokens:rotate'|'project_tokens:revoke'|'webhooks:read'|'webhooks:manage'|'webhooks:delete'|'webhooks:rotate_secret'|'stats:read'|'messages:read'|'messages:read_content'|'messages:send'|'suppressions:read'|'suppressions:add'|'suppressions:remove'> $permissions * @property bool $assignable */ final class TeamRoleData extends Resource diff --git a/src/Objects/UpdateProjectData.php b/src/Objects/UpdateProjectData.php index 9126d5a..92cfd21 100644 --- a/src/Objects/UpdateProjectData.php +++ b/src/Objects/UpdateProjectData.php @@ -9,6 +9,7 @@ * @property bool|null $smtp_enabled * @property bool|null $redact_email_content * @property string|null $default_route_id + * @property 'live'|'sandbox'|null $delivery_mode */ final class UpdateProjectData extends Resource { diff --git a/src/Objects/UpdateRouteData.php b/src/Objects/UpdateRouteData.php index 08b5799..ec0435a 100644 --- a/src/Objects/UpdateRouteData.php +++ b/src/Objects/UpdateRouteData.php @@ -6,8 +6,8 @@ /** * @property string|null $name - * @property \Lettermint\Objects\UpdateRouteSettingsData|mixed $settings - * @property \Lettermint\Objects\UpdateRouteInboundSettingsData|mixed $inbound_settings + * @property \Lettermint\Objects\UpdateRouteSettingsData|null $settings + * @property \Lettermint\Objects\UpdateRouteInboundSettingsData|null $inbound_settings */ final class UpdateRouteData extends Resource { diff --git a/src/Objects/UpdateRouteInboundSettingsData.php b/src/Objects/UpdateRouteInboundSettingsData.php index 00930b7..2d1a213 100644 --- a/src/Objects/UpdateRouteInboundSettingsData.php +++ b/src/Objects/UpdateRouteInboundSettingsData.php @@ -7,7 +7,7 @@ /** * @property string|null $inbound_domain * @property float|int|null $inbound_spam_threshold - * @property 'inline'|'url'|mixed $attachment_delivery + * @property 'inline'|'url'|null $attachment_delivery */ final class UpdateRouteInboundSettingsData extends Resource { diff --git a/src/Objects/UpdateRouteSettingsData.php b/src/Objects/UpdateRouteSettingsData.php index 30b2c07..c299e65 100644 --- a/src/Objects/UpdateRouteSettingsData.php +++ b/src/Objects/UpdateRouteSettingsData.php @@ -9,6 +9,7 @@ * @property bool|null $track_clicks * @property bool|null $generate_plaintext_fallback * @property bool|null $suppress_auto_responders + * @property bool|null $suppress_disposable_recipients * @property 'opportunistic'|'enforced'|null $tls * @property bool|null $disable_hosted_unsubscribe * @property bool|null $redact_email_content diff --git a/src/Objects/UpdateWebhookData.php b/src/Objects/UpdateWebhookData.php index 2fb1a7f..2665c46 100644 --- a/src/Objects/UpdateWebhookData.php +++ b/src/Objects/UpdateWebhookData.php @@ -7,9 +7,14 @@ /** * @property string $name * @property string $url + * @property list<'message.created'|'message.sent'|'message.delivered'|'message.auto_replied'|'message.hard_bounced'|'message.soft_bounced'|'message.spam_complaint'|'message.failed'|'message.suppressed'|'message.unsubscribed'|'message.opened'|'message.clicked'|'message.inbound'|'message.policy_rejected'|'message.scheduled'|'message.rescheduled'|'message.canceled'|'message.released'|'suppression.added'|'suppression.removed'|'webhook.test'> $events * @property bool $enabled * @property bool $include_machine_events - * @property list<'message.created'|'message.sent'|'message.delivered'|'message.auto_replied'|'message.hard_bounced'|'message.soft_bounced'|'message.spam_complaint'|'message.failed'|'message.suppressed'|'message.unsubscribed'|'message.opened'|'message.clicked'|'message.inbound'|'message.policy_rejected'|'suppression.added'|'suppression.removed'|'webhook.test'> $events + * @property 'team'|'project'|'route' $scope + * @property list $project_ids + * @property list $route_ids + * @property string|null $route_id + * @property 'live'|'sandbox'|'both' $delivery_mode_filter */ final class UpdateWebhookData extends Resource { diff --git a/src/Objects/WebhookData.php b/src/Objects/WebhookData.php index 26f8b50..65851ae 100644 --- a/src/Objects/WebhookData.php +++ b/src/Objects/WebhookData.php @@ -6,16 +6,19 @@ /** * @property string $id - * @property string $route_id + * @property 'team'|'project'|'route' $scope + * @property list $project_ids + * @property list $route_ids + * @property string|null $route_id * @property string $name * @property string $url * @property list $events * @property bool $enabled * @property bool $include_machine_events - * @property string $secret * @property string|null $last_called_at * @property string $created_at * @property string $updated_at + * @property 'live'|'sandbox'|'both' $delivery_mode_filter */ final class WebhookData extends Resource { diff --git a/src/Objects/WebhookDeliveryData.php b/src/Objects/WebhookDeliveryData.php index c42ff11..cf5013b 100644 --- a/src/Objects/WebhookDeliveryData.php +++ b/src/Objects/WebhookDeliveryData.php @@ -7,7 +7,10 @@ /** * @property string $id * @property string $webhook_id - * @property 'message.created'|'message.sent'|'message.delivered'|'message.auto_replied'|'message.hard_bounced'|'message.soft_bounced'|'message.spam_complaint'|'message.failed'|'message.suppressed'|'message.unsubscribed'|'message.opened'|'message.clicked'|'message.inbound'|'message.policy_rejected'|'suppression.added'|'suppression.removed'|'webhook.test' $event_type + * @property 'message.created'|'message.sent'|'message.delivered'|'message.auto_replied'|'message.hard_bounced'|'message.soft_bounced'|'message.spam_complaint'|'message.failed'|'message.suppressed'|'message.unsubscribed'|'message.opened'|'message.clicked'|'message.inbound'|'message.policy_rejected'|'message.scheduled'|'message.rescheduled'|'message.canceled'|'message.released'|'suppression.added'|'suppression.removed'|'webhook.test' $event_type + * @property string|null $source_scope + * @property string|null $source_project_id + * @property string|null $source_route_id * @property 'pending'|'success'|'failed'|'client_error'|'server_error'|'timeout' $status * @property int $attempt_number * @property int|null $http_status_code @@ -18,6 +21,7 @@ * @property string|null $error_message * @property string|null $delivered_at * @property string $timestamp + * @property bool $sandbox */ final class WebhookDeliveryData extends Resource { diff --git a/src/Objects/WebhookDeliveryListData.php b/src/Objects/WebhookDeliveryListData.php index 0cd577c..571dabf 100644 --- a/src/Objects/WebhookDeliveryListData.php +++ b/src/Objects/WebhookDeliveryListData.php @@ -7,7 +7,10 @@ /** * @property string $id * @property string $webhook_id - * @property 'message.created'|'message.sent'|'message.delivered'|'message.auto_replied'|'message.hard_bounced'|'message.soft_bounced'|'message.spam_complaint'|'message.failed'|'message.suppressed'|'message.unsubscribed'|'message.opened'|'message.clicked'|'message.inbound'|'message.policy_rejected'|'suppression.added'|'suppression.removed'|'webhook.test' $event_type + * @property 'message.created'|'message.sent'|'message.delivered'|'message.auto_replied'|'message.hard_bounced'|'message.soft_bounced'|'message.spam_complaint'|'message.failed'|'message.suppressed'|'message.unsubscribed'|'message.opened'|'message.clicked'|'message.inbound'|'message.policy_rejected'|'message.scheduled'|'message.rescheduled'|'message.canceled'|'message.released'|'suppression.added'|'suppression.removed'|'webhook.test' $event_type + * @property string|null $source_scope + * @property string|null $source_project_id + * @property string|null $source_route_id * @property 'pending'|'success'|'failed'|'client_error'|'server_error'|'timeout' $status * @property int $attempt_number * @property int|null $http_status_code diff --git a/src/Objects/WebhookListData.php b/src/Objects/WebhookListData.php index f798f6c..aaac202 100644 --- a/src/Objects/WebhookListData.php +++ b/src/Objects/WebhookListData.php @@ -6,10 +6,13 @@ /** * @property string $id - * @property string $route_id + * @property 'team'|'project'|'route' $scope + * @property list $project_ids + * @property list $route_ids + * @property string|null $route_id * @property string $name * @property string $url - * @property list<'message.created'|'message.sent'|'message.delivered'|'message.auto_replied'|'message.hard_bounced'|'message.soft_bounced'|'message.spam_complaint'|'message.failed'|'message.suppressed'|'message.unsubscribed'|'message.opened'|'message.clicked'|'message.inbound'|'message.policy_rejected'|'suppression.added'|'suppression.removed'|'webhook.test'> $events + * @property list $events * @property bool $enabled * @property string|null $last_called_at * @property string $created_at diff --git a/src/Objects/WebhookSecretData.php b/src/Objects/WebhookSecretData.php new file mode 100644 index 0000000..8737b75 --- /dev/null +++ b/src/Objects/WebhookSecretData.php @@ -0,0 +1,27 @@ + $project_ids + * @property list $route_ids + * @property string|null $route_id + * @property string $name + * @property string $url + * @property list $events + * @property bool $enabled + * @property bool $include_machine_events + * @property string $secret + * @property string|null $last_called_at + * @property string $created_at + * @property string $updated_at + * @property 'live'|'sandbox'|'both' $delivery_mode_filter + */ +final class WebhookSecretData extends Resource +{ + // +} diff --git a/src/Responses/CreateWebhookResponse.php b/src/Responses/CreateWebhookResponse.php index d16a058..8ab24ed 100644 --- a/src/Responses/CreateWebhookResponse.php +++ b/src/Responses/CreateWebhookResponse.php @@ -5,12 +5,12 @@ use Lettermint\Resource; /** - * @property \Lettermint\Objects\WebhookData $data + * @property \Lettermint\Objects\WebhookSecretData $data * @property string $message */ final class CreateWebhookResponse extends Resource { protected static array $casts = [ - 'data' => \Lettermint\Objects\WebhookData::class, + 'data' => \Lettermint\Objects\WebhookSecretData::class, ]; } diff --git a/src/Responses/DomainResponse.php b/src/Responses/DomainResponse.php index f01a742..c585564 100644 --- a/src/Responses/DomainResponse.php +++ b/src/Responses/DomainResponse.php @@ -2,7 +2,6 @@ namespace Lettermint\Responses; -use Lettermint\Objects\DomainDnsRecordData; use Lettermint\Resource; /** @@ -11,7 +10,7 @@ * @property 'legacy_txt'|'managed_cname' $dkim_mode * @property bool $rotation_ready * @property string|null $status_changed_at - * @property list $dns_records + * @property list<\Lettermint\Objects\DomainDnsRecordData> $dns_records * @property list> $projects * @property string $created_at */ diff --git a/src/Responses/MessageEventsResponse.php b/src/Responses/MessageEventsResponse.php index 3421fc6..2d3e61e 100644 --- a/src/Responses/MessageEventsResponse.php +++ b/src/Responses/MessageEventsResponse.php @@ -6,12 +6,8 @@ /** * @property list<\Lettermint\Objects\MessageEventData> $data - * @property string|null $path - * @property int $per_page - * @property string|null $next_cursor - * @property string|null $next_page_url - * @property string|null $prev_cursor - * @property string|null $prev_page_url + * @property list $links + * @property array $meta */ final class MessageEventsResponse extends Resource { diff --git a/src/Responses/MessageListResponse.php b/src/Responses/MessageListResponse.php index cf58085..68f6b9c 100644 --- a/src/Responses/MessageListResponse.php +++ b/src/Responses/MessageListResponse.php @@ -6,12 +6,8 @@ /** * @property list<\Lettermint\Objects\MessageListData> $data - * @property string|null $path - * @property int $per_page - * @property string|null $next_cursor - * @property string|null $next_page_url - * @property string|null $prev_cursor - * @property string|null $prev_page_url + * @property list $links + * @property array $meta */ final class MessageListResponse extends Resource { diff --git a/src/Responses/MessageResponse.php b/src/Responses/MessageResponse.php index c0b8b63..86cdb37 100644 --- a/src/Responses/MessageResponse.php +++ b/src/Responses/MessageResponse.php @@ -7,9 +7,11 @@ /** * @property string $id * @property 'inbound'|'outbound' $type - * @property 'pending'|'queued'|'suppressed'|'processed'|'delivered'|'opened'|'clicked'|'soft_bounced'|'hard_bounced'|'spam_complaint'|'failed'|'blocked'|'policy_rejected'|'unsubscribed' $status + * @property 'scheduled'|'pending'|'queued'|'quarantined'|'suppressed'|'processed'|'delivered'|'opened'|'clicked'|'soft_bounced'|'hard_bounced'|'spam_complaint'|'failed'|'blocked'|'policy_rejected'|'unsubscribed'|'canceled' $status * @property string|null $status_changed_at + * @property string|null $scheduled_at * @property string|null $tag + * @property list> $tags * @property string $from_email * @property string|null $from_name * @property list|null $reply_to @@ -23,6 +25,8 @@ * @property list<\Lettermint\Objects\SpamSymbol> $spam_symbols * @property string $route_id * @property string $created_at + * @property 'live'|'sandbox' $delivery_mode + * @property 'delivered'|'hard_bounced'|'soft_bounced'|'deferred'|'failed'|'suppressed'|'spam_complaint'|'auto_replied'|'opened'|'clicked'|'unsubscribed'|null $sandbox_result */ final class MessageResponse extends Resource { diff --git a/src/Responses/ProjectResponse.php b/src/Responses/ProjectResponse.php index f43bdb6..f0eb8fc 100644 --- a/src/Responses/ProjectResponse.php +++ b/src/Responses/ProjectResponse.php @@ -2,9 +2,6 @@ namespace Lettermint\Responses; -use Lettermint\Objects\DomainData; -use Lettermint\Objects\MessageStatsData; -use Lettermint\Objects\RouteData; use Lettermint\Resource; /** @@ -16,13 +13,14 @@ * @property string|null $token_generated_at * @property string|null $token_last_used_at * @property string|null $token_last_used_ip - * @property list $routes + * @property list<\Lettermint\Objects\RouteData> $routes * @property int $routes_count - * @property list $domains + * @property list<\Lettermint\Objects\DomainData> $domains * @property int $domains_count - * @property MessageStatsData|mixed $last_28_days + * @property \Lettermint\Objects\MessageStatsData|null $last_28_days * @property string $created_at * @property string $updated_at + * @property 'live'|'sandbox' $delivery_mode */ final class ProjectResponse extends Resource { diff --git a/src/Responses/RegenerateWebhookSecretResponse.php b/src/Responses/RegenerateWebhookSecretResponse.php index 2272d23..734cdc3 100644 --- a/src/Responses/RegenerateWebhookSecretResponse.php +++ b/src/Responses/RegenerateWebhookSecretResponse.php @@ -5,12 +5,12 @@ use Lettermint\Resource; /** - * @property \Lettermint\Objects\WebhookData $data + * @property \Lettermint\Objects\WebhookSecretData $data * @property string $message */ final class RegenerateWebhookSecretResponse extends Resource { protected static array $casts = [ - 'data' => \Lettermint\Objects\WebhookData::class, + 'data' => \Lettermint\Objects\WebhookSecretData::class, ]; } diff --git a/src/Responses/RouteResponse.php b/src/Responses/RouteResponse.php index fef6dc8..a241a8f 100644 --- a/src/Responses/RouteResponse.php +++ b/src/Responses/RouteResponse.php @@ -2,8 +2,6 @@ namespace Lettermint\Responses; -use Lettermint\Objects\ProjectData; -use Lettermint\Objects\RouteStatisticData; use Lettermint\Resource; /** @@ -14,15 +12,16 @@ * @property 'transactional'|'broadcast'|'inbound' $route_type * @property bool $is_default * @property string|null $inbound_address + * @property string $inbound_mx_hostname * @property string|null $inbound_domain * @property string|null $inbound_domain_verified_at * @property float|int|null $inbound_spam_threshold * @property 'inline'|'url' $attachment_delivery - * @property array|mixed $settings - * @property ProjectData $project + * @property array|null $settings + * @property \Lettermint\Objects\ProjectData $project * @property int $webhooks_count * @property int $suppressed_recipients_count - * @property array|list $statistics + * @property list<\Lettermint\Objects\RouteStatisticData> $statistics * @property string $created_at * @property string $updated_at */ diff --git a/src/Responses/SendMailResponse.php b/src/Responses/SendMailResponse.php index 3e2feae..fbaa4aa 100644 --- a/src/Responses/SendMailResponse.php +++ b/src/Responses/SendMailResponse.php @@ -5,9 +5,11 @@ use Lettermint\Resource; /** - * @property string $message_id - * @property 'scheduled'|'pending'|'queued'|'suppressed'|'processed'|'delivered'|'opened'|'clicked'|'soft_bounced'|'hard_bounced'|'spam_complaint'|'failed'|'blocked'|'policy_rejected'|'unsubscribed'|'canceled' $status + * @property string|null $message_id + * @property 'scheduled'|'pending'|'queued'|'quarantined'|'suppressed'|'processed'|'delivered'|'opened'|'clicked'|'soft_bounced'|'hard_bounced'|'spam_complaint'|'failed'|'blocked'|'policy_rejected'|'unsubscribed'|'canceled' $status * @property string $scheduled_at + * @property bool $sandbox + * @property 'delivered'|'hard_bounced'|'soft_bounced'|'deferred'|'failed'|'suppressed'|'spam_complaint'|'auto_replied'|'opened'|'clicked'|'unsubscribed' $sandbox_result */ final class SendMailResponse extends Resource { diff --git a/src/Responses/TeamMembersAssignmentUpdateResponse.php b/src/Responses/TeamMembersAssignmentUpdateResponse.php index 30fd634..80c3b98 100644 --- a/src/Responses/TeamMembersAssignmentUpdateResponse.php +++ b/src/Responses/TeamMembersAssignmentUpdateResponse.php @@ -2,7 +2,6 @@ namespace Lettermint\Responses; -use Lettermint\Objects\TeamMemberProjectAccessData; use Lettermint\Resource; /** @@ -10,12 +9,10 @@ * @property string $name * @property string $email * @property array $role - * @property TeamMemberProjectAccessData $project_access + * @property \Lettermint\Objects\TeamMemberProjectAccessData $project_access * @property string|null $joined_at */ final class TeamMembersAssignmentUpdateResponse extends Resource { - protected static array $casts = [ - 'project_access' => TeamMemberProjectAccessData::class, - ]; + // } diff --git a/src/Responses/TeamMembersShowResponse.php b/src/Responses/TeamMembersShowResponse.php index e180ffb..9ce8a9e 100644 --- a/src/Responses/TeamMembersShowResponse.php +++ b/src/Responses/TeamMembersShowResponse.php @@ -2,7 +2,6 @@ namespace Lettermint\Responses; -use Lettermint\Objects\TeamMemberProjectAccessData; use Lettermint\Resource; /** @@ -10,12 +9,10 @@ * @property string $name * @property string $email * @property array $role - * @property TeamMemberProjectAccessData $project_access + * @property \Lettermint\Objects\TeamMemberProjectAccessData $project_access * @property string|null $joined_at */ final class TeamMembersShowResponse extends Resource { - protected static array $casts = [ - 'project_access' => TeamMemberProjectAccessData::class, - ]; + // } diff --git a/src/Responses/TeamResponse.php b/src/Responses/TeamResponse.php index 404000f..3b7849c 100644 --- a/src/Responses/TeamResponse.php +++ b/src/Responses/TeamResponse.php @@ -2,7 +2,6 @@ namespace Lettermint\Responses; -use Lettermint\Objects\TeamAddonData; use Lettermint\Resource; /** @@ -14,7 +13,7 @@ * @property int $tier * @property string|null $verified_at * @property list $features - * @property list $addons + * @property list<\Lettermint\Objects\TeamAddonData> $addons * @property string $created_at * @property int $domains_count * @property int $projects_count diff --git a/src/Responses/TeamRolesResponse.php b/src/Responses/TeamRolesResponse.php index 6074d8a..fe3a9ce 100644 --- a/src/Responses/TeamRolesResponse.php +++ b/src/Responses/TeamRolesResponse.php @@ -2,15 +2,14 @@ namespace Lettermint\Responses; -use Lettermint\Objects\TeamRoleData; use Lettermint\Resource; /** - * @property list $data + * @property list<\Lettermint\Objects\TeamRoleData> $data */ final class TeamRolesResponse extends Resource { protected static array $casts = [ - 'data' => [TeamRoleData::class], + 'data' => [\Lettermint\Objects\TeamRoleData::class], ]; } diff --git a/src/Responses/WebhookDeliveryResponse.php b/src/Responses/WebhookDeliveryResponse.php index a69d6f2..74a0a4e 100644 --- a/src/Responses/WebhookDeliveryResponse.php +++ b/src/Responses/WebhookDeliveryResponse.php @@ -7,7 +7,10 @@ /** * @property string $id * @property string $webhook_id - * @property 'message.created'|'message.sent'|'message.delivered'|'message.auto_replied'|'message.hard_bounced'|'message.soft_bounced'|'message.spam_complaint'|'message.failed'|'message.suppressed'|'message.unsubscribed'|'message.opened'|'message.clicked'|'message.inbound'|'message.policy_rejected'|'suppression.added'|'suppression.removed'|'webhook.test' $event_type + * @property 'message.created'|'message.sent'|'message.delivered'|'message.auto_replied'|'message.hard_bounced'|'message.soft_bounced'|'message.spam_complaint'|'message.failed'|'message.suppressed'|'message.unsubscribed'|'message.opened'|'message.clicked'|'message.inbound'|'message.policy_rejected'|'message.scheduled'|'message.rescheduled'|'message.canceled'|'message.released'|'suppression.added'|'suppression.removed'|'webhook.test' $event_type + * @property string|null $source_scope + * @property string|null $source_project_id + * @property string|null $source_route_id * @property 'pending'|'success'|'failed'|'client_error'|'server_error'|'timeout' $status * @property int $attempt_number * @property int|null $http_status_code @@ -18,6 +21,7 @@ * @property string|null $error_message * @property string|null $delivered_at * @property string $timestamp + * @property bool $sandbox */ final class WebhookDeliveryResponse extends Resource { diff --git a/src/Responses/WebhookResponse.php b/src/Responses/WebhookResponse.php index ba69d01..a818948 100644 --- a/src/Responses/WebhookResponse.php +++ b/src/Responses/WebhookResponse.php @@ -6,16 +6,19 @@ /** * @property string $id - * @property string $route_id + * @property 'team'|'project'|'route' $scope + * @property list $project_ids + * @property list $route_ids + * @property string|null $route_id * @property string $name * @property string $url * @property list $events * @property bool $enabled * @property bool $include_machine_events - * @property string $secret * @property string|null $last_called_at * @property string $created_at * @property string $updated_at + * @property 'live'|'sandbox'|'both' $delivery_mode_filter */ final class WebhookResponse extends Resource { diff --git a/src/Types/ApiTypes.php b/src/Types/ApiTypes.php index 9b4723e..4cb03e5 100644 --- a/src/Types/ApiTypes.php +++ b/src/Types/ApiTypes.php @@ -8,9 +8,10 @@ * @phpstan-type ApiObject array * @phpstan-type CursorPage array{data: list, path: string|null, per_page: int, next_cursor: string|null, next_page_url: string|null, prev_cursor: string|null, prev_page_url: string|null} * @phpstan-type MessageStatus 'scheduled'|'pending'|'queued'|'quarantined'|'suppressed'|'processed'|'delivered'|'opened'|'clicked'|'soft_bounced'|'hard_bounced'|'spam_complaint'|'failed'|'blocked'|'policy_rejected'|'unsubscribed'|'canceled' - * @phpstan-type SendMailRequest array{route?: string, from: string, to: non-empty-list, cc?: list, bcc?: list, reply_to?: list, subject: string, scheduled_at?: string, headers?: array, metadata?: array, tag?: string|null, tags?: list, settings?: array{track_opens?: bool, track_clicks?: bool, tls?: TlsPolicy}|null, html?: string|null, text?: string|null, attachments?: list} + * @phpstan-type SendMailRequest array{route?: string, from: string, to: non-empty-list, cc?: list, bcc?: list, reply_to?: list, subject: string, scheduled_at?: string, headers?: array, metadata?: array, tag?: string|null, tags?: list, settings?: array{track_opens?: bool, track_clicks?: bool, tls?: TlsPolicy}|null, html?: string|null, text?: string|null, attachments?: list, sandbox_result?: SandboxResult} * @phpstan-type SendBatchMailRequest list * @phpstan-type TlsPolicy 'opportunistic'|'enforced' + * @phpstan-type SandboxResult 'delivered'|'hard_bounced'|'soft_bounced'|'deferred'|'failed'|'suppressed'|'spam_complaint'|'auto_replied'|'opened'|'clicked'|'unsubscribed' * @phpstan-type AttachmentDelivery 'inline'|'url' * @phpstan-type BuiltInTeamRole 'owner'|'admin'|'member' * @phpstan-type CursorPaginator array{data: list, path: string|null, per_page: int, next_cursor: string|null, next_page_url: string|null, prev_cursor: string|null, prev_page_url: string|null} @@ -24,21 +25,22 @@ * @phpstan-type DomainStatus 'verified'|'partially_verified'|'pending_verification'|'failed_verification' * @phpstan-type InitialRoutes 'both'|'transactional'|'broadcast' * @phpstan-type MessageAttachmentData array{size: int, filename: string, content_id: string|null, content_type: string} - * @phpstan-type MessageData array{id: string, type: MessageType, status: MessageStatus, status_changed_at: string|null, scheduled_at: string|null, tag: string|null, tags: list, from_email: string, from_name: string|null, reply_to: list|null, subject: string|null, to: list|null, cc: list|null, bcc: list|null, attachments: list|null, metadata: array|null, spam_score?: float|int|null, spam_symbols?: list, route_id: string, created_at: string} + * @phpstan-type MessageData array{id: string, type: MessageType, status: MessageStatus, status_changed_at: string|null, scheduled_at: string|null, tag: string|null, tags: list, from_email: string, from_name: string|null, reply_to: list|null, subject: string|null, to: list|null, cc: list|null, bcc: list|null, attachments: list|null, metadata: array|null, spam_score?: float|int|null, spam_symbols?: list, route_id: string, created_at: string, delivery_mode: DeliveryMode, sandbox_result: SandboxResult|null} * @phpstan-type MessageEventData array{message_id: string, event: MessageEventType, tag: string|null, tags: list, metadata: array|null, timestamp: string} * @phpstan-type MessageEventType 'scheduled'|'rescheduled'|'canceled'|'released'|'queued'|'processed'|'suppressed'|'delivered'|'auto_replied'|'soft_bounced'|'hard_bounced'|'spam_complaint'|'failed'|'blocked'|'policy_rejected'|'unsubscribed'|'opened'|'clicked'|'inbound_received'|'inbound_queued'|'inbound_spam_blocked'|'inbound_released'|'inbound_processed'|'inbound_retry' - * @phpstan-type MessageListData array{id: string, type: MessageType, status: MessageStatus, scheduled_at: string|null, spam_score?: float|int|null, from_email: string, from_name: string|null, subject: string|null, to: list|null, cc: list|null, bcc: list|null, reply_to: list|null, tag: string|null, tags: list, status_changed_at: string|null, created_at: string} - * @phpstan-type MessageRecipientData array{email: string, name: string|null} + * @phpstan-type MessageListData array{id: string, type: MessageType, status: MessageStatus, scheduled_at: string|null, spam_score?: float|int|null, from_email: string, from_name: string|null, subject: string|null, to: list|null, cc: list|null, bcc: list|null, reply_to: list|null, tag: string|null, tags: list, status_changed_at: string|null, created_at: string, delivery_mode: DeliveryMode, sandbox_result: SandboxResult|null} + * @phpstan-type MessageRecipientData array{email: string, name: string|null, sandbox_result: SandboxResult|null} * @phpstan-type MessageStatsData array{messages_transactional: int, messages_broadcast: int, messages_inbound: int, deliverability: float|int} * @phpstan-type MessageType 'inbound'|'outbound' * @phpstan-type Plan 'free'|'starter'|'growth'|'pro' * @phpstan-type ProjectAccessScope 'all'|'selected' - * @phpstan-type ProjectData array{id: string, name: string, smtp_enabled: bool, redact_email_content: bool, default_route_id: string|null, token_generated_at: string|null, token_last_used_at: string|null, token_last_used_ip: string|null, routes?: list, routes_count?: int, domains?: list, domains_count?: int, last_28_days?: MessageStatsData|null, created_at: string, updated_at: string} + * @phpstan-type ProjectData array{id: string, name: string, smtp_enabled: bool, redact_email_content: bool, default_route_id: string|null, token_generated_at: string|null, token_last_used_at: string|null, token_last_used_ip: string|null, routes?: list, routes_count?: int, domains?: list, domains_count?: int, last_28_days?: MessageStatsData|null, created_at: string, updated_at: string, delivery_mode: DeliveryMode} * @phpstan-type ProjectListData array{id: string, name: string, smtp_enabled: bool, routes_count: int, domains_count: int, last_28_days: MessageStatsData, created_at: string, updated_at: string} * @phpstan-type RbacConflictCode 'stale_resource'|'owner_protected'|'last_owner'|'built_in_role_immutable'|'custom_role_requires_pro' * @phpstan-type RbacPermission 'team:manage'|'billing:manage'|'security:manage'|'audit:read'|'support:manage'|'members:read'|'members:manage'|'roles:manage'|'team_tokens:read'|'team_tokens:manage'|'team_tokens:rotate'|'team_tokens:revoke'|'projects:create'|'team_suppressions:read'|'team_suppressions:add'|'team_suppressions:remove'|'projects:read'|'projects:manage'|'projects:delete'|'routes:read'|'routes:manage'|'routes:delete'|'domains:read'|'domains:manage'|'domains:delete'|'project_tokens:read'|'project_tokens:manage'|'project_tokens:rotate'|'project_tokens:revoke'|'webhooks:read'|'webhooks:manage'|'webhooks:delete'|'webhooks:rotate_secret'|'stats:read'|'messages:read'|'messages:read_content'|'messages:send'|'suppressions:read'|'suppressions:add'|'suppressions:remove' * @phpstan-type RecordType 'TXT'|'CNAME'|'MX' - * @phpstan-type RouteData array{id: string, project_id: string, slug: string, name: string, route_type: RouteType, is_default: bool, inbound_address?: string|null, inbound_domain?: string|null, inbound_domain_verified_at?: string|null, inbound_spam_threshold?: float|int|null, attachment_delivery?: AttachmentDelivery, settings?: array{disable_hosted_unsubscribe?: bool, track_opens?: bool, track_clicks?: bool, generate_plaintext_fallback?: bool, suppress_auto_responders?: bool, suppress_disposable_recipients?: bool, tls?: TlsPolicy, redact_email_content?: bool, attachment_delivery?: array}|null, project?: ProjectListData, webhooks_count?: int, suppressed_recipients_count?: int, statistics?: list, created_at: string, updated_at: string} + * @phpstan-type RescheduleMessageRequest array{scheduled_at: string} + * @phpstan-type RouteData array{id: string, project_id: string, slug: string, name: string, route_type: RouteType, is_default: bool, inbound_address?: string|null, inbound_mx_hostname?: string, inbound_domain?: string|null, inbound_domain_verified_at?: string|null, inbound_spam_threshold?: float|int|null, attachment_delivery?: AttachmentDelivery, settings?: array{disable_hosted_unsubscribe?: bool, track_opens?: bool, track_clicks?: bool, generate_plaintext_fallback?: bool, suppress_auto_responders?: bool, suppress_disposable_recipients?: bool, tls?: TlsPolicy, redact_email_content?: bool, attachment_delivery?: array}|null, project?: ProjectListData, webhooks_count?: int, suppressed_recipients_count?: int, statistics?: list, created_at: string, updated_at: string} * @phpstan-type RouteListData array{id: string, slug: string, name: string, route_type: RouteType, is_default: bool, webhooks_count: int, suppressed_recipients_count: int, created_at: string, updated_at: string} * @phpstan-type RouteStatisticData array{date: string, sent_count: int, delivered_count: int, opened_count: int, clicked_count: int, hard_bounce_count: int, spam_complaint_count: int, inbound_received_count: int, observed_opened_count?: int|null, human_opened_count?: int|null, privacy_opened_count?: int|null, effective_opened_count: int|null, machine_opened_count: int|null, machine_clicked_count: int|null} * @phpstan-type RouteType 'transactional'|'broadcast'|'inbound' @@ -50,13 +52,14 @@ * @phpstan-type StatsTotalsData array{sent: int, delivered: int, hard_bounced: int, spam_complaints: int, opened: int|null, clicked: int|null, inbound: StatsInboundData, transactional: StatsTypeData|null, broadcast: StatsTypeData|null, observed_opened?: int|null, human_opened?: int|null, privacy_opened?: int|null, effective_opened: int|null, machine_opened: int|null, machine_clicked: int|null} * @phpstan-type StatsTypeData array{sent: int, hard_bounced: int, spam_complaints: int} * @phpstan-type StoreDomainData array{domain: string} - * @phpstan-type StoreProjectData array{name: string, smtp_enabled?: bool, initial_routes?: InitialRoutes, short_token?: bool} + * @phpstan-type StoreProjectData array{name: string, smtp_enabled?: bool, initial_routes?: InitialRoutes, short_token?: bool, delivery_mode?: DeliveryMode} * @phpstan-type StoreRouteData array{name: string, route_type: RouteType, slug?: string|null} - * @phpstan-type StoreSuppressionData array{email?: string|null, emails?: non-empty-list|null, reason: SuppressionReason, scope: SuppressionScope, route_id?: string|null, project_id?: string|null} - * @phpstan-type StoreWebhookData array{route_id: string, name: string, url: string, events: non-empty-list, enabled?: bool|null, include_machine_events?: bool|null} - * @phpstan-type SuppressedRecipientData array{id: string, type: SuppressionType, value: string, reason: SuppressionReason, scope: SuppressionScope, project_id: string|null, route_id: string|null, source_message?: SuppressionSourceMessageData|null, created_at: string, updated_at: string} + * @phpstan-type StoreSuppressionData array{email?: string|null, emails?: non-empty-list|null, reason: SuppressionReason, scope: SuppressionScope, route_id?: string|null, project_id?: string|null, applies_to?: SuppressionAppliesTo|null} + * @phpstan-type StoreWebhookData array{name: string, url: string, events: non-empty-list, enabled?: bool|null, include_machine_events?: bool|null, scope?: WebhookScope|null, project_ids?: list, route_ids?: list, route_id?: string|null, delivery_mode_filter?: WebhookDeliveryModeFilter|null} + * @phpstan-type SuppressedRecipientData array{id: string, type: SuppressionType, value: string, reason: SuppressionReason, scope: SuppressionScope, applies_to: SuppressionAppliesTo, project_id: string|null, route_id: string|null, source_message?: SuppressionSourceMessageData|null, created_at: string} + * @phpstan-type SuppressionAppliesTo 'all'|'broadcast' * @phpstan-type SuppressionReason 'spam_complaint'|'hard_bounce'|'unsubscribe'|'manual' - * @phpstan-type SuppressionScope 'global'|'team'|'project'|'route' + * @phpstan-type SuppressionScope 'team'|'project'|'route' * @phpstan-type SuppressionSourceMessageData array{id: string, available: bool, subject: string|null, created_at: string|null} * @phpstan-type SuppressionType 'email'|'domain'|'extension' * @phpstan-type TeamAddonData array{type: string|null, expires_at: string|null} @@ -68,24 +71,28 @@ * @phpstan-type TeamUsageDetailData array{current_period: TeamUsagePeriodData, historical_usage: list} * @phpstan-type TeamUsagePeriodData array{usage: int, last_incremented_at: string|null, period_start: string, period_end: string} * @phpstan-type UpdateDomainProjectsData array{project_ids: non-empty-list} - * @phpstan-type UpdateProjectData array{name?: string|null, smtp_enabled?: bool|null, redact_email_content?: bool|null, default_route_id?: string|null} + * @phpstan-type UpdateProjectData array{name?: string|null, smtp_enabled?: bool|null, redact_email_content?: bool|null, default_route_id?: string|null, delivery_mode?: DeliveryMode|null} * @phpstan-type UpdateRouteData array{name?: string|null, settings?: UpdateRouteSettingsData|null, inbound_settings?: UpdateRouteInboundSettingsData|null} * @phpstan-type UpdateRouteInboundSettingsData array{inbound_domain?: string|null, inbound_spam_threshold?: float|int|null, attachment_delivery?: AttachmentDelivery|null} * @phpstan-type UpdateRouteSettingsData array{track_opens?: bool|null, track_clicks?: bool|null, generate_plaintext_fallback?: bool|null, suppress_auto_responders?: bool|null, suppress_disposable_recipients?: bool|null, tls?: TlsPolicy|null, disable_hosted_unsubscribe?: bool|null, redact_email_content?: bool|null} * @phpstan-type UpdateTeamData array{name?: string|null} * @phpstan-type UpdateTeamMemberAssignmentData array{role_id: string, project_access: array{scope: ProjectAccessScope, project_ids?: list}} - * @phpstan-type UpdateWebhookData array{name?: string, url?: string, events?: non-empty-list, enabled?: bool, include_machine_events?: bool} - * @phpstan-type WebhookData array{id: string, route_id: string, name: string, url: string, events: non-empty-list, enabled: bool, include_machine_events: bool, secret?: string, last_called_at: string|null, created_at: string, updated_at: string} - * @phpstan-type WebhookDeliveryData array{id: string, webhook_id: string, event_type: WebhookEvent, status: WebhookDeliveryStatus, attempt_number: int, http_status_code: int|null, duration_ms: int|null, payload: non-empty-list, response_body: string|null, response_headers: list|null, error_message: string|null, delivered_at: string|null, timestamp: string} - * @phpstan-type WebhookDeliveryListData array{id: string, webhook_id: string, event_type: WebhookEvent, status: WebhookDeliveryStatus, attempt_number: int, http_status_code: int|null, duration_ms: int|null, delivered_at: string|null, created_at: string} + * @phpstan-type UpdateWebhookData array{name?: string, url?: string, events?: non-empty-list, enabled?: bool, include_machine_events?: bool, scope?: WebhookScope, project_ids?: list, route_ids?: list, route_id?: string|null, delivery_mode_filter?: WebhookDeliveryModeFilter} + * @phpstan-type WebhookData array{id: string, scope: WebhookScope, project_ids: list, route_ids: list, route_id: string|null, name: string, url: string, events: list, enabled: bool, include_machine_events: bool, last_called_at: string|null, created_at: string, updated_at: string, delivery_mode_filter: WebhookDeliveryModeFilter} + * @phpstan-type WebhookDeliveryData array{id: string, webhook_id: string, event_type: WebhookEvent, source_scope: string|null, source_project_id: string|null, source_route_id: string|null, status: WebhookDeliveryStatus, attempt_number: int, http_status_code: int|null, duration_ms: int|null, payload: non-empty-list, response_body: string|null, response_headers: list|null, error_message: string|null, delivered_at: string|null, timestamp: string, sandbox: bool} + * @phpstan-type WebhookDeliveryListData array{id: string, webhook_id: string, event_type: WebhookEvent, source_scope: string|null, source_project_id: string|null, source_route_id: string|null, status: WebhookDeliveryStatus, attempt_number: int, http_status_code: int|null, duration_ms: int|null, delivered_at: string|null, created_at: string} * @phpstan-type WebhookDeliveryStatus 'pending'|'success'|'failed'|'client_error'|'server_error'|'timeout' - * @phpstan-type WebhookEvent 'message.created'|'message.sent'|'message.delivered'|'message.auto_replied'|'message.hard_bounced'|'message.soft_bounced'|'message.spam_complaint'|'message.failed'|'message.suppressed'|'message.unsubscribed'|'message.opened'|'message.clicked'|'message.inbound'|'message.policy_rejected'|'suppression.added'|'suppression.removed'|'webhook.test' - * @phpstan-type WebhookListData array{id: string, route_id: string, name: string, url: string, events: list, enabled: bool, last_called_at: string|null, created_at: string, updated_at: string} + * @phpstan-type WebhookEvent 'message.created'|'message.sent'|'message.delivered'|'message.auto_replied'|'message.hard_bounced'|'message.soft_bounced'|'message.spam_complaint'|'message.failed'|'message.suppressed'|'message.unsubscribed'|'message.opened'|'message.clicked'|'message.inbound'|'message.policy_rejected'|'message.scheduled'|'message.rescheduled'|'message.canceled'|'message.released'|'suppression.added'|'suppression.removed'|'webhook.test' + * @phpstan-type WebhookListData array{id: string, scope: WebhookScope, project_ids: list, route_ids: list, route_id: string|null, name: string, url: string, events: list, enabled: bool, last_called_at: string|null, created_at: string, updated_at: string} + * @phpstan-type WebhookScope 'team'|'project'|'route' + * @phpstan-type WebhookSecretData array{id: string, scope: WebhookScope, project_ids: list, route_ids: list, route_id: string|null, name: string, url: string, events: list, enabled: bool, include_machine_events: bool, secret: string, last_called_at: string|null, created_at: string, updated_at: string, delivery_mode_filter: WebhookDeliveryModeFilter} + * @phpstan-type DeliveryMode 'live'|'sandbox' + * @phpstan-type WebhookDeliveryModeFilter 'live'|'sandbox'|'both' * @phpstan-type StatsQuery StatsRequestData - * @phpstan-type SendMailResponse array{message_id: string|null, status: MessageStatus, scheduled_at?: string} + * @phpstan-type SendMailResponse array{message_id: string|null, status: MessageStatus, scheduled_at: string, sandbox?: bool, sandbox_result?: SandboxResult}|array{message_id: string|null, status: MessageStatus, sandbox?: bool, sandbox_result?: SandboxResult} * @phpstan-type SendBatchMailResponse list - * @phpstan-type RescheduleMessageRequest array{scheduled_at: string} * @phpstan-type RescheduleMessageResponse array{message_id: string, status: MessageStatus|null, scheduled_at: string|null} + * @phpstan-type CancelScheduledMessageResponse array{message_id: string, status: MessageStatus|null, scheduled_at: string|null} * @phpstan-type DomainListResponse array{data: list, path: string|null, per_page: int, next_cursor: string|null, next_page_url: string|null, prev_cursor: string|null, prev_page_url: string|null} * @phpstan-type DomainResponse DomainData * @phpstan-type DeleteDomainResponse array{message: string} @@ -93,8 +100,8 @@ * @phpstan-type VerifyDnsRecordResponse array{message: string} * @phpstan-type UpdateDomainProjectsResponse array{data: DomainData, message: string} * @phpstan-type BlockedFileTypesResponse array{extensions: list, mime_types: list} - * @phpstan-type MessageListResponse array{data: list, links: list, meta: array{path: string|null, per_page: int, next_cursor: string|null, next_cursor_url: string|null, prev_cursor: string|null, prev_cursor_url: string|null}} * @phpstan-type MessageResponse MessageData + * @phpstan-type MessageListResponse array{data: list, links: list, meta: array{path: string|null, per_page: int, next_cursor: string|null, next_cursor_url: string|null, prev_cursor: string|null, prev_cursor_url: string|null}} * @phpstan-type MessageEventsResponse array{data: list, links: list, meta: array{path: string|null, per_page: int, next_cursor: string|null, next_cursor_url: string|null, prev_cursor: string|null, prev_cursor_url: string|null}} * @phpstan-type ProcessInboundMessageResponse array{data: array{message_id: string, status: 'queued', webhook_target_count: int}} * @phpstan-type ProjectListResponse array{data: list, path: string|null, per_page: int, next_cursor: string|null, next_page_url: string|null, prev_cursor: string|null, prev_page_url: string|null} @@ -121,12 +128,12 @@ * @phpstan-type TeamMembersShowResponse TeamMemberData * @phpstan-type TeamMembersAssignmentUpdateResponse TeamMemberData * @phpstan-type WebhookListResponse array{data: list, path: string|null, per_page: int, next_cursor: string|null, next_page_url: string|null, prev_cursor: string|null, prev_page_url: string|null} - * @phpstan-type CreateWebhookResponse array{data: WebhookData, message: string} + * @phpstan-type CreateWebhookResponse array{data: WebhookSecretData, message: string} * @phpstan-type WebhookResponse WebhookData * @phpstan-type UpdateWebhookResponse array{data: WebhookData, message: string} * @phpstan-type DeleteWebhookResponse array{message: string} * @phpstan-type TestWebhookResponse array{message: string, delivery_id: string} - * @phpstan-type RegenerateWebhookSecretResponse array{data: WebhookData, message: string} + * @phpstan-type RegenerateWebhookSecretResponse array{data: WebhookSecretData, message: string} * @phpstan-type WebhookDeliveriesResponse array{data: list, path: string|null, per_page: int, next_cursor: string|null, next_page_url: string|null, prev_cursor: string|null, prev_page_url: string|null} * @phpstan-type WebhookDeliveryResponse WebhookDeliveryData */ diff --git a/tests/Endpoints/EmailEndpointTest.php b/tests/Endpoints/EmailEndpointTest.php index 5ea51d9..d0f85c2 100644 --- a/tests/Endpoints/EmailEndpointTest.php +++ b/tests/Endpoints/EmailEndpointTest.php @@ -25,6 +25,7 @@ ->toBeString() ->toContain('@phpstan-import-type SendMailRequest') ->toContain('@phpstan-import-type SendBatchMailRequest') + ->toContain('@phpstan-import-type SandboxResult') ->not->toContain('@phpstan-type SendResponse'); expect($methodReflection->getReturnType()?->getName())->toBe(SendMailResponse::class); @@ -273,6 +274,34 @@ ->send(); }); +test('it handles a Sandbox result', function () { + $this->httpClient + ->shouldReceive('post') + ->once() + ->with('/v1/send', [ + 'from' => 'sender@example.com', + 'to' => ['recipient@example.com'], + 'subject' => 'Test Subject', + 'sandbox_result' => 'hard_bounced', + ], []) + ->andReturn([ + 'message_id' => '123', + 'status' => 'hard_bounced', + 'sandbox' => true, + 'sandbox_result' => 'hard_bounced', + ]); + + $response = $this->endpoint + ->from('sender@example.com') + ->to('recipient@example.com') + ->subject('Test Subject') + ->sandboxResult('hard_bounced') + ->send(); + + expect($response->sandbox)->toBeTrue() + ->and($response->sandbox_result)->toBe('hard_bounced'); +}); + test('it handles attachment content type', function () { $attachment = [ 'filename' => 'invite.ics', diff --git a/tests/SdkCoverageTest.php b/tests/SdkCoverageTest.php index 640397e..af15614 100644 --- a/tests/SdkCoverageTest.php +++ b/tests/SdkCoverageTest.php @@ -206,3 +206,33 @@ ->toContain('spam_score?: float|int|null') ->toContain('scope: SuppressionScope'); }); + +test('generated php api types preserve scheduled message and cursor aliases', function () { + $typesSource = file_get_contents(__DIR__.'/../src/Types/ApiTypes.php'); + + expect($typesSource) + ->toContain('@phpstan-type CursorPaginator array{') + ->toContain('@phpstan-type RescheduleMessageResponse array{') + ->toContain('@phpstan-type CancelScheduledMessageResponse array{') + ->toContain('@phpstan-type ProcessInboundMessageResponse array{'); +}); + +test('generated php api types include Sandbox contracts', function () { + $typesSource = file_get_contents(__DIR__.'/../src/Types/ApiTypes.php'); + $sendResponseSource = file_get_contents(__DIR__.'/../src/Responses/SendMailResponse.php'); + $webhookDeliverySource = file_get_contents(__DIR__.'/../src/Objects/WebhookDeliveryData.php'); + + expect($typesSource) + ->toContain("@phpstan-type DeliveryMode 'live'|'sandbox'") + ->toContain('@phpstan-type SandboxResult ') + ->toContain('sandbox_result?: SandboxResult') + ->toContain('delivery_mode: DeliveryMode') + ->toContain('delivery_mode_filter: WebhookDeliveryModeFilter') + ->toContain('sandbox: bool'); + + expect($sendResponseSource) + ->toContain('$sandbox') + ->toContain('$sandbox_result'); + + expect($webhookDeliverySource)->toContain('@property bool $sandbox'); +});