@headless-lms/adapter-db 0.2.0 → 0.4.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 +12 -6
- package/dist/index.js +12 -6
- package/dist/repositories/admin.d.ts +23 -0
- package/dist/repositories/admin.js +393 -0
- package/dist/repositories/admin.js.map +1 -0
- package/dist/repositories/assets.d.ts +6 -3
- package/dist/repositories/assets.js +46 -9
- package/dist/repositories/assets.js.map +1 -1
- package/dist/repositories/automations.d.ts +5 -2
- package/dist/repositories/automations.js +29 -2
- package/dist/repositories/automations.js.map +1 -1
- package/dist/repositories/chats.d.ts +55 -0
- package/dist/repositories/chats.js +469 -0
- package/dist/repositories/chats.js.map +1 -0
- package/dist/repositories/content.d.ts +24 -1
- package/dist/repositories/content.js +316 -9
- package/dist/repositories/content.js.map +1 -1
- package/dist/repositories/devices.d.ts +17 -0
- package/dist/repositories/devices.js +75 -0
- package/dist/repositories/devices.js.map +1 -0
- package/dist/repositories/digest-runs.d.ts +14 -0
- package/dist/repositories/digest-runs.js +39 -0
- package/dist/repositories/digest-runs.js.map +1 -0
- package/dist/repositories/discussion.d.ts +16 -4
- package/dist/repositories/discussion.js +78 -18
- package/dist/repositories/discussion.js.map +1 -1
- package/dist/repositories/entitlements.d.ts +31 -9
- package/dist/repositories/entitlements.js +213 -17
- package/dist/repositories/entitlements.js.map +1 -1
- package/dist/repositories/grant-covers.d.ts +20 -0
- package/dist/repositories/grant-covers.js +55 -0
- package/dist/repositories/grant-covers.js.map +1 -0
- package/dist/repositories/identity.d.ts +4 -2
- package/dist/repositories/identity.js +32 -1
- package/dist/repositories/identity.js.map +1 -1
- package/dist/repositories/inserted-row.d.ts +5 -0
- package/dist/repositories/inserted-row.js +7 -0
- package/dist/repositories/inserted-row.js.map +1 -0
- package/dist/repositories/member.d.ts +16 -0
- package/dist/repositories/member.js +63 -0
- package/dist/repositories/member.js.map +1 -0
- package/dist/repositories/members.js +2 -2
- package/dist/repositories/members.js.map +1 -1
- package/dist/repositories/mentions.d.ts +17 -0
- package/dist/repositories/mentions.js +55 -0
- package/dist/repositories/mentions.js.map +1 -0
- package/dist/repositories/notification-settings.d.ts +19 -0
- package/dist/repositories/notification-settings.js +67 -0
- package/dist/repositories/notification-settings.js.map +1 -0
- package/dist/repositories/notifications.d.ts +30 -0
- package/dist/repositories/notifications.js +178 -0
- package/dist/repositories/notifications.js.map +1 -0
- package/dist/repositories/org-user-profile.d.ts +214 -1
- package/dist/repositories/org-user-profile.js +23 -2
- package/dist/repositories/org-user-profile.js.map +1 -1
- package/dist/repositories/organizations.d.ts +4 -2
- package/dist/repositories/organizations.js +23 -8
- package/dist/repositories/organizations.js.map +1 -1
- package/dist/repositories/pg-errors.js +3 -1
- package/dist/repositories/pg-errors.js.map +1 -1
- package/dist/repositories/posts.d.ts +35 -0
- package/dist/repositories/posts.js +252 -0
- package/dist/repositories/posts.js.map +1 -0
- package/dist/repositories/subscriptions.d.ts +18 -0
- package/dist/repositories/subscriptions.js +72 -0
- package/dist/repositories/subscriptions.js.map +1 -0
- package/dist/schema/assets.d.ts +19 -2
- package/dist/schema/assets.js +10 -4
- package/dist/schema/assets.js.map +1 -1
- package/dist/schema/automations.d.ts +545 -2
- package/dist/schema/automations.js +73 -3
- package/dist/schema/automations.js.map +1 -1
- package/dist/schema/better-auth.d.ts +1613 -238
- package/dist/schema/better-auth.js +107 -22
- package/dist/schema/better-auth.js.map +1 -1
- package/dist/schema/content.d.ts +642 -5
- package/dist/schema/content.js +119 -10
- package/dist/schema/content.js.map +1 -1
- package/dist/schema/discussion.d.ts +2182 -42
- package/dist/schema/discussion.js +461 -11
- package/dist/schema/discussion.js.map +1 -1
- package/dist/schema/entitlements.d.ts +432 -1
- package/dist/schema/entitlements.js +109 -4
- package/dist/schema/entitlements.js.map +1 -1
- package/dist/schema/identity.d.ts +517 -1
- package/dist/schema/identity.js +76 -2
- package/dist/schema/identity.js.map +1 -1
- package/dist/schema/index.d.ts +7 -7
- package/dist/schema/index.js +35 -8
- package/dist/schema/organizations.d.ts +4 -4
- package/dist/schema/organizations.js +2 -0
- package/dist/schema/organizations.js.map +1 -1
- package/drizzle/0003_community.sql +340 -0
- package/drizzle/0004_assets_sources.sql +1 -0
- package/drizzle/0005_notices_and_seed_index.sql +12 -0
- package/drizzle/0006_community_review_fixes.sql +24 -0
- package/drizzle/0007_notifications.sql +37 -0
- package/drizzle/0008_content_access.sql +13 -0
- package/drizzle/0009_community_indexes.sql +56 -0
- package/drizzle/0010_mcp_access.sql +114 -0
- package/drizzle/0011_digest_runs.sql +8 -0
- package/drizzle/0012_subscriptions.sql +16 -0
- package/drizzle/0013_mentions.sql +10 -0
- package/drizzle/0014_notification_settings_devices.sql +36 -0
- package/drizzle/0015_automations_drop_source.sql +2 -0
- package/drizzle/0016_notifications_automations.sql +48 -0
- package/drizzle/meta/0003_snapshot.json +7061 -0
- package/drizzle/meta/0004_snapshot.json +7068 -0
- package/drizzle/meta/0005_snapshot.json +7180 -0
- package/drizzle/meta/0006_snapshot.json +7298 -0
- package/drizzle/meta/0007_snapshot.json +7620 -0
- package/drizzle/meta/0008_snapshot.json +7666 -0
- package/drizzle/meta/0009_snapshot.json +8185 -0
- package/drizzle/meta/0010_snapshot.json +8813 -0
- package/drizzle/meta/0011_snapshot.json +8868 -0
- package/drizzle/meta/0012_snapshot.json +8873 -0
- package/drizzle/meta/0013_snapshot.json +8943 -0
- package/drizzle/meta/0014_snapshot.json +9305 -0
- package/drizzle/meta/0015_snapshot.json +9270 -0
- package/drizzle/meta/0016_snapshot.json +9230 -0
- package/drizzle/meta/_journal.json +99 -1
- package/package.json +2 -2
- package/dist/repositories/course-analytics.d.ts +0 -15
- package/dist/repositories/course-analytics.js +0 -137
- package/dist/repositories/course-analytics.js.map +0 -1
- package/dist/repositories/dashboard.d.ts +0 -14
- package/dist/repositories/dashboard.js +0 -57
- package/dist/repositories/dashboard.js.map +0 -1
- package/dist/repositories/learn.d.ts +0 -19
- package/dist/repositories/learn.js +0 -56
- package/dist/repositories/learn.js.map +0 -1
- package/dist/repositories/students.d.ts +0 -16
- package/dist/repositories/students.js +0 -160
- package/dist/repositories/students.js.map +0 -1
package/dist/schema/content.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { organizations } from "./organizations.js";
|
|
2
1
|
import { assets } from "./assets.js";
|
|
2
|
+
import { organizations } from "./organizations.js";
|
|
3
3
|
import { sql } from "drizzle-orm";
|
|
4
|
-
import { check, foreignKey, integer, jsonb, pgTable, primaryKey, text, timestamp, unique } from "drizzle-orm/pg-core";
|
|
4
|
+
import { check, foreignKey, index, integer, jsonb, pgTable, primaryKey, text, timestamp, unique } from "drizzle-orm/pg-core";
|
|
5
5
|
import { genId } from "@headless-lms/core/shared/id";
|
|
6
6
|
//#region src/schema/content.ts
|
|
7
7
|
const bundles = pgTable("bundles", {
|
|
@@ -17,13 +17,17 @@ const bundles = pgTable("bundles", {
|
|
|
17
17
|
const contentItems = pgTable("content_items", {
|
|
18
18
|
orgId: text("org_id").notNull().references(() => organizations.id),
|
|
19
19
|
id: text("id").notNull(),
|
|
20
|
-
type: text("type", { enum: [
|
|
20
|
+
type: text("type", { enum: [
|
|
21
|
+
"course",
|
|
22
|
+
"download",
|
|
23
|
+
"community"
|
|
24
|
+
] }).notNull(),
|
|
21
25
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
22
26
|
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow().$onUpdate(() => /* @__PURE__ */ new Date())
|
|
23
27
|
}, (t) => ({
|
|
24
28
|
pk: primaryKey({ columns: [t.orgId, t.id] }),
|
|
25
29
|
typeUq: unique().on(t.orgId, t.id, t.type),
|
|
26
|
-
typeCk: check("content_items_type_check", sql`${t.type} in ('course', 'download')`)
|
|
30
|
+
typeCk: check("content_items_type_check", sql`${t.type} in ('course', 'download', 'community')`)
|
|
27
31
|
}));
|
|
28
32
|
const bundleItems = pgTable("bundle_items", {
|
|
29
33
|
orgId: text("org_id").notNull().references(() => organizations.id),
|
|
@@ -44,7 +48,8 @@ const bundleItems = pgTable("bundle_items", {
|
|
|
44
48
|
bundleFk: foreignKey({
|
|
45
49
|
columns: [t.orgId, t.bundleId],
|
|
46
50
|
foreignColumns: [bundles.orgId, bundles.id]
|
|
47
|
-
}).onDelete("cascade")
|
|
51
|
+
}).onDelete("cascade"),
|
|
52
|
+
contentIdx: index("bundle_items_content_idx").on(t.orgId, t.contentId)
|
|
48
53
|
}));
|
|
49
54
|
const courses = pgTable("courses", {
|
|
50
55
|
orgId: text("org_id").notNull().references(() => organizations.id),
|
|
@@ -76,7 +81,8 @@ const courses = pgTable("courses", {
|
|
|
76
81
|
thumbnailAssetFk: foreignKey({
|
|
77
82
|
columns: [t.orgId, t.thumbnailAssetId],
|
|
78
83
|
foreignColumns: [assets.orgId, assets.id]
|
|
79
|
-
})
|
|
84
|
+
}),
|
|
85
|
+
thumbnailIdx: index("courses_thumbnail_idx").on(t.orgId, t.thumbnailAssetId)
|
|
80
86
|
}));
|
|
81
87
|
const modules = pgTable("modules", {
|
|
82
88
|
orgId: text("org_id").notNull().references(() => organizations.id),
|
|
@@ -137,7 +143,8 @@ const activityAssets = pgTable("activity_assets", {
|
|
|
137
143
|
columns: [t.orgId, t.assetId],
|
|
138
144
|
foreignColumns: [assets.orgId, assets.id]
|
|
139
145
|
}),
|
|
140
|
-
activityAssetUq: unique().on(t.orgId, t.activityId, t.assetId)
|
|
146
|
+
activityAssetUq: unique().on(t.orgId, t.activityId, t.assetId),
|
|
147
|
+
assetIdx: index("activity_assets_asset_idx").on(t.orgId, t.assetId)
|
|
141
148
|
}));
|
|
142
149
|
const downloads = pgTable("downloads", {
|
|
143
150
|
orgId: text("org_id").notNull().references(() => organizations.id),
|
|
@@ -169,7 +176,8 @@ const downloads = pgTable("downloads", {
|
|
|
169
176
|
thumbnailFk: foreignKey({
|
|
170
177
|
columns: [t.orgId, t.thumbnailAssetId],
|
|
171
178
|
foreignColumns: [assets.orgId, assets.id]
|
|
172
|
-
})
|
|
179
|
+
}),
|
|
180
|
+
thumbnailIdx: index("downloads_thumbnail_idx").on(t.orgId, t.thumbnailAssetId)
|
|
173
181
|
}));
|
|
174
182
|
const downloadAssets = pgTable("download_assets", {
|
|
175
183
|
orgId: text("org_id").notNull().references(() => organizations.id),
|
|
@@ -190,9 +198,110 @@ const downloadAssets = pgTable("download_assets", {
|
|
|
190
198
|
columns: [t.orgId, t.assetId],
|
|
191
199
|
foreignColumns: [assets.orgId, assets.id]
|
|
192
200
|
}),
|
|
193
|
-
downloadAssetUq: unique().on(t.orgId, t.downloadId, t.assetId)
|
|
201
|
+
downloadAssetUq: unique().on(t.orgId, t.downloadId, t.assetId),
|
|
202
|
+
assetIdx: index("download_assets_asset_idx").on(t.orgId, t.assetId)
|
|
203
|
+
}));
|
|
204
|
+
const communities = pgTable("communities", {
|
|
205
|
+
orgId: text("org_id").notNull().references(() => organizations.id),
|
|
206
|
+
id: text("id").notNull().$defaultFn(() => genId("community")),
|
|
207
|
+
type: text("type").$type().notNull().generatedAlwaysAs(sql`'community'`),
|
|
208
|
+
title: text("title").notNull(),
|
|
209
|
+
slug: text("slug").notNull(),
|
|
210
|
+
description: text("description").notNull().default(""),
|
|
211
|
+
status: text("status", { enum: ["draft", "published"] }).notNull().default("draft"),
|
|
212
|
+
thumbnailAssetId: text("thumbnail_asset_id"),
|
|
213
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
214
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow().$onUpdate(() => /* @__PURE__ */ new Date())
|
|
215
|
+
}, (t) => ({
|
|
216
|
+
pk: primaryKey({ columns: [t.orgId, t.id] }),
|
|
217
|
+
slugUq: unique().on(t.orgId, t.slug),
|
|
218
|
+
contentItemFk: foreignKey({
|
|
219
|
+
columns: [
|
|
220
|
+
t.orgId,
|
|
221
|
+
t.id,
|
|
222
|
+
t.type
|
|
223
|
+
],
|
|
224
|
+
foreignColumns: [
|
|
225
|
+
contentItems.orgId,
|
|
226
|
+
contentItems.id,
|
|
227
|
+
contentItems.type
|
|
228
|
+
]
|
|
229
|
+
}).onDelete("cascade"),
|
|
230
|
+
thumbnailAssetFk: foreignKey({
|
|
231
|
+
columns: [t.orgId, t.thumbnailAssetId],
|
|
232
|
+
foreignColumns: [assets.orgId, assets.id]
|
|
233
|
+
}),
|
|
234
|
+
thumbnailIdx: index("communities_thumbnail_idx").on(t.orgId, t.thumbnailAssetId)
|
|
235
|
+
}));
|
|
236
|
+
const spaces = pgTable("spaces", {
|
|
237
|
+
orgId: text("org_id").notNull().references(() => organizations.id),
|
|
238
|
+
id: text("id").notNull().$defaultFn(() => genId("space")),
|
|
239
|
+
communityId: text("community_id").notNull(),
|
|
240
|
+
name: text("name").notNull(),
|
|
241
|
+
description: text("description").notNull().default(""),
|
|
242
|
+
seq: integer("seq").notNull(),
|
|
243
|
+
accessRule: text("access_rule", { enum: [
|
|
244
|
+
"all_members",
|
|
245
|
+
"by_request",
|
|
246
|
+
"by_invite"
|
|
247
|
+
] }).notNull().default("all_members"),
|
|
248
|
+
capacity: integer("capacity"),
|
|
249
|
+
settings: jsonb("settings").$type().notNull().default({
|
|
250
|
+
comments: true,
|
|
251
|
+
reactions: true,
|
|
252
|
+
requireReview: false
|
|
253
|
+
}),
|
|
254
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
255
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow().$onUpdate(() => /* @__PURE__ */ new Date())
|
|
256
|
+
}, (t) => ({
|
|
257
|
+
pk: primaryKey({ columns: [t.orgId, t.id] }),
|
|
258
|
+
communityUq: unique().on(t.orgId, t.id, t.communityId),
|
|
259
|
+
communityFk: foreignKey({
|
|
260
|
+
columns: [t.orgId, t.communityId],
|
|
261
|
+
foreignColumns: [communities.orgId, communities.id]
|
|
262
|
+
}).onDelete("cascade"),
|
|
263
|
+
capacityCk: check("spaces_capacity_check", sql`${t.capacity} is null or ${t.accessRule} <> 'all_members'`),
|
|
264
|
+
orderIdx: index("spaces_order_idx").on(t.orgId, t.communityId, t.seq)
|
|
265
|
+
}));
|
|
266
|
+
const spaceTopics = pgTable("space_topics", {
|
|
267
|
+
orgId: text("org_id").notNull().references(() => organizations.id),
|
|
268
|
+
id: text("id").notNull().$defaultFn(() => genId("topic")),
|
|
269
|
+
spaceId: text("space_id").notNull(),
|
|
270
|
+
name: text("name").notNull(),
|
|
271
|
+
seq: integer("seq").notNull(),
|
|
272
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
273
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow().$onUpdate(() => /* @__PURE__ */ new Date())
|
|
274
|
+
}, (t) => ({
|
|
275
|
+
pk: primaryKey({ columns: [t.orgId, t.id] }),
|
|
276
|
+
nameUq: unique().on(t.orgId, t.spaceId, t.name),
|
|
277
|
+
spaceUq: unique().on(t.orgId, t.spaceId, t.id),
|
|
278
|
+
spaceFk: foreignKey({
|
|
279
|
+
columns: [t.orgId, t.spaceId],
|
|
280
|
+
foreignColumns: [spaces.orgId, spaces.id]
|
|
281
|
+
}).onDelete("cascade")
|
|
282
|
+
}));
|
|
283
|
+
const spaceLinks = pgTable("space_links", {
|
|
284
|
+
orgId: text("org_id").notNull().references(() => organizations.id),
|
|
285
|
+
id: text("id").notNull().$defaultFn(() => genId("spaceLink")),
|
|
286
|
+
spaceId: text("space_id").notNull(),
|
|
287
|
+
contentId: text("content_id").notNull(),
|
|
288
|
+
seq: integer("seq").notNull().default(0),
|
|
289
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
290
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow().$onUpdate(() => /* @__PURE__ */ new Date())
|
|
291
|
+
}, (t) => ({
|
|
292
|
+
pk: primaryKey({ columns: [t.orgId, t.id] }),
|
|
293
|
+
contentUq: unique().on(t.orgId, t.spaceId, t.contentId),
|
|
294
|
+
spaceFk: foreignKey({
|
|
295
|
+
columns: [t.orgId, t.spaceId],
|
|
296
|
+
foreignColumns: [spaces.orgId, spaces.id]
|
|
297
|
+
}).onDelete("cascade"),
|
|
298
|
+
contentFk: foreignKey({
|
|
299
|
+
columns: [t.orgId, t.contentId],
|
|
300
|
+
foreignColumns: [contentItems.orgId, contentItems.id]
|
|
301
|
+
}).onDelete("cascade"),
|
|
302
|
+
contentIdx: index("space_links_content_idx").on(t.orgId, t.contentId)
|
|
194
303
|
}));
|
|
195
304
|
//#endregion
|
|
196
|
-
export { activities, activityAssets, bundleItems, bundles, contentItems, courses, downloadAssets, downloads, modules };
|
|
305
|
+
export { activities, activityAssets, bundleItems, bundles, communities, contentItems, courses, downloadAssets, downloads, modules, spaceLinks, spaceTopics, spaces };
|
|
197
306
|
|
|
198
307
|
//# sourceMappingURL=content.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content.js","names":[],"sources":["../../src/schema/content.ts"],"sourcesContent":["import {\n pgTable,\n text,\n integer,\n jsonb,\n timestamp,\n primaryKey,\n foreignKey,\n unique,\n check,\n} from \"drizzle-orm/pg-core\";\nimport { sql } from \"drizzle-orm\";\nimport type {\n Activity,\n ActivityAsset,\n Bundle,\n BundleItem,\n ContentItem,\n Course,\n Download,\n DownloadAsset,\n Module,\n} from \"@headless-lms/core/schemas\";\nimport { genId } from \"@headless-lms/core/shared/id\";\nimport { organizations } from \"./organizations.js\";\nimport { assets } from \"./assets.js\";\nimport type { Expect, NoDrift } from \"./drift.js\";\n\n// Bundles.\nexport const bundles = pgTable(\n \"bundles\",\n {\n orgId: text(\"org_id\")\n .notNull()\n .references(() => organizations.id),\n id: text(\"id\").notNull(),\n name: text(\"name\").notNull(),\n createdAt: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n updatedAt: timestamp(\"updated_at\", { withTimezone: true })\n .notNull()\n .defaultNow()\n .$onUpdate(() => new Date()),\n },\n (t) => ({\n pk: primaryKey({ columns: [t.orgId, t.id] }),\n typeUq: unique().on(t.orgId, t.id, t.name),\n }),\n);\n\n// The content registry one row per piece of content, any\n// type. this is so we can PK to content items of different types.\nexport const contentItems = pgTable(\n \"content_items\",\n {\n orgId: text(\"org_id\")\n .notNull()\n .references(() => organizations.id),\n id: text(\"id\").notNull(),\n type: text(\"type\", { enum: [\"course\", \"download\"] }).notNull(),\n createdAt: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n updatedAt: timestamp(\"updated_at\", { withTimezone: true })\n .notNull()\n .defaultNow()\n .$onUpdate(() => new Date()),\n },\n (t) => ({\n pk: primaryKey({ columns: [t.orgId, t.id] }),\n // FK target for type-pinned references from concrete content tables.\n typeUq: unique().on(t.orgId, t.id, t.type),\n // Widened per new content type.\n typeCk: check(\"content_items_type_check\", sql`${t.type} in ('course', 'download')`),\n }),\n);\n\n// The content registry one row per piece of content, any\n// type. this is so we can PK to content items of different types.\nexport const bundleItems = pgTable(\n \"bundle_items\",\n {\n orgId: text(\"org_id\")\n .notNull()\n .references(() => organizations.id),\n bundleId: text(\"bundle_id\").notNull(),\n contentId: text(\"content_id\").notNull(),\n\n createdAt: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n updatedAt: timestamp(\"updated_at\", { withTimezone: true })\n .notNull()\n .defaultNow()\n .$onUpdate(() => new Date()),\n },\n (t) => ({\n pk: primaryKey({ columns: [t.orgId, t.bundleId, t.contentId] }),\n contentItemFk: foreignKey({\n columns: [t.orgId, t.contentId],\n foreignColumns: [contentItems.orgId, contentItems.id],\n }).onDelete(\"cascade\"),\n bundleFk: foreignKey({\n columns: [t.orgId, t.bundleId],\n foreignColumns: [bundles.orgId, bundles.id],\n }).onDelete(\"cascade\"),\n }),\n);\n\nexport const courses = pgTable(\n \"courses\",\n {\n orgId: text(\"org_id\")\n .notNull()\n .references(() => organizations.id),\n id: text(\"id\")\n .notNull()\n .$defaultFn(() => genId(\"course\")),\n // Pinned to 'course' so the composite FK below cannot attach this row to a\n // registry row of another content type.\n type: text(\"type\")\n .$type<Course[\"type\"]>()\n .notNull()\n .generatedAlwaysAs(sql`'course'`),\n title: text(\"title\").notNull(),\n slug: text(\"slug\").notNull(),\n description: text(\"description\").notNull().default(\"\"),\n status: text(\"status\", { enum: [\"draft\", \"published\"] })\n .notNull()\n .default(\"draft\"),\n category: text(\"category\").notNull().default(\"\"),\n // Media-library asset rendered as the course's cover. Null = no cover.\n thumbnailAssetId: text(\"thumbnail_asset_id\"),\n createdAt: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n updatedAt: timestamp(\"updated_at\", { withTimezone: true })\n .notNull()\n .defaultNow()\n .$onUpdate(() => new Date()),\n },\n (t) => ({\n pk: primaryKey({ columns: [t.orgId, t.id] }),\n slugUq: unique().on(t.orgId, t.slug),\n contentItemFk: foreignKey({\n columns: [t.orgId, t.id, t.type],\n foreignColumns: [contentItems.orgId, contentItems.id, contentItems.type],\n }).onDelete(\"cascade\"),\n // Restrictive, like `activity_assets.assetFk` — the asset is owned by the\n // assets domain and must be unlinked before it can be deleted. MATCH SIMPLE\n // means the constraint is skipped entirely while the thumbnail is null.\n thumbnailAssetFk: foreignKey({\n columns: [t.orgId, t.thumbnailAssetId],\n foreignColumns: [assets.orgId, assets.id],\n }),\n }),\n);\n\nexport const modules = pgTable(\n \"modules\",\n {\n orgId: text(\"org_id\")\n .notNull()\n .references(() => organizations.id),\n id: text(\"id\")\n .notNull()\n .$defaultFn(() => genId(\"module\")),\n courseId: text(\"course_id\").notNull(),\n title: text(\"title\").notNull(),\n seq: integer(\"seq\").notNull(),\n createdAt: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n updatedAt: timestamp(\"updated_at\", { withTimezone: true })\n .notNull()\n .defaultNow()\n .$onUpdate(() => new Date()),\n },\n (t) => ({\n pk: primaryKey({ columns: [t.orgId, t.id] }),\n // Modules are part of the course aggregate: deleting the course deletes them.\n courseFk: foreignKey({\n columns: [t.orgId, t.courseId],\n foreignColumns: [courses.orgId, courses.id],\n }).onDelete(\"cascade\"),\n // FK target for the course-pinned reference from activities.\n courseUq: unique().on(t.orgId, t.id, t.courseId),\n }),\n);\n\n// The leaf, directly in a module. Uniform content: seq + opaque settings blob.\nexport const activities = pgTable(\n \"activities\",\n {\n orgId: text(\"org_id\")\n .notNull()\n .references(() => organizations.id),\n id: text(\"id\")\n .notNull()\n .$defaultFn(() => genId(\"activity\")),\n moduleId: text(\"module_id\").notNull(),\n // Denormalised from the module: the course an activity belongs to is asked\n // for far more often than its module (progress, discussion, entitlements),\n // and the FK below pins the pair, so it cannot disagree with the module.\n courseId: text(\"course_id\").notNull(),\n seq: integer(\"seq\").notNull(),\n // Opaque per-activity blob: title, type, body, completion rule — whatever the\n // content needs. Assets are the one thing kept out of the blob.\n settings: jsonb(\"settings\").$type<Activity[\"settings\"]>(),\n createdAt: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n updatedAt: timestamp(\"updated_at\", { withTimezone: true })\n .notNull()\n .defaultNow()\n .$onUpdate(() => new Date()),\n },\n (t) => ({\n pk: primaryKey({ columns: [t.orgId, t.id] }),\n // Course-pinned, like `courses.contentItemFk`: the module reference carries\n // `course_id`, so an activity whose stored course disagrees with its\n // module's is rejected by the database rather than silently rotting.\n moduleFk: foreignKey({\n columns: [t.orgId, t.moduleId, t.courseId],\n foreignColumns: [modules.orgId, modules.id, modules.courseId],\n }).onDelete(\"cascade\"),\n seqUq: unique().on(t.orgId, t.moduleId, t.seq),\n }),\n);\n\n// activity ↔ asset: many-to-many (an activity uses many assets; an asset can be\n// reused by many activities). Assets owned by the assets domain, tracked here.\nexport const activityAssets = pgTable(\n \"activity_assets\",\n {\n orgId: text(\"org_id\")\n .notNull()\n .references(() => organizations.id),\n id: text(\"id\")\n .notNull()\n .$defaultFn(() => genId(\"activityAsset\")),\n activityId: text(\"activity_id\").notNull(),\n assetId: text(\"asset_id\").notNull(),\n seq: integer(\"seq\").notNull().default(0),\n createdAt: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n updatedAt: timestamp(\"updated_at\", { withTimezone: true })\n .notNull()\n .defaultNow()\n .$onUpdate(() => new Date()),\n },\n (t) => ({\n pk: primaryKey({ columns: [t.orgId, t.id] }),\n // The link cascades with its activity; the asset itself is owned by the\n // assets domain and survives (assetFk stays restrictive).\n activityFk: foreignKey({\n columns: [t.orgId, t.activityId],\n foreignColumns: [activities.orgId, activities.id],\n }).onDelete(\"cascade\"),\n assetFk: foreignKey({\n columns: [t.orgId, t.assetId],\n foreignColumns: [assets.orgId, assets.id],\n }),\n activityAssetUq: unique().on(t.orgId, t.activityId, t.assetId),\n }),\n);\n\n// A download: an ordered set of media-library assets. Shares its PK with a\n// registry row (same id) via the type-pinned composite FK, exactly like courses.\nexport const downloads = pgTable(\n \"downloads\",\n {\n orgId: text(\"org_id\")\n .notNull()\n .references(() => organizations.id),\n id: text(\"id\")\n .notNull()\n .$defaultFn(() => genId(\"download\")),\n // Pinned to 'download' so the composite FK below cannot attach this row to\n // a registry row of another content type.\n type: text(\"type\")\n .$type<Download[\"type\"]>()\n .notNull()\n .generatedAlwaysAs(sql`'download'`),\n title: text(\"title\").notNull(),\n slug: text(\"slug\").notNull(),\n description: text(\"description\").notNull().default(\"\"),\n status: text(\"status\", { enum: [\"draft\", \"published\"] })\n .notNull()\n .default(\"draft\"),\n category: text(\"category\").notNull().default(\"\"),\n thumbnailAssetId: text(\"thumbnail_asset_id\"),\n createdAt: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n updatedAt: timestamp(\"updated_at\", { withTimezone: true })\n .notNull()\n .defaultNow()\n .$onUpdate(() => new Date()),\n },\n (t) => ({\n pk: primaryKey({ columns: [t.orgId, t.id] }),\n slugUq: unique().on(t.orgId, t.slug),\n contentItemFk: foreignKey({\n columns: [t.orgId, t.id, t.type],\n foreignColumns: [contentItems.orgId, contentItems.id, contentItems.type],\n }).onDelete(\"cascade\"),\n // Restrictive: a thumbnail in use blocks deleting the asset.\n thumbnailFk: foreignKey({\n columns: [t.orgId, t.thumbnailAssetId],\n foreignColumns: [assets.orgId, assets.id],\n }),\n }),\n);\n\n// download ↔ asset: the ordered set. Mirrors activity_assets one level\n// shallower — a download has no intermediate structure.\nexport const downloadAssets = pgTable(\n \"download_assets\",\n {\n orgId: text(\"org_id\")\n .notNull()\n .references(() => organizations.id),\n id: text(\"id\")\n .notNull()\n .$defaultFn(() => genId(\"downloadAsset\")),\n downloadId: text(\"download_id\").notNull(),\n assetId: text(\"asset_id\").notNull(),\n seq: integer(\"seq\").notNull().default(0),\n // Author's label; null falls back to the asset's filename.\n displayName: text(\"display_name\"),\n createdAt: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n updatedAt: timestamp(\"updated_at\", { withTimezone: true })\n .notNull()\n .defaultNow()\n .$onUpdate(() => new Date()),\n },\n (t) => ({\n pk: primaryKey({ columns: [t.orgId, t.id] }),\n // The link cascades with its download; the asset is owned by the assets\n // domain and survives (assetFk stays restrictive).\n downloadFk: foreignKey({\n columns: [t.orgId, t.downloadId],\n foreignColumns: [downloads.orgId, downloads.id],\n }).onDelete(\"cascade\"),\n assetFk: foreignKey({\n columns: [t.orgId, t.assetId],\n foreignColumns: [assets.orgId, assets.id],\n }),\n // Lets delivery key on asset_id rather than the link row id.\n downloadAssetUq: unique().on(t.orgId, t.downloadId, t.assetId),\n }),\n);\n\ntype _BundlesDrift = Expect<NoDrift<typeof bundles.$inferSelect, Bundle>>;\ntype _BundleItemsDrift = Expect<NoDrift<typeof bundleItems.$inferSelect, BundleItem>>;\ntype _ContentItemsDrift = Expect<NoDrift<typeof contentItems.$inferSelect, ContentItem>>;\ntype _CoursesDrift = Expect<NoDrift<typeof courses.$inferSelect, Omit<Course, \"settings\">>>;\ntype _ModulesDrift = Expect<NoDrift<typeof modules.$inferSelect, Module>>;\ntype _ActivitiesDrift = Expect<NoDrift<typeof activities.$inferSelect, Activity>>;\ntype _ActivityAssetsDrift = Expect<NoDrift<typeof activityAssets.$inferSelect, ActivityAsset>>;\ntype _DownloadsDrift = Expect<NoDrift<typeof downloads.$inferSelect, Download>>;\ntype _DownloadAssetsDrift = Expect<NoDrift<typeof downloadAssets.$inferSelect, DownloadAsset>>;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"content.js","names":[],"sources":["../../src/schema/content.ts"],"sourcesContent":["import {\n pgTable,\n text,\n integer,\n jsonb,\n timestamp,\n primaryKey,\n foreignKey,\n unique,\n index,\n check,\n} from \"drizzle-orm/pg-core\";\nimport { sql } from \"drizzle-orm\";\nimport type {\n Activity,\n ActivityAsset,\n Bundle,\n BundleItem,\n Community,\n ContentItem,\n Course,\n Download,\n DownloadAsset,\n Module,\n Space,\n SpaceLink,\n SpaceTopic,\n} from \"@headless-lms/core/schemas\";\nimport { genId } from \"@headless-lms/core/shared/id\";\nimport { organizations } from \"./organizations.js\";\nimport { assets } from \"./assets.js\";\nimport type { Expect, NoDrift } from \"./drift.js\";\n\n// Bundles.\nexport const bundles = pgTable(\n \"bundles\",\n {\n orgId: text(\"org_id\")\n .notNull()\n .references(() => organizations.id),\n id: text(\"id\").notNull(),\n name: text(\"name\").notNull(),\n createdAt: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n updatedAt: timestamp(\"updated_at\", { withTimezone: true })\n .notNull()\n .defaultNow()\n .$onUpdate(() => new Date()),\n },\n (t) => ({\n pk: primaryKey({ columns: [t.orgId, t.id] }),\n typeUq: unique().on(t.orgId, t.id, t.name),\n }),\n);\n\n// The content registry one row per piece of content, any\n// type. this is so we can PK to content items of different types.\nexport const contentItems = pgTable(\n \"content_items\",\n {\n orgId: text(\"org_id\")\n .notNull()\n .references(() => organizations.id),\n id: text(\"id\").notNull(),\n type: text(\"type\", { enum: [\"course\", \"download\", \"community\"] }).notNull(),\n createdAt: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n updatedAt: timestamp(\"updated_at\", { withTimezone: true })\n .notNull()\n .defaultNow()\n .$onUpdate(() => new Date()),\n },\n (t) => ({\n pk: primaryKey({ columns: [t.orgId, t.id] }),\n // FK target for type-pinned references from concrete content tables.\n typeUq: unique().on(t.orgId, t.id, t.type),\n // Widened per new content type.\n typeCk: check(\n \"content_items_type_check\",\n sql`${t.type} in ('course', 'download', 'community')`,\n ),\n }),\n);\n\n// The content registry one row per piece of content, any\n// type. this is so we can PK to content items of different types.\nexport const bundleItems = pgTable(\n \"bundle_items\",\n {\n orgId: text(\"org_id\")\n .notNull()\n .references(() => organizations.id),\n bundleId: text(\"bundle_id\").notNull(),\n contentId: text(\"content_id\").notNull(),\n\n createdAt: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n updatedAt: timestamp(\"updated_at\", { withTimezone: true })\n .notNull()\n .defaultNow()\n .$onUpdate(() => new Date()),\n },\n (t) => ({\n pk: primaryKey({ columns: [t.orgId, t.bundleId, t.contentId] }),\n contentItemFk: foreignKey({\n columns: [t.orgId, t.contentId],\n foreignColumns: [contentItems.orgId, contentItems.id],\n }).onDelete(\"cascade\"),\n bundleFk: foreignKey({\n columns: [t.orgId, t.bundleId],\n foreignColumns: [bundles.orgId, bundles.id],\n }).onDelete(\"cascade\"),\n contentIdx: index(\"bundle_items_content_idx\").on(t.orgId, t.contentId),\n }),\n);\n\nexport const courses = pgTable(\n \"courses\",\n {\n orgId: text(\"org_id\")\n .notNull()\n .references(() => organizations.id),\n id: text(\"id\")\n .notNull()\n .$defaultFn(() => genId(\"course\")),\n // Pinned to 'course' so the composite FK below cannot attach this row to a\n // registry row of another content type.\n type: text(\"type\")\n .$type<Course[\"type\"]>()\n .notNull()\n .generatedAlwaysAs(sql`'course'`),\n title: text(\"title\").notNull(),\n slug: text(\"slug\").notNull(),\n description: text(\"description\").notNull().default(\"\"),\n status: text(\"status\", { enum: [\"draft\", \"published\"] })\n .notNull()\n .default(\"draft\"),\n category: text(\"category\").notNull().default(\"\"),\n // Media-library asset rendered as the course's cover. Null = no cover.\n thumbnailAssetId: text(\"thumbnail_asset_id\"),\n createdAt: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n updatedAt: timestamp(\"updated_at\", { withTimezone: true })\n .notNull()\n .defaultNow()\n .$onUpdate(() => new Date()),\n },\n (t) => ({\n pk: primaryKey({ columns: [t.orgId, t.id] }),\n slugUq: unique().on(t.orgId, t.slug),\n contentItemFk: foreignKey({\n columns: [t.orgId, t.id, t.type],\n foreignColumns: [contentItems.orgId, contentItems.id, contentItems.type],\n }).onDelete(\"cascade\"),\n // Restrictive, like `activity_assets.assetFk` — the asset is owned by the\n // assets domain and must be unlinked before it can be deleted. MATCH SIMPLE\n // means the constraint is skipped entirely while the thumbnail is null.\n thumbnailAssetFk: foreignKey({\n columns: [t.orgId, t.thumbnailAssetId],\n foreignColumns: [assets.orgId, assets.id],\n }),\n thumbnailIdx: index(\"courses_thumbnail_idx\").on(t.orgId, t.thumbnailAssetId),\n }),\n);\n\nexport const modules = pgTable(\n \"modules\",\n {\n orgId: text(\"org_id\")\n .notNull()\n .references(() => organizations.id),\n id: text(\"id\")\n .notNull()\n .$defaultFn(() => genId(\"module\")),\n courseId: text(\"course_id\").notNull(),\n title: text(\"title\").notNull(),\n seq: integer(\"seq\").notNull(),\n createdAt: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n updatedAt: timestamp(\"updated_at\", { withTimezone: true })\n .notNull()\n .defaultNow()\n .$onUpdate(() => new Date()),\n },\n (t) => ({\n pk: primaryKey({ columns: [t.orgId, t.id] }),\n // Modules are part of the course aggregate: deleting the course deletes them.\n courseFk: foreignKey({\n columns: [t.orgId, t.courseId],\n foreignColumns: [courses.orgId, courses.id],\n }).onDelete(\"cascade\"),\n // FK target for the course-pinned reference from activities.\n courseUq: unique().on(t.orgId, t.id, t.courseId),\n }),\n);\n\n// The leaf, directly in a module. Uniform content: seq + opaque settings blob.\nexport const activities = pgTable(\n \"activities\",\n {\n orgId: text(\"org_id\")\n .notNull()\n .references(() => organizations.id),\n id: text(\"id\")\n .notNull()\n .$defaultFn(() => genId(\"activity\")),\n moduleId: text(\"module_id\").notNull(),\n // Denormalised from the module: the course an activity belongs to is asked\n // for far more often than its module (progress, discussion, entitlements),\n // and the FK below pins the pair, so it cannot disagree with the module.\n courseId: text(\"course_id\").notNull(),\n seq: integer(\"seq\").notNull(),\n // Opaque per-activity blob: title, type, body, completion rule — whatever the\n // content needs. Assets are the one thing kept out of the blob.\n settings: jsonb(\"settings\").$type<Activity[\"settings\"]>(),\n createdAt: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n updatedAt: timestamp(\"updated_at\", { withTimezone: true })\n .notNull()\n .defaultNow()\n .$onUpdate(() => new Date()),\n },\n (t) => ({\n pk: primaryKey({ columns: [t.orgId, t.id] }),\n // Course-pinned, like `courses.contentItemFk`: the module reference carries\n // `course_id`, so an activity whose stored course disagrees with its\n // module's is rejected by the database rather than silently rotting.\n moduleFk: foreignKey({\n columns: [t.orgId, t.moduleId, t.courseId],\n foreignColumns: [modules.orgId, modules.id, modules.courseId],\n }).onDelete(\"cascade\"),\n seqUq: unique().on(t.orgId, t.moduleId, t.seq),\n }),\n);\n\n// activity ↔ asset: many-to-many (an activity uses many assets; an asset can be\n// reused by many activities). Assets owned by the assets domain, tracked here.\nexport const activityAssets = pgTable(\n \"activity_assets\",\n {\n orgId: text(\"org_id\")\n .notNull()\n .references(() => organizations.id),\n id: text(\"id\")\n .notNull()\n .$defaultFn(() => genId(\"activityAsset\")),\n activityId: text(\"activity_id\").notNull(),\n assetId: text(\"asset_id\").notNull(),\n seq: integer(\"seq\").notNull().default(0),\n createdAt: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n updatedAt: timestamp(\"updated_at\", { withTimezone: true })\n .notNull()\n .defaultNow()\n .$onUpdate(() => new Date()),\n },\n (t) => ({\n pk: primaryKey({ columns: [t.orgId, t.id] }),\n // The link cascades with its activity; the asset itself is owned by the\n // assets domain and survives (assetFk stays restrictive).\n activityFk: foreignKey({\n columns: [t.orgId, t.activityId],\n foreignColumns: [activities.orgId, activities.id],\n }).onDelete(\"cascade\"),\n assetFk: foreignKey({\n columns: [t.orgId, t.assetId],\n foreignColumns: [assets.orgId, assets.id],\n }),\n activityAssetUq: unique().on(t.orgId, t.activityId, t.assetId),\n assetIdx: index(\"activity_assets_asset_idx\").on(t.orgId, t.assetId),\n }),\n);\n\n// A download: an ordered set of media-library assets. Shares its PK with a\n// registry row (same id) via the type-pinned composite FK, exactly like courses.\nexport const downloads = pgTable(\n \"downloads\",\n {\n orgId: text(\"org_id\")\n .notNull()\n .references(() => organizations.id),\n id: text(\"id\")\n .notNull()\n .$defaultFn(() => genId(\"download\")),\n // Pinned to 'download' so the composite FK below cannot attach this row to\n // a registry row of another content type.\n type: text(\"type\")\n .$type<Download[\"type\"]>()\n .notNull()\n .generatedAlwaysAs(sql`'download'`),\n title: text(\"title\").notNull(),\n slug: text(\"slug\").notNull(),\n description: text(\"description\").notNull().default(\"\"),\n status: text(\"status\", { enum: [\"draft\", \"published\"] })\n .notNull()\n .default(\"draft\"),\n category: text(\"category\").notNull().default(\"\"),\n thumbnailAssetId: text(\"thumbnail_asset_id\"),\n createdAt: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n updatedAt: timestamp(\"updated_at\", { withTimezone: true })\n .notNull()\n .defaultNow()\n .$onUpdate(() => new Date()),\n },\n (t) => ({\n pk: primaryKey({ columns: [t.orgId, t.id] }),\n slugUq: unique().on(t.orgId, t.slug),\n contentItemFk: foreignKey({\n columns: [t.orgId, t.id, t.type],\n foreignColumns: [contentItems.orgId, contentItems.id, contentItems.type],\n }).onDelete(\"cascade\"),\n // Restrictive: a thumbnail in use blocks deleting the asset.\n thumbnailFk: foreignKey({\n columns: [t.orgId, t.thumbnailAssetId],\n foreignColumns: [assets.orgId, assets.id],\n }),\n thumbnailIdx: index(\"downloads_thumbnail_idx\").on(t.orgId, t.thumbnailAssetId),\n }),\n);\n\n// download ↔ asset: the ordered set. Mirrors activity_assets one level\n// shallower — a download has no intermediate structure.\nexport const downloadAssets = pgTable(\n \"download_assets\",\n {\n orgId: text(\"org_id\")\n .notNull()\n .references(() => organizations.id),\n id: text(\"id\")\n .notNull()\n .$defaultFn(() => genId(\"downloadAsset\")),\n downloadId: text(\"download_id\").notNull(),\n assetId: text(\"asset_id\").notNull(),\n seq: integer(\"seq\").notNull().default(0),\n // Author's label; null falls back to the asset's filename.\n displayName: text(\"display_name\"),\n createdAt: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n updatedAt: timestamp(\"updated_at\", { withTimezone: true })\n .notNull()\n .defaultNow()\n .$onUpdate(() => new Date()),\n },\n (t) => ({\n pk: primaryKey({ columns: [t.orgId, t.id] }),\n // The link cascades with its download; the asset is owned by the assets\n // domain and survives (assetFk stays restrictive).\n downloadFk: foreignKey({\n columns: [t.orgId, t.downloadId],\n foreignColumns: [downloads.orgId, downloads.id],\n }).onDelete(\"cascade\"),\n assetFk: foreignKey({\n columns: [t.orgId, t.assetId],\n foreignColumns: [assets.orgId, assets.id],\n }),\n // Lets delivery key on asset_id rather than the link row id.\n downloadAssetUq: unique().on(t.orgId, t.downloadId, t.assetId),\n assetIdx: index(\"download_assets_asset_idx\").on(t.orgId, t.assetId),\n }),\n);\n\nexport const communities = pgTable(\n \"communities\",\n {\n orgId: text(\"org_id\")\n .notNull()\n .references(() => organizations.id),\n id: text(\"id\")\n .notNull()\n .$defaultFn(() => genId(\"community\")),\n type: text(\"type\")\n .$type<Community[\"type\"]>()\n .notNull()\n .generatedAlwaysAs(sql`'community'`),\n title: text(\"title\").notNull(),\n slug: text(\"slug\").notNull(),\n description: text(\"description\").notNull().default(\"\"),\n status: text(\"status\", { enum: [\"draft\", \"published\"] })\n .notNull()\n .default(\"draft\"),\n thumbnailAssetId: text(\"thumbnail_asset_id\"),\n createdAt: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n updatedAt: timestamp(\"updated_at\", { withTimezone: true })\n .notNull()\n .defaultNow()\n .$onUpdate(() => new Date()),\n },\n (t) => ({\n pk: primaryKey({ columns: [t.orgId, t.id] }),\n slugUq: unique().on(t.orgId, t.slug),\n contentItemFk: foreignKey({\n columns: [t.orgId, t.id, t.type],\n foreignColumns: [contentItems.orgId, contentItems.id, contentItems.type],\n }).onDelete(\"cascade\"),\n thumbnailAssetFk: foreignKey({\n columns: [t.orgId, t.thumbnailAssetId],\n foreignColumns: [assets.orgId, assets.id],\n }),\n thumbnailIdx: index(\"communities_thumbnail_idx\").on(t.orgId, t.thumbnailAssetId),\n }),\n);\n\nexport const spaces = pgTable(\n \"spaces\",\n {\n orgId: text(\"org_id\")\n .notNull()\n .references(() => organizations.id),\n id: text(\"id\")\n .notNull()\n .$defaultFn(() => genId(\"space\")),\n communityId: text(\"community_id\").notNull(),\n name: text(\"name\").notNull(),\n description: text(\"description\").notNull().default(\"\"),\n seq: integer(\"seq\").notNull(),\n accessRule: text(\"access_rule\", { enum: [\"all_members\", \"by_request\", \"by_invite\"] })\n .notNull()\n .default(\"all_members\"),\n capacity: integer(\"capacity\"),\n settings: jsonb(\"settings\")\n .$type<Space[\"settings\"]>()\n .notNull()\n .default({ comments: true, reactions: true, requireReview: false }),\n createdAt: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n updatedAt: timestamp(\"updated_at\", { withTimezone: true })\n .notNull()\n .defaultNow()\n .$onUpdate(() => new Date()),\n },\n (t) => ({\n pk: primaryKey({ columns: [t.orgId, t.id] }),\n communityUq: unique().on(t.orgId, t.id, t.communityId),\n communityFk: foreignKey({\n columns: [t.orgId, t.communityId],\n foreignColumns: [communities.orgId, communities.id],\n }).onDelete(\"cascade\"),\n capacityCk: check(\n \"spaces_capacity_check\",\n sql`${t.capacity} is null or ${t.accessRule} <> 'all_members'`,\n ),\n orderIdx: index(\"spaces_order_idx\").on(t.orgId, t.communityId, t.seq),\n }),\n);\n\nexport const spaceTopics = pgTable(\n \"space_topics\",\n {\n orgId: text(\"org_id\")\n .notNull()\n .references(() => organizations.id),\n id: text(\"id\")\n .notNull()\n .$defaultFn(() => genId(\"topic\")),\n spaceId: text(\"space_id\").notNull(),\n name: text(\"name\").notNull(),\n seq: integer(\"seq\").notNull(),\n createdAt: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n updatedAt: timestamp(\"updated_at\", { withTimezone: true })\n .notNull()\n .defaultNow()\n .$onUpdate(() => new Date()),\n },\n (t) => ({\n pk: primaryKey({ columns: [t.orgId, t.id] }),\n nameUq: unique().on(t.orgId, t.spaceId, t.name),\n spaceUq: unique().on(t.orgId, t.spaceId, t.id),\n spaceFk: foreignKey({\n columns: [t.orgId, t.spaceId],\n foreignColumns: [spaces.orgId, spaces.id],\n }).onDelete(\"cascade\"),\n }),\n);\n\nexport const spaceLinks = pgTable(\n \"space_links\",\n {\n orgId: text(\"org_id\")\n .notNull()\n .references(() => organizations.id),\n id: text(\"id\")\n .notNull()\n .$defaultFn(() => genId(\"spaceLink\")),\n spaceId: text(\"space_id\").notNull(),\n contentId: text(\"content_id\").notNull(),\n seq: integer(\"seq\").notNull().default(0),\n createdAt: timestamp(\"created_at\", { withTimezone: true }).notNull().defaultNow(),\n updatedAt: timestamp(\"updated_at\", { withTimezone: true })\n .notNull()\n .defaultNow()\n .$onUpdate(() => new Date()),\n },\n (t) => ({\n pk: primaryKey({ columns: [t.orgId, t.id] }),\n contentUq: unique().on(t.orgId, t.spaceId, t.contentId),\n spaceFk: foreignKey({\n columns: [t.orgId, t.spaceId],\n foreignColumns: [spaces.orgId, spaces.id],\n }).onDelete(\"cascade\"),\n contentFk: foreignKey({\n columns: [t.orgId, t.contentId],\n foreignColumns: [contentItems.orgId, contentItems.id],\n }).onDelete(\"cascade\"),\n contentIdx: index(\"space_links_content_idx\").on(t.orgId, t.contentId),\n }),\n);\n\ntype _BundlesDrift = Expect<NoDrift<typeof bundles.$inferSelect, Bundle>>;\ntype _BundleItemsDrift = Expect<NoDrift<typeof bundleItems.$inferSelect, BundleItem>>;\ntype _ContentItemsDrift = Expect<NoDrift<typeof contentItems.$inferSelect, ContentItem>>;\ntype _CoursesDrift = Expect<NoDrift<typeof courses.$inferSelect, Omit<Course, \"settings\">>>;\ntype _ModulesDrift = Expect<NoDrift<typeof modules.$inferSelect, Module>>;\ntype _ActivitiesDrift = Expect<NoDrift<typeof activities.$inferSelect, Activity>>;\ntype _ActivityAssetsDrift = Expect<NoDrift<typeof activityAssets.$inferSelect, ActivityAsset>>;\ntype _DownloadsDrift = Expect<NoDrift<typeof downloads.$inferSelect, Download>>;\ntype _DownloadAssetsDrift = Expect<NoDrift<typeof downloadAssets.$inferSelect, DownloadAsset>>;\ntype _CommunitiesDrift = Expect<\n NoDrift<typeof communities.$inferSelect, Omit<Community, \"settings\">>\n>;\ntype _SpacesDrift = Expect<NoDrift<typeof spaces.$inferSelect, Space>>;\ntype _SpaceTopicsDrift = Expect<NoDrift<typeof spaceTopics.$inferSelect, SpaceTopic>>;\ntype _SpaceLinksDrift = Expect<NoDrift<typeof spaceLinks.$inferSelect, SpaceLink>>;\n"],"mappings":"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"}
|