@grapadigital/shared-schemas 1.0.186 → 1.0.188

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.
@@ -0,0 +1,220 @@
1
+ import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
2
+ import {
3
+ HydratedDocument,
4
+ Schema as MongooseSchema,
5
+ Types,
6
+ model as MongooseModel,
7
+ } from 'mongoose';
8
+ import { Action } from './action.schema';
9
+
10
+ export type ContentCaptureProcessDocument = HydratedDocument<ContentCaptureProcess>;
11
+
12
+ @Schema({ _id: false })
13
+ export class ContentCaptureProcessMetrics {
14
+ @Prop({ type: Number, required: false, default: null })
15
+ impressionCount?: number | null;
16
+
17
+ @Prop({ type: Number, required: false, default: null })
18
+ reachCount?: number | null;
19
+
20
+ @Prop({ type: Number, required: false, default: null })
21
+ engagementCount?: number | null;
22
+
23
+ @Prop({ type: Number, required: false, default: null })
24
+ engagementRate?: number | null;
25
+
26
+ @Prop({ type: Number, required: false, default: null })
27
+ sentimentPositive?: number | null;
28
+
29
+ @Prop({ type: Number, required: false, default: null })
30
+ sentimentNegative?: number | null;
31
+
32
+ @Prop({ type: Number, required: false, default: null })
33
+ sentimentNeutral?: number | null;
34
+
35
+ @Prop({ type: Number, required: false, default: null })
36
+ emv?: number | null;
37
+ }
38
+
39
+ export const ContentCaptureProcessMetricsSchema = SchemaFactory.createForClass(
40
+ ContentCaptureProcessMetrics,
41
+ );
42
+
43
+ @Schema({ _id: false })
44
+ export class ContentCaptureProcessInfluencer {
45
+ @Prop({ type: String, required: false })
46
+ username?: string;
47
+
48
+ @Prop({ type: String, required: false })
49
+ displayName?: string;
50
+
51
+ @Prop({ type: String, required: false })
52
+ platform?: string;
53
+ }
54
+
55
+ export const ContentCaptureProcessInfluencerSchema = SchemaFactory.createForClass(
56
+ ContentCaptureProcessInfluencer,
57
+ );
58
+
59
+ @Schema({ _id: false })
60
+ export class ContentCaptureProcessCommentCaptureStatus {
61
+ @Prop({
62
+ type: String,
63
+ enum: ['captured', 'skipped_cooldown', 'skipped_network', 'out_of_scope', 'failed'],
64
+ required: true,
65
+ })
66
+ status: 'captured' | 'skipped_cooldown' | 'skipped_network' | 'out_of_scope' | 'failed';
67
+
68
+ @Prop({ type: Number, required: false })
69
+ commentsCaptured?: number;
70
+
71
+ @Prop({ type: String, required: false })
72
+ error?: string;
73
+ }
74
+
75
+ export const ContentCaptureProcessCommentCaptureStatusSchema = SchemaFactory.createForClass(
76
+ ContentCaptureProcessCommentCaptureStatus,
77
+ );
78
+
79
+ @Schema({ _id: false })
80
+ export class ContentCaptureProcessItem {
81
+ @Prop({ type: String, required: false })
82
+ primetagId?: string;
83
+
84
+ @Prop({ type: MongooseSchema.Types.ObjectId, required: false })
85
+ contentId?: Types.ObjectId;
86
+
87
+ @Prop({ type: String, required: false })
88
+ link?: string;
89
+
90
+ @Prop({ type: String, required: false })
91
+ type?: string;
92
+
93
+ @Prop({ type: String, required: false })
94
+ socialnetwork?: string;
95
+
96
+ @Prop({ type: String, enum: ['created', 'updated'], required: false })
97
+ status?: 'created' | 'updated';
98
+
99
+ @Prop({ type: ContentCaptureProcessMetricsSchema, required: false })
100
+ metrics?: ContentCaptureProcessMetrics;
101
+
102
+ @Prop({ type: ContentCaptureProcessMetricsSchema, required: false })
103
+ previousMetrics?: ContentCaptureProcessMetrics;
104
+
105
+ @Prop({ type: ContentCaptureProcessInfluencerSchema, required: false })
106
+ influencer?: ContentCaptureProcessInfluencer;
107
+
108
+ @Prop({ type: ContentCaptureProcessCommentCaptureStatusSchema, required: false })
109
+ commentCapture?: ContentCaptureProcessCommentCaptureStatus;
110
+ }
111
+
112
+ export const ContentCaptureProcessItemSchema =
113
+ SchemaFactory.createForClass(ContentCaptureProcessItem);
114
+
115
+ @Schema({ _id: false })
116
+ export class ContentCaptureProcessResponsibleContact {
117
+ @Prop({ type: String, required: false })
118
+ name?: string;
119
+
120
+ @Prop({ type: String, required: false })
121
+ team?: string;
122
+
123
+ @Prop({ type: String, required: false })
124
+ email?: string;
125
+ }
126
+
127
+ export const ContentCaptureProcessResponsibleContactSchema = SchemaFactory.createForClass(
128
+ ContentCaptureProcessResponsibleContact,
129
+ );
130
+
131
+ @Schema({ _id: false })
132
+ export class ContentCaptureProcessResponsibles {
133
+ @Prop({ type: ContentCaptureProcessResponsibleContactSchema, required: false })
134
+ service?: ContentCaptureProcessResponsibleContact;
135
+ }
136
+
137
+ export const ContentCaptureProcessResponsiblesSchema = SchemaFactory.createForClass(
138
+ ContentCaptureProcessResponsibles,
139
+ );
140
+
141
+ @Schema({ collection: 'content-capture-processes', timestamps: true })
142
+ export class ContentCaptureProcess {
143
+ @Prop({ type: MongooseSchema.Types.ObjectId, auto: true, required: false })
144
+ _id?: Types.ObjectId;
145
+
146
+ @Prop({ type: MongooseSchema.Types.ObjectId, ref: 'Action', required: true })
147
+ actionId: Types.ObjectId | Action;
148
+
149
+ @Prop({ type: String, required: true })
150
+ runId: string;
151
+
152
+ @Prop({ type: String, required: true })
153
+ actionTitle: string;
154
+
155
+ @Prop({ type: String, required: false })
156
+ primetagId?: string;
157
+
158
+ @Prop({ type: ContentCaptureProcessResponsiblesSchema, required: false })
159
+ responsibles?: ContentCaptureProcessResponsibles;
160
+
161
+ @Prop({
162
+ type: String,
163
+ enum: ['fetching', 'awaiting_comments', 'reported', 'failed'],
164
+ required: true,
165
+ default: 'fetching',
166
+ })
167
+ status: 'fetching' | 'awaiting_comments' | 'reported' | 'failed';
168
+
169
+ @Prop({ type: Number, required: true, default: 0 })
170
+ publicationsFetched: number;
171
+
172
+ @Prop({ type: Number, required: true, default: 0 })
173
+ contentsMapped: number;
174
+
175
+ @Prop({ type: Number, required: true, default: 0 })
176
+ contentsCreated: number;
177
+
178
+ @Prop({ type: Number, required: true, default: 0 })
179
+ contentsUpdated: number;
180
+
181
+ @Prop({ type: Number, required: true, default: 0 })
182
+ expectedCommentCaptureCount: number;
183
+
184
+ @Prop({ type: [MongooseSchema.Types.ObjectId], required: true, default: [] })
185
+ processedContentIds: Types.ObjectId[];
186
+
187
+ @Prop({ type: [ContentCaptureProcessItemSchema], required: true, default: [] })
188
+ contents: ContentCaptureProcessItem[];
189
+
190
+ @Prop({ type: String, required: false })
191
+ error?: string;
192
+
193
+ @Prop({ type: Date, required: true, default: Date.now })
194
+ startedAt: Date;
195
+
196
+ @Prop({ type: Date, required: false })
197
+ fetchFinishedAt?: Date;
198
+
199
+ @Prop({ type: Date, required: false })
200
+ commentsFinishedAt?: Date;
201
+
202
+ @Prop({ type: Date, required: false })
203
+ reportedAt?: Date;
204
+
205
+ @Prop({ default: Date.now, required: false })
206
+ createdAt?: Date;
207
+
208
+ @Prop({ default: Date.now, required: false })
209
+ updatedAt?: Date;
210
+ }
211
+
212
+ export const ContentCaptureProcessSchema = SchemaFactory.createForClass(ContentCaptureProcess);
213
+
214
+ ContentCaptureProcessSchema.index({ actionId: 1, runId: 1 }, { unique: true });
215
+ ContentCaptureProcessSchema.index({ status: 1 });
216
+
217
+ export const ContentCaptureProcessModel = MongooseModel(
218
+ 'ContentCaptureProcess',
219
+ ContentCaptureProcessSchema,
220
+ );
@@ -0,0 +1,111 @@
1
+ import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
2
+ import {
3
+ HydratedDocument,
4
+ Schema as MongooseSchema,
5
+ Types,
6
+ model as MongooseModel,
7
+ } from 'mongoose';
8
+ import { Profile } from './profile.schema';
9
+ import { Action } from './action.schema';
10
+ import {
11
+ Metrics,
12
+ MetricsSchema,
13
+ Estimates,
14
+ EstimatesSchema,
15
+ SentimentAnalysis,
16
+ SentimentAnalysisSchema,
17
+ } from './content.schema';
18
+
19
+ export type ContentDraftDocument = HydratedDocument<ContentDraft>;
20
+
21
+ /**
22
+ * Resultado do fetch+map da Primetag, antes de ser promovido para `Content`
23
+ * (promoção feita pelo metrics-generator-worker, que agrega métricas e
24
+ * reaproveita o mesmo _id). Mesma forma de `Content`, sem os campos que só
25
+ * fazem sentido depois de promovido (status de moderação, linha do Google
26
+ * Sheets, flags de edição).
27
+ */
28
+ @Schema({ collection: 'content-drafts', timestamps: true })
29
+ export class ContentDraft {
30
+ @Prop({ type: MongooseSchema.Types.ObjectId, auto: true, required: false })
31
+ _id?: Types.ObjectId;
32
+
33
+ @Prop({ type: String, required: false, default: '' })
34
+ caption?: string;
35
+
36
+ @Prop({ type: String, required: true })
37
+ link: string;
38
+
39
+ @Prop({
40
+ type: String,
41
+ enum: ['reel', 'image', 'carousel', 'story', 'video', 'post', 'pin', 'tweet'],
42
+ required: true,
43
+ })
44
+ type: 'reel' | 'carousel' | 'image' | 'story' | 'video' | 'post' | 'pin' | 'tweet';
45
+
46
+ @Prop({
47
+ type: String,
48
+ enum: ['withTag', 'withoutTag', 'brandExposure'],
49
+ required: true,
50
+ })
51
+ tagType: 'withTag' | 'withoutTag' | 'brandExposure';
52
+
53
+ @Prop({
54
+ type: String,
55
+ enum: ['instagram', 'tiktok', 'youtube', 'pinterest', 'linkedin', 'twitter'],
56
+ required: true,
57
+ })
58
+ socialnetwork: 'instagram' | 'tiktok' | 'youtube' | 'pinterest' | 'linkedin' | 'twitter';
59
+
60
+ @Prop({ type: MongooseSchema.Types.ObjectId, ref: 'Profile', required: true })
61
+ profile: Types.ObjectId | Profile;
62
+
63
+ @Prop({ type: MongooseSchema.Types.ObjectId, ref: 'Action', required: true })
64
+ action: Types.ObjectId | Action;
65
+
66
+ @Prop({ type: Date, required: true })
67
+ postedAt: Date;
68
+
69
+ @Prop({ type: Boolean, required: true, default: false })
70
+ isCollab: boolean;
71
+
72
+ @Prop({ type: Boolean, required: true, default: false })
73
+ isBoosted: boolean;
74
+
75
+ @Prop({ type: Boolean, required: true, default: false })
76
+ hasAffiliateLink: boolean;
77
+
78
+ @Prop([{ type: MongooseSchema.Types.ObjectId, ref: 'Profile', required: false }])
79
+ collabs?: Types.ObjectId[] | Profile[];
80
+
81
+ @Prop({ type: MetricsSchema, required: true })
82
+ metrics: Metrics;
83
+
84
+ @Prop({ type: EstimatesSchema, required: true })
85
+ estimates: Estimates;
86
+
87
+ @Prop({ type: String, required: false })
88
+ primetagId?: string;
89
+
90
+ @Prop({ type: SentimentAnalysisSchema, required: false, default: null })
91
+ sentimentAnalysis?: SentimentAnalysis | null;
92
+
93
+ @Prop({ type: String, required: false })
94
+ thumbnailUrl?: string;
95
+
96
+ @Prop({ type: String, required: false })
97
+ mediaUrl?: string;
98
+
99
+ @Prop({ default: Date.now, required: false })
100
+ createdAt?: Date;
101
+
102
+ @Prop({ default: Date.now, required: false })
103
+ updatedAt?: Date;
104
+ }
105
+
106
+ export const ContentDraftSchema = SchemaFactory.createForClass(ContentDraft);
107
+
108
+ ContentDraftSchema.index({ action: 1, primetagId: 1 });
109
+ ContentDraftSchema.index({ action: 1, link: 1 });
110
+
111
+ export const ContentDraftModel = MongooseModel('ContentDraft', ContentDraftSchema);
@@ -0,0 +1,52 @@
1
+ import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
2
+ import {
3
+ HydratedDocument,
4
+ Schema as MongooseSchema,
5
+ Types,
6
+ model as MongooseModel,
7
+ } from 'mongoose';
8
+
9
+ export type ExportCommentsJobDocument = HydratedDocument<ExportCommentsJob>;
10
+
11
+ /**
12
+ * Checkpoint de idempotência para o job assíncrono de captura de comentários
13
+ * na exportcomments.com: garante que um crash no meio do polling não crie um
14
+ * job duplicado na API externa ao reprocessar a mensagem.
15
+ */
16
+ @Schema({ collection: 'export-comments-jobs', timestamps: true })
17
+ export class ExportCommentsJob {
18
+ @Prop({ type: MongooseSchema.Types.ObjectId, auto: true, required: false })
19
+ _id?: Types.ObjectId;
20
+
21
+ @Prop({ type: MongooseSchema.Types.ObjectId, required: true })
22
+ contentId: Types.ObjectId;
23
+
24
+ @Prop({ type: String, required: false })
25
+ guid?: string;
26
+
27
+ @Prop({ type: String, required: false })
28
+ jsonUrl?: string;
29
+
30
+ @Prop({
31
+ type: String,
32
+ enum: ['creating', 'polling', 'done', 'error', 'timeout'],
33
+ required: true,
34
+ default: 'creating',
35
+ })
36
+ status: 'creating' | 'polling' | 'done' | 'error' | 'timeout';
37
+
38
+ @Prop({ type: String, required: false })
39
+ error?: string;
40
+
41
+ @Prop({ default: Date.now, required: false })
42
+ createdAt?: Date;
43
+
44
+ @Prop({ default: Date.now, required: false })
45
+ updatedAt?: Date;
46
+ }
47
+
48
+ export const ExportCommentsJobSchema = SchemaFactory.createForClass(ExportCommentsJob);
49
+
50
+ ExportCommentsJobSchema.index({ contentId: 1 }, { unique: true });
51
+
52
+ export const ExportCommentsJobModel = MongooseModel('ExportCommentsJob', ExportCommentsJobSchema);