|
| 1 | +import { extendZodWithOpenApi } from '@asteasolutions/zod-to-openapi'; |
| 2 | +import { z } from 'zod'; |
| 3 | + |
| 4 | +extendZodWithOpenApi(z); |
| 5 | + |
| 6 | +// Define Word Generator Response Schema |
| 7 | +export type WordGeneratorResponse = z.infer<typeof WordGeneratorResponseSchema>; |
| 8 | +export const WordGeneratorResponseSchema = z.object({ |
| 9 | + filepath: z.string().openapi({ |
| 10 | + description: 'The file path where the generated Word document is saved.', |
| 11 | + }), |
| 12 | +}); |
| 13 | + |
| 14 | +// Define Cell Schema |
| 15 | +const CellSchema = z.object({ |
| 16 | + text: z.string().optional().openapi({ |
| 17 | + description: 'Text content within a cell.', |
| 18 | + }), |
| 19 | +}); |
| 20 | + |
| 21 | +// Define Row Schema |
| 22 | +const RowSchema = z.object({ |
| 23 | + cells: z.array(CellSchema).optional().openapi({ |
| 24 | + description: 'Array of cells within a row.', |
| 25 | + }), |
| 26 | +}); |
| 27 | + |
| 28 | +// Define Content Schema |
| 29 | +const ContentSchema = z.object({ |
| 30 | + type: z.enum(['paragraph', 'listing', 'table', 'pageBreak', 'emptyLine']).openapi({ |
| 31 | + description: 'Type of the content item.', |
| 32 | + }), |
| 33 | + text: z.string().optional().openapi({ |
| 34 | + description: 'Text content for paragraphs or listings.', |
| 35 | + }), |
| 36 | + items: z.array(z.string()).optional().openapi({ |
| 37 | + description: 'Items in a list for listing type content.', |
| 38 | + }), |
| 39 | + headers: z.array(z.string()).optional().openapi({ |
| 40 | + description: 'Headers for table content.', |
| 41 | + }), |
| 42 | + rows: z.array(RowSchema).optional().openapi({ |
| 43 | + description: 'Rows for table content.', |
| 44 | + }), |
| 45 | +}); |
| 46 | + |
| 47 | +// Define the base schema for a section |
| 48 | +const BaseSectionSchema = z.object({ |
| 49 | + heading: z.string().optional().openapi({ |
| 50 | + description: 'Heading of the section.', |
| 51 | + }), |
| 52 | + headingLevel: z.number().int().min(1).optional().openapi({ |
| 53 | + description: 'Level of the heading (e.g., 1 for main heading, 2 for subheading).', |
| 54 | + }), |
| 55 | + content: z.array(ContentSchema).optional().openapi({ |
| 56 | + description: 'Content contained within the section, including paragraphs, tables, etc.', |
| 57 | + }), |
| 58 | +}); |
| 59 | + |
| 60 | +// Extend the base schema with subSections |
| 61 | +const SectionSchema = BaseSectionSchema.extend({ |
| 62 | + subSections: z.array(BaseSectionSchema).optional().openapi({ |
| 63 | + description: 'Subsections within the main section.', |
| 64 | + }), |
| 65 | +}); |
| 66 | + |
| 67 | +// Request Body Schema |
| 68 | +export const WordGeneratorRequestBodySchema = z.object({ |
| 69 | + title: z.string().openapi({ |
| 70 | + description: 'Title of the document.', |
| 71 | + }), |
| 72 | + header: z.object({ |
| 73 | + text: z.string().openapi({ |
| 74 | + description: 'Text content for the header.', |
| 75 | + }), |
| 76 | + alignment: z.enum(['left', 'center', 'right']).default('left').openapi({ |
| 77 | + description: 'Alignment of the header text.', |
| 78 | + }), |
| 79 | + }), |
| 80 | + footer: z.object({ |
| 81 | + text: z.string().openapi({ |
| 82 | + description: 'Text content for the footer.', |
| 83 | + }), |
| 84 | + alignment: z.enum(['left', 'center', 'right']).default('left').openapi({ |
| 85 | + description: 'Alignment of the footer text.', |
| 86 | + }), |
| 87 | + }), |
| 88 | + sections: z.array(SectionSchema).openapi({ |
| 89 | + description: 'Sections of the document, which may include sub-sections.', |
| 90 | + }), |
| 91 | + wordConfig: z |
| 92 | + .object({ |
| 93 | + fontSize: z.number().default(12).openapi({ |
| 94 | + description: 'Font size for the slides, default is 12 pt.', |
| 95 | + }), |
| 96 | + lineHeight: z.enum(['1', '1.15', '1.25', '1.5', '2']).default('1').openapi({ |
| 97 | + description: 'Line height for text content.', |
| 98 | + }), |
| 99 | + fontFamily: z |
| 100 | + .enum(['Arial', 'Calibri', 'Times New Roman', 'Courier New', 'Verdana', 'Tahoma', 'Georgia', 'Comic Sans MS']) |
| 101 | + .default('Arial') |
| 102 | + .openapi({ |
| 103 | + description: 'Font family for the slides, default is Arial.', |
| 104 | + }), |
| 105 | + showPageNumber: z.boolean().default(false).openapi({ |
| 106 | + description: 'Option to display page numbers in the document.', |
| 107 | + }), |
| 108 | + showTableOfContent: z.boolean().default(false).openapi({ |
| 109 | + description: 'Option to display a table of contents.', |
| 110 | + }), |
| 111 | + showNumberingInHeader: z.boolean().default(false).openapi({ |
| 112 | + description: 'Option to display numbering in the header.', |
| 113 | + }), |
| 114 | + numberingReference: z |
| 115 | + .enum([ |
| 116 | + '1.1.1.1 (Decimal)', |
| 117 | + 'I.1.a.i (Roman -> Decimal > Lower Letter -> Lower Roman)', |
| 118 | + 'I.A.1.a (Roman -> Upper Letter -> Decimal -> Lower Letter)', |
| 119 | + '1)a)i)(i) (Decimal -> Lower Letter -> Lower Roman -> Lower Roman with Parentheses)', |
| 120 | + 'A.1.a.i (Upper Letter -> Decimal -> Lower Letter -> Lower Roman)', |
| 121 | + ]) |
| 122 | + .default('1.1.1.1 (Decimal)') |
| 123 | + .openapi({ |
| 124 | + description: 'Set numbering hierarchy format for the document.', |
| 125 | + }), |
| 126 | + pageOrientation: z.enum(['portrait', 'landscape']).default('portrait').openapi({ |
| 127 | + description: 'Set the page orientation for the document.', |
| 128 | + }), |
| 129 | + margins: z.enum(['normal', 'narrow', 'moderate', 'wide', 'mirrored']).default('normal').openapi({ |
| 130 | + description: 'Set page margins for the document.', |
| 131 | + }), |
| 132 | + }) |
| 133 | + .openapi({ |
| 134 | + description: 'Word configuration settings for generating the document.', |
| 135 | + }), |
| 136 | +}); |
| 137 | + |
| 138 | +export type WordGeneratorRequestBody = z.infer<typeof WordGeneratorRequestBodySchema>; |
0 commit comments