@natrave/shared-entities 8.34.0 → 8.36.0

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.
@@ -15,4 +15,6 @@ export * from './promotion-targets';
15
15
  export * from './promotion-user-states';
16
16
  export * from './promotions';
17
17
  export type { PromotionCreativeContent, PromotionCreativeContentByTemplate, TournamentPosterContent, } from './types/promotion-content.types';
18
+ export type { PromotionCreativeIssue, PromotionCreativeValidationInput, } from './validation/promotion-creative.validation';
19
+ export { isPromotionCreativeLive, validatePromotionCreative, } from './validation/promotion-creative.validation';
18
20
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/promotions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,MAAM,+CAA+C,CAAC;AAC9F,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACjF,OAAO,EAAE,yBAAyB,EAAE,MAAM,0CAA0C,CAAC;AACrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,cAAc,CAAC;AAC7B,YAAY,EACV,wBAAwB,EACxB,kCAAkC,EAClC,uBAAuB,GACxB,MAAM,iCAAiC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/promotions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,MAAM,+CAA+C,CAAC;AAC9F,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACjF,OAAO,EAAE,yBAAyB,EAAE,MAAM,0CAA0C,CAAC;AACrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,cAAc,CAAC;AAC7B,YAAY,EACV,wBAAwB,EACxB,kCAAkC,EAClC,uBAAuB,GACxB,MAAM,iCAAiC,CAAC;AACzC,YAAY,EACV,sBAAsB,EACtB,gCAAgC,GACjC,MAAM,4CAA4C,CAAC;AACpD,OAAO,EACL,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,4CAA4C,CAAC"}
@@ -14,6 +14,10 @@ export * from "./promotion-events/index.js";
14
14
  export * from "./promotion-targets/index.js";
15
15
  export * from "./promotion-user-states/index.js";
16
16
  export * from "./promotions/index.js";
17
+ import {
18
+ isPromotionCreativeLive,
19
+ validatePromotionCreative
20
+ } from "./validation/promotion-creative.validation.js";
17
21
  export {
18
22
  PromotionAdvertiserEntityType,
19
23
  PromotionCreativeStatus,
@@ -23,5 +27,7 @@ export {
23
27
  PromotionPlacement,
24
28
  PromotionStatus,
25
29
  PromotionSubjectType,
26
- PromotionTargetType
30
+ PromotionTargetType,
31
+ isPromotionCreativeLive,
32
+ validatePromotionCreative
27
33
  };
@@ -1 +1 @@
1
- {"version":3,"file":"promotion-creative.entity.d.ts","sourceRoot":"","sources":["../../../src/promotions/promotion-creatives/promotion-creative.entity.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAClF,OAAO,EAAE,yBAAyB,EAAE,MAAM,2CAA2C,CAAC;AACtF,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAC3D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAuBjF,qBAWa,iBAAiB;IAK5B,EAAE,EAAE,MAAM,CAAC;IAOX,WAAW,EAAE,MAAM,CAAC;IAOpB,KAAK,EAAE,MAAM,CAAC;IAOd,SAAS,EAAE,kBAAkB,CAAC;IAO9B,QAAQ,EAAE,yBAAyB,CAAC;IAMpC,OAAO,EAAE,wBAAwB,CAAC;IASlC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAQ3B,MAAM,EAAE,uBAAuB,CAAC;IAOhC,MAAM,EAAE,MAAM,CAAC;IASf,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAQzB,SAAS,EAAE,IAAI,CAAC;IAQhB,SAAS,EAAE,IAAI,CAAC;IAShB,SAAS,EAAE,SAAS,CAAC;CACtB"}
1
+ {"version":3,"file":"promotion-creative.entity.d.ts","sourceRoot":"","sources":["../../../src/promotions/promotion-creatives/promotion-creative.entity.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAClF,OAAO,EAAE,yBAAyB,EAAE,MAAM,2CAA2C,CAAC;AACtF,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAC3D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAyBjF,qBAOa,iBAAiB;IAK5B,EAAE,EAAE,MAAM,CAAC;IAOX,WAAW,EAAE,MAAM,CAAC;IAOpB,KAAK,EAAE,MAAM,CAAC;IAOd,SAAS,EAAE,kBAAkB,CAAC;IAO9B,QAAQ,EAAE,yBAAyB,CAAC;IAMpC,OAAO,EAAE,wBAAwB,CAAC;IASlC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAQ3B,MAAM,EAAE,uBAAuB,CAAC;IAOhC,MAAM,EAAE,MAAM,CAAC;IASf,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAQzB,SAAS,EAAE,IAAI,CAAC;IAQhB,SAAS,EAAE,IAAI,CAAC;IAShB,SAAS,EAAE,SAAS,CAAC;CACtB"}
@@ -68,7 +68,7 @@ __decorateClass([
68
68
  name: "consent_text",
69
69
  type: "text",
70
70
  nullable: true,
71
- comment: "Aviso exibido junto do bot\xE3o de interesse. Obrigat\xF3rio quando o template coleta lead."
71
+ comment: "Aviso exibido junto do bot\xE3o de interesse. Obrigat\xF3rio para ir ao ar quando o template coleta lead."
72
72
  })
73
73
  ], PromotionCreative.prototype, "consentText", 2);
74
74
  __decorateClass([
@@ -125,11 +125,7 @@ PromotionCreative = __decorateClass([
125
125
  Check("CHK_promotion_creatives_placement", `"placement" IN ('HOME_MODAL')`),
126
126
  Check("CHK_promotion_creatives_template", `"template" IN ('TOURNAMENT_POSTER')`),
127
127
  Check("CHK_promotion_creatives_weight", `"weight" >= 1`),
128
- Check("CHK_promotion_creatives_content_object", `jsonb_typeof("content") = 'object'`),
129
- Check(
130
- "CHK_promotion_creatives_consent",
131
- `"template" <> 'TOURNAMENT_POSTER' OR ("consent_text" IS NOT NULL AND length(trim("consent_text")) > 0)`
132
- )
128
+ Check("CHK_promotion_creatives_content_object", `jsonb_typeof("content") = 'object'`)
133
129
  ], PromotionCreative);
134
130
  export {
135
131
  PromotionCreative
@@ -8,18 +8,18 @@ export declare class Promotion {
8
8
  id: string;
9
9
  name: string;
10
10
  status: PromotionStatus;
11
- advertiserId: string;
11
+ advertiserId: string | null;
12
12
  subjectType: PromotionSubjectType | null;
13
13
  subjectId: string | null;
14
- startsAt: Date;
15
- endsAt: Date;
14
+ startsAt: Date | null;
15
+ endsAt: Date | null;
16
16
  priority: number;
17
17
  maxImpressionsPerUser: number;
18
18
  contractRef: string | null;
19
19
  createdBy: string | null;
20
20
  createdAt: Date;
21
21
  updatedAt: Date;
22
- advertiser: PromotionAdvertiser;
22
+ advertiser: PromotionAdvertiser | null;
23
23
  targets: PromotionTarget[];
24
24
  creatives: PromotionCreative[];
25
25
  contacts: PromotionContact[];
@@ -1 +1 @@
1
- {"version":3,"file":"promotion.entity.d.ts","sourceRoot":"","sources":["../../../src/promotions/promotions/promotion.entity.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,sDAAsD,CAAC;AAC3F,OAAO,EAAE,gBAAgB,EAAE,MAAM,gDAAgD,CAAC;AAClF,OAAO,EAAE,iBAAiB,EAAE,MAAM,kDAAkD,CAAC;AACrF,OAAO,EAAE,eAAe,EAAE,MAAM,8CAA8C,CAAC;AA6B/E,qBAYa,SAAS;IAKpB,EAAE,EAAE,MAAM,CAAC;IAOX,IAAI,EAAE,MAAM,CAAC;IAQb,MAAM,EAAE,eAAe,CAAC;IAOxB,YAAY,EAAE,MAAM,CAAC;IASrB,WAAW,EAAE,oBAAoB,GAAG,IAAI,CAAC;IASzC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAOzB,QAAQ,EAAE,IAAI,CAAC;IAOf,MAAM,EAAE,IAAI,CAAC;IAOb,QAAQ,EAAE,MAAM,CAAC;IAQjB,qBAAqB,EAAE,MAAM,CAAC;IAS9B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAS3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAQzB,SAAS,EAAE,IAAI,CAAC;IAQhB,SAAS,EAAE,IAAI,CAAC;IAWhB,UAAU,EAAE,mBAAmB,CAAC;IAGhC,OAAO,EAAE,eAAe,EAAE,CAAC;IAG3B,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAG/B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;CAC9B"}
1
+ {"version":3,"file":"promotion.entity.d.ts","sourceRoot":"","sources":["../../../src/promotions/promotions/promotion.entity.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,sDAAsD,CAAC;AAC3F,OAAO,EAAE,gBAAgB,EAAE,MAAM,gDAAgD,CAAC;AAClF,OAAO,EAAE,iBAAiB,EAAE,MAAM,kDAAkD,CAAC;AACrF,OAAO,EAAE,eAAe,EAAE,MAAM,8CAA8C,CAAC;AAkC/E,qBAiBa,SAAS;IAKpB,EAAE,EAAE,MAAM,CAAC;IAOX,IAAI,EAAE,MAAM,CAAC;IAQb,MAAM,EAAE,eAAe,CAAC;IAQxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAS5B,WAAW,EAAE,oBAAoB,GAAG,IAAI,CAAC;IASzC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAQzB,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC;IAQtB,MAAM,EAAE,IAAI,GAAG,IAAI,CAAC;IAOpB,QAAQ,EAAE,MAAM,CAAC;IAQjB,qBAAqB,EAAE,MAAM,CAAC;IAS9B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAS3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAQzB,SAAS,EAAE,IAAI,CAAC;IAQhB,SAAS,EAAE,IAAI,CAAC;IAYhB,UAAU,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAGvC,OAAO,EAAE,eAAe,EAAE,CAAC;IAG3B,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAG/B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;CAC9B"}
@@ -52,7 +52,8 @@ __decorateClass([
52
52
  Column({
53
53
  name: "advertiser_id",
54
54
  type: "uuid",
55
- comment: "FK promotion_advertisers.id. Quem pagou pelo destaque."
55
+ nullable: true,
56
+ comment: "FK promotion_advertisers.id. Quem pagou pelo destaque. Nulo s\xF3 em rascunho."
56
57
  })
57
58
  ], Promotion.prototype, "advertiserId", 2);
58
59
  __decorateClass([
@@ -76,14 +77,16 @@ __decorateClass([
76
77
  Column({
77
78
  name: "starts_at",
78
79
  type: "timestamptz",
79
- comment: "In\xEDcio da janela em que o destaque pode aparecer."
80
+ nullable: true,
81
+ comment: "In\xEDcio da janela em que o destaque pode aparecer. Nulo s\xF3 em rascunho."
80
82
  })
81
83
  ], Promotion.prototype, "startsAt", 2);
82
84
  __decorateClass([
83
85
  Column({
84
86
  name: "ends_at",
85
87
  type: "timestamptz",
86
- comment: "Fim da janela (exclusivo). Depois disso n\xE3o aparece mais."
88
+ nullable: true,
89
+ comment: "Fim da janela (exclusivo). Depois disso n\xE3o aparece mais. Nulo s\xF3 em rascunho."
87
90
  })
88
91
  ], Promotion.prototype, "endsAt", 2);
89
92
  __decorateClass([
@@ -137,6 +140,7 @@ __decorateClass([
137
140
  ], Promotion.prototype, "updatedAt", 2);
138
141
  __decorateClass([
139
142
  ManyToOne(() => PromotionAdvertiser, (advertiser) => advertiser.promotions, {
143
+ nullable: true,
140
144
  onDelete: "RESTRICT"
141
145
  }),
142
146
  JoinColumn({
@@ -164,6 +168,10 @@ Promotion = __decorateClass([
164
168
  `("subject_type" IS NULL AND "subject_id" IS NULL) OR ("subject_type" IS NOT NULL AND "subject_type" IN ('TOURNAMENT') AND "subject_id" IS NOT NULL)`
165
169
  ),
166
170
  Check("CHK_promotions_window", `"ends_at" > "starts_at"`),
171
+ Check(
172
+ "CHK_promotions_ready",
173
+ `"status" = 'DRAFT' OR ("advertiser_id" IS NOT NULL AND "starts_at" IS NOT NULL AND "ends_at" IS NOT NULL)`
174
+ ),
167
175
  Check("CHK_promotions_max_impressions", `"max_impressions_per_user" >= 1`)
168
176
  ], Promotion);
169
177
  export {
@@ -0,0 +1,13 @@
1
+ export interface PromotionCreativeIssue {
2
+ field: string;
3
+ code: 'REQUIRED' | 'INVALID' | 'TOO_LONG' | 'UNKNOWN_TEMPLATE';
4
+ message: string;
5
+ }
6
+ export interface PromotionCreativeValidationInput {
7
+ template: string;
8
+ content: unknown;
9
+ consentText: string | null;
10
+ }
11
+ export declare function validatePromotionCreative(input: PromotionCreativeValidationInput): PromotionCreativeIssue[];
12
+ export declare function isPromotionCreativeLive(input: PromotionCreativeValidationInput): boolean;
13
+ //# sourceMappingURL=promotion-creative.validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promotion-creative.validation.d.ts","sourceRoot":"","sources":["../../../src/promotions/validation/promotion-creative.validation.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,sBAAsB;IAErC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,kBAAkB,CAAC;IAC/D,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAsDD,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,gCAAgC,GACtC,sBAAsB,EAAE,CA+B1B;AAGD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,gCAAgC,GAAG,OAAO,CAExF"}
@@ -0,0 +1,75 @@
1
+ import { PromotionCreativeTemplate } from "../enums/promotion-creative-template.enum.js";
2
+ const HEX_COLOR = /^#[0-9a-fA-F]{6}$/;
3
+ const HTTPS_URL = /^https:\/\/\S+$/;
4
+ const CONSENT_MAX_LENGTH = 280;
5
+ const TOURNAMENT_POSTER_RULES = {
6
+ posterImageUrl: {
7
+ required: true,
8
+ maxLength: 2048,
9
+ pattern: HTTPS_URL,
10
+ patternMessage: "Use uma URL https."
11
+ },
12
+ posterColor: {
13
+ required: false,
14
+ maxLength: 7,
15
+ pattern: HEX_COLOR,
16
+ patternMessage: "Use a cor no formato #RRGGBB."
17
+ },
18
+ monogram: { required: false, maxLength: 3 },
19
+ headline: { required: false, maxLength: 80 },
20
+ kicker: { required: false, maxLength: 80 },
21
+ badge: { required: false, maxLength: 40 },
22
+ ctaLabel: { required: true, maxLength: 40 },
23
+ dismissLabel: { required: true, maxLength: 40 },
24
+ contactMessage: { required: false, maxLength: 500 }
25
+ };
26
+ const isFilled = (value) => typeof value === "string" && value.trim().length > 0;
27
+ function validatePromotionCreative(input) {
28
+ if (input.template !== PromotionCreativeTemplate.TOURNAMENT_POSTER) {
29
+ return [{ field: "template", code: "UNKNOWN_TEMPLATE", message: "Layout desconhecido." }];
30
+ }
31
+ const issues = [];
32
+ if (isFilled(input.consentText) && input.consentText.trim().length > CONSENT_MAX_LENGTH) {
33
+ issues.push({
34
+ field: "consentText",
35
+ code: "TOO_LONG",
36
+ message: `Use at\xE9 ${CONSENT_MAX_LENGTH} caracteres.`
37
+ });
38
+ }
39
+ const content = input.content;
40
+ if (typeof content !== "object" || content === null || Array.isArray(content)) {
41
+ issues.push({ field: "content", code: "INVALID", message: "Conte\xFAdo do criativo inv\xE1lido." });
42
+ return issues;
43
+ }
44
+ const fields = new Map(Object.entries(content));
45
+ for (const [name, rule] of Object.entries(TOURNAMENT_POSTER_RULES)) {
46
+ const issue = checkField(name, fields.get(name), rule);
47
+ if (issue) {
48
+ issues.push(issue);
49
+ }
50
+ }
51
+ return issues;
52
+ }
53
+ function isPromotionCreativeLive(input) {
54
+ return validatePromotionCreative(input).length === 0;
55
+ }
56
+ function checkField(name, value, rule) {
57
+ const field = `content.${name}`;
58
+ if (value === void 0 || value === null || typeof value === "string" && !value.trim()) {
59
+ return rule.required ? { field, code: "REQUIRED", message: "Campo obrigat\xF3rio." } : null;
60
+ }
61
+ if (typeof value !== "string") {
62
+ return { field, code: "INVALID", message: "Use texto." };
63
+ }
64
+ if (value.trim().length > rule.maxLength) {
65
+ return { field, code: "TOO_LONG", message: `Use at\xE9 ${rule.maxLength} caracteres.` };
66
+ }
67
+ if (rule.pattern && !rule.pattern.test(value.trim())) {
68
+ return { field, code: "INVALID", message: rule.patternMessage ?? "Formato inv\xE1lido." };
69
+ }
70
+ return null;
71
+ }
72
+ export {
73
+ isPromotionCreativeLive,
74
+ validatePromotionCreative
75
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@natrave/shared-entities",
3
- "version": "8.34.0",
3
+ "version": "8.36.0",
4
4
  "description": "Entidades compartilhadass da NaTrave",
5
5
  "module": "dist/index.js",
6
6
  "main": "dist/index.js",