@headless-lms/adapter-db 0.2.0 → 0.3.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.
Files changed (104) hide show
  1. package/dist/index.d.ts +7 -6
  2. package/dist/index.js +7 -6
  3. package/dist/repositories/admin.d.ts +23 -0
  4. package/dist/repositories/admin.js +393 -0
  5. package/dist/repositories/admin.js.map +1 -0
  6. package/dist/repositories/assets.d.ts +6 -2
  7. package/dist/repositories/assets.js +50 -9
  8. package/dist/repositories/assets.js.map +1 -1
  9. package/dist/repositories/automations.d.ts +6 -2
  10. package/dist/repositories/automations.js +45 -2
  11. package/dist/repositories/automations.js.map +1 -1
  12. package/dist/repositories/chats.d.ts +55 -0
  13. package/dist/repositories/chats.js +454 -0
  14. package/dist/repositories/chats.js.map +1 -0
  15. package/dist/repositories/content.d.ts +24 -1
  16. package/dist/repositories/content.js +293 -9
  17. package/dist/repositories/content.js.map +1 -1
  18. package/dist/repositories/discussion.d.ts +10 -3
  19. package/dist/repositories/discussion.js +70 -15
  20. package/dist/repositories/discussion.js.map +1 -1
  21. package/dist/repositories/entitlements.d.ts +29 -9
  22. package/dist/repositories/entitlements.js +207 -17
  23. package/dist/repositories/entitlements.js.map +1 -1
  24. package/dist/repositories/grant-covers.d.ts +20 -0
  25. package/dist/repositories/grant-covers.js +55 -0
  26. package/dist/repositories/grant-covers.js.map +1 -0
  27. package/dist/repositories/identity.d.ts +4 -2
  28. package/dist/repositories/identity.js +32 -1
  29. package/dist/repositories/identity.js.map +1 -1
  30. package/dist/repositories/member.d.ts +16 -0
  31. package/dist/repositories/member.js +63 -0
  32. package/dist/repositories/member.js.map +1 -0
  33. package/dist/repositories/members.js +2 -2
  34. package/dist/repositories/members.js.map +1 -1
  35. package/dist/repositories/notifications.d.ts +23 -0
  36. package/dist/repositories/notifications.js +70 -0
  37. package/dist/repositories/notifications.js.map +1 -0
  38. package/dist/repositories/org-user-profile.d.ts +214 -1
  39. package/dist/repositories/org-user-profile.js +23 -2
  40. package/dist/repositories/org-user-profile.js.map +1 -1
  41. package/dist/repositories/organizations.d.ts +3 -2
  42. package/dist/repositories/organizations.js +20 -8
  43. package/dist/repositories/organizations.js.map +1 -1
  44. package/dist/repositories/pg-errors.js +3 -1
  45. package/dist/repositories/pg-errors.js.map +1 -1
  46. package/dist/repositories/posts.d.ts +39 -0
  47. package/dist/repositories/posts.js +255 -0
  48. package/dist/repositories/posts.js.map +1 -0
  49. package/dist/schema/assets.d.ts +19 -2
  50. package/dist/schema/assets.js +10 -4
  51. package/dist/schema/assets.js.map +1 -1
  52. package/dist/schema/automations.d.ts +38 -0
  53. package/dist/schema/automations.js +5 -1
  54. package/dist/schema/automations.js.map +1 -1
  55. package/dist/schema/better-auth.d.ts +1613 -238
  56. package/dist/schema/better-auth.js +107 -22
  57. package/dist/schema/better-auth.js.map +1 -1
  58. package/dist/schema/content.d.ts +642 -5
  59. package/dist/schema/content.js +119 -10
  60. package/dist/schema/content.js.map +1 -1
  61. package/dist/schema/discussion.d.ts +2045 -55
  62. package/dist/schema/discussion.js +426 -11
  63. package/dist/schema/discussion.js.map +1 -1
  64. package/dist/schema/entitlements.d.ts +432 -1
  65. package/dist/schema/entitlements.js +109 -4
  66. package/dist/schema/entitlements.js.map +1 -1
  67. package/dist/schema/identity.d.ts +517 -1
  68. package/dist/schema/identity.js +118 -2
  69. package/dist/schema/identity.js.map +1 -1
  70. package/dist/schema/index.d.ts +6 -6
  71. package/dist/schema/index.js +30 -7
  72. package/dist/schema/organizations.d.ts +4 -4
  73. package/dist/schema/organizations.js +2 -0
  74. package/dist/schema/organizations.js.map +1 -1
  75. package/drizzle/0003_community.sql +340 -0
  76. package/drizzle/0004_assets_sources.sql +1 -0
  77. package/drizzle/0005_notices_and_seed_index.sql +12 -0
  78. package/drizzle/0006_community_review_fixes.sql +24 -0
  79. package/drizzle/0007_notifications.sql +37 -0
  80. package/drizzle/0008_content_access.sql +13 -0
  81. package/drizzle/0009_community_indexes.sql +56 -0
  82. package/drizzle/0010_mcp_access.sql +114 -0
  83. package/drizzle/meta/0003_snapshot.json +7061 -0
  84. package/drizzle/meta/0004_snapshot.json +7068 -0
  85. package/drizzle/meta/0005_snapshot.json +7180 -0
  86. package/drizzle/meta/0006_snapshot.json +7298 -0
  87. package/drizzle/meta/0007_snapshot.json +7620 -0
  88. package/drizzle/meta/0008_snapshot.json +7666 -0
  89. package/drizzle/meta/0009_snapshot.json +8185 -0
  90. package/drizzle/meta/0010_snapshot.json +8813 -0
  91. package/drizzle/meta/_journal.json +57 -1
  92. package/package.json +2 -2
  93. package/dist/repositories/course-analytics.d.ts +0 -15
  94. package/dist/repositories/course-analytics.js +0 -137
  95. package/dist/repositories/course-analytics.js.map +0 -1
  96. package/dist/repositories/dashboard.d.ts +0 -14
  97. package/dist/repositories/dashboard.js +0 -57
  98. package/dist/repositories/dashboard.js.map +0 -1
  99. package/dist/repositories/learn.d.ts +0 -19
  100. package/dist/repositories/learn.js +0 -56
  101. package/dist/repositories/learn.js.map +0 -1
  102. package/dist/repositories/students.d.ts +0 -16
  103. package/dist/repositories/students.js +0 -160
  104. package/dist/repositories/students.js.map +0 -1
@@ -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: ["course", "download"] }).notNull(),
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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"}