@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
@@ -13,6 +13,7 @@ declare const assetEvents: {
13
13
  size: number;
14
14
  status: "pending" | "ready";
15
15
  uploadedBy: string;
16
+ contentId: string | null;
16
17
  createdAt: Date;
17
18
  updatedAt: Date;
18
19
  }, "asset.created", 1>, {
@@ -26,6 +27,7 @@ declare const assetEvents: {
26
27
  size: number;
27
28
  status: "pending" | "ready";
28
29
  uploadedBy: string;
30
+ contentId: string | null;
29
31
  createdAt: unknown;
30
32
  updatedAt: unknown;
31
33
  }, import("zod").ZodObject<{
@@ -37,20 +39,20 @@ declare const assetEvents: {
37
39
  audio: "audio";
38
40
  document: "document";
39
41
  }>;
40
- source: import("zod").ZodEnum<{
41
- library: "library";
42
- member: "member";
43
- }>;
42
+ createdAt: import("zod").ZodCoercedDate<unknown>;
43
+ updatedAt: import("zod").ZodCoercedDate<unknown>;
44
44
  status: import("zod").ZodEnum<{
45
45
  pending: "pending";
46
46
  ready: "ready";
47
47
  }>;
48
+ source: import("zod").ZodEnum<{
49
+ library: "library";
50
+ member: "member";
51
+ }>;
48
52
  uploadedBy: import("zod").ZodString;
49
53
  filename: import("zod").ZodString;
50
54
  contentType: import("zod").ZodString;
51
55
  size: import("zod").ZodNumber;
52
- createdAt: import("zod").ZodCoercedDate<unknown>;
53
- updatedAt: import("zod").ZodCoercedDate<unknown>;
54
56
  }, import("zod/v4/core").$strip>>;
55
57
  assetReady: RuntimeEventDefinition<VersionedDomainEvent<{
56
58
  orgId: string;
@@ -63,6 +65,7 @@ declare const assetEvents: {
63
65
  size: number;
64
66
  status: "pending" | "ready";
65
67
  uploadedBy: string;
68
+ contentId: string | null;
66
69
  createdAt: Date;
67
70
  updatedAt: Date;
68
71
  }, "asset.ready", 1>, {
@@ -76,6 +79,7 @@ declare const assetEvents: {
76
79
  size: number;
77
80
  status: "pending" | "ready";
78
81
  uploadedBy: string;
82
+ contentId: string | null;
79
83
  createdAt: unknown;
80
84
  updatedAt: unknown;
81
85
  }, import("zod").ZodObject<{
@@ -87,20 +91,20 @@ declare const assetEvents: {
87
91
  audio: "audio";
88
92
  document: "document";
89
93
  }>;
90
- source: import("zod").ZodEnum<{
91
- library: "library";
92
- member: "member";
93
- }>;
94
+ createdAt: import("zod").ZodCoercedDate<unknown>;
95
+ updatedAt: import("zod").ZodCoercedDate<unknown>;
94
96
  status: import("zod").ZodEnum<{
95
97
  pending: "pending";
96
98
  ready: "ready";
97
99
  }>;
100
+ source: import("zod").ZodEnum<{
101
+ library: "library";
102
+ member: "member";
103
+ }>;
98
104
  uploadedBy: import("zod").ZodString;
99
105
  filename: import("zod").ZodString;
100
106
  contentType: import("zod").ZodString;
101
107
  size: import("zod").ZodNumber;
102
- createdAt: import("zod").ZodCoercedDate<unknown>;
103
- updatedAt: import("zod").ZodCoercedDate<unknown>;
104
108
  }, import("zod/v4/core").$strip>>;
105
109
  assetDeleted: RuntimeEventDefinition<VersionedDomainEvent<{
106
110
  orgId: string;
@@ -113,6 +117,7 @@ declare const assetEvents: {
113
117
  size: number;
114
118
  status: "pending" | "ready";
115
119
  uploadedBy: string;
120
+ contentId: string | null;
116
121
  createdAt: Date;
117
122
  updatedAt: Date;
118
123
  }, "asset.deleted", 1>, {
@@ -126,6 +131,7 @@ declare const assetEvents: {
126
131
  size: number;
127
132
  status: "pending" | "ready";
128
133
  uploadedBy: string;
134
+ contentId: string | null;
129
135
  createdAt: unknown;
130
136
  updatedAt: unknown;
131
137
  }, import("zod").ZodObject<{
@@ -137,20 +143,20 @@ declare const assetEvents: {
137
143
  audio: "audio";
138
144
  document: "document";
139
145
  }>;
140
- source: import("zod").ZodEnum<{
141
- library: "library";
142
- member: "member";
143
- }>;
146
+ createdAt: import("zod").ZodCoercedDate<unknown>;
147
+ updatedAt: import("zod").ZodCoercedDate<unknown>;
144
148
  status: import("zod").ZodEnum<{
145
149
  pending: "pending";
146
150
  ready: "ready";
147
151
  }>;
152
+ source: import("zod").ZodEnum<{
153
+ library: "library";
154
+ member: "member";
155
+ }>;
148
156
  uploadedBy: import("zod").ZodString;
149
157
  filename: import("zod").ZodString;
150
158
  contentType: import("zod").ZodString;
151
159
  size: import("zod").ZodNumber;
152
- createdAt: import("zod").ZodCoercedDate<unknown>;
153
- updatedAt: import("zod").ZodCoercedDate<unknown>;
154
160
  }, import("zod/v4/core").$strip>>;
155
161
  };
156
162
  type AssetCreated = EventOf<typeof assetEvents.assetCreated>;
@@ -1,20 +1,24 @@
1
1
  //#region src/assets/file-urls.d.ts
2
- type ThumbnailOwner = 'course' | 'download' | 'community';
3
- /** Stable, access-checked URLs on the API for every file a response refers to.
4
- * Each one is answered by a route that checks access, then redirects to a
5
- * signed storage URL; none of them expires. */
2
+ type ThumbnailOwner = 'course' | 'download' | 'community' | 'event';
3
+ /** URLs for every file a response refers to. A public image (a profile photo, or the
4
+ * thumbnail or cover of a published item) is a public storage URL; every other file is a
5
+ * stable, access-checked URL on the API that redirects to a signed storage URL. */
6
6
  interface FileUrls {
7
+ publicImage(orgId: string, ownerId: string, assetId: string): string;
7
8
  thumbnail(owner: ThumbnailOwner, ownerId: string): string;
8
9
  activityAsset(activityId: string, assetId: string): string;
9
10
  downloadFile(downloadId: string, assetId: string): string;
11
+ eventFile(eventId: string, assetId: string): string;
10
12
  postCover(postId: string): string;
13
+ postAsset(postId: string, assetId: string): string;
11
14
  messageAttachment(chatId: string, messageId: string, assetId: string): string;
12
- personImage(orgUserId: string): string;
13
15
  memberUpload(assetId: string): string;
14
16
  libraryFile(assetId: string): string;
15
17
  libraryDownload(assetId: string): string;
16
18
  }
17
- declare function createFileUrls(apiUrl: string): FileUrls;
19
+ declare function publicImagePrefix(orgId: string, ownerId: string): string;
20
+ declare function publicImageKey(orgId: string, ownerId: string, assetId: string): string;
21
+ declare function createFileUrls(apiUrl: string, publicUrl: (key: string) => string): FileUrls;
18
22
  //#endregion
19
- export { FileUrls, ThumbnailOwner, createFileUrls };
23
+ export { FileUrls, ThumbnailOwner, createFileUrls, publicImageKey, publicImagePrefix };
20
24
  //# sourceMappingURL=file-urls.d.ts.map
@@ -1,25 +1,35 @@
1
+ import { PUBLIC_PREFIX } from "../types/ports.js";
1
2
  //#region src/assets/file-urls.ts
2
3
  const THUMBNAIL_PATHS = {
3
4
  course: "courses",
4
5
  download: "downloads",
5
- community: "communities"
6
+ community: "communities",
7
+ event: "events"
6
8
  };
7
- function createFileUrls(apiUrl) {
9
+ function publicImagePrefix(orgId, ownerId) {
10
+ return `${PUBLIC_PREFIX}${orgId}/${ownerId}/`;
11
+ }
12
+ function publicImageKey(orgId, ownerId, assetId) {
13
+ return `${publicImagePrefix(orgId, ownerId)}${assetId}`;
14
+ }
15
+ function createFileUrls(apiUrl, publicUrl) {
8
16
  const base = apiUrl.replace(/\/+$/, "");
9
17
  const at = (...segments) => `${base}/api/${segments.map((s) => encodeURIComponent(s)).join("/")}`;
10
18
  return {
19
+ publicImage: (orgId, ownerId, assetId) => publicUrl(publicImageKey(orgId, ownerId, assetId)),
11
20
  thumbnail: (owner, ownerId) => at("member", THUMBNAIL_PATHS[owner], ownerId, "thumbnail"),
12
21
  activityAsset: (activityId, assetId) => at("member", "activities", activityId, "assets", assetId),
13
22
  downloadFile: (downloadId, assetId) => at("member", "downloads", downloadId, "assets", assetId),
23
+ eventFile: (eventId, assetId) => at("member", "events", eventId, "assets", assetId),
14
24
  postCover: (postId) => at("member", "posts", postId, "cover"),
25
+ postAsset: (postId, assetId) => at("member", "posts", postId, "assets", assetId),
15
26
  messageAttachment: (chatId, messageId, assetId) => at("member", "chats", chatId, "messages", messageId, "attachments", assetId),
16
- personImage: (orgUserId) => at("member", "people", orgUserId, "image"),
17
27
  memberUpload: (assetId) => at("member", "uploads", assetId, "file"),
18
28
  libraryFile: (assetId) => at("assets", assetId, "file"),
19
29
  libraryDownload: (assetId) => at("assets", assetId, "download")
20
30
  };
21
31
  }
22
32
  //#endregion
23
- export { createFileUrls };
33
+ export { createFileUrls, publicImageKey, publicImagePrefix };
24
34
 
25
35
  //# sourceMappingURL=file-urls.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"file-urls.js","names":[],"sources":["../../src/assets/file-urls.ts"],"sourcesContent":["export type ThumbnailOwner = 'course' | 'download' | 'community';\n\n/** Stable, access-checked URLs on the API for every file a response refers to.\n * Each one is answered by a route that checks access, then redirects to a\n * signed storage URL; none of them expires. */\nexport interface FileUrls {\n thumbnail(owner: ThumbnailOwner, ownerId: string): string;\n activityAsset(activityId: string, assetId: string): string;\n downloadFile(downloadId: string, assetId: string): string;\n postCover(postId: string): string;\n messageAttachment(chatId: string, messageId: string, assetId: string): string;\n personImage(orgUserId: string): string;\n memberUpload(assetId: string): string;\n libraryFile(assetId: string): string;\n libraryDownload(assetId: string): string;\n}\n\nconst THUMBNAIL_PATHS: Record<ThumbnailOwner, string> = {\n course: 'courses',\n download: 'downloads',\n community: 'communities',\n};\n\nexport function createFileUrls(apiUrl: string): FileUrls {\n const base = apiUrl.replace(/\\/+$/, '');\n const at = (...segments: string[]) =>\n `${base}/api/${segments.map((s) => encodeURIComponent(s)).join('/')}`;\n return {\n thumbnail: (owner, ownerId) => at('member', THUMBNAIL_PATHS[owner], ownerId, 'thumbnail'),\n activityAsset: (activityId, assetId) =>\n at('member', 'activities', activityId, 'assets', assetId),\n downloadFile: (downloadId, assetId) => at('member', 'downloads', downloadId, 'assets', assetId),\n postCover: (postId) => at('member', 'posts', postId, 'cover'),\n messageAttachment: (chatId, messageId, assetId) =>\n at('member', 'chats', chatId, 'messages', messageId, 'attachments', assetId),\n personImage: (orgUserId) => at('member', 'people', orgUserId, 'image'),\n memberUpload: (assetId) => at('member', 'uploads', assetId, 'file'),\n libraryFile: (assetId) => at('assets', assetId, 'file'),\n libraryDownload: (assetId) => at('assets', assetId, 'download'),\n };\n}\n"],"mappings":";AAiBA,MAAM,kBAAkD;CACtD,QAAQ;CACR,UAAU;CACV,WAAW;AACb;AAEA,SAAgB,eAAe,QAA0B;CACvD,MAAM,OAAO,OAAO,QAAQ,QAAQ,EAAE;CACtC,MAAM,MAAM,GAAG,aACb,GAAG,KAAK,OAAO,SAAS,KAAK,MAAM,mBAAmB,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG;CACpE,OAAO;EACL,YAAY,OAAO,YAAY,GAAG,UAAU,gBAAgB,QAAQ,SAAS,WAAW;EACxF,gBAAgB,YAAY,YAC1B,GAAG,UAAU,cAAc,YAAY,UAAU,OAAO;EAC1D,eAAe,YAAY,YAAY,GAAG,UAAU,aAAa,YAAY,UAAU,OAAO;EAC9F,YAAY,WAAW,GAAG,UAAU,SAAS,QAAQ,OAAO;EAC5D,oBAAoB,QAAQ,WAAW,YACrC,GAAG,UAAU,SAAS,QAAQ,YAAY,WAAW,eAAe,OAAO;EAC7E,cAAc,cAAc,GAAG,UAAU,UAAU,WAAW,OAAO;EACrE,eAAe,YAAY,GAAG,UAAU,WAAW,SAAS,MAAM;EAClE,cAAc,YAAY,GAAG,UAAU,SAAS,MAAM;EACtD,kBAAkB,YAAY,GAAG,UAAU,SAAS,UAAU;CAChE;AACF"}
1
+ {"version":3,"file":"file-urls.js","names":[],"sources":["../../src/assets/file-urls.ts"],"sourcesContent":["import { PUBLIC_PREFIX } from '../types/index.js';\n\nexport type ThumbnailOwner = 'course' | 'download' | 'community' | 'event';\n\n/** URLs for every file a response refers to. A public image (a profile photo, or the\n * thumbnail or cover of a published item) is a public storage URL; every other file is a\n * stable, access-checked URL on the API that redirects to a signed storage URL. */\nexport interface FileUrls {\n publicImage(orgId: string, ownerId: string, assetId: string): string;\n thumbnail(owner: ThumbnailOwner, ownerId: string): string;\n activityAsset(activityId: string, assetId: string): string;\n downloadFile(downloadId: string, assetId: string): string;\n eventFile(eventId: string, assetId: string): string;\n postCover(postId: string): string;\n postAsset(postId: string, assetId: string): string;\n messageAttachment(chatId: string, messageId: string, assetId: string): string;\n memberUpload(assetId: string): string;\n libraryFile(assetId: string): string;\n libraryDownload(assetId: string): string;\n}\n\nconst THUMBNAIL_PATHS: Record<ThumbnailOwner, string> = {\n course: 'courses',\n download: 'downloads',\n community: 'communities',\n event: 'events',\n};\n\nexport function publicImagePrefix(orgId: string, ownerId: string): string {\n return `${PUBLIC_PREFIX}${orgId}/${ownerId}/`;\n}\n\nexport function publicImageKey(orgId: string, ownerId: string, assetId: string): string {\n return `${publicImagePrefix(orgId, ownerId)}${assetId}`;\n}\n\nexport function createFileUrls(apiUrl: string, publicUrl: (key: string) => string): FileUrls {\n const base = apiUrl.replace(/\\/+$/, '');\n const at = (...segments: string[]) =>\n `${base}/api/${segments.map((s) => encodeURIComponent(s)).join('/')}`;\n return {\n publicImage: (orgId, ownerId, assetId) => publicUrl(publicImageKey(orgId, ownerId, assetId)),\n thumbnail: (owner, ownerId) => at('member', THUMBNAIL_PATHS[owner], ownerId, 'thumbnail'),\n activityAsset: (activityId, assetId) =>\n at('member', 'activities', activityId, 'assets', assetId),\n downloadFile: (downloadId, assetId) => at('member', 'downloads', downloadId, 'assets', assetId),\n eventFile: (eventId, assetId) => at('member', 'events', eventId, 'assets', assetId),\n postCover: (postId) => at('member', 'posts', postId, 'cover'),\n postAsset: (postId, assetId) => at('member', 'posts', postId, 'assets', assetId),\n messageAttachment: (chatId, messageId, assetId) =>\n at('member', 'chats', chatId, 'messages', messageId, 'attachments', assetId),\n memberUpload: (assetId) => at('member', 'uploads', assetId, 'file'),\n libraryFile: (assetId) => at('assets', assetId, 'file'),\n libraryDownload: (assetId) => at('assets', assetId, 'download'),\n };\n}\n"],"mappings":";;AAqBA,MAAM,kBAAkD;CACtD,QAAQ;CACR,UAAU;CACV,WAAW;CACX,OAAO;AACT;AAEA,SAAgB,kBAAkB,OAAe,SAAyB;CACxE,OAAO,GAAG,gBAAgB,MAAM,GAAG,QAAQ;AAC7C;AAEA,SAAgB,eAAe,OAAe,SAAiB,SAAyB;CACtF,OAAO,GAAG,kBAAkB,OAAO,OAAO,IAAI;AAChD;AAEA,SAAgB,eAAe,QAAgB,WAA8C;CAC3F,MAAM,OAAO,OAAO,QAAQ,QAAQ,EAAE;CACtC,MAAM,MAAM,GAAG,aACb,GAAG,KAAK,OAAO,SAAS,KAAK,MAAM,mBAAmB,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG;CACpE,OAAO;EACL,cAAc,OAAO,SAAS,YAAY,UAAU,eAAe,OAAO,SAAS,OAAO,CAAC;EAC3F,YAAY,OAAO,YAAY,GAAG,UAAU,gBAAgB,QAAQ,SAAS,WAAW;EACxF,gBAAgB,YAAY,YAC1B,GAAG,UAAU,cAAc,YAAY,UAAU,OAAO;EAC1D,eAAe,YAAY,YAAY,GAAG,UAAU,aAAa,YAAY,UAAU,OAAO;EAC9F,YAAY,SAAS,YAAY,GAAG,UAAU,UAAU,SAAS,UAAU,OAAO;EAClF,YAAY,WAAW,GAAG,UAAU,SAAS,QAAQ,OAAO;EAC5D,YAAY,QAAQ,YAAY,GAAG,UAAU,SAAS,QAAQ,UAAU,OAAO;EAC/E,oBAAoB,QAAQ,WAAW,YACrC,GAAG,UAAU,SAAS,QAAQ,YAAY,WAAW,eAAe,OAAO;EAC7E,eAAe,YAAY,GAAG,UAAU,WAAW,SAAS,MAAM;EAClE,cAAc,YAAY,GAAG,UAAU,SAAS,MAAM;EACtD,kBAAkB,YAAY,GAAG,UAAU,SAAS,UAAU;CAChE;AACF"}
@@ -1,8 +1,9 @@
1
1
  import { Page } from "../types/shared.js";
2
2
  import { Asset, AssetKind, AssetSource, AssetStatus, AssetUrls, AssetView, AssetsQuery, RequestUploadInput, UploadTicket } from "../types/schemas/assets.js";
3
3
  import { AssetCreated, AssetDeleted, AssetEvent, AssetReady, assetEvents } from "./events.js";
4
- import { FileUrls, ThumbnailOwner, createFileUrls } from "./file-urls.js";
4
+ import { FileUrls, ThumbnailOwner, createFileUrls, publicImageKey, publicImagePrefix } from "./file-urls.js";
5
5
  import "./model.js";
6
- import { AssetFiles, AssetsRepository, AssetsService, LibraryAssetReader, MemberImageReader, MemberUploadInput, ReadyFile } from "./ports.js";
7
- import { AssetsServiceImpl, MEMBER_IMAGE_TYPE, isMemberImageType, kindOf } from "./service.js";
8
- export { type Asset, type AssetCreated, type AssetDeleted, type AssetEvent, type AssetFiles, type AssetKind, type AssetReady, type AssetSource, type AssetStatus, type AssetUrls, type AssetView, type AssetsQuery, type AssetsRepository, type AssetsService, AssetsServiceImpl, type FileUrls, type LibraryAssetReader, MEMBER_IMAGE_TYPE, type MemberImageReader, type MemberUploadInput, type Page, type ReadyFile, type RequestUploadInput, type ThumbnailOwner, type UploadTicket, assetEvents, createFileUrls, isMemberImageType, kindOf };
6
+ import { AssetFiles, AssetsRepository, AssetsService, LibraryAssetReader, MemberImageReader, MemberUpload, MemberUploadInput, MemberUploadReader, OrgDirectory, ReadyFile } from "./ports.js";
7
+ import { AssetsServiceImpl, MEMBER_IMAGE_TYPE, isMemberImageType, kindOf, memberKindOf } from "./service.js";
8
+ import { UPLOADS_REMOVE_UNATTACHED_JOB, assetsJobs, assetsRecurringJobs } from "./jobs.js";
9
+ export { type Asset, type AssetCreated, type AssetDeleted, type AssetEvent, type AssetFiles, type AssetKind, type AssetReady, type AssetSource, type AssetStatus, type AssetUrls, type AssetView, type AssetsQuery, type AssetsRepository, type AssetsService, AssetsServiceImpl, type FileUrls, type LibraryAssetReader, MEMBER_IMAGE_TYPE, type MemberImageReader, type MemberUpload, type MemberUploadInput, type MemberUploadReader, type OrgDirectory, type Page, type ReadyFile, type RequestUploadInput, type ThumbnailOwner, UPLOADS_REMOVE_UNATTACHED_JOB, type UploadTicket, assetEvents, assetsJobs, assetsRecurringJobs, createFileUrls, isMemberImageType, kindOf, memberKindOf, publicImageKey, publicImagePrefix };
@@ -1,4 +1,5 @@
1
+ import { createFileUrls, publicImageKey, publicImagePrefix } from "./file-urls.js";
1
2
  import { assetEvents } from "./events.js";
2
- import { createFileUrls } from "./file-urls.js";
3
- import { AssetsServiceImpl, MEMBER_IMAGE_TYPE, isMemberImageType, kindOf } from "./service.js";
4
- export { AssetsServiceImpl, MEMBER_IMAGE_TYPE, assetEvents, createFileUrls, isMemberImageType, kindOf };
3
+ import { AssetsServiceImpl, MEMBER_IMAGE_TYPE, isMemberImageType, kindOf, memberKindOf } from "./service.js";
4
+ import { UPLOADS_REMOVE_UNATTACHED_JOB, assetsJobs, assetsRecurringJobs } from "./jobs.js";
5
+ export { AssetsServiceImpl, MEMBER_IMAGE_TYPE, UPLOADS_REMOVE_UNATTACHED_JOB, assetEvents, assetsJobs, assetsRecurringJobs, createFileUrls, isMemberImageType, kindOf, memberKindOf, publicImageKey, publicImagePrefix };
@@ -0,0 +1,15 @@
1
+ import { Logger } from "../types/ports.js";
2
+ import { RecurringJob, ScheduledJob } from "../shared/ports.js";
3
+ import { AssetsService, OrgDirectory } from "./ports.js";
4
+ //#region src/assets/jobs.d.ts
5
+ declare const UPLOADS_REMOVE_UNATTACHED_JOB = "assets.uploads.removeUnattached";
6
+ interface AssetsJobDeps {
7
+ assets: Pick<AssetsService, 'removeUnattached'>;
8
+ orgs: OrgDirectory;
9
+ logger?: Logger;
10
+ }
11
+ declare function assetsJobs(deps: AssetsJobDeps): ScheduledJob[];
12
+ declare const assetsRecurringJobs: RecurringJob[];
13
+ //#endregion
14
+ export { AssetsJobDeps, UPLOADS_REMOVE_UNATTACHED_JOB, assetsJobs, assetsRecurringJobs };
15
+ //# sourceMappingURL=jobs.d.ts.map
@@ -0,0 +1,30 @@
1
+ import { noopLogger } from "../shared/logger.js";
2
+ //#region src/assets/jobs.ts
3
+ const UPLOADS_REMOVE_UNATTACHED_JOB = "assets.uploads.removeUnattached";
4
+ function assetsJobs(deps) {
5
+ const logger = deps.logger ?? noopLogger;
6
+ return [{
7
+ job: UPLOADS_REMOVE_UNATTACHED_JOB,
8
+ async run(_payload, fire) {
9
+ let failed = 0;
10
+ for (const orgId of await deps.orgs.orgIds()) try {
11
+ await deps.assets.removeUnattached(orgId, fire.startedAt);
12
+ } catch (err) {
13
+ failed += 1;
14
+ logger.error("unattached uploads not swept", {
15
+ orgId,
16
+ err
17
+ });
18
+ }
19
+ if (failed > 0) throw new Error(`unattached uploads of ${failed} orgs could not be swept`);
20
+ }
21
+ }];
22
+ }
23
+ const assetsRecurringJobs = [{
24
+ job: UPLOADS_REMOVE_UNATTACHED_JOB,
25
+ cron: "0 * * * *"
26
+ }];
27
+ //#endregion
28
+ export { UPLOADS_REMOVE_UNATTACHED_JOB, assetsJobs, assetsRecurringJobs };
29
+
30
+ //# sourceMappingURL=jobs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jobs.js","names":[],"sources":["../../src/assets/jobs.ts"],"sourcesContent":["import type { Logger, RecurringJob, ScheduledJob } from '../shared/ports.js';\nimport { noopLogger } from '../shared/logger.js';\nimport type { AssetsService, OrgDirectory } from './ports.js';\n\nexport const UPLOADS_REMOVE_UNATTACHED_JOB = 'assets.uploads.removeUnattached';\n\nexport interface AssetsJobDeps {\n assets: Pick<AssetsService, 'removeUnattached'>;\n orgs: OrgDirectory;\n logger?: Logger;\n}\n\nexport function assetsJobs(deps: AssetsJobDeps): ScheduledJob[] {\n const logger = deps.logger ?? noopLogger;\n return [\n {\n job: UPLOADS_REMOVE_UNATTACHED_JOB,\n async run(_payload, fire) {\n let failed = 0;\n for (const orgId of await deps.orgs.orgIds()) {\n try {\n await deps.assets.removeUnattached(orgId, fire.startedAt);\n } catch (err) {\n failed += 1;\n logger.error('unattached uploads not swept', { orgId, err });\n }\n }\n if (failed > 0) {\n throw new Error(`unattached uploads of ${failed} orgs could not be swept`);\n }\n },\n },\n ];\n}\n\nexport const assetsRecurringJobs: RecurringJob[] = [\n { job: UPLOADS_REMOVE_UNATTACHED_JOB, cron: '0 * * * *' },\n];\n"],"mappings":";;AAIA,MAAa,gCAAgC;AAQ7C,SAAgB,WAAW,MAAqC;CAC9D,MAAM,SAAS,KAAK,UAAU;CAC9B,OAAO,CACL;EACE,KAAK;EACL,MAAM,IAAI,UAAU,MAAM;GACxB,IAAI,SAAS;GACb,KAAK,MAAM,SAAS,MAAM,KAAK,KAAK,OAAO,GACzC,IAAI;IACF,MAAM,KAAK,OAAO,iBAAiB,OAAO,KAAK,SAAS;GAC1D,SAAS,KAAK;IACZ,UAAU;IACV,OAAO,MAAM,gCAAgC;KAAE;KAAO;IAAI,CAAC;GAC7D;GAEF,IAAI,SAAS,GACX,MAAM,IAAI,MAAM,yBAAyB,OAAO,yBAAyB;EAE7E;CACF,CACF;AACF;AAEA,MAAa,sBAAsC,CACjD;CAAE,KAAK;CAA+B,MAAM;AAAY,CAC1D"}
@@ -1,13 +1,30 @@
1
1
  import { Page } from "../types/shared.js";
2
- import { Asset, AssetView, AssetsQuery, RequestUploadInput, UploadTicket } from "../types/schemas/assets.js";
2
+ import { ContentType } from "../types/schemas/content.js";
3
+ import { Asset, AssetKind, AssetView, AssetsQuery, RequestUploadInput, UploadTicket } from "../types/schemas/assets.js";
4
+ import "../types/index.js";
5
+ import { Actor } from "../shared/actor.js";
3
6
  import { OutboxAppender, UnitOfWork } from "../shared/ports.js";
4
7
  import "./model.js";
5
8
  //#region src/assets/ports.d.ts
6
9
  interface MemberImageReader {
7
10
  ownsImage(orgId: string, assetId: string, orgUserId: string): Promise<boolean>;
8
11
  }
12
+ interface MemberUpload {
13
+ id: string;
14
+ kind: AssetKind;
15
+ filename: string;
16
+ contentType: string;
17
+ size: number;
18
+ }
19
+ interface MemberUploadReader {
20
+ ownsUpload(orgId: string, assetId: string, orgUserId: string): Promise<boolean>;
21
+ memberUploads(orgId: string, assetIds: string[]): Promise<MemberUpload[]>;
22
+ }
9
23
  interface LibraryAssetReader {
10
- libraryAssetsAmong(orgId: string, assetIds: string[]): Promise<string[]>;
24
+ libraryAssetsFor(orgId: string, assetIds: string[]): Promise<{
25
+ id: string;
26
+ contentId: string | null;
27
+ }[]>;
11
28
  }
12
29
  interface ReadyFile {
13
30
  filename: string;
@@ -22,27 +39,30 @@ interface AssetFiles {
22
39
  signFile(orgId: string, assetId: string, opts?: {
23
40
  saveAs?: string;
24
41
  }): Promise<string | null>;
42
+ syncPublicImage(orgId: string, ownerId: string, assetId: string | null): Promise<void>;
25
43
  }
26
44
  interface MemberUploadInput {
27
45
  filename: string;
28
46
  contentType: string;
29
47
  }
30
- interface AssetsService extends MemberImageReader, LibraryAssetReader, AssetFiles {
31
- requestUpload(orgId: string, input: RequestUploadInput): Promise<UploadTicket>;
32
- requestMemberUpload(orgId: string, orgUserId: string, input: MemberUploadInput): Promise<UploadTicket>;
33
- confirm(orgId: string, id: string): Promise<AssetView | null>;
34
- confirmOwn(orgId: string, id: string, orgUserId: string): Promise<AssetView | null>;
35
- list(orgId: string, query: AssetsQuery): Promise<Page<AssetView>>;
36
- get(orgId: string, id: string): Promise<AssetView | null>;
37
- libraryFile(orgId: string, assetId: string, opts: {
48
+ interface AssetsService extends MemberImageReader, MemberUploadReader, LibraryAssetReader, AssetFiles {
49
+ requestUpload(input: RequestUploadInput, actor: Actor): Promise<UploadTicket>;
50
+ requestMemberUpload(input: MemberUploadInput, actor: Actor): Promise<UploadTicket>;
51
+ confirm(id: string, actor: Actor): Promise<AssetView>;
52
+ confirmOwn(id: string, actor: Actor): Promise<AssetView>;
53
+ list(query: AssetsQuery, actor: Actor): Promise<Page<AssetView>>;
54
+ get(id: string, actor: Actor): Promise<AssetView>;
55
+ libraryFile(assetId: string, opts: {
38
56
  download: boolean;
39
- }): Promise<string | null>;
40
- ownUploadFile(orgId: string, assetId: string, orgUserId: string): Promise<string | null>;
41
- remove(orgId: string, id: string): Promise<boolean>;
42
- removeOwn(orgId: string, id: string, orgUserId: string): Promise<boolean>;
43
- hasUnattached(orgId: string, now: Date): Promise<boolean>;
57
+ }, actor: Actor): Promise<string>;
58
+ ownUploadFile(assetId: string, actor: Actor): Promise<string>;
59
+ remove(id: string, actor: Actor): Promise<void>;
60
+ removeOwn(id: string, actor: Actor): Promise<void>;
44
61
  removeUnattached(orgId: string, now: Date): Promise<number>;
45
62
  }
63
+ interface OrgDirectory {
64
+ orgIds(): Promise<string[]>;
65
+ }
46
66
  interface AssetsRepository {
47
67
  insert(orgId: string, asset: Asset): Promise<Asset>;
48
68
  list(orgId: string, query: AssetsQuery): Promise<Page<Asset>>;
@@ -50,9 +70,9 @@ interface AssetsRepository {
50
70
  findByIds(orgId: string, ids: string[]): Promise<Asset[]>;
51
71
  markReady(orgId: string, id: string, patch: Pick<Asset, 'key' | 'kind' | 'size' | 'contentType'>): Promise<Asset | null>;
52
72
  delete(orgId: string, id: string): Promise<boolean>;
53
- hasUnreferencedMemberUploads(orgId: string, before: Date): Promise<boolean>;
54
73
  listUnreferencedMemberUploads(orgId: string, before: Date): Promise<Asset[]>;
55
74
  heldKeys(orgId: string, keys: string[]): Promise<string[]>;
75
+ contentTypeOf(orgId: string, contentId: string): Promise<ContentType | null>;
56
76
  }
57
77
  interface AssetsWriteScope {
58
78
  assets: AssetsRepository;
@@ -60,5 +80,5 @@ interface AssetsWriteScope {
60
80
  }
61
81
  type AssetsUnitOfWork = UnitOfWork<AssetsWriteScope>;
62
82
  //#endregion
63
- export { AssetFiles, AssetsRepository, AssetsService, AssetsUnitOfWork, AssetsWriteScope, LibraryAssetReader, MemberImageReader, MemberUploadInput, ReadyFile };
83
+ export { AssetFiles, AssetsRepository, AssetsService, AssetsUnitOfWork, AssetsWriteScope, LibraryAssetReader, MemberImageReader, MemberUpload, MemberUploadInput, MemberUploadReader, OrgDirectory, ReadyFile };
64
84
  //# sourceMappingURL=ports.d.ts.map
@@ -1,19 +1,22 @@
1
1
  import { Page } from "../types/shared.js";
2
2
  import { Logger, ObjectStorage } from "../types/ports.js";
3
3
  import { AssetKind, AssetView, AssetsQuery, RequestUploadInput, UploadTicket } from "../types/schemas/assets.js";
4
+ import { Actor } from "../shared/actor.js";
4
5
  import "../shared/ports.js";
5
6
  import { FileUrls } from "./file-urls.js";
6
7
  import "./model.js";
7
- import { AssetsRepository, AssetsService, AssetsUnitOfWork, MemberUploadInput, ReadyFile } from "./ports.js";
8
+ import { AssetsRepository, AssetsService, AssetsUnitOfWork, MemberUpload, MemberUploadInput, ReadyFile } from "./ports.js";
8
9
  //#region src/assets/service.d.ts
9
10
  declare const MEMBER_IMAGE_TYPE: RegExp;
10
11
  declare function isMemberImageType(contentType: string): boolean;
12
+ declare function memberKindOf(contentType: string): AssetKind;
11
13
  declare function kindOf(contentType: string): AssetKind;
12
14
  type AssetsServiceParams = {
13
15
  storage: ObjectStorage;
14
16
  repo: AssetsRepository;
15
17
  uow: AssetsUnitOfWork;
16
18
  memberImageMaxBytes: number;
19
+ memberFileMaxBytes: number;
17
20
  downloadLinkExpirySeconds: number;
18
21
  fileUrls: FileUrls;
19
22
  logger?: Logger;
@@ -23,30 +26,41 @@ declare class AssetsServiceImpl implements AssetsService {
23
26
  private readonly repo;
24
27
  private readonly uow;
25
28
  private readonly memberImageMaxBytes;
29
+ private readonly memberFileMaxBytes;
26
30
  private readonly downloadLinkExpirySeconds;
27
31
  private readonly fileUrls;
28
32
  private readonly logger;
29
33
  constructor(params: AssetsServiceParams);
30
- requestUpload(orgId: string, input: RequestUploadInput): Promise<UploadTicket>;
31
- requestMemberUpload(orgId: string, orgUserId: string, input: MemberUploadInput): Promise<UploadTicket>;
32
- confirm(orgId: string, id: string): Promise<AssetView | null>;
33
- confirmOwn(orgId: string, id: string, orgUserId: string): Promise<AssetView | null>;
34
- ownUploadFile(orgId: string, assetId: string, orgUserId: string): Promise<string | null>;
34
+ requestUpload(input: RequestUploadInput, actor: Actor): Promise<UploadTicket>;
35
+ requestMemberUpload(input: MemberUploadInput, actor: Actor): Promise<UploadTicket>;
36
+ private createUpload;
37
+ confirm(id: string, actor: Actor): Promise<AssetView>;
38
+ confirmOwn(id: string, actor: Actor): Promise<AssetView>;
39
+ ownUploadFile(assetId: string, actor: Actor): Promise<string>;
40
+ ownsUpload(orgId: string, assetId: string, orgUserId: string): Promise<boolean>;
41
+ memberUploads(orgId: string, assetIds: string[]): Promise<MemberUpload[]>;
35
42
  ownsImage(orgId: string, assetId: string, orgUserId: string): Promise<boolean>;
36
- libraryAssetsAmong(orgId: string, assetIds: string[]): Promise<string[]>;
37
- list(orgId: string, query: AssetsQuery): Promise<Page<AssetView>>;
38
- get(orgId: string, id: string): Promise<AssetView | null>;
43
+ libraryAssetsFor(orgId: string, assetIds: string[]): Promise<{
44
+ id: string;
45
+ contentId: string | null;
46
+ }[]>;
47
+ list(query: AssetsQuery, actor: Actor): Promise<Page<AssetView>>;
48
+ get(id: string, actor: Actor): Promise<AssetView>;
39
49
  readyFiles(orgId: string, assetIds: readonly string[]): Promise<Record<string, ReadyFile>>;
40
50
  signFile(orgId: string, assetId: string, opts?: {
41
51
  saveAs?: string;
42
52
  }): Promise<string | null>;
43
- libraryFile(orgId: string, assetId: string, opts: {
53
+ syncPublicImage(orgId: string, ownerId: string, assetId: string | null): Promise<void>;
54
+ libraryFile(assetId: string, opts: {
44
55
  download: boolean;
45
- }): Promise<string | null>;
46
- remove(orgId: string, id: string): Promise<boolean>;
47
- removeOwn(orgId: string, id: string, orgUserId: string): Promise<boolean>;
48
- hasUnattached(orgId: string, now: Date): Promise<boolean>;
56
+ }, actor: Actor): Promise<string>;
57
+ remove(id: string, actor: Actor): Promise<void>;
58
+ removeOwn(id: string, actor: Actor): Promise<void>;
59
+ private removeAsset;
60
+ private requireReach;
61
+ private requireItemWrite;
49
62
  removeUnattached(orgId: string, now: Date): Promise<number>;
63
+ private orphanPublicImages;
50
64
  private strayUploads;
51
65
  private finalize;
52
66
  private finalizeMember;
@@ -54,8 +68,9 @@ declare class AssetsServiceImpl implements AssetsService {
54
68
  private readyAmong;
55
69
  private view;
56
70
  private discard;
71
+ private removePublicCopies;
57
72
  private removeObject;
58
73
  }
59
74
  //#endregion
60
- export { AssetsServiceImpl, AssetsServiceParams, MEMBER_IMAGE_TYPE, isMemberImageType, kindOf };
75
+ export { AssetsServiceImpl, AssetsServiceParams, MEMBER_IMAGE_TYPE, isMemberImageType, kindOf, memberKindOf };
61
76
  //# sourceMappingURL=service.d.ts.map