@iblai/data-layer 1.19.1 → 1.21.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/dist/index.d.ts +1748 -2
- package/dist/index.esm.js +344 -39
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +368 -38
- package/dist/index.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/src/features/courses/__tests__/completion.test.d.ts +1 -0
- package/dist/src/features/courses/__tests__/outline-fixture.d.ts +10 -0
- package/dist/src/features/courses/api-slice.d.ts +270 -0
- package/dist/src/features/courses/completion.d.ts +47 -0
- package/dist/src/features/courses/types.d.ts +94 -0
- package/dist/src/features/custom-domain/index.d.ts +3 -0
- package/dist/src/features/custom-domain/types.d.ts +31 -0
- package/dist/src/features/hosting/api-slice.d.ts +1176 -0
- package/dist/src/features/hosting/constants.d.ts +32 -0
- package/dist/src/features/hosting/index.d.ts +3 -0
- package/dist/src/features/hosting/types.d.ts +90 -0
- package/dist/src/index.d.ts +4 -0
- package/dist/tests/features/custom-domain/constants.test.d.ts +1 -0
- package/dist/tests/features/hosting/api-slice.test.d.ts +1 -0
- package/dist/tests/features/hosting/constants.test.d.ts +1 -0
- package/dist/tests/features/hosting/index.test.d.ts +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/dist/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CompletionOutlineBlock } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Reduced from the live `endpoint=outline` response for
|
|
4
|
+
* course-v1:1718796901+C0+2025-09 ("Exam course for baba"). It keeps the
|
|
5
|
+
* quirks that matter: missing `children` on leaves and empty verticals,
|
|
6
|
+
* `complete` only on containers or when true, `resume_block` only along the
|
|
7
|
+
* path to the one completed leaf ("Raw HTML" in Section 3).
|
|
8
|
+
*/
|
|
9
|
+
export declare const COURSE_ID = "course-v1:1718796901+C0+2025-09";
|
|
10
|
+
export declare const outlineFixture: CompletionOutlineBlock;
|
|
@@ -8,6 +8,13 @@ export declare const coursesApiSlice: import("@reduxjs/toolkit/query").Api<impor
|
|
|
8
8
|
user_id: string | number;
|
|
9
9
|
query?: Record<string, string | number | boolean | undefined>;
|
|
10
10
|
}, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", EnrolledCourseResponse, "coursesApiSlice", unknown>;
|
|
11
|
+
/**
|
|
12
|
+
* Per-learner course outline with block-level completion. Name the learner
|
|
13
|
+
* with exactly one of `username` / `user_id` / `email`, even for one's own
|
|
14
|
+
* data. Errors keep their HTTP status; map them with
|
|
15
|
+
* `normalizeLearnerCompletionError`.
|
|
16
|
+
*/
|
|
17
|
+
getLearnerCourseOutline: import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>;
|
|
11
18
|
}, "coursesApiSlice", "user-enrolled-courses" | "user-assigned-courses", typeof import("@reduxjs/toolkit/query").coreModuleName | typeof import("@reduxjs/toolkit/dist/query/react").reactHooksModuleName>;
|
|
12
19
|
export declare const useGetUserEnrolledCoursesQuery: <R extends Record<string, any> = import("@reduxjs/toolkit/query").TSHelpersId<(Omit<{
|
|
13
20
|
status: import("@reduxjs/toolkit/query").QueryStatus.uninitialized;
|
|
@@ -661,4 +668,267 @@ export declare const useGetUserEnrolledCoursesQuery: <R extends Record<string, a
|
|
|
661
668
|
user_id: string | number;
|
|
662
669
|
query?: Record<string, string | number | boolean | undefined>;
|
|
663
670
|
};
|
|
671
|
+
}], useGetLearnerCourseOutlineQuery: <R extends Record<string, any> = import("@reduxjs/toolkit/query").TSHelpersId<(Omit<{
|
|
672
|
+
status: import("@reduxjs/toolkit/query").QueryStatus.uninitialized;
|
|
673
|
+
originalArgs?: undefined | undefined;
|
|
674
|
+
data?: undefined | undefined;
|
|
675
|
+
error?: undefined | undefined;
|
|
676
|
+
requestId?: undefined | undefined;
|
|
677
|
+
endpointName?: string | undefined;
|
|
678
|
+
startedTimeStamp?: undefined | undefined;
|
|
679
|
+
fulfilledTimeStamp?: undefined | undefined;
|
|
680
|
+
} & {
|
|
681
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
682
|
+
isUninitialized: false;
|
|
683
|
+
isLoading: false;
|
|
684
|
+
isFetching: false;
|
|
685
|
+
isSuccess: false;
|
|
686
|
+
isError: false;
|
|
687
|
+
}, "isUninitialized"> & {
|
|
688
|
+
isUninitialized: true;
|
|
689
|
+
}) | import("@reduxjs/toolkit/query").TSHelpersOverride<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
690
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
691
|
+
isUninitialized: false;
|
|
692
|
+
isLoading: false;
|
|
693
|
+
isFetching: false;
|
|
694
|
+
isSuccess: false;
|
|
695
|
+
isError: false;
|
|
696
|
+
}, {
|
|
697
|
+
isLoading: true;
|
|
698
|
+
isFetching: boolean;
|
|
699
|
+
data: undefined;
|
|
700
|
+
} | ({
|
|
701
|
+
isSuccess: true;
|
|
702
|
+
isFetching: true;
|
|
703
|
+
error: undefined;
|
|
704
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
705
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
706
|
+
isUninitialized: false;
|
|
707
|
+
isLoading: false;
|
|
708
|
+
isFetching: false;
|
|
709
|
+
isSuccess: false;
|
|
710
|
+
isError: false;
|
|
711
|
+
}, "data" | "fulfilledTimeStamp">>) | ({
|
|
712
|
+
isSuccess: true;
|
|
713
|
+
isFetching: false;
|
|
714
|
+
error: undefined;
|
|
715
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
716
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
717
|
+
isUninitialized: false;
|
|
718
|
+
isLoading: false;
|
|
719
|
+
isFetching: false;
|
|
720
|
+
isSuccess: false;
|
|
721
|
+
isError: false;
|
|
722
|
+
}, "data" | "fulfilledTimeStamp" | "currentData">>) | ({
|
|
723
|
+
isError: true;
|
|
724
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
725
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
726
|
+
isUninitialized: false;
|
|
727
|
+
isLoading: false;
|
|
728
|
+
isFetching: false;
|
|
729
|
+
isSuccess: false;
|
|
730
|
+
isError: false;
|
|
731
|
+
}, "error">>)>> & {
|
|
732
|
+
status: import("@reduxjs/toolkit/query").QueryStatus;
|
|
733
|
+
}>(arg: import("./types").LearnerCompletionArgs | typeof import("@reduxjs/toolkit/query").skipToken, options?: (import("@reduxjs/toolkit/query").SubscriptionOptions & {
|
|
734
|
+
skip?: boolean;
|
|
735
|
+
refetchOnMountOrArgChange?: boolean | number;
|
|
736
|
+
} & {
|
|
737
|
+
skip?: boolean;
|
|
738
|
+
selectFromResult?: ((state: import("@reduxjs/toolkit/query").TSHelpersId<(Omit<{
|
|
739
|
+
status: import("@reduxjs/toolkit/query").QueryStatus.uninitialized;
|
|
740
|
+
originalArgs?: undefined | undefined;
|
|
741
|
+
data?: undefined | undefined;
|
|
742
|
+
error?: undefined | undefined;
|
|
743
|
+
requestId?: undefined | undefined;
|
|
744
|
+
endpointName?: string | undefined;
|
|
745
|
+
startedTimeStamp?: undefined | undefined;
|
|
746
|
+
fulfilledTimeStamp?: undefined | undefined;
|
|
747
|
+
} & {
|
|
748
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
749
|
+
isUninitialized: false;
|
|
750
|
+
isLoading: false;
|
|
751
|
+
isFetching: false;
|
|
752
|
+
isSuccess: false;
|
|
753
|
+
isError: false;
|
|
754
|
+
}, "isUninitialized"> & {
|
|
755
|
+
isUninitialized: true;
|
|
756
|
+
}) | import("@reduxjs/toolkit/query").TSHelpersOverride<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
757
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
758
|
+
isUninitialized: false;
|
|
759
|
+
isLoading: false;
|
|
760
|
+
isFetching: false;
|
|
761
|
+
isSuccess: false;
|
|
762
|
+
isError: false;
|
|
763
|
+
}, {
|
|
764
|
+
isLoading: true;
|
|
765
|
+
isFetching: boolean;
|
|
766
|
+
data: undefined;
|
|
767
|
+
} | ({
|
|
768
|
+
isSuccess: true;
|
|
769
|
+
isFetching: true;
|
|
770
|
+
error: undefined;
|
|
771
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
772
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
773
|
+
isUninitialized: false;
|
|
774
|
+
isLoading: false;
|
|
775
|
+
isFetching: false;
|
|
776
|
+
isSuccess: false;
|
|
777
|
+
isError: false;
|
|
778
|
+
}, "data" | "fulfilledTimeStamp">>) | ({
|
|
779
|
+
isSuccess: true;
|
|
780
|
+
isFetching: false;
|
|
781
|
+
error: undefined;
|
|
782
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
783
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
784
|
+
isUninitialized: false;
|
|
785
|
+
isLoading: false;
|
|
786
|
+
isFetching: false;
|
|
787
|
+
isSuccess: false;
|
|
788
|
+
isError: false;
|
|
789
|
+
}, "data" | "fulfilledTimeStamp" | "currentData">>) | ({
|
|
790
|
+
isError: true;
|
|
791
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
792
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
793
|
+
isUninitialized: false;
|
|
794
|
+
isLoading: false;
|
|
795
|
+
isFetching: false;
|
|
796
|
+
isSuccess: false;
|
|
797
|
+
isError: false;
|
|
798
|
+
}, "error">>)>> & {
|
|
799
|
+
status: import("@reduxjs/toolkit/query").QueryStatus;
|
|
800
|
+
}) => R) | undefined;
|
|
801
|
+
}) | undefined) => [R][R extends any ? 0 : never] & {
|
|
802
|
+
refetch: () => import("@reduxjs/toolkit/query").QueryActionCreatorResult<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>>;
|
|
803
|
+
}, useLazyGetLearnerCourseOutlineQuery: <R extends Record<string, any> = import("@reduxjs/toolkit/query").TSHelpersId<(Omit<{
|
|
804
|
+
status: import("@reduxjs/toolkit/query").QueryStatus.uninitialized;
|
|
805
|
+
originalArgs?: undefined | undefined;
|
|
806
|
+
data?: undefined | undefined;
|
|
807
|
+
error?: undefined | undefined;
|
|
808
|
+
requestId?: undefined | undefined;
|
|
809
|
+
endpointName?: string | undefined;
|
|
810
|
+
startedTimeStamp?: undefined | undefined;
|
|
811
|
+
fulfilledTimeStamp?: undefined | undefined;
|
|
812
|
+
} & {
|
|
813
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
814
|
+
isUninitialized: false;
|
|
815
|
+
isLoading: false;
|
|
816
|
+
isFetching: false;
|
|
817
|
+
isSuccess: false;
|
|
818
|
+
isError: false;
|
|
819
|
+
}, "isUninitialized"> & {
|
|
820
|
+
isUninitialized: true;
|
|
821
|
+
}) | import("@reduxjs/toolkit/query").TSHelpersOverride<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
822
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
823
|
+
isUninitialized: false;
|
|
824
|
+
isLoading: false;
|
|
825
|
+
isFetching: false;
|
|
826
|
+
isSuccess: false;
|
|
827
|
+
isError: false;
|
|
828
|
+
}, {
|
|
829
|
+
isLoading: true;
|
|
830
|
+
isFetching: boolean;
|
|
831
|
+
data: undefined;
|
|
832
|
+
} | ({
|
|
833
|
+
isSuccess: true;
|
|
834
|
+
isFetching: true;
|
|
835
|
+
error: undefined;
|
|
836
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
837
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
838
|
+
isUninitialized: false;
|
|
839
|
+
isLoading: false;
|
|
840
|
+
isFetching: false;
|
|
841
|
+
isSuccess: false;
|
|
842
|
+
isError: false;
|
|
843
|
+
}, "data" | "fulfilledTimeStamp">>) | ({
|
|
844
|
+
isSuccess: true;
|
|
845
|
+
isFetching: false;
|
|
846
|
+
error: undefined;
|
|
847
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
848
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
849
|
+
isUninitialized: false;
|
|
850
|
+
isLoading: false;
|
|
851
|
+
isFetching: false;
|
|
852
|
+
isSuccess: false;
|
|
853
|
+
isError: false;
|
|
854
|
+
}, "data" | "fulfilledTimeStamp" | "currentData">>) | ({
|
|
855
|
+
isError: true;
|
|
856
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
857
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
858
|
+
isUninitialized: false;
|
|
859
|
+
isLoading: false;
|
|
860
|
+
isFetching: false;
|
|
861
|
+
isSuccess: false;
|
|
862
|
+
isError: false;
|
|
863
|
+
}, "error">>)>> & {
|
|
864
|
+
status: import("@reduxjs/toolkit/query").QueryStatus;
|
|
865
|
+
}>(options?: (import("@reduxjs/toolkit/query").SubscriptionOptions & Omit<{
|
|
866
|
+
skip?: boolean;
|
|
867
|
+
selectFromResult?: ((state: import("@reduxjs/toolkit/query").TSHelpersId<(Omit<{
|
|
868
|
+
status: import("@reduxjs/toolkit/query").QueryStatus.uninitialized;
|
|
869
|
+
originalArgs?: undefined | undefined;
|
|
870
|
+
data?: undefined | undefined;
|
|
871
|
+
error?: undefined | undefined;
|
|
872
|
+
requestId?: undefined | undefined;
|
|
873
|
+
endpointName?: string | undefined;
|
|
874
|
+
startedTimeStamp?: undefined | undefined;
|
|
875
|
+
fulfilledTimeStamp?: undefined | undefined;
|
|
876
|
+
} & {
|
|
877
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
878
|
+
isUninitialized: false;
|
|
879
|
+
isLoading: false;
|
|
880
|
+
isFetching: false;
|
|
881
|
+
isSuccess: false;
|
|
882
|
+
isError: false;
|
|
883
|
+
}, "isUninitialized"> & {
|
|
884
|
+
isUninitialized: true;
|
|
885
|
+
}) | import("@reduxjs/toolkit/query").TSHelpersOverride<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
886
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
887
|
+
isUninitialized: false;
|
|
888
|
+
isLoading: false;
|
|
889
|
+
isFetching: false;
|
|
890
|
+
isSuccess: false;
|
|
891
|
+
isError: false;
|
|
892
|
+
}, {
|
|
893
|
+
isLoading: true;
|
|
894
|
+
isFetching: boolean;
|
|
895
|
+
data: undefined;
|
|
896
|
+
} | ({
|
|
897
|
+
isSuccess: true;
|
|
898
|
+
isFetching: true;
|
|
899
|
+
error: undefined;
|
|
900
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
901
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
902
|
+
isUninitialized: false;
|
|
903
|
+
isLoading: false;
|
|
904
|
+
isFetching: false;
|
|
905
|
+
isSuccess: false;
|
|
906
|
+
isError: false;
|
|
907
|
+
}, "data" | "fulfilledTimeStamp">>) | ({
|
|
908
|
+
isSuccess: true;
|
|
909
|
+
isFetching: false;
|
|
910
|
+
error: undefined;
|
|
911
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
912
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
913
|
+
isUninitialized: false;
|
|
914
|
+
isLoading: false;
|
|
915
|
+
isFetching: false;
|
|
916
|
+
isSuccess: false;
|
|
917
|
+
isError: false;
|
|
918
|
+
}, "data" | "fulfilledTimeStamp" | "currentData">>) | ({
|
|
919
|
+
isError: true;
|
|
920
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
921
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
922
|
+
isUninitialized: false;
|
|
923
|
+
isLoading: false;
|
|
924
|
+
isFetching: false;
|
|
925
|
+
isSuccess: false;
|
|
926
|
+
isError: false;
|
|
927
|
+
}, "error">>)>> & {
|
|
928
|
+
status: import("@reduxjs/toolkit/query").QueryStatus;
|
|
929
|
+
}) => R) | undefined;
|
|
930
|
+
}, "skip">) | undefined) => [(arg: import("./types").LearnerCompletionArgs, preferCacheValue?: boolean) => import("@reduxjs/toolkit/query").QueryActionCreatorResult<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>>, [R][R extends any ? 0 : never] & {
|
|
931
|
+
reset: () => void;
|
|
932
|
+
}, {
|
|
933
|
+
lastArg: import("./types").LearnerCompletionArgs;
|
|
664
934
|
}];
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { BaseQueryApi } from '@reduxjs/toolkit/query';
|
|
2
|
+
import { type ExtendedFetchBaseQueryError } from '../utils';
|
|
3
|
+
import type { CompletionOutlineBlock, CompletionOutlineSection, FlatCompletionOutlineEntry, LearnerCompletionArgs, LearnerCompletionEndpoint, LearnerCompletionError, NormalizedCompletionOutlineBlock } from './types';
|
|
4
|
+
export declare const LEARNER_COMPLETION_PATH = "/api/catalog/enrollment/courses/completion/";
|
|
5
|
+
/**
|
|
6
|
+
* Checks the args carry exactly one learner identifier plus `course_id` and
|
|
7
|
+
* `platform_key`. Returns a reason string when they don't.
|
|
8
|
+
*/
|
|
9
|
+
export declare function validateLearnerCompletionArgs(args: LearnerCompletionArgs): string | null;
|
|
10
|
+
/**
|
|
11
|
+
* Builds the completion URL for one `endpoint` selector. Only the learner
|
|
12
|
+
* identifier, `course_id` and `platform_key` are sent; the DM forwards
|
|
13
|
+
* nothing else to edX.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildLearnerCompletionUrl(args: LearnerCompletionArgs, endpoint: LearnerCompletionEndpoint): string;
|
|
16
|
+
type QueryResult<T> = {
|
|
17
|
+
data: T;
|
|
18
|
+
} | {
|
|
19
|
+
error: ExtendedFetchBaseQueryError;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* One completion request through `iblFetchBaseQuery` (DM token, token
|
|
23
|
+
* refresh, registered error handlers). `iblFetchBaseQuery` throws on HTTP
|
|
24
|
+
* errors, which RTK would turn into a SerializedError without the status;
|
|
25
|
+
* catching here keeps `{ status, data }` so the UI can tell 403/404/502 apart.
|
|
26
|
+
*/
|
|
27
|
+
export declare function fetchLearnerCompletion<T>(args: LearnerCompletionArgs, endpoint: LearnerCompletionEndpoint, api: BaseQueryApi, extraOptions?: Record<string, unknown>): Promise<QueryResult<T>>;
|
|
28
|
+
/**
|
|
29
|
+
* Maps a failed completion query onto the states the UI shows. 403 and 404
|
|
30
|
+
* are deliberately coarse on the backend (one body for every hidden case),
|
|
31
|
+
* so don't try to read more into them.
|
|
32
|
+
*/
|
|
33
|
+
export declare function normalizeLearnerCompletionError(error: unknown): LearnerCompletionError | null;
|
|
34
|
+
/** Fills the fields edX omits: `children ?? []`, `complete`/`resume_block ?? false`. */
|
|
35
|
+
export declare function normalizeOutline(block: CompletionOutlineBlock): NormalizedCompletionOutlineBlock;
|
|
36
|
+
/** Depth-first, course order. The root has depth 0 and `parentId` null. */
|
|
37
|
+
export declare function flattenOutline(root: CompletionOutlineBlock): FlatCompletionOutlineEntry[];
|
|
38
|
+
/**
|
|
39
|
+
* Follows `resume_block: true` from the root to the deepest marked node (the
|
|
40
|
+
* last-visited leaf). Returns null when the learner hasn't visited anything.
|
|
41
|
+
*/
|
|
42
|
+
export declare function findResumeBlock(root: CompletionOutlineBlock): CompletionOutlineBlock | null;
|
|
43
|
+
/** Counts leaves (blocks without children) by `type`. */
|
|
44
|
+
export declare function countByType(root: CompletionOutlineBlock): Record<string, number>;
|
|
45
|
+
/** Top-level sections (chapters) for a summary view, in course order. */
|
|
46
|
+
export declare function getSections(root: CompletionOutlineBlock): CompletionOutlineSection[];
|
|
47
|
+
export {};
|
|
@@ -24,3 +24,97 @@ export interface EnrolledCourseResponse {
|
|
|
24
24
|
previous_page: number | null;
|
|
25
25
|
results: EnrolledCourse[];
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Learner course completion (DM proxy over Open edX completion).
|
|
29
|
+
* `GET /api/catalog/enrollment/courses/completion/`
|
|
30
|
+
*
|
|
31
|
+
* The learner must always be named explicitly, even when reading one's own
|
|
32
|
+
* data: edX ignores `username` for non-staff tokens, so the DM resolves the
|
|
33
|
+
* learner and checks the caller may read them.
|
|
34
|
+
*/
|
|
35
|
+
export type LearnerIdentifier = {
|
|
36
|
+
username: string;
|
|
37
|
+
user_id?: never;
|
|
38
|
+
email?: never;
|
|
39
|
+
} | {
|
|
40
|
+
user_id: string | number;
|
|
41
|
+
username?: never;
|
|
42
|
+
email?: never;
|
|
43
|
+
} | {
|
|
44
|
+
email: string;
|
|
45
|
+
username?: never;
|
|
46
|
+
user_id?: never;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* `endpoint` selector accepted by the DM. Only `outline` is implemented;
|
|
50
|
+
* the others are listed so sibling queries can reuse the URL builder.
|
|
51
|
+
*/
|
|
52
|
+
export type LearnerCompletionEndpoint = 'status' | 'outline' | 'blocks' | 'progress';
|
|
53
|
+
export type LearnerCompletionArgs = LearnerIdentifier & {
|
|
54
|
+
course_id: string;
|
|
55
|
+
platform_key: string;
|
|
56
|
+
};
|
|
57
|
+
export type LearnerCourseOutlineArgs = LearnerCompletionArgs;
|
|
58
|
+
export interface SpecialExamInfo {
|
|
59
|
+
short_description: string;
|
|
60
|
+
suggested_icon: string;
|
|
61
|
+
in_completed_state: boolean;
|
|
62
|
+
}
|
|
63
|
+
export interface CompletionOutlineBlock {
|
|
64
|
+
/** Full usage key; the only globally unique field. */
|
|
65
|
+
id: string;
|
|
66
|
+
block_id: string;
|
|
67
|
+
/** 'course' | 'chapter' | 'sequential' | 'vertical' | 'problem' | 'video' | 'html' | … */
|
|
68
|
+
type: string;
|
|
69
|
+
display_name: string;
|
|
70
|
+
lms_web_url: string;
|
|
71
|
+
legacy_web_url: string;
|
|
72
|
+
student_view_url: string;
|
|
73
|
+
graded: boolean;
|
|
74
|
+
start: string;
|
|
75
|
+
has_score: boolean;
|
|
76
|
+
scored: boolean;
|
|
77
|
+
num_graded_problems: number;
|
|
78
|
+
/** 0–100, computed by the backend. Display as-is; don't recompute. */
|
|
79
|
+
completion_percentage: number;
|
|
80
|
+
/** Absent on leaves and on empty containers. */
|
|
81
|
+
children?: CompletionOutlineBlock[];
|
|
82
|
+
/** Absent means false (leaves only carry it when true). */
|
|
83
|
+
complete?: boolean;
|
|
84
|
+
/** Leaves only; 0–1. */
|
|
85
|
+
completion?: number;
|
|
86
|
+
weight?: number;
|
|
87
|
+
/** Only present (true) along the path to the last-visited leaf. */
|
|
88
|
+
resume_block?: boolean;
|
|
89
|
+
special_exam_info?: SpecialExamInfo;
|
|
90
|
+
/** Root only. */
|
|
91
|
+
has_scheduled_content?: boolean;
|
|
92
|
+
}
|
|
93
|
+
/** Root node, `type === 'course'`. */
|
|
94
|
+
export type CompletionOutlineResponse = CompletionOutlineBlock;
|
|
95
|
+
export type NormalizedCompletionOutlineBlock = Omit<CompletionOutlineBlock, 'children' | 'complete' | 'resume_block'> & {
|
|
96
|
+
children: NormalizedCompletionOutlineBlock[];
|
|
97
|
+
complete: boolean;
|
|
98
|
+
resume_block: boolean;
|
|
99
|
+
};
|
|
100
|
+
export interface FlatCompletionOutlineEntry {
|
|
101
|
+
block: CompletionOutlineBlock;
|
|
102
|
+
depth: number;
|
|
103
|
+
parentId: string | null;
|
|
104
|
+
/** Display names from the root down to (and including) this block. */
|
|
105
|
+
path: string[];
|
|
106
|
+
}
|
|
107
|
+
export interface CompletionOutlineSection {
|
|
108
|
+
id: string;
|
|
109
|
+
display_name: string;
|
|
110
|
+
completion_percentage: number;
|
|
111
|
+
complete: boolean;
|
|
112
|
+
block: CompletionOutlineBlock;
|
|
113
|
+
}
|
|
114
|
+
export type LearnerCompletionErrorKind = 'invalid_request' | 'unauthorized' | 'forbidden' | 'not_enrolled' | 'unavailable' | 'unknown';
|
|
115
|
+
export interface LearnerCompletionError {
|
|
116
|
+
kind: LearnerCompletionErrorKind;
|
|
117
|
+
status?: number | string;
|
|
118
|
+
/** Only `unavailable` (502/503/504, network) is worth retrying. */
|
|
119
|
+
retryable: boolean;
|
|
120
|
+
}
|
|
@@ -2,13 +2,44 @@ export interface CustomDomainImage {
|
|
|
2
2
|
image: string;
|
|
3
3
|
alt: string;
|
|
4
4
|
}
|
|
5
|
+
/**
|
|
6
|
+
* One DNS record the domain's owner has to set at their registrar. `reason`
|
|
7
|
+
* explains why it is needed and is written for a human, so it can be shown
|
|
8
|
+
* as-is.
|
|
9
|
+
*/
|
|
10
|
+
export interface DomainRecord {
|
|
11
|
+
type: string;
|
|
12
|
+
name: string;
|
|
13
|
+
value: string;
|
|
14
|
+
reason?: string;
|
|
15
|
+
}
|
|
16
|
+
/** A domain serving a deployed app rather than one of the sign-in/app SPAs. */
|
|
17
|
+
export declare const VERCEL_SPA = "vercel";
|
|
5
18
|
export interface CustomDomain {
|
|
6
19
|
id: number;
|
|
7
20
|
custom_domain: string;
|
|
21
|
+
/** `vercel` for a deployed app; the other values are the sign-in/app SPAs. */
|
|
8
22
|
spa: string;
|
|
9
23
|
spa_display?: string;
|
|
10
24
|
registered_with_dns_pro?: boolean;
|
|
11
25
|
dns_pro_display?: string;
|
|
26
|
+
/**
|
|
27
|
+
* When the organization last proved it controls the domain; `null` if never.
|
|
28
|
+
* Only ever set on hosted (`spa: 'vercel'`) rows — the SPA domains are
|
|
29
|
+
* verified in the browser instead, and have no server-side record of it.
|
|
30
|
+
*/
|
|
31
|
+
verified_at?: string | null;
|
|
32
|
+
/**
|
|
33
|
+
* When another organization claimed the domain, `null` while this one still
|
|
34
|
+
* holds it. A lost domain comes back the moment it verifies again.
|
|
35
|
+
*/
|
|
36
|
+
lost_at?: string | null;
|
|
37
|
+
/**
|
|
38
|
+
* The records to set, structured. Written only on the hosting path, so an
|
|
39
|
+
* SPA row always reads `[]` and its single CNAME is computed client-side.
|
|
40
|
+
*/
|
|
41
|
+
records?: DomainRecord[];
|
|
42
|
+
/** The same records as free text. Prefer `records`; do not parse this. */
|
|
12
43
|
instructions?: string;
|
|
13
44
|
platform_id?: number;
|
|
14
45
|
platform_key?: string;
|