taleem-kernel 1.3.0 → 1.5.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.
@@ -8,18 +8,12 @@ export default class Communication {
8
8
  const where = {};
9
9
 
10
10
  if (filters.courseSlug) {
11
- const items = await this.kernel.db.library.findMany({
12
- where: { courseSlug: filters.courseSlug },
13
- select: { slug: true }
14
- });
15
-
16
- where.librarySlug = {
17
- in: items.map(item => item.slug)
18
- };
11
+ where.library = { courseSlug: filters.courseSlug };
19
12
  }
20
13
 
21
14
  if (filters.librarySlug) where.librarySlug = filters.librarySlug;
22
15
  if (filters.userId) where.userId = filters.userId;
16
+ if (filters.initiator) where.initiator = filters.initiator;
23
17
 
24
18
  if (filters.unanswered) {
25
19
  where.OR = [
@@ -30,35 +24,20 @@ export default class Communication {
30
24
 
31
25
  return this.kernel.db.communication.findMany({
32
26
  where,
33
- include: { user: true },
27
+ include: { user: true, library: true },
34
28
  orderBy: { createdAt: "desc" }
35
29
  });
36
30
  }
37
31
 
38
32
  async get(id) {
39
- const item = await this.kernel.db.communication.findUnique({
33
+ return this.kernel.db.communication.findUnique({
40
34
  where: { id },
41
- include: { user: true }
35
+ include: { user: true, library: true }
42
36
  });
43
-
44
- if (!item) return null;
45
-
46
- const library = await this.kernel.db.library.findUnique({
47
- where: { slug: item.librarySlug },
48
- select: {
49
- slug: true,
50
- title: true,
51
- courseSlug: true
52
- }
53
- });
54
-
55
- return {
56
- ...item,
57
- library
58
- };
59
37
  }
60
38
 
61
39
  async create(data) {
40
+ // throws if librarySlug doesn't resolve to an existing Library row
62
41
  return this.kernel.db.communication.create({ data });
63
42
  }
64
43
 
@@ -76,30 +55,7 @@ export default class Communication {
76
55
  }
77
56
 
78
57
  async listUnanswered(courseSlug) {
79
- const items = await this.list({
80
- courseSlug,
81
- unanswered: true
82
- });
83
-
84
- const slugs = [...new Set(items.map(item => item.librarySlug))];
85
-
86
- const libraries = await this.kernel.db.library.findMany({
87
- where: { slug: { in: slugs } },
88
- select: {
89
- slug: true,
90
- title: true,
91
- courseSlug: true
92
- }
93
- });
94
-
95
- const map = new Map(
96
- libraries.map(item => [item.slug, item])
97
- );
98
-
99
- return items.map(item => ({
100
- ...item,
101
- library: map.get(item.librarySlug) || null
102
- }));
58
+ return this.list({ courseSlug, unanswered: true });
103
59
  }
104
60
 
105
61
  async countUserOpenQuestions(userId) {
@@ -4,51 +4,44 @@ export default class Course {
4
4
  async list(filters = {}) {
5
5
  const where = {};
6
6
  if (filters.access) where.access = filters.access;
7
+ if (filters.isActive !== undefined) where.isActive = filters.isActive;
7
8
  return this.kernel.db.course.findMany({ where });
8
9
  }
10
+
9
11
  async get(slug) {
10
12
  return this.kernel.db.course.findUnique({ where: { slug } });
11
13
  }
12
- async getGroups(courseSlug) {
13
- return this.kernel.db.group.findMany({
14
- where: { courseSlug },
15
- orderBy: { id: 'asc' }
16
- });
17
- }
18
- async getGroup(courseSlug, groupSlug) {
19
- return this.kernel.db.group.findUnique({
20
- where: {
21
- courseSlug_slug: { courseSlug, slug: groupSlug }
22
- }
23
- });
24
- }
25
- async getGroupItems(courseSlug, groupSlug) {
26
- const group = await this.getGroup(courseSlug, groupSlug);
27
- return group?.items ?? [];
28
- }
29
- async wipe() {
30
- await this.kernel.db.group.deleteMany();
31
- await this.kernel.db.course.deleteMany();
32
- }
33
- async seed(course) {
34
- const { groupings = [], ...courseData } = course;
35
-
36
- const created = await this.kernel.db.course.create({
37
- data: courseData
38
- });
39
-
40
- for (const group of groupings) {
41
- await this.kernel.db.group.create({
42
- data: {
43
- courseSlug: created.slug,
44
- slug: group.slug,
45
- title: group.title,
46
- thumbnail: group.thumbnail ?? null,
47
- items: group.items ?? []
48
- }
49
- });
50
- }
51
-
52
- return created;
14
+
15
+ async create(data) {
16
+ return this.kernel.db.course.create({ data });
17
+ }
18
+
19
+ async update(slug, data) {
20
+ return this.kernel.db.course.update({ where: { slug }, data });
21
+ }
22
+
23
+ async delete(slug) {
24
+ // throws if any Group or Subscription still references this course
25
+ return this.kernel.db.course.delete({ where: { slug } });
26
+ }
27
+
28
+ async authorize(userId, courseSlug) {
29
+ const course = await this.get(courseSlug);
30
+ if (!course) throw new Error(`Course "${courseSlug}" not found.`);
31
+
32
+ if (course.access === "OPEN") return true;
33
+
34
+ if (course.access === "MEMBERS") {
35
+ if (!userId) throw new Error("Login required for this course.");
36
+ return true;
37
+ }
38
+
39
+ if (course.access === "SUBSCRIPTION") {
40
+ if (!userId) throw new Error("Login required for this course.");
41
+ await this.kernel.subscription.authorize(userId, courseSlug);
42
+ return true;
43
+ }
44
+
45
+ throw new Error(`Unknown access level "${course.access}".`);
53
46
  }
54
47
  }
@@ -0,0 +1,48 @@
1
+ export default class Group {
2
+ constructor(kernel) { this.kernel = kernel; }
3
+
4
+ async list(filters = {}) {
5
+ const where = {};
6
+ if (filters.courseSlug) where.courseSlug = filters.courseSlug;
7
+
8
+ return this.kernel.db.group.findMany({
9
+ where,
10
+ orderBy: { id: "asc" }
11
+ });
12
+ }
13
+
14
+ async listByCourse(courseSlug) {
15
+ return this.list({ courseSlug });
16
+ }
17
+
18
+ async get(courseSlug, slug) {
19
+ return this.kernel.db.group.findUnique({
20
+ where: {
21
+ courseSlug_slug: { courseSlug, slug }
22
+ }
23
+ });
24
+ }
25
+
26
+ async create(data) {
27
+ // throws if data.courseSlug doesn't resolve to an existing Course
28
+ return this.kernel.db.group.create({ data });
29
+ }
30
+
31
+ async update(courseSlug, slug, data) {
32
+ return this.kernel.db.group.update({
33
+ where: {
34
+ courseSlug_slug: { courseSlug, slug }
35
+ },
36
+ data
37
+ });
38
+ }
39
+
40
+ async delete(courseSlug, slug) {
41
+ // throws if any Library rows still reference this group (Restrict)
42
+ return this.kernel.db.group.delete({
43
+ where: {
44
+ courseSlug_slug: { courseSlug, slug }
45
+ }
46
+ });
47
+ }
48
+ }
@@ -1,12 +1,17 @@
1
+ const PUBLIC_STATUS = "PUBLISHED";
2
+
1
3
  export default class Library {
2
4
  constructor(kernel) { this.kernel = kernel; }
3
5
 
4
- async list(filters = {}) {
6
+ async list(filters = {}, { includeUnpublished = false } = {}) {
5
7
  const where = {};
6
8
  if (filters.type) where.type = filters.type;
7
9
  if (filters.courseSlug) where.courseSlug = filters.courseSlug;
8
10
  if (filters.groupSlug) where.groupSlug = filters.groupSlug;
9
11
 
12
+ if (!includeUnpublished) where.status = PUBLIC_STATUS;
13
+ else if (filters.status) where.status = filters.status;
14
+
10
15
  return this.kernel.db.library.findMany({
11
16
  where,
12
17
  select: {
@@ -15,6 +20,7 @@ export default class Library {
15
20
  description: true,
16
21
  thumbnail: true,
17
22
  type: true,
23
+ status: true,
18
24
  courseSlug: true,
19
25
  groupSlug: true,
20
26
  sortOrder: true,
@@ -26,17 +32,20 @@ export default class Library {
26
32
  });
27
33
  }
28
34
 
29
- async listByCourse(courseSlug) {
30
- return this.list({ courseSlug });
35
+ async listByCourse(courseSlug, opts) {
36
+ return this.list({ courseSlug }, opts);
31
37
  }
32
38
 
33
- async listByGroup(courseSlug, groupSlug) {
34
- return this.list({ courseSlug, groupSlug });
39
+ async listByGroup(courseSlug, groupSlug, opts) {
40
+ return this.list({ courseSlug, groupSlug }, opts);
35
41
  }
36
42
 
37
- async get(slug) {
43
+ async get(slug, { includeUnpublished = false } = {}) {
38
44
  return this.kernel.db.library.findUnique({
39
- where: { slug }
45
+ where: {
46
+ slug,
47
+ ...(includeUnpublished ? {} : { status: PUBLIC_STATUS })
48
+ }
40
49
  });
41
50
  }
42
51
 
@@ -52,11 +61,13 @@ export default class Library {
52
61
  }
53
62
 
54
63
  async delete(slug) {
64
+ // throws if Communication rows still reference this slug (Restrict)
55
65
  return this.kernel.db.library.delete({
56
66
  where: { slug }
57
67
  });
58
68
  }
59
- async createFromSlot(slug, courseSlug, groupSlug, type) {
69
+
70
+ async createFromSlot(slug, courseSlug, groupSlug, type) {
60
71
  return this.create({
61
72
  slug,
62
73
  courseSlug,
@@ -65,4 +76,5 @@ export default class Library {
65
76
  title: slug
66
77
  });
67
78
  }
79
+
68
80
  }
@@ -1,97 +1,48 @@
1
- // src/serverKernel/modules/Subscription.js
2
-
3
1
  export default class Subscription {
4
-
5
- constructor(kernel) {
6
- this.kernel = kernel;
7
- }
8
-
9
- // --------------------------------------------------
10
- // Queries
11
- // --------------------------------------------------
2
+ constructor(kernel) { this.kernel = kernel; }
12
3
 
13
4
  async list(filters = {}) {
14
-
15
5
  const where = {};
16
-
17
- if (filters.userId) {
18
- where.userId = filters.userId;
19
- }
20
-
21
- if (filters.courseId) {
22
- where.courseId = filters.courseId;
23
- }
24
-
25
- return this.kernel.db.subscription.findMany({
26
- where
27
- });
28
-
6
+ if (filters.userId) where.userId = filters.userId;
7
+ if (filters.courseSlug) where.courseSlug = filters.courseSlug;
8
+ return this.kernel.db.subscription.findMany({ where });
29
9
  }
30
10
 
31
11
  async get(id) {
32
-
33
- return this.kernel.db.subscription.findUnique({
34
- where: { id }
35
- });
36
-
12
+ return this.kernel.db.subscription.findUnique({ where: { id } });
37
13
  }
38
14
 
39
- // --------------------------------------------------
40
- // CRUD
41
- // --------------------------------------------------
42
-
43
15
  async create(data) {
44
-
45
- return this.kernel.db.subscription.create({
46
- data
47
- });
48
-
16
+ // throws if courseSlug doesn't resolve to an existing Course
17
+ return this.kernel.db.subscription.create({ data });
49
18
  }
50
19
 
51
20
  async update(id, data) {
52
-
53
- return this.kernel.db.subscription.update({
54
- where: { id },
55
- data
56
- });
57
-
21
+ return this.kernel.db.subscription.update({ where: { id }, data });
58
22
  }
59
23
 
60
24
  async delete(id) {
61
-
62
- return this.kernel.db.subscription.delete({
63
- where: { id }
64
- });
65
-
25
+ return this.kernel.db.subscription.delete({ where: { id } });
66
26
  }
67
27
 
68
- // --------------------------------------------------
69
- // Utilities
70
- // --------------------------------------------------
71
-
72
- async authorize(userId, courseId) {
73
- debugger;
28
+ async authorize(userId, courseSlug) {
74
29
  const now = new Date();
75
30
 
76
31
  const subscription = await this.kernel.db.subscription.findFirst({
77
-
78
32
  where: {
79
33
  userId,
80
- courseId,
34
+ courseSlug,
81
35
  startsAt: { lte: now },
82
36
  endsAt: { gte: now }
83
37
  }
84
-
85
38
  });
86
39
 
87
40
  if (!subscription) {
88
41
  throw new Error(
89
- `User "${userId}" does not have an active subscription for course "${courseId}".`
42
+ `User "${userId}" does not have an active subscription for course "${courseSlug}".`
90
43
  );
91
44
  }
92
45
 
93
46
  return subscription;
94
-
95
47
  }
96
-
97
48
  }
@@ -1,12 +1,8 @@
1
- // src/serverKernel/modules/Svg.js
2
-
3
1
  export default class Svg {
4
2
  constructor(kernel) { this.kernel = kernel; }
5
3
 
6
4
  async list() {
7
- return this.kernel.db.svg.findMany({
8
- orderBy: { title: "asc" }
9
- });
5
+ return this.kernel.db.svg.findMany({ orderBy: { title: "asc" } });
10
6
  }
11
7
 
12
8
  async get(slug) {
@@ -14,25 +10,11 @@ export default class Svg {
14
10
  }
15
11
 
16
12
  async create(data) {
17
- return this.kernel.db.svg.create({
18
- data: {
19
- slug: data.slug,
20
- title: data.title,
21
- body: data.body,
22
- tags: data.tags ?? "[]"
23
- }
24
- });
13
+ return this.kernel.db.svg.create({ data });
25
14
  }
26
15
 
27
16
  async update(slug, data) {
28
- return this.kernel.db.svg.update({
29
- where: { slug },
30
- data: {
31
- title: data.title,
32
- body: data.body,
33
- tags: data.tags
34
- }
35
- });
17
+ return this.kernel.db.svg.update({ where: { slug }, data });
36
18
  }
37
19
 
38
20
  async delete(slug) {
package/prisma/content.db DELETED
Binary file