@purpleschool/gptbot-tools 0.0.27 → 0.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/common/errors/errors.js +191 -0
- package/build/index.js +5 -0
- package/build/language/index.js +17 -0
- package/build/language/models/index.js +17 -0
- package/build/language/models/language.schema.js +11 -0
- package/build/presentation/commands/create-presentation.command.js +18 -0
- package/build/presentation/commands/delete-all-user-presentations.command.js +13 -0
- package/build/presentation/commands/delete-presentation.command.js +14 -0
- package/build/presentation/commands/delete-slide-outline.command.js +15 -0
- package/build/presentation/commands/export-as-pptx.command.js +18 -0
- package/build/presentation/commands/generate-presentation-outline.command.js +18 -0
- package/build/presentation/commands/generate-slides.command.js +15 -0
- package/build/presentation/commands/index.js +27 -0
- package/build/presentation/commands/reposition-slide-outline.command.js +16 -0
- package/build/presentation/commands/update-presentation-outline.command.js +16 -0
- package/build/presentation/commands/update-presentation.command.js +16 -0
- package/build/presentation/commands/update-slide-outline.command.js +17 -0
- package/build/presentation/constants/index.js +17 -0
- package/build/presentation/constants/slide-layout-map.constant.js +16 -0
- package/build/presentation/enums/index.js +22 -0
- package/build/presentation/enums/presentation-stage.enum.js +14 -0
- package/build/presentation/enums/slide-content-type.enum.js +15 -0
- package/build/presentation/enums/slide-icon-slot-status.enum.js +10 -0
- package/build/presentation/enums/slide-image-job-status.enum.js +10 -0
- package/build/presentation/enums/slide-image-slot-status.enum.js +10 -0
- package/build/presentation/enums/slide-layout.enum.js +8 -0
- package/build/presentation/index.js +22 -0
- package/build/presentation/models/index.js +25 -0
- package/build/presentation/models/pptx-export-payload.js +183 -0
- package/build/presentation/models/presentation-config.schema.js +17 -0
- package/build/presentation/models/presentation-template.schema.js +13 -0
- package/build/presentation/models/presentation.schema.js +30 -0
- package/build/presentation/models/slide-content-type.schema.js +14 -0
- package/build/presentation/models/slide-content.schema.js +178 -0
- package/build/presentation/models/slide-icon-slot.schema.js +15 -0
- package/build/presentation/models/slide-image-slot.schema.js +16 -0
- package/build/presentation/models/slide-outline.schema.js +50 -0
- package/build/presentation/models/slide.schema.js +20 -0
- package/build/presentation/queries/find-presentation-by-uuid.query.js +13 -0
- package/build/presentation/queries/find-presentation-outline.query.js +15 -0
- package/build/presentation/queries/find-presentations.query.js +21 -0
- package/build/presentation/queries/get-presentation-config.query.js +9 -0
- package/build/presentation/queries/index.js +20 -0
- package/build/presentation/routes/index.js +17 -0
- package/build/presentation/routes/presentation.routes.js +22 -0
- package/common/errors/errors.ts +191 -0
- package/index.ts +5 -0
- package/language/index.ts +1 -0
- package/language/models/index.ts +1 -0
- package/language/models/language.schema.ts +9 -0
- package/package.json +1 -1
- package/presentation/commands/create-presentation.command.ts +18 -0
- package/presentation/commands/delete-all-user-presentations.command.ts +13 -0
- package/presentation/commands/delete-presentation.command.ts +14 -0
- package/presentation/commands/delete-slide-outline.command.ts +15 -0
- package/presentation/commands/export-as-pptx.command.ts +20 -0
- package/presentation/commands/generate-presentation-outline.command.ts +18 -0
- package/presentation/commands/generate-slides.command.ts +15 -0
- package/presentation/commands/index.ts +11 -0
- package/presentation/commands/reposition-slide-outline.command.ts +16 -0
- package/presentation/commands/update-presentation-outline.command.ts +16 -0
- package/presentation/commands/update-presentation.command.ts +16 -0
- package/presentation/commands/update-slide-outline.command.ts +17 -0
- package/presentation/constants/index.ts +1 -0
- package/presentation/constants/slide-layout-map.constant.ts +14 -0
- package/presentation/enums/index.ts +6 -0
- package/presentation/enums/presentation-stage.enum.ts +13 -0
- package/presentation/enums/slide-content-type.enum.ts +11 -0
- package/presentation/enums/slide-icon-slot-status.enum.ts +6 -0
- package/presentation/enums/slide-image-job-status.enum.ts +6 -0
- package/presentation/enums/slide-image-slot-status.enum.ts +6 -0
- package/presentation/enums/slide-layout.enum.ts +4 -0
- package/presentation/index.ts +6 -0
- package/presentation/models/index.ts +9 -0
- package/presentation/models/pptx-export-payload.ts +212 -0
- package/presentation/models/presentation-config.schema.ts +16 -0
- package/presentation/models/presentation-template.schema.ts +12 -0
- package/presentation/models/presentation.schema.ts +33 -0
- package/presentation/models/slide-content-type.schema.ts +13 -0
- package/presentation/models/slide-content.schema.ts +221 -0
- package/presentation/models/slide-icon-slot.schema.ts +13 -0
- package/presentation/models/slide-image-slot.schema.ts +14 -0
- package/presentation/models/slide-outline.schema.ts +58 -0
- package/presentation/models/slide.schema.ts +19 -0
- package/presentation/queries/find-presentation-by-uuid.query.ts +13 -0
- package/presentation/queries/find-presentation-outline.query.ts +15 -0
- package/presentation/queries/find-presentations.query.ts +24 -0
- package/presentation/queries/get-presentation-config.query.ts +8 -0
- package/presentation/queries/index.ts +4 -0
- package/presentation/routes/index.ts +1 -0
- package/presentation/routes/presentation.routes.ts +20 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
export enum PPTX_SHAPE_TYPE {
|
|
4
|
+
TEXT_BOX = 'text_box',
|
|
5
|
+
PICTURE_BOX = 'picture_box',
|
|
6
|
+
CUSTOM_SHAPE = 'custom_shape',
|
|
7
|
+
TABLE = 'table',
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export enum PPTX_H_ALIGN {
|
|
11
|
+
LEFT = 'left',
|
|
12
|
+
CENTER = 'center',
|
|
13
|
+
RIGHT = 'right',
|
|
14
|
+
JUSTIFY = 'justify',
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export enum PPTX_V_ALIGN {
|
|
18
|
+
TOP = 'top',
|
|
19
|
+
MIDDLE = 'middle',
|
|
20
|
+
BOTTOM = 'bottom',
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export enum PPTX_OBJECT_FIT {
|
|
24
|
+
COVER = 'cover',
|
|
25
|
+
CONTAIN = 'contain',
|
|
26
|
+
CROP = 'crop',
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export enum PPTX_BORDER_TYPE {
|
|
30
|
+
SOLID = 'solid',
|
|
31
|
+
NONE = 'none',
|
|
32
|
+
DASH = 'dash',
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export enum PPTX_FILL_TYPE {
|
|
36
|
+
SOLID = 'solid',
|
|
37
|
+
NONE = 'none',
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export enum PPTX_SHADOW_TYPE {
|
|
41
|
+
OUTER = 'outer',
|
|
42
|
+
INNER = 'inner',
|
|
43
|
+
NONE = 'none',
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export enum PPTX_CUSTOM_SHAPE_TYPE {
|
|
47
|
+
ROUND_RECT = 'roundRect',
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const PPTXShadowSchema = z.object({
|
|
51
|
+
type: z.nativeEnum(PPTX_SHADOW_TYPE),
|
|
52
|
+
opacity: z.number().min(0).max(100).optional().describe('percents, range 0-100'),
|
|
53
|
+
color: z.string().optional().describe('hex color'),
|
|
54
|
+
blur: z.number().min(0).max(100).optional().describe('degrees, range 0-100'),
|
|
55
|
+
angle: z.number().min(0).max(359).optional().describe('degrees, range 0-359'),
|
|
56
|
+
offset: z.number().min(0).max(200).optional().describe('points, range 0-200'),
|
|
57
|
+
rotateWithShape: z.boolean().optional().describe('whether or not to rotate shadow with shape'),
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
export const PPTXFillSchema = z.object({
|
|
61
|
+
color: z.string(),
|
|
62
|
+
type: z.nativeEnum(PPTX_FILL_TYPE),
|
|
63
|
+
transparency: z.number().min(0).max(100).optional().describe('percents, range 0-100'),
|
|
64
|
+
alpha: z.number().min(0).max(1).optional().describe('range 0-1'),
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
export const PPTXMarginSchema = z.union([
|
|
68
|
+
z.number(),
|
|
69
|
+
z.tuple([z.number(), z.number(), z.number(), z.number()]),
|
|
70
|
+
]);
|
|
71
|
+
export type PPTXMargin = z.infer<typeof PPTXMarginSchema>;
|
|
72
|
+
|
|
73
|
+
// Common
|
|
74
|
+
export const PPTXPositionSchema = z.object({
|
|
75
|
+
height: z.number(),
|
|
76
|
+
width: z.number(),
|
|
77
|
+
top: z.number(),
|
|
78
|
+
left: z.number(),
|
|
79
|
+
});
|
|
80
|
+
export type PPTXPosition = z.infer<typeof PPTXPositionSchema>;
|
|
81
|
+
|
|
82
|
+
export const PPTXFontSchema = z.object({
|
|
83
|
+
bold: z.boolean().optional(),
|
|
84
|
+
color: z.string(),
|
|
85
|
+
name: z.string(),
|
|
86
|
+
size: z.number(),
|
|
87
|
+
lineHeight: z
|
|
88
|
+
.union([
|
|
89
|
+
z.object({
|
|
90
|
+
percent: z.number(),
|
|
91
|
+
}),
|
|
92
|
+
z.object({
|
|
93
|
+
px: z.number(),
|
|
94
|
+
}),
|
|
95
|
+
])
|
|
96
|
+
.optional(),
|
|
97
|
+
});
|
|
98
|
+
export type PPTXFont = z.infer<typeof PPTXFontSchema>;
|
|
99
|
+
|
|
100
|
+
// Textual
|
|
101
|
+
export const PPTXParagraphSchema = z.object({
|
|
102
|
+
alignment: z.nativeEnum(PPTX_H_ALIGN),
|
|
103
|
+
font: PPTXFontSchema,
|
|
104
|
+
valign: z.nativeEnum(PPTX_V_ALIGN).optional(),
|
|
105
|
+
margin: PPTXMarginSchema.optional(),
|
|
106
|
+
rotate: z.number().optional(),
|
|
107
|
+
text: z.string(),
|
|
108
|
+
});
|
|
109
|
+
export type PPTXParagraph = z.infer<typeof PPTXParagraphSchema>;
|
|
110
|
+
|
|
111
|
+
export const PPTXTextBoxSchema = z.object({
|
|
112
|
+
type: z.literal(PPTX_SHAPE_TYPE.TEXT_BOX),
|
|
113
|
+
position: PPTXPositionSchema,
|
|
114
|
+
|
|
115
|
+
paragraphs: z.array(PPTXParagraphSchema),
|
|
116
|
+
});
|
|
117
|
+
export type PPTXTextBox = z.infer<typeof PPTXTextBoxSchema>;
|
|
118
|
+
|
|
119
|
+
// Picture
|
|
120
|
+
export const PPTXPictureBoxSchema = z.object({
|
|
121
|
+
type: z.literal(PPTX_SHAPE_TYPE.PICTURE_BOX),
|
|
122
|
+
position: PPTXPositionSchema,
|
|
123
|
+
borderRadius: z.array(z.number()).optional(),
|
|
124
|
+
objectFit: z.nativeEnum(PPTX_OBJECT_FIT),
|
|
125
|
+
data: z.union([
|
|
126
|
+
z.object({
|
|
127
|
+
base64: z
|
|
128
|
+
.string()
|
|
129
|
+
.describe('Base64 encoded image in "image/{mimeType};base64,{bas64}" format'),
|
|
130
|
+
}),
|
|
131
|
+
z.object({
|
|
132
|
+
path: z.string().describe('URL to image'),
|
|
133
|
+
}),
|
|
134
|
+
]),
|
|
135
|
+
});
|
|
136
|
+
export type PPTXPictureBox = z.infer<typeof PPTXPictureBoxSchema>;
|
|
137
|
+
|
|
138
|
+
// CustomShape
|
|
139
|
+
export const PPTXCustomShapeSchema = z.object({
|
|
140
|
+
type: z.literal(PPTX_SHAPE_TYPE.CUSTOM_SHAPE),
|
|
141
|
+
customShapeType: z.nativeEnum(PPTX_CUSTOM_SHAPE_TYPE).optional(),
|
|
142
|
+
position: PPTXPositionSchema,
|
|
143
|
+
borderRadius: z.number(),
|
|
144
|
+
fill: PPTXFillSchema.optional(),
|
|
145
|
+
shadow: PPTXShadowSchema.optional(),
|
|
146
|
+
});
|
|
147
|
+
export type PPTXCustomShape = z.infer<typeof PPTXCustomShapeSchema>;
|
|
148
|
+
|
|
149
|
+
// Table
|
|
150
|
+
export const PPTXTableCellSchema = z.object({
|
|
151
|
+
text: z.string().optional(),
|
|
152
|
+
font: PPTXFontSchema.optional(),
|
|
153
|
+
fill: z
|
|
154
|
+
.object({
|
|
155
|
+
color: z.string(),
|
|
156
|
+
type: z.nativeEnum(PPTX_FILL_TYPE),
|
|
157
|
+
transparency: z.number().min(0).max(100).optional().describe('percents, range 0-100'),
|
|
158
|
+
})
|
|
159
|
+
.optional(),
|
|
160
|
+
align: z.nativeEnum(PPTX_H_ALIGN).optional(),
|
|
161
|
+
valign: z.nativeEnum(PPTX_V_ALIGN).optional(),
|
|
162
|
+
colspan: z.number().int().optional(),
|
|
163
|
+
rowspan: z.number().int().optional(),
|
|
164
|
+
margin: PPTXMarginSchema.optional(),
|
|
165
|
+
});
|
|
166
|
+
export type PPTXTableCell = z.infer<typeof PPTXTableCellSchema>;
|
|
167
|
+
|
|
168
|
+
export const PPTXTableRowSchema = z.array(PPTXTableCellSchema);
|
|
169
|
+
export type PPTXTableRow = z.infer<typeof PPTXTableRowSchema>;
|
|
170
|
+
|
|
171
|
+
export const PPTXTableShapeSchema = z.object({
|
|
172
|
+
type: z.literal(PPTX_SHAPE_TYPE.TABLE),
|
|
173
|
+
position: PPTXPositionSchema,
|
|
174
|
+
rows: z.array(PPTXTableRowSchema),
|
|
175
|
+
columnWidths: z.array(z.number()).optional(),
|
|
176
|
+
headerRows: z.number().int().min(0).optional(),
|
|
177
|
+
border: z.object({
|
|
178
|
+
type: z.nativeEnum(PPTX_BORDER_TYPE),
|
|
179
|
+
color: z.string(),
|
|
180
|
+
px: z.number(),
|
|
181
|
+
}),
|
|
182
|
+
});
|
|
183
|
+
export type PPTXTableShape = z.infer<typeof PPTXTableShapeSchema>;
|
|
184
|
+
|
|
185
|
+
// Overview
|
|
186
|
+
|
|
187
|
+
export const PPTXShapeSchema = z.discriminatedUnion('type', [
|
|
188
|
+
PPTXTextBoxSchema,
|
|
189
|
+
PPTXPictureBoxSchema,
|
|
190
|
+
PPTXCustomShapeSchema,
|
|
191
|
+
PPTXTableShapeSchema,
|
|
192
|
+
]);
|
|
193
|
+
export type PPTXShape = z.infer<typeof PPTXShapeSchema>;
|
|
194
|
+
|
|
195
|
+
export const SlideBackground = z.union([
|
|
196
|
+
PPTXFillSchema,
|
|
197
|
+
z.object({
|
|
198
|
+
path: z.string(),
|
|
199
|
+
}),
|
|
200
|
+
]);
|
|
201
|
+
export type SlideBackground = z.infer<typeof SlideBackground>;
|
|
202
|
+
|
|
203
|
+
export const PPTXSlideSchema = z.object({
|
|
204
|
+
background: SlideBackground.optional(),
|
|
205
|
+
shapes: z.array(PPTXShapeSchema),
|
|
206
|
+
});
|
|
207
|
+
export type PPTXSlide = z.infer<typeof PPTXSlideSchema>;
|
|
208
|
+
|
|
209
|
+
export const PPTXExportPayloadSchema = z.object({
|
|
210
|
+
slides: z.array(PPTXSlideSchema),
|
|
211
|
+
});
|
|
212
|
+
export type PPTXExportPayload = z.infer<typeof PPTXExportPayloadSchema>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { SlideContentTypeSchema } from './slide-content-type.schema';
|
|
3
|
+
import { LanguageSchema } from '../../language';
|
|
4
|
+
import { PresentationTemplateSchema } from './presentation-template.schema';
|
|
5
|
+
|
|
6
|
+
export const PresentationConfigSchema = z.object({
|
|
7
|
+
slideContentTypes: z.array(SlideContentTypeSchema),
|
|
8
|
+
languages: z.array(LanguageSchema),
|
|
9
|
+
templates: z.array(PresentationTemplateSchema),
|
|
10
|
+
slideGenerationPrice: z.number(),
|
|
11
|
+
maxSlides: z.number(),
|
|
12
|
+
minSlides: z.number(),
|
|
13
|
+
maxSlideOutlineLength: z.number(),
|
|
14
|
+
maxPromptLength: z.number(),
|
|
15
|
+
});
|
|
16
|
+
export type PresentationConfig = z.infer<typeof PresentationConfigSchema>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
export const PresentationTemplateSchema = z.object({
|
|
4
|
+
uuid: z.string().uuid(),
|
|
5
|
+
title: z.string(),
|
|
6
|
+
image: z.string(),
|
|
7
|
+
order: z.number(),
|
|
8
|
+
imagePlaceholder: z.string(),
|
|
9
|
+
createdAt: z.date(),
|
|
10
|
+
updatedAt: z.date(),
|
|
11
|
+
});
|
|
12
|
+
export type PresentationTemplate = z.infer<typeof PresentationTemplateSchema>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { PRESENTATION_STAGE } from '../enums';
|
|
3
|
+
import { SlideOutlineSchema } from './slide-outline.schema';
|
|
4
|
+
import { SlideSchema } from './slide.schema';
|
|
5
|
+
|
|
6
|
+
export const PresentationSchema = z.object({
|
|
7
|
+
uuid: z.string().uuid(),
|
|
8
|
+
prompt: z.string(),
|
|
9
|
+
stage: z.nativeEnum(PRESENTATION_STAGE),
|
|
10
|
+
title: z.string(),
|
|
11
|
+
thumbnail: z.string(),
|
|
12
|
+
languageId: z.string(),
|
|
13
|
+
templateId: z.string(),
|
|
14
|
+
downloadUrl: z.string().nullable(),
|
|
15
|
+
userId: z.string().uuid().nullable().optional(),
|
|
16
|
+
unregisteredUserId: z.string().uuid().nullable().optional(),
|
|
17
|
+
slideCount: z.number(),
|
|
18
|
+
isDeleted: z.boolean(),
|
|
19
|
+
createdAt: z.date(),
|
|
20
|
+
updatedAt: z.date(),
|
|
21
|
+
});
|
|
22
|
+
export type Presentation = z.infer<typeof PresentationSchema>;
|
|
23
|
+
|
|
24
|
+
export const PresentationWithSlidesSchema = PresentationSchema.extend({
|
|
25
|
+
outline: z.array(SlideOutlineSchema),
|
|
26
|
+
slides: z.array(SlideSchema),
|
|
27
|
+
});
|
|
28
|
+
export type PresentationWithSlides = z.infer<typeof PresentationWithSlidesSchema>;
|
|
29
|
+
|
|
30
|
+
export const PresentationUpdateSchema = PresentationSchema.pick({
|
|
31
|
+
title: true,
|
|
32
|
+
});
|
|
33
|
+
export type PresentationUpdate = z.infer<typeof PresentationUpdateSchema>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { SLIDE_CONTENT_TYPE, SLIDE_LAYOUT } from '../enums';
|
|
3
|
+
|
|
4
|
+
export const SlideContentTypeSchema = z.object({
|
|
5
|
+
id: z.nativeEnum(SLIDE_CONTENT_TYPE),
|
|
6
|
+
title: z.string(),
|
|
7
|
+
layouts: z.array(z.nativeEnum(SLIDE_LAYOUT)),
|
|
8
|
+
order: z.number(),
|
|
9
|
+
icon: z.string(),
|
|
10
|
+
createdAt: z.date(),
|
|
11
|
+
updatedAt: z.date(),
|
|
12
|
+
});
|
|
13
|
+
export type SlideContentType = z.infer<typeof SlideContentTypeSchema>;
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { SLIDE_CONTENT_TYPE } from '../enums';
|
|
3
|
+
|
|
4
|
+
export enum SLIDE_CHART_TYPE {
|
|
5
|
+
BAR = 'BAR',
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const ImageSlotSchema = z.object({
|
|
9
|
+
uuid: z
|
|
10
|
+
.string()
|
|
11
|
+
.uuid()
|
|
12
|
+
.describe('Generate a valid uuid for image slot, that will be used for future lookups'),
|
|
13
|
+
prompt: z.string().describe('Image prompt for slide'),
|
|
14
|
+
});
|
|
15
|
+
export type ImageSlot = z.infer<typeof ImageSlotSchema>;
|
|
16
|
+
|
|
17
|
+
export const IconSlotSchema = z.object({
|
|
18
|
+
uuid: z
|
|
19
|
+
.string()
|
|
20
|
+
.uuid()
|
|
21
|
+
.describe('Generate a valid uuid for icon slot, that will be used for future lookups'),
|
|
22
|
+
prompt: z
|
|
23
|
+
.string()
|
|
24
|
+
.describe(
|
|
25
|
+
'Icons are stored locally. Provide a search query for a fitting icon. MUST BE IN ENGLISH',
|
|
26
|
+
),
|
|
27
|
+
});
|
|
28
|
+
export type IconSlot = z.infer<typeof IconSlotSchema>;
|
|
29
|
+
|
|
30
|
+
export const CoverSlideDataSchema = z.object({
|
|
31
|
+
contentType: z.literal(SLIDE_CONTENT_TYPE.COVER),
|
|
32
|
+
title: z.string().describe('Slide title in about 6 words').min(10).max(200),
|
|
33
|
+
author: z.object({
|
|
34
|
+
label: z.string().describe('Literal "Author" in presentation\'s language'),
|
|
35
|
+
value: z
|
|
36
|
+
.string()
|
|
37
|
+
.describe('Literal "Author of the presentation" in presentation\'s language'),
|
|
38
|
+
}),
|
|
39
|
+
date: z.object({
|
|
40
|
+
label: z.string().describe('Literal "Date" in presentation\'s language'),
|
|
41
|
+
value: z
|
|
42
|
+
.string()
|
|
43
|
+
.describe(
|
|
44
|
+
'Date of the presentation in the "dd month yyyy" format in presentation\'s locale',
|
|
45
|
+
),
|
|
46
|
+
}),
|
|
47
|
+
email: z.object({
|
|
48
|
+
label: z.string().describe('Just default word "Email"'),
|
|
49
|
+
value: z.string().describe('Just default "email@example.com"'),
|
|
50
|
+
}),
|
|
51
|
+
});
|
|
52
|
+
export type CoverSlideData = z.infer<typeof CoverSlideDataSchema>;
|
|
53
|
+
|
|
54
|
+
export const ThankYouSlideDataSchema = z.object({
|
|
55
|
+
contentType: z.literal(SLIDE_CONTENT_TYPE.THANK_YOU),
|
|
56
|
+
title: z.string().describe('Slide title in about 6 words').min(10).max(200),
|
|
57
|
+
author: z.object({
|
|
58
|
+
label: z.string().describe('Literal "Author" in presentation\'s language'),
|
|
59
|
+
value: z
|
|
60
|
+
.string()
|
|
61
|
+
.describe('Literal "Author of the presentation" in presentation\'s language'),
|
|
62
|
+
}),
|
|
63
|
+
date: z.object({
|
|
64
|
+
label: z.string().describe('Literal "Date" in presentation\'s language'),
|
|
65
|
+
value: z
|
|
66
|
+
.string()
|
|
67
|
+
.describe(
|
|
68
|
+
'Date of the presentation in the "dd month yyyy" format in presentation\'s locale',
|
|
69
|
+
),
|
|
70
|
+
}),
|
|
71
|
+
email: z.object({
|
|
72
|
+
label: z.string().describe('Just default word "Email"'),
|
|
73
|
+
value: z.string().describe('Just default "email@example.com"'),
|
|
74
|
+
}),
|
|
75
|
+
});
|
|
76
|
+
export type ThankYouSlideData = z.infer<typeof ThankYouSlideDataSchema>;
|
|
77
|
+
|
|
78
|
+
export const StructuredListSlideDataSchema = z.object({
|
|
79
|
+
contentType: z.literal(SLIDE_CONTENT_TYPE.STRUCTURED_LIST),
|
|
80
|
+
title: z.string().describe('Slide title, 2–6 words'),
|
|
81
|
+
description: z.string().describe('One short framing sentence'),
|
|
82
|
+
list: z
|
|
83
|
+
.array(
|
|
84
|
+
z.object({
|
|
85
|
+
title: z.string().describe('2–4 words, concrete'),
|
|
86
|
+
description: z
|
|
87
|
+
.string()
|
|
88
|
+
.describe('One clear short framing sentence, explains the point, 8–14 words'),
|
|
89
|
+
}),
|
|
90
|
+
)
|
|
91
|
+
.length(4),
|
|
92
|
+
});
|
|
93
|
+
export type StructuredListSlideData = z.infer<typeof StructuredListSlideDataSchema>;
|
|
94
|
+
|
|
95
|
+
export const TextSlideDataSchema = z.object({
|
|
96
|
+
contentType: z.literal(SLIDE_CONTENT_TYPE.TEXT),
|
|
97
|
+
title: z.string().describe('Slide title in about 6 words').min(10).max(200),
|
|
98
|
+
description: z
|
|
99
|
+
.string()
|
|
100
|
+
.describe(
|
|
101
|
+
'Fairly long textual description of the point presented in the title. A couple of paragraphs.',
|
|
102
|
+
)
|
|
103
|
+
.min(300)
|
|
104
|
+
.max(1000),
|
|
105
|
+
});
|
|
106
|
+
export type TextSlideData = z.infer<typeof TextSlideDataSchema>;
|
|
107
|
+
|
|
108
|
+
export const ContentsSlideDataSchema = z.object({
|
|
109
|
+
contentType: z.literal(SLIDE_CONTENT_TYPE.CONTENTS),
|
|
110
|
+
title: z
|
|
111
|
+
.string()
|
|
112
|
+
.describe(
|
|
113
|
+
'This slide represents table of contents for the presentation and must be named "Contents" in the presentation language',
|
|
114
|
+
)
|
|
115
|
+
.min(10)
|
|
116
|
+
.max(200),
|
|
117
|
+
items: z
|
|
118
|
+
.array(z.string().min(1))
|
|
119
|
+
.min(1)
|
|
120
|
+
.describe(
|
|
121
|
+
'List of slide titles. Must be relevant and generated after all the slides are generated',
|
|
122
|
+
),
|
|
123
|
+
});
|
|
124
|
+
export type ContentsSlideData = z.infer<typeof ContentsSlideDataSchema>;
|
|
125
|
+
|
|
126
|
+
export const ImageSlideDataSchema = z.object({
|
|
127
|
+
contentType: z.literal(SLIDE_CONTENT_TYPE.IMAGE),
|
|
128
|
+
title: z.string().describe('Slide title in about 6 words').min(10).max(200),
|
|
129
|
+
description: z
|
|
130
|
+
.string()
|
|
131
|
+
.describe(
|
|
132
|
+
"Either a short description or a slightly long description of the slide's title depending on the context",
|
|
133
|
+
)
|
|
134
|
+
.min(10)
|
|
135
|
+
.max(500),
|
|
136
|
+
imageSlot: ImageSlotSchema,
|
|
137
|
+
});
|
|
138
|
+
export type ImageSlideData = z.infer<typeof ImageSlideDataSchema>;
|
|
139
|
+
|
|
140
|
+
export const SectionBreakSlideDataSchema = z.object({
|
|
141
|
+
contentType: z.literal(SLIDE_CONTENT_TYPE.SECTION_BREAK),
|
|
142
|
+
title: z.string().describe('Slide title in about 6 words').min(10).max(200),
|
|
143
|
+
description: z.string().describe('Description of the slide in about 6 words').min(10).max(200),
|
|
144
|
+
});
|
|
145
|
+
export type SectionBreakSlideData = z.infer<typeof SectionBreakSlideDataSchema>;
|
|
146
|
+
|
|
147
|
+
export const TableSlideDataSchema = z.object({
|
|
148
|
+
contentType: z.literal(SLIDE_CONTENT_TYPE.TABLE),
|
|
149
|
+
title: z
|
|
150
|
+
.string()
|
|
151
|
+
.describe('Slide title and table title at the same time in a couple of words')
|
|
152
|
+
.min(10)
|
|
153
|
+
.max(200),
|
|
154
|
+
description: z.string().describe('Description of the table represents').min(10).max(200),
|
|
155
|
+
table: z.object({
|
|
156
|
+
columnHeaders: z
|
|
157
|
+
.array(z.string().min(1).max(50))
|
|
158
|
+
.min(1)
|
|
159
|
+
.max(10)
|
|
160
|
+
.describe('Array of column header labels'),
|
|
161
|
+
rows: z
|
|
162
|
+
.array(z.array(z.string().min(1).max(150)))
|
|
163
|
+
.min(2)
|
|
164
|
+
.max(10)
|
|
165
|
+
.describe(
|
|
166
|
+
'Table rows; each row must have exactly the same number of cells as columnHeaders',
|
|
167
|
+
),
|
|
168
|
+
hasRowHeaders: z.boolean().describe('If table needs special row headers, set this to true'),
|
|
169
|
+
hasSummaryRow: z.boolean().describe('If table needs a summary row, set this to true'),
|
|
170
|
+
}),
|
|
171
|
+
});
|
|
172
|
+
export type TableSlideData = z.infer<typeof TableSlideDataSchema>;
|
|
173
|
+
|
|
174
|
+
// Charts
|
|
175
|
+
export const BarChartSlideDataSchema = z.object({
|
|
176
|
+
type: z.literal(SLIDE_CHART_TYPE.BAR),
|
|
177
|
+
categories: z
|
|
178
|
+
.array(z.string().min(1).max(12))
|
|
179
|
+
.min(1)
|
|
180
|
+
.max(12)
|
|
181
|
+
.describe('Category labels (e.g., months, products, regions)'),
|
|
182
|
+
series: z
|
|
183
|
+
.array(
|
|
184
|
+
z.object({
|
|
185
|
+
name: z.string().min(1).max(12).describe('Series name for legend'),
|
|
186
|
+
data: z.array(z.number()).describe('Values corresponding to categories'),
|
|
187
|
+
type: z
|
|
188
|
+
.number()
|
|
189
|
+
.min(0)
|
|
190
|
+
.max(11)
|
|
191
|
+
.describe('Series type. Used to discriminate colors when applying theme'),
|
|
192
|
+
}),
|
|
193
|
+
)
|
|
194
|
+
.min(1)
|
|
195
|
+
.max(12)
|
|
196
|
+
.describe('Data series for the chart'),
|
|
197
|
+
yAxisLabel: z.string().max(40).optional().describe('Y-axis label'),
|
|
198
|
+
unit: z.string().max(10).optional().describe('Unit symbol (%, $, etc.)'),
|
|
199
|
+
});
|
|
200
|
+
export type BarChartSlideData = z.infer<typeof BarChartSlideDataSchema>;
|
|
201
|
+
|
|
202
|
+
export const ChartSlideDataSchema = z.object({
|
|
203
|
+
contentType: z.literal(SLIDE_CONTENT_TYPE.CHART),
|
|
204
|
+
title: z.string().describe('Slide title in about 6 words').min(10).max(200),
|
|
205
|
+
description: z.string().describe("Information on slide's topic").min(10).max(400),
|
|
206
|
+
chart: z.discriminatedUnion('type', [BarChartSlideDataSchema]),
|
|
207
|
+
});
|
|
208
|
+
export type ChartSlideData = z.infer<typeof ChartSlideDataSchema>;
|
|
209
|
+
|
|
210
|
+
export const SlideContentSchema = z.discriminatedUnion('contentType', [
|
|
211
|
+
CoverSlideDataSchema,
|
|
212
|
+
StructuredListSlideDataSchema,
|
|
213
|
+
TextSlideDataSchema,
|
|
214
|
+
ContentsSlideDataSchema,
|
|
215
|
+
SectionBreakSlideDataSchema,
|
|
216
|
+
ImageSlideDataSchema,
|
|
217
|
+
ThankYouSlideDataSchema,
|
|
218
|
+
TableSlideDataSchema,
|
|
219
|
+
ChartSlideDataSchema,
|
|
220
|
+
]);
|
|
221
|
+
export type SlideContent = z.infer<typeof SlideContentSchema>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { SLIDE_ICON_SLOT_STATUS } from '../enums';
|
|
3
|
+
|
|
4
|
+
export const SlideIconSlotSchema = z.object({
|
|
5
|
+
uuid: z.string().uuid(),
|
|
6
|
+
prompt: z.string(),
|
|
7
|
+
alt: z.string(),
|
|
8
|
+
url: z.string().nullable(),
|
|
9
|
+
slideId: z.string(),
|
|
10
|
+
status: z.nativeEnum(SLIDE_ICON_SLOT_STATUS),
|
|
11
|
+
createdAt: z.date(),
|
|
12
|
+
updatedAt: z.date(),
|
|
13
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { SLIDE_IMAGE_SLOT_STATUS } from '../enums';
|
|
3
|
+
|
|
4
|
+
export const SlideImageSlotSchema = z.object({
|
|
5
|
+
uuid: z.string().uuid(),
|
|
6
|
+
prompt: z.string(),
|
|
7
|
+
alt: z.string(),
|
|
8
|
+
url: z.string().nullable(),
|
|
9
|
+
placeholder: z.string(),
|
|
10
|
+
slideId: z.string(),
|
|
11
|
+
status: z.nativeEnum(SLIDE_IMAGE_SLOT_STATUS),
|
|
12
|
+
createdAt: z.date(),
|
|
13
|
+
updatedAt: z.date(),
|
|
14
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { SLIDE_CONTENT_TYPE } from '../enums';
|
|
3
|
+
|
|
4
|
+
export const SlideOutlineSchema = z.object({
|
|
5
|
+
uuid: z.string(),
|
|
6
|
+
order: z.number(),
|
|
7
|
+
title: z.string().max(80),
|
|
8
|
+
body: z.string().max(500),
|
|
9
|
+
contentTypeId: z.nativeEnum(SLIDE_CONTENT_TYPE),
|
|
10
|
+
presentationId: z.string(),
|
|
11
|
+
createdAt: z.date(),
|
|
12
|
+
updatedAt: z.date(),
|
|
13
|
+
});
|
|
14
|
+
export type SlideOutline = z.infer<typeof SlideOutlineSchema>;
|
|
15
|
+
|
|
16
|
+
export const SlideOutlineUpdateSchema = SlideOutlineSchema.pick({
|
|
17
|
+
title: true,
|
|
18
|
+
body: true,
|
|
19
|
+
contentTypeId: true,
|
|
20
|
+
}).partial();
|
|
21
|
+
export type SlideOutlineUpdate = z.infer<typeof SlideOutlineUpdateSchema>;
|
|
22
|
+
|
|
23
|
+
export const SlideOutlineBulkUpdateSchema = SlideOutlineSchema.pick({
|
|
24
|
+
order: true,
|
|
25
|
+
title: true,
|
|
26
|
+
body: true,
|
|
27
|
+
contentTypeId: true,
|
|
28
|
+
presentationId: true,
|
|
29
|
+
})
|
|
30
|
+
.extend({
|
|
31
|
+
uuid: z.string().uuid().optional(),
|
|
32
|
+
})
|
|
33
|
+
.array()
|
|
34
|
+
.min(1, 'Must include at least one slide outline')
|
|
35
|
+
.refine(
|
|
36
|
+
(arr) => {
|
|
37
|
+
const orders = arr.map((s) => s.order);
|
|
38
|
+
const unique = new Set(orders);
|
|
39
|
+
if (unique.size !== orders.length) return false;
|
|
40
|
+
const sorted = [...orders].sort((a, b) => a - b);
|
|
41
|
+
return sorted.every((val, idx) => val === idx);
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
message: 'Slide orders must be unique and sequential starting at 0',
|
|
45
|
+
path: ['order'],
|
|
46
|
+
},
|
|
47
|
+
)
|
|
48
|
+
.refine(
|
|
49
|
+
(arr) => {
|
|
50
|
+
const [firstId, ...rest] = arr.map((s) => s.presentationId);
|
|
51
|
+
return rest.every((id) => id === firstId);
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
message: 'All slide outlines must belong to the same presentation',
|
|
55
|
+
path: ['presentationId'],
|
|
56
|
+
},
|
|
57
|
+
);
|
|
58
|
+
export type SlideOutlineBulkUpdate = z.infer<typeof SlideOutlineBulkUpdateSchema>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { SlideContentSchema } from './slide-content.schema';
|
|
3
|
+
import { SLIDE_CONTENT_TYPE, SLIDE_LAYOUT } from '../enums';
|
|
4
|
+
import { SlideIconSlotSchema } from './slide-icon-slot.schema';
|
|
5
|
+
import { SlideImageSlotSchema } from './slide-image-slot.schema';
|
|
6
|
+
|
|
7
|
+
export const SlideSchema = z.object({
|
|
8
|
+
uuid: z.string().uuid(),
|
|
9
|
+
order: z.number(),
|
|
10
|
+
contentTypeId: z.nativeEnum(SLIDE_CONTENT_TYPE),
|
|
11
|
+
layoutId: z.nativeEnum(SLIDE_LAYOUT),
|
|
12
|
+
content: SlideContentSchema,
|
|
13
|
+
presentationId: z.string(),
|
|
14
|
+
iconSlots: z.array(SlideIconSlotSchema),
|
|
15
|
+
imageSlots: z.array(SlideImageSlotSchema),
|
|
16
|
+
createdAt: z.date(),
|
|
17
|
+
updatedAt: z.date(),
|
|
18
|
+
});
|
|
19
|
+
export type Slide = z.infer<typeof SlideSchema>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ICommandResponseSchema } from '../../common';
|
|
3
|
+
import { PresentationWithSlidesSchema } from '../models';
|
|
4
|
+
|
|
5
|
+
export namespace FindPresentationByUuidQuery {
|
|
6
|
+
export const RequestSchema = z.object({
|
|
7
|
+
uuid: z.string().uuid(),
|
|
8
|
+
});
|
|
9
|
+
export type Request = z.infer<typeof RequestSchema>;
|
|
10
|
+
|
|
11
|
+
export const ResponseSchema = ICommandResponseSchema(PresentationWithSlidesSchema);
|
|
12
|
+
export type Response = z.infer<typeof ResponseSchema>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ICommandResponseSchema } from '../../common';
|
|
3
|
+
import { SlideOutlineSchema } from '../models';
|
|
4
|
+
|
|
5
|
+
export namespace FindPresentationOutlineQuery {
|
|
6
|
+
export const RequestSchema = z.object({
|
|
7
|
+
presentationId: z.string().uuid(),
|
|
8
|
+
userId: z.string().uuid().nullable().optional(),
|
|
9
|
+
unregisteredUserId: z.string().uuid().nullable().optional(),
|
|
10
|
+
});
|
|
11
|
+
export type Request = z.infer<typeof RequestSchema>;
|
|
12
|
+
|
|
13
|
+
export const ResponseSchema = ICommandResponseSchema(z.array(SlideOutlineSchema));
|
|
14
|
+
export type Response = z.infer<typeof ResponseSchema>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ICommandResponseSchema } from '../../common/models/command-response.schema';
|
|
3
|
+
import { PresentationSchema } from '../models';
|
|
4
|
+
|
|
5
|
+
export namespace FindPresentationsQuery {
|
|
6
|
+
export const RequestSchema = z.object({
|
|
7
|
+
userId: z.string().uuid().optional(),
|
|
8
|
+
unregisteredUserId: z.string().uuid().optional(),
|
|
9
|
+
title: z.string().optional(),
|
|
10
|
+
limit: z.coerce.number().min(1).optional(),
|
|
11
|
+
offset: z.coerce.number().min(0).optional(),
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export type Request = z.infer<typeof RequestSchema>;
|
|
15
|
+
|
|
16
|
+
export const ResponseSchema = ICommandResponseSchema(
|
|
17
|
+
z.object({
|
|
18
|
+
data: z.array(PresentationSchema),
|
|
19
|
+
page: z.number(),
|
|
20
|
+
totalPages: z.number(),
|
|
21
|
+
}),
|
|
22
|
+
);
|
|
23
|
+
export type Response = z.infer<typeof ResponseSchema>;
|
|
24
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ICommandResponseSchema } from '../../common';
|
|
3
|
+
import { PresentationConfigSchema } from '../models';
|
|
4
|
+
|
|
5
|
+
export namespace GetPresentationConfigQuery {
|
|
6
|
+
export const ResponseSchema = ICommandResponseSchema(PresentationConfigSchema);
|
|
7
|
+
export type Response = z.infer<typeof ResponseSchema>;
|
|
8
|
+
}
|