diff --git a/packages/api/v1/examples/01-create-and-send-document.ts b/packages/api/v1/examples/01-create-and-send-document.ts new file mode 100644 index 000000000..925d86656 --- /dev/null +++ b/packages/api/v1/examples/01-create-and-send-document.ts @@ -0,0 +1,59 @@ +import { initClient } from '@ts-rest/core'; + +import { ApiContractV1 } from '../contract'; + +const main = async () => { + const client = initClient(ApiContractV1, { + baseUrl: 'http://localhost:3000/api/v1', + baseHeaders: { + authorization: 'Bearer ', + }, + }); + + const { status, body } = await client.createDocument({ + body: { + title: 'My Document', + recipients: [ + { + name: 'John Doe', + email: 'john@example.com', + role: 'SIGNER', + }, + { + name: 'Jane Doe', + email: 'jane@example.com', + role: 'APPROVER', + }, + ], + meta: { + subject: 'Please sign this document', + message: 'Hey {signer.name}, please sign the following document: {document.name}', + }, + }, + }); + + if (status !== 200) { + throw new Error('Failed to create document'); + } + + const { uploadUrl, documentId } = body; + + await fetch(uploadUrl, { + method: 'PUT', + headers: { + 'Content-Type': 'application/octet-stream', + }, + body: '', + }); + + await client.sendDocument({ + params: { + id: documentId.toString(), + }, + }); +}; + +main().catch((error) => { + console.error(error); + process.exit(1); +}); diff --git a/packages/api/v1/examples/02-add-a-field.ts b/packages/api/v1/examples/02-add-a-field.ts new file mode 100644 index 000000000..6b186694a --- /dev/null +++ b/packages/api/v1/examples/02-add-a-field.ts @@ -0,0 +1,43 @@ +import { initClient } from '@ts-rest/core'; + +import { ApiContractV1 } from '../contract'; + +const main = async () => { + const client = initClient(ApiContractV1, { + baseUrl: 'http://localhost:3000/api/v1', + baseHeaders: { + authorization: 'Bearer ', + }, + }); + + const documentId = '1'; + const recipientId = 1; + + const { status, body } = await client.createField({ + params: { + id: documentId, + }, + body: { + type: 'SIGNATURE', + pageHeight: 2.5, // percent of page to occupy in height + pageWidth: 5, // percent of page to occupy in width + pageX: 10, // percent from left + pageY: 10, // percent from top + pageNumber: 1, + recipientId, + }, + }); + + if (status !== 200) { + throw new Error('Failed to create field'); + } + + const { id: fieldId } = body; + + console.log(`Field created with id: ${fieldId}`); +}; + +main().catch((error) => { + console.error(error); + process.exit(1); +}); diff --git a/packages/api/v1/examples/03-update-a-field.ts b/packages/api/v1/examples/03-update-a-field.ts new file mode 100644 index 000000000..d93831b7c --- /dev/null +++ b/packages/api/v1/examples/03-update-a-field.ts @@ -0,0 +1,39 @@ +import { initClient } from '@ts-rest/core'; + +import { ApiContractV1 } from '../contract'; + +const main = async () => { + const client = initClient(ApiContractV1, { + baseUrl: 'http://localhost:3000/api/v1', + baseHeaders: { + authorization: 'Bearer ', + }, + }); + + const documentId = '1'; + const fieldId = '1'; + + const { status } = await client.updateField({ + params: { + id: documentId, + fieldId, + }, + body: { + type: 'SIGNATURE', + pageHeight: 2.5, // percent of page to occupy in height + pageWidth: 5, // percent of page to occupy in width + pageX: 10, // percent from left + pageY: 10, // percent from top + pageNumber: 1, + }, + }); + + if (status !== 200) { + throw new Error('Failed to update field'); + } +}; + +main().catch((error) => { + console.error(error); + process.exit(1); +}); diff --git a/packages/api/v1/examples/04-remove-a-field.ts b/packages/api/v1/examples/04-remove-a-field.ts new file mode 100644 index 000000000..d7f233940 --- /dev/null +++ b/packages/api/v1/examples/04-remove-a-field.ts @@ -0,0 +1,31 @@ +import { initClient } from '@ts-rest/core'; + +import { ApiContractV1 } from '../contract'; + +const main = async () => { + const client = initClient(ApiContractV1, { + baseUrl: 'http://localhost:3000/api/v1', + baseHeaders: { + authorization: 'Bearer ', + }, + }); + + const documentId = '1'; + const fieldId = '1'; + + const { status } = await client.deleteField({ + params: { + id: documentId, + fieldId, + }, + }); + + if (status !== 200) { + throw new Error('Failed to remove field'); + } +}; + +main().catch((error) => { + console.error(error); + process.exit(1); +}); diff --git a/packages/api/v1/examples/05-add-a-recipient.ts b/packages/api/v1/examples/05-add-a-recipient.ts new file mode 100644 index 000000000..e63abd9e5 --- /dev/null +++ b/packages/api/v1/examples/05-add-a-recipient.ts @@ -0,0 +1,38 @@ +import { initClient } from '@ts-rest/core'; + +import { ApiContractV1 } from '../contract'; + +const main = async () => { + const client = initClient(ApiContractV1, { + baseUrl: 'http://localhost:3000/api/v1', + baseHeaders: { + authorization: 'Bearer ', + }, + }); + + const documentId = '1'; + + const { status, body } = await client.createRecipient({ + params: { + id: documentId, + }, + body: { + name: 'John Doe', + email: 'john@example.com', + role: 'APPROVER', + }, + }); + + if (status !== 200) { + throw new Error('Failed to add recipient'); + } + + const { id: recipientId } = body; + + console.log(`Recipient added with id: ${recipientId}`); +}; + +main().catch((error) => { + console.error(error); + process.exit(1); +}); diff --git a/packages/api/v1/examples/06-update-a-recipient.ts b/packages/api/v1/examples/06-update-a-recipient.ts new file mode 100644 index 000000000..d9e8255e7 --- /dev/null +++ b/packages/api/v1/examples/06-update-a-recipient.ts @@ -0,0 +1,34 @@ +import { initClient } from '@ts-rest/core'; + +import { ApiContractV1 } from '../contract'; + +const main = async () => { + const client = initClient(ApiContractV1, { + baseUrl: 'http://localhost:3000/api/v1', + baseHeaders: { + authorization: 'Bearer ', + }, + }); + + const documentId = '1'; + const recipientId = '1'; + + const { status } = await client.updateRecipient({ + params: { + id: documentId, + recipientId, + }, + body: { + name: 'Johnathon Doe', + }, + }); + + if (status !== 200) { + throw new Error('Failed to update recipient'); + } +}; + +main().catch((error) => { + console.error(error); + process.exit(1); +}); diff --git a/packages/api/v1/examples/07-remove-a-recipient.ts b/packages/api/v1/examples/07-remove-a-recipient.ts new file mode 100644 index 000000000..956e7dcae --- /dev/null +++ b/packages/api/v1/examples/07-remove-a-recipient.ts @@ -0,0 +1,31 @@ +import { initClient } from '@ts-rest/core'; + +import { ApiContractV1 } from '../contract'; + +const main = async () => { + const client = initClient(ApiContractV1, { + baseUrl: 'http://localhost:3000/api/v1', + baseHeaders: { + authorization: 'Bearer ', + }, + }); + + const documentId = '1'; + const recipientId = '1'; + + const { status } = await client.deleteRecipient({ + params: { + id: documentId, + recipientId, + }, + }); + + if (status !== 200) { + throw new Error('Failed to update recipient'); + } +}; + +main().catch((error) => { + console.error(error); + process.exit(1); +}); diff --git a/packages/api/v1/examples/08-get-a-document.ts b/packages/api/v1/examples/08-get-a-document.ts new file mode 100644 index 000000000..eb69cc8e8 --- /dev/null +++ b/packages/api/v1/examples/08-get-a-document.ts @@ -0,0 +1,31 @@ +import { initClient } from '@ts-rest/core'; + +import { ApiContractV1 } from '../contract'; + +const main = async () => { + const client = initClient(ApiContractV1, { + baseUrl: 'http://localhost:3000/api/v1', + baseHeaders: { + authorization: 'Bearer ', + }, + }); + + const documentId = '1'; + + const { status, body } = await client.getDocument({ + params: { + id: documentId, + }, + }); + + if (status !== 200) { + throw new Error('Failed to get document'); + } + + console.log(`Got document with id: ${documentId} and title: ${body.title}`); +}; + +main().catch((error) => { + console.error(error); + process.exit(1); +}); diff --git a/packages/api/v1/examples/09-paginate-all-documents.ts b/packages/api/v1/examples/09-paginate-all-documents.ts new file mode 100644 index 000000000..f0330b620 --- /dev/null +++ b/packages/api/v1/examples/09-paginate-all-documents.ts @@ -0,0 +1,37 @@ +import { initClient } from '@ts-rest/core'; + +import { ApiContractV1 } from '../contract'; + +const main = async () => { + const client = initClient(ApiContractV1, { + baseUrl: 'http://localhost:3000/api/v1', + baseHeaders: { + authorization: 'Bearer ', + }, + }); + + const page = 1; + const perPage = 10; + + const { status, body } = await client.getDocuments({ + query: { + page, + perPage, + }, + }); + + if (status !== 200) { + throw new Error('Failed to get documents'); + } + + for (const document of body.documents) { + console.log(`Got document with id: ${document.id} and title: ${document.title}`); + } + + console.log(`Total documents: ${body.totalPages * perPage}`); +}; + +main().catch((error) => { + console.error(error); + process.exit(1); +}); diff --git a/packages/api/v1/schema.ts b/packages/api/v1/schema.ts index 091e01fb6..511f4060b 100644 --- a/packages/api/v1/schema.ts +++ b/packages/api/v1/schema.ts @@ -12,8 +12,8 @@ import { * Documents */ export const ZGetDocumentsQuerySchema = z.object({ - page: z.string().optional(), - perPage: z.string().optional(), + page: z.number().min(1).optional().default(1), + perPage: z.number().min(1).optional().default(1), }); export type TGetDocumentsQuerySchema = z.infer; @@ -55,13 +55,15 @@ export const ZCreateDocumentMutationSchema = z.object({ role: z.nativeEnum(RecipientRole).optional().default(RecipientRole.SIGNER), }), ), - meta: z.object({ - subject: z.string(), - message: z.string(), - timezone: z.string(), - dateFormat: z.string(), - redirectUrl: z.string(), - }), + meta: z + .object({ + subject: z.string(), + message: z.string(), + timezone: z.string(), + dateFormat: z.string(), + redirectUrl: z.string(), + }) + .partial(), }); export type TCreateDocumentMutationSchema = z.infer; @@ -142,6 +144,7 @@ export const ZDeleteFieldMutationSchema = null; export type TDeleteFieldMutationSchema = typeof ZDeleteFieldMutationSchema; export const ZSuccessfulFieldResponseSchema = z.object({ + id: z.number(), documentId: z.number(), recipientId: z.number(), type: z.nativeEnum(FieldType),