@escapenavigator/types 1.10.142 → 1.10.144

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.
@@ -3,6 +3,7 @@ export declare class QueryClientDto {
3
3
  lastGame?: [string, string];
4
4
  birthday?: [string, string];
5
5
  gamesCount?: string[];
6
+ visitsCount?: 'exactly_1' | 'exactly_2' | 'more_2' | 'more_3' | 'more_4';
6
7
  selectedMonth?: string | number;
7
8
  blockedClient?: 'blocked' | 'not_blocked';
8
9
  alowedToAds?: 'allowed' | 'not_allowed';
@@ -38,6 +38,11 @@ __decorate([
38
38
  (0, class_transformer_1.Transform)(({ value }) => (typeof value === 'object' ? value : ['', ''])),
39
39
  __metadata("design:type", Array)
40
40
  ], QueryClientDto.prototype, "gamesCount", void 0);
41
+ __decorate([
42
+ (0, class_validator_1.IsOptional)(),
43
+ (0, class_transformer_1.Expose)(),
44
+ __metadata("design:type", String)
45
+ ], QueryClientDto.prototype, "visitsCount", void 0);
41
46
  __decorate([
42
47
  (0, class_validator_1.IsOptional)(),
43
48
  (0, class_transformer_1.Expose)(),
@@ -133,8 +133,36 @@ export declare const isEmailContentJsonV2: (raw: unknown) => raw is EmailContent
133
133
  */
134
134
  export declare const DEFAULT_EMAIL_THEME: EmailThemeV2;
135
135
  export declare const createEmptyEmailContent: () => EmailContentJsonV2;
136
+ /**
137
+ * Локализуемые строки seed-шаблона (`createDefaultEmailContent`).
138
+ * Пакет `types` без i18n, поэтому строки приходят сверху из app-слоя
139
+ * (хелпер `useDefaultEmailTexts` в `components/email-builder`). Если
140
+ * не переданы — используются RU-дефолты (см. `DEFAULT_EMAIL_TEXTS`).
141
+ */
142
+ export type DefaultEmailTexts = {
143
+ /** H1-заголовок письма. */
144
+ heading: string;
145
+ /** Текст ПОСЛЕ переменной названия компании (начинается с ", "). */
146
+ intro: string;
147
+ /** Абзац-подсказка про «/» и «@». */
148
+ tryEditing: string;
149
+ /** Подпись на кнопке-примере. */
150
+ buttonText: string;
151
+ /** Приглушённый абзац о развитии редактора. */
152
+ feedback: string;
153
+ /** Строка подписи («С уважением,»). */
154
+ signoff: string;
155
+ /** Подпись команды («Команда Escape Navigator»). */
156
+ team: string;
157
+ /** Лейбл inline-переменной названия компании. */
158
+ companyLabel: string;
159
+ };
160
+ /** RU-дефолты seed-шаблона — fallback, если `texts` не передан. */
161
+ export declare const DEFAULT_EMAIL_TEXTS: DefaultEmailTexts;
136
162
  export type CreateDefaultEmailContentOptions = {
137
163
  logo?: string | null;
164
+ /** Локализованные строки seed-шаблона. По умолчанию — RU. */
165
+ texts?: Partial<DefaultEmailTexts>;
138
166
  };
139
167
  /**
140
168
  * Image-нода с предустановленным логотипом. Используется и в seed'е
@@ -11,7 +11,7 @@
11
11
  * for transactional emails that are NOT user-editable.
12
12
  */
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.EmailScope = exports.normalizeEmailTheme = exports.createDefaultEmailContent = exports.createLogoNode = exports.createEmptyEmailContent = exports.DEFAULT_EMAIL_THEME = exports.isEmailContentJsonV2 = exports.resolveEmailThemeColors = exports.deriveEmailTextColors = exports.EMAIL_CONTENT_VERSION_V2 = void 0;
14
+ exports.EmailScope = exports.normalizeEmailTheme = exports.createDefaultEmailContent = exports.createLogoNode = exports.DEFAULT_EMAIL_TEXTS = exports.createEmptyEmailContent = exports.DEFAULT_EMAIL_THEME = exports.isEmailContentJsonV2 = exports.resolveEmailThemeColors = exports.deriveEmailTextColors = exports.EMAIL_CONTENT_VERSION_V2 = void 0;
15
15
  exports.EMAIL_CONTENT_VERSION_V2 = 'v2';
16
16
  /**
17
17
  * Compute the relative luminance of an opaque hex color in [0, 1].
@@ -156,6 +156,25 @@ const createEmptyEmailContent = () => ({
156
156
  theme: exports.DEFAULT_EMAIL_THEME,
157
157
  });
158
158
  exports.createEmptyEmailContent = createEmptyEmailContent;
159
+ /** RU-дефолты seed-шаблона — fallback, если `texts` не передан. */
160
+ exports.DEFAULT_EMAIL_TEXTS = {
161
+ heading: 'Email конструктор 2.0',
162
+ intro: ', готовы преобразить email-коммуникацию? ' +
163
+ 'Встречайте мощный редактор писем, который ' +
164
+ 'помогает быстро и красиво готовить рассылки ' +
165
+ 'клиентам.',
166
+ tryEditing: 'Попробуйте отредактировать этот шаблон, или ' +
167
+ 'начните с чистого листа — нажмите «/» в любом ' +
168
+ 'месте, чтобы вставить блок, и «@» — чтобы ' +
169
+ 'добавить переменную клиента.',
170
+ buttonText: 'Пример кнопки →',
171
+ feedback: 'Делитесь идеями и улучшениями — мы ' +
172
+ 'постоянно развиваем редактор, чтобы ' +
173
+ 'делать ваш маркетинг проще.',
174
+ signoff: 'С уважением,',
175
+ team: 'Команда Escape Navigator',
176
+ companyLabel: 'Название компании',
177
+ };
159
178
  /**
160
179
  * Бренд, используемый в `alt`/`title` для логотипа. Захардкожен — это
161
180
  * не персонализированное имя профиля (которое подставляется через
@@ -193,6 +212,7 @@ const createLogoNode = (logo) => {
193
212
  exports.createLogoNode = createLogoNode;
194
213
  const createDefaultEmailContent = (options = {}) => {
195
214
  const { logo } = options;
215
+ const txt = Object.assign(Object.assign({}, exports.DEFAULT_EMAIL_TEXTS), options.texts);
196
216
  const content = [];
197
217
  const logoNode = (0, exports.createLogoNode)(logo);
198
218
  if (logoNode)
@@ -200,7 +220,7 @@ const createDefaultEmailContent = (options = {}) => {
200
220
  content.push({
201
221
  type: 'heading',
202
222
  attrs: { level: 1, textAlign: 'left' },
203
- content: [{ type: 'text', text: 'Email конструктор 2.0' }],
223
+ content: [{ type: 'text', text: txt.heading }],
204
224
  }, {
205
225
  type: 'paragraph',
206
226
  attrs: { textAlign: 'left' },
@@ -221,7 +241,7 @@ const createDefaultEmailContent = (options = {}) => {
221
241
  type: 'variable',
222
242
  attrs: {
223
243
  id: 'profile.title',
224
- label: 'Название компании',
244
+ label: txt.companyLabel,
225
245
  fallback: null,
226
246
  required: false,
227
247
  hideDefaultValue: false,
@@ -229,10 +249,7 @@ const createDefaultEmailContent = (options = {}) => {
229
249
  },
230
250
  {
231
251
  type: 'text',
232
- text: ', готовы преобразить email-коммуникацию? ' +
233
- 'Встречайте мощный редактор писем, который ' +
234
- 'помогает быстро и красиво готовить рассылки ' +
235
- 'клиентам.',
252
+ text: txt.intro,
236
253
  },
237
254
  ],
238
255
  }, {
@@ -241,16 +258,13 @@ const createDefaultEmailContent = (options = {}) => {
241
258
  content: [
242
259
  {
243
260
  type: 'text',
244
- text: 'Попробуйте отредактировать этот шаблон, или ' +
245
- 'начните с чистого листа — нажмите «/» в любом ' +
246
- 'месте, чтобы вставить блок, и «@» — чтобы ' +
247
- 'добавить переменную клиента.',
261
+ text: txt.tryEditing,
248
262
  },
249
263
  ],
250
264
  }, {
251
265
  type: 'button',
252
266
  attrs: {
253
- text: 'Перейти к редактору →',
267
+ text: txt.buttonText,
254
268
  url: '',
255
269
  alignment: 'left',
256
270
  variant: 'filled',
@@ -266,9 +280,7 @@ const createDefaultEmailContent = (options = {}) => {
266
280
  content: [
267
281
  {
268
282
  type: 'text',
269
- text: 'Делитесь идеями и улучшениями — мы ' +
270
- 'постоянно развиваем редактор, чтобы ' +
271
- 'делать ваш маркетинг проще.',
283
+ text: txt.feedback,
272
284
  marks: [MUTED_TEXT_MARK],
273
285
  },
274
286
  ],
@@ -276,9 +288,9 @@ const createDefaultEmailContent = (options = {}) => {
276
288
  type: 'paragraph',
277
289
  attrs: { textAlign: 'left' },
278
290
  content: [
279
- { type: 'text', text: уважением,' },
291
+ { type: 'text', text: txt.signoff },
280
292
  { type: 'hardBreak' },
281
- { type: 'text', text: 'Команда Escape Navigator' },
293
+ { type: 'text', text: txt.team },
282
294
  ],
283
295
  });
284
296
  return {
@@ -0,0 +1,56 @@
1
+ import { EmailScope } from '../../email-builder';
2
+ import { Languages } from '../../shared/enum/languages.enum';
3
+ import { EmailContentJsonV2Dto } from './create-profile-marketing-email-campaign.dto';
4
+ import { PreviewPromocodeDto } from './preview-campaign-v2.dto';
5
+ /**
6
+ * Request body for `POST /profile-marketing-email-campaigns/test-send-v2`.
7
+ *
8
+ * «Тестовая отправка» письма прямо из режима превью: бэк резолвит
9
+ * переменные шаблона на РЕАЛЬНЫХ данных и шлёт письмо на указанный
10
+ * `email`, как будто оно ушло в запланированное время.
11
+ *
12
+ * Источник данных зависит от scope письма:
13
+ * - письма, привязанные к игре/брони (`order-post-game`,
14
+ * `custom-booking-template`) → нужен `orderCode` (код брони).
15
+ * Бэк находит заказ по коду В РАМКАХ профиля (проверка владения)
16
+ * и резолвит `order.*` / `client.*` / `questroom.*` / `location.*`
17
+ * / `promocode.*` именно по нему;
18
+ * - письма, привязанные к клиенту (`birthday-marketing`,
19
+ * `marketing-campaign`) → нужен `clientId` (номер клиента в профиле).
20
+ */
21
+ export declare class TestSendMarketingEmailV2Dto {
22
+ contentJson: EmailContentJsonV2Dto;
23
+ scope: EmailScope;
24
+ /** Куда отправить тестовое письмо (inbox оператора). */
25
+ email: string;
26
+ /**
27
+ * Код брони (человекочитаемый, напр. `B1234567`). Обязателен для
28
+ * scope'ов, завязанных на игру/бронь. Бэк проверяет, что бронь
29
+ * принадлежит текущему профилю.
30
+ */
31
+ orderCode?: string;
32
+ /**
33
+ * Номер (id) клиента в рамках профиля. Обязателен для scope'ов,
34
+ * завязанных на клиента (birthday / marketing-campaign).
35
+ */
36
+ clientId?: number;
37
+ /**
38
+ * Необязательная тема письма (если редактор/форма её знает —
39
+ * напр. `locale.title` из карточки рассылки). К теме всё равно
40
+ * добавляется префикс `[TEST]`. Нужна, чтобы при отправке из
41
+ * родительской карточки проверить и тему письма.
42
+ */
43
+ subject?: string;
44
+ /**
45
+ * Язык письма. При отправке из карточки рассылки фронт шлёт язык
46
+ * выбранной локали — бэк подставляет его в `order.language`, чтобы
47
+ * резолверы выбрали нужную локаль квеста/локации и формат даты.
48
+ */
49
+ language?: Languages;
50
+ /**
51
+ * Промокод для теста (код/скидка/срок) — те же поля, что и в
52
+ * preview. Если передан, письмо рендерит реальную «валидность»
53
+ * (срок действия) из настроек скидки рассылки, а не общий образец.
54
+ */
55
+ previewPromocode?: PreviewPromocodeDto;
56
+ }
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.TestSendMarketingEmailV2Dto = void 0;
13
+ const class_transformer_1 = require("class-transformer");
14
+ const class_validator_1 = require("class-validator");
15
+ const email_builder_1 = require("../../email-builder");
16
+ const languages_enum_1 = require("../../shared/enum/languages.enum");
17
+ const create_profile_marketing_email_campaign_dto_1 = require("./create-profile-marketing-email-campaign.dto");
18
+ const preview_campaign_v2_dto_1 = require("./preview-campaign-v2.dto");
19
+ /**
20
+ * Request body for `POST /profile-marketing-email-campaigns/test-send-v2`.
21
+ *
22
+ * «Тестовая отправка» письма прямо из режима превью: бэк резолвит
23
+ * переменные шаблона на РЕАЛЬНЫХ данных и шлёт письмо на указанный
24
+ * `email`, как будто оно ушло в запланированное время.
25
+ *
26
+ * Источник данных зависит от scope письма:
27
+ * - письма, привязанные к игре/брони (`order-post-game`,
28
+ * `custom-booking-template`) → нужен `orderCode` (код брони).
29
+ * Бэк находит заказ по коду В РАМКАХ профиля (проверка владения)
30
+ * и резолвит `order.*` / `client.*` / `questroom.*` / `location.*`
31
+ * / `promocode.*` именно по нему;
32
+ * - письма, привязанные к клиенту (`birthday-marketing`,
33
+ * `marketing-campaign`) → нужен `clientId` (номер клиента в профиле).
34
+ */
35
+ class TestSendMarketingEmailV2Dto {
36
+ }
37
+ exports.TestSendMarketingEmailV2Dto = TestSendMarketingEmailV2Dto;
38
+ __decorate([
39
+ (0, class_validator_1.IsDefined)(),
40
+ (0, class_validator_1.ValidateNested)(),
41
+ (0, class_transformer_1.Type)(() => create_profile_marketing_email_campaign_dto_1.EmailContentJsonV2Dto),
42
+ (0, class_transformer_1.Expose)(),
43
+ __metadata("design:type", create_profile_marketing_email_campaign_dto_1.EmailContentJsonV2Dto)
44
+ ], TestSendMarketingEmailV2Dto.prototype, "contentJson", void 0);
45
+ __decorate([
46
+ (0, class_validator_1.IsEnum)(email_builder_1.EmailScope),
47
+ (0, class_transformer_1.Expose)(),
48
+ __metadata("design:type", String)
49
+ ], TestSendMarketingEmailV2Dto.prototype, "scope", void 0);
50
+ __decorate([
51
+ (0, class_validator_1.IsEmail)(),
52
+ (0, class_transformer_1.Expose)(),
53
+ __metadata("design:type", String)
54
+ ], TestSendMarketingEmailV2Dto.prototype, "email", void 0);
55
+ __decorate([
56
+ (0, class_validator_1.IsOptional)(),
57
+ (0, class_validator_1.IsString)(),
58
+ (0, class_transformer_1.Expose)(),
59
+ __metadata("design:type", String)
60
+ ], TestSendMarketingEmailV2Dto.prototype, "orderCode", void 0);
61
+ __decorate([
62
+ (0, class_validator_1.IsOptional)(),
63
+ (0, class_validator_1.IsInt)(),
64
+ (0, class_transformer_1.Expose)(),
65
+ __metadata("design:type", Number)
66
+ ], TestSendMarketingEmailV2Dto.prototype, "clientId", void 0);
67
+ __decorate([
68
+ (0, class_validator_1.IsOptional)(),
69
+ (0, class_validator_1.IsString)(),
70
+ (0, class_transformer_1.Expose)(),
71
+ __metadata("design:type", String)
72
+ ], TestSendMarketingEmailV2Dto.prototype, "subject", void 0);
73
+ __decorate([
74
+ (0, class_validator_1.IsOptional)(),
75
+ (0, class_validator_1.IsEnum)(languages_enum_1.Languages),
76
+ (0, class_transformer_1.Expose)(),
77
+ __metadata("design:type", String)
78
+ ], TestSendMarketingEmailV2Dto.prototype, "language", void 0);
79
+ __decorate([
80
+ (0, class_validator_1.IsOptional)(),
81
+ (0, class_validator_1.ValidateNested)(),
82
+ (0, class_transformer_1.Type)(() => preview_campaign_v2_dto_1.PreviewPromocodeDto),
83
+ (0, class_transformer_1.Expose)(),
84
+ __metadata("design:type", preview_campaign_v2_dto_1.PreviewPromocodeDto)
85
+ ], TestSendMarketingEmailV2Dto.prototype, "previewPromocode", void 0);
@@ -24,3 +24,21 @@ export declare const EXPORT_LIMITS: {
24
24
  readonly GOOGLE_PLACES: 5000;
25
25
  };
26
26
  export type ExportLimitKey = keyof typeof EXPORT_LIMITS;
27
+ /**
28
+ * Единый порог для всех CSV-экспортов (`GET /<resource>/export`).
29
+ *
30
+ * Один эндпоинт, один запрос с фронта:
31
+ * - `count <= EXPORT_SYNC_LIMIT` → CSV отдаётся сразу потоком (скачивание);
32
+ * - `count > EXPORT_SYNC_LIMIT` → запускается фоновая джоба, файл уходит
33
+ * на почту пользователя; фронт показывает тост «пришлём на e-mail».
34
+ *
35
+ * Порог низкий (1000) намеренно: синхронно отдаём только «лёгкие» срезы,
36
+ * всё крупное уводим в фон, чтобы не держать HTTP-соединение и heap.
37
+ */
38
+ export declare const EXPORT_SYNC_LIMIT = 1000;
39
+ /**
40
+ * Сколько фоновых (email) экспортов разрешено запустить одному профилю в
41
+ * час. Защита от спама тяжёлыми выгрузками. При превышении бэкенд отвечает
42
+ * 429, фронт показывает тост «слишком часто, попробуйте позже».
43
+ */
44
+ export declare const EXPORT_RATE_LIMIT_PER_HOUR = 10;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.EXPORT_LIMITS = void 0;
3
+ exports.EXPORT_RATE_LIMIT_PER_HOUR = exports.EXPORT_SYNC_LIMIT = exports.EXPORT_LIMITS = void 0;
4
4
  /**
5
5
  * Единые лимиты на размер XLSX-выгрузок. Импортится и бэком
6
6
  * (`*.Service.EXPORT_LIMIT` + count-precheck в контроллере), и
@@ -26,3 +26,21 @@ exports.EXPORT_LIMITS = {
26
26
  USER_SESSIONS: 5000,
27
27
  GOOGLE_PLACES: 5000,
28
28
  };
29
+ /**
30
+ * Единый порог для всех CSV-экспортов (`GET /<resource>/export`).
31
+ *
32
+ * Один эндпоинт, один запрос с фронта:
33
+ * - `count <= EXPORT_SYNC_LIMIT` → CSV отдаётся сразу потоком (скачивание);
34
+ * - `count > EXPORT_SYNC_LIMIT` → запускается фоновая джоба, файл уходит
35
+ * на почту пользователя; фронт показывает тост «пришлём на e-mail».
36
+ *
37
+ * Порог низкий (1000) намеренно: синхронно отдаём только «лёгкие» срезы,
38
+ * всё крупное уводим в фон, чтобы не держать HTTP-соединение и heap.
39
+ */
40
+ exports.EXPORT_SYNC_LIMIT = 1000;
41
+ /**
42
+ * Сколько фоновых (email) экспортов разрешено запустить одному профилю в
43
+ * час. Защита от спама тяжёлыми выгрузками. При превышении бэкенд отвечает
44
+ * 429, фронт показывает тост «слишком часто, попробуйте позже».
45
+ */
46
+ exports.EXPORT_RATE_LIMIT_PER_HOUR = 10;