@crimson-education/sdk 0.2.3 → 0.2.4

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/README.md CHANGED
@@ -116,11 +116,13 @@ const page = await client.missions.listPaginated("student-uid", undefined, {
116
116
  涉及接口:
117
117
 
118
118
  - `GET /roadmap/action-items`
119
+ - `GET /roadmap/action-items/creators`
119
120
  - `POST /roadmap/action-items`
120
121
  - `PUT /roadmap/action-items/:id`
121
122
  - `DELETE /roadmap/action-items/:id`
122
123
  - `POST /roadmap/action-items/:actionItemId/resources`
123
124
  - `POST /roadmap/upload`
125
+ - `GET /roadmap/download`
124
126
 
125
127
  主要方法:
126
128
 
@@ -138,6 +140,10 @@ const page = await client.missions.listPaginated("student-uid", undefined, {
138
140
  - 当 **同时提供** `roadmapId` 且提供 `start/limit` 时:返回 `PaginatedResult<Task>`
139
141
  - `listPaginated(roadmapId, userId, filters?, pagination?)`
140
142
  - 始终返回 `PaginatedResult<Task>`(内部复用 `list`)
143
+ - `getCreators(roadmapId)`
144
+ - 获取指定 roadmap 下所有任务的创建者列表
145
+ - `getDownloadUrl(key)`
146
+ - 获取 S3 资源的预签名下载 URL
141
147
  - `create(data: Partial<Task>)`
142
148
  - 支持两种模式:
143
149
  - Mission 关联任务:提供 `roadmapMissionId`(或 `missionId`)
@@ -203,6 +209,8 @@ SDK 会将后端返回的 action item 做归一化,保证至少返回以下核
203
209
  涉及接口:
204
210
 
205
211
  - `GET /roadmap/library/missions`
212
+ - `POST /roadmap/library/missions`
213
+ - `PUT /roadmap/library/missions/:missionId`
206
214
  - `GET /roadmap/library/tasks`
207
215
  - `POST /roadmap/library/missions/copy`
208
216
  - `POST /roadmap/library/missions/assign-bulk`
@@ -213,6 +221,8 @@ SDK 会将后端返回的 action item 做归一化,保证至少返回以下核
213
221
  主要方法:
214
222
 
215
223
  - `listTemplateMissions(filters?: TemplateMissionFilters): Promise<PaginatedResult<TemplateMission>>`
224
+ - `createTemplateMission(input: TemplateMissionCreateInput): Promise<TemplateMission>`
225
+ - `updateTemplateMission(id: string, raw: TemplateMission, update: TemplateMissionUpdateInput): Promise<TemplateMission>`
216
226
  - `listTemplateTasks(filters?: TemplateTaskFilters): Promise<PaginatedResult<TemplateTask>>`
217
227
  - `copyTemplateMission(input: CopyTemplateMissionInput): Promise<TemplateMission[]>`
218
228
  - `assignBulkMission(input: AssignBulkMissionInput[]): Promise<{ code: number; msg?: string }>`
@@ -314,9 +324,16 @@ Props:
314
324
  - `useTasks(missionId, enabled)`:拉取某 mission 的 tasks
315
325
  - `useTasksInfinite(roadmapId, userId, filters?, options?)`:分页拉取 tasks
316
326
  - `useRoadmapContext(userId, enabled)`:拉取 roadmap context
327
+ - `useTaskCreators(roadmapId, enabled)`:获取任务创建者列表
317
328
  - CRUD mutation:
318
329
  - `useCreateMission/useUpdateMission/useDeleteMission`
319
330
  - `useCreateTask/useUpdateTask/useDeleteTask`
331
+ - `useCreateTemplateMission/useUpdateTemplateMission`
332
+ - `useGetDownloadUrl`:获取文件下载地址
333
+ - 模板库相关:
334
+ - `useTemplateMissions/useTemplateMissionsInfinite`
335
+ - `useTemplateTasks/useTemplateTasksInfinite`
336
+ - `useTemplateMissionDetail(missionId)`
320
337
 
321
338
  ---
322
339
 
@@ -39,6 +39,17 @@ export interface CreateFromPredefinedInput {
39
39
  missionId: string;
40
40
  predefinedTaskIds: string[];
41
41
  }
42
+ export interface TemplateMissionCreateInput {
43
+ title: string;
44
+ description: string;
45
+ category: string;
46
+ subcategory: string;
47
+ tasks: {
48
+ id?: string | null;
49
+ description: string;
50
+ content: string;
51
+ }[];
52
+ }
42
53
  export declare class MissionLibraryApi {
43
54
  private client;
44
55
  constructor(client: CrimsonClient);
@@ -46,6 +57,10 @@ export declare class MissionLibraryApi {
46
57
  * List template missions with pagination
47
58
  */
48
59
  listTemplateMissions(filters?: TemplateMissionFilters): Promise<PaginatedResult<TemplateMission>>;
60
+ /**
61
+ * Create a new template mission
62
+ */
63
+ createTemplateMission(input: TemplateMissionCreateInput): Promise<TemplateMission>;
49
64
  /**
50
65
  * List template tasks with pagination
51
66
  */
@@ -49,6 +49,17 @@ class MissionLibraryApi {
49
49
  return this.client.fetch(path);
50
50
  });
51
51
  }
52
+ /**
53
+ * Create a new template mission
54
+ */
55
+ createTemplateMission(input) {
56
+ return __awaiter(this, void 0, void 0, function* () {
57
+ return this.client.fetch("/roadmap/library/missions", {
58
+ method: "POST",
59
+ body: JSON.stringify(Object.assign(Object.assign({}, input), { type: "custom" })),
60
+ });
61
+ });
62
+ }
52
63
  /**
53
64
  * List template tasks with pagination
54
65
  */
@@ -1,5 +1,5 @@
1
1
  import type { CrimsonClient } from "./client";
2
- import type { Task, PaginationParams, PaginatedResult, ActionItemResource, AddResourceInput, UploadUrlResponse, UpdateTaskResourceInput } from "./types";
2
+ import type { Task, PaginationParams, PaginatedResult, ActionItemResource, AddResourceInput, UploadUrlResponse, DownloadUrlResponse, UpdateTaskResourceInput, User } from "./types";
3
3
  export type TaskOrderBy = "priority" | "dueDate" | "missionTitle" | "createdAt" | "description";
4
4
  export interface TaskFilters extends PaginationParams {
5
5
  status?: string[];
@@ -28,6 +28,10 @@ export declare class TasksApi {
28
28
  * List tasks with pagination (requires roadmapId, always returns paginated result)
29
29
  */
30
30
  listPaginated(roadmapId: string, userId: string, filters?: Omit<TaskFilters, "start" | "limit">, pagination?: PaginationParams): Promise<PaginatedResult<Task>>;
31
+ /**
32
+ * Get all creators of tasks in a roadmap
33
+ */
34
+ getCreators(roadmapId: string): Promise<User[]>;
31
35
  /**
32
36
  * Create a new task/action item
33
37
  *
@@ -92,6 +96,13 @@ export declare class TasksApi {
92
96
  * await tasks.updateResources(taskId, [{ title: "Document", type: "Upload", url }]);
93
97
  */
94
98
  getUploadUrl(filename: string, contentType: string): Promise<UploadUrlResponse>;
99
+ /**
100
+ * Get a presigned URL for downloading a file from S3
101
+ *
102
+ * @param key - The S3 object key
103
+ * @returns Promise with url (presigned download URL)
104
+ */
105
+ getDownloadUrl(key: string): Promise<DownloadUrlResponse>;
95
106
  /**
96
107
  * Upload a file and get the S3 URL
97
108
  *
@@ -149,6 +149,12 @@ class TasksApi {
149
149
  var _a, _b;
150
150
  return this.list({ roadmapId, userId }, Object.assign(Object.assign({}, filters), { start: (_a = pagination === null || pagination === void 0 ? void 0 : pagination.start) !== null && _a !== void 0 ? _a : 0, limit: (_b = pagination === null || pagination === void 0 ? void 0 : pagination.limit) !== null && _b !== void 0 ? _b : 20 }));
151
151
  }
152
+ /**
153
+ * Get all creators of tasks in a roadmap
154
+ */
155
+ getCreators(roadmapId) {
156
+ return this.client.fetch(`/roadmap/action-items/creators?roadmapId=${roadmapId}`);
157
+ }
152
158
  /**
153
159
  * Create a new task/action item
154
160
  *
@@ -246,6 +252,17 @@ class TasksApi {
246
252
  body: JSON.stringify({ filename, contentType }),
247
253
  });
248
254
  }
255
+ /**
256
+ * Get a presigned URL for downloading a file from S3
257
+ *
258
+ * @param key - The S3 object key
259
+ * @returns Promise with url (presigned download URL)
260
+ */
261
+ getDownloadUrl(key) {
262
+ return this.client.fetch(`/roadmap/download?key=${encodeURIComponent(key)}`, {
263
+ method: "GET",
264
+ });
265
+ }
249
266
  /**
250
267
  * Upload a file and get the S3 URL
251
268
  *
@@ -297,6 +297,10 @@ export interface UploadUrlResponse {
297
297
  /** S3 bucket name */
298
298
  bucket: string;
299
299
  }
300
+ export interface DownloadUrlResponse {
301
+ /** Presigned URL for downloading the file */
302
+ url: string;
303
+ }
300
304
  export interface UpdateTaskResourceInput {
301
305
  /** Resource ID - include to update existing, omit to create new */
302
306
  id?: string;
@@ -2,7 +2,7 @@ export { useAuthState } from "./useAuthState";
2
2
  export { useOAuth, useOAuthCallback } from "./useOAuth";
3
3
  export type { UseOAuthResult } from "./useOAuth";
4
4
  export { useMissions, useMissionsInfinite, useCreateMission, useUpdateMission, useDeleteMission, missionKeys, } from "./useMissions";
5
- export { useTasks, useAllUserTasks, useTasksByRoadmapId, useTasksInfinite, useCreateTask, useUpdateTask, useDeleteTask, taskKeys, } from "./useTasks";
5
+ export { useTasks, useAllUserTasks, useTasksByRoadmapId, useTasksInfinite, useCreateTask, useUpdateTask, useDeleteTask, taskKeys, useGetDownloadUrl, useTaskCreators } from "./useTasks";
6
6
  export { useUsers, useUser, userKeys } from "./useUsers";
7
7
  export { useCurrentUserRoles, useMyStudents, accountKeys } from "./useAccount";
8
8
  export { useRoadmapContext } from "./useRoadmapContext";
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.studentProfileKeys = exports.useStudentPrefilledInfo = exports.useStudentProfile = exports.missionLibraryKeys = exports.useCreateFromPredefinedTasks = exports.useAssignBulkTask = exports.useAssignBulkMission = exports.useCopyTemplateMission = exports.useUpdateTemplateMission = exports.useTemplateMissionDetail = exports.useTemplateTasksInfinite = exports.useTemplateTasks = exports.useTemplateMissionsInfinite = exports.useTemplateMissions = exports.useRoadmapContext = exports.accountKeys = exports.useMyStudents = exports.useCurrentUserRoles = exports.userKeys = exports.useUser = exports.useUsers = exports.taskKeys = exports.useDeleteTask = exports.useUpdateTask = exports.useCreateTask = exports.useTasksInfinite = exports.useTasksByRoadmapId = exports.useAllUserTasks = exports.useTasks = exports.missionKeys = exports.useDeleteMission = exports.useUpdateMission = exports.useCreateMission = exports.useMissionsInfinite = exports.useMissions = exports.useOAuthCallback = exports.useOAuth = exports.useAuthState = void 0;
3
+ exports.studentProfileKeys = exports.useStudentPrefilledInfo = exports.useStudentProfile = exports.missionLibraryKeys = exports.useCreateFromPredefinedTasks = exports.useAssignBulkTask = exports.useAssignBulkMission = exports.useCopyTemplateMission = exports.useUpdateTemplateMission = exports.useTemplateMissionDetail = exports.useTemplateTasksInfinite = exports.useTemplateTasks = exports.useTemplateMissionsInfinite = exports.useTemplateMissions = exports.useRoadmapContext = exports.accountKeys = exports.useMyStudents = exports.useCurrentUserRoles = exports.userKeys = exports.useUser = exports.useUsers = exports.useTaskCreators = exports.useGetDownloadUrl = exports.taskKeys = exports.useDeleteTask = exports.useUpdateTask = exports.useCreateTask = exports.useTasksInfinite = exports.useTasksByRoadmapId = exports.useAllUserTasks = exports.useTasks = exports.missionKeys = exports.useDeleteMission = exports.useUpdateMission = exports.useCreateMission = exports.useMissionsInfinite = exports.useMissions = exports.useOAuthCallback = exports.useOAuth = exports.useAuthState = void 0;
4
4
  var useAuthState_1 = require("./useAuthState");
5
5
  Object.defineProperty(exports, "useAuthState", { enumerable: true, get: function () { return useAuthState_1.useAuthState; } });
6
6
  var useOAuth_1 = require("./useOAuth");
@@ -22,6 +22,8 @@ Object.defineProperty(exports, "useCreateTask", { enumerable: true, get: functio
22
22
  Object.defineProperty(exports, "useUpdateTask", { enumerable: true, get: function () { return useTasks_1.useUpdateTask; } });
23
23
  Object.defineProperty(exports, "useDeleteTask", { enumerable: true, get: function () { return useTasks_1.useDeleteTask; } });
24
24
  Object.defineProperty(exports, "taskKeys", { enumerable: true, get: function () { return useTasks_1.taskKeys; } });
25
+ Object.defineProperty(exports, "useGetDownloadUrl", { enumerable: true, get: function () { return useTasks_1.useGetDownloadUrl; } });
26
+ Object.defineProperty(exports, "useTaskCreators", { enumerable: true, get: function () { return useTasks_1.useTaskCreators; } });
25
27
  var useUsers_1 = require("./useUsers");
26
28
  Object.defineProperty(exports, "useUsers", { enumerable: true, get: function () { return useUsers_1.useUsers; } });
27
29
  Object.defineProperty(exports, "useUser", { enumerable: true, get: function () { return useUsers_1.useUser; } });
@@ -1,5 +1,5 @@
1
1
  import type { TemplateMission, TemplateTask, MissionDetail, AssignBulkMissionInput, AssignBulkTaskInput } from "../../core/types";
2
- import type { TemplateMissionFilters, TemplateTaskFilters, CopyTemplateMissionInput, CreateFromPredefinedInput, TemplateMissionUpdateInput } from "../../core/missionLibrary";
2
+ import type { TemplateMissionFilters, TemplateTaskFilters, CopyTemplateMissionInput, CreateFromPredefinedInput, TemplateMissionUpdateInput, TemplateMissionCreateInput } from "../../core/missionLibrary";
3
3
  export declare const missionLibraryKeys: {
4
4
  all: readonly ["missionLibrary"];
5
5
  missions: (filters?: TemplateMissionFilters) => readonly ["missionLibrary", "missions", TemplateMissionFilters | undefined];
@@ -24,6 +24,7 @@ export declare function useUpdateTemplateMission(): import("@tanstack/react-quer
24
24
  raw: TemplateMission;
25
25
  update: TemplateMissionUpdateInput;
26
26
  }, unknown>;
27
+ export declare function useCreateTemplateMission(): import("@tanstack/react-query").UseMutationResult<TemplateMission, Error, TemplateMissionCreateInput, unknown>;
27
28
  export declare function useCopyTemplateMission(): import("@tanstack/react-query").UseMutationResult<TemplateMission[], Error, CopyTemplateMissionInput, unknown>;
28
29
  export declare function useAssignBulkMission(): import("@tanstack/react-query").UseMutationResult<{
29
30
  code: number;
@@ -17,6 +17,7 @@ exports.useTemplateTasks = useTemplateTasks;
17
17
  exports.useTemplateTasksInfinite = useTemplateTasksInfinite;
18
18
  exports.useTemplateMissionDetail = useTemplateMissionDetail;
19
19
  exports.useUpdateTemplateMission = useUpdateTemplateMission;
20
+ exports.useCreateTemplateMission = useCreateTemplateMission;
20
21
  exports.useCopyTemplateMission = useCopyTemplateMission;
21
22
  exports.useAssignBulkMission = useAssignBulkMission;
22
23
  exports.useAssignBulkTask = useAssignBulkTask;
@@ -121,6 +122,20 @@ function useUpdateTemplateMission() {
121
122
  },
122
123
  });
123
124
  }
125
+ function useCreateTemplateMission() {
126
+ const client = (0, provider_1.useCrimsonClient)();
127
+ const queryClient = (0, react_query_1.useQueryClient)();
128
+ return (0, react_query_1.useMutation)({
129
+ mutationFn: (input) => client.library.createTemplateMission(input),
130
+ onSuccess: () => {
131
+ queryClient.invalidateQueries({
132
+ queryKey: exports.missionLibraryKeys.missionsInfinite({
133
+ groups: ["custom"],
134
+ }),
135
+ });
136
+ },
137
+ });
138
+ }
124
139
  function useCopyTemplateMission() {
125
140
  const client = (0, provider_1.useCrimsonClient)();
126
141
  const queryClient = (0, react_query_1.useQueryClient)();
@@ -1,4 +1,4 @@
1
- import type { Task, PaginatedResult } from "../../core/types";
1
+ import type { Task, PaginatedResult, User } from "../../core/types";
2
2
  import type { TaskFilters } from "../../core/tasks";
3
3
  export declare const taskKeys: {
4
4
  all: readonly ["tasks"];
@@ -7,8 +7,10 @@ export declare const taskKeys: {
7
7
  infinite: (roadmapId: string, userId: string, filters?: Omit<TaskFilters, "start" | "limit">) => readonly ["tasks", "infinite", string, string, Omit<TaskFilters, "start" | "limit"> | undefined];
8
8
  details: () => readonly ["tasks", "detail"];
9
9
  detail: (id: string) => readonly ["tasks", "detail", string];
10
+ creators: (roadmapId: string) => readonly ["tasks", "creators", string];
10
11
  };
11
12
  export declare function useTasks(missionId: string | null, enabled: boolean): import("@tanstack/react-query").UseQueryResult<Task[], Error>;
13
+ export declare function useTaskCreators(roadmapId: string | null, enabled?: boolean): import("@tanstack/react-query").UseQueryResult<User[], Error>;
12
14
  export declare function useAllUserTasks(missionLinkIds: string[], enabled: boolean): import("@tanstack/react-query").UseQueryResult<Task[], Error>;
13
15
  export declare function useTasksByRoadmapId(roadmapId: string | null, userId: string | null, enabled: boolean): import("@tanstack/react-query").UseQueryResult<Task[], Error>;
14
16
  /**
@@ -24,3 +26,4 @@ export declare function useUpdateTask(): import("@tanstack/react-query").UseMuta
24
26
  data: Partial<Task>;
25
27
  }, unknown>;
26
28
  export declare function useDeleteTask(): import("@tanstack/react-query").UseMutationResult<void, Error, string, unknown>;
29
+ export declare function useGetDownloadUrl(): import("@tanstack/react-query").UseMutationResult<import("../../core/types").DownloadUrlResponse, Error, string, unknown>;
@@ -12,12 +12,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
13
  exports.taskKeys = void 0;
14
14
  exports.useTasks = useTasks;
15
+ exports.useTaskCreators = useTaskCreators;
15
16
  exports.useAllUserTasks = useAllUserTasks;
16
17
  exports.useTasksByRoadmapId = useTasksByRoadmapId;
17
18
  exports.useTasksInfinite = useTasksInfinite;
18
19
  exports.useCreateTask = useCreateTask;
19
20
  exports.useUpdateTask = useUpdateTask;
20
21
  exports.useDeleteTask = useDeleteTask;
22
+ exports.useGetDownloadUrl = useGetDownloadUrl;
21
23
  const react_query_1 = require("@tanstack/react-query");
22
24
  const provider_1 = require("../provider");
23
25
  // Query keys
@@ -28,6 +30,7 @@ exports.taskKeys = {
28
30
  infinite: (roadmapId, userId, filters) => [...exports.taskKeys.all, "infinite", roadmapId, userId, filters],
29
31
  details: () => [...exports.taskKeys.all, "detail"],
30
32
  detail: (id) => [...exports.taskKeys.details(), id],
33
+ creators: (roadmapId) => [...exports.taskKeys.all, "creators", roadmapId],
31
34
  };
32
35
  function useTasks(missionId, enabled) {
33
36
  const client = (0, provider_1.useCrimsonClient)();
@@ -43,6 +46,19 @@ function useTasks(missionId, enabled) {
43
46
  enabled: !!missionId && enabled,
44
47
  });
45
48
  }
49
+ function useTaskCreators(roadmapId, enabled = true) {
50
+ const client = (0, provider_1.useCrimsonClient)();
51
+ return (0, react_query_1.useQuery)({
52
+ queryKey: exports.taskKeys.creators(roadmapId || ""),
53
+ queryFn: () => __awaiter(this, void 0, void 0, function* () {
54
+ if (!roadmapId) {
55
+ return [];
56
+ }
57
+ return client.tasks.getCreators(roadmapId);
58
+ }),
59
+ enabled: !!roadmapId && enabled,
60
+ });
61
+ }
46
62
  function useAllUserTasks(missionLinkIds, enabled) {
47
63
  const client = (0, provider_1.useCrimsonClient)();
48
64
  return (0, react_query_1.useQuery)({
@@ -135,3 +151,9 @@ function useDeleteTask() {
135
151
  },
136
152
  });
137
153
  }
154
+ function useGetDownloadUrl() {
155
+ const client = (0, provider_1.useCrimsonClient)();
156
+ return (0, react_query_1.useMutation)({
157
+ mutationFn: (key) => client.tasks.getDownloadUrl(key),
158
+ });
159
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crimson-education/sdk",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "Crimson SDK for accessing Crimson App APIs",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",