musora-content-services 2.122.7 → 2.123.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 (220) hide show
  1. package/.coderabbit.yaml +0 -0
  2. package/.editorconfig +0 -0
  3. package/.github/pull_request_template.md +0 -0
  4. package/.github/workflows/conventional-commits.yaml +0 -0
  5. package/.github/workflows/docs.js.yml +0 -0
  6. package/.github/workflows/node.js.yml +0 -0
  7. package/.prettierignore +0 -0
  8. package/.prettierrc +0 -0
  9. package/CHANGELOG.md +21 -0
  10. package/CLAUDE.md +1 -1
  11. package/README.md +0 -0
  12. package/babel.config.cjs +0 -0
  13. package/jest.config.js +0 -0
  14. package/jsdoc.json +0 -0
  15. package/package.json +1 -1
  16. package/src/constants/award-assets.js +0 -0
  17. package/src/constants/membership-permissions.ts +0 -0
  18. package/src/contentMetaData.js +10 -0
  19. package/src/filterBuilder.js +0 -0
  20. package/src/index.d.ts +4 -0
  21. package/src/index.js +4 -0
  22. package/src/infrastructure/http/HttpClient.ts +0 -0
  23. package/src/infrastructure/http/executors/FetchRequestExecutor.ts +0 -0
  24. package/src/infrastructure/http/index.ts +0 -0
  25. package/src/infrastructure/http/interfaces/HeaderProvider.ts +0 -0
  26. package/src/infrastructure/http/interfaces/HttpError.ts +0 -0
  27. package/src/infrastructure/http/interfaces/NetworkError.ts +0 -0
  28. package/src/infrastructure/http/interfaces/RequestExecutor.ts +0 -0
  29. package/src/infrastructure/http/interfaces/RequestOptions.ts +0 -0
  30. package/src/infrastructure/http/providers/DefaultHeaderProvider.ts +0 -0
  31. package/src/lib/ads/monoid.ts +0 -0
  32. package/src/lib/ads/semigroup.ts +0 -0
  33. package/src/lib/brands.ts +0 -0
  34. package/src/lib/lastUpdated.js +0 -0
  35. package/src/lib/sanity/filter.ts +0 -0
  36. package/src/lib/sanity/query.ts +0 -0
  37. package/src/services/api/types.js +0 -0
  38. package/src/services/api/types.ts +0 -0
  39. package/src/services/awards/award-callbacks.js +0 -0
  40. package/src/services/awards/award-query.js +0 -0
  41. package/src/services/awards/internal/.indexignore +0 -0
  42. package/src/services/awards/internal/award-definitions.js +0 -0
  43. package/src/services/awards/internal/award-events.js +0 -0
  44. package/src/services/awards/internal/award-manager.js +0 -0
  45. package/src/services/awards/internal/certificate-builder.js +0 -0
  46. package/src/services/awards/internal/completion-data-generator.js +0 -0
  47. package/src/services/awards/internal/content-progress-observer.js +0 -0
  48. package/src/services/awards/internal/image-utils.js +0 -0
  49. package/src/services/awards/internal/message-generator.js +0 -0
  50. package/src/services/awards/internal/types.js +0 -0
  51. package/src/services/awards/types.d.ts +0 -0
  52. package/src/services/awards/types.js +0 -0
  53. package/src/services/config.js +0 -0
  54. package/src/services/content/artist.ts +0 -0
  55. package/src/services/content/content.ts +0 -0
  56. package/src/services/content/genre.ts +0 -0
  57. package/src/services/content/instructor.ts +0 -0
  58. package/src/services/content-org/content-org.js +0 -0
  59. package/src/services/content-org/guided-courses.ts +0 -0
  60. package/src/services/content-org/learning-paths.ts +3 -7
  61. package/src/services/content-org/playlists-types.js +0 -0
  62. package/src/services/content-org/playlists.js +0 -0
  63. package/src/services/content.js +3 -3
  64. package/src/services/contentAggregator.js +0 -0
  65. package/src/services/contentLikes.js +0 -0
  66. package/src/services/contentProgress.js +0 -0
  67. package/src/services/dataContext.js +0 -0
  68. package/src/services/dateUtils.js +0 -0
  69. package/src/services/eventsAPI.js +0 -0
  70. package/src/services/forums/categories.ts +0 -0
  71. package/src/services/forums/forums.ts +0 -0
  72. package/src/services/forums/threads.ts +0 -0
  73. package/src/services/forums/types.ts +0 -0
  74. package/src/services/gamification/awards.ts +0 -0
  75. package/src/services/gamification/gamification.js +0 -0
  76. package/src/services/imageSRCBuilder.js +0 -0
  77. package/src/services/imageSRCVerify.js +0 -0
  78. package/src/services/liveTesting.ts +0 -0
  79. package/src/services/permissions/PermissionsAdapterFactory.ts +0 -0
  80. package/src/services/permissions/PermissionsV1Adapter.ts +0 -0
  81. package/src/services/permissions/PermissionsV2Adapter.ts +0 -0
  82. package/src/services/permissions/README.md +0 -0
  83. package/src/services/permissions/index.ts +0 -0
  84. package/src/services/progress-events.js +0 -0
  85. package/src/services/progress-row/base.js +0 -0
  86. package/src/services/progress-row/rows/.indexignore +0 -0
  87. package/src/services/progress-row/rows/method-card.js +0 -0
  88. package/src/services/progress-row/rows/playlist-card.js +0 -0
  89. package/src/services/railcontent.js +0 -0
  90. package/src/services/recommendations.js +26 -13
  91. package/src/services/reporting/README.md +0 -0
  92. package/src/services/reporting/types.ts +0 -0
  93. package/src/services/sentry/.indexignore +0 -0
  94. package/src/services/sentry/index.ts +0 -0
  95. package/src/services/sync/.indexignore +0 -0
  96. package/src/services/sync/adapters/factory.ts +0 -0
  97. package/src/services/sync/adapters/lokijs.ts +0 -0
  98. package/src/services/sync/adapters/sqlite.ts +0 -0
  99. package/src/services/sync/context/index.ts +0 -0
  100. package/src/services/sync/context/providers/base.ts +0 -0
  101. package/src/services/sync/context/providers/connectivity.ts +0 -0
  102. package/src/services/sync/context/providers/durability.ts +0 -0
  103. package/src/services/sync/context/providers/index.ts +0 -0
  104. package/src/services/sync/context/providers/session.ts +0 -0
  105. package/src/services/sync/context/providers/tabs.ts +0 -0
  106. package/src/services/sync/context/providers/visibility.ts +0 -0
  107. package/src/services/sync/database/factory.ts +0 -0
  108. package/src/services/sync/effects/index.ts +0 -0
  109. package/src/services/sync/effects/logout-warning.ts +0 -0
  110. package/src/services/sync/errors/boundary.ts +0 -0
  111. package/src/services/sync/errors/index.ts +0 -0
  112. package/src/services/sync/errors/validators.ts +0 -0
  113. package/src/services/sync/fetch.ts +0 -0
  114. package/src/services/sync/index.ts +0 -0
  115. package/src/services/sync/manager.ts +0 -0
  116. package/src/services/sync/models/Base.ts +0 -0
  117. package/src/services/sync/models/ContentLike.ts +0 -0
  118. package/src/services/sync/models/ContentProgress.ts +0 -0
  119. package/src/services/sync/models/Practice.ts +0 -0
  120. package/src/services/sync/models/PracticeDayNote.ts +0 -0
  121. package/src/services/sync/models/UserAwardProgress.ts +0 -0
  122. package/src/services/sync/models/index.ts +0 -0
  123. package/src/services/sync/repositories/base.ts +0 -0
  124. package/src/services/sync/repositories/content-likes.ts +0 -0
  125. package/src/services/sync/repositories/content-progress.ts +3 -1
  126. package/src/services/sync/repositories/index.ts +0 -0
  127. package/src/services/sync/repositories/practice-day-notes.ts +0 -0
  128. package/src/services/sync/repositories/practices.ts +0 -0
  129. package/src/services/sync/repositories/user-award-progress.ts +0 -0
  130. package/src/services/sync/repository-proxy.ts +0 -0
  131. package/src/services/sync/resolver.ts +9 -1
  132. package/src/services/sync/retry.ts +0 -0
  133. package/src/services/sync/run-scope.ts +0 -0
  134. package/src/services/sync/schema/index.ts +0 -0
  135. package/src/services/sync/serializers/index.ts +0 -0
  136. package/src/services/sync/serializers/model.ts +0 -0
  137. package/src/services/sync/serializers/raw.ts +0 -0
  138. package/src/services/sync/store/index.ts +7 -1
  139. package/src/services/sync/store/push-coalescer.ts +0 -0
  140. package/src/services/sync/store-configs.ts +0 -0
  141. package/src/services/sync/strategies/base.ts +0 -0
  142. package/src/services/sync/strategies/index.ts +0 -0
  143. package/src/services/sync/strategies/initial.ts +0 -0
  144. package/src/services/sync/strategies/polling.ts +0 -0
  145. package/src/services/sync/telemetry/flood-prevention.ts +0 -0
  146. package/src/services/sync/telemetry/index.ts +9 -6
  147. package/src/services/sync/telemetry/sampling.ts +0 -0
  148. package/src/services/sync/utils/event-emitter.ts +0 -0
  149. package/src/services/sync/utils/index.ts +0 -0
  150. package/src/services/sync/utils/throttle.ts +0 -0
  151. package/src/services/sync/utils/timers.ts +0 -0
  152. package/src/services/types.js +0 -0
  153. package/src/services/user/account.ts +0 -0
  154. package/src/services/user/chat.js +0 -0
  155. package/src/services/user/interests.js +0 -0
  156. package/src/services/user/management.js +0 -0
  157. package/src/services/user/memberships.ts +0 -0
  158. package/src/services/user/notifications.js +0 -0
  159. package/src/services/user/onboarding.ts +0 -0
  160. package/src/services/user/payments.ts +0 -0
  161. package/src/services/user/permissions.js +0 -0
  162. package/src/services/user/profile.js +0 -0
  163. package/src/services/user/sessions.js +24 -29
  164. package/src/services/user/streakCalculator.ts +0 -0
  165. package/src/services/user/types.d.ts +0 -0
  166. package/src/services/user/types.js +0 -0
  167. package/src/services/user/user-management-system.js +0 -0
  168. package/test/HttpClient.test.js +0 -0
  169. package/test/awards/award-alacarte-observer.test.js +0 -0
  170. package/test/awards/award-auto-refresh.test.js +0 -0
  171. package/test/awards/award-calculations.test.js +0 -0
  172. package/test/awards/award-certificate-display.test.js +0 -0
  173. package/test/awards/award-collection-edge-cases.test.js +0 -0
  174. package/test/awards/award-collection-filtering.test.js +0 -0
  175. package/test/awards/award-completion-flow.test.js +0 -0
  176. package/test/awards/award-exclusion-handling.test.js +0 -0
  177. package/test/awards/award-multi-lesson.test.js +0 -0
  178. package/test/awards/award-observer-integration.test.js +0 -0
  179. package/test/awards/award-query-messages.test.js +0 -0
  180. package/test/awards/award-user-collection.test.js +0 -0
  181. package/test/awards/duplicate-prevention.test.js +0 -0
  182. package/test/awards/helpers/completion-mock.js +0 -0
  183. package/test/awards/helpers/index.js +0 -0
  184. package/test/awards/helpers/mock-setup.js +0 -0
  185. package/test/awards/helpers/progress-emitter.js +0 -0
  186. package/test/awards/message-generator.test.js +0 -0
  187. package/test/content.test.js +0 -0
  188. package/test/contentLikes.test.js +0 -0
  189. package/test/contentProgress.test.js +0 -0
  190. package/test/dataContext.test.js +0 -0
  191. package/test/forum.test.js +0 -0
  192. package/test/imageSRCBuilder.test.js +0 -0
  193. package/test/imageSRCVerify.test.js +0 -0
  194. package/test/initializeTests.js +0 -0
  195. package/test/learningPaths.test.js +0 -0
  196. package/test/lib/__snapshots__/filter.test.ts.snap +0 -0
  197. package/test/lib/filter.test.ts +0 -0
  198. package/test/lib/lastUpdated.test.js +0 -0
  199. package/test/lib/query.test.ts +0 -0
  200. package/test/live/contentProgressLive.test.js +0 -0
  201. package/test/live/railcontentLive.test.js +0 -0
  202. package/test/localStorageMock.js +0 -0
  203. package/test/log.js +0 -0
  204. package/test/mockData/award-definitions.js +0 -0
  205. package/test/mockData/mockData_fetchByRailContentIds_one_content.json +0 -0
  206. package/test/mockData/mockData_progress_content.json +0 -0
  207. package/test/mockData/mockData_sanity_progress_content.json +0 -0
  208. package/test/mockData/mockData_user_practices.json +0 -0
  209. package/test/notifications.test.js +0 -0
  210. package/test/progressRows.test.js +0 -0
  211. package/test/sanityQueryService.test.js +0 -0
  212. package/test/streakMessage.test.js +0 -0
  213. package/test/sync/adapter.ts +0 -0
  214. package/test/sync/initialize-sync-manager.js +4 -3
  215. package/test/sync/models/award-database-integration.test.js +0 -0
  216. package/test/user/permissions.test.js +0 -0
  217. package/test/userActivity.test.js +0 -0
  218. package/tools/generate-index.cjs +0 -0
  219. package/.claude/settings.local.json +0 -8
  220. package/TECHNICAL_DEBT.md +0 -482
package/.coderabbit.yaml CHANGED
File without changes
package/.editorconfig CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
package/.prettierignore CHANGED
File without changes
package/.prettierrc CHANGED
File without changes
package/CHANGELOG.md CHANGED
@@ -2,6 +2,27 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [2.123.1](https://github.com/railroadmedia/musora-content-services/compare/v2.123.0...v2.123.1) (2026-01-28)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * **auth:** use http client for auth functions ([#751](https://github.com/railroadmedia/musora-content-services/issues/751)) ([6958adc](https://github.com/railroadmedia/musora-content-services/commit/6958adc87689a7dd433a8c66ccaff60317e6e962))
11
+
12
+ ## [2.123.0](https://github.com/railroadmedia/musora-content-services/compare/v2.122.7...v2.123.0) (2026-01-28)
13
+
14
+
15
+ ### Features
16
+
17
+ * better user impersonation ([#731](https://github.com/railroadmedia/musora-content-services/issues/731)) ([768022d](https://github.com/railroadmedia/musora-content-services/commit/768022df839b2c2e206d02985c82075b0d4de008))
18
+ * **T3PS-1537:** Playbass Recommendations V2 ([#744](https://github.com/railroadmedia/musora-content-services/issues/744)) ([b88ffbd](https://github.com/railroadmedia/musora-content-services/commit/b88ffbd85a9982371e108d9f23190a9217cf29d0))
19
+ * **TP-1080:** ignore resume time until past 10s window ([#749](https://github.com/railroadmedia/musora-content-services/issues/749)) ([c22f4c2](https://github.com/railroadmedia/musora-content-services/commit/c22f4c201ec60dbf9475eebbcee199dfea967bbf))
20
+
21
+
22
+ ### Bug Fixes
23
+
24
+ * makes methodIntroComplete function send formatted date matching getDailySession ([#725](https://github.com/railroadmedia/musora-content-services/issues/725)) ([6ac47a0](https://github.com/railroadmedia/musora-content-services/commit/6ac47a04dfa2ea4a0d355409b4be8fa743af1b48))
25
+
5
26
  ### [2.122.7](https://github.com/railroadmedia/musora-content-services/compare/v2.122.3...v2.122.7) (2026-01-28)
6
27
 
7
28
 
package/CLAUDE.md CHANGED
@@ -328,7 +328,7 @@ import { ContentLike, ContentProgress, Practice, PracticeDayNote } from 'musora-
328
328
  // - DurabilityProvider: no-op (storage always available on mobile)
329
329
  // - TabsProvider: no-op (single "tab" on mobile)
330
330
 
331
- const manager = new SyncManager(context, db)
331
+ const manager = new SyncManager(userScope, context, db)
332
332
  manager.registerStrategies(
333
333
  ContentLike, ContentProgress, Practice, PracticeDayNote],
334
334
  [initialStrategy, onlineStrategy, activityStrategy, hourlyPollingStrategy]
package/README.md CHANGED
File without changes
package/babel.config.cjs CHANGED
File without changes
package/jest.config.js CHANGED
File without changes
package/jsdoc.json CHANGED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "musora-content-services",
3
- "version": "2.122.7",
3
+ "version": "2.123.1",
4
4
  "description": "A package for Musoras content services ",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
File without changes
File without changes
@@ -56,6 +56,7 @@ export class LengthFilterOptions {
56
56
 
57
57
  export class Tabs {
58
58
  static ForYou = { name: 'For You', short_name: 'For You', value: 'tab,for you' }
59
+ static PlaybassAll = { name: 'All', short_name: 'All', value: 'tab,for you' }
59
60
  static Individuals = { name: 'Individuals', short_name: 'Individuals', value: 'type,individuals', cardType: 'big' }
60
61
  static Collections = { name: 'Collections', short_name: 'Collections', value: 'type,collections', cardType: 'big' }
61
62
  static ExploreAll = { name: 'Explore All', short_name: 'Explore All', value: 'tab,explore all', icon: 'icon-filters', cardType: 'big'}
@@ -330,6 +331,15 @@ const contentMetadata = {
330
331
  },
331
332
  playbass: {
332
333
  'songs-types': ['Tutorials', 'Tabs', 'Play-Alongs', 'Jam Tracks'],
334
+ lessons: {
335
+ tabs: [
336
+ Tabs.PlaybassAll,
337
+ Tabs.SingleLessons,
338
+ Tabs.Courses,
339
+ Tabs.SkillPacks,
340
+ Tabs.ExploreAll,
341
+ ]
342
+ },
333
343
  },
334
344
  singeo: {
335
345
  'songs-types': ['Tutorials', 'Sheet Music', 'Play-Alongs', 'Jam Tracks'],
File without changes
package/src/index.d.ts CHANGED
@@ -211,7 +211,9 @@ import {
211
211
 
212
212
  import {
213
213
  getProgressRows,
214
+ getUserPinProgressKey,
214
215
  pinProgressRow,
216
+ setUserPinnedProgressRow,
215
217
  unpinProgressRow
216
218
  } from './services/progress-row/base.js';
217
219
 
@@ -634,6 +636,7 @@ declare module 'musora-content-services' {
634
636
  getUpgradePrice,
635
637
  getUserData,
636
638
  getUserMonthlyStats,
639
+ getUserPinProgressKey,
637
640
  getUserSignature,
638
641
  getUserWeeklyStats,
639
642
  getWeekNumber,
@@ -702,6 +705,7 @@ declare module 'musora-content-services' {
702
705
  sendAccountSetupEmail,
703
706
  sendPasswordResetEmail,
704
707
  setStudentViewForUser,
708
+ setUserPinnedProgressRow,
705
709
  setUserSignature,
706
710
  setupAccount,
707
711
  startLearningPath,
package/src/index.js CHANGED
@@ -215,7 +215,9 @@ import {
215
215
 
216
216
  import {
217
217
  getProgressRows,
218
+ getUserPinProgressKey,
218
219
  pinProgressRow,
220
+ setUserPinnedProgressRow,
219
221
  unpinProgressRow
220
222
  } from './services/progress-row/base.js';
221
223
 
@@ -633,6 +635,7 @@ export {
633
635
  getUpgradePrice,
634
636
  getUserData,
635
637
  getUserMonthlyStats,
638
+ getUserPinProgressKey,
636
639
  getUserSignature,
637
640
  getUserWeeklyStats,
638
641
  getWeekNumber,
@@ -701,6 +704,7 @@ export {
701
704
  sendAccountSetupEmail,
702
705
  sendPasswordResetEmail,
703
706
  setStudentViewForUser,
707
+ setUserPinnedProgressRow,
704
708
  setUserSignature,
705
709
  setupAccount,
706
710
  startLearningPath,
File without changes
File without changes
File without changes
File without changes
File without changes
package/src/lib/brands.ts CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -442,14 +442,10 @@ export async function completeMethodIntroVideo(
442
442
  return response
443
443
  }
444
444
 
445
- async function methodIntroVideoCompleteActions(
446
- brand: string,
447
- learningPathId: number,
448
- userDate: Date
449
- ) {
450
- const stringDate = userDate.toISOString().split('T')[0]
445
+ async function methodIntroVideoCompleteActions(brand: string, learningPathId: number, userDate: Date) {
446
+ const dateWithTimezone = formatLocalDateTime(userDate)
451
447
  const url: string = `${LEARNING_PATHS_PATH}/method-intro-video-complete-actions`
452
- const body = { brand: brand, learningPathId: learningPathId, userDate: stringDate }
448
+ const body = { brand: brand, learningPathId: learningPathId, userDate: dateWithTimezone }
453
449
  return (await POST(url, body)) as DailySessionResponse
454
450
  }
455
451
 
File without changes
File without changes
@@ -471,10 +471,10 @@ export async function getRecommendedForYou(brand, rowId = null, {
471
471
  } = {}) {
472
472
  const requiredItems = page * limit;
473
473
  const data = await recommendations( brand, {limit: requiredItems})
474
+ const title = brand === 'playbass' ? "You Might Like" : "Recommended For You"
474
475
  if (!data || !data.length) {
475
- return { id: 'recommended', title: 'Recommended For You', items: [] };
476
+ return { id: 'recommended', title: title, items: [] };
476
477
  }
477
-
478
478
  // Apply pagination before calling fetchByRailContentIds
479
479
  const startIndex = (page - 1) * limit;
480
480
  const paginatedData = data.slice(startIndex, startIndex + limit);
@@ -491,7 +491,7 @@ export async function getRecommendedForYou(brand, rowId = null, {
491
491
  };
492
492
  }
493
493
 
494
- return { id: 'recommended', title: 'Recommended For You', items: contents }
494
+ return { id: 'recommended', title: title, items: contents }
495
495
  }
496
496
 
497
497
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -4,6 +4,7 @@
4
4
 
5
5
  import { globalConfig } from './config.js'
6
6
  import { GET, HttpClient } from '../infrastructure/http/HttpClient.ts'
7
+ import { fetchByRailContentIds } from './sanity.js'
7
8
 
8
9
  /**
9
10
  * Exported functions that are excluded from index generation.
@@ -31,20 +32,32 @@ export async function fetchSimilarItems(content_id, brand, count = 10) {
31
32
  if (!content_id) {
32
33
  return []
33
34
  }
34
- content_id = parseInt(content_id)
35
- const data = {
36
- brand: brand,
37
- content_ids: content_id,
38
- num_similar: count + 1,
39
- }
40
- const url = `/similar_items/`
41
- try {
42
- const response = await recommenderClient.post(url, data)
43
- return response['similar_items'].filter((item) => item !== content_id).slice(0, count)
44
- } catch (error) {
45
- console.error('Fetch error:', error)
46
- return null
35
+ if (brand === 'playbass') {
36
+ // V2 launch customization for playbass
37
+ const content = (await fetchByRailContentIds([content_id], 'tab-data'))[0] ?? []
38
+ if (!content) {
39
+ return []
40
+ }
41
+ const section = content.page_type === 'song' ? 'song' : ''
42
+ const recs = await recommendations('playbass', {section: section})
43
+ return recs.slice(0, count)
44
+ } else {
45
+ content_id = parseInt(content_id)
46
+ const data = {
47
+ brand: brand,
48
+ content_ids: content_id,
49
+ num_similar: count + 1,
50
+ }
51
+ const url = `/similar_items/`
52
+ try {
53
+ const response = await recommenderClient.post(url, data)
54
+ return response['similar_items'].filter((item) => item !== content_id).slice(0, count)
55
+ } catch (error) {
56
+ console.error('Fetch error:', error)
57
+ return null
58
+ }
47
59
  }
60
+
48
61
  }
49
62
 
50
63
  /**
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -154,7 +154,9 @@ export default class ProgressRepository extends SyncRepository<ContentProgress>
154
154
  r.progress_percent = progressPct
155
155
 
156
156
  if (typeof resumeTime != 'undefined') {
157
- r.resume_time_seconds = Math.floor(resumeTime)
157
+ if (resumeTime >= 10 || r.resume_time_seconds !== null) {
158
+ r.resume_time_seconds = Math.floor(resumeTime)
159
+ }
158
160
  }
159
161
 
160
162
  if (!fromLearningPath) {
File without changes
File without changes
File without changes
@@ -7,6 +7,7 @@ export type SyncResolution = {
7
7
  tuplesForUpdate: [BaseModel, SyncEntry][]
8
8
  tuplesForRestore: [BaseModel, SyncEntry][]
9
9
  idsForDestroy: RecordId[]
10
+ recordsForSynced: BaseModel[]
10
11
  }
11
12
 
12
13
  export type SyncResolverComparator<T extends BaseModel = BaseModel> = (serverEntry: SyncEntryNonDeleted<T>, localModel: T) => 'SERVER' | 'LOCAL'
@@ -24,7 +25,8 @@ export default class SyncResolver {
24
25
  entriesForCreate: [],
25
26
  tuplesForUpdate: [],
26
27
  tuplesForRestore: [],
27
- idsForDestroy: []
28
+ idsForDestroy: [],
29
+ recordsForSynced: []
28
30
  }
29
31
  }
30
32
 
@@ -58,6 +60,9 @@ export default class SyncResolver {
58
60
  } else if (this.comparator(server as SyncEntryNonDeleted<BaseModel>, local) !== 'LOCAL') {
59
61
  // local is older, so update it with server's
60
62
  this.resolution.tuplesForUpdate.push([local, server])
63
+ } else {
64
+ // server is older - can happen with clock skew - just mark as synced
65
+ this.resolution.recordsForSynced.push(local)
61
66
  }
62
67
  }
63
68
 
@@ -69,6 +74,9 @@ export default class SyncResolver {
69
74
  } else if (this.comparator(server as SyncEntryNonDeleted<BaseModel>, local) !== 'LOCAL') {
70
75
  // local is older, so update it with server's
71
76
  this.resolution.tuplesForUpdate.push([local, server])
77
+ } else {
78
+ // server is older - can happen with clock skew - just mark as synced
79
+ this.resolution.recordsForSynced.push(local)
72
80
  }
73
81
  }
74
82
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -956,9 +956,15 @@ export default class SyncStore<TModel extends BaseModel = BaseModel> {
956
956
  r._raw._changed = ''
957
957
  })
958
958
  })
959
+ const syncedBuilds = result.recordsForSynced.map((record) => {
960
+ return record.prepareUpdate((r) => {
961
+ r._raw._status = 'synced'
962
+ r._raw._changed = ''
963
+ })
964
+ })
959
965
 
960
966
  return [
961
- [...destroyedBuilds, ...createdBuilds, ...updatedBuilds, ...restoreDestroyBuilds],
967
+ [...destroyedBuilds, ...createdBuilds, ...updatedBuilds, ...restoreDestroyBuilds, ...syncedBuilds],
962
968
  [...restoreCreateBuilds],
963
969
  ]
964
970
  }
File without changes
File without changes
File without changes