taleem-kernel 1.2.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.
@@ -1,20 +1,31 @@
1
+ // /home/bilal-tariq/00--TALEEM/taleem-kernel/bin/schema-check.js
1
2
  import fs from "fs";
2
3
  import path from "path";
3
4
  import { fileURLToPath } from "url";
4
5
 
5
- const kernelSchema = fs.readFileSync(
6
- path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../prisma/schema.prisma"),
7
- "utf8"
6
+ const kernelSchemaPath = path.resolve(
7
+ path.dirname(fileURLToPath(import.meta.url)),
8
+ "../prisma/schema.prisma"
8
9
  );
9
10
 
10
- const appSchema = fs.readFileSync(
11
- path.resolve(process.cwd(), "prisma/schema.prisma"),
12
- "utf8"
13
- );
11
+ const appSchemaPath = path.resolve(process.cwd(), "prisma/schema.prisma");
12
+
13
+ function normalize(schema) {
14
+ return schema
15
+ .split("\n")
16
+ .map(line => line.replace(/\/\/.*$/, "").trim())
17
+ .filter(line => line.length > 0)
18
+ .join("\n");
19
+ }
14
20
 
15
- if (kernelSchema !== appSchema) {
16
- console.error("❌ Taleem Prisma schema mismatch.");
21
+ if (!fs.existsSync(appSchemaPath)) {
22
+ console.error(`❌ No schema.prisma found at ${appSchemaPath}.`);
23
+ console.error(`Run this command from the root of a Taleem application.`);
17
24
  process.exit(1);
18
25
  }
19
26
 
20
- console.log("✓ Taleem Prisma schema is up to date.");
27
+ const kernelSchema = fs.readFileSync(kernelSchemaPath, "utf8");
28
+ const appSchema = fs.readFileSync(appSchemaPath, "utf8");
29
+
30
+ if (normalize(kernelSchema) !== normalize(appSchema)) {
31
+ console.error("❌ Taleem Prisma schema mismatch.");
@@ -1,2 +1,3 @@
1
+ ///home/bilal-tariq/00--TALEEM/taleem-kernel/bin/schema-update.js
1
2
  fs.copyFileSync(kernelSchemaPath, appSchemaPath);
2
3
  console.log("✓ Taleem Prisma schema updated.");
package/package.json CHANGED
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "taleem-kernel",
3
- "version": "1.2.0",
3
+ "version": "1.5.0",
4
4
  "description": "Taleem data and business-logic kernel. HTTP is only an adapter.",
5
5
  "type": "module",
6
- "main": "./src/ServerKernel.js",
6
+ "main": "./src/index.js",
7
7
  "exports": {
8
- ".": "./src/ServerKernel.js"
8
+ ".": "./src/index.js"
9
9
  },
10
10
  "bin": {
11
11
  "taleem-kernel": "./bin/cli.js"
12
12
  },
13
13
  "scripts": {
14
- "test": "vitest run"
14
+ "test": "vitest run --no-file-parallelism"
15
15
  },
16
16
  "files": [
17
17
  "src",
package/prisma/dev.db CHANGED
Binary file
@@ -0,0 +1,24 @@
1
+ -- RedefineTables
2
+ PRAGMA defer_foreign_keys=ON;
3
+ PRAGMA foreign_keys=OFF;
4
+ CREATE TABLE "new_Library" (
5
+ "slug" TEXT NOT NULL PRIMARY KEY,
6
+ "title" TEXT NOT NULL,
7
+ "description" TEXT,
8
+ "thumbnail" TEXT,
9
+ "type" TEXT NOT NULL,
10
+ "status" TEXT NOT NULL DEFAULT 'DRAFT',
11
+ "body" TEXT,
12
+ "courseSlug" TEXT NOT NULL,
13
+ "groupSlug" TEXT NOT NULL,
14
+ "sortOrder" INTEGER NOT NULL DEFAULT 0,
15
+ "allowCommunication" BOOLEAN NOT NULL DEFAULT true,
16
+ "meta" TEXT,
17
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
18
+ "updatedAt" DATETIME NOT NULL
19
+ );
20
+ INSERT INTO "new_Library" ("allowCommunication", "body", "courseSlug", "createdAt", "description", "groupSlug", "meta", "slug", "sortOrder", "thumbnail", "title", "type", "updatedAt") SELECT "allowCommunication", "body", "courseSlug", "createdAt", "description", "groupSlug", "meta", "slug", "sortOrder", "thumbnail", "title", "type", "updatedAt" FROM "Library";
21
+ DROP TABLE "Library";
22
+ ALTER TABLE "new_Library" RENAME TO "Library";
23
+ PRAGMA foreign_keys=ON;
24
+ PRAGMA defer_foreign_keys=OFF;
@@ -0,0 +1,96 @@
1
+ /*
2
+ Warnings:
3
+
4
+ - You are about to drop the column `items` on the `Group` table. All the data in the column will be lost.
5
+
6
+ */
7
+ -- RedefineTables
8
+ PRAGMA defer_foreign_keys=ON;
9
+ PRAGMA foreign_keys=OFF;
10
+ CREATE TABLE "new_Communication" (
11
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
12
+ "userId" INTEGER NOT NULL,
13
+ "librarySlug" TEXT NOT NULL,
14
+ "type" TEXT NOT NULL,
15
+ "initiator" TEXT NOT NULL DEFAULT 'STUDENT',
16
+ "meta" TEXT,
17
+ "message" TEXT NOT NULL,
18
+ "authorResponse" TEXT,
19
+ "isPublic" BOOLEAN NOT NULL DEFAULT false,
20
+ "readAt" DATETIME,
21
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
22
+ "updatedAt" DATETIME NOT NULL,
23
+ CONSTRAINT "Communication_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
24
+ CONSTRAINT "Communication_librarySlug_fkey" FOREIGN KEY ("librarySlug") REFERENCES "Library" ("slug") ON DELETE RESTRICT ON UPDATE CASCADE
25
+ );
26
+ INSERT INTO "new_Communication" ("authorResponse", "createdAt", "id", "isPublic", "librarySlug", "message", "meta", "readAt", "type", "updatedAt", "userId") SELECT "authorResponse", "createdAt", "id", "isPublic", "librarySlug", "message", "meta", "readAt", "type", "updatedAt", "userId" FROM "Communication";
27
+ DROP TABLE "Communication";
28
+ ALTER TABLE "new_Communication" RENAME TO "Communication";
29
+ CREATE INDEX "Communication_userId_idx" ON "Communication"("userId");
30
+ CREATE INDEX "Communication_librarySlug_idx" ON "Communication"("librarySlug");
31
+ CREATE TABLE "new_Course" (
32
+ "slug" TEXT NOT NULL PRIMARY KEY,
33
+ "title" TEXT NOT NULL,
34
+ "description" TEXT,
35
+ "thumbnail" TEXT,
36
+ "access" TEXT NOT NULL DEFAULT 'OPEN',
37
+ "isActive" BOOLEAN NOT NULL DEFAULT true,
38
+ "price" INTEGER NOT NULL DEFAULT 0
39
+ );
40
+ INSERT INTO "new_Course" ("access", "description", "price", "slug", "thumbnail", "title") SELECT "access", "description", "price", "slug", "thumbnail", "title" FROM "Course";
41
+ DROP TABLE "Course";
42
+ ALTER TABLE "new_Course" RENAME TO "Course";
43
+ CREATE TABLE "new_Group" (
44
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
45
+ "courseSlug" TEXT NOT NULL,
46
+ "slug" TEXT NOT NULL,
47
+ "title" TEXT NOT NULL,
48
+ "thumbnail" TEXT,
49
+ "description" TEXT,
50
+ CONSTRAINT "Group_courseSlug_fkey" FOREIGN KEY ("courseSlug") REFERENCES "Course" ("slug") ON DELETE RESTRICT ON UPDATE CASCADE
51
+ );
52
+ INSERT INTO "new_Group" ("courseSlug", "id", "slug", "thumbnail", "title") SELECT "courseSlug", "id", "slug", "thumbnail", "title" FROM "Group";
53
+ DROP TABLE "Group";
54
+ ALTER TABLE "new_Group" RENAME TO "Group";
55
+ CREATE INDEX "Group_courseSlug_idx" ON "Group"("courseSlug");
56
+ CREATE UNIQUE INDEX "Group_courseSlug_slug_key" ON "Group"("courseSlug", "slug");
57
+ CREATE TABLE "new_Library" (
58
+ "slug" TEXT NOT NULL PRIMARY KEY,
59
+ "title" TEXT NOT NULL,
60
+ "description" TEXT,
61
+ "thumbnail" TEXT,
62
+ "type" TEXT NOT NULL,
63
+ "status" TEXT NOT NULL DEFAULT 'DRAFT',
64
+ "body" TEXT,
65
+ "courseSlug" TEXT NOT NULL,
66
+ "groupSlug" TEXT NOT NULL,
67
+ "sortOrder" INTEGER NOT NULL DEFAULT 0,
68
+ "allowCommunication" BOOLEAN NOT NULL DEFAULT true,
69
+ "meta" TEXT,
70
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
71
+ "updatedAt" DATETIME NOT NULL,
72
+ CONSTRAINT "Library_courseSlug_groupSlug_fkey" FOREIGN KEY ("courseSlug", "groupSlug") REFERENCES "Group" ("courseSlug", "slug") ON DELETE RESTRICT ON UPDATE CASCADE
73
+ );
74
+ INSERT INTO "new_Library" ("allowCommunication", "body", "courseSlug", "createdAt", "description", "groupSlug", "meta", "slug", "sortOrder", "status", "thumbnail", "title", "type", "updatedAt") SELECT "allowCommunication", "body", "courseSlug", "createdAt", "description", "groupSlug", "meta", "slug", "sortOrder", "status", "thumbnail", "title", "type", "updatedAt" FROM "Library";
75
+ DROP TABLE "Library";
76
+ ALTER TABLE "new_Library" RENAME TO "Library";
77
+ CREATE INDEX "Library_courseSlug_idx" ON "Library"("courseSlug");
78
+ CREATE INDEX "Library_groupSlug_idx" ON "Library"("groupSlug");
79
+ CREATE TABLE "new_Subscription" (
80
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
81
+ "userId" INTEGER NOT NULL,
82
+ "courseSlug" TEXT NOT NULL,
83
+ "startsAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
84
+ "endsAt" DATETIME,
85
+ "amount" INTEGER,
86
+ "cancelledAt" DATETIME,
87
+ CONSTRAINT "Subscription_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
88
+ CONSTRAINT "Subscription_courseSlug_fkey" FOREIGN KEY ("courseSlug") REFERENCES "Course" ("slug") ON DELETE RESTRICT ON UPDATE CASCADE
89
+ );
90
+ INSERT INTO "new_Subscription" ("amount", "cancelledAt", "courseSlug", "endsAt", "id", "startsAt", "userId") SELECT "amount", "cancelledAt", "courseSlug", "endsAt", "id", "startsAt", "userId" FROM "Subscription";
91
+ DROP TABLE "Subscription";
92
+ ALTER TABLE "new_Subscription" RENAME TO "Subscription";
93
+ CREATE INDEX "Subscription_userId_idx" ON "Subscription"("userId");
94
+ CREATE INDEX "Subscription_courseSlug_idx" ON "Subscription"("courseSlug");
95
+ PRAGMA foreign_keys=ON;
96
+ PRAGMA defer_foreign_keys=OFF;
@@ -6,6 +6,10 @@ datasource db {
6
6
  provider = "sqlite"
7
7
  url = env("DATABASE_URL")
8
8
  }
9
+ enum CommunicationInitiator {
10
+ STUDENT
11
+ TEACHER
12
+ }
9
13
 
10
14
  enum ContentType {
11
15
  ARTICLE
@@ -13,6 +17,12 @@ enum ContentType {
13
17
  MCQ
14
18
  }
15
19
 
20
+ enum LibraryStatus {
21
+ DRAFT
22
+ PUBLISHED
23
+ ARCHIVED
24
+ }
25
+
16
26
  enum CourseAccess {
17
27
  OPEN
18
28
  MEMBERS
@@ -24,37 +34,67 @@ enum AdminRole {
24
34
  SUPER_ADMIN
25
35
  }
26
36
 
37
+ model Course {
38
+ slug String @id
39
+ title String
40
+ description String?
41
+ thumbnail String?
42
+ access CourseAccess @default(OPEN)
43
+ isActive Boolean @default(true)
44
+ price Int @default(0)
45
+
46
+ groups Group[]
47
+ subscriptions Subscription[]
48
+ }
49
+
50
+
27
51
  model Group {
28
- id Int @id @default(autoincrement())
29
- courseSlug String
30
- slug String
31
- title String
32
- thumbnail String?
33
- items Json
52
+ id Int @id @default(autoincrement())
53
+ courseSlug String
54
+ slug String
55
+ title String
56
+ thumbnail String?
57
+ description String?
58
+ course Course @relation(fields: [courseSlug], references: [slug], onDelete: Restrict)
59
+ library Library[]
34
60
 
35
61
  @@unique([courseSlug, slug])
36
62
  @@index([courseSlug])
37
63
  }
38
64
 
39
- model Course {
40
- slug String @unique
41
- title String
42
- description String?
43
- thumbnail String?
44
- access CourseAccess @default(OPEN)
45
- price Int @default(0)
46
- }
65
+ model Library {
66
+ slug String @id
67
+ title String
68
+ description String?
69
+ thumbnail String?
70
+ type ContentType
71
+ status LibraryStatus @default(DRAFT)
72
+ body String?
73
+ courseSlug String
74
+ groupSlug String
75
+ sortOrder Int @default(0)
76
+ allowCommunication Boolean @default(true)
77
+ meta String?
78
+ createdAt DateTime @default(now())
79
+ updatedAt DateTime @updatedAt
80
+
81
+ group Group @relation(fields: [courseSlug, groupSlug], references: [courseSlug, slug], onDelete: Restrict)
47
82
 
83
+ communications Communication[]
84
+
85
+ @@index([courseSlug])
86
+ @@index([groupSlug])
87
+ }
48
88
  model User {
49
- id Int @id @default(autoincrement())
50
- email String @unique
51
- password String
52
- name String?
53
- role String @default("student")
54
- resource String?
55
- createdAt DateTime @default(now())
56
- subscriptions Subscription[]
57
- communications Communication[]
89
+ id Int @id @default(autoincrement())
90
+ email String @unique
91
+ password String
92
+ name String?
93
+ role String @default("student")
94
+ resource String?
95
+ createdAt DateTime @default(now())
96
+ subscriptions Subscription[]
97
+ communications Communication[]
58
98
  }
59
99
 
60
100
  model Admin {
@@ -68,21 +108,6 @@ model Admin {
68
108
  updatedAt DateTime @updatedAt
69
109
  }
70
110
 
71
- model Library {
72
- slug String @id
73
- title String
74
- description String?
75
- thumbnail String?
76
- type ContentType
77
- body String?
78
- courseSlug String
79
- groupSlug String
80
- sortOrder Int @default(0)
81
- allowCommunication Boolean @default(true)
82
- meta String?
83
- createdAt DateTime @default(now())
84
- updatedAt DateTime @updatedAt
85
- }
86
111
 
87
112
  model Subscription {
88
113
  id Int @id @default(autoincrement())
@@ -91,9 +116,11 @@ model Subscription {
91
116
  startsAt DateTime @default(now())
92
117
  endsAt DateTime?
93
118
  amount Int?
94
- user User @relation(fields: [userId], references: [id])
95
119
  cancelledAt DateTime?
96
120
 
121
+ user User @relation(fields: [userId], references: [id])
122
+ course Course @relation(fields: [courseSlug], references: [slug], onDelete: Restrict)
123
+
97
124
  @@index([userId])
98
125
  @@index([courseSlug])
99
126
  }
@@ -103,6 +130,7 @@ model Communication {
103
130
  userId Int
104
131
  librarySlug String
105
132
  type String
133
+ initiator CommunicationInitiator @default(STUDENT)
106
134
  meta String?
107
135
  message String
108
136
  authorResponse String?
@@ -110,50 +138,47 @@ model Communication {
110
138
  readAt DateTime?
111
139
  createdAt DateTime @default(now())
112
140
  updatedAt DateTime @updatedAt
113
- user User @relation(fields: [userId], references: [id])
141
+ user User @relation(fields: [userId], references: [id])
142
+ library Library @relation(fields: [librarySlug], references: [slug], onDelete: Restrict)
114
143
 
115
144
  @@index([userId])
116
145
  @@index([librarySlug])
117
146
  }
118
- model Svg {
119
147
 
120
- slug String @id
148
+ model Svg {
149
+ slug String @id
121
150
 
122
- title String
151
+ title String
123
152
 
124
- body String
153
+ body String
125
154
 
126
- tags String @default("[]")
155
+ tags String @default("[]")
127
156
 
128
157
  createdAt DateTime @default(now())
129
158
 
130
159
  updatedAt DateTime @updatedAt
131
-
132
160
  }
133
161
 
134
162
  model Image {
163
+ slug String @id
135
164
 
136
- slug String @id
137
-
138
- title String
165
+ title String
139
166
 
140
- tags String @default("[]")
167
+ tags String @default("[]")
141
168
 
142
169
  createdAt DateTime @default(now())
143
170
 
144
171
  updatedAt DateTime @updatedAt
145
-
146
172
  }
147
- model Audio {
148
173
 
149
- slug String @id
174
+ model Audio {
175
+ slug String @id
150
176
 
151
- title String
177
+ title String
152
178
 
153
- tags String @default("[]")
179
+ tags String @default("[]")
154
180
 
155
181
  createdAt DateTime @default(now())
156
182
 
157
183
  updatedAt DateTime @updatedAt
158
-
159
- }
184
+ }