diff --git a/openapi.json b/openapi.json index 1e2a319..eeac855 100644 --- a/openapi.json +++ b/openapi.json @@ -114,6 +114,1989 @@ }, "401": { "description": "Authentication failed (bad API key, invalid OAuth token, incorrect scopes, etc.)" + }, + "campaignResponse": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "data", + "meta" + ], + "properties": { + "data": { + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "campaign" + ] + }, + "attributes": { + "$ref": "#/components/schemas/campaign" + }, + "relationships": { + "properties": { + "benefits": { + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "benefit" + ] + } + }, + "required": [ + "id", + "type" + ] + } + } + } + }, + "creator": { + "required": [ + "data" + ], + "properties": { + "data": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "user" + ] + } + }, + "required": [ + "id", + "type" + ] + }, + "links": { + "properties": { + "related": { + "type": "string", + "format": "uri" + } + } + } + } + }, + "goals": { + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "goal" + ] + } + }, + "required": [ + "id", + "type" + ] + } + } + } + }, + "tiers": { + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "tier" + ] + } + }, + "required": [ + "id", + "type" + ] + } + } + } + } + } + } + } + }, + "included": { + "type": "array", + "items": { + "oneOf": [ + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "benefit" + ] + }, + "attributes": { + "$ref": "#/components/schemas/benefit" + } + } + }, + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "user" + ] + }, + "attributes": { + "$ref": "#/components/schemas/user" + } + } + }, + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "goal" + ] + }, + "attributes": { + "$ref": "#/components/schemas/goal" + } + } + }, + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "tier" + ] + }, + "attributes": { + "$ref": "#/components/schemas/tier" + } + } + } + ] + } + }, + "links": { + "properties": { + "self": { + "type": "string" + } + } + } + } + } + } + } + }, + "campaignsResponse": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "data", + "links" + ], + "properties": { + "data": { + "type": "array", + "items": { + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "campaign" + ] + }, + "attributes": { + "$ref": "#/components/schemas/campaign" + }, + "relationships": { + "properties": { + "benefits": { + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "benefit" + ] + } + }, + "required": [ + "id", + "type" + ] + } + } + } + }, + "creator": { + "required": [ + "data" + ], + "properties": { + "data": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "user" + ] + } + }, + "required": [ + "id", + "type" + ] + }, + "links": { + "properties": { + "related": { + "type": "string", + "format": "uri" + } + } + } + } + }, + "goals": { + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "goal" + ] + } + }, + "required": [ + "id", + "type" + ] + } + } + } + }, + "tiers": { + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "tier" + ] + } + }, + "required": [ + "id", + "type" + ] + } + } + } + } + } + } + } + } + }, + "included": { + "type": "array", + "items": { + "oneOf": [ + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "benefit" + ] + }, + "attributes": { + "$ref": "#/components/schemas/benefit" + } + } + }, + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "user" + ] + }, + "attributes": { + "$ref": "#/components/schemas/user" + } + } + }, + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "goal" + ] + }, + "attributes": { + "$ref": "#/components/schemas/goal" + } + } + }, + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "tier" + ] + }, + "attributes": { + "$ref": "#/components/schemas/tier" + } + } + } + ] + } + }, + "meta": { + "properties": { + "total": { + "type": "number" + }, + "pagination": { + "properties": { + "cursors": { + "properties": { + "next": { + "type": [ + "string", + "null" + ] + } + } + } + } + } + } + } + } + } + } + } + }, + "userResponse": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "data", + "meta" + ], + "properties": { + "data": { + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "user" + ] + }, + "attributes": { + "$ref": "#/components/schemas/user" + }, + "relationships": { + "properties": { + "campaign": { + "required": [ + "data" + ], + "properties": { + "data": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "campaign" + ] + } + }, + "required": [ + "id", + "type" + ] + }, + "links": { + "properties": { + "related": { + "type": "string", + "format": "uri" + } + } + } + } + }, + "memberships": { + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "member" + ] + } + }, + "required": [ + "id", + "type" + ] + } + } + } + } + } + } + } + }, + "included": { + "type": "array", + "items": { + "oneOf": [ + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "campaign" + ] + }, + "attributes": { + "$ref": "#/components/schemas/campaign" + } + } + }, + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "member" + ] + }, + "attributes": { + "$ref": "#/components/schemas/member" + } + } + } + ] + } + }, + "links": { + "properties": { + "self": { + "type": "string" + } + } + } + } + } + } + } + }, + "membersResponse": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "data", + "links" + ], + "properties": { + "data": { + "type": "array", + "items": { + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "member" + ] + }, + "attributes": { + "$ref": "#/components/schemas/member" + }, + "relationships": { + "properties": { + "address": { + "required": [ + "data" + ], + "properties": { + "data": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "address" + ] + } + }, + "required": [ + "id", + "type" + ] + }, + "links": { + "properties": { + "related": { + "type": "string", + "format": "uri" + } + } + } + } + }, + "campaign": { + "required": [ + "data" + ], + "properties": { + "data": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "campaign" + ] + } + }, + "required": [ + "id", + "type" + ] + }, + "links": { + "properties": { + "related": { + "type": "string", + "format": "uri" + } + } + } + } + }, + "currently_entitled_tiers": { + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "tier" + ] + } + }, + "required": [ + "id", + "type" + ] + } + } + } + }, + "pledge_history": { + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "pledge-event" + ] + } + }, + "required": [ + "id", + "type" + ] + } + } + } + }, + "user": { + "required": [ + "data" + ], + "properties": { + "data": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "user" + ] + } + }, + "required": [ + "id", + "type" + ] + }, + "links": { + "properties": { + "related": { + "type": "string", + "format": "uri" + } + } + } + } + } + } + } + } + } + }, + "included": { + "type": "array", + "items": { + "oneOf": [ + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "address" + ] + }, + "attributes": { + "$ref": "#/components/schemas/address" + } + } + }, + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "campaign" + ] + }, + "attributes": { + "$ref": "#/components/schemas/campaign" + } + } + }, + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "tier" + ] + }, + "attributes": { + "$ref": "#/components/schemas/tier" + } + } + }, + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "pledge-event" + ] + }, + "attributes": { + "$ref": "#/components/schemas/pledge-event" + } + } + }, + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "user" + ] + }, + "attributes": { + "$ref": "#/components/schemas/user" + } + } + } + ] + } + }, + "meta": { + "properties": { + "total": { + "type": "number" + }, + "pagination": { + "properties": { + "cursors": { + "properties": { + "next": { + "type": [ + "string", + "null" + ] + } + } + } + } + } + } + } + } + } + } + } + }, + "memberResponse": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "data", + "meta" + ], + "properties": { + "data": { + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "member" + ] + }, + "attributes": { + "$ref": "#/components/schemas/member" + }, + "relationships": { + "properties": { + "address": { + "required": [ + "data" + ], + "properties": { + "data": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "address" + ] + } + }, + "required": [ + "id", + "type" + ] + }, + "links": { + "properties": { + "related": { + "type": "string", + "format": "uri" + } + } + } + } + }, + "campaign": { + "required": [ + "data" + ], + "properties": { + "data": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "campaign" + ] + } + }, + "required": [ + "id", + "type" + ] + }, + "links": { + "properties": { + "related": { + "type": "string", + "format": "uri" + } + } + } + } + }, + "currently_entitled_tiers": { + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "tier" + ] + } + }, + "required": [ + "id", + "type" + ] + } + } + } + }, + "pledge_history": { + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "pledge-event" + ] + } + }, + "required": [ + "id", + "type" + ] + } + } + } + }, + "user": { + "required": [ + "data" + ], + "properties": { + "data": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "user" + ] + } + }, + "required": [ + "id", + "type" + ] + }, + "links": { + "properties": { + "related": { + "type": "string", + "format": "uri" + } + } + } + } + } + } + } + } + }, + "included": { + "type": "array", + "items": { + "oneOf": [ + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "address" + ] + }, + "attributes": { + "$ref": "#/components/schemas/address" + } + } + }, + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "campaign" + ] + }, + "attributes": { + "$ref": "#/components/schemas/campaign" + } + } + }, + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "tier" + ] + }, + "attributes": { + "$ref": "#/components/schemas/tier" + } + } + }, + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "pledge-event" + ] + }, + "attributes": { + "$ref": "#/components/schemas/pledge-event" + } + } + }, + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "user" + ] + }, + "attributes": { + "$ref": "#/components/schemas/user" + } + } + } + ] + } + }, + "links": { + "properties": { + "self": { + "type": "string" + } + } + } + } + } + } + } + }, + "postsResponse": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "data", + "links" + ], + "properties": { + "data": { + "type": "array", + "items": { + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "post" + ] + }, + "attributes": { + "$ref": "#/components/schemas/post" + }, + "relationships": { + "properties": { + "user": { + "required": [ + "data" + ], + "properties": { + "data": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "user" + ] + } + }, + "required": [ + "id", + "type" + ] + }, + "links": { + "properties": { + "related": { + "type": "string", + "format": "uri" + } + } + } + } + }, + "campaign": { + "required": [ + "data" + ], + "properties": { + "data": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "campaign" + ] + } + }, + "required": [ + "id", + "type" + ] + }, + "links": { + "properties": { + "related": { + "type": "string", + "format": "uri" + } + } + } + } + } + } + } + } + } + }, + "included": { + "type": "array", + "items": { + "oneOf": [ + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "user" + ] + }, + "attributes": { + "$ref": "#/components/schemas/user" + } + } + }, + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "campaign" + ] + }, + "attributes": { + "$ref": "#/components/schemas/campaign" + } + } + } + ] + } + }, + "meta": { + "properties": { + "total": { + "type": "number" + }, + "pagination": { + "properties": { + "cursors": { + "properties": { + "next": { + "type": [ + "string", + "null" + ] + } + } + } + } + } + } + } + } + } + } + } + }, + "postResponse": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "data", + "meta" + ], + "properties": { + "data": { + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "post" + ] + }, + "attributes": { + "$ref": "#/components/schemas/post" + }, + "relationships": { + "properties": { + "user": { + "required": [ + "data" + ], + "properties": { + "data": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "user" + ] + } + }, + "required": [ + "id", + "type" + ] + }, + "links": { + "properties": { + "related": { + "type": "string", + "format": "uri" + } + } + } + } + }, + "campaign": { + "required": [ + "data" + ], + "properties": { + "data": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "campaign" + ] + } + }, + "required": [ + "id", + "type" + ] + }, + "links": { + "properties": { + "related": { + "type": "string", + "format": "uri" + } + } + } + } + } + } + } + } + }, + "included": { + "type": "array", + "items": { + "oneOf": [ + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "user" + ] + }, + "attributes": { + "$ref": "#/components/schemas/user" + } + } + }, + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "campaign" + ] + }, + "attributes": { + "$ref": "#/components/schemas/campaign" + } + } + } + ] + } + }, + "links": { + "properties": { + "self": { + "type": "string" + } + } + } + } + } + } + } + }, + "webhookResponse": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "data", + "meta" + ], + "properties": { + "data": { + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "webhook" + ] + }, + "attributes": { + "$ref": "#/components/schemas/webhook" + }, + "relationships": { + "properties": { + "campaign": { + "required": [ + "data" + ], + "properties": { + "data": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "campaign" + ] + } + }, + "required": [ + "id", + "type" + ] + }, + "links": { + "properties": { + "related": { + "type": "string", + "format": "uri" + } + } + } + } + }, + "client": { + "required": [ + "data" + ], + "properties": { + "data": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "client" + ] + } + }, + "required": [ + "id", + "type" + ] + }, + "links": { + "properties": { + "related": { + "type": "string", + "format": "uri" + } + } + } + } + } + } + } + } + }, + "included": { + "type": "array", + "items": { + "oneOf": [ + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "campaign" + ] + }, + "attributes": { + "$ref": "#/components/schemas/campaign" + } + } + }, + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "client" + ] + }, + "attributes": { + "$ref": "#/components/schemas/client" + } + } + } + ] + } + }, + "links": { + "properties": { + "self": { + "type": "string" + } + } + } + } + } + } + } + }, + "webhooksResponse": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "data", + "links" + ], + "properties": { + "data": { + "type": "array", + "items": { + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "webhook" + ] + }, + "attributes": { + "$ref": "#/components/schemas/webhook" + }, + "relationships": { + "properties": { + "campaign": { + "required": [ + "data" + ], + "properties": { + "data": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "campaign" + ] + } + }, + "required": [ + "id", + "type" + ] + }, + "links": { + "properties": { + "related": { + "type": "string", + "format": "uri" + } + } + } + } + }, + "client": { + "required": [ + "data" + ], + "properties": { + "data": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "client" + ] + } + }, + "required": [ + "id", + "type" + ] + }, + "links": { + "properties": { + "related": { + "type": "string", + "format": "uri" + } + } + } + } + } + } + } + } + } + }, + "included": { + "type": "array", + "items": { + "oneOf": [ + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "campaign" + ] + }, + "attributes": { + "$ref": "#/components/schemas/campaign" + } + } + }, + { + "required": [ + "attributes", + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "client" + ] + }, + "attributes": { + "$ref": "#/components/schemas/client" + } + } + } + ] + } + }, + "meta": { + "properties": { + "total": { + "type": "number" + }, + "pagination": { + "properties": { + "cursors": { + "properties": { + "next": { + "type": [ + "string", + "null" + ] + } + } + } + } + } + } + } + } + } + } + } } }, "securitySchemes": { @@ -678,7 +2661,10 @@ }, "full_name": { "type": "string", - "description": "Full name of the member user" + "description": "Full name of the member user", + "examples": [ + "John Doe" + ] }, "is_follower": { "type": "boolean", @@ -738,7 +2724,10 @@ }, "pledge_cadence": { "type": "number", - "description": "Number of months between charges\n\nNote: this will be `1` if Campaign.is_monthly is `true`" + "description": "Number of months between charges\n\nNote: this will be `1` if Campaign.is_monthly is `true`", + "examples": [ + "1" + ] }, "pledge_relationship_start": { "type": [ @@ -750,7 +2739,10 @@ }, "will_pay_amount_cents": { "type": "number", - "description": "The amount in cents the user will pay at the next pay cycle" + "description": "The amount in cents the user will pay at the next pay cycle", + "examples": [ + "500" + ] } } }, @@ -1212,7 +3204,7 @@ ], "responses": { "200": { - "$ref": "#/components/responses/200" + "$ref": "#/components/responses/campaignResponse" }, "400": { "$ref": "#/components/responses/400" @@ -1245,7 +3237,7 @@ ], "responses": { "200": { - "$ref": "#/components/responses/200" + "$ref": "#/components/responses/campaignsResponse" }, "400": { "$ref": "#/components/responses/400" @@ -1278,7 +3270,7 @@ ], "responses": { "200": { - "$ref": "#/components/responses/200" + "$ref": "#/components/responses/userResponse" }, "400": { "$ref": "#/components/responses/400" @@ -1314,7 +3306,7 @@ ], "responses": { "200": { - "$ref": "#/components/responses/200" + "$ref": "#/components/responses/membersResponse" }, "400": { "$ref": "#/components/responses/400" @@ -1350,7 +3342,7 @@ ], "responses": { "200": { - "$ref": "#/components/responses/200" + "$ref": "#/components/responses/memberResponse" }, "400": { "$ref": "#/components/responses/400" @@ -1386,7 +3378,7 @@ ], "responses": { "200": { - "$ref": "#/components/responses/200" + "$ref": "#/components/responses/postsResponse" }, "400": { "$ref": "#/components/responses/400" @@ -1422,7 +3414,7 @@ ], "responses": { "200": { - "$ref": "#/components/responses/200" + "$ref": "#/components/responses/postResponse" }, "400": { "$ref": "#/components/responses/400" @@ -1511,7 +3503,7 @@ ], "responses": { "200": { - "$ref": "#/components/responses/200" + "$ref": "#/components/responses/webhookResponse" }, "400": { "$ref": "#/components/responses/400" @@ -1544,7 +3536,7 @@ ], "responses": { "200": { - "$ref": "#/components/responses/200" + "$ref": "#/components/responses/webhooksResponse" }, "400": { "$ref": "#/components/responses/400" @@ -1647,7 +3639,7 @@ ], "responses": { "200": { - "$ref": "#/components/responses/200" + "$ref": "#/components/responses/webhooksResponse" }, "400": { "$ref": "#/components/responses/400" diff --git a/src/schemas/v2/api/components/parameters.ts b/src/schemas/v2/api/components/parameters.ts index 08362fb..b4692e1 100644 --- a/src/schemas/v2/api/components/parameters.ts +++ b/src/schemas/v2/api/components/parameters.ts @@ -1,3 +1,29 @@ +import { SchemaRelationshipKeys, Type } from '../../../../v2' + +// eslint-disable-next-line jsdoc/require-jsdoc +export function getResourceParameters (resource: Type) { + const relationshipKeys = SchemaRelationshipKeys as Record + + const includes = relationshipKeys[resource].map(({ includeKey }) => includeKey) + + const resources = includes.map(includeKey => { + // Throw when includes field is not found + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return relationshipKeys[resource].find(key => key.includeKey === includeKey)!.resourceKey + }) + + return { + includes, + resources, + includesKeys: relationshipKeys[resource], + } +} + export default { id: { name: 'id', diff --git a/src/schemas/v2/api/components/responses.ts b/src/schemas/v2/api/components/responses.ts index 68701d4..ea7bb94 100644 --- a/src/schemas/v2/api/components/responses.ts +++ b/src/schemas/v2/api/components/responses.ts @@ -1,3 +1,85 @@ +import { Type } from '../../../../v2' +import { getResourceParameters } from './parameters' + +// eslint-disable-next-line jsdoc/require-jsdoc +function createBaseItem (resource: Type) { + return { + id: { + type: 'string', + }, + type: { + type: 'string', + enum: [resource], + }, + } +} + +// eslint-disable-next-line jsdoc/require-jsdoc +export function createResponse (resource: Type, array?: boolean) { + const { includesKeys, resources } = getResourceParameters(resource) + + const data = { + required: ['id', 'type'], + properties: { + ...createBaseItem(resource), + attributes: { + $ref: `#/components/schemas/${resource}`, + }, + relationships: { + properties: includesKeys.reduce((props, key) => ({ + ...props, + [key.includeKey]: { + required: ['data'], + properties: { + data: key.isArray + ? { type: 'array', items: { properties: createBaseItem(key.resourceKey), required: ['id', 'type'] } } + : { properties: createBaseItem(key.resourceKey), required: ['id', 'type'] }, + ...(!key.isArray ? { links: { properties: { related: { type: 'string', format: 'uri' } } } } : {}), + } + } + }), {}), + }, + } + } + + return { + type: 'object', + required: ['data', array ? 'links' : 'meta'], + properties: { + data: array ? { type: 'array', items: data } : data, + included: { + type: 'array', + items: { + oneOf: resources.map(resource => ({ + required: ['attributes', 'type', 'id'], + properties: { + ...createBaseItem(resource), + attributes: { + $ref: `#/components/schemas/${resource}`, + }, + } + })), + } + }, + ...(array + ? { meta: { properties: { + total: { type: 'number' }, + pagination: { + properties: { + cursors: { + properties: { + next: { type: ['string', 'null'] } + } + } + } + } + } } } + : { links: { properties: { self: { type: 'string' } } } } + ) + } + } +} + export default { '200': { description: 'OK', diff --git a/src/schemas/v2/api/components/schemas.ts b/src/schemas/v2/api/components/schemas.ts index 8c1e709..f145a1e 100644 --- a/src/schemas/v2/api/components/schemas.ts +++ b/src/schemas/v2/api/components/schemas.ts @@ -32,6 +32,9 @@ function createResourceSchemas (options: ResourceSchemaOption const nullable = property.getType().isNullable() const baseType = type.getBaseTypeOfLiteralType().getText() const format = formatMap?.[property.getName()] + const examples = property.getJsDocs().at(0)?.getTags() + .filter(tag => tag.getTagName() === 'example') + .map(tag => tag.getCommentText()) return { ...properties, @@ -52,6 +55,7 @@ function createResourceSchemas (options: ResourceSchemaOption ), ...(format != undefined ? { format } : {}), description: getJsDocDescription(property), + ...(examples != undefined && examples.length ? { examples: examples } : {}), } } }, {}) diff --git a/src/schemas/v2/api/paths/index.ts b/src/schemas/v2/api/paths/index.ts index 91a718c..47046e5 100644 --- a/src/schemas/v2/api/paths/index.ts +++ b/src/schemas/v2/api/paths/index.ts @@ -1,3 +1,4 @@ +import { Route } from '../types/paths' import campaign from './campaign' import identity from './identity' import member from './member' @@ -10,4 +11,4 @@ export default [ ...member, ...post, ...webhook, -] +] as Route[] diff --git a/src/schemas/v2/resources/member.ts b/src/schemas/v2/resources/member.ts index 91ca427..3967617 100644 --- a/src/schemas/v2/resources/member.ts +++ b/src/schemas/v2/resources/member.ts @@ -19,6 +19,7 @@ export interface Member { /** * Full name of the member user + * @example John Doe */ full_name: string @@ -80,6 +81,7 @@ export interface Member { * Number of months between charges * * Note: this will be `1` if Campaign.is_monthly is `true` + * @example 1 */ pledge_cadence: number @@ -91,6 +93,7 @@ export interface Member { /** * The amount in cents the user will pay at the next pay cycle + * @example 500 */ will_pay_amount_cents: number } \ No newline at end of file diff --git a/src/schemas/v2/scripts/api.ts b/src/schemas/v2/scripts/api.ts index a7ca5b7..8dbf4b1 100644 --- a/src/schemas/v2/scripts/api.ts +++ b/src/schemas/v2/scripts/api.ts @@ -1,19 +1,12 @@ import { writeFile } from 'fs/promises' -// import { SchemaRelationshipKeys, Type } from '../../../v2' +import { RequestMethod } from '../../../v2' import details from '../api/details' import routes from '../api/paths/' import * as components from '../api/components/' +import { createResponse } from '../api/components/responses' import type { Route } from '../api/types/paths' -import { RequestMethod } from '../../../v2' - -// const relationshipKeys = SchemaRelationshipKeys as Record interface SchemaOptions { fileName: string @@ -31,12 +24,6 @@ function createPaths (options: PathSchemaOptions) { ...obj, [options.base + path.route(`{${path.params?.id ?? 'id'}}`)]: path.methods.reduce((options, data) => { const { id, method, body } = data - // const includes = relationshipKeys[path.resource].map(key => key.includeKey) - // const resources = includes.map(includeKey => { - // // Throw when includes field is not found - // // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - // return relationshipKeys[path.resource].find(key => key.includeKey === includeKey)!.resourceKey - // }).concat(path.resource) return { ...options, @@ -62,21 +49,23 @@ function createPaths (options: PathSchemaOptions) { parameters: [ ...(path.params ? [ { - '$ref': `#/components/parameters/${path.params.id ?? 'id'}`, + $ref: `#/components/parameters/${path.params.id ?? 'id'}`, } ] : []), ...(method === RequestMethod.Get ? [ { - '$ref': '#/components/parameters/include', + $ref: '#/components/parameters/include', } ]: []), { - '$ref': '#/components/parameters/userAgent', + $ref: '#/components/parameters/userAgent', }, ], responses: { - '200': { '$ref': '#/components/responses/200' }, - '400': { '$ref': '#/components/responses/400' }, + '200': { + $ref: `#/components/responses/${path.resource}${path.response?.array ? 's' : ''}Response` + }, + '400': { $ref: '#/components/responses/400' }, }, security: [ { @@ -95,7 +84,23 @@ export async function writeOpenAPISchema(options: SchemaOptions) { await writeFile(fileName, JSON.stringify({ ...details, - components, + components: { + ...components, + responses: { + ...components.responses, + ...routes.reduce((obj, route) => ({ + ...obj, + [`${route.resource}${route.response?.array ? 's' : ''}Response`]: { + description: 'OK', + content: { + 'application/json': { + schema: createResponse(route.resource, route.response?.array), + } + } + } + }), {}) + } + }, paths: createPaths({ base: '/api/oauth/v2', routes,