@uptime.app/contracts 3.0.54 → 4.0.0-rc.1

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 (250) hide show
  1. package/dist/cjs/app-hack/app-hack-metadata.d.ts +1 -0
  2. package/dist/cjs/app-hack/app-hack-metadata.d.ts.map +1 -1
  3. package/dist/cjs/cms-hack/cms-searchable-hack.d.ts +2 -0
  4. package/dist/cjs/cms-hack/cms-searchable-hack.d.ts.map +1 -1
  5. package/dist/cjs/draft-hack/draft-hack.d.ts +2 -0
  6. package/dist/cjs/draft-hack/draft-hack.d.ts.map +1 -1
  7. package/dist/cjs/enriched-hack/enriched-hack.d.ts +2 -0
  8. package/dist/cjs/enriched-hack/enriched-hack.d.ts.map +1 -1
  9. package/dist/cjs/flashcard/flashcard.d.ts +3 -1
  10. package/dist/cjs/flashcard/flashcard.d.ts.map +1 -1
  11. package/dist/cjs/hack/hack.d.ts +3 -0
  12. package/dist/cjs/hack/hack.d.ts.map +1 -1
  13. package/dist/cjs/hack-mapping/app-hack-metadata.d.ts.map +1 -1
  14. package/dist/cjs/hack-mapping/app-hack-metadata.js +1 -0
  15. package/dist/cjs/hack-mapping/app-hack-metadata.js.map +1 -1
  16. package/dist/cjs/identity-provider/identity-provider.d.ts +0 -4
  17. package/dist/cjs/identity-provider/identity-provider.d.ts.map +1 -1
  18. package/dist/cjs/index.d.ts +2 -0
  19. package/dist/cjs/index.d.ts.map +1 -1
  20. package/dist/cjs/index.js +2 -0
  21. package/dist/cjs/index.js.map +1 -1
  22. package/dist/cjs/interest/interest.d.ts +1 -0
  23. package/dist/cjs/interest/interest.d.ts.map +1 -1
  24. package/dist/cjs/pending-hack/pending-hack.d.ts +2 -0
  25. package/dist/cjs/pending-hack/pending-hack.d.ts.map +1 -1
  26. package/dist/cjs/spark/spark.d.ts +1 -1
  27. package/dist/cjs/spark/spark.d.ts.map +1 -1
  28. package/dist/cjs/topics/primary-topic-mapping.d.ts +11 -0
  29. package/dist/cjs/topics/primary-topic-mapping.d.ts.map +1 -0
  30. package/dist/cjs/topics/primary-topic-mapping.js +119 -0
  31. package/dist/cjs/topics/primary-topic-mapping.js.map +1 -0
  32. package/dist/cjs/topics/primary-topic.d.ts +4 -0
  33. package/dist/cjs/topics/primary-topic.d.ts.map +1 -0
  34. package/dist/cjs/topics/primary-topic.js +3 -0
  35. package/dist/cjs/topics/primary-topic.js.map +1 -0
  36. package/dist/esm/app-hack/app-hack-metadata.d.ts +1 -0
  37. package/dist/esm/app-hack/app-hack-metadata.d.ts.map +1 -1
  38. package/dist/esm/cms-hack/cms-searchable-hack.d.ts +2 -0
  39. package/dist/esm/cms-hack/cms-searchable-hack.d.ts.map +1 -1
  40. package/dist/esm/draft-hack/draft-hack.d.ts +2 -0
  41. package/dist/esm/draft-hack/draft-hack.d.ts.map +1 -1
  42. package/dist/esm/enriched-hack/enriched-hack.d.ts +2 -0
  43. package/dist/esm/enriched-hack/enriched-hack.d.ts.map +1 -1
  44. package/dist/esm/flashcard/flashcard.d.ts +3 -1
  45. package/dist/esm/flashcard/flashcard.d.ts.map +1 -1
  46. package/dist/esm/hack/hack.d.ts +3 -0
  47. package/dist/esm/hack/hack.d.ts.map +1 -1
  48. package/dist/esm/hack-mapping/app-hack-metadata.d.ts.map +1 -1
  49. package/dist/esm/hack-mapping/app-hack-metadata.js +1 -0
  50. package/dist/esm/hack-mapping/app-hack-metadata.js.map +1 -1
  51. package/dist/esm/identity-provider/identity-provider.d.ts +0 -4
  52. package/dist/esm/identity-provider/identity-provider.d.ts.map +1 -1
  53. package/dist/esm/index.d.ts +2 -0
  54. package/dist/esm/index.d.ts.map +1 -1
  55. package/dist/esm/index.js +2 -0
  56. package/dist/esm/index.js.map +1 -1
  57. package/dist/esm/interest/interest.d.ts +1 -0
  58. package/dist/esm/interest/interest.d.ts.map +1 -1
  59. package/dist/esm/pending-hack/pending-hack.d.ts +2 -0
  60. package/dist/esm/pending-hack/pending-hack.d.ts.map +1 -1
  61. package/dist/esm/spark/spark.d.ts +1 -1
  62. package/dist/esm/spark/spark.d.ts.map +1 -1
  63. package/dist/esm/topics/primary-topic-mapping.d.ts +11 -0
  64. package/dist/esm/topics/primary-topic-mapping.d.ts.map +1 -0
  65. package/dist/esm/topics/primary-topic-mapping.js +114 -0
  66. package/dist/esm/topics/primary-topic-mapping.js.map +1 -0
  67. package/dist/esm/topics/primary-topic.d.ts +4 -0
  68. package/dist/esm/topics/primary-topic.d.ts.map +1 -0
  69. package/dist/esm/topics/primary-topic.js +2 -0
  70. package/dist/esm/topics/primary-topic.js.map +1 -0
  71. package/package.json +2 -2
  72. package/src/access-control/collection-access-control.ts +28 -28
  73. package/src/access-control/hack-access-control.ts +32 -32
  74. package/src/access-control/profile-access-control.ts +27 -27
  75. package/src/app-hack/app-full-hack.ts +9 -9
  76. package/src/app-hack/app-hack-metadata.ts +62 -61
  77. package/src/app-hack/app-restricted-hack.ts +22 -22
  78. package/src/b2b-content-access/b2b-content-access.ts +57 -57
  79. package/src/b2b-organisation/b2b-carousel.ts +33 -33
  80. package/src/b2b-organisation/b2b-org-idp-mapping.ts +27 -27
  81. package/src/b2b-organisation/b2b-organisation-events.ts +21 -21
  82. package/src/b2b-organisation/b2b-organisation-group-events.ts +21 -21
  83. package/src/b2b-organisation/b2b-organisation-group-membership-events.ts +21 -21
  84. package/src/b2b-organisation/b2b-organisation-group-membership.ts +17 -17
  85. package/src/b2b-organisation/b2b-organisation-group.ts +42 -42
  86. package/src/b2b-organisation/b2b-organisation-invitation.ts +45 -45
  87. package/src/b2b-organisation/b2b-organisation-member-events.ts +21 -21
  88. package/src/b2b-organisation/b2b-organisation-member.ts +19 -19
  89. package/src/b2b-organisation/b2b-organisation.ts +38 -38
  90. package/src/brand/brand-events.ts +21 -21
  91. package/src/brand/brand.ts +77 -77
  92. package/src/catalogue/catalogue.ts +152 -152
  93. package/src/cms-hack/cms-searchable-hack.ts +47 -44
  94. package/src/collection/collection-events.ts +21 -21
  95. package/src/collection/collection.ts +59 -59
  96. package/src/collection/enriched-collection-events.ts +18 -18
  97. package/src/collection/enriched-collection.ts +65 -65
  98. package/src/course/course-events.ts +20 -20
  99. package/src/course/course.ts +25 -25
  100. package/src/course-enrollment/course-enrollment-events.ts +21 -21
  101. package/src/course-enrollment/course-enrollment.ts +36 -36
  102. package/src/creator/creator-events.ts +32 -32
  103. package/src/creator/creator.ts +7 -7
  104. package/src/distribution/collection-distribution.ts +17 -17
  105. package/src/distribution/distribution-events.ts +61 -61
  106. package/src/distribution/hack-distribution.ts +18 -18
  107. package/src/draft-hack/draft-hack-events.ts +21 -21
  108. package/src/draft-hack/draft-hack.ts +192 -190
  109. package/src/draft-hack-generation/draft-hack-generation-commands.ts +10 -10
  110. package/src/draft-hack-generation/draft-hack-generation-events.ts +52 -52
  111. package/src/draft-hack-generation/draft-hack-generation.ts +39 -39
  112. package/src/enriched-b2b-organisation/enriched-b2b-organisation-events.ts +21 -21
  113. package/src/enriched-b2b-organisation/enriched-b2b-organisation.ts +37 -37
  114. package/src/enriched-hack/enriched-hack-events.ts +21 -21
  115. package/src/enriched-hack/enriched-hack.ts +111 -109
  116. package/src/enrichment-asset/hack-enrichment-video-events.ts +55 -55
  117. package/src/enrichment-asset/hack-enrichment-video.ts +40 -40
  118. package/src/entitlement/user-entitlements-commands.ts +54 -54
  119. package/src/entitlement/user-entitlements-events.ts +29 -29
  120. package/src/entitlement/user-entitlements.ts +18 -18
  121. package/src/flashcard/flashcard-events.ts +85 -85
  122. package/src/flashcard/flashcard.ts +161 -138
  123. package/src/hack/extracted-subject.ts +31 -31
  124. package/src/hack/hack-events.ts +21 -21
  125. package/src/hack/hack-published.ts +21 -21
  126. package/src/hack/hack-with-voice-events.ts +20 -20
  127. package/src/hack/hack-with-voice.ts +36 -36
  128. package/src/hack/hack.ts +130 -127
  129. package/src/hack/publish-hack-command.ts +20 -20
  130. package/src/hack/republish-hack-command.ts +20 -20
  131. package/src/hack-mapping/access-helper.ts +6 -6
  132. package/src/hack-mapping/app-full-hack.test.ts +13 -13
  133. package/src/hack-mapping/app-full-hack.ts +14 -14
  134. package/src/hack-mapping/app-hack-metadata.test.ts +22 -22
  135. package/src/hack-mapping/app-hack-metadata.ts +83 -82
  136. package/src/hack-mapping/app-restricted-hack.test.ts +12 -12
  137. package/src/hack-mapping/app-restricted-hack.ts +21 -21
  138. package/src/hack-mapping/remove-undefined-fields.ts +9 -9
  139. package/src/hack-mapping/test-data/enriched-hack.json +2569 -2564
  140. package/src/hack-mapping/test-data/expected-app-full-hack.json +2502 -2497
  141. package/src/hack-mapping/test-data/expected-app-hack-metadata.json +86 -81
  142. package/src/hack-mapping/test-data/expected-app-restricted-hack.json +792 -787
  143. package/src/hack-metadata/hack-metadata-events.ts +21 -21
  144. package/src/hack-metadata/hack-metadata.ts +17 -17
  145. package/src/hack-of-the-day/hack-of-the-day-events.ts +21 -21
  146. package/src/hack-of-the-day/hack-of-the-day.ts +13 -13
  147. package/src/hack-statistics/hack-statistics-events.ts +21 -21
  148. package/src/hack-statistics/hack-statistics.ts +9 -9
  149. package/src/hackbot/hack-generation-commands.ts +45 -45
  150. package/src/hackbot/hack-generation-trigger-events.ts +21 -21
  151. package/src/hackbot/hack-generation-trigger.ts +57 -57
  152. package/src/history/history-events.ts +21 -21
  153. package/src/history/history.ts +46 -46
  154. package/src/identity-provider/domain-identity-provider-events.ts +20 -20
  155. package/src/identity-provider/domain-identity-provider.ts +10 -10
  156. package/src/identity-provider/identity-provider-events.ts +20 -20
  157. package/src/identity-provider/identity-provider.ts +47 -51
  158. package/src/index.ts +223 -220
  159. package/src/interest/interest-events.ts +21 -21
  160. package/src/interest/interest.ts +16 -15
  161. package/src/knowledge-source/knowledge-source-events.ts +21 -21
  162. package/src/knowledge-source/knowledge-source.ts +43 -43
  163. package/src/knowledge-source-parsing/knowledge-source-metadata.ts +58 -58
  164. package/src/knowledge-source-parsing/knowledge-source-parsing-commands.ts +41 -41
  165. package/src/knowledge-source-parsing/knowledge-source-parsing-events.ts +30 -30
  166. package/src/knowledge-source-parsing/podcast-metadata.ts +44 -44
  167. package/src/knowledge-source-parsing/podcast-parsing-events.ts +28 -28
  168. package/src/knowledge-source-parsing/user-hack-generation-options.ts +7 -7
  169. package/src/learn-upon/get-sqsso-url.ts +13 -13
  170. package/src/learn-upon/learn-upon-commands.ts +33 -33
  171. package/src/learn-upon/learn-upon-course-enrollment-events.ts +21 -21
  172. package/src/learn-upon/learn-upon-course-enrollment.ts +62 -62
  173. package/src/learn-upon/learn-upon-course-events.ts +21 -21
  174. package/src/learn-upon/learn-upon-course.ts +108 -108
  175. package/src/learn-upon/learn-upon-portal-events.ts +20 -20
  176. package/src/learn-upon/learn-upon-portal.ts +12 -12
  177. package/src/learn-upon/learn-upon-user-mapping-events.ts +18 -18
  178. package/src/learn-upon/learn-upon-user-mapping.ts +9 -9
  179. package/src/learn-upon/learn-upon-webhook-events.ts +80 -80
  180. package/src/learn-upon/learn-upon-webhook-types.ts +346 -346
  181. package/src/learn-upon/unenroll.ts +6 -6
  182. package/src/localisation/live-locales.ts +45 -45
  183. package/src/localisation/locale-language.ts +4 -4
  184. package/src/localisation/supported-languages.ts +11 -11
  185. package/src/localisation/supported-locales.ts +67 -67
  186. package/src/message-bus/context.ts +7 -7
  187. package/src/moderation/hack-moderation-result-events.ts +18 -18
  188. package/src/moderation/hack-moderation-result.ts +27 -27
  189. package/src/partner/partner-events.ts +21 -21
  190. package/src/partner/partner.ts +7 -7
  191. package/src/pending-hack/pending-hack-events.ts +20 -20
  192. package/src/pending-hack/pending-hack-with-voice-events.ts +20 -20
  193. package/src/pending-hack/pending-hack-with-voice.ts +25 -25
  194. package/src/pending-hack/pending-hack.ts +80 -78
  195. package/src/preferences/preferences-events.ts +15 -15
  196. package/src/preferences/preferences.ts +35 -35
  197. package/src/profile/profile-events.ts +41 -41
  198. package/src/profile/profile.ts +36 -36
  199. package/src/profile/translated-profile.ts +13 -13
  200. package/src/referral/referral-events.ts +41 -41
  201. package/src/referral/referral.ts +76 -76
  202. package/src/saved/saved-collection-events.ts +19 -19
  203. package/src/saved/saved-collection.ts +8 -8
  204. package/src/segment/segment-commands.ts +75 -75
  205. package/src/segment/segment-events.ts +42 -42
  206. package/src/segment/segment-with-voice.ts +8 -8
  207. package/src/segment/segment.ts +82 -82
  208. package/src/service-simulator/mock-request-response.ts +17 -17
  209. package/src/skin/skin-events.ts +21 -21
  210. package/src/skin/skin.ts +6 -6
  211. package/src/spark/spark-board-read-model.ts +17 -17
  212. package/src/spark/spark-board.ts +12 -12
  213. package/src/spark/spark-events.ts +42 -42
  214. package/src/spark/spark.ts +74 -75
  215. package/src/text-analysis/hack-categories-extracted-events.ts +24 -24
  216. package/src/text-analysis/hack-categories-extracted.ts +31 -31
  217. package/src/text-analysis/hack-entities-extracted-events.ts +24 -24
  218. package/src/text-analysis/hack-entities-extracted.ts +38 -38
  219. package/src/text-analysis/hack-keywords-extracted-events.ts +24 -24
  220. package/src/text-analysis/hack-keywords-extracted.ts +23 -23
  221. package/src/text-analysis/hack-topics-extracted-events.ts +24 -24
  222. package/src/text-analysis/hack-topics-extracted.ts +31 -31
  223. package/src/text-to-speech/create-speech-commands.ts +22 -22
  224. package/src/text-to-speech/speech-created-events.ts +10 -10
  225. package/src/text-to-speech/supported-voices.ts +222 -222
  226. package/src/text-to-speech/text-segment.ts +29 -29
  227. package/src/theme/theme-events.ts +21 -21
  228. package/src/theme/theme.ts +68 -68
  229. package/src/topics/primary-topic-mapping.test.ts +87 -0
  230. package/src/topics/primary-topic-mapping.ts +136 -0
  231. package/src/topics/primary-topic.ts +3 -0
  232. package/src/translation/translation-events.ts +73 -73
  233. package/src/translation/translation.ts +25 -25
  234. package/src/trending/trending-events.ts +21 -21
  235. package/src/trending/trending-hacks.ts +8 -8
  236. package/src/user/cognito-user-authentication-log.ts +7 -7
  237. package/src/user/get-user.ts +63 -63
  238. package/src/user/user-events.ts +39 -39
  239. package/src/user-acl/user-acl-utils.test.ts +273 -273
  240. package/src/user-acl/user-acl-utils.ts +176 -176
  241. package/src/user-context/user-context-events.ts +21 -21
  242. package/src/user-context/user-context.ts +15 -15
  243. package/src/user-notification-context/user-notification-context-events.ts +21 -21
  244. package/src/user-notification-context/user-notification-context.ts +9 -9
  245. package/src/user-statistics/user-statistics-events.ts +97 -97
  246. package/src/user-statistics/user-statistics.ts +82 -82
  247. package/src/video-cropping/video-cropping-events.ts +43 -43
  248. package/src/video-cropping/video-metadata.ts +12 -12
  249. package/tsconfig.cjs.json +7 -7
  250. package/tsconfig.npm.json +22 -22
@@ -1,68 +1,68 @@
1
- export interface ThemeTemplate {
2
- /** the url of the background video */
3
- backgroundVideoUrl?: string;
4
- /** the url of the background image */
5
- backgroundImageUrl?: string;
6
- /** the font color that will be used when rendering text in the foreground */
7
- fontColor: string;
8
- }
9
-
10
- export interface SegmentThemeTemplates {
11
- overview: {
12
- a: ThemeTemplate;
13
- b: ThemeTemplate;
14
- },
15
- insightOne: {
16
- // one template is for the title card
17
- // the other one for insight content
18
- a: ThemeTemplate;
19
- b: ThemeTemplate;
20
- },
21
- insightTwo: {
22
- a: ThemeTemplate;
23
- b: ThemeTemplate;
24
- },
25
- insightThree: {
26
- a: ThemeTemplate;
27
- b: ThemeTemplate;
28
- },
29
- dark: {
30
- overview: {
31
- a: ThemeTemplate;
32
- b: ThemeTemplate;
33
- },
34
- insightOne: {
35
- a: ThemeTemplate;
36
- b: ThemeTemplate;
37
- },
38
- insightTwo: {
39
- a: ThemeTemplate;
40
- b: ThemeTemplate;
41
- },
42
- insightThree: {
43
- a: ThemeTemplate;
44
- b: ThemeTemplate;
45
- }
46
- }
47
- }
48
-
49
- export interface Theme {
50
- id: string;
51
- name: string;
52
- fontFamily: string;
53
- templates: SegmentThemeTemplates;
54
- mood: 'neutral' | 'sombre' | 'vibrant';
55
- isCustom: boolean;
56
- /* properties of the story and audio player */
57
- player?: {
58
- light: {
59
- backgroundColor: string;
60
- },
61
- dark: {
62
- backgroundColor: string;
63
- }
64
- }
65
- updatedAt: string;
66
- createdAt: string;
67
- v: number;
68
- }
1
+ export interface ThemeTemplate {
2
+ /** the url of the background video */
3
+ backgroundVideoUrl?: string;
4
+ /** the url of the background image */
5
+ backgroundImageUrl?: string;
6
+ /** the font color that will be used when rendering text in the foreground */
7
+ fontColor: string;
8
+ }
9
+
10
+ export interface SegmentThemeTemplates {
11
+ overview: {
12
+ a: ThemeTemplate;
13
+ b: ThemeTemplate;
14
+ },
15
+ insightOne: {
16
+ // one template is for the title card
17
+ // the other one for insight content
18
+ a: ThemeTemplate;
19
+ b: ThemeTemplate;
20
+ },
21
+ insightTwo: {
22
+ a: ThemeTemplate;
23
+ b: ThemeTemplate;
24
+ },
25
+ insightThree: {
26
+ a: ThemeTemplate;
27
+ b: ThemeTemplate;
28
+ },
29
+ dark: {
30
+ overview: {
31
+ a: ThemeTemplate;
32
+ b: ThemeTemplate;
33
+ },
34
+ insightOne: {
35
+ a: ThemeTemplate;
36
+ b: ThemeTemplate;
37
+ },
38
+ insightTwo: {
39
+ a: ThemeTemplate;
40
+ b: ThemeTemplate;
41
+ },
42
+ insightThree: {
43
+ a: ThemeTemplate;
44
+ b: ThemeTemplate;
45
+ }
46
+ }
47
+ }
48
+
49
+ export interface Theme {
50
+ id: string;
51
+ name: string;
52
+ fontFamily: string;
53
+ templates: SegmentThemeTemplates;
54
+ mood: 'neutral' | 'sombre' | 'vibrant';
55
+ isCustom: boolean;
56
+ /* properties of the story and audio player */
57
+ player?: {
58
+ light: {
59
+ backgroundColor: string;
60
+ },
61
+ dark: {
62
+ backgroundColor: string;
63
+ }
64
+ }
65
+ updatedAt: string;
66
+ createdAt: string;
67
+ v: number;
68
+ }
@@ -0,0 +1,87 @@
1
+ import {
2
+ TOPIC_TO_PRIMARY_TOPIC_FUZZY_MAPPING,
3
+ fuzzyMapTopicsToPrimaryTopics,
4
+ mapPrimaryTopicsToOldTopics,
5
+ OLD_TOPIC_TAGS,
6
+ VALID_PRIMARY_TOPIC_TAGS
7
+ } from './primary-topic-mapping';
8
+
9
+ describe('mapPrimaryTopicsToOldTopics', () => {
10
+ test('maps split primary topics back to their old topic', () => {
11
+ expect(mapPrimaryTopicsToOldTopics(['Politics, Law & Economics'])).toEqual(['Culture & Society']);
12
+ expect(mapPrimaryTopicsToOldTopics(['Communication'])).toEqual(['Personal Growth']);
13
+ expect(mapPrimaryTopicsToOldTopics(['AI & Technology'])).toEqual(['Technology & the Future']);
14
+ });
15
+
16
+ test('supports PrimaryTopic objects', () => {
17
+ expect(mapPrimaryTopicsToOldTopics([{ name: 'Career Success' }])).toEqual(['Career & Success']);
18
+ });
19
+
20
+ test('returns no matching topic for unknown topics', () => {
21
+ expect(mapPrimaryTopicsToOldTopics(['Unknown Topic'])).toEqual([]);
22
+ });
23
+
24
+ test('maps every valid primary topic tag to a known old topic tag', () => {
25
+ for (const primaryTopic of VALID_PRIMARY_TOPIC_TAGS) {
26
+ const oldTopic = mapPrimaryTopicsToOldTopics([primaryTopic])[0];
27
+ expect(oldTopic).toBeDefined();
28
+ expect(OLD_TOPIC_TAGS).toContain(oldTopic);
29
+ }
30
+ });
31
+ test('deduplicates old topics while preserving input order', () => {
32
+ expect(
33
+ mapPrimaryTopicsToOldTopics([
34
+ { name: 'Marketing' },
35
+ { name: 'Sales' },
36
+ { name: 'Biographies' },
37
+ { name: 'Marketing' },
38
+ { name: 'Unknown Topic' }
39
+ ])
40
+ ).toEqual(['Marketing & Sales', 'Biographies']);
41
+ });
42
+ });
43
+
44
+ describe('mapFuzzyTopicsToPrimaryTopics', () => {
45
+ test('maps broad fuzzy topics to multiple primary topics', () => {
46
+ expect(fuzzyMapTopicsToPrimaryTopics(['Health & Fitness'])).toEqual([
47
+ 'Nutrition & Health',
48
+ 'Fitness & Sports',
49
+ 'Mental Health',
50
+ 'Neurodiversity'
51
+ ]);
52
+ });
53
+
54
+ test('maps single fuzzy topics to their primary topic', () => {
55
+ expect(fuzzyMapTopicsToPrimaryTopics(['Biographies'])).toEqual(['Biographies']);
56
+ });
57
+
58
+ test('supports topic objects', () => {
59
+ expect(fuzzyMapTopicsToPrimaryTopics([{ name: 'Career & Success' }])).toEqual(['Career Success']);
60
+ });
61
+
62
+ test('returns an empty array for unknown topics', () => {
63
+ expect(fuzzyMapTopicsToPrimaryTopics(['Unknown Topic'])).toEqual([]);
64
+ });
65
+
66
+ test('deduplicates primary topics while preserving input and mapping order', () => {
67
+ expect(
68
+ fuzzyMapTopicsToPrimaryTopics([
69
+ { name: 'Marketing & Sales' },
70
+ { name: 'Business' },
71
+ { name: 'Marketing & Sales' },
72
+ { name: 'Unknown Topic' }
73
+ ])
74
+ ).toEqual(['Marketing', 'Sales', 'Business']);
75
+ });
76
+
77
+ test('maps every fuzzy topic tag to valid primary topic tags', () => {
78
+ for (const fuzzyTopic of OLD_TOPIC_TAGS) {
79
+ const primaryTopics = TOPIC_TO_PRIMARY_TOPIC_FUZZY_MAPPING[fuzzyTopic];
80
+
81
+ expect(primaryTopics.length).toBeGreaterThan(0);
82
+ for (const primaryTopic of primaryTopics) {
83
+ expect(VALID_PRIMARY_TOPIC_TAGS).toContain(primaryTopic);
84
+ }
85
+ }
86
+ });
87
+ });
@@ -0,0 +1,136 @@
1
+ import { PrimaryTopic } from './primary-topic';
2
+
3
+ export const VALID_PRIMARY_TOPIC_TAGS = [
4
+ 'Arts & Design',
5
+ 'Biographies',
6
+ 'Business',
7
+ 'Career Success',
8
+ 'Communication',
9
+ 'Education & Studying',
10
+ 'Entrepreneurship',
11
+ 'Environment',
12
+ 'Fitness & Sports',
13
+ 'History',
14
+ 'Home & Hobbies',
15
+ 'Humanity & Societies',
16
+ 'Identity & Equality',
17
+ 'Investing',
18
+ 'Leadership & Management',
19
+ 'Marketing',
20
+ 'Media & Entertainment',
21
+ 'Mental Health',
22
+ 'Mindfulness',
23
+ 'Money & Finances',
24
+ 'Neurodiversity',
25
+ 'Nutrition & Health',
26
+ 'Parenting & Family',
27
+ 'Personal Growth',
28
+ 'Politics, Law & Economics',
29
+ 'Psychology & Philosophy',
30
+ 'Relationships',
31
+ 'Religion',
32
+ 'Sales',
33
+ 'Science',
34
+ 'Sex',
35
+ 'AI & Technology'
36
+ ] as const;
37
+
38
+ export const OLD_TOPIC_TAGS = [
39
+ 'Arts & Design',
40
+ 'Biographies',
41
+ 'Business',
42
+ 'Culture & Society',
43
+ 'Career & Success',
44
+ 'Education',
45
+ 'Health & Fitness',
46
+ 'History',
47
+ 'Leadership & Entrepreneurship',
48
+ 'Lifestyle',
49
+ 'Marketing & Sales',
50
+ 'Mind & Philosophy',
51
+ 'Money & Investing',
52
+ 'Parenting & Relationships',
53
+ 'Personal Growth',
54
+ 'Religion & Spirituality',
55
+ 'Science & the Environment',
56
+ 'Technology & the Future'
57
+ ] as const;
58
+
59
+ export type PrimaryTopicTag = (typeof VALID_PRIMARY_TOPIC_TAGS)[number];
60
+ export type OldTopicTag = (typeof OLD_TOPIC_TAGS)[number];
61
+
62
+ export const TOPIC_TO_PRIMARY_TOPIC_FUZZY_MAPPING: Record<OldTopicTag, PrimaryTopicTag[]> = {
63
+ 'Arts & Design': ['Arts & Design', 'Media & Entertainment'],
64
+ 'Biographies': ['Biographies'],
65
+ 'Business': ['Business'],
66
+ 'Culture & Society': ['Identity & Equality', 'Politics, Law & Economics', 'Humanity & Societies'],
67
+ 'Career & Success': ['Career Success'],
68
+ 'Education': ['Education & Studying'],
69
+ 'Health & Fitness': ['Nutrition & Health', 'Fitness & Sports', 'Mental Health', 'Neurodiversity'],
70
+ 'History': ['History'],
71
+ 'Leadership & Entrepreneurship': ['Leadership & Management', 'Entrepreneurship'],
72
+ 'Lifestyle': ['Home & Hobbies'],
73
+ 'Marketing & Sales': ['Marketing', 'Sales'],
74
+ 'Mind & Philosophy': ['Mindfulness', 'Psychology & Philosophy'],
75
+ 'Money & Investing': ['Money & Finances', 'Investing'],
76
+ 'Parenting & Relationships': ['Sex', 'Relationships', 'Parenting & Family'],
77
+ 'Personal Growth': ['Personal Growth', 'Communication'],
78
+ 'Religion & Spirituality': ['Religion'],
79
+ 'Science & the Environment': ['Science', 'Environment'],
80
+ 'Technology & the Future': ['AI & Technology']
81
+ };
82
+
83
+ const PRIMARY_TOPIC_TO_OLD_TOPIC_MAPPING = Object.entries(TOPIC_TO_PRIMARY_TOPIC_FUZZY_MAPPING).reduce(
84
+ (mapping, [oldTopic, primaryTopics]) => {
85
+ for (const primaryTopic of primaryTopics) {
86
+ mapping[primaryTopic] = oldTopic as OldTopicTag;
87
+ }
88
+
89
+ return mapping;
90
+ },
91
+ {} as Record<PrimaryTopicTag, OldTopicTag>
92
+ );
93
+
94
+ function topicNameOf(topic: { name: string } | string): string {
95
+ return typeof topic === 'string' ? topic : topic.name;
96
+ }
97
+
98
+ function addIfNotPresent<T>(items: T[], item: T): void {
99
+ if (items.indexOf(item) === -1) {
100
+ items.push(item);
101
+ }
102
+ }
103
+
104
+ function mapPrimaryTopicToOldTopic(primaryTopic: PrimaryTopic | string): OldTopicTag | undefined {
105
+ return PRIMARY_TOPIC_TO_OLD_TOPIC_MAPPING[topicNameOf(primaryTopic) as PrimaryTopicTag];
106
+ }
107
+
108
+ export function mapPrimaryTopicsToOldTopics(primaryTopics: Array<PrimaryTopic | string>): OldTopicTag[] {
109
+ const oldTopics: OldTopicTag[] = [];
110
+
111
+ for (const primaryTopic of primaryTopics) {
112
+ const oldTopic = mapPrimaryTopicToOldTopic(primaryTopic);
113
+
114
+ if (oldTopic !== undefined) {
115
+ addIfNotPresent(oldTopics, oldTopic);
116
+ }
117
+ }
118
+
119
+ return oldTopics;
120
+ }
121
+
122
+ function fuzzyMapTopicToPrimaryTopics(fuzzyTopic: { name: string } | string): PrimaryTopicTag[] {
123
+ return TOPIC_TO_PRIMARY_TOPIC_FUZZY_MAPPING[topicNameOf(fuzzyTopic) as OldTopicTag] ?? [];
124
+ }
125
+
126
+ export function fuzzyMapTopicsToPrimaryTopics(fuzzyTopics: Array<{ name: string } | string>): PrimaryTopicTag[] {
127
+ const primaryTopics: PrimaryTopicTag[] = [];
128
+
129
+ for (const fuzzyTopic of fuzzyTopics) {
130
+ for (const primaryTopic of fuzzyMapTopicToPrimaryTopics(fuzzyTopic)) {
131
+ addIfNotPresent(primaryTopics, primaryTopic);
132
+ }
133
+ }
134
+
135
+ return primaryTopics;
136
+ }
@@ -0,0 +1,3 @@
1
+ export interface PrimaryTopic {
2
+ name: string;
3
+ }
@@ -1,73 +1,73 @@
1
- import { SupportedLocale } from '../localisation/supported-locales';
2
- import { ObjectToTranslate, TextWithTranslation } from './translation';
3
- import { Text } from './translation';
4
-
5
- export interface TextTranslatedEvent {
6
- id: string;
7
- type: 'TextTranslated';
8
- payload: {
9
- reference: string;
10
- fromLocale: string;
11
- toLocale: string;
12
- text: TextWithTranslation[];
13
- };
14
- }
15
-
16
- export interface ObjectsTranslatedEvent {
17
- id: string;
18
- type: 'ObjectsTranslated';
19
- payload: {
20
- reference: string;
21
- fromLocale: string;
22
- toLocale: string;
23
- translatedObjects: TranslatedObject[];
24
- };
25
- }
26
-
27
- export interface TranslatedObject {
28
- translatedObject: any;
29
- reference: string;
30
- }
31
-
32
- /**
33
- * Translate JSON objects using Chat GPT
34
- */
35
- export interface TranslateObjectsCommand {
36
- id: string;
37
- type: 'TranslateObjects';
38
- payload: TranslateObjectsCommandPayload;
39
- }
40
-
41
- export interface TranslateObjectsCommandPayload {
42
- /**
43
- * Identifier set by the creator of the command. It also shows up in the TextTranslated event and
44
- * it has the same value as in the original command, so that interested services can match their command to the event.
45
- */
46
- reference: string;
47
- fromLocale: SupportedLocale;
48
- toLocale: SupportedLocale;
49
- objectsToTranslate: ObjectToTranslate[];
50
- /**
51
- * Optional model to use for translation. If not provided, the default model will be used.
52
- * It used to be a SupportedGptModel enum
53
- */
54
- chatGptModel?: string;
55
- }
56
-
57
- export interface TranslateTextCommand {
58
- id: string;
59
- type: 'TranslateText';
60
- payload: TranslateTextCommandPayload
61
- }
62
-
63
- export interface TranslateTextCommandPayload {
64
- /**
65
- * Identifier set by the creator of the command. It also shows up in the TextTranslated event and
66
- * it has the same value as in the original command, so that interested services can match their command to the event.
67
- */
68
- reference: string;
69
- // TODO fromLocale and toLocale to use contracts' SupportedLocales
70
- fromLocale: string;
71
- toLocale: string;
72
- text: Text[];
73
- }
1
+ import { SupportedLocale } from '../localisation/supported-locales';
2
+ import { ObjectToTranslate, TextWithTranslation } from './translation';
3
+ import { Text } from './translation';
4
+
5
+ export interface TextTranslatedEvent {
6
+ id: string;
7
+ type: 'TextTranslated';
8
+ payload: {
9
+ reference: string;
10
+ fromLocale: string;
11
+ toLocale: string;
12
+ text: TextWithTranslation[];
13
+ };
14
+ }
15
+
16
+ export interface ObjectsTranslatedEvent {
17
+ id: string;
18
+ type: 'ObjectsTranslated';
19
+ payload: {
20
+ reference: string;
21
+ fromLocale: string;
22
+ toLocale: string;
23
+ translatedObjects: TranslatedObject[];
24
+ };
25
+ }
26
+
27
+ export interface TranslatedObject {
28
+ translatedObject: any;
29
+ reference: string;
30
+ }
31
+
32
+ /**
33
+ * Translate JSON objects using Chat GPT
34
+ */
35
+ export interface TranslateObjectsCommand {
36
+ id: string;
37
+ type: 'TranslateObjects';
38
+ payload: TranslateObjectsCommandPayload;
39
+ }
40
+
41
+ export interface TranslateObjectsCommandPayload {
42
+ /**
43
+ * Identifier set by the creator of the command. It also shows up in the TextTranslated event and
44
+ * it has the same value as in the original command, so that interested services can match their command to the event.
45
+ */
46
+ reference: string;
47
+ fromLocale: SupportedLocale;
48
+ toLocale: SupportedLocale;
49
+ objectsToTranslate: ObjectToTranslate[];
50
+ /**
51
+ * Optional model to use for translation. If not provided, the default model will be used.
52
+ * It used to be a SupportedGptModel enum
53
+ */
54
+ chatGptModel?: string;
55
+ }
56
+
57
+ export interface TranslateTextCommand {
58
+ id: string;
59
+ type: 'TranslateText';
60
+ payload: TranslateTextCommandPayload
61
+ }
62
+
63
+ export interface TranslateTextCommandPayload {
64
+ /**
65
+ * Identifier set by the creator of the command. It also shows up in the TextTranslated event and
66
+ * it has the same value as in the original command, so that interested services can match their command to the event.
67
+ */
68
+ reference: string;
69
+ // TODO fromLocale and toLocale to use contracts' SupportedLocales
70
+ fromLocale: string;
71
+ toLocale: string;
72
+ text: Text[];
73
+ }
@@ -1,25 +1,25 @@
1
- export interface Text {
2
- /**
3
- * Identifier set by the creator of the command. TextWithTranslation entities have the same
4
- * references as in the original command, so that they can be easily matched by the receiving service.
5
- */
6
- reference: string;
7
- content: string;
8
- }
9
-
10
- export interface ObjectToTranslate {
11
- /**
12
- * Stringified size must be lower than 7000 characters so that it can work with ChatGPT
13
- */
14
- objectToTranslate: any;
15
- translationCacheKey: string;
16
- /** refresh the cache item */
17
- refreshCache?: boolean
18
- reference: string;
19
- /** additional text that will be added to the GPT prompt when requesting translation */
20
- promptAdditions?: string;
21
- }
22
-
23
- export interface TextWithTranslation extends Text {
24
- translation: string;
25
- }
1
+ export interface Text {
2
+ /**
3
+ * Identifier set by the creator of the command. TextWithTranslation entities have the same
4
+ * references as in the original command, so that they can be easily matched by the receiving service.
5
+ */
6
+ reference: string;
7
+ content: string;
8
+ }
9
+
10
+ export interface ObjectToTranslate {
11
+ /**
12
+ * Stringified size must be lower than 7000 characters so that it can work with ChatGPT
13
+ */
14
+ objectToTranslate: any;
15
+ translationCacheKey: string;
16
+ /** refresh the cache item */
17
+ refreshCache?: boolean
18
+ reference: string;
19
+ /** additional text that will be added to the GPT prompt when requesting translation */
20
+ promptAdditions?: string;
21
+ }
22
+
23
+ export interface TextWithTranslation extends Text {
24
+ translation: string;
25
+ }
@@ -1,21 +1,21 @@
1
- import { TrendingHacks } from './trending-hacks';
2
-
3
- export interface TrendingHacksCreatedEvent {
4
- id: string;
5
- type: 'TrendingHacksCreated';
6
- payload: TrendingHacks;
7
- }
8
-
9
- export interface TrendingHacksUpdatedEvent {
10
- id: string;
11
- type: 'TrendingHacksUpdated';
12
- payload: TrendingHacks;
13
- }
14
-
15
- export interface TrendingHacksDeletedEvent {
16
- id: string;
17
- type: 'TrendingHacksDeleted';
18
- payload: TrendingHacks;
19
- }
20
-
21
- export type TrendingHacksChangedEvent = TrendingHacksCreatedEvent | TrendingHacksUpdatedEvent | TrendingHacksDeletedEvent;
1
+ import { TrendingHacks } from './trending-hacks';
2
+
3
+ export interface TrendingHacksCreatedEvent {
4
+ id: string;
5
+ type: 'TrendingHacksCreated';
6
+ payload: TrendingHacks;
7
+ }
8
+
9
+ export interface TrendingHacksUpdatedEvent {
10
+ id: string;
11
+ type: 'TrendingHacksUpdated';
12
+ payload: TrendingHacks;
13
+ }
14
+
15
+ export interface TrendingHacksDeletedEvent {
16
+ id: string;
17
+ type: 'TrendingHacksDeleted';
18
+ payload: TrendingHacks;
19
+ }
20
+
21
+ export type TrendingHacksChangedEvent = TrendingHacksCreatedEvent | TrendingHacksUpdatedEvent | TrendingHacksDeletedEvent;
@@ -1,8 +1,8 @@
1
- export interface TrendingHacks {
2
- id: string;
3
- v: number;
4
- createdAt: string;
5
- updatedAt: string;
6
- date: string;
7
- hackIds: string[];
8
- }
1
+ export interface TrendingHacks {
2
+ id: string;
3
+ v: number;
4
+ createdAt: string;
5
+ updatedAt: string;
6
+ date: string;
7
+ hackIds: string[];
8
+ }
@@ -1,8 +1,8 @@
1
- export interface CognitoUserAuthenticationLog {
2
- id: string;
3
- v: number;
4
- createdAt: string;
5
- updatedAt: string;
6
- cognitoUserId: string;
7
- lastAuthenticatedAt: string;
1
+ export interface CognitoUserAuthenticationLog {
2
+ id: string;
3
+ v: number;
4
+ createdAt: string;
5
+ updatedAt: string;
6
+ cognitoUserId: string;
7
+ lastAuthenticatedAt: string;
8
8
  }