feed-common 0.0.1 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. package/.releaserc.json +33 -0
  2. package/CHANGELOG.md +23 -0
  3. package/dist/constants/google.constants.d.ts +11 -0
  4. package/dist/constants/google.constants.js.map +1 -1
  5. package/dist/constants/product.constants.d.ts +4 -0
  6. package/dist/constants/product.constants.js.map +1 -1
  7. package/dist/constants/profile.constants.d.ts +69 -0
  8. package/dist/constants/profile.constants.js.map +1 -1
  9. package/dist/index.d.ts +9 -0
  10. package/dist/index.js +10 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/types/company.types.d.ts +9 -0
  13. package/dist/types/company.types.js +2 -0
  14. package/dist/types/company.types.js.map +1 -0
  15. package/dist/types/product.types.d.ts +86 -0
  16. package/dist/types/product.types.js.map +1 -1
  17. package/dist/types/profile.types.d.ts +68 -0
  18. package/dist/types/profile.types.js.map +1 -1
  19. package/dist/utils/gmc.d.ts +16 -0
  20. package/dist/utils/gmc.js.map +1 -1
  21. package/dist/utils/profile.d.ts +28 -0
  22. package/dist/utils/profile.js.map +1 -1
  23. package/dist/utils/utils.d.ts +1 -0
  24. package/dist/utils/utils.js.map +1 -1
  25. package/package.json +4 -2
  26. package/scripts/install.sh +9 -0
  27. package/src/constants/google.constants.ts +12 -0
  28. package/src/constants/product.constants.ts +4 -0
  29. package/src/constants/profile.constants.ts +369 -0
  30. package/src/index.ts +11 -0
  31. package/src/types/company.types.ts +10 -0
  32. package/src/types/product.types.ts +97 -0
  33. package/src/types/profile.types.ts +73 -0
  34. package/src/utils/gmc.ts +69 -0
  35. package/src/utils/profile.ts +348 -0
  36. package/src/utils/utils.ts +3 -0
  37. package/.releaserc +0 -10
  38. package/dist/google.constants.js +0 -14
  39. package/dist/google.constants.js.map +0 -1
  40. package/dist/product.constants.js +0 -6
  41. package/dist/product.constants.js.map +0 -1
  42. package/dist/profile.constants.js +0 -356
  43. package/dist/profile.constants.js.map +0 -1
@@ -0,0 +1,348 @@
1
+ import {
2
+ OptionType,
3
+ OptionTypeItem,
4
+ OptionTypeGroup,
5
+ ProductUploadProfile,
6
+ } from '../types/profile.types.js';
7
+ import { ProductUploadMappings } from '../constants/profile.constants.js';
8
+ import { ProductUploadMapping } from '../types/profile.types.js';
9
+ import {
10
+ ProductUploadRuleFilterType,
11
+ RuleOperatorsType,
12
+ } from '../types/profile.types.js';
13
+ import {
14
+ ProductUploadRuleItem,
15
+ ProductUploadRuleSection,
16
+ ProductUploadRules,
17
+ } from '../types/profile.types.js';
18
+ import { code } from './utils.js';
19
+
20
+ export function checkRuleDuplication (rules: ProductUploadRuleItem[]): string[] {
21
+ return rules
22
+ .map((r) => {
23
+ for (const rule of rules) {
24
+ if (
25
+ r.id !== rule.id &&
26
+ r.attribute === rule.attribute &&
27
+ r.operator === rule.operator &&
28
+ r.value === rule.value
29
+ ) {
30
+ return r.id;
31
+ }
32
+ }
33
+ return null;
34
+ })
35
+ .filter(Boolean) as string[];
36
+ }
37
+
38
+ export function checkRuleAlwaysness (rules: ProductUploadRuleItem[]): string[] {
39
+ return rules
40
+ .map((r) => {
41
+ for (const rule of rules) {
42
+ if (isExlusive(r, rule)) {
43
+ return r.id;
44
+ }
45
+ }
46
+ return null;
47
+ })
48
+ .filter(Boolean) as string[];
49
+ }
50
+
51
+ export function checkRuleDeadlocks (
52
+ sections: ProductUploadRuleSection[]
53
+ ): string[] {
54
+ let totalList = [] as string[];
55
+
56
+ for (let i = 0; i < sections.length; i++) {
57
+ const currentSection = sections[i];
58
+ const currentList = [] as string[];
59
+
60
+ for (let y = 0; y < sections.length; y++) {
61
+ if (i === y) {
62
+ continue;
63
+ }
64
+
65
+ from_start: for (const ruleA of currentSection.ruleItems) {
66
+ for (const ruleB of sections[y].ruleItems) {
67
+ if (isExlusive(ruleA, ruleB)) {
68
+ currentList.push(ruleA.id);
69
+ continue from_start;
70
+ }
71
+ }
72
+ }
73
+ }
74
+
75
+ if (currentList.length === currentSection.ruleItems.length) {
76
+ totalList = [...totalList, ...currentList];
77
+ }
78
+ }
79
+
80
+ return totalList;
81
+ }
82
+
83
+ function isExlusive (
84
+ rule1: ProductUploadRuleItem,
85
+ rule2: ProductUploadRuleItem
86
+ ): boolean {
87
+ return (
88
+ rule1.id !== rule2.id &&
89
+ rule1.attribute === rule2.attribute &&
90
+ rule1.operator ===
91
+ getOperatorCounterpart(rule2.operator as keyof RuleOperatorsType) &&
92
+ rule1.value === rule2.value
93
+ );
94
+ }
95
+
96
+ function getOperatorCounterpart (
97
+ operator: keyof RuleOperatorsType
98
+ ): keyof RuleOperatorsType {
99
+ switch (operator) {
100
+ case 'equals':
101
+ return 'notEquals';
102
+ case 'notEquals':
103
+ return 'equals';
104
+ case 'contains':
105
+ return 'notContains';
106
+ case 'notContains':
107
+ return 'contains';
108
+ case 'startsWith':
109
+ return 'notStartsWith';
110
+ case 'notStartsWith':
111
+ return 'startsWith';
112
+ case 'endsWith':
113
+ return 'notEndsWith';
114
+ case 'notEndsWith':
115
+ return 'endsWith';
116
+ case 'in':
117
+ return 'notIn';
118
+ case 'notIn':
119
+ return 'in';
120
+ default:
121
+ throw new Error(`Unknown operator ${String(operator)}`);
122
+ }
123
+ }
124
+
125
+ export function getEmptyRuleItem (
126
+ attribute: ProductUploadRuleFilterType['value'] = ''
127
+ ): ProductUploadRuleItem {
128
+ return { attribute, operator: '', value: '', id: code() };
129
+ }
130
+
131
+ export function sortMappings (
132
+ a: ProductUploadMapping,
133
+ b: ProductUploadMapping
134
+ ): number {
135
+ if (!a.attribute) {
136
+ return 1;
137
+ }
138
+
139
+ if (!b.attribute) {
140
+ return -1;
141
+ }
142
+
143
+ const sourceA = ProductUploadMappings.find(
144
+ (m) => m.attribute === a.attribute
145
+ );
146
+ const sourceB = ProductUploadMappings.find(
147
+ (m) => m.attribute === b.attribute
148
+ );
149
+
150
+ if (sourceA?.required && !sourceB?.required) {
151
+ return -1;
152
+ }
153
+
154
+ if (sourceB?.required && !sourceA?.required) {
155
+ return 1;
156
+ }
157
+
158
+ if (a.attribute < b.attribute) {
159
+ return -1;
160
+ }
161
+
162
+ if (a.attribute > b.attribute) {
163
+ return 1;
164
+ }
165
+
166
+ return 0;
167
+ }
168
+
169
+ export function hasRules (rules: ProductUploadRules): boolean {
170
+ return (
171
+ Array.isArray(rules?.sections) &&
172
+ rules.sections.some((section) => section.ruleItems.length > 0)
173
+ );
174
+ }
175
+
176
+ /**
177
+ * Checks if two rules are the same
178
+ * @param a
179
+ * @param b
180
+ * @returns
181
+ */
182
+ export function compareRules (
183
+ a: ProductUploadRules = { sections: [] },
184
+ b: ProductUploadRules = { sections: [] }
185
+ ): boolean {
186
+ const matchedSections = [] as number[];
187
+ const sameRule = (
188
+ rA: ProductUploadRuleItem,
189
+ rB: ProductUploadRuleItem
190
+ ): boolean => {
191
+ return (
192
+ rA.attribute === rB.attribute &&
193
+ rA.operator === rB.operator &&
194
+ compareValues(rA.value, rB.value)
195
+ );
196
+ };
197
+
198
+ a.sections = a.sections.filter((s) => s.ruleItems.length > 0);
199
+ b.sections = b.sections.filter((s) => s.ruleItems.length > 0);
200
+
201
+ if (a.sections.length !== b.sections.length) {
202
+ return false;
203
+ }
204
+
205
+ for (let i = 0; i < a.sections.length; i++) {
206
+ const rulesA = a.sections[i].ruleItems;
207
+
208
+ for (let j = 0; j < b.sections.length; j++) {
209
+ if (matchedSections.includes(j)) {
210
+ continue;
211
+ }
212
+
213
+ const rulesB = b.sections[j].ruleItems;
214
+
215
+ if (rulesA.length !== rulesB.length) {
216
+ continue;
217
+ }
218
+
219
+ if (
220
+ rulesA.every((ruleA) => rulesB.some((ruleB) => sameRule(ruleA, ruleB)))
221
+ ) {
222
+ matchedSections.push(j);
223
+ break;
224
+ }
225
+ }
226
+ }
227
+
228
+ return matchedSections.length === a.sections.length;
229
+ }
230
+
231
+ function compareValues (a: any, b: any): boolean {
232
+ if (Array.isArray(a) && Array.isArray(b)) {
233
+ return a.length === b.length && a.every((i) => b.includes(i));
234
+ }
235
+
236
+ return a === b;
237
+ }
238
+
239
+ export function compareMappings (
240
+ a: ProductUploadMapping[],
241
+ b: ProductUploadMapping[]
242
+ ): boolean {
243
+ const matchedMappings = [] as number[];
244
+
245
+ if (a.length !== b.length) {
246
+ return false;
247
+ }
248
+
249
+ for (let i = 0; i < a.length; i++) {
250
+ const mappingA = a[i];
251
+
252
+ for (let j = 0; j < b.length; j++) {
253
+ if (matchedMappings.includes(j)) {
254
+ continue;
255
+ }
256
+
257
+ const mappingB = b[j];
258
+
259
+ if (
260
+ mappingA.attribute === mappingB.attribute &&
261
+ compareValues(mappingA.value, mappingB.value) &&
262
+ compareRules(mappingA.rules, mappingB.rules)
263
+ ) {
264
+ matchedMappings.push(j);
265
+ break;
266
+ }
267
+ }
268
+ }
269
+
270
+ return matchedMappings.length === a.length;
271
+ }
272
+ export function optionIsString (option: OptionType): option is string {
273
+ return typeof option === 'string';
274
+ }
275
+
276
+ export function optionIsItem (option: OptionType): option is OptionTypeItem {
277
+ return typeof option !== 'string' && 'value' in option;
278
+ }
279
+
280
+ export function optionIsGroup (option: OptionType): option is OptionTypeGroup {
281
+ return typeof option !== 'string' && 'options' in option;
282
+ }
283
+ export function detectProfileChange (
284
+ a: ProductUploadProfile,
285
+ b: ProductUploadProfile
286
+ ): { name: boolean; rules: boolean; mappings: boolean; id: boolean } {
287
+ const changes = {
288
+ name: false,
289
+ rules: false,
290
+ mappings: false,
291
+ id: false,
292
+ };
293
+
294
+ if (a.name !== b.name) {
295
+ changes.name = true;
296
+ }
297
+
298
+ if (a.mappings !== b.mappings) {
299
+ const mappingsA = a.mappings?.filter(
300
+ (m) =>
301
+ m.attribute !== 'targetCountry' && m.attribute !== 'contentLanguage'
302
+ );
303
+ const mappingsB = b.mappings?.filter(
304
+ (m) =>
305
+ m.attribute !== 'targetCountry' && m.attribute !== 'contentLanguage'
306
+ );
307
+ changes.mappings = !compareMappings(mappingsA, mappingsB);
308
+ }
309
+
310
+ if (
311
+ ['targetCountry', 'contentLanguage'].some((key) => {
312
+ const mappingA = a.mappings?.filter((m) => m.attribute === key) ?? [];
313
+ const mappingB = b.mappings?.filter((m) => m.attribute === key) ?? [];
314
+
315
+ return !compareMappings(mappingA, mappingB);
316
+ })
317
+ ) {
318
+ changes.id = true;
319
+ }
320
+
321
+ if (!compareRules(a.rules, b.rules)) {
322
+ changes.rules = true;
323
+ }
324
+
325
+ return changes;
326
+ }
327
+
328
+ export function sanitizeUploadProfile (
329
+ profile: ProductUploadProfile
330
+ ): ProductUploadProfile {
331
+ if (profile.rules?.sections) {
332
+ profile.rules.sections = profile.rules.sections.filter(
333
+ (section) => section.ruleItems.length > 0
334
+ );
335
+ }
336
+
337
+ profile.mappings = profile.mappings?.map((mapping) => {
338
+ if (mapping.rules?.sections) {
339
+ mapping.rules.sections = mapping.rules.sections.filter(
340
+ (section) => section.ruleItems.length > 0
341
+ );
342
+ }
343
+
344
+ return mapping;
345
+ });
346
+
347
+ return profile;
348
+ }
@@ -0,0 +1,3 @@
1
+ export function code () {
2
+ return (Math.random() * 1000000).toFixed(0);
3
+ }
package/.releaserc DELETED
@@ -1,10 +0,0 @@
1
- branches:
2
- - master
3
- repositoryUrl: "https://github.com/advertikon/package-maxify-feed-common.git"
4
- plugins:
5
- - "@semantic-release/commit-analyzer"
6
- - "@semantic-release/changelog"
7
- - "@semantic-release/release-notes-generator"
8
- - "@semantic-release/npm"
9
- - "@semantic-release/git"
10
- - "@semantic-release/github"
@@ -1,14 +0,0 @@
1
- export var GmcProductSyncStatus;
2
- (function (GmcProductSyncStatus) {
3
- GmcProductSyncStatus["REJECTED"] = "rejected";
4
- GmcProductSyncStatus["APPROVED"] = "approved";
5
- GmcProductSyncStatus["WARINING"] = "warning";
6
- GmcProductSyncStatus["SYNC_SHEDULED"] = "sync_sheduled";
7
- })(GmcProductSyncStatus || (GmcProductSyncStatus = {}));
8
- export var GoogleAccountStatus;
9
- (function (GoogleAccountStatus) {
10
- GoogleAccountStatus["ENABLED"] = "ENABLED";
11
- GoogleAccountStatus["REMOVED"] = "REMOVED";
12
- GoogleAccountStatus["REJECTED"] = "REJECTED";
13
- })(GoogleAccountStatus || (GoogleAccountStatus = {}));
14
- //# sourceMappingURL=google.constants.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"google.constants.js","sourceRoot":"","sources":["../src/common/constants/google.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,oBAKX;AALD,WAAY,oBAAoB;IAC9B,6CAAqB,CAAA;IACrB,6CAAqB,CAAA;IACrB,4CAAoB,CAAA;IACpB,uDAA+B,CAAA;AACjC,CAAC,EALW,oBAAoB,KAApB,oBAAoB,QAK/B;AAED,MAAM,CAAN,IAAY,mBAIX;AAJD,WAAY,mBAAmB;IAC7B,0CAAmB,CAAA;IACnB,0CAAmB,CAAA;IACnB,4CAAqB,CAAA;AACvB,CAAC,EAJW,mBAAmB,KAAnB,mBAAmB,QAI9B"}
@@ -1,6 +0,0 @@
1
- export var ProductSyncStatus;
2
- (function (ProductSyncStatus) {
3
- ProductSyncStatus["SYNCING"] = "syncing";
4
- ProductSyncStatus["SYNCED"] = "synced";
5
- })(ProductSyncStatus || (ProductSyncStatus = {}));
6
- //# sourceMappingURL=product.constants.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"product.constants.js","sourceRoot":"","sources":["../src/common/constants/product.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,iBAGX;AAHD,WAAY,iBAAiB;IAC3B,wCAAmB,CAAA;IACnB,sCAAiB,CAAA;AACnB,CAAC,EAHW,iBAAiB,KAAjB,iBAAiB,QAG5B"}