@headless-lms/core 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (307) hide show
  1. package/dist/assets/events.d.ts +24 -18
  2. package/dist/assets/file-urls.d.ts +11 -7
  3. package/dist/assets/file-urls.js +14 -4
  4. package/dist/assets/file-urls.js.map +1 -1
  5. package/dist/assets/index.d.ts +5 -4
  6. package/dist/assets/index.js +4 -3
  7. package/dist/assets/jobs.d.ts +15 -0
  8. package/dist/assets/jobs.js +30 -0
  9. package/dist/assets/jobs.js.map +1 -0
  10. package/dist/assets/ports.d.ts +37 -17
  11. package/dist/assets/service.d.ts +30 -15
  12. package/dist/assets/service.js +229 -59
  13. package/dist/assets/service.js.map +1 -1
  14. package/dist/automations/actions.js +2 -63
  15. package/dist/automations/actions.js.map +1 -1
  16. package/dist/automations/catalog.d.ts +1 -2
  17. package/dist/automations/catalog.js +137 -65
  18. package/dist/automations/catalog.js.map +1 -1
  19. package/dist/automations/community-derivations.js +20 -20
  20. package/dist/automations/community-derivations.js.map +1 -1
  21. package/dist/automations/community-mail.d.ts +36 -20
  22. package/dist/automations/community-mail.js +32 -24
  23. package/dist/automations/community-mail.js.map +1 -1
  24. package/dist/automations/event-permissions.d.ts +12 -0
  25. package/dist/automations/event-permissions.js +38 -0
  26. package/dist/automations/event-permissions.js.map +1 -0
  27. package/dist/automations/events.d.ts +0 -10
  28. package/dist/automations/index.d.ts +12 -4
  29. package/dist/automations/index.js +9 -1
  30. package/dist/automations/notifications/applicable.d.ts +8 -0
  31. package/dist/automations/notifications/applicable.js +12 -0
  32. package/dist/automations/notifications/applicable.js.map +1 -0
  33. package/dist/automations/notifications/debounce.d.ts +25 -0
  34. package/dist/automations/notifications/debounce.js +93 -0
  35. package/dist/automations/notifications/debounce.js.map +1 -0
  36. package/dist/automations/notifications/defaults.d.ts +8 -0
  37. package/dist/automations/notifications/defaults.js +346 -0
  38. package/dist/automations/notifications/defaults.js.map +1 -0
  39. package/dist/automations/notifications/delivery.d.ts +28 -0
  40. package/dist/automations/notifications/delivery.js +88 -0
  41. package/dist/automations/notifications/delivery.js.map +1 -0
  42. package/dist/automations/notifications/processor.d.ts +64 -0
  43. package/dist/automations/notifications/processor.js +270 -0
  44. package/dist/automations/notifications/processor.js.map +1 -0
  45. package/dist/automations/notifications/rules/content.d.ts +6 -0
  46. package/dist/automations/notifications/rules/content.js +96 -0
  47. package/dist/automations/notifications/rules/content.js.map +1 -0
  48. package/dist/automations/notifications/rules/discussion.d.ts +7 -0
  49. package/dist/automations/notifications/rules/discussion.js +678 -0
  50. package/dist/automations/notifications/rules/discussion.js.map +1 -0
  51. package/dist/automations/notifications/rules/entitlements.d.ts +6 -0
  52. package/dist/automations/notifications/rules/entitlements.js +276 -0
  53. package/dist/automations/notifications/rules/entitlements.js.map +1 -0
  54. package/dist/automations/notifications/rules/events.d.ts +9 -0
  55. package/dist/automations/notifications/rules/events.js +27 -0
  56. package/dist/automations/notifications/rules/events.js.map +1 -0
  57. package/dist/automations/notifications/rules/index.d.ts +6 -0
  58. package/dist/automations/notifications/rules/index.js +15 -0
  59. package/dist/automations/notifications/rules/index.js.map +1 -0
  60. package/dist/automations/notifications/rules/organizations.d.ts +6 -0
  61. package/dist/automations/notifications/rules/organizations.js +35 -0
  62. package/dist/automations/notifications/rules/organizations.js.map +1 -0
  63. package/dist/automations/notifications/rules/recipients.d.ts +32 -0
  64. package/dist/automations/notifications/rules/recipients.js +98 -0
  65. package/dist/automations/notifications/rules/recipients.js.map +1 -0
  66. package/dist/automations/notifications/service.d.ts +29 -0
  67. package/dist/automations/notifications/service.js +45 -0
  68. package/dist/automations/notifications/service.js.map +1 -0
  69. package/dist/automations/notifications/types.d.ts +7 -0
  70. package/dist/automations/notifications/types.js +560 -0
  71. package/dist/automations/notifications/types.js.map +1 -0
  72. package/dist/automations/ports.d.ts +134 -21
  73. package/dist/automations/service.d.ts +30 -30
  74. package/dist/automations/service.js +111 -144
  75. package/dist/automations/service.js.map +1 -1
  76. package/dist/content/event-sight.d.ts +11 -0
  77. package/dist/content/event-sight.js +11 -0
  78. package/dist/content/event-sight.js.map +1 -0
  79. package/dist/content/events.d.ts +437 -46
  80. package/dist/content/events.js +45 -1
  81. package/dist/content/events.js.map +1 -1
  82. package/dist/content/index.d.ts +8 -4
  83. package/dist/content/index.js +5 -1
  84. package/dist/content/jobs.d.ts +16 -0
  85. package/dist/content/jobs.js +37 -0
  86. package/dist/content/jobs.js.map +1 -0
  87. package/dist/content/model.d.ts +2 -2
  88. package/dist/content/notification-categories.d.ts +37 -0
  89. package/dist/content/notification-categories.js +73 -0
  90. package/dist/content/notification-categories.js.map +1 -0
  91. package/dist/content/ports.d.ts +132 -68
  92. package/dist/content/service.d.ts +100 -68
  93. package/dist/content/service.js +703 -146
  94. package/dist/content/service.js.map +1 -1
  95. package/dist/content/titles.d.ts +25 -0
  96. package/dist/content/titles.js +82 -0
  97. package/dist/content/titles.js.map +1 -0
  98. package/dist/content/types.d.ts +2 -2
  99. package/dist/discussion/authors.d.ts +4 -2
  100. package/dist/discussion/authors.js +9 -5
  101. package/dist/discussion/authors.js.map +1 -1
  102. package/dist/discussion/chats.d.ts +63 -39
  103. package/dist/discussion/chats.js +455 -190
  104. package/dist/discussion/chats.js.map +1 -1
  105. package/dist/discussion/digests.d.ts +24 -0
  106. package/dist/discussion/digests.js +104 -0
  107. package/dist/discussion/digests.js.map +1 -0
  108. package/dist/discussion/events.d.ts +227 -23
  109. package/dist/discussion/events.js +114 -19
  110. package/dist/discussion/events.js.map +1 -1
  111. package/dist/discussion/index.d.ts +12 -4
  112. package/dist/discussion/index.js +9 -2
  113. package/dist/discussion/jobs.d.ts +16 -0
  114. package/dist/discussion/jobs.js +40 -0
  115. package/dist/discussion/jobs.js.map +1 -0
  116. package/dist/discussion/live.d.ts +106 -0
  117. package/dist/discussion/live.js +642 -0
  118. package/dist/discussion/live.js.map +1 -0
  119. package/dist/discussion/mentions.d.ts +11 -0
  120. package/dist/discussion/mentions.js +35 -0
  121. package/dist/discussion/mentions.js.map +1 -0
  122. package/dist/discussion/ports.d.ts +279 -114
  123. package/dist/discussion/ports.js.map +1 -1
  124. package/dist/discussion/posts.d.ts +60 -44
  125. package/dist/discussion/posts.js +453 -287
  126. package/dist/discussion/posts.js.map +1 -1
  127. package/dist/discussion/rules.d.ts +18 -0
  128. package/dist/discussion/rules.js +22 -0
  129. package/dist/discussion/rules.js.map +1 -0
  130. package/dist/discussion/service.d.ts +50 -35
  131. package/dist/discussion/service.js +333 -205
  132. package/dist/discussion/service.js.map +1 -1
  133. package/dist/discussion/subscriptions.d.ts +37 -0
  134. package/dist/discussion/subscriptions.js +115 -0
  135. package/dist/discussion/subscriptions.js.map +1 -0
  136. package/dist/discussion/titles.d.ts +28 -0
  137. package/dist/discussion/titles.js +98 -0
  138. package/dist/discussion/titles.js.map +1 -0
  139. package/dist/entitlements/events.d.ts +20 -20
  140. package/dist/entitlements/index.d.ts +5 -4
  141. package/dist/entitlements/index.js +3 -2
  142. package/dist/entitlements/jobs.d.ts +12 -0
  143. package/dist/entitlements/jobs.js +18 -0
  144. package/dist/entitlements/jobs.js.map +1 -0
  145. package/dist/entitlements/model.d.ts +2 -2
  146. package/dist/entitlements/ports.d.ts +68 -38
  147. package/dist/entitlements/rules.d.ts +3 -6
  148. package/dist/entitlements/rules.js +5 -10
  149. package/dist/entitlements/rules.js.map +1 -1
  150. package/dist/entitlements/service.d.ts +43 -28
  151. package/dist/entitlements/service.js +387 -160
  152. package/dist/entitlements/service.js.map +1 -1
  153. package/dist/identity/devices.d.ts +30 -0
  154. package/dist/identity/devices.js +109 -0
  155. package/dist/identity/devices.js.map +1 -0
  156. package/dist/identity/index.d.ts +6 -5
  157. package/dist/identity/index.js +4 -3
  158. package/dist/identity/model.d.ts +2 -2
  159. package/dist/identity/notification-settings.d.ts +28 -0
  160. package/dist/identity/notification-settings.js +114 -0
  161. package/dist/identity/notification-settings.js.map +1 -0
  162. package/dist/identity/ports.d.ts +80 -56
  163. package/dist/identity/service.d.ts +8 -7
  164. package/dist/identity/service.js +17 -13
  165. package/dist/identity/service.js.map +1 -1
  166. package/dist/integrations/ports.d.ts +9 -8
  167. package/dist/integrations/service.d.ts +9 -8
  168. package/dist/integrations/service.js +33 -16
  169. package/dist/integrations/service.js.map +1 -1
  170. package/dist/organizations/default-roles.d.ts +22 -0
  171. package/dist/organizations/default-roles.js +89 -0
  172. package/dist/organizations/default-roles.js.map +1 -0
  173. package/dist/organizations/effective-permissions.d.ts +45 -0
  174. package/dist/organizations/effective-permissions.js +113 -0
  175. package/dist/organizations/effective-permissions.js.map +1 -0
  176. package/dist/organizations/events.d.ts +320 -181
  177. package/dist/organizations/events.js +90 -18
  178. package/dist/organizations/events.js.map +1 -1
  179. package/dist/organizations/index.d.ts +15 -10
  180. package/dist/organizations/index.js +8 -3
  181. package/dist/organizations/members.d.ts +66 -8
  182. package/dist/organizations/members.js.map +1 -1
  183. package/dist/organizations/notification-catalog.d.ts +31 -0
  184. package/dist/organizations/notification-catalog.js +32 -0
  185. package/dist/organizations/notification-catalog.js.map +1 -0
  186. package/dist/organizations/notification-categories.d.ts +34 -0
  187. package/dist/organizations/notification-categories.js +66 -0
  188. package/dist/organizations/notification-categories.js.map +1 -0
  189. package/dist/organizations/org-roles.d.ts +33 -0
  190. package/dist/organizations/org-roles.js +49 -0
  191. package/dist/organizations/org-roles.js.map +1 -0
  192. package/dist/organizations/permissions.d.ts +311 -0
  193. package/dist/organizations/permissions.js +327 -0
  194. package/dist/organizations/permissions.js.map +1 -0
  195. package/dist/organizations/ports.d.ts +187 -65
  196. package/dist/organizations/service.d.ts +104 -35
  197. package/dist/organizations/service.js +1247 -323
  198. package/dist/organizations/service.js.map +1 -1
  199. package/dist/organizations/testing.d.ts +18 -0
  200. package/dist/organizations/testing.js +37 -0
  201. package/dist/organizations/testing.js.map +1 -0
  202. package/dist/organizations/types.d.ts +5 -16
  203. package/dist/progress/index.d.ts +2 -2
  204. package/dist/progress/ports.d.ts +11 -3
  205. package/dist/progress/service.d.ts +6 -5
  206. package/dist/progress/service.js +23 -8
  207. package/dist/progress/service.js.map +1 -1
  208. package/dist/reporting/admin/index.d.ts +6 -4
  209. package/dist/reporting/admin/model.d.ts +36 -3
  210. package/dist/reporting/admin/ports.d.ts +39 -14
  211. package/dist/reporting/admin/service.d.ts +32 -11
  212. package/dist/reporting/admin/service.js +102 -18
  213. package/dist/reporting/admin/service.js.map +1 -1
  214. package/dist/reporting/events/index.d.ts +27 -0
  215. package/dist/reporting/events/index.js +20 -0
  216. package/dist/reporting/events/index.js.map +1 -0
  217. package/dist/reporting/member/calendar.d.ts +11 -0
  218. package/dist/reporting/member/calendar.js +75 -0
  219. package/dist/reporting/member/calendar.js.map +1 -0
  220. package/dist/reporting/member/index.d.ts +3 -2
  221. package/dist/reporting/member/model.d.ts +80 -26
  222. package/dist/reporting/member/ports.d.ts +50 -28
  223. package/dist/reporting/member/service.d.ts +81 -35
  224. package/dist/reporting/member/service.js +438 -145
  225. package/dist/reporting/member/service.js.map +1 -1
  226. package/dist/shared/actor.d.ts +22 -3
  227. package/dist/shared/errors.d.ts +15 -2
  228. package/dist/shared/errors.js +21 -2
  229. package/dist/shared/errors.js.map +1 -1
  230. package/dist/shared/id.d.ts +7 -0
  231. package/dist/shared/id.js +8 -1
  232. package/dist/shared/id.js.map +1 -1
  233. package/dist/shared/logger.d.ts +2 -1
  234. package/dist/shared/logger.js +10 -1
  235. package/dist/shared/logger.js.map +1 -1
  236. package/dist/shared/mailer.d.ts +11 -1
  237. package/dist/shared/mailer.js +32 -5
  238. package/dist/shared/mailer.js.map +1 -1
  239. package/dist/shared/notification-categories.d.ts +16 -0
  240. package/dist/shared/notification-categories.js +94 -0
  241. package/dist/shared/notification-categories.js.map +1 -0
  242. package/dist/shared/notification-settings.d.ts +14 -0
  243. package/dist/shared/notification-settings.js +61 -0
  244. package/dist/shared/notification-settings.js.map +1 -0
  245. package/dist/shared/ports.d.ts +68 -2
  246. package/dist/shared/settings.d.ts +2 -1
  247. package/dist/shared/settings.js +1 -0
  248. package/dist/shared/settings.js.map +1 -1
  249. package/dist/types/automations.d.ts +8 -2
  250. package/dist/types/content.d.ts +2 -2
  251. package/dist/types/discussion.d.ts +4 -5
  252. package/dist/types/email-templates.d.ts +119 -6
  253. package/dist/types/entitlements.d.ts +2 -2
  254. package/dist/types/identity.d.ts +14 -17
  255. package/dist/types/index.d.ts +13 -12
  256. package/dist/types/index.js +2 -1
  257. package/dist/types/notifications.d.ts +157 -0
  258. package/dist/types/notifications.js +1 -0
  259. package/dist/types/organizations.d.ts +3 -2
  260. package/dist/types/ports.d.ts +8 -1
  261. package/dist/types/ports.js +7 -1
  262. package/dist/types/ports.js.map +1 -0
  263. package/dist/types/schemas/assets.d.ts +5 -5
  264. package/dist/types/schemas/assets.js +4 -3
  265. package/dist/types/schemas/assets.js.map +1 -1
  266. package/dist/types/schemas/automations.d.ts +1 -10
  267. package/dist/types/schemas/automations.js +1 -3
  268. package/dist/types/schemas/automations.js.map +1 -1
  269. package/dist/types/schemas/content.d.ts +596 -11
  270. package/dist/types/schemas/content.js +225 -9
  271. package/dist/types/schemas/content.js.map +1 -1
  272. package/dist/types/schemas/discussion.d.ts +362 -66
  273. package/dist/types/schemas/discussion.js +123 -15
  274. package/dist/types/schemas/discussion.js.map +1 -1
  275. package/dist/types/schemas/entitlements.d.ts +14 -1
  276. package/dist/types/schemas/entitlements.js +11 -4
  277. package/dist/types/schemas/entitlements.js.map +1 -1
  278. package/dist/types/schemas/identity.d.ts +1 -85
  279. package/dist/types/schemas/identity.js +1 -42
  280. package/dist/types/schemas/identity.js.map +1 -1
  281. package/dist/types/schemas/index.d.ts +8 -7
  282. package/dist/types/schemas/index.js +8 -7
  283. package/dist/types/schemas/notifications.d.ts +96 -0
  284. package/dist/types/schemas/notifications.js +57 -0
  285. package/dist/types/schemas/notifications.js.map +1 -0
  286. package/dist/types/schemas/organizations.d.ts +96 -60
  287. package/dist/types/schemas/organizations.js +78 -27
  288. package/dist/types/schemas/organizations.js.map +1 -1
  289. package/dist/types/schemas/progress.d.ts +0 -1
  290. package/dist/types/schemas/progress.js +0 -1
  291. package/dist/types/schemas/progress.js.map +1 -1
  292. package/package.json +1 -1
  293. package/dist/automations/community-notifications.d.ts +0 -16
  294. package/dist/automations/community-notifications.js +0 -84
  295. package/dist/automations/community-notifications.js.map +0 -1
  296. package/dist/automations/seeds.d.ts +0 -17
  297. package/dist/automations/seeds.js +0 -235
  298. package/dist/automations/seeds.js.map +0 -1
  299. package/dist/identity/notifications.d.ts +0 -27
  300. package/dist/identity/notifications.js +0 -101
  301. package/dist/identity/notifications.js.map +0 -1
  302. package/dist/organizations/access-scopes.d.ts +0 -19
  303. package/dist/organizations/access-scopes.js +0 -89
  304. package/dist/organizations/access-scopes.js.map +0 -1
  305. package/dist/organizations/roles.d.ts +0 -19
  306. package/dist/organizations/roles.js +0 -82
  307. package/dist/organizations/roles.js.map +0 -1
@@ -1,5 +1,7 @@
1
- import { inviteSchema, orgUserSchema, organizationSchema } from "../types/schemas/organizations.js";
1
+ import { contentTypeSchema } from "../types/schemas/content.js";
2
+ import { inviteSchema, levelSchema, orgUserSchema, organizationSchema } from "../types/schemas/organizations.js";
2
3
  import { defineEvent } from "../shared/events.js";
4
+ import { z } from "zod";
3
5
  //#region src/organizations/events.ts
4
6
  const publicOrganization = organizationSchema.pick({
5
7
  id: true,
@@ -13,7 +15,6 @@ const publicOrgUser = orgUserSchema.pick({
13
15
  id: true,
14
16
  orgId: true,
15
17
  userId: true,
16
- role: true,
17
18
  status: true,
18
19
  createdAt: true,
19
20
  updatedAt: true
@@ -22,13 +23,48 @@ const publicInvite = inviteSchema.pick({
22
23
  id: true,
23
24
  orgId: true,
24
25
  email: true,
25
- role: true,
26
+ roleKey: true,
26
27
  status: true,
27
28
  invitedBy: true,
28
29
  expiresAt: true,
29
30
  createdAt: true,
30
31
  updatedAt: true
31
32
  }).strip();
33
+ const orgUserWithRole = orgUserSchema.extend({ orgRole: z.object({ key: z.string() }) });
34
+ const publicOrgUserWithRole = publicOrgUser.extend({ orgRole: z.object({ key: z.string() }) });
35
+ const roleSnapshot = z.object({
36
+ key: z.string(),
37
+ name: z.string(),
38
+ description: z.string(),
39
+ base: z.string(),
40
+ levels: z.array(levelSchema),
41
+ team: z.boolean(),
42
+ permissions: z.array(z.string())
43
+ });
44
+ const roleUpdated = z.object({
45
+ key: z.string(),
46
+ before: roleSnapshot,
47
+ after: roleSnapshot
48
+ });
49
+ const roleCreated = z.object({ role: roleSnapshot });
50
+ const roleDeleted = z.object({ key: z.string() });
51
+ const roleAssigned = z.object({
52
+ orgUserId: z.string(),
53
+ roleKey: z.string(),
54
+ contentId: z.string().nullable(),
55
+ contentType: contentTypeSchema.nullable(),
56
+ previousRoleKey: z.string().nullable()
57
+ });
58
+ const roleUnassigned = z.object({
59
+ orgUserId: z.string(),
60
+ roleKey: z.string(),
61
+ contentId: z.string(),
62
+ contentType: contentTypeSchema
63
+ });
64
+ const ownershipTransferred = z.object({
65
+ previousOwnerOrgUserId: z.string(),
66
+ newOwnerOrgUserId: z.string()
67
+ });
32
68
  const organizationEvents = {
33
69
  organizationCreated: defineEvent({
34
70
  type: "organization.created",
@@ -50,54 +86,90 @@ const organizationEvents = {
50
86
  }),
51
87
  orgUserLinked: defineEvent({
52
88
  type: "organization.user.linked",
53
- version: 1,
54
- data: orgUserSchema,
55
- publicData: publicOrgUser
89
+ version: 2,
90
+ data: orgUserWithRole,
91
+ publicData: publicOrgUserWithRole
56
92
  }),
57
93
  orgUserDeleted: defineEvent({
58
94
  type: "organization.user.deleted",
59
- version: 1,
60
- data: orgUserSchema,
61
- publicData: publicOrgUser
95
+ version: 2,
96
+ data: orgUserWithRole,
97
+ publicData: publicOrgUserWithRole
62
98
  }),
63
99
  orgUserUpdated: defineEvent({
64
100
  type: "organization.user.updated",
65
- version: 1,
66
- data: orgUserSchema,
67
- publicData: publicOrgUser
101
+ version: 2,
102
+ data: orgUserWithRole,
103
+ publicData: publicOrgUserWithRole
68
104
  }),
69
105
  inviteCreated: defineEvent({
70
106
  type: "organization.invite.created",
71
- version: 1,
107
+ version: 2,
72
108
  data: inviteSchema,
73
109
  publicData: publicInvite
74
110
  }),
75
111
  inviteAccepted: defineEvent({
76
112
  type: "organization.invite.accepted",
77
- version: 1,
113
+ version: 2,
78
114
  data: inviteSchema,
79
115
  publicData: publicInvite
80
116
  }),
81
117
  inviteCanceled: defineEvent({
82
118
  type: "organization.invite.canceled",
83
- version: 1,
119
+ version: 2,
84
120
  data: inviteSchema
85
121
  }),
86
122
  studentCreated: defineEvent({
87
123
  type: "organization.student.created",
88
- version: 1,
124
+ version: 2,
89
125
  data: orgUserSchema,
90
126
  publicData: publicOrgUser
91
127
  }),
92
128
  studentDeleted: defineEvent({
93
129
  type: "organization.student.deleted",
94
- version: 1,
130
+ version: 2,
95
131
  data: orgUserSchema,
96
132
  publicData: publicOrgUser
97
133
  }),
134
+ roleUpdated: defineEvent({
135
+ type: "organization.role.updated",
136
+ version: 1,
137
+ data: roleUpdated,
138
+ publicData: roleUpdated
139
+ }),
140
+ roleCreated: defineEvent({
141
+ type: "organization.role.created",
142
+ version: 1,
143
+ data: roleCreated,
144
+ publicData: roleCreated
145
+ }),
146
+ roleDeleted: defineEvent({
147
+ type: "organization.role.deleted",
148
+ version: 1,
149
+ data: roleDeleted,
150
+ publicData: roleDeleted
151
+ }),
152
+ roleAssigned: defineEvent({
153
+ type: "organization.role.assigned",
154
+ version: 1,
155
+ data: roleAssigned,
156
+ publicData: roleAssigned
157
+ }),
158
+ roleUnassigned: defineEvent({
159
+ type: "organization.role.unassigned",
160
+ version: 1,
161
+ data: roleUnassigned,
162
+ publicData: roleUnassigned
163
+ }),
164
+ ownershipTransferred: defineEvent({
165
+ type: "organization.ownership.transferred",
166
+ version: 1,
167
+ data: ownershipTransferred,
168
+ publicData: ownershipTransferred
169
+ }),
98
170
  studentLinked: defineEvent({
99
171
  type: "organization.student.linked",
100
- version: 1,
172
+ version: 2,
101
173
  data: orgUserSchema,
102
174
  publicData: publicOrgUser
103
175
  })
@@ -1 +1 @@
1
- {"version":3,"file":"events.js","names":[],"sources":["../../src/organizations/events.ts"],"sourcesContent":["import { inviteSchema, organizationSchema, orgUserSchema } from '../types/schemas/index.js';\nimport { defineEvent, type EventOf, type EventOfValues } from '../shared/ports.js';\n\nconst publicOrganization = organizationSchema\n .pick({\n id: true,\n name: true,\n slug: true,\n ownerId: true,\n createdAt: true,\n updatedAt: true,\n })\n .strip();\n\nconst publicOrgUser = orgUserSchema\n .pick({\n id: true,\n orgId: true,\n userId: true,\n role: true,\n status: true,\n createdAt: true,\n updatedAt: true,\n })\n .strip();\n\nconst publicInvite = inviteSchema\n .pick({\n id: true,\n orgId: true,\n email: true,\n role: true,\n status: true,\n invitedBy: true,\n expiresAt: true,\n createdAt: true,\n updatedAt: true,\n })\n .strip();\n\nexport const organizationEvents = {\n organizationCreated: defineEvent({\n type: 'organization.created',\n version: 1,\n data: organizationSchema,\n publicData: publicOrganization,\n }),\n organizationUpdated: defineEvent({\n type: 'organization.updated',\n version: 1,\n data: organizationSchema,\n publicData: publicOrganization,\n }),\n organizationDeleted: defineEvent({\n type: 'organization.deleted',\n version: 1,\n data: organizationSchema,\n publicData: publicOrganization,\n }),\n orgUserLinked: defineEvent({\n type: 'organization.user.linked',\n version: 1,\n data: orgUserSchema,\n publicData: publicOrgUser,\n }),\n orgUserDeleted: defineEvent({\n type: 'organization.user.deleted',\n version: 1,\n data: orgUserSchema,\n publicData: publicOrgUser,\n }),\n orgUserUpdated: defineEvent({\n type: 'organization.user.updated',\n version: 1,\n data: orgUserSchema,\n publicData: publicOrgUser,\n }),\n inviteCreated: defineEvent({\n type: 'organization.invite.created',\n version: 1,\n data: inviteSchema,\n publicData: publicInvite,\n }),\n inviteAccepted: defineEvent({\n type: 'organization.invite.accepted',\n version: 1,\n data: inviteSchema,\n publicData: publicInvite,\n }),\n inviteCanceled: defineEvent({\n type: 'organization.invite.canceled',\n version: 1,\n data: inviteSchema,\n }),\n studentCreated: defineEvent({\n type: 'organization.student.created',\n version: 1,\n data: orgUserSchema,\n publicData: publicOrgUser,\n }),\n studentDeleted: defineEvent({\n type: 'organization.student.deleted',\n version: 1,\n data: orgUserSchema,\n publicData: publicOrgUser,\n }),\n studentLinked: defineEvent({\n type: 'organization.student.linked',\n version: 1,\n data: orgUserSchema,\n publicData: publicOrgUser,\n }),\n};\n\nexport type OrganizationCreated = EventOf<typeof organizationEvents.organizationCreated>;\nexport type OrganizationUpdated = EventOf<typeof organizationEvents.organizationUpdated>;\nexport type OrganizationDeleted = EventOf<typeof organizationEvents.organizationDeleted>;\nexport type OrgUserLinked = EventOf<typeof organizationEvents.orgUserLinked>;\nexport type OrgUserDeleted = EventOf<typeof organizationEvents.orgUserDeleted>;\nexport type OrgUserUpdated = EventOf<typeof organizationEvents.orgUserUpdated>;\nexport type InviteCreated = EventOf<typeof organizationEvents.inviteCreated>;\nexport type InviteAccepted = EventOf<typeof organizationEvents.inviteAccepted>;\nexport type InviteCanceled = EventOf<typeof organizationEvents.inviteCanceled>;\nexport type StudentCreated = EventOf<typeof organizationEvents.studentCreated>;\nexport type StudentDeleted = EventOf<typeof organizationEvents.studentDeleted>;\nexport type StudentLinked = EventOf<typeof organizationEvents.studentLinked>;\nexport type OrganizationEvent = EventOfValues<typeof organizationEvents>;\n"],"mappings":";;;AAGA,MAAM,qBAAqB,mBACxB,KAAK;CACJ,IAAI;CACJ,MAAM;CACN,MAAM;CACN,SAAS;CACT,WAAW;CACX,WAAW;AACb,CAAC,CAAC,CACD,MAAM;AAET,MAAM,gBAAgB,cACnB,KAAK;CACJ,IAAI;CACJ,OAAO;CACP,QAAQ;CACR,MAAM;CACN,QAAQ;CACR,WAAW;CACX,WAAW;AACb,CAAC,CAAC,CACD,MAAM;AAET,MAAM,eAAe,aAClB,KAAK;CACJ,IAAI;CACJ,OAAO;CACP,OAAO;CACP,MAAM;CACN,QAAQ;CACR,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;AACb,CAAC,CAAC,CACD,MAAM;AAET,MAAa,qBAAqB;CAChC,qBAAqB,YAAY;EAC/B,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,qBAAqB,YAAY;EAC/B,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,qBAAqB,YAAY;EAC/B,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,eAAe,YAAY;EACzB,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,gBAAgB,YAAY;EAC1B,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,gBAAgB,YAAY;EAC1B,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,eAAe,YAAY;EACzB,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,gBAAgB,YAAY;EAC1B,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,gBAAgB,YAAY;EAC1B,MAAM;EACN,SAAS;EACT,MAAM;CACR,CAAC;CACD,gBAAgB,YAAY;EAC1B,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,gBAAgB,YAAY;EAC1B,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,eAAe,YAAY;EACzB,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;AACH"}
1
+ {"version":3,"file":"events.js","names":[],"sources":["../../src/organizations/events.ts"],"sourcesContent":["import { z } from 'zod';\nimport {\n contentTypeSchema,\n inviteSchema,\n levelSchema,\n organizationSchema,\n orgUserSchema,\n} from '../types/schemas/index.js';\nimport { defineEvent, type EventOf, type EventOfValues } from '../shared/ports.js';\n\nconst publicOrganization = organizationSchema\n .pick({\n id: true,\n name: true,\n slug: true,\n ownerId: true,\n createdAt: true,\n updatedAt: true,\n })\n .strip();\n\nconst publicOrgUser = orgUserSchema\n .pick({\n id: true,\n orgId: true,\n userId: true,\n status: true,\n createdAt: true,\n updatedAt: true,\n })\n .strip();\n\nconst publicInvite = inviteSchema\n .pick({\n id: true,\n orgId: true,\n email: true,\n roleKey: true,\n status: true,\n invitedBy: true,\n expiresAt: true,\n createdAt: true,\n updatedAt: true,\n })\n .strip();\n\nconst orgUserWithRole = orgUserSchema.extend({ orgRole: z.object({ key: z.string() }) });\nconst publicOrgUserWithRole = publicOrgUser.extend({ orgRole: z.object({ key: z.string() }) });\n\nconst roleSnapshot = z.object({\n key: z.string(),\n name: z.string(),\n description: z.string(),\n base: z.string(),\n levels: z.array(levelSchema),\n team: z.boolean(),\n permissions: z.array(z.string()),\n});\n\nconst roleUpdated = z.object({ key: z.string(), before: roleSnapshot, after: roleSnapshot });\nconst roleCreated = z.object({ role: roleSnapshot });\nconst roleDeleted = z.object({ key: z.string() });\nconst roleAssigned = z.object({\n orgUserId: z.string(),\n roleKey: z.string(),\n contentId: z.string().nullable(),\n contentType: contentTypeSchema.nullable(),\n previousRoleKey: z.string().nullable(),\n});\nconst roleUnassigned = z.object({\n orgUserId: z.string(),\n roleKey: z.string(),\n contentId: z.string(),\n contentType: contentTypeSchema,\n});\nconst ownershipTransferred = z.object({\n previousOwnerOrgUserId: z.string(),\n newOwnerOrgUserId: z.string(),\n});\n\nexport const organizationEvents = {\n organizationCreated: defineEvent({\n type: 'organization.created',\n version: 1,\n data: organizationSchema,\n publicData: publicOrganization,\n }),\n organizationUpdated: defineEvent({\n type: 'organization.updated',\n version: 1,\n data: organizationSchema,\n publicData: publicOrganization,\n }),\n organizationDeleted: defineEvent({\n type: 'organization.deleted',\n version: 1,\n data: organizationSchema,\n publicData: publicOrganization,\n }),\n orgUserLinked: defineEvent({\n type: 'organization.user.linked',\n version: 2,\n data: orgUserWithRole,\n publicData: publicOrgUserWithRole,\n }),\n orgUserDeleted: defineEvent({\n type: 'organization.user.deleted',\n version: 2,\n data: orgUserWithRole,\n publicData: publicOrgUserWithRole,\n }),\n orgUserUpdated: defineEvent({\n type: 'organization.user.updated',\n version: 2,\n data: orgUserWithRole,\n publicData: publicOrgUserWithRole,\n }),\n inviteCreated: defineEvent({\n type: 'organization.invite.created',\n version: 2,\n data: inviteSchema,\n publicData: publicInvite,\n }),\n inviteAccepted: defineEvent({\n type: 'organization.invite.accepted',\n version: 2,\n data: inviteSchema,\n publicData: publicInvite,\n }),\n inviteCanceled: defineEvent({\n type: 'organization.invite.canceled',\n version: 2,\n data: inviteSchema,\n }),\n studentCreated: defineEvent({\n type: 'organization.student.created',\n version: 2,\n data: orgUserSchema,\n publicData: publicOrgUser,\n }),\n studentDeleted: defineEvent({\n type: 'organization.student.deleted',\n version: 2,\n data: orgUserSchema,\n publicData: publicOrgUser,\n }),\n roleUpdated: defineEvent({\n type: 'organization.role.updated',\n version: 1,\n data: roleUpdated,\n publicData: roleUpdated,\n }),\n roleCreated: defineEvent({\n type: 'organization.role.created',\n version: 1,\n data: roleCreated,\n publicData: roleCreated,\n }),\n roleDeleted: defineEvent({\n type: 'organization.role.deleted',\n version: 1,\n data: roleDeleted,\n publicData: roleDeleted,\n }),\n roleAssigned: defineEvent({\n type: 'organization.role.assigned',\n version: 1,\n data: roleAssigned,\n publicData: roleAssigned,\n }),\n roleUnassigned: defineEvent({\n type: 'organization.role.unassigned',\n version: 1,\n data: roleUnassigned,\n publicData: roleUnassigned,\n }),\n ownershipTransferred: defineEvent({\n type: 'organization.ownership.transferred',\n version: 1,\n data: ownershipTransferred,\n publicData: ownershipTransferred,\n }),\n studentLinked: defineEvent({\n type: 'organization.student.linked',\n version: 2,\n data: orgUserSchema,\n publicData: publicOrgUser,\n }),\n};\n\nexport type OrganizationCreated = EventOf<typeof organizationEvents.organizationCreated>;\nexport type OrganizationUpdated = EventOf<typeof organizationEvents.organizationUpdated>;\nexport type OrganizationDeleted = EventOf<typeof organizationEvents.organizationDeleted>;\nexport type OrgUserLinked = EventOf<typeof organizationEvents.orgUserLinked>;\nexport type OrgUserDeleted = EventOf<typeof organizationEvents.orgUserDeleted>;\nexport type OrgUserUpdated = EventOf<typeof organizationEvents.orgUserUpdated>;\nexport type InviteCreated = EventOf<typeof organizationEvents.inviteCreated>;\nexport type InviteAccepted = EventOf<typeof organizationEvents.inviteAccepted>;\nexport type InviteCanceled = EventOf<typeof organizationEvents.inviteCanceled>;\nexport type StudentCreated = EventOf<typeof organizationEvents.studentCreated>;\nexport type StudentDeleted = EventOf<typeof organizationEvents.studentDeleted>;\nexport type StudentLinked = EventOf<typeof organizationEvents.studentLinked>;\nexport type RoleUpdated = EventOf<typeof organizationEvents.roleUpdated>;\nexport type RoleCreated = EventOf<typeof organizationEvents.roleCreated>;\nexport type RoleDeleted = EventOf<typeof organizationEvents.roleDeleted>;\nexport type RoleAssigned = EventOf<typeof organizationEvents.roleAssigned>;\nexport type RoleUnassigned = EventOf<typeof organizationEvents.roleUnassigned>;\nexport type OwnershipTransferred = EventOf<typeof organizationEvents.ownershipTransferred>;\nexport type OrganizationEvent = EventOfValues<typeof organizationEvents>;\n"],"mappings":";;;;;AAUA,MAAM,qBAAqB,mBACxB,KAAK;CACJ,IAAI;CACJ,MAAM;CACN,MAAM;CACN,SAAS;CACT,WAAW;CACX,WAAW;AACb,CAAC,CAAC,CACD,MAAM;AAET,MAAM,gBAAgB,cACnB,KAAK;CACJ,IAAI;CACJ,OAAO;CACP,QAAQ;CACR,QAAQ;CACR,WAAW;CACX,WAAW;AACb,CAAC,CAAC,CACD,MAAM;AAET,MAAM,eAAe,aAClB,KAAK;CACJ,IAAI;CACJ,OAAO;CACP,OAAO;CACP,SAAS;CACT,QAAQ;CACR,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;AACb,CAAC,CAAC,CACD,MAAM;AAET,MAAM,kBAAkB,cAAc,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;AACvF,MAAM,wBAAwB,cAAc,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;AAE7F,MAAM,eAAe,EAAE,OAAO;CAC5B,KAAK,EAAE,OAAO;CACd,MAAM,EAAE,OAAO;CACf,aAAa,EAAE,OAAO;CACtB,MAAM,EAAE,OAAO;CACf,QAAQ,EAAE,MAAM,WAAW;CAC3B,MAAM,EAAE,QAAQ;CAChB,aAAa,EAAE,MAAM,EAAE,OAAO,CAAC;AACjC,CAAC;AAED,MAAM,cAAc,EAAE,OAAO;CAAE,KAAK,EAAE,OAAO;CAAG,QAAQ;CAAc,OAAO;AAAa,CAAC;AAC3F,MAAM,cAAc,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACnD,MAAM,cAAc,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAChD,MAAM,eAAe,EAAE,OAAO;CAC5B,WAAW,EAAE,OAAO;CACpB,SAAS,EAAE,OAAO;CAClB,WAAW,EAAE,OAAO,CAAC,CAAC,SAAS;CAC/B,aAAa,kBAAkB,SAAS;CACxC,iBAAiB,EAAE,OAAO,CAAC,CAAC,SAAS;AACvC,CAAC;AACD,MAAM,iBAAiB,EAAE,OAAO;CAC9B,WAAW,EAAE,OAAO;CACpB,SAAS,EAAE,OAAO;CAClB,WAAW,EAAE,OAAO;CACpB,aAAa;AACf,CAAC;AACD,MAAM,uBAAuB,EAAE,OAAO;CACpC,wBAAwB,EAAE,OAAO;CACjC,mBAAmB,EAAE,OAAO;AAC9B,CAAC;AAED,MAAa,qBAAqB;CAChC,qBAAqB,YAAY;EAC/B,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,qBAAqB,YAAY;EAC/B,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,qBAAqB,YAAY;EAC/B,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,eAAe,YAAY;EACzB,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,gBAAgB,YAAY;EAC1B,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,gBAAgB,YAAY;EAC1B,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,eAAe,YAAY;EACzB,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,gBAAgB,YAAY;EAC1B,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,gBAAgB,YAAY;EAC1B,MAAM;EACN,SAAS;EACT,MAAM;CACR,CAAC;CACD,gBAAgB,YAAY;EAC1B,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,gBAAgB,YAAY;EAC1B,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,aAAa,YAAY;EACvB,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,aAAa,YAAY;EACvB,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,aAAa,YAAY;EACvB,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,cAAc,YAAY;EACxB,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,gBAAgB,YAAY;EAC1B,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,sBAAsB,YAAY;EAChC,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CACD,eAAe,YAAY;EACzB,MAAM;EACN,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;AACH"}
@@ -1,12 +1,17 @@
1
- import { AcceptInviteInput, AddOrgUserInput, CreateInviteInput, CreateOrgUserInput, Invite, InviteRole, NewOrganizationInput, OrgUser, OrgUserStatus, Organization, Role, UpdateOrgUserInput } from "../types/schemas/organizations.js";
1
+ import { AcceptInviteInput, AddOrgUserInput, CreateInviteInput, CreateOrgUserInput, Invite, NewOrganizationInput, OrgUser, OrgUserStatus, Organization, UpdateOrgUserInput } from "../types/schemas/organizations.js";
2
2
  import { InviteId, OrgUserId, OrganizationId } from "../types/organizations.js";
3
- import "./model.js";
4
- import { Capability, Permission, ROLES, STAFF_ROLES, STUDENT_ROLE, StaffRole, TeamRole, canModerate, capability, isRole, isStaffRole, normalizeRole, parseRole } from "./roles.js";
5
- import { InviteError, Member, MemberRoleChange, MemberStatus, MembersQuery, OrganizationRuleError, Page } from "./members.js";
6
- import { CreateOrganizationInput, LinkOrgUserInput, ResendStudentInviteInput, UnlinkOrgUserInput, UpdateOrganizationInput } from "./types.js";
7
3
  import { AuthHeaders } from "../identity/ports.js";
8
- import { AuthOrganization, MemberRecord, MemberWriteContext, MembersRepository, NewInviteRow, NewOrganizationRow, OrgAdmin, OrganizationService, OrganizationsRepository } from "./ports.js";
9
- import { OrganizationServiceImpl } from "./service.js";
10
- import { InviteAccepted, InviteCanceled, InviteCreated, OrgUserDeleted, OrgUserLinked, OrgUserUpdated, OrganizationCreated, OrganizationDeleted, OrganizationEvent, OrganizationUpdated, StudentCreated, StudentDeleted, StudentLinked, organizationEvents } from "./events.js";
11
- import { ACCESS_SCOPES, AccessScope, SCOPE_PERMISSION, ScopeOption, assertRoleHoldsScopes, isAccessScope, isDeleteScope, roleHoldsScope, scopeOptions, scopesForRole } from "./access-scopes.js";
12
- export { ACCESS_SCOPES, type AcceptInviteInput, AccessScope, type AddOrgUserInput, type AuthHeaders, type AuthOrganization, type Capability, type CreateInviteInput, type CreateOrgUserInput, type CreateOrganizationInput, type Invite, type InviteAccepted, type InviteCanceled, type InviteCreated, InviteError, type InviteId, type InviteRole, type LinkOrgUserInput, type Member, type MemberRecord, type MemberRoleChange, type MemberStatus, type MemberWriteContext, type MembersQuery, type MembersRepository, type NewInviteRow, type NewOrganizationInput, type NewOrganizationRow, type OrgAdmin, type OrgUser, type OrgUserDeleted, type OrgUserId, type OrgUserLinked, type OrgUserStatus, type OrgUserUpdated, type Organization, type OrganizationCreated, type OrganizationDeleted, type OrganizationEvent, type OrganizationId, OrganizationRuleError, type OrganizationService, OrganizationServiceImpl, type OrganizationUpdated, type OrganizationsRepository, type Page, type Permission, ROLES, type ResendStudentInviteInput, type Role, SCOPE_PERMISSION, STAFF_ROLES, STUDENT_ROLE, ScopeOption, type StaffRole, type StudentCreated, type StudentDeleted, type StudentLinked, type TeamRole, type UnlinkOrgUserInput, type UpdateOrgUserInput, type UpdateOrganizationInput, assertRoleHoldsScopes, canModerate, capability, isAccessScope, isDeleteScope, isRole, isStaffRole, normalizeRole, organizationEvents, parseRole, roleHoldsScope, scopeOptions, scopesForRole };
4
+ import { DEFAULT_ROLES, MEMBER_ROLE_KEY, OWNER_ROLE_KEY, RoleDefinition, RoleSetError, defaultHolders, validateRoleSet } from "./default-roles.js";
5
+ import { OrgRole, RoleCatalog, StoredOrgRole, catalogOf, isSystemRole, resolveOrgRoles, resolveRole } from "./org-roles.js";
6
+ import { AssignmentRow, ResolveInput, ResolvedPermissions, resolvePermissions, systemPermissions } from "./effective-permissions.js";
7
+ import { InviteAccepted, InviteCanceled, InviteCreated, OrgUserDeleted, OrgUserLinked, OrgUserUpdated, OrganizationCreated, OrganizationDeleted, OrganizationEvent, OrganizationUpdated, OwnershipTransferred, RoleAssigned, RoleCreated, RoleDeleted, RoleUnassigned, RoleUpdated, StudentCreated, StudentDeleted, StudentLinked, organizationEvents } from "./events.js";
8
+ import "./model.js";
9
+ import { AssignmentView, CreateRoleInput, InviteDetails, InviteError, ItemRole, Member, MemberStatus, MembersQuery, OrganizationRuleError, Page, RoleView, UpdateRoleInput, ViewerPermissions } from "./members.js";
10
+ import { ALL_PERMISSIONS, PERMISSIONS, PermissionDefinition, PermissionGroup, PermissionListEntry, fitsLevels, isPermission, permissionList, withImplied } from "./permissions.js";
11
+ import { CreateOrganizationInput, UpdateOrganizationInput } from "./types.js";
12
+ import { Accounts, ActorFacts, ApiKeyRole, ApiKeys, AuthOrganization, CallerFacts, CallerLimit, CreateApiKeyInput, GrantReader, MembersRepository, NewApiKey, NewInviteRow, NewOrganizationRow, OrgAdmin, OrganizationService, OrganizationsRepository, OrganizationsUnitOfWork, OrganizationsWriteScope, PlatformAccount, PlatformOrganization, PlatformOrganizationInput, ResolvedCaller, RolesRepository, StoredApiKey, TeamRow, TransferOwnershipInput } from "./ports.js";
13
+ import { InviteUrls, OrganizationServiceImpl, OrganizationServiceParams } from "./service.js";
14
+ import { OrgNotificationCategories } from "./notification-categories.js";
15
+ import { NotificationCatalog, NotificationCatalogParams, NotificationCatalogService } from "./notification-catalog.js";
16
+ import { ActorShape, actorWith } from "./testing.js";
17
+ export { ALL_PERMISSIONS, type AcceptInviteInput, type Accounts, type ActorFacts, type ActorShape, type AddOrgUserInput, type ApiKeyRole, type ApiKeys, type AssignmentRow, type AssignmentView, type AuthHeaders, type AuthOrganization, type CallerFacts, type CallerLimit, type CreateApiKeyInput, type CreateInviteInput, type CreateOrgUserInput, type CreateOrganizationInput, type CreateRoleInput, DEFAULT_ROLES, type GrantReader, type Invite, type InviteAccepted, type InviteCanceled, type InviteCreated, type InviteDetails, InviteError, type InviteId, type InviteUrls, type ItemRole, MEMBER_ROLE_KEY, type Member, type MemberStatus, type MembersQuery, type MembersRepository, type NewApiKey, type NewInviteRow, type NewOrganizationInput, type NewOrganizationRow, NotificationCatalog, type NotificationCatalogParams, type NotificationCatalogService, OWNER_ROLE_KEY, type OrgAdmin, OrgNotificationCategories, type OrgRole, type OrgUser, type OrgUserDeleted, type OrgUserId, type OrgUserLinked, type OrgUserStatus, type OrgUserUpdated, type Organization, type OrganizationCreated, type OrganizationDeleted, type OrganizationEvent, type OrganizationId, OrganizationRuleError, type OrganizationService, OrganizationServiceImpl, type OrganizationServiceParams, type OrganizationUpdated, type OrganizationsRepository, type OrganizationsUnitOfWork, type OrganizationsWriteScope, type OwnershipTransferred, PERMISSIONS, type Page, type PermissionDefinition, type PermissionGroup, type PermissionListEntry, type PlatformAccount, type PlatformOrganization, type PlatformOrganizationInput, type ResolveInput, type ResolvedCaller, ResolvedPermissions, type RoleAssigned, type RoleCatalog, type RoleCreated, type RoleDefinition, type RoleDeleted, RoleSetError, type RoleUnassigned, type RoleUpdated, type RoleView, type RolesRepository, type StoredApiKey, type StoredOrgRole, type StudentCreated, type StudentDeleted, type StudentLinked, type TeamRow, type TransferOwnershipInput, type UpdateOrgUserInput, type UpdateOrganizationInput, type UpdateRoleInput, type ViewerPermissions, actorWith, catalogOf, defaultHolders, fitsLevels, isPermission, isSystemRole, organizationEvents, permissionList, resolveOrgRoles, resolvePermissions, resolveRole, systemPermissions, validateRoleSet, withImplied };
@@ -1,6 +1,11 @@
1
- import { ROLES, STAFF_ROLES, STUDENT_ROLE, canModerate, capability, isRole, isStaffRole, normalizeRole, parseRole } from "./roles.js";
2
1
  import { InviteError, OrganizationRuleError } from "./members.js";
3
2
  import { organizationEvents } from "./events.js";
3
+ import { ALL_PERMISSIONS, PERMISSIONS, fitsLevels, isPermission, permissionList, withImplied } from "./permissions.js";
4
+ import { DEFAULT_ROLES, MEMBER_ROLE_KEY, OWNER_ROLE_KEY, RoleSetError, defaultHolders, validateRoleSet } from "./default-roles.js";
5
+ import { catalogOf, isSystemRole, resolveOrgRoles, resolveRole } from "./org-roles.js";
6
+ import { ResolvedPermissions, resolvePermissions, systemPermissions } from "./effective-permissions.js";
4
7
  import { OrganizationServiceImpl } from "./service.js";
5
- import { ACCESS_SCOPES, SCOPE_PERMISSION, assertRoleHoldsScopes, isAccessScope, isDeleteScope, roleHoldsScope, scopeOptions, scopesForRole } from "./access-scopes.js";
6
- export { ACCESS_SCOPES, InviteError, OrganizationRuleError, OrganizationServiceImpl, ROLES, SCOPE_PERMISSION, STAFF_ROLES, STUDENT_ROLE, assertRoleHoldsScopes, canModerate, capability, isAccessScope, isDeleteScope, isRole, isStaffRole, normalizeRole, organizationEvents, parseRole, roleHoldsScope, scopeOptions, scopesForRole };
8
+ import { OrgNotificationCategories } from "./notification-categories.js";
9
+ import { NotificationCatalog } from "./notification-catalog.js";
10
+ import { actorWith } from "./testing.js";
11
+ export { ALL_PERMISSIONS, DEFAULT_ROLES, InviteError, MEMBER_ROLE_KEY, NotificationCatalog, OWNER_ROLE_KEY, OrgNotificationCategories, OrganizationRuleError, OrganizationServiceImpl, PERMISSIONS, ResolvedPermissions, RoleSetError, actorWith, catalogOf, defaultHolders, fitsLevels, isPermission, isSystemRole, organizationEvents, permissionList, resolveOrgRoles, resolvePermissions, resolveRole, systemPermissions, validateRoleSet, withImplied };
@@ -1,23 +1,31 @@
1
- import { OrgUserProfile, Role } from "../types/schemas/organizations.js";
1
+ import { ContentType } from "../types/schemas/content.js";
2
+ import { Level, OrgUserProfile, Permission } from "../types/schemas/organizations.js";
2
3
  import "../types/index.js";
3
- import { TeamRole } from "./roles.js";
4
4
  //#region src/organizations/members.d.ts
5
5
  type MemberStatus = 'active' | 'invited';
6
+ interface ItemRole {
7
+ contentId: string;
8
+ contentType: ContentType;
9
+ roleKey: string;
10
+ roleName: string;
11
+ }
6
12
  interface Member extends OrgUserProfile {
7
- role: TeamRole;
13
+ orgRole: {
14
+ key: string;
15
+ name: string;
16
+ };
17
+ isOwner: boolean;
18
+ items: ItemRole[];
8
19
  status: MemberStatus;
9
20
  joinedAt: string | null;
10
21
  invitedAt: string | null;
11
22
  }
12
- interface MemberRoleChange extends Omit<Member, 'role'> {
13
- role: Role;
14
- }
15
23
  interface MembersQuery {
16
24
  page: number;
17
25
  pageSize: number;
18
26
  search?: string | undefined;
19
27
  sort?: string | undefined;
20
- role?: TeamRole | undefined;
28
+ roleKey?: string | undefined;
21
29
  status?: MemberStatus | undefined;
22
30
  }
23
31
  interface Page<T> {
@@ -26,10 +34,60 @@ interface Page<T> {
26
34
  page: number;
27
35
  pageSize: number;
28
36
  }
37
+ interface RoleView {
38
+ key: string;
39
+ name: string;
40
+ description: string;
41
+ base: string;
42
+ levels: Level[];
43
+ team: boolean;
44
+ permissions: Permission[];
45
+ system: boolean;
46
+ added: boolean;
47
+ customized: boolean;
48
+ holders: number;
49
+ givable: boolean;
50
+ }
51
+ interface UpdateRoleInput {
52
+ name?: string | undefined;
53
+ description?: string | undefined;
54
+ levels?: Level[] | undefined;
55
+ team?: boolean | undefined;
56
+ permissions?: Partial<Record<Permission, boolean>> | undefined;
57
+ }
58
+ interface CreateRoleInput {
59
+ base: string;
60
+ name: string;
61
+ description?: string | undefined;
62
+ levels?: Level[] | undefined;
63
+ team?: boolean | undefined;
64
+ permissions?: Partial<Record<Permission, boolean>> | undefined;
65
+ }
66
+ interface AssignmentView {
67
+ orgUserId: string;
68
+ roleKey: string;
69
+ roleName: string;
70
+ contentId: string | null;
71
+ contentType: ContentType | null;
72
+ }
73
+ interface ViewerPermissions {
74
+ orgRole: {
75
+ key: string;
76
+ name: string;
77
+ };
78
+ isOwner: boolean;
79
+ org: Permission[];
80
+ content: Record<string, Permission[]>;
81
+ }
82
+ interface InviteDetails {
83
+ email: string;
84
+ firstName: string | null;
85
+ lastName: string | null;
86
+ }
29
87
  declare class OrganizationRuleError extends Error {}
30
88
  declare class InviteError extends Error {
31
89
  constructor(message: string);
32
90
  }
33
91
  //#endregion
34
- export { InviteError, Member, MemberRoleChange, MemberStatus, MembersQuery, OrganizationRuleError, Page };
92
+ export { AssignmentView, CreateRoleInput, InviteDetails, InviteError, ItemRole, Member, MemberStatus, MembersQuery, OrganizationRuleError, Page, RoleView, UpdateRoleInput, ViewerPermissions };
35
93
  //# sourceMappingURL=members.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"members.js","names":[],"sources":["../../src/organizations/members.ts"],"sourcesContent":["// organizations context — member-management types (invite / change-role / remove).\n// The operational surface over the org's members and pending invites. Roles\n// come from ./roles.ts (the single role model); writes go through Better Auth.\nimport type { Role, TeamRole } from './roles.js';\nimport type { OrgUserProfile } from '../types/index.js';\n\nexport type MemberStatus = 'active' | 'invited';\n\nexport interface Member extends OrgUserProfile {\n role: TeamRole;\n status: MemberStatus;\n joinedAt: string | null;\n invitedAt: string | null;\n}\n\nexport interface MemberRoleChange extends Omit<Member, 'role'> {\n role: Role;\n}\n\nexport interface MembersQuery {\n page: number;\n pageSize: number;\n search?: string | undefined;\n sort?: string | undefined;\n role?: TeamRole | undefined;\n status?: MemberStatus | undefined;\n}\n\nexport interface Page<T> {\n rows: T[];\n total: number;\n page: number;\n pageSize: number;\n}\n\nexport class OrganizationRuleError extends Error {}\nexport class InviteError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'InviteError';\n }\n}\n"],"mappings":";AAmCA,IAAa,wBAAb,cAA2C,MAAM,CAAC;AAClD,IAAa,cAAb,cAAiC,MAAM;CACrC,YAAY,SAAiB;EAC3B,MAAM,OAAO;EACb,KAAK,OAAO;CACd;AACF"}
1
+ {"version":3,"file":"members.js","names":[],"sources":["../../src/organizations/members.ts"],"sourcesContent":["import type { ContentType, Level, OrgUserProfile, Permission } from '../types/index.js';\n\nexport type MemberStatus = 'active' | 'invited';\n\nexport interface ItemRole {\n contentId: string;\n contentType: ContentType;\n roleKey: string;\n roleName: string;\n}\n\nexport interface Member extends OrgUserProfile {\n orgRole: { key: string; name: string };\n isOwner: boolean;\n items: ItemRole[];\n status: MemberStatus;\n joinedAt: string | null;\n invitedAt: string | null;\n}\n\nexport interface MembersQuery {\n page: number;\n pageSize: number;\n search?: string | undefined;\n sort?: string | undefined;\n roleKey?: string | undefined;\n status?: MemberStatus | undefined;\n}\n\nexport interface Page<T> {\n rows: T[];\n total: number;\n page: number;\n pageSize: number;\n}\n\nexport interface RoleView {\n key: string;\n name: string;\n description: string;\n base: string;\n levels: Level[];\n team: boolean;\n permissions: Permission[];\n system: boolean;\n added: boolean;\n customized: boolean;\n holders: number;\n givable: boolean;\n}\n\nexport interface UpdateRoleInput {\n name?: string | undefined;\n description?: string | undefined;\n levels?: Level[] | undefined;\n team?: boolean | undefined;\n permissions?: Partial<Record<Permission, boolean>> | undefined;\n}\n\nexport interface CreateRoleInput {\n base: string;\n name: string;\n description?: string | undefined;\n levels?: Level[] | undefined;\n team?: boolean | undefined;\n permissions?: Partial<Record<Permission, boolean>> | undefined;\n}\n\nexport interface AssignmentView {\n orgUserId: string;\n roleKey: string;\n roleName: string;\n contentId: string | null;\n contentType: ContentType | null;\n}\n\nexport interface ViewerPermissions {\n orgRole: { key: string; name: string };\n isOwner: boolean;\n org: Permission[];\n content: Record<string, Permission[]>;\n}\n\nexport interface InviteDetails {\n email: string;\n firstName: string | null;\n lastName: string | null;\n}\n\nexport class OrganizationRuleError extends Error {}\nexport class InviteError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'InviteError';\n }\n}\n"],"mappings":";AAyFA,IAAa,wBAAb,cAA2C,MAAM,CAAC;AAClD,IAAa,cAAb,cAAiC,MAAM;CACrC,YAAY,SAAiB;EAC3B,MAAM,OAAO;EACb,KAAK,OAAO;CACd;AACF"}
@@ -0,0 +1,31 @@
1
+ import { NotificationCategory, NotificationTypeDeclaration } from "../types/notifications.js";
2
+ import "../types/index.js";
3
+ import { Actor } from "../shared/actor.js";
4
+ import { ChannelRegistry, NotificationTypeRegistry } from "../shared/ports.js";
5
+ import { CategoryListScope } from "../shared/notification-categories.js";
6
+ //#region src/organizations/notification-catalog.d.ts
7
+ interface NotificationCatalogService {
8
+ types(actor: Actor, scope: CategoryListScope): Pick<NotificationTypeDeclaration, 'type' | 'scopes' | 'reasons'>[];
9
+ channels(actor: Actor): {
10
+ channel: string;
11
+ }[];
12
+ defaults(actor: Actor, scope: CategoryListScope): NotificationCategory[];
13
+ }
14
+ type NotificationCatalogParams = {
15
+ types: NotificationTypeRegistry;
16
+ channels: Pick<ChannelRegistry, 'list'>;
17
+ };
18
+ declare class NotificationCatalog implements NotificationCatalogService {
19
+ private readonly registry;
20
+ private readonly channelRegistry;
21
+ constructor(params: NotificationCatalogParams);
22
+ types(actor: Actor, scope: CategoryListScope): Pick<NotificationTypeDeclaration, 'type' | 'scopes' | 'reasons'>[];
23
+ channels(actor: Actor): {
24
+ channel: string;
25
+ }[];
26
+ defaults(actor: Actor, scope: CategoryListScope): NotificationCategory[];
27
+ private requireFor;
28
+ }
29
+ //#endregion
30
+ export { NotificationCatalog, NotificationCatalogParams, NotificationCatalogService };
31
+ //# sourceMappingURL=notification-catalog.d.ts.map
@@ -0,0 +1,32 @@
1
+ import { ForbiddenError } from "../shared/errors.js";
2
+ import { typesForList } from "../shared/notification-categories.js";
3
+ //#region src/organizations/notification-catalog.ts
4
+ var NotificationCatalog = class {
5
+ registry;
6
+ channelRegistry;
7
+ constructor(params) {
8
+ this.registry = params.types;
9
+ this.channelRegistry = params.channels;
10
+ }
11
+ types(actor, scope) {
12
+ this.requireFor(actor, scope);
13
+ return typesForList(this.registry, scope);
14
+ }
15
+ channels(actor) {
16
+ this.requireFor(actor, "community");
17
+ return this.channelRegistry.list().map((channel) => ({ channel }));
18
+ }
19
+ defaults(actor, scope) {
20
+ this.requireFor(actor, scope);
21
+ return this.registry.defaults(scope);
22
+ }
23
+ requireFor(actor, scope) {
24
+ if (actor.permissions.has("notification_categories:read")) return;
25
+ if (scope === "community" && actor.permissions.anywhere("communities:read")) return;
26
+ throw new ForbiddenError(scope === "org" ? "You need notification_categories:read" : "You need notification_categories:read or communities:read");
27
+ }
28
+ };
29
+ //#endregion
30
+ export { NotificationCatalog };
31
+
32
+ //# sourceMappingURL=notification-catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notification-catalog.js","names":[],"sources":["../../src/organizations/notification-catalog.ts"],"sourcesContent":["import type { NotificationCategory, NotificationTypeDeclaration } from '../types/index.js';\nimport type { ChannelRegistry, NotificationTypeRegistry } from '../shared/ports.js';\nimport type { Actor } from '../shared/actor.js';\nimport { ForbiddenError } from '../shared/errors.js';\nimport { typesForList, type CategoryListScope } from '../shared/notification-categories.js';\n\nexport interface NotificationCatalogService {\n types(\n actor: Actor,\n scope: CategoryListScope,\n ): Pick<NotificationTypeDeclaration, 'type' | 'scopes' | 'reasons'>[];\n channels(actor: Actor): { channel: string }[];\n defaults(actor: Actor, scope: CategoryListScope): NotificationCategory[];\n}\n\nexport type NotificationCatalogParams = {\n types: NotificationTypeRegistry;\n channels: Pick<ChannelRegistry, 'list'>;\n};\n\nexport class NotificationCatalog implements NotificationCatalogService {\n private readonly registry: NotificationTypeRegistry;\n private readonly channelRegistry: Pick<ChannelRegistry, 'list'>;\n\n constructor(params: NotificationCatalogParams) {\n this.registry = params.types;\n this.channelRegistry = params.channels;\n }\n\n types(\n actor: Actor,\n scope: CategoryListScope,\n ): Pick<NotificationTypeDeclaration, 'type' | 'scopes' | 'reasons'>[] {\n this.requireFor(actor, scope);\n return typesForList(this.registry, scope);\n }\n\n channels(actor: Actor): { channel: string }[] {\n this.requireFor(actor, 'community');\n return this.channelRegistry.list().map((channel) => ({ channel }));\n }\n\n defaults(actor: Actor, scope: CategoryListScope): NotificationCategory[] {\n this.requireFor(actor, scope);\n return this.registry.defaults(scope);\n }\n\n private requireFor(actor: Actor, scope: CategoryListScope): void {\n if (actor.permissions.has('notification_categories:read')) {\n return;\n }\n if (scope === 'community' && actor.permissions.anywhere('communities:read')) {\n return;\n }\n throw new ForbiddenError(\n scope === 'org'\n ? 'You need notification_categories:read'\n : 'You need notification_categories:read or communities:read',\n );\n }\n}\n"],"mappings":";;;AAoBA,IAAa,sBAAb,MAAuE;CACrE;CACA;CAEA,YAAY,QAAmC;EAC7C,KAAK,WAAW,OAAO;EACvB,KAAK,kBAAkB,OAAO;CAChC;CAEA,MACE,OACA,OACoE;EACpE,KAAK,WAAW,OAAO,KAAK;EAC5B,OAAO,aAAa,KAAK,UAAU,KAAK;CAC1C;CAEA,SAAS,OAAqC;EAC5C,KAAK,WAAW,OAAO,WAAW;EAClC,OAAO,KAAK,gBAAgB,KAAK,CAAC,CAAC,KAAK,aAAa,EAAE,QAAQ,EAAE;CACnE;CAEA,SAAS,OAAc,OAAkD;EACvE,KAAK,WAAW,OAAO,KAAK;EAC5B,OAAO,KAAK,SAAS,SAAS,KAAK;CACrC;CAEA,WAAmB,OAAc,OAAgC;EAC/D,IAAI,MAAM,YAAY,IAAI,8BAA8B,GACtD;EAEF,IAAI,UAAU,eAAe,MAAM,YAAY,SAAS,kBAAkB,GACxE;EAEF,MAAM,IAAI,eACR,UAAU,QACN,0CACA,2DACN;CACF;AACF"}
@@ -0,0 +1,34 @@
1
+ import { Logger } from "../types/ports.js";
2
+ import { NotificationCategory } from "../types/notifications.js";
3
+ import "../types/index.js";
4
+ import { Actor } from "../shared/actor.js";
5
+ import { ChannelRegistry, NotificationCategoryService, NotificationTypeRegistry } from "../shared/ports.js";
6
+ import { SettingsService } from "../shared/settings.js";
7
+ //#region src/organizations/notification-categories.d.ts
8
+ type OrgNotificationCategoriesParams = {
9
+ settings: SettingsService;
10
+ types: NotificationTypeRegistry;
11
+ channels: ChannelRegistry;
12
+ logger?: Logger;
13
+ };
14
+ declare class OrgNotificationCategories implements NotificationCategoryService {
15
+ private readonly settings;
16
+ private readonly types;
17
+ private readonly channels;
18
+ private readonly logger;
19
+ constructor(params: OrgNotificationCategoriesParams);
20
+ get(scopeId: string, actor: Actor): Promise<{
21
+ categories: NotificationCategory[];
22
+ source: 'default' | 'stored';
23
+ }>;
24
+ replace(scopeId: string, categories: NotificationCategory[], actor: Actor): Promise<{
25
+ categories: NotificationCategory[];
26
+ source: 'stored';
27
+ }>;
28
+ reset(scopeId: string, actor: Actor): Promise<void>;
29
+ defaults(actor: Actor): NotificationCategory[];
30
+ private assertOrg;
31
+ }
32
+ //#endregion
33
+ export { OrgNotificationCategories, OrgNotificationCategoriesParams };
34
+ //# sourceMappingURL=notification-categories.d.ts.map
@@ -0,0 +1,66 @@
1
+ import { noopLogger } from "../shared/logger.js";
2
+ import { NotFoundError } from "../shared/errors.js";
3
+ import "../shared/settings.js";
4
+ import { assertValidCategoryList, offeringConfigured, storedCategoryList } from "../shared/notification-categories.js";
5
+ //#region src/organizations/notification-categories.ts
6
+ var OrgNotificationCategories = class {
7
+ settings;
8
+ types;
9
+ channels;
10
+ logger;
11
+ constructor(params) {
12
+ this.settings = params.settings;
13
+ this.types = params.types;
14
+ this.channels = params.channels;
15
+ this.logger = params.logger ?? noopLogger;
16
+ }
17
+ async get(scopeId, actor) {
18
+ actor.permissions.require("notification_categories:read");
19
+ this.assertOrg(scopeId, actor);
20
+ const stored = storedCategoryList((await this.settings.get(actor.orgId, "organizations", scopeId))?.notificationCategories);
21
+ return stored ? {
22
+ categories: offeringConfigured(stored, this.channels.list()),
23
+ source: "stored"
24
+ } : {
25
+ categories: this.types.defaults("org"),
26
+ source: "default"
27
+ };
28
+ }
29
+ async replace(scopeId, categories, actor) {
30
+ actor.permissions.require("notification_categories:write");
31
+ this.assertOrg(scopeId, actor);
32
+ const configured = this.channels.list();
33
+ assertValidCategoryList(categories, "org", this.types, configured);
34
+ const ordered = offeringConfigured(categories, configured);
35
+ await this.settings.patch(actor.orgId, "organizations", scopeId, { notificationCategories: ordered });
36
+ this.logger.info("org notification categories replaced", {
37
+ orgId: actor.orgId,
38
+ orgUserId: actor.id,
39
+ keys: categories.map((category) => category.key)
40
+ });
41
+ return {
42
+ categories: ordered,
43
+ source: "stored"
44
+ };
45
+ }
46
+ async reset(scopeId, actor) {
47
+ actor.permissions.require("notification_categories:write");
48
+ this.assertOrg(scopeId, actor);
49
+ await this.settings.patch(actor.orgId, "organizations", scopeId, { notificationCategories: null });
50
+ this.logger.info("org notification categories reset", {
51
+ orgId: actor.orgId,
52
+ orgUserId: actor.id
53
+ });
54
+ }
55
+ defaults(actor) {
56
+ actor.permissions.require("notification_categories:read");
57
+ return this.types.defaults("org");
58
+ }
59
+ assertOrg(scopeId, actor) {
60
+ if (scopeId !== actor.orgId) throw new NotFoundError("Organization", scopeId);
61
+ }
62
+ };
63
+ //#endregion
64
+ export { OrgNotificationCategories };
65
+
66
+ //# sourceMappingURL=notification-categories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notification-categories.js","names":[],"sources":["../../src/organizations/notification-categories.ts"],"sourcesContent":["import type { NotificationCategory } from '../types/index.js';\nimport type {\n ChannelRegistry,\n Logger,\n NotificationCategoryService,\n NotificationTypeRegistry,\n} from '../shared/ports.js';\nimport type { Actor } from '../shared/actor.js';\nimport { NotFoundError } from '../shared/errors.js';\nimport { noopLogger } from '../shared/logger.js';\nimport { SettingsNamespace, type SettingsService } from '../shared/settings.js';\nimport {\n assertValidCategoryList,\n offeringConfigured,\n storedCategoryList,\n} from '../shared/notification-categories.js';\n\nexport type OrgNotificationCategoriesParams = {\n settings: SettingsService;\n types: NotificationTypeRegistry;\n channels: ChannelRegistry;\n logger?: Logger;\n};\n\nexport class OrgNotificationCategories implements NotificationCategoryService {\n private readonly settings: SettingsService;\n private readonly types: NotificationTypeRegistry;\n private readonly channels: ChannelRegistry;\n private readonly logger: Logger;\n\n constructor(params: OrgNotificationCategoriesParams) {\n this.settings = params.settings;\n this.types = params.types;\n this.channels = params.channels;\n this.logger = params.logger ?? noopLogger;\n }\n\n async get(\n scopeId: string,\n actor: Actor,\n ): Promise<{ categories: NotificationCategory[]; source: 'default' | 'stored' }> {\n actor.permissions.require('notification_categories:read');\n this.assertOrg(scopeId, actor);\n const value = await this.settings.get<Record<string, unknown>>(\n actor.orgId,\n SettingsNamespace.organizations,\n scopeId,\n );\n const stored = storedCategoryList(value?.notificationCategories);\n return stored\n ? { categories: offeringConfigured(stored, this.channels.list()), source: 'stored' }\n : { categories: this.types.defaults('org'), source: 'default' };\n }\n\n async replace(\n scopeId: string,\n categories: NotificationCategory[],\n actor: Actor,\n ): Promise<{ categories: NotificationCategory[]; source: 'stored' }> {\n actor.permissions.require('notification_categories:write');\n this.assertOrg(scopeId, actor);\n const configured = this.channels.list();\n assertValidCategoryList(categories, 'org', this.types, configured);\n const ordered = offeringConfigured(categories, configured);\n await this.settings.patch(actor.orgId, SettingsNamespace.organizations, scopeId, {\n notificationCategories: ordered,\n });\n this.logger.info('org notification categories replaced', {\n orgId: actor.orgId,\n orgUserId: actor.id,\n keys: categories.map((category) => category.key),\n });\n return { categories: ordered, source: 'stored' };\n }\n\n async reset(scopeId: string, actor: Actor): Promise<void> {\n actor.permissions.require('notification_categories:write');\n this.assertOrg(scopeId, actor);\n await this.settings.patch(actor.orgId, SettingsNamespace.organizations, scopeId, {\n notificationCategories: null,\n });\n this.logger.info('org notification categories reset', {\n orgId: actor.orgId,\n orgUserId: actor.id,\n });\n }\n\n defaults(actor: Actor): NotificationCategory[] {\n actor.permissions.require('notification_categories:read');\n return this.types.defaults('org');\n }\n\n private assertOrg(scopeId: string, actor: Actor): void {\n if (scopeId !== actor.orgId) {\n throw new NotFoundError('Organization', scopeId);\n }\n }\n}\n"],"mappings":";;;;;AAwBA,IAAa,4BAAb,MAA8E;CAC5E;CACA;CACA;CACA;CAEA,YAAY,QAAyC;EACnD,KAAK,WAAW,OAAO;EACvB,KAAK,QAAQ,OAAO;EACpB,KAAK,WAAW,OAAO;EACvB,KAAK,SAAS,OAAO,UAAU;CACjC;CAEA,MAAM,IACJ,SACA,OAC+E;EAC/E,MAAM,YAAY,QAAQ,8BAA8B;EACxD,KAAK,UAAU,SAAS,KAAK;EAM7B,MAAM,SAAS,oBAAmB,MALd,KAAK,SAAS,IAChC,MAAM,OAAA,iBAEN,OACF,EAAA,EACyC,sBAAsB;EAC/D,OAAO,SACH;GAAE,YAAY,mBAAmB,QAAQ,KAAK,SAAS,KAAK,CAAC;GAAG,QAAQ;EAAS,IACjF;GAAE,YAAY,KAAK,MAAM,SAAS,KAAK;GAAG,QAAQ;EAAU;CAClE;CAEA,MAAM,QACJ,SACA,YACA,OACmE;EACnE,MAAM,YAAY,QAAQ,+BAA+B;EACzD,KAAK,UAAU,SAAS,KAAK;EAC7B,MAAM,aAAa,KAAK,SAAS,KAAK;EACtC,wBAAwB,YAAY,OAAO,KAAK,OAAO,UAAU;EACjE,MAAM,UAAU,mBAAmB,YAAY,UAAU;EACzD,MAAM,KAAK,SAAS,MAAM,MAAM,OAAA,iBAAwC,SAAS,EAC/E,wBAAwB,QAC1B,CAAC;EACD,KAAK,OAAO,KAAK,wCAAwC;GACvD,OAAO,MAAM;GACb,WAAW,MAAM;GACjB,MAAM,WAAW,KAAK,aAAa,SAAS,GAAG;EACjD,CAAC;EACD,OAAO;GAAE,YAAY;GAAS,QAAQ;EAAS;CACjD;CAEA,MAAM,MAAM,SAAiB,OAA6B;EACxD,MAAM,YAAY,QAAQ,+BAA+B;EACzD,KAAK,UAAU,SAAS,KAAK;EAC7B,MAAM,KAAK,SAAS,MAAM,MAAM,OAAA,iBAAwC,SAAS,EAC/E,wBAAwB,KAC1B,CAAC;EACD,KAAK,OAAO,KAAK,qCAAqC;GACpD,OAAO,MAAM;GACb,WAAW,MAAM;EACnB,CAAC;CACH;CAEA,SAAS,OAAsC;EAC7C,MAAM,YAAY,QAAQ,8BAA8B;EACxD,OAAO,KAAK,MAAM,SAAS,KAAK;CAClC;CAEA,UAAkB,SAAiB,OAAoB;EACrD,IAAI,YAAY,MAAM,OACpB,MAAM,IAAI,cAAc,gBAAgB,OAAO;CAEnD;AACF"}
@@ -0,0 +1,33 @@
1
+ import { Level, Permission } from "../types/schemas/organizations.js";
2
+ import "../types/index.js";
3
+ import { RoleDefinition } from "./default-roles.js";
4
+ //#region src/organizations/org-roles.d.ts
5
+ interface StoredOrgRole {
6
+ key: string;
7
+ name: string | null;
8
+ description: string | null;
9
+ base: string;
10
+ levels: Level[] | null;
11
+ permissions: Partial<Record<Permission, boolean>>;
12
+ team: boolean | null;
13
+ }
14
+ interface OrgRole {
15
+ key: string;
16
+ name: string;
17
+ description: string;
18
+ base: string;
19
+ levels: Level[];
20
+ team: boolean;
21
+ permissions: Permission[];
22
+ system: boolean;
23
+ added: boolean;
24
+ customized: boolean;
25
+ }
26
+ type RoleCatalog = ReadonlyMap<string, RoleDefinition>;
27
+ declare function catalogOf(roles: readonly RoleDefinition[]): RoleCatalog;
28
+ declare function isSystemRole(key: string): boolean;
29
+ declare function resolveRole(key: string, catalog: RoleCatalog, stored: StoredOrgRole | undefined): OrgRole | null;
30
+ declare function resolveOrgRoles(catalog: RoleCatalog, stored: readonly StoredOrgRole[]): OrgRole[];
31
+ //#endregion
32
+ export { OrgRole, RoleCatalog, StoredOrgRole, catalogOf, isSystemRole, resolveOrgRoles, resolveRole };
33
+ //# sourceMappingURL=org-roles.d.ts.map
@@ -0,0 +1,49 @@
1
+ import { ALL_PERMISSIONS, fitsLevels } from "./permissions.js";
2
+ import "./default-roles.js";
3
+ //#region src/organizations/org-roles.ts
4
+ function catalogOf(roles) {
5
+ return new Map(roles.map((role) => [role.key, role]));
6
+ }
7
+ function isSystemRole(key) {
8
+ return key === "owner" || key === "member";
9
+ }
10
+ function resolveRole(key, catalog, stored) {
11
+ const baseKey = stored?.base ?? key;
12
+ const base = catalog.get(baseKey);
13
+ if (!base) return null;
14
+ const own = catalog.get(key);
15
+ if (!own && !stored) return null;
16
+ const levels = stored?.levels ?? base.levels;
17
+ const permissions = key === "owner" ? [...ALL_PERMISSIONS] : key === "member" ? [] : ALL_PERMISSIONS.filter((permission) => {
18
+ return (stored?.permissions[permission] ?? base.permissions.includes(permission)) && fitsLevels(permission, levels);
19
+ });
20
+ return {
21
+ key,
22
+ name: stored?.name ?? own?.name ?? base.name,
23
+ description: stored?.description ?? own?.description ?? base.description,
24
+ base: baseKey,
25
+ levels: key === "owner" || key === "member" ? ["org"] : levels,
26
+ team: stored?.team ?? own?.team ?? base.team,
27
+ permissions,
28
+ system: isSystemRole(key),
29
+ added: !own,
30
+ customized: stored !== void 0
31
+ };
32
+ }
33
+ function resolveOrgRoles(catalog, stored) {
34
+ const byKey = new Map(stored.map((row) => [row.key, row]));
35
+ const out = [];
36
+ for (const key of catalog.keys()) {
37
+ const role = resolveRole(key, catalog, byKey.get(key));
38
+ if (role) out.push(role);
39
+ }
40
+ for (const row of stored) if (!catalog.has(row.key)) {
41
+ const role = resolveRole(row.key, catalog, row);
42
+ if (role) out.push(role);
43
+ }
44
+ return out;
45
+ }
46
+ //#endregion
47
+ export { catalogOf, isSystemRole, resolveOrgRoles, resolveRole };
48
+
49
+ //# sourceMappingURL=org-roles.js.map