diff --git a/apps/docs/api-reference/openapi.json b/apps/docs/api-reference/openapi.json index de775bf8..308164e1 100644 --- a/apps/docs/api-reference/openapi.json +++ b/apps/docs/api-reference/openapi.json @@ -626,10 +626,10 @@ { "schema": { "type": "number", - "nullable": false, + "nullable": true, "example": 1 }, - "required": true, + "required": false, "name": "id", "in": "path" } @@ -643,152 +643,55 @@ "type": "object", "properties": { "id": { - "type": "number", - "description": "The ID of the domain", - "example": 1 - }, - "name": { - "type": "string", - "description": "The name of the domain", - "example": "example.com" - }, - "teamId": { - "type": "number", - "description": "The ID of the team", - "example": 1 - }, - "status": { - "type": "string", - "enum": [ - "NOT_STARTED", - "PENDING", - "SUCCESS", - "FAILED", - "TEMPORARY_FAILURE" - ] - }, - "region": { - "type": "string", - "default": "us-east-1" - }, - "clickTracking": { - "type": "boolean", - "default": false + "type": "number" }, - "openTracking": { - "type": "boolean", - "default": false + "success": { + "type": "boolean" }, - "publicKey": { + "message": { "type": "string" - }, - "dkimStatus": { - "type": "string", - "nullable": true - }, - "spfDetails": { - "type": "string", - "nullable": true - }, - "createdAt": { + } + }, + "required": [ + "id", + "success", + "message" + ] + } + } + } + }, + "403": { + "description": "Forbidden - API key doesn't have access", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "error": { "type": "string" - }, - "updatedAt": { + } + }, + "required": [ + "error" + ] + } + } + } + }, + "404": { + "description": "Domain not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "error": { "type": "string" - }, - "dmarcAdded": { - "type": "boolean", - "default": false - }, - "isVerifying": { - "type": "boolean", - "default": false - }, - "errorMessage": { - "type": "string", - "nullable": true - }, - "subdomain": { - "type": "string", - "nullable": true - }, - "verificationError": { - "type": "string", - "nullable": true - }, - "lastCheckedTime": { - "type": "string", - "nullable": true - }, - "dnsRecords": { - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "MX", - "TXT" - ], - "description": "DNS record type", - "example": "TXT" - }, - "name": { - "type": "string", - "description": "DNS record name", - "example": "mail" - }, - "value": { - "type": "string", - "description": "DNS record value", - "example": "v=spf1 include:amazonses.com ~all" - }, - "ttl": { - "type": "string", - "description": "DNS record TTL", - "example": "Auto" - }, - "priority": { - "type": "string", - "nullable": true, - "description": "DNS record priority", - "example": "10" - }, - "status": { - "type": "string", - "enum": [ - "NOT_STARTED", - "PENDING", - "SUCCESS", - "FAILED", - "TEMPORARY_FAILURE" - ] - }, - "recommended": { - "type": "boolean", - "description": "Whether the record is recommended" - } - }, - "required": [ - "type", - "name", - "value", - "ttl", - "status" - ] - } } }, "required": [ - "id", - "name", - "teamId", - "status", - "publicKey", - "createdAt", - "updatedAt", - "dnsRecords" + "error" ] } } diff --git a/apps/docs/docs.json b/apps/docs/docs.json index 3b18c53a..c98135a9 100644 --- a/apps/docs/docs.json +++ b/apps/docs/docs.json @@ -34,23 +34,15 @@ }, { "group": "Self Hosting", - "pages": [ - "self-hosting/overview", - "self-hosting/railway" - ] + "pages": ["self-hosting/overview", "self-hosting/railway"] }, { "group": "Guides", - "pages": [ - "guides/use-with-react-email" - ] + "pages": ["guides/use-with-react-email"] }, { "group": "Community SDKs", - "pages": [ - "community-sdk/python", - "community-sdk/go" - ] + "pages": ["community-sdk/python", "community-sdk/go"] } ] }, @@ -59,9 +51,7 @@ "groups": [ { "group": "API Reference", - "pages": [ - "api-reference/introduction" - ] + "pages": ["api-reference/introduction"] }, { "group": "Emails", @@ -91,7 +81,8 @@ "api-reference/domains/get-domain", "api-reference/domains/list-domains", "api-reference/domains/create-domain", - "api-reference/domains/verify-domain" + "api-reference/domains/verify-domain", + "api-reference/domains/delete-domain" ] } ] @@ -147,12 +138,6 @@ } }, "contextual": { - "options": [ - "copy", - "view", - "chatgpt", - "claude", - "perplexity" - ] + "options": ["copy", "view", "chatgpt", "claude", "perplexity"] } -} \ No newline at end of file +} diff --git a/apps/web/src/server/public-api/api/domains/delete-domain.ts b/apps/web/src/server/public-api/api/domains/delete-domain.ts index 10397f9e..d0a5d862 100644 --- a/apps/web/src/server/public-api/api/domains/delete-domain.ts +++ b/apps/web/src/server/public-api/api/domains/delete-domain.ts @@ -5,83 +5,90 @@ import { UnsendApiError } from "../../api-error"; import { deleteDomain as deleteDomainService } from "~/server/service/domain-service"; const route = createRoute({ - method: "delete", - path: "/v1/domains/{id}", - request: { - params: z.object({ - id: z.coerce.number().openapi({ - param: { - name: "id", - in: "path", - }, - example: 1, - }), - }), - }, - responses: { - 200: { - content: { - "application/json": { - schema: z.object({ - success: z.boolean(), - message: z.string(), - }), - }, - }, - description: "Domain deleted successfully", + method: "delete", + path: "/v1/domains/{id}", + request: { + params: z.object({ + id: z.coerce.number().openapi({ + param: { + name: "id", + in: "path", }, - 403: { - "application/json": { - schema: z.object({ - error: z.string(), - }), - }, - description: "Forbidden - API key doesn't have access", + example: 1, + }), + }), + }, + responses: { + 200: { + content: { + "application/json": { + schema: z.object({ + id: z.number(), + success: z.boolean(), + message: z.string(), + }), }, - 404: { - content: { - "application/json": { - schema: z.object({ - error: z.string(), - }), - }, - }, - description: "Domain not found", + }, + description: "Domain deleted successfully", + }, + 403: { + content: { + "application/json": { + schema: z.object({ + error: z.string(), + }), }, - } -}) + }, + description: "Forbidden - API key doesn't have access", + }, + 404: { + content: { + "application/json": { + schema: z.object({ + error: z.string(), + }), + }, + }, + description: "Domain not found", + }, + }, +}); function deleteDomain(app: PublicAPIApp) { - app.openapi(route, async (c) => { - const team = c.var.team; - const domainId = c.req.valid("param").id; + app.openapi(route, async (c) => { + const team = c.var.team; + const domainId = c.req.valid("param").id; - // Enforce API key domain restriction - if (team.apiKey.domainId && team.apiKey.domainId !== domainId) { - throw new UnsendApiError({ - code: "FORBIDDEN", - message: "API key doesn't have access to this domain", - }); - } + // Enforce API key domain restriction + if (team.apiKey.domainId && team.apiKey.domainId !== domainId) { + throw new UnsendApiError({ + code: "FORBIDDEN", + message: "API key doesn't have access to this domain", + }); + } - const domain = await db.domain.findFirst({ - where: { - id: domainId, - teamId: team.id - }, - }); + const domain = await db.domain.findFirst({ + where: { + id: domainId, + teamId: team.id, + }, + }); - if (!domain) { - throw new UnsendApiError({ - code: "NOT_FOUND", - message: "Domain not found", - }); - } + if (!domain) { + throw new UnsendApiError({ + code: "NOT_FOUND", + message: "Domain not found", + }); + } - const deletedDomain = await deleteDomainService(domainId); + const deletedDomain = await deleteDomainService(domainId); - return c.json(deletedDomain); + return c.json({ + id: deletedDomain.id, + success: true, + message: "Domain deleted successfully", }); + }); } -export default deleteDomain; \ No newline at end of file +export default deleteDomain; diff --git a/packages/python-sdk/pyproject.toml b/packages/python-sdk/pyproject.toml index 155d7fe5..d9c72cd3 100644 --- a/packages/python-sdk/pyproject.toml +++ b/packages/python-sdk/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "usesend" -version = "0.2.5" +version = "0.2.6" description = "Python SDK for the UseSend API" authors = ["UseSend"] license = "MIT" diff --git a/packages/python-sdk/usesend/domains.py b/packages/python-sdk/usesend/domains.py index e53b5438..73fcc8ac 100644 --- a/packages/python-sdk/usesend/domains.py +++ b/packages/python-sdk/usesend/domains.py @@ -8,6 +8,7 @@ Domain, DomainCreate, DomainCreateResponse, + DomainDeleteResponse, DomainVerifyResponse, ) @@ -34,7 +35,7 @@ def get(self, domain_id: int) -> Tuple[Optional[Domain], Optional[APIError]]: data, err = self.usesend.get(f"/domains/{domain_id}") return (data, err) # type: ignore[return-value] - def delete(self, domain_id: int) -> Tuple[Optional[Domain], Optional[APIError]]: + def delete(self, domain_id: int) -> Tuple[Optional[DomainDeleteResponse], Optional[APIError]]: data, err = self.usesend.delete(f"/domains/{domain_id}") return (data, err) # type: ignore[return-value] diff --git a/packages/python-sdk/usesend/types.py b/packages/python-sdk/usesend/types.py index 0cbeae5b..d9669060 100644 --- a/packages/python-sdk/usesend/types.py +++ b/packages/python-sdk/usesend/types.py @@ -94,6 +94,11 @@ class DomainVerifyResponse(TypedDict): message: str +class DomainDeleteResponse(TypedDict): + id: int + success: bool + message: str + # --------------------------------------------------------------------------- # Emails # --------------------------------------------------------------------------- diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 944f9769..bd87bd64 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "usesend-js", - "version": "1.5.4", + "version": "1.5.5", "description": "", "main": "./dist/index.js", "module": "./dist/index.mjs", diff --git a/packages/sdk/types/schema.d.ts b/packages/sdk/types/schema.d.ts index cee724db..7472a62f 100644 --- a/packages/sdk/types/schema.d.ts +++ b/packages/sdk/types/schema.d.ts @@ -369,7 +369,7 @@ export interface paths { query?: never; header?: never; path: { - id: number; + id: number | null; }; cookie?: never; }; @@ -382,78 +382,13 @@ export interface paths { }; content: { "application/json": { - /** - * @description The ID of the domain - * @example 1 - */ id: number; - /** - * @description The name of the domain - * @example example.com - */ - name: string; - /** - * @description The ID of the team - * @example 1 - */ - teamId: number; - /** @enum {string} */ - status: "NOT_STARTED" | "PENDING" | "SUCCESS" | "FAILED" | "TEMPORARY_FAILURE"; - /** @default us-east-1 */ - region: string; - /** @default false */ - clickTracking: boolean; - /** @default false */ - openTracking: boolean; - publicKey: string; - dkimStatus?: string | null; - spfDetails?: string | null; - createdAt: string; - updatedAt: string; - /** @default false */ - dmarcAdded: boolean; - /** @default false */ - isVerifying: boolean; - errorMessage?: string | null; - subdomain?: string | null; - verificationError?: string | null; - lastCheckedTime?: string | null; - dnsRecords: { - /** - * @description DNS record type - * @example TXT - * @enum {string} - */ - type: "MX" | "TXT"; - /** - * @description DNS record name - * @example mail - */ - name: string; - /** - * @description DNS record value - * @example v=spf1 include:amazonses.com ~all - */ - value: string; - /** - * @description DNS record TTL - * @example Auto - */ - ttl: string; - /** - * @description DNS record priority - * @example 10 - */ - priority?: string | null; - /** @enum {string} */ - status: "NOT_STARTED" | "PENDING" | "SUCCESS" | "FAILED" | "TEMPORARY_FAILURE"; - /** @description Whether the record is recommended */ - recommended?: boolean; - }[]; + success: boolean; + message: string; }; }; }; - /** @description Forbidden - API key doesn't have access to this domain */ + /** @description Forbidden - API key doesn't have access */ 403: { headers: { [name: string]: unknown;