musora-content-services 2.105.0 → 2.106.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.
- package/.coderabbit.yaml +0 -0
- package/.editorconfig +0 -0
- package/.github/pull_request_template.md +0 -0
- package/.github/workflows/conventional-commits.yaml +0 -0
- package/.github/workflows/docs.js.yml +0 -0
- package/.github/workflows/node.js.yml +0 -0
- package/.prettierignore +0 -0
- package/.prettierrc +0 -0
- package/CHANGELOG.md +7 -0
- package/CLAUDE.md +0 -0
- package/README.md +0 -0
- package/babel.config.cjs +0 -0
- package/jest.config.js +0 -0
- package/jsdoc.json +0 -0
- package/package.json +1 -1
- package/src/constants/award-assets.js +0 -0
- package/src/contentMetaData.js +0 -0
- package/src/infrastructure/http/HttpClient.ts +0 -0
- package/src/infrastructure/http/executors/FetchRequestExecutor.ts +0 -0
- package/src/infrastructure/http/index.ts +0 -0
- package/src/infrastructure/http/interfaces/HeaderProvider.ts +0 -0
- package/src/infrastructure/http/interfaces/HttpError.ts +0 -0
- package/src/infrastructure/http/interfaces/NetworkError.ts +0 -0
- package/src/infrastructure/http/interfaces/RequestExecutor.ts +0 -0
- package/src/infrastructure/http/interfaces/RequestOptions.ts +0 -0
- package/src/infrastructure/http/providers/DefaultHeaderProvider.ts +0 -0
- package/src/lib/brands.ts +0 -0
- package/src/lib/lastUpdated.js +0 -0
- package/src/services/api/types.js +0 -0
- package/src/services/api/types.ts +0 -0
- package/src/services/awards/internal/.indexignore +0 -0
- package/src/services/awards/internal/award-events.js +0 -0
- package/src/services/awards/internal/completion-data-generator.js +0 -0
- package/src/services/awards/internal/content-progress-observer.js +0 -0
- package/src/services/awards/internal/image-utils.js +0 -0
- package/src/services/awards/internal/message-generator.js +0 -0
- package/src/services/awards/internal/types.js +0 -0
- package/src/services/config.js +0 -0
- package/src/services/content/content.ts +0 -0
- package/src/services/content-org/content-org.js +0 -0
- package/src/services/content-org/guided-courses.ts +0 -0
- package/src/services/content-org/playlists-types.js +0 -0
- package/src/services/content-org/playlists.js +0 -0
- package/src/services/contentLikes.js +0 -0
- package/src/services/dataContext.js +0 -0
- package/src/services/dateUtils.js +0 -0
- package/src/services/eventsAPI.js +0 -0
- package/src/services/forums/categories.ts +0 -0
- package/src/services/forums/posts.ts +0 -0
- package/src/services/forums/types.ts +0 -0
- package/src/services/gamification/awards.ts +0 -0
- package/src/services/gamification/gamification.js +0 -0
- package/src/services/imageSRCBuilder.js +0 -0
- package/src/services/imageSRCVerify.js +0 -0
- package/src/services/liveTesting.ts +0 -0
- package/src/services/permissions/PermissionsAdapter.ts +0 -0
- package/src/services/permissions/PermissionsAdapterFactory.ts +0 -0
- package/src/services/permissions/PermissionsV1Adapter.ts +0 -0
- package/src/services/permissions/README.md +0 -0
- package/src/services/permissions/index.ts +0 -0
- package/src/services/recommendations.js +0 -0
- package/src/services/reporting/README.md +0 -0
- package/src/services/reporting/reporting.ts +0 -0
- package/src/services/reporting/types.ts +0 -0
- package/src/services/sentry/.indexignore +0 -0
- package/src/services/sentry/index.ts +0 -0
- package/src/services/sync/.indexignore +0 -0
- package/src/services/sync/adapters/factory.ts +0 -0
- package/src/services/sync/adapters/lokijs.ts +0 -0
- package/src/services/sync/adapters/sqlite.ts +0 -0
- package/src/services/sync/concurrency-safety.ts +0 -0
- package/src/services/sync/context/index.ts +0 -0
- package/src/services/sync/context/providers/base.ts +0 -0
- package/src/services/sync/context/providers/connectivity.ts +0 -0
- package/src/services/sync/context/providers/durability.ts +0 -0
- package/src/services/sync/context/providers/index.ts +0 -0
- package/src/services/sync/context/providers/session.ts +0 -0
- package/src/services/sync/context/providers/tabs.ts +0 -0
- package/src/services/sync/context/providers/visibility.ts +0 -0
- package/src/services/sync/database/factory.ts +0 -0
- package/src/services/sync/errors/boundary.ts +0 -0
- package/src/services/sync/errors/index.ts +8 -0
- package/src/services/sync/errors/validators.ts +42 -0
- package/src/services/sync/fetch.ts +1 -1
- package/src/services/sync/index.ts +0 -0
- package/src/services/sync/models/Base.ts +0 -0
- package/src/services/sync/models/ContentLike.ts +2 -1
- package/src/services/sync/models/ContentProgress.ts +26 -9
- package/src/services/sync/models/Practice.ts +32 -9
- package/src/services/sync/models/PracticeDayNote.ts +4 -2
- package/src/services/sync/models/UserAwardProgress.ts +14 -3
- package/src/services/sync/models/index.ts +0 -0
- package/src/services/sync/repositories/base.ts +0 -0
- package/src/services/sync/repositories/content-likes.ts +0 -0
- package/src/services/sync/repositories/index.ts +0 -0
- package/src/services/sync/repositories/practice-day-notes.ts +0 -0
- package/src/services/sync/repositories/practices.ts +0 -0
- package/src/services/sync/repository-proxy.ts +0 -0
- package/src/services/sync/resolver.ts +0 -0
- package/src/services/sync/run-scope.ts +0 -0
- package/src/services/sync/schema/index.ts +2 -2
- package/src/services/sync/serializers/index.ts +0 -0
- package/src/services/sync/serializers/model.ts +0 -0
- package/src/services/sync/serializers/raw.ts +0 -0
- package/src/services/sync/store/push-coalescer.ts +0 -0
- package/src/services/sync/store-configs.ts +0 -0
- package/src/services/sync/strategies/base.ts +0 -0
- package/src/services/sync/strategies/index.ts +0 -0
- package/src/services/sync/strategies/initial.ts +0 -0
- package/src/services/sync/strategies/polling.ts +0 -0
- package/src/services/sync/telemetry/index.ts +0 -0
- package/src/services/sync/telemetry/sampling.ts +0 -0
- package/src/services/sync/utils/event-emitter.ts +0 -0
- package/src/services/sync/utils/index.ts +0 -0
- package/src/services/sync/utils/throttle.ts +0 -0
- package/src/services/sync/utils/timers.ts +0 -0
- package/src/services/types.js +0 -0
- package/src/services/user/account.ts +0 -0
- package/src/services/user/chat.js +0 -0
- package/src/services/user/interests.js +0 -0
- package/src/services/user/management.js +0 -0
- package/src/services/user/notifications.js +0 -0
- package/src/services/user/payments.ts +0 -0
- package/src/services/user/permissions.js +0 -0
- package/src/services/user/profile.js +0 -0
- package/src/services/user/user-management-system.js +0 -0
- package/test/HttpClient.test.js +0 -0
- package/test/awards/award-alacarte-observer.test.js +0 -0
- package/test/awards/award-auto-refresh.test.js +0 -0
- package/test/awards/award-calculations.test.js +0 -0
- package/test/awards/award-certificate-display.test.js +0 -0
- package/test/awards/award-collection-edge-cases.test.js +0 -0
- package/test/awards/award-collection-filtering.test.js +0 -0
- package/test/awards/award-exclusion-handling.test.js +0 -0
- package/test/awards/award-multi-lesson.test.js +0 -0
- package/test/awards/award-observer-integration.test.js +0 -0
- package/test/awards/award-query-messages.test.js +0 -0
- package/test/awards/award-user-collection.test.js +0 -0
- package/test/awards/duplicate-prevention.test.js +0 -0
- package/test/awards/helpers/completion-mock.js +0 -0
- package/test/awards/helpers/index.js +0 -0
- package/test/awards/helpers/mock-setup.js +0 -0
- package/test/awards/helpers/progress-emitter.js +0 -0
- package/test/awards/message-generator.test.js +0 -0
- package/test/content.test.js +0 -0
- package/test/contentLikes.test.js +0 -0
- package/test/contentProgress.test.js +0 -0
- package/test/dataContext.test.js +0 -0
- package/test/forum.test.js +0 -0
- package/test/imageSRCBuilder.test.js +0 -0
- package/test/imageSRCVerify.test.js +0 -0
- package/test/lib/lastUpdated.test.js +0 -0
- package/test/live/contentProgressLive.test.js +0 -0
- package/test/live/railcontentLive.test.js +0 -0
- package/test/localStorageMock.js +0 -0
- package/test/log.js +0 -0
- package/test/mockData/award-definitions.js +0 -0
- package/test/mockData/mockData_fetchByRailContentIds_one_content.json +0 -0
- package/test/mockData/mockData_progress_content.json +0 -0
- package/test/mockData/mockData_sanity_progress_content.json +0 -0
- package/test/mockData/mockData_user_practices.json +0 -0
- package/test/notifications.test.js +0 -0
- package/test/progressRows.test.js +0 -0
- package/test/streakMessage.test.js +0 -0
- package/test/sync/models/award-database-integration.test.js +0 -0
- package/test/user/permissions.test.js +0 -0
- package/test/userActivity.test.js +0 -0
- package/tools/generate-index.cjs +0 -0
- package/.claude/settings.local.json +0 -18
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,13 @@
|
|
|
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.106.0](https://github.com/railroadmedia/musora-content-services/compare/v2.105.0...v2.106.0) (2025-12-18)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* Add some validators prior to writing to watermelon ([#663](https://github.com/railroadmedia/musora-content-services/issues/663)) ([9eeedac](https://github.com/railroadmedia/musora-content-services/commit/9eeedac5a3cf8b4eedd091fcb8252ffd5bae6c85))
|
|
11
|
+
|
|
5
12
|
## [2.105.0](https://github.com/railroadmedia/musora-content-services/compare/v2.104.9...v2.105.0) (2025-12-17)
|
|
6
13
|
|
|
7
14
|
|
package/CLAUDE.md
CHANGED
|
File without changes
|
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
|
File without changes
|
package/src/contentMetaData.js
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
|
package/src/lib/brands.ts
CHANGED
|
File without changes
|
package/src/lib/lastUpdated.js
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
|
package/src/services/config.js
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
|
|
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
|
|
@@ -47,3 +47,11 @@ export class SyncUnexpectedError extends SyncError {
|
|
|
47
47
|
Object.setPrototypeOf(this, new.target.prototype)
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
+
|
|
51
|
+
export class SyncValidationError extends SyncError {
|
|
52
|
+
constructor(message: string, value: any, expected: any) {
|
|
53
|
+
super('validationError', { message: message, value: value, expected: expected })
|
|
54
|
+
this.name = 'SyncValidationError'
|
|
55
|
+
Object.setPrototypeOf(this, new.target.prototype)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { SyncValidationError } from './index'
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export function throwIfNotNumber(val: any) {
|
|
5
|
+
// note: this will accept decimal values
|
|
6
|
+
if (typeof val !== 'number') throw new SyncValidationError('Sync value is not a number: ' + val, typeof val, 'number');
|
|
7
|
+
return val
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function throwIfNotString(val: any) {
|
|
11
|
+
if (typeof val !== 'string') throw new SyncValidationError('Sync value is not a string: ' + val, typeof val, 'string');
|
|
12
|
+
return val
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function throwIfNotBoolean(val: any) {
|
|
16
|
+
if (typeof val !== 'boolean') throw new SyncValidationError('Sync value is not a boolean: ' + val, typeof val, 'boolean');
|
|
17
|
+
return val
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function throwIfNotNullableNumber(val: any) {
|
|
21
|
+
return val === null ? val : throwIfNotNumber(val)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function throwIfNotNullableString(val: any) {
|
|
25
|
+
return val === null ? val : throwIfNotString(val)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function throwIfOutsideRange(val: number, minimum?: number, maximum?: number) {
|
|
29
|
+
if (minimum !== undefined && val < minimum) throw new SyncValidationError('Sync value is less than minimum value ' + minimum + ': ' + val, val, null);
|
|
30
|
+
if (maximum !== undefined && val > maximum) throw new SyncValidationError('Sync value is greater than maximum value ' + maximum + ': ' + val, val, null);
|
|
31
|
+
return val
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function throwIfMaxLengthExceeded(val: string, maximum: number) {
|
|
35
|
+
if (val.length > maximum) throw new SyncValidationError('Sync value exceeds the maximum length ' + maximum + ': ' + val, val, null);
|
|
36
|
+
return val
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function throwIfInvalidEnumValue(val: string, enumClass: any) {
|
|
40
|
+
if (!Object.values(enumClass).includes(val)) throw new SyncValidationError('Sync value is invalid enum value: ' + val, val, enumClass);
|
|
41
|
+
return val
|
|
42
|
+
}
|
|
@@ -34,7 +34,7 @@ type SyncPushFetchFailureResponse = SyncResponseBase & {
|
|
|
34
34
|
failureType: 'fetch'
|
|
35
35
|
isRetryable: boolean
|
|
36
36
|
}
|
|
37
|
-
type SyncPushFailureResponse = SyncResponseBase & {
|
|
37
|
+
export type SyncPushFailureResponse = SyncResponseBase & {
|
|
38
38
|
ok: false,
|
|
39
39
|
failureType: 'error'
|
|
40
40
|
originalError: Error
|
|
File without changes
|
|
File without changes
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SYNC_TABLES } from '../schema'
|
|
2
2
|
import BaseModel from './Base'
|
|
3
|
+
import { throwIfNotNumber } from '../errors/validators'
|
|
3
4
|
|
|
4
5
|
export default class ContentLike extends BaseModel<{
|
|
5
6
|
content_id: number
|
|
@@ -11,6 +12,6 @@ export default class ContentLike extends BaseModel<{
|
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
set content_id(value: number) {
|
|
14
|
-
this._setRaw('content_id', value)
|
|
15
|
+
this._setRaw('content_id', throwIfNotNumber(value))
|
|
15
16
|
}
|
|
16
17
|
}
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import BaseModel from './Base'
|
|
2
2
|
import { SYNC_TABLES } from '../schema'
|
|
3
|
+
import {
|
|
4
|
+
throwIfInvalidEnumValue,
|
|
5
|
+
throwIfNotNullableNumber,
|
|
6
|
+
throwIfNotNullableString,
|
|
7
|
+
throwIfNotNumber,
|
|
8
|
+
throwIfOutsideRange,
|
|
9
|
+
} from '../errors/validators'
|
|
3
10
|
|
|
4
11
|
export enum COLLECTION_TYPE {
|
|
5
12
|
SELF = 'self',
|
|
@@ -16,6 +23,7 @@ export enum STATE {
|
|
|
16
23
|
|
|
17
24
|
export default class ContentProgress extends BaseModel<{
|
|
18
25
|
content_id: number
|
|
26
|
+
content_brand: string | null
|
|
19
27
|
collection_type: COLLECTION_TYPE
|
|
20
28
|
collection_id: number
|
|
21
29
|
state: STATE
|
|
@@ -28,7 +36,7 @@ export default class ContentProgress extends BaseModel<{
|
|
|
28
36
|
return this._getRaw('content_id') as number
|
|
29
37
|
}
|
|
30
38
|
get content_brand() {
|
|
31
|
-
return this._getRaw('content_brand') as string
|
|
39
|
+
return this._getRaw('content_brand') as string | null
|
|
32
40
|
}
|
|
33
41
|
get state() {
|
|
34
42
|
return this._getRaw('state') as STATE
|
|
@@ -47,28 +55,37 @@ export default class ContentProgress extends BaseModel<{
|
|
|
47
55
|
}
|
|
48
56
|
|
|
49
57
|
set content_id(value: number) {
|
|
50
|
-
|
|
58
|
+
// unsigned int
|
|
59
|
+
throwIfNotNumber(value)
|
|
60
|
+
this._setRaw('content_id', throwIfOutsideRange(value, 0))
|
|
51
61
|
}
|
|
52
|
-
set content_brand(value: string) {
|
|
53
|
-
this._setRaw('content_brand', value)
|
|
62
|
+
set content_brand(value: string | null) {
|
|
63
|
+
this._setRaw('content_brand', throwIfNotNullableString(value))
|
|
54
64
|
}
|
|
55
65
|
// IMPORTANT: progress percent only moves forward and is clamped between 0 and 100
|
|
56
66
|
// also has implications for last-write-wins sync strategy
|
|
57
67
|
set progress_percent(value: number) {
|
|
58
|
-
|
|
59
|
-
|
|
68
|
+
// tinyint unsigned
|
|
69
|
+
throwIfNotNumber(value)
|
|
70
|
+
throwIfOutsideRange(value, 0, 100)
|
|
71
|
+
const percent = value === 0 ? 0 : Math.max(value, this.progress_percent)
|
|
60
72
|
|
|
61
73
|
this._setRaw('progress_percent', percent)
|
|
62
74
|
this._setRaw('state', percent === 100 ? STATE.COMPLETED : STATE.STARTED)
|
|
63
75
|
}
|
|
64
76
|
set collection_type(value: COLLECTION_TYPE) {
|
|
65
|
-
|
|
77
|
+
// enum collection_type
|
|
78
|
+
this._setRaw('collection_type', throwIfInvalidEnumValue(value, COLLECTION_TYPE))
|
|
66
79
|
}
|
|
67
80
|
set collection_id(value: number) {
|
|
68
|
-
|
|
81
|
+
// unsigned mediumint 16777215
|
|
82
|
+
throwIfNotNumber(value)
|
|
83
|
+
this._setRaw('collection_id', throwIfOutsideRange(value, 0, 16777215))
|
|
69
84
|
}
|
|
70
85
|
set resume_time_seconds(value: number | null) {
|
|
71
|
-
|
|
86
|
+
// smallint unsigned
|
|
87
|
+
throwIfNotNullableNumber(value)
|
|
88
|
+
this._setRaw('resume_time_seconds', value !== null ? throwIfOutsideRange(value, 0, 65535) : value)
|
|
72
89
|
}
|
|
73
90
|
|
|
74
91
|
}
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { SYNC_TABLES } from '../schema'
|
|
2
2
|
import BaseModel from './Base'
|
|
3
|
+
import {
|
|
4
|
+
throwIfMaxLengthExceeded,
|
|
5
|
+
throwIfNotBoolean,
|
|
6
|
+
throwIfNotNullableNumber,
|
|
7
|
+
throwIfNotNullableString,
|
|
8
|
+
throwIfNotNumber,
|
|
9
|
+
throwIfNotString,
|
|
10
|
+
throwIfOutsideRange,
|
|
11
|
+
} from '../errors/validators'
|
|
3
12
|
|
|
4
13
|
export default class Practice extends BaseModel<{
|
|
5
14
|
manual_id: string | null
|
|
@@ -43,30 +52,44 @@ export default class Practice extends BaseModel<{
|
|
|
43
52
|
}
|
|
44
53
|
|
|
45
54
|
set manual_id(value: string | null) {
|
|
46
|
-
|
|
55
|
+
// char(26)
|
|
56
|
+
throwIfNotNullableString(value)
|
|
57
|
+
this._setRaw('manual_id', value !== null ? throwIfMaxLengthExceeded(value, 26) : value)
|
|
47
58
|
}
|
|
48
59
|
set content_id(value: number | null) {
|
|
49
|
-
|
|
60
|
+
// int unsigned
|
|
61
|
+
throwIfNotNullableNumber(value)
|
|
62
|
+
this._setRaw('content_id', value !== null ? throwIfOutsideRange(value, 0) : value)
|
|
50
63
|
}
|
|
51
64
|
set date(value: string) {
|
|
52
|
-
this._setRaw('date', value)
|
|
65
|
+
this._setRaw('date', throwIfNotString(value))
|
|
53
66
|
}
|
|
54
67
|
set auto(value: boolean) {
|
|
55
|
-
|
|
68
|
+
// tinyint(1)
|
|
69
|
+
this._setRaw('auto', throwIfNotBoolean(value))
|
|
56
70
|
}
|
|
57
71
|
set duration_seconds(value: number) {
|
|
58
|
-
|
|
72
|
+
throwIfNotNumber(value)
|
|
73
|
+
this._setRaw('duration_seconds', throwIfOutsideRange(value, 0, 59999))
|
|
59
74
|
}
|
|
60
75
|
set title(value: string | null) {
|
|
61
|
-
|
|
76
|
+
// varchar(64)
|
|
77
|
+
throwIfNotNullableString(value)
|
|
78
|
+
this._setRaw('title', value !== null ? throwIfMaxLengthExceeded(value, 64) : value)
|
|
62
79
|
}
|
|
63
80
|
set thumbnail_url(value: string | null) {
|
|
64
|
-
|
|
81
|
+
// varchar(255)
|
|
82
|
+
throwIfNotNullableString(value)
|
|
83
|
+
this._setRaw('thumbnail_url', value !== null ? throwIfMaxLengthExceeded(value, 255) : value)
|
|
65
84
|
}
|
|
66
85
|
set category_id(value: number | null) {
|
|
67
|
-
|
|
86
|
+
// tinyint unsigned
|
|
87
|
+
throwIfNotNullableNumber(value)
|
|
88
|
+
this._setRaw('category_id', value !== null ? throwIfOutsideRange(value, 0, 255) : value)
|
|
68
89
|
}
|
|
69
90
|
set instrument_id(value: number | null) {
|
|
70
|
-
|
|
91
|
+
// tinyint unsigned
|
|
92
|
+
throwIfNotNullableNumber(value)
|
|
93
|
+
this._setRaw('instrument_id', value !== null ? throwIfOutsideRange(value, 0, 255) : value)
|
|
71
94
|
}
|
|
72
95
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SYNC_TABLES } from '../schema'
|
|
2
2
|
import BaseModel from './Base'
|
|
3
|
+
import { throwIfMaxLengthExceeded, throwIfNotString } from '../errors/validators'
|
|
3
4
|
|
|
4
5
|
export default class PracticeDayNote extends BaseModel<{
|
|
5
6
|
date: string
|
|
@@ -15,9 +16,10 @@ export default class PracticeDayNote extends BaseModel<{
|
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
set date(value: string) {
|
|
18
|
-
this._setRaw('date', value)
|
|
19
|
+
this._setRaw('date', throwIfNotString(value))
|
|
19
20
|
}
|
|
20
21
|
set notes(value: string) {
|
|
21
|
-
|
|
22
|
+
throwIfNotString(value)
|
|
23
|
+
this._setRaw('notes', throwIfMaxLengthExceeded(value, 3000))
|
|
22
24
|
}
|
|
23
25
|
}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import BaseModel from './Base'
|
|
2
2
|
import { SYNC_TABLES } from '../schema'
|
|
3
3
|
import type { CompletionData } from '../../awards/types'
|
|
4
|
+
import {
|
|
5
|
+
throwIfMaxLengthExceeded,
|
|
6
|
+
throwIfNotNullableString,
|
|
7
|
+
throwIfNotNumber,
|
|
8
|
+
throwIfNotString,
|
|
9
|
+
throwIfOutsideRange,
|
|
10
|
+
} from '../errors/validators'
|
|
4
11
|
|
|
5
12
|
export default class UserAwardProgress extends BaseModel<{
|
|
6
13
|
award_id: string
|
|
@@ -34,15 +41,19 @@ export default class UserAwardProgress extends BaseModel<{
|
|
|
34
41
|
}
|
|
35
42
|
|
|
36
43
|
set award_id(value: string) {
|
|
37
|
-
|
|
44
|
+
// varchar(255)
|
|
45
|
+
throwIfNotString(value)
|
|
46
|
+
this._setRaw('award_id', throwIfMaxLengthExceeded(value, 255))
|
|
38
47
|
}
|
|
39
48
|
|
|
40
49
|
set progress_percentage(value: number) {
|
|
41
|
-
|
|
50
|
+
// int
|
|
51
|
+
throwIfNotNumber(value)
|
|
52
|
+
this._setRaw('progress_percentage', throwIfOutsideRange(value, 0, 100))
|
|
42
53
|
}
|
|
43
54
|
|
|
44
55
|
set completed_at(value: string | null) {
|
|
45
|
-
this._setRaw('completed_at', value)
|
|
56
|
+
this._setRaw('completed_at', throwIfNotNullableString(value))
|
|
46
57
|
}
|
|
47
58
|
|
|
48
59
|
set progress_data(value: any) {
|
|
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
|
|
@@ -21,8 +21,8 @@ const contentProgressTable = tableSchema({
|
|
|
21
21
|
columns: [
|
|
22
22
|
{ name: 'content_id', type: 'number', isIndexed: true },
|
|
23
23
|
{ name: 'content_brand', type: 'string', isOptional: true, isIndexed: true },
|
|
24
|
-
{ name: 'collection_type', type: 'string',
|
|
25
|
-
{ name: 'collection_id', type: 'number',
|
|
24
|
+
{ name: 'collection_type', type: 'string', isIndexed: true },
|
|
25
|
+
{ name: 'collection_id', type: 'number', isIndexed: true },
|
|
26
26
|
{ name: 'state', type: 'string', isIndexed: true },
|
|
27
27
|
{ name: 'progress_percent', type: 'number' },
|
|
28
28
|
{ name: 'resume_time_seconds', type: 'number', isOptional: true },
|
|
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
|
package/src/services/types.js
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
|
package/test/HttpClient.test.js
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
|
package/test/content.test.js
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/test/dataContext.test.js
CHANGED
|
File without changes
|
package/test/forum.test.js
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/test/localStorageMock.js
CHANGED
|
File without changes
|
package/test/log.js
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
|
package/tools/generate-index.cjs
CHANGED
|
File without changes
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"permissions": {
|
|
3
|
-
"allow": [
|
|
4
|
-
"Bash(find:*)",
|
|
5
|
-
"Bash(docker exec:*)",
|
|
6
|
-
"Bash(npm test:*)",
|
|
7
|
-
"WebSearch",
|
|
8
|
-
"WebFetch(domain:watermelondb.dev)",
|
|
9
|
-
"WebFetch(domain:github.com)",
|
|
10
|
-
"Bash(git checkout:*)",
|
|
11
|
-
"Bash(npm run doc:*)",
|
|
12
|
-
"Bash(cat:*)",
|
|
13
|
-
"Bash(tr:*)"
|
|
14
|
-
],
|
|
15
|
-
"deny": [],
|
|
16
|
-
"ask": []
|
|
17
|
-
}
|
|
18
|
-
}
|