@purpleschool/gptbot-tools 0.0.50 → 0.0.52-presentation

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.
Files changed (29) hide show
  1. package/build/common/errors/errors.js +40 -0
  2. package/build/presentation/commands/build-blank-slide.command.js +15 -0
  3. package/build/presentation/commands/generate-and-insert-slide.command.js +22 -0
  4. package/build/presentation/commands/index.js +4 -0
  5. package/build/presentation/commands/update-presentation-slides.command.js +16 -0
  6. package/build/presentation/commands/update-slide-image-slot.command.js +36 -0
  7. package/build/presentation/enums/index.js +1 -0
  8. package/build/presentation/enums/slide-image-slot-action.enum.js +8 -0
  9. package/build/presentation/models/presentation.schema.js +4 -1
  10. package/build/presentation/models/slide-content-edit.schema.js +135 -0
  11. package/build/presentation/models/slide.schema.js +32 -1
  12. package/build/presentation/routes/presentation.routes.js +4 -0
  13. package/build/tools/enums/tool-type.enum.js +3 -0
  14. package/common/errors/errors.ts +40 -0
  15. package/package.json +1 -1
  16. package/presentation/commands/build-blank-slide.command.ts +15 -0
  17. package/presentation/commands/generate-and-insert-slide.command.ts +22 -0
  18. package/presentation/commands/index.ts +4 -0
  19. package/presentation/commands/update-presentation-slides.command.ts +16 -0
  20. package/presentation/commands/update-slide-image-slot.command.ts +41 -0
  21. package/presentation/enums/index.ts +1 -0
  22. package/presentation/enums/slide-image-slot-action.enum.ts +4 -0
  23. package/presentation/models/presentation.schema.ts +4 -1
  24. package/presentation/models/slide-content-edit.schema.ts +160 -0
  25. package/presentation/models/slide-content.schema.ts +97 -10
  26. package/presentation/models/slide-image-slot.schema.ts +1 -0
  27. package/presentation/models/slide.schema.ts +38 -0
  28. package/presentation/routes/presentation.routes.ts +4 -0
  29. package/tools/enums/tool-type.enum.ts +3 -0
@@ -343,6 +343,46 @@ exports.ERRORS = {
343
343
  message: 'У пользователя недостаточно средств для генерации слайдов',
344
344
  httpCode: 400,
345
345
  },
346
+ CREATE_BLANK_SLIDE_ERROR: {
347
+ code: 'PRESENTATION.CREATE_BLANK_SLIDE_ERROR',
348
+ message: 'Произошла ошибка при создании пустого слайда',
349
+ httpCode: 500,
350
+ },
351
+ INVALID_CONTENT_TYPE_CHANGE: {
352
+ code: 'PRESENTATION.INVALID_CONTENT_TYPE_CHANGE',
353
+ message: 'Невозможно изменить тип существующего слайда',
354
+ httpCode: 400,
355
+ },
356
+ INVALID_SLIDE_POSITION: {
357
+ code: 'PRESENTATION.INVALID_SLIDE_POSITION',
358
+ message: 'Неверная позиция для вставки слайда',
359
+ httpCode: 400,
360
+ },
361
+ SLIDES_UPDATE_ERROR: {
362
+ code: 'PRESENTATION.SLIDES_UPDATE_ERROR',
363
+ message: 'Произошла ошибка при обновлении слайдов презентации',
364
+ httpCode: 500,
365
+ },
366
+ SLIDE_NOT_FOUND: {
367
+ code: 'PRESENTATION.SLIDE_NOT_FOUND',
368
+ message: 'Слайд не найден',
369
+ httpCode: 404,
370
+ },
371
+ SLIDE_IMAGE_SLOT_NOT_FOUND: {
372
+ code: 'PRESENTATION.SLIDE_IMAGE_SLOT_NOT_FOUND',
373
+ message: 'Слот изображения слайда не найден',
374
+ httpCode: 404,
375
+ },
376
+ SLIDE_IMAGE_UPDATE_ERROR: {
377
+ code: 'PRESENTATION.SLIDE_IMAGE_UPDATE_ERROR',
378
+ message: 'Произошла ошибка при обновлении слота изображения слайда',
379
+ httpCode: 500,
380
+ },
381
+ INSUFFICIENT_BALANCE_FOR_IMAGE_GENERATION: {
382
+ code: 'PRESENTATION.INSUFFICIENT_BALANCE_FOR_IMAGE_GENERATION',
383
+ message: 'У пользователя недостаточно средств для генерации изображения',
384
+ httpCode: 400,
385
+ },
346
386
  },
347
387
  SLIDE_OUTLINE: {
348
388
  DELETE_ERROR: {
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BuildBlankSlideCommand = void 0;
4
+ const common_1 = require("../../common");
5
+ const enums_1 = require("../enums");
6
+ const zod_1 = require("zod");
7
+ const models_1 = require("../models");
8
+ var BuildBlankSlideCommand;
9
+ (function (BuildBlankSlideCommand) {
10
+ BuildBlankSlideCommand.RequestSchema = zod_1.z.object({
11
+ slideContentType: zod_1.z.nativeEnum(enums_1.SLIDE_CONTENT_TYPE),
12
+ layoutId: zod_1.z.nativeEnum(enums_1.SLIDE_LAYOUT).optional(),
13
+ });
14
+ BuildBlankSlideCommand.ResponseSchema = (0, common_1.ICommandResponseSchema)(models_1.SlideSchema);
15
+ })(BuildBlankSlideCommand || (exports.BuildBlankSlideCommand = BuildBlankSlideCommand = {}));
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GenerateAndInsertSlideCommand = void 0;
4
+ const zod_1 = require("zod");
5
+ const common_1 = require("../../common");
6
+ const enums_1 = require("../enums");
7
+ const models_1 = require("../models");
8
+ var GenerateAndInsertSlideCommand;
9
+ (function (GenerateAndInsertSlideCommand) {
10
+ GenerateAndInsertSlideCommand.RequestSchema = zod_1.z.object({
11
+ userId: zod_1.z.string().uuid().nullable().optional(),
12
+ unregisteredUserId: zod_1.z.string().uuid().nullable().optional(),
13
+ userBalance: zod_1.z.number(),
14
+ presentationId: zod_1.z.string().uuid(),
15
+ contentTypeId: zod_1.z.nativeEnum(enums_1.SLIDE_CONTENT_TYPE),
16
+ prompt: zod_1.z.string().min(1).max(1000),
17
+ title: zod_1.z.string().max(80),
18
+ position: zod_1.z.number().int().min(0),
19
+ layoutId: zod_1.z.nativeEnum(enums_1.SLIDE_LAYOUT).optional(),
20
+ });
21
+ GenerateAndInsertSlideCommand.ResponseSchema = (0, common_1.ICommandResponseSchema)(models_1.SlideSchema.array());
22
+ })(GenerateAndInsertSlideCommand || (exports.GenerateAndInsertSlideCommand = GenerateAndInsertSlideCommand = {}));
@@ -14,14 +14,18 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./build-blank-slide.command"), exports);
17
18
  __exportStar(require("./create-presentation.command"), exports);
18
19
  __exportStar(require("./delete-all-user-presentations.command"), exports);
19
20
  __exportStar(require("./delete-presentation.command"), exports);
20
21
  __exportStar(require("./delete-slide-outline.command"), exports);
21
22
  __exportStar(require("./generate-presentation-outline.command"), exports);
23
+ __exportStar(require("./generate-and-insert-slide.command"), exports);
22
24
  __exportStar(require("./export-as-pptx.command"), exports);
23
25
  __exportStar(require("./generate-slides.command"), exports);
24
26
  __exportStar(require("./reposition-slide-outline.command"), exports);
25
27
  __exportStar(require("./update-slide-outline.command"), exports);
26
28
  __exportStar(require("./update-presentation.command"), exports);
27
29
  __exportStar(require("./update-presentation-outline.command"), exports);
30
+ __exportStar(require("./update-presentation-slides.command"), exports);
31
+ __exportStar(require("./update-slide-image-slot.command"), exports);
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UpdatePresentationSlidesCommand = void 0;
4
+ const zod_1 = require("zod");
5
+ const models_1 = require("../models");
6
+ const common_1 = require("../../common");
7
+ var UpdatePresentationSlidesCommand;
8
+ (function (UpdatePresentationSlidesCommand) {
9
+ UpdatePresentationSlidesCommand.RequestSchema = zod_1.z.object({
10
+ userId: zod_1.z.string().uuid().nullable().optional(),
11
+ unregisteredUserId: zod_1.z.string().uuid().nullable().optional(),
12
+ presentationId: zod_1.z.string().uuid(),
13
+ data: models_1.SlideBulkUpdateSchema,
14
+ });
15
+ UpdatePresentationSlidesCommand.ResponseSchema = (0, common_1.ICommandResponseSchema)(zod_1.z.array(models_1.SlideSchema));
16
+ })(UpdatePresentationSlidesCommand || (exports.UpdatePresentationSlidesCommand = UpdatePresentationSlidesCommand = {}));
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UpdateSlideImageSlotCommand = void 0;
4
+ const zod_1 = require("zod");
5
+ const common_1 = require("../../common");
6
+ const models_1 = require("../models");
7
+ const enums_1 = require("../enums");
8
+ var UpdateSlideImageSlotCommand;
9
+ (function (UpdateSlideImageSlotCommand) {
10
+ const ReplacePayload = zod_1.z.object({
11
+ action: zod_1.z.literal(enums_1.SLIDE_IMAGE_SLOT_ACTION.REPLACE),
12
+ url: zod_1.z.string().url(),
13
+ });
14
+ const GeneratePayload = zod_1.z.object({
15
+ action: zod_1.z.literal(enums_1.SLIDE_IMAGE_SLOT_ACTION.GENERATE),
16
+ prompt: zod_1.z.string().min(1).max(1000).optional(),
17
+ });
18
+ const UpdateImageSlotPayload = zod_1.z.discriminatedUnion('action', [
19
+ ReplacePayload,
20
+ GeneratePayload,
21
+ ]);
22
+ UpdateSlideImageSlotCommand.RequestSchema = zod_1.z.object({
23
+ userId: zod_1.z.string().uuid().nullable().optional(),
24
+ unregisteredUserId: zod_1.z.string().uuid().nullable().optional(),
25
+ presentationId: zod_1.z.string().uuid(),
26
+ slideId: zod_1.z.string().uuid(),
27
+ slotId: zod_1.z.string().uuid().optional(),
28
+ payload: UpdateImageSlotPayload,
29
+ userBalance: zod_1.z.number(),
30
+ });
31
+ UpdateSlideImageSlotCommand.ResponseSchema = (0, common_1.ICommandResponseSchema)(zod_1.z.object({
32
+ oldImage: zod_1.z.string().url().optional(),
33
+ newImage: zod_1.z.string().url(),
34
+ imageSlot: models_1.SlideImageSlotSchema,
35
+ }));
36
+ })(UpdateSlideImageSlotCommand || (exports.UpdateSlideImageSlotCommand = UpdateSlideImageSlotCommand = {}));
@@ -20,3 +20,4 @@ __exportStar(require("./slide-image-job-status.enum"), exports);
20
20
  __exportStar(require("./slide-image-slot-status.enum"), exports);
21
21
  __exportStar(require("./slide-icon-slot-status.enum"), exports);
22
22
  __exportStar(require("./slide-layout.enum"), exports);
23
+ __exportStar(require("./slide-image-slot-action.enum"), exports);
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SLIDE_IMAGE_SLOT_ACTION = void 0;
4
+ var SLIDE_IMAGE_SLOT_ACTION;
5
+ (function (SLIDE_IMAGE_SLOT_ACTION) {
6
+ SLIDE_IMAGE_SLOT_ACTION["REPLACE"] = "REPLACE";
7
+ SLIDE_IMAGE_SLOT_ACTION["GENERATE"] = "GENERATE";
8
+ })(SLIDE_IMAGE_SLOT_ACTION || (exports.SLIDE_IMAGE_SLOT_ACTION = SLIDE_IMAGE_SLOT_ACTION = {}));
@@ -18,6 +18,8 @@ exports.PresentationSchema = zod_1.z.object({
18
18
  unregisteredUserId: zod_1.z.string().uuid().nullable().optional(),
19
19
  slideCount: zod_1.z.number(),
20
20
  isDeleted: zod_1.z.boolean(),
21
+ lastContentUpdateAt: zod_1.z.date().nullable(),
22
+ lastPptxExportedAt: zod_1.z.date().nullable(),
21
23
  createdAt: zod_1.z.date(),
22
24
  updatedAt: zod_1.z.date(),
23
25
  });
@@ -27,4 +29,5 @@ exports.PresentationWithSlidesSchema = exports.PresentationSchema.extend({
27
29
  });
28
30
  exports.PresentationUpdateSchema = exports.PresentationSchema.pick({
29
31
  title: true,
30
- });
32
+ templateId: true,
33
+ }).partial();
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SlideContentUserEditSchema = exports.ChartSlideDataUserEditSchema = exports.BarChartSlideDataUserEditSchema = exports.TableSlideDataUserEditSchema = exports.SectionBreakSlideDataUserEditSchema = exports.ImageSlideDataUserEditSchema = exports.ContentsSlideDataUserEditSchema = exports.StructuredListSlideDataUserEditSchema = exports.TextSlideDataUserEditSchema = exports.ThankYouSlideDataUserEditSchema = exports.CoverSlideDataUserEditSchema = void 0;
7
+ const zod_1 = __importDefault(require("zod"));
8
+ const enums_1 = require("../enums");
9
+ const slide_content_schema_1 = require("./slide-content.schema");
10
+ exports.CoverSlideDataUserEditSchema = zod_1.default.object({
11
+ contentType: zod_1.default.literal(enums_1.SLIDE_CONTENT_TYPE.COVER),
12
+ title: zod_1.default.string().min(1).max(500),
13
+ author: zod_1.default.object({
14
+ label: zod_1.default.string().min(1).max(100),
15
+ value: zod_1.default.string().min(1).max(200),
16
+ }),
17
+ date: zod_1.default.object({
18
+ label: zod_1.default.string().min(1).max(100),
19
+ value: zod_1.default.string().min(1).max(200),
20
+ }),
21
+ email: zod_1.default.object({
22
+ label: zod_1.default.string().min(1).max(100),
23
+ value: zod_1.default.string().min(1).max(200),
24
+ }),
25
+ version: zod_1.default.literal(1),
26
+ });
27
+ exports.ThankYouSlideDataUserEditSchema = zod_1.default.object({
28
+ contentType: zod_1.default.literal(enums_1.SLIDE_CONTENT_TYPE.THANK_YOU),
29
+ title: zod_1.default.string().min(1).max(500),
30
+ author: zod_1.default.object({
31
+ label: zod_1.default.string().min(1).max(100),
32
+ value: zod_1.default.string().min(1).max(200),
33
+ }),
34
+ date: zod_1.default.object({
35
+ label: zod_1.default.string().min(1).max(100),
36
+ value: zod_1.default.string().min(1).max(200),
37
+ }),
38
+ email: zod_1.default.object({
39
+ label: zod_1.default.string().min(1).max(100),
40
+ value: zod_1.default.string().min(1).max(200),
41
+ }),
42
+ version: zod_1.default.literal(1),
43
+ });
44
+ exports.TextSlideDataUserEditSchema = zod_1.default.object({
45
+ contentType: zod_1.default.literal(enums_1.SLIDE_CONTENT_TYPE.TEXT),
46
+ title: zod_1.default.string().min(1).max(500),
47
+ description: zod_1.default.string().min(1).max(3000),
48
+ version: zod_1.default.literal(1),
49
+ });
50
+ exports.StructuredListSlideDataUserEditSchema = zod_1.default.object({
51
+ contentType: zod_1.default.literal(enums_1.SLIDE_CONTENT_TYPE.STRUCTURED_LIST),
52
+ title: zod_1.default.string().min(1).max(500),
53
+ description: zod_1.default.string().min(1).max(1000),
54
+ list: zod_1.default
55
+ .array(zod_1.default.object({
56
+ title: zod_1.default.string().min(1).max(200),
57
+ description: zod_1.default.string().min(1).max(500),
58
+ }))
59
+ .min(1)
60
+ .max(10),
61
+ version: zod_1.default.literal(1),
62
+ });
63
+ exports.ContentsSlideDataUserEditSchema = zod_1.default.object({
64
+ contentType: zod_1.default.literal(enums_1.SLIDE_CONTENT_TYPE.CONTENTS),
65
+ title: zod_1.default.string().min(1).max(500),
66
+ items: zod_1.default
67
+ .array(zod_1.default.object({
68
+ pageNumber: zod_1.default.number(),
69
+ title: zod_1.default.string().min(1).max(500),
70
+ }))
71
+ .min(1)
72
+ .max(50),
73
+ version: zod_1.default.literal(1),
74
+ });
75
+ exports.ImageSlideDataUserEditSchema = zod_1.default.object({
76
+ contentType: zod_1.default.literal(enums_1.SLIDE_CONTENT_TYPE.TEXT_WITH_IMAGE),
77
+ title: zod_1.default.string().min(1).max(500),
78
+ description: zod_1.default.string().min(1).max(2000),
79
+ imageSlot: slide_content_schema_1.ImageSlotSchema,
80
+ version: zod_1.default.literal(1),
81
+ });
82
+ exports.SectionBreakSlideDataUserEditSchema = zod_1.default.object({
83
+ contentType: zod_1.default.literal(enums_1.SLIDE_CONTENT_TYPE.SECTION_BREAK),
84
+ title: zod_1.default.string().min(1).max(500),
85
+ description: zod_1.default.string().min(1).max(500),
86
+ version: zod_1.default.literal(1),
87
+ });
88
+ exports.TableSlideDataUserEditSchema = zod_1.default.object({
89
+ contentType: zod_1.default.literal(enums_1.SLIDE_CONTENT_TYPE.TABLE),
90
+ title: zod_1.default.string().min(1).max(500),
91
+ description: zod_1.default.string().min(1).max(1000),
92
+ table: zod_1.default.object({
93
+ columnHeaders: zod_1.default.array(zod_1.default.string().min(1).max(200)).min(1).max(20),
94
+ rows: zod_1.default
95
+ .array(zod_1.default.array(zod_1.default.string().min(1).max(500)))
96
+ .min(1)
97
+ .max(20),
98
+ hasRowHeaders: zod_1.default.boolean(),
99
+ hasSummaryRow: zod_1.default.boolean(),
100
+ }),
101
+ version: zod_1.default.literal(1),
102
+ });
103
+ exports.BarChartSlideDataUserEditSchema = zod_1.default.object({
104
+ type: zod_1.default.literal(slide_content_schema_1.SLIDE_CHART_TYPE.BAR),
105
+ categories: zod_1.default.array(zod_1.default.string().min(1).max(200)).min(1).max(50),
106
+ series: zod_1.default
107
+ .array(zod_1.default.object({
108
+ name: zod_1.default.string().min(1).max(200),
109
+ data: zod_1.default.array(zod_1.default.number()),
110
+ type: zod_1.default.number().min(0).max(11),
111
+ }))
112
+ .min(1)
113
+ .max(5),
114
+ yAxisLabel: zod_1.default.string().max(200).optional(),
115
+ unit: zod_1.default.string().max(50).optional(),
116
+ version: zod_1.default.literal(1),
117
+ });
118
+ exports.ChartSlideDataUserEditSchema = zod_1.default.object({
119
+ contentType: zod_1.default.literal(enums_1.SLIDE_CONTENT_TYPE.CHART),
120
+ title: zod_1.default.string().min(1).max(500),
121
+ description: zod_1.default.string().min(1).max(2000),
122
+ chart: zod_1.default.discriminatedUnion('type', [exports.BarChartSlideDataUserEditSchema]),
123
+ version: zod_1.default.literal(1),
124
+ });
125
+ exports.SlideContentUserEditSchema = zod_1.default.discriminatedUnion('contentType', [
126
+ exports.CoverSlideDataUserEditSchema,
127
+ exports.StructuredListSlideDataUserEditSchema,
128
+ exports.TextSlideDataUserEditSchema,
129
+ exports.ContentsSlideDataUserEditSchema,
130
+ exports.SectionBreakSlideDataUserEditSchema,
131
+ exports.ImageSlideDataUserEditSchema,
132
+ exports.ThankYouSlideDataUserEditSchema,
133
+ exports.TableSlideDataUserEditSchema,
134
+ exports.ChartSlideDataUserEditSchema,
135
+ ]);
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SlideSchema = void 0;
3
+ exports.SlideBulkUpdateSchema = exports.SlideSchema = void 0;
4
4
  const zod_1 = require("zod");
5
5
  const slide_content_schema_1 = require("./slide-content.schema");
6
6
  const enums_1 = require("../enums");
7
7
  const slide_icon_slot_schema_1 = require("./slide-icon-slot.schema");
8
8
  const slide_image_slot_schema_1 = require("./slide-image-slot.schema");
9
+ const slide_content_edit_schema_1 = require("./slide-content-edit.schema");
9
10
  exports.SlideSchema = zod_1.z.object({
10
11
  uuid: zod_1.z.string().uuid(),
11
12
  order: zod_1.z.number(),
@@ -18,3 +19,33 @@ exports.SlideSchema = zod_1.z.object({
18
19
  createdAt: zod_1.z.date(),
19
20
  updatedAt: zod_1.z.date(),
20
21
  });
22
+ exports.SlideBulkUpdateSchema = exports.SlideSchema.pick({
23
+ order: true,
24
+ contentTypeId: true,
25
+ layoutId: true,
26
+ presentationId: true,
27
+ })
28
+ .extend({
29
+ uuid: zod_1.z.string().uuid().optional(),
30
+ content: slide_content_edit_schema_1.SlideContentUserEditSchema,
31
+ })
32
+ .array()
33
+ .min(1, 'Must include at least one slide')
34
+ .refine((arr) => {
35
+ const orders = arr.map((s) => s.order);
36
+ const unique = new Set(orders);
37
+ if (unique.size !== orders.length)
38
+ return false;
39
+ const sorted = [...orders].sort((a, b) => a - b);
40
+ return sorted.every((val, idx) => val === idx);
41
+ }, {
42
+ message: 'Slide orders must be unique and sequential starting at 0',
43
+ path: ['order'],
44
+ })
45
+ .refine((arr) => {
46
+ const [firstId, ...rest] = arr.map((s) => s.presentationId);
47
+ return rest.every((id) => id === firstId);
48
+ }, {
49
+ message: 'All slides must belong to the same presentation',
50
+ path: ['presentationId'],
51
+ });
@@ -7,6 +7,7 @@ exports.PRESENTATION_AMQP_ROUTES = {
7
7
  FIND_BY_UUID: 'tools.presentation.find-by-uuid.rpc',
8
8
  GENERATE_PRESENTATION_OUTLINE: 'tools.presentation.generate-outline.rpc',
9
9
  GENERATE_PRESENTATION_SLIDES: 'tools.presentation.generate-slides.rpc',
10
+ GENERATE_AND_INSERT_SLIDE: 'tools.presentation.generate-and-insert-slide.rpc',
10
11
  UPDATE_PRESENTATION_OUTLINE: 'tools.presentation.update-presentation-outline.rpc',
11
12
  LIST_PRESENTATIONS: 'tools.presentation.list-presentations.rpc',
12
13
  DELETE_PRESENTATION: 'tools.presentation.delete-presentation.rpc',
@@ -14,6 +15,9 @@ exports.PRESENTATION_AMQP_ROUTES = {
14
15
  EXPORT_AS_PPTX: 'tools.presentation.export-as-pptx.rpc',
15
16
  UPDATE_PRESENTATION: 'tools.presentation.update-presentation.rpc',
16
17
  DELETE_ALL_USER_PRESENTATIONS: 'tools.presentation.delete-all-user-presentations.rpc',
18
+ BUILD_BLANK_SLIDE: 'tools.presentation.build-blank-slide.rpc',
19
+ UPDATE_PRESENTATION_SLIDES: 'tools.presentation.update-presentation-slides.rpc',
20
+ UPDATE_SLIDE_IMAGE_SLOT: 'tools.presentation.update-slide-image-slot.rpc',
17
21
  };
18
22
  exports.PRESENTATION_SLIDE_OUTLINE_AMQP_ROUTES = {
19
23
  REPOSITION: 'tools.presentation.slide-outline.reposition-slide-outline.rpc',
@@ -8,4 +8,7 @@ var TOOL_TYPE;
8
8
  TOOL_TYPE["VIDEO"] = "VIDEO";
9
9
  TOOL_TYPE["AUDIO"] = "AUDIO";
10
10
  TOOL_TYPE["PRESENTATION"] = "PRESENTATION";
11
+ TOOL_TYPE["PRESENTATION_AI_ACTION"] = "PRESENTATION_AI_ACTION";
12
+ TOOL_TYPE["WRITER"] = "WRITER";
13
+ TOOL_TYPE["PARAPHRASE"] = "PARAPHRASE";
11
14
  })(TOOL_TYPE || (exports.TOOL_TYPE = TOOL_TYPE = {}));
@@ -342,6 +342,46 @@ export const ERRORS = {
342
342
  message: 'У пользователя недостаточно средств для генерации слайдов',
343
343
  httpCode: 400,
344
344
  },
345
+ CREATE_BLANK_SLIDE_ERROR: {
346
+ code: 'PRESENTATION.CREATE_BLANK_SLIDE_ERROR',
347
+ message: 'Произошла ошибка при создании пустого слайда',
348
+ httpCode: 500,
349
+ },
350
+ INVALID_CONTENT_TYPE_CHANGE: {
351
+ code: 'PRESENTATION.INVALID_CONTENT_TYPE_CHANGE',
352
+ message: 'Невозможно изменить тип существующего слайда',
353
+ httpCode: 400,
354
+ },
355
+ INVALID_SLIDE_POSITION: {
356
+ code: 'PRESENTATION.INVALID_SLIDE_POSITION',
357
+ message: 'Неверная позиция для вставки слайда',
358
+ httpCode: 400,
359
+ },
360
+ SLIDES_UPDATE_ERROR: {
361
+ code: 'PRESENTATION.SLIDES_UPDATE_ERROR',
362
+ message: 'Произошла ошибка при обновлении слайдов презентации',
363
+ httpCode: 500,
364
+ },
365
+ SLIDE_NOT_FOUND: {
366
+ code: 'PRESENTATION.SLIDE_NOT_FOUND',
367
+ message: 'Слайд не найден',
368
+ httpCode: 404,
369
+ },
370
+ SLIDE_IMAGE_SLOT_NOT_FOUND: {
371
+ code: 'PRESENTATION.SLIDE_IMAGE_SLOT_NOT_FOUND',
372
+ message: 'Слот изображения слайда не найден',
373
+ httpCode: 404,
374
+ },
375
+ SLIDE_IMAGE_UPDATE_ERROR: {
376
+ code: 'PRESENTATION.SLIDE_IMAGE_UPDATE_ERROR',
377
+ message: 'Произошла ошибка при обновлении слота изображения слайда',
378
+ httpCode: 500,
379
+ },
380
+ INSUFFICIENT_BALANCE_FOR_IMAGE_GENERATION: {
381
+ code: 'PRESENTATION.INSUFFICIENT_BALANCE_FOR_IMAGE_GENERATION',
382
+ message: 'У пользователя недостаточно средств для генерации изображения',
383
+ httpCode: 400,
384
+ },
345
385
  },
346
386
  SLIDE_OUTLINE: {
347
387
  DELETE_ERROR: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@purpleschool/gptbot-tools",
3
- "version": "0.0.50",
3
+ "version": "0.0.52-presentation",
4
4
  "main": "build/index.js",
5
5
  "types": "build/index.d.ts",
6
6
  "scripts": {
@@ -0,0 +1,15 @@
1
+ import { ICommandResponseSchema } from '../../common';
2
+ import { SLIDE_CONTENT_TYPE, SLIDE_LAYOUT } from '../enums';
3
+ import { z } from 'zod';
4
+ import { SlideSchema } from '../models';
5
+
6
+ export namespace BuildBlankSlideCommand {
7
+ export const RequestSchema = z.object({
8
+ slideContentType: z.nativeEnum(SLIDE_CONTENT_TYPE),
9
+ layoutId: z.nativeEnum(SLIDE_LAYOUT).optional(),
10
+ });
11
+ export type Request = z.infer<typeof RequestSchema>;
12
+
13
+ export const ResponseSchema = ICommandResponseSchema(SlideSchema);
14
+ export type Response = z.infer<typeof ResponseSchema>;
15
+ }
@@ -0,0 +1,22 @@
1
+ import { z } from 'zod';
2
+ import { ICommandResponseSchema } from '../../common';
3
+ import { SLIDE_CONTENT_TYPE, SLIDE_LAYOUT } from '../enums';
4
+ import { SlideSchema } from '../models';
5
+
6
+ export namespace GenerateAndInsertSlideCommand {
7
+ export const RequestSchema = z.object({
8
+ userId: z.string().uuid().nullable().optional(),
9
+ unregisteredUserId: z.string().uuid().nullable().optional(),
10
+ userBalance: z.number(),
11
+ presentationId: z.string().uuid(),
12
+ contentTypeId: z.nativeEnum(SLIDE_CONTENT_TYPE),
13
+ prompt: z.string().min(1).max(1000),
14
+ title: z.string().max(80),
15
+ position: z.number().int().min(0),
16
+ layoutId: z.nativeEnum(SLIDE_LAYOUT).optional(),
17
+ });
18
+ export type Request = z.infer<typeof RequestSchema>;
19
+
20
+ export const ResponseSchema = ICommandResponseSchema(SlideSchema.array());
21
+ export type Response = z.infer<typeof ResponseSchema>;
22
+ }
@@ -1,11 +1,15 @@
1
+ export * from './build-blank-slide.command';
1
2
  export * from './create-presentation.command';
2
3
  export * from './delete-all-user-presentations.command';
3
4
  export * from './delete-presentation.command';
4
5
  export * from './delete-slide-outline.command';
5
6
  export * from './generate-presentation-outline.command';
7
+ export * from './generate-and-insert-slide.command';
6
8
  export * from './export-as-pptx.command';
7
9
  export * from './generate-slides.command';
8
10
  export * from './reposition-slide-outline.command';
9
11
  export * from './update-slide-outline.command';
10
12
  export * from './update-presentation.command';
11
13
  export * from './update-presentation-outline.command';
14
+ export * from './update-presentation-slides.command';
15
+ export * from './update-slide-image-slot.command';
@@ -0,0 +1,16 @@
1
+ import { z } from 'zod';
2
+ import { SlideSchema, SlideBulkUpdateSchema } from '../models';
3
+ import { ICommandResponseSchema } from '../../common';
4
+
5
+ export namespace UpdatePresentationSlidesCommand {
6
+ export const RequestSchema = z.object({
7
+ userId: z.string().uuid().nullable().optional(),
8
+ unregisteredUserId: z.string().uuid().nullable().optional(),
9
+ presentationId: z.string().uuid(),
10
+ data: SlideBulkUpdateSchema,
11
+ });
12
+ export type Request = z.infer<typeof RequestSchema>;
13
+
14
+ export const ResponseSchema = ICommandResponseSchema(z.array(SlideSchema));
15
+ export type Response = z.infer<typeof ResponseSchema>;
16
+ }
@@ -0,0 +1,41 @@
1
+ import { z } from 'zod';
2
+ import { ICommandResponseSchema } from '../../common';
3
+ import { SlideImageSlotSchema } from '../models';
4
+ import { SLIDE_IMAGE_SLOT_ACTION } from '../enums';
5
+
6
+ export namespace UpdateSlideImageSlotCommand {
7
+ const ReplacePayload = z.object({
8
+ action: z.literal(SLIDE_IMAGE_SLOT_ACTION.REPLACE),
9
+ url: z.string().url(),
10
+ });
11
+
12
+ const GeneratePayload = z.object({
13
+ action: z.literal(SLIDE_IMAGE_SLOT_ACTION.GENERATE),
14
+ prompt: z.string().min(1).max(1000).optional(),
15
+ });
16
+
17
+ const UpdateImageSlotPayload = z.discriminatedUnion('action', [
18
+ ReplacePayload,
19
+ GeneratePayload,
20
+ ]);
21
+
22
+ export const RequestSchema = z.object({
23
+ userId: z.string().uuid().nullable().optional(),
24
+ unregisteredUserId: z.string().uuid().nullable().optional(),
25
+ presentationId: z.string().uuid(),
26
+ slideId: z.string().uuid(),
27
+ slotId: z.string().uuid().optional(),
28
+ payload: UpdateImageSlotPayload,
29
+ userBalance: z.number(),
30
+ });
31
+ export type Request = z.infer<typeof RequestSchema>;
32
+
33
+ export const ResponseSchema = ICommandResponseSchema(
34
+ z.object({
35
+ oldImage: z.string().url().optional(),
36
+ newImage: z.string().url(),
37
+ imageSlot: SlideImageSlotSchema,
38
+ }),
39
+ );
40
+ export type Response = z.infer<typeof ResponseSchema>;
41
+ }
@@ -4,3 +4,4 @@ export * from './slide-image-job-status.enum';
4
4
  export * from './slide-image-slot-status.enum';
5
5
  export * from './slide-icon-slot-status.enum';
6
6
  export * from './slide-layout.enum';
7
+ export * from './slide-image-slot-action.enum';
@@ -0,0 +1,4 @@
1
+ export enum SLIDE_IMAGE_SLOT_ACTION {
2
+ REPLACE = 'REPLACE',
3
+ GENERATE = 'GENERATE',
4
+ }
@@ -16,6 +16,8 @@ export const PresentationSchema = z.object({
16
16
  unregisteredUserId: z.string().uuid().nullable().optional(),
17
17
  slideCount: z.number(),
18
18
  isDeleted: z.boolean(),
19
+ lastContentUpdateAt: z.date().nullable(),
20
+ lastPptxExportedAt: z.date().nullable(),
19
21
  createdAt: z.date(),
20
22
  updatedAt: z.date(),
21
23
  });
@@ -29,5 +31,6 @@ export type PresentationWithSlides = z.infer<typeof PresentationWithSlidesSchema
29
31
 
30
32
  export const PresentationUpdateSchema = PresentationSchema.pick({
31
33
  title: true,
32
- });
34
+ templateId: true,
35
+ }).partial();
33
36
  export type PresentationUpdate = z.infer<typeof PresentationUpdateSchema>;
@@ -0,0 +1,160 @@
1
+ import z from 'zod';
2
+ import { SLIDE_CONTENT_TYPE } from '../enums';
3
+ import {
4
+ ICoverSlideDataStructure,
5
+ IThankYouSlideDataStructure,
6
+ ITextSlideDataStructure,
7
+ IStructuredListSlideDataStructure,
8
+ IContentsSlideDataStructure,
9
+ IImageSlideDataStructure,
10
+ ISectionBreakSlideDataStructure,
11
+ ITableSlideDataStructure,
12
+ SLIDE_CHART_TYPE,
13
+ IBarChartSlideDataStructure,
14
+ IChartSlideDataStructure,
15
+ ImageSlotSchema,
16
+ } from './slide-content.schema';
17
+
18
+ export const CoverSlideDataUserEditSchema = z.object({
19
+ contentType: z.literal(SLIDE_CONTENT_TYPE.COVER),
20
+ title: z.string().min(1).max(500),
21
+ author: z.object({
22
+ label: z.string().min(1).max(100),
23
+ value: z.string().min(1).max(200),
24
+ }),
25
+ date: z.object({
26
+ label: z.string().min(1).max(100),
27
+ value: z.string().min(1).max(200),
28
+ }),
29
+ email: z.object({
30
+ label: z.string().min(1).max(100),
31
+ value: z.string().min(1).max(200),
32
+ }),
33
+ version: z.literal(1),
34
+ }) satisfies z.ZodType<ICoverSlideDataStructure>;
35
+
36
+ export const ThankYouSlideDataUserEditSchema = z.object({
37
+ contentType: z.literal(SLIDE_CONTENT_TYPE.THANK_YOU),
38
+ title: z.string().min(1).max(500),
39
+ author: z.object({
40
+ label: z.string().min(1).max(100),
41
+ value: z.string().min(1).max(200),
42
+ }),
43
+ date: z.object({
44
+ label: z.string().min(1).max(100),
45
+ value: z.string().min(1).max(200),
46
+ }),
47
+ email: z.object({
48
+ label: z.string().min(1).max(100),
49
+ value: z.string().min(1).max(200),
50
+ }),
51
+ version: z.literal(1),
52
+ }) satisfies z.ZodType<IThankYouSlideDataStructure>;
53
+
54
+ export const TextSlideDataUserEditSchema = z.object({
55
+ contentType: z.literal(SLIDE_CONTENT_TYPE.TEXT),
56
+ title: z.string().min(1).max(500),
57
+ description: z.string().min(1).max(3000),
58
+ version: z.literal(1),
59
+ }) satisfies z.ZodType<ITextSlideDataStructure>;
60
+
61
+ export const StructuredListSlideDataUserEditSchema = z.object({
62
+ contentType: z.literal(SLIDE_CONTENT_TYPE.STRUCTURED_LIST),
63
+ title: z.string().min(1).max(500),
64
+ description: z.string().min(1).max(1000),
65
+ list: z
66
+ .array(
67
+ z.object({
68
+ title: z.string().min(1).max(200),
69
+ description: z.string().min(1).max(500),
70
+ }),
71
+ )
72
+ .min(1)
73
+ .max(10),
74
+ version: z.literal(1),
75
+ }) satisfies z.ZodType<IStructuredListSlideDataStructure>;
76
+
77
+ export const ContentsSlideDataUserEditSchema = z.object({
78
+ contentType: z.literal(SLIDE_CONTENT_TYPE.CONTENTS),
79
+ title: z.string().min(1).max(500),
80
+ items: z
81
+ .array(
82
+ z.object({
83
+ pageNumber: z.number(),
84
+ title: z.string().min(1).max(500),
85
+ }),
86
+ )
87
+ .min(1)
88
+ .max(50),
89
+ version: z.literal(1),
90
+ }) satisfies z.ZodType<IContentsSlideDataStructure>;
91
+
92
+ export const ImageSlideDataUserEditSchema = z.object({
93
+ contentType: z.literal(SLIDE_CONTENT_TYPE.TEXT_WITH_IMAGE),
94
+ title: z.string().min(1).max(500),
95
+ description: z.string().min(1).max(2000),
96
+ imageSlot: ImageSlotSchema,
97
+ version: z.literal(1),
98
+ }) satisfies z.ZodType<IImageSlideDataStructure>;
99
+
100
+ export const SectionBreakSlideDataUserEditSchema = z.object({
101
+ contentType: z.literal(SLIDE_CONTENT_TYPE.SECTION_BREAK),
102
+ title: z.string().min(1).max(500),
103
+ description: z.string().min(1).max(500),
104
+ version: z.literal(1),
105
+ }) satisfies z.ZodType<ISectionBreakSlideDataStructure>;
106
+
107
+ export const TableSlideDataUserEditSchema = z.object({
108
+ contentType: z.literal(SLIDE_CONTENT_TYPE.TABLE),
109
+ title: z.string().min(1).max(500),
110
+ description: z.string().min(1).max(1000),
111
+ table: z.object({
112
+ columnHeaders: z.array(z.string().min(1).max(200)).min(1).max(20),
113
+ rows: z
114
+ .array(z.array(z.string().min(1).max(500)))
115
+ .min(1)
116
+ .max(20),
117
+ hasRowHeaders: z.boolean(),
118
+ hasSummaryRow: z.boolean(),
119
+ }),
120
+ version: z.literal(1),
121
+ }) satisfies z.ZodType<ITableSlideDataStructure>;
122
+
123
+ export const BarChartSlideDataUserEditSchema = z.object({
124
+ type: z.literal(SLIDE_CHART_TYPE.BAR),
125
+ categories: z.array(z.string().min(1).max(200)).min(1).max(50),
126
+ series: z
127
+ .array(
128
+ z.object({
129
+ name: z.string().min(1).max(200),
130
+ data: z.array(z.number()),
131
+ type: z.number().min(0).max(11),
132
+ }),
133
+ )
134
+ .min(1)
135
+ .max(5),
136
+ yAxisLabel: z.string().max(200).optional(),
137
+ unit: z.string().max(50).optional(),
138
+ version: z.literal(1),
139
+ }) satisfies z.ZodType<IBarChartSlideDataStructure>;
140
+
141
+ export const ChartSlideDataUserEditSchema = z.object({
142
+ contentType: z.literal(SLIDE_CONTENT_TYPE.CHART),
143
+ title: z.string().min(1).max(500),
144
+ description: z.string().min(1).max(2000),
145
+ chart: z.discriminatedUnion('type', [BarChartSlideDataUserEditSchema]),
146
+ version: z.literal(1),
147
+ }) satisfies z.ZodType<IChartSlideDataStructure>;
148
+
149
+ export const SlideContentUserEditSchema = z.discriminatedUnion('contentType', [
150
+ CoverSlideDataUserEditSchema,
151
+ StructuredListSlideDataUserEditSchema,
152
+ TextSlideDataUserEditSchema,
153
+ ContentsSlideDataUserEditSchema,
154
+ SectionBreakSlideDataUserEditSchema,
155
+ ImageSlideDataUserEditSchema,
156
+ ThankYouSlideDataUserEditSchema,
157
+ TableSlideDataUserEditSchema,
158
+ ChartSlideDataUserEditSchema,
159
+ ]);
160
+ export type SlideContentUserEdit = z.infer<typeof SlideContentUserEditSchema>;
@@ -23,6 +23,91 @@ export const IconSlotSchema = z.object({
23
23
  });
24
24
  export type IconSlot = z.infer<typeof IconSlotSchema>;
25
25
 
26
+ export interface ICoverSlideDataStructure {
27
+ contentType: SLIDE_CONTENT_TYPE.COVER;
28
+ title: string;
29
+ author: { label: string; value: string };
30
+ date: { label: string; value: string };
31
+ email: { label: string; value: string };
32
+ version: 1;
33
+ }
34
+
35
+ export interface IThankYouSlideDataStructure {
36
+ contentType: SLIDE_CONTENT_TYPE.THANK_YOU;
37
+ title: string;
38
+ author: { label: string; value: string };
39
+ date: { label: string; value: string };
40
+ email: { label: string; value: string };
41
+ version: 1;
42
+ }
43
+
44
+ export interface ITextSlideDataStructure {
45
+ contentType: SLIDE_CONTENT_TYPE.TEXT;
46
+ title: string;
47
+ description: string;
48
+ version: 1;
49
+ }
50
+
51
+ export interface IStructuredListSlideDataStructure {
52
+ contentType: SLIDE_CONTENT_TYPE.STRUCTURED_LIST;
53
+ title: string;
54
+ description: string;
55
+ list: Array<{ title: string; description: string }>;
56
+ version: 1;
57
+ }
58
+
59
+ export interface IContentsSlideDataStructure {
60
+ contentType: SLIDE_CONTENT_TYPE.CONTENTS;
61
+ title: string;
62
+ items: Array<{ pageNumber: number; title: string }>;
63
+ version: 1;
64
+ }
65
+
66
+ export interface IImageSlideDataStructure {
67
+ contentType: SLIDE_CONTENT_TYPE.TEXT_WITH_IMAGE;
68
+ title: string;
69
+ description: string;
70
+ imageSlot?: ImageSlot;
71
+ version: 1;
72
+ }
73
+
74
+ export interface ISectionBreakSlideDataStructure {
75
+ contentType: SLIDE_CONTENT_TYPE.SECTION_BREAK;
76
+ title: string;
77
+ description: string;
78
+ version: 1;
79
+ }
80
+
81
+ export interface ITableSlideDataStructure {
82
+ contentType: SLIDE_CONTENT_TYPE.TABLE;
83
+ title: string;
84
+ description: string;
85
+ table: {
86
+ columnHeaders: string[];
87
+ rows: string[][];
88
+ hasRowHeaders: boolean;
89
+ hasSummaryRow: boolean;
90
+ };
91
+ version: 1;
92
+ }
93
+
94
+ export interface IBarChartSlideDataStructure {
95
+ type: SLIDE_CHART_TYPE.BAR;
96
+ categories: string[];
97
+ series: Array<{ name: string; data: number[]; type: number }>;
98
+ yAxisLabel?: string;
99
+ unit?: string;
100
+ version: 1;
101
+ }
102
+
103
+ export interface IChartSlideDataStructure {
104
+ contentType: SLIDE_CONTENT_TYPE.CHART;
105
+ title: string;
106
+ description: string;
107
+ chart: IBarChartSlideDataStructure;
108
+ version: 1;
109
+ }
110
+
26
111
  export const CoverSlideDataSchema = z.object({
27
112
  contentType: z.literal(SLIDE_CONTENT_TYPE.COVER),
28
113
  title: z.string().describe('Slide title in about 6 words').min(10).max(150),
@@ -45,7 +130,7 @@ export const CoverSlideDataSchema = z.object({
45
130
  value: z.string().describe('Just default "email@example.com"'),
46
131
  }),
47
132
  version: z.literal(1),
48
- });
133
+ }) satisfies z.ZodType<ICoverSlideDataStructure>;
49
134
  export type CoverSlideData = z.infer<typeof CoverSlideDataSchema>;
50
135
 
51
136
  export const ThankYouSlideDataSchema = z.object({
@@ -72,7 +157,7 @@ export const ThankYouSlideDataSchema = z.object({
72
157
  value: z.string().describe('Just default "email@example.com"'),
73
158
  }),
74
159
  version: z.literal(1),
75
- });
160
+ }) satisfies z.ZodType<IThankYouSlideDataStructure>;
76
161
  export type ThankYouSlideData = z.infer<typeof ThankYouSlideDataSchema>;
77
162
 
78
163
  export const StructuredListSlideDataSchema = z.object({
@@ -88,7 +173,7 @@ export const StructuredListSlideDataSchema = z.object({
88
173
  )
89
174
  .length(4),
90
175
  version: z.literal(1),
91
- });
176
+ }) satisfies z.ZodType<IStructuredListSlideDataStructure>;
92
177
  export type StructuredListSlideData = z.infer<typeof StructuredListSlideDataSchema>;
93
178
 
94
179
  export const TextSlideDataSchema = z.object({
@@ -102,7 +187,7 @@ export const TextSlideDataSchema = z.object({
102
187
  .min(300)
103
188
  .max(600),
104
189
  version: z.literal(1),
105
- });
190
+ }) satisfies z.ZodType<ITextSlideDataStructure>;
106
191
  export type TextSlideData = z.infer<typeof TextSlideDataSchema>;
107
192
 
108
193
  export const ContentsSlideDataSchema = z.object({
@@ -126,7 +211,7 @@ export const ContentsSlideDataSchema = z.object({
126
211
  'List of slide titles. Must be relevant and generated after all the slides are generated',
127
212
  ),
128
213
  version: z.literal(1),
129
- });
214
+ }) satisfies z.ZodType<IContentsSlideDataStructure>;
130
215
  export type ContentsSlideData = z.infer<typeof ContentsSlideDataSchema>;
131
216
 
132
217
  export const ImageSlideDataSchema = z
@@ -141,7 +226,9 @@ export const ImageSlideDataSchema = z
141
226
  imageSlot: ImageSlotSchema,
142
227
  version: z.literal(1),
143
228
  })
144
- .describe('Slide that contains a title, description of the title');
229
+ .describe(
230
+ 'Slide that contains a title, description of the title',
231
+ ) satisfies z.ZodType<IImageSlideDataStructure>;
145
232
  export type ImageSlideData = z.infer<typeof ImageSlideDataSchema>;
146
233
 
147
234
  export const SectionBreakSlideDataSchema = z.object({
@@ -149,7 +236,7 @@ export const SectionBreakSlideDataSchema = z.object({
149
236
  title: z.string().describe('Slide title in about 6 words').min(10).max(200),
150
237
  description: z.string().describe('Description of the slide in about 6 words').min(10).max(200),
151
238
  version: z.literal(1),
152
- });
239
+ }) satisfies z.ZodType<ISectionBreakSlideDataStructure>;
153
240
  export type SectionBreakSlideData = z.infer<typeof SectionBreakSlideDataSchema>;
154
241
 
155
242
  export const TableSlideDataSchema = z.object({
@@ -177,7 +264,7 @@ export const TableSlideDataSchema = z.object({
177
264
  hasSummaryRow: z.boolean().describe('If table needs a summary row, set this to true'),
178
265
  }),
179
266
  version: z.literal(1),
180
- });
267
+ }) satisfies z.ZodType<ITableSlideDataStructure>;
181
268
  export type TableSlideData = z.infer<typeof TableSlideDataSchema>;
182
269
 
183
270
  // Charts
@@ -208,7 +295,7 @@ export const BarChartSlideDataSchema = z.object({
208
295
  yAxisLabel: z.string().max(40).optional().describe('Y-axis label'),
209
296
  unit: z.string().max(10).optional().describe('Unit symbol (%, $, etc.)'),
210
297
  version: z.literal(1),
211
- });
298
+ }) satisfies z.ZodType<IBarChartSlideDataStructure>;
212
299
  export type BarChartSlideData = z.infer<typeof BarChartSlideDataSchema>;
213
300
 
214
301
  export const ChartSlideDataSchema = z.object({
@@ -217,7 +304,7 @@ export const ChartSlideDataSchema = z.object({
217
304
  description: z.string().describe("Information on slide's topic").max(600),
218
305
  chart: z.discriminatedUnion('type', [BarChartSlideDataSchema]),
219
306
  version: z.literal(1),
220
- });
307
+ }) satisfies z.ZodType<IChartSlideDataStructure>;
221
308
  export type ChartSlideData = z.infer<typeof ChartSlideDataSchema>;
222
309
 
223
310
  export const SlideContentSchema = z.discriminatedUnion('contentType', [
@@ -12,3 +12,4 @@ export const SlideImageSlotSchema = z.object({
12
12
  createdAt: z.date(),
13
13
  updatedAt: z.date(),
14
14
  });
15
+ export type SlideImageSlot = z.infer<typeof SlideImageSlotSchema>;
@@ -3,6 +3,7 @@ import { SlideContentSchema } from './slide-content.schema';
3
3
  import { SLIDE_CONTENT_TYPE, SLIDE_LAYOUT } from '../enums';
4
4
  import { SlideIconSlotSchema } from './slide-icon-slot.schema';
5
5
  import { SlideImageSlotSchema } from './slide-image-slot.schema';
6
+ import { SlideContentUserEditSchema } from './slide-content-edit.schema';
6
7
 
7
8
  export const SlideSchema = z.object({
8
9
  uuid: z.string().uuid(),
@@ -17,3 +18,40 @@ export const SlideSchema = z.object({
17
18
  updatedAt: z.date(),
18
19
  });
19
20
  export type Slide = z.infer<typeof SlideSchema>;
21
+
22
+ export const SlideBulkUpdateSchema = SlideSchema.pick({
23
+ order: true,
24
+ contentTypeId: true,
25
+ layoutId: true,
26
+ presentationId: true,
27
+ })
28
+ .extend({
29
+ uuid: z.string().uuid().optional(),
30
+ content: SlideContentUserEditSchema,
31
+ })
32
+ .array()
33
+ .min(1, 'Must include at least one slide')
34
+ .refine(
35
+ (arr) => {
36
+ const orders = arr.map((s) => s.order);
37
+ const unique = new Set(orders);
38
+ if (unique.size !== orders.length) return false;
39
+ const sorted = [...orders].sort((a, b) => a - b);
40
+ return sorted.every((val, idx) => val === idx);
41
+ },
42
+ {
43
+ message: 'Slide orders must be unique and sequential starting at 0',
44
+ path: ['order'],
45
+ },
46
+ )
47
+ .refine(
48
+ (arr) => {
49
+ const [firstId, ...rest] = arr.map((s) => s.presentationId);
50
+ return rest.every((id) => id === firstId);
51
+ },
52
+ {
53
+ message: 'All slides must belong to the same presentation',
54
+ path: ['presentationId'],
55
+ },
56
+ );
57
+ export type SlideBulkUpdate = z.infer<typeof SlideBulkUpdateSchema>;
@@ -4,6 +4,7 @@ export const PRESENTATION_AMQP_ROUTES = {
4
4
  FIND_BY_UUID: 'tools.presentation.find-by-uuid.rpc',
5
5
  GENERATE_PRESENTATION_OUTLINE: 'tools.presentation.generate-outline.rpc',
6
6
  GENERATE_PRESENTATION_SLIDES: 'tools.presentation.generate-slides.rpc',
7
+ GENERATE_AND_INSERT_SLIDE: 'tools.presentation.generate-and-insert-slide.rpc',
7
8
  UPDATE_PRESENTATION_OUTLINE: 'tools.presentation.update-presentation-outline.rpc',
8
9
  LIST_PRESENTATIONS: 'tools.presentation.list-presentations.rpc',
9
10
  DELETE_PRESENTATION: 'tools.presentation.delete-presentation.rpc',
@@ -11,6 +12,9 @@ export const PRESENTATION_AMQP_ROUTES = {
11
12
  EXPORT_AS_PPTX: 'tools.presentation.export-as-pptx.rpc',
12
13
  UPDATE_PRESENTATION: 'tools.presentation.update-presentation.rpc',
13
14
  DELETE_ALL_USER_PRESENTATIONS: 'tools.presentation.delete-all-user-presentations.rpc',
15
+ BUILD_BLANK_SLIDE: 'tools.presentation.build-blank-slide.rpc',
16
+ UPDATE_PRESENTATION_SLIDES: 'tools.presentation.update-presentation-slides.rpc',
17
+ UPDATE_SLIDE_IMAGE_SLOT: 'tools.presentation.update-slide-image-slot.rpc',
14
18
  } as const;
15
19
 
16
20
  export const PRESENTATION_SLIDE_OUTLINE_AMQP_ROUTES = {
@@ -4,4 +4,7 @@ export enum TOOL_TYPE {
4
4
  VIDEO = 'VIDEO',
5
5
  AUDIO = 'AUDIO',
6
6
  PRESENTATION = 'PRESENTATION',
7
+ PRESENTATION_AI_ACTION = 'PRESENTATION_AI_ACTION',
8
+ WRITER = 'WRITER',
9
+ PARAPHRASE = 'PARAPHRASE',
7
10
  }