@commonpub/server 0.1.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 (147) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +59 -0
  3. package/dist/admin/admin.d.ts +113 -0
  4. package/dist/admin/admin.d.ts.map +1 -0
  5. package/dist/admin/admin.js +426 -0
  6. package/dist/admin/admin.js.map +1 -0
  7. package/dist/admin/index.d.ts +3 -0
  8. package/dist/admin/index.d.ts.map +1 -0
  9. package/dist/admin/index.js +2 -0
  10. package/dist/admin/index.js.map +1 -0
  11. package/dist/content/content.d.ts +39 -0
  12. package/dist/content/content.d.ts.map +1 -0
  13. package/dist/content/content.js +507 -0
  14. package/dist/content/content.js.map +1 -0
  15. package/dist/content/index.d.ts +3 -0
  16. package/dist/content/index.d.ts.map +1 -0
  17. package/dist/content/index.js +2 -0
  18. package/dist/content/index.js.map +1 -0
  19. package/dist/contest/contest.d.ts +92 -0
  20. package/dist/contest/contest.d.ts.map +1 -0
  21. package/dist/contest/contest.js +343 -0
  22. package/dist/contest/contest.js.map +1 -0
  23. package/dist/contest/index.d.ts +3 -0
  24. package/dist/contest/index.d.ts.map +1 -0
  25. package/dist/contest/index.js +2 -0
  26. package/dist/contest/index.js.map +1 -0
  27. package/dist/docs/docs.d.ts +71 -0
  28. package/dist/docs/docs.d.ts.map +1 -0
  29. package/dist/docs/docs.js +398 -0
  30. package/dist/docs/docs.js.map +1 -0
  31. package/dist/docs/index.d.ts +2 -0
  32. package/dist/docs/index.d.ts.map +1 -0
  33. package/dist/docs/index.js +2 -0
  34. package/dist/docs/index.js.map +1 -0
  35. package/dist/email.d.ts +3 -0
  36. package/dist/email.d.ts.map +1 -0
  37. package/dist/email.js +3 -0
  38. package/dist/email.js.map +1 -0
  39. package/dist/federation/federation.d.ts +46 -0
  40. package/dist/federation/federation.d.ts.map +1 -0
  41. package/dist/federation/federation.js +308 -0
  42. package/dist/federation/federation.js.map +1 -0
  43. package/dist/federation/index.d.ts +2 -0
  44. package/dist/federation/index.d.ts.map +1 -0
  45. package/dist/federation/index.js +2 -0
  46. package/dist/federation/index.js.map +1 -0
  47. package/dist/hub/hub.d.ts +110 -0
  48. package/dist/hub/hub.d.ts.map +1 -0
  49. package/dist/hub/hub.js +917 -0
  50. package/dist/hub/hub.js.map +1 -0
  51. package/dist/hub/index.d.ts +2 -0
  52. package/dist/hub/index.d.ts.map +1 -0
  53. package/dist/hub/index.js +2 -0
  54. package/dist/hub/index.js.map +1 -0
  55. package/dist/image.d.ts +3 -0
  56. package/dist/image.d.ts.map +1 -0
  57. package/dist/image.js +3 -0
  58. package/dist/image.js.map +1 -0
  59. package/dist/index.d.ts +38 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +43 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/learning/index.d.ts +6 -0
  64. package/dist/learning/index.d.ts.map +1 -0
  65. package/dist/learning/index.js +6 -0
  66. package/dist/learning/index.js.map +1 -0
  67. package/dist/learning/learning.d.ts +85 -0
  68. package/dist/learning/learning.d.ts.map +1 -0
  69. package/dist/learning/learning.js +681 -0
  70. package/dist/learning/learning.js.map +1 -0
  71. package/dist/messaging/index.d.ts +3 -0
  72. package/dist/messaging/index.d.ts.map +1 -0
  73. package/dist/messaging/index.js +2 -0
  74. package/dist/messaging/index.js.map +1 -0
  75. package/dist/messaging/messaging.d.ts +27 -0
  76. package/dist/messaging/messaging.d.ts.map +1 -0
  77. package/dist/messaging/messaging.js +132 -0
  78. package/dist/messaging/messaging.js.map +1 -0
  79. package/dist/notification/index.d.ts +3 -0
  80. package/dist/notification/index.d.ts.map +1 -0
  81. package/dist/notification/index.js +2 -0
  82. package/dist/notification/index.js.map +1 -0
  83. package/dist/notification/notification.d.ts +38 -0
  84. package/dist/notification/notification.d.ts.map +1 -0
  85. package/dist/notification/notification.js +92 -0
  86. package/dist/notification/notification.js.map +1 -0
  87. package/dist/oauthCodes.d.ts +14 -0
  88. package/dist/oauthCodes.d.ts.map +1 -0
  89. package/dist/oauthCodes.js +40 -0
  90. package/dist/oauthCodes.js.map +1 -0
  91. package/dist/product/index.d.ts +3 -0
  92. package/dist/product/index.d.ts.map +1 -0
  93. package/dist/product/index.js +2 -0
  94. package/dist/product/index.js.map +1 -0
  95. package/dist/product/product.d.ts +143 -0
  96. package/dist/product/product.d.ts.map +1 -0
  97. package/dist/product/product.js +493 -0
  98. package/dist/product/product.js.map +1 -0
  99. package/dist/profile/index.d.ts +2 -0
  100. package/dist/profile/index.d.ts.map +1 -0
  101. package/dist/profile/index.js +2 -0
  102. package/dist/profile/index.js.map +1 -0
  103. package/dist/profile/profile.d.ts +28 -0
  104. package/dist/profile/profile.d.ts.map +1 -0
  105. package/dist/profile/profile.js +122 -0
  106. package/dist/profile/profile.js.map +1 -0
  107. package/dist/query.d.ts +331 -0
  108. package/dist/query.d.ts.map +1 -0
  109. package/dist/query.js +103 -0
  110. package/dist/query.js.map +1 -0
  111. package/dist/security.d.ts +3 -0
  112. package/dist/security.d.ts.map +1 -0
  113. package/dist/security.js +3 -0
  114. package/dist/security.js.map +1 -0
  115. package/dist/social/index.d.ts +3 -0
  116. package/dist/social/index.d.ts.map +1 -0
  117. package/dist/social/index.js +2 -0
  118. package/dist/social/index.js.map +1 -0
  119. package/dist/social/social.d.ts +84 -0
  120. package/dist/social/social.d.ts.map +1 -0
  121. package/dist/social/social.js +353 -0
  122. package/dist/social/social.js.map +1 -0
  123. package/dist/storage.d.ts +3 -0
  124. package/dist/storage.d.ts.map +1 -0
  125. package/dist/storage.js +3 -0
  126. package/dist/storage.js.map +1 -0
  127. package/dist/theme.d.ts +12 -0
  128. package/dist/theme.d.ts.map +1 -0
  129. package/dist/theme.js +55 -0
  130. package/dist/theme.js.map +1 -0
  131. package/dist/types.d.ts +266 -0
  132. package/dist/types.d.ts.map +1 -0
  133. package/dist/types.js +2 -0
  134. package/dist/types.js.map +1 -0
  135. package/dist/utils.d.ts +7 -0
  136. package/dist/utils.d.ts.map +1 -0
  137. package/dist/utils.js +46 -0
  138. package/dist/utils.js.map +1 -0
  139. package/dist/video/index.d.ts +3 -0
  140. package/dist/video/index.d.ts.map +1 -0
  141. package/dist/video/index.js +2 -0
  142. package/dist/video/index.js.map +1 -0
  143. package/dist/video/video.d.ts +61 -0
  144. package/dist/video/video.d.ts.map +1 -0
  145. package/dist/video/video.js +157 -0
  146. package/dist/video/video.js.map +1 -0
  147. package/package.json +129 -0
@@ -0,0 +1,122 @@
1
+ import { eq, and, sql, isNull } from 'drizzle-orm';
2
+ import { contentItems, users, follows } from '@commonpub/schema';
3
+ import { listContent } from '../content/content.js';
4
+ export async function getUserByUsername(db, username) {
5
+ const rows = await db
6
+ .select()
7
+ .from(users)
8
+ .where(and(eq(users.username, username), isNull(users.deletedAt)))
9
+ .limit(1);
10
+ if (rows.length === 0)
11
+ return null;
12
+ const user = rows[0];
13
+ // Get content counts by type + aggregated view/like counts
14
+ const [contentCounts, viewLikeResult, followerResult, followingResult] = await Promise.all([
15
+ db
16
+ .select({
17
+ type: contentItems.type,
18
+ count: sql `count(*)::int`,
19
+ })
20
+ .from(contentItems)
21
+ .where(and(eq(contentItems.authorId, user.id), eq(contentItems.status, 'published')))
22
+ .groupBy(contentItems.type),
23
+ db
24
+ .select({
25
+ totalViews: sql `coalesce(sum(${contentItems.viewCount}), 0)::int`,
26
+ totalLikes: sql `coalesce(sum(${contentItems.likeCount}), 0)::int`,
27
+ })
28
+ .from(contentItems)
29
+ .where(and(eq(contentItems.authorId, user.id), eq(contentItems.status, 'published'))),
30
+ db
31
+ .select({ count: sql `count(*)::int` })
32
+ .from(follows)
33
+ .where(eq(follows.followingId, user.id)),
34
+ db
35
+ .select({ count: sql `count(*)::int` })
36
+ .from(follows)
37
+ .where(eq(follows.followerId, user.id)),
38
+ ]);
39
+ const countMap = {};
40
+ for (const row of contentCounts) {
41
+ countMap[row.type] = row.count;
42
+ }
43
+ const followerCount = followerResult[0]?.count ?? 0;
44
+ const followingCount = followingResult[0]?.count ?? 0;
45
+ const socialLinks = user.socialLinks ?? null;
46
+ return {
47
+ id: user.id,
48
+ username: user.username,
49
+ displayName: user.displayName,
50
+ avatarUrl: user.avatarUrl,
51
+ bio: user.bio ?? null,
52
+ headline: user.headline ?? null,
53
+ location: user.location ?? null,
54
+ website: user.website ?? null,
55
+ bannerUrl: user.bannerUrl ?? null,
56
+ socialLinks,
57
+ skills: user.skills ?? null,
58
+ pronouns: user.pronouns ?? null,
59
+ createdAt: user.createdAt,
60
+ followerCount,
61
+ followingCount,
62
+ viewCount: viewLikeResult[0]?.totalViews ?? 0,
63
+ likeCount: viewLikeResult[0]?.totalLikes ?? 0,
64
+ stats: {
65
+ projects: countMap['project'] ?? 0,
66
+ explainers: countMap['explainer'] ?? 0,
67
+ articles: countMap['article'] ?? 0,
68
+ followers: followerCount,
69
+ following: followingCount,
70
+ },
71
+ };
72
+ }
73
+ export async function updateUserProfile(db, userId, input) {
74
+ const existing = await db
75
+ .select({ id: users.id })
76
+ .from(users)
77
+ .where(eq(users.id, userId))
78
+ .limit(1);
79
+ if (existing.length === 0)
80
+ return null;
81
+ const updates = { updatedAt: new Date() };
82
+ if (input.displayName !== undefined)
83
+ updates.displayName = input.displayName;
84
+ if (input.bio !== undefined)
85
+ updates.bio = input.bio;
86
+ if (input.headline !== undefined)
87
+ updates.headline = input.headline;
88
+ if (input.location !== undefined)
89
+ updates.location = input.location;
90
+ if (input.website !== undefined)
91
+ updates.website = input.website;
92
+ if (input.avatarUrl !== undefined)
93
+ updates.avatarUrl = input.avatarUrl;
94
+ if (input.bannerUrl !== undefined)
95
+ updates.bannerUrl = input.bannerUrl;
96
+ if (input.socialLinks !== undefined)
97
+ updates.socialLinks = input.socialLinks;
98
+ if (input.skills !== undefined)
99
+ updates.skills = input.skills;
100
+ if (input.pronouns !== undefined)
101
+ updates.pronouns = input.pronouns;
102
+ if (input.timezone !== undefined)
103
+ updates.timezone = input.timezone;
104
+ if (input.emailNotifications !== undefined)
105
+ updates.emailNotifications = input.emailNotifications;
106
+ await db.update(users).set(updates).where(eq(users.id, userId));
107
+ const user = await db
108
+ .select({ username: users.username })
109
+ .from(users)
110
+ .where(eq(users.id, userId))
111
+ .limit(1);
112
+ return getUserByUsername(db, user[0].username);
113
+ }
114
+ export async function getUserContent(db, userId, type) {
115
+ return listContent(db, {
116
+ authorId: userId,
117
+ status: 'published',
118
+ type,
119
+ limit: 20,
120
+ });
121
+ }
122
+ //# sourceMappingURL=profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/profile/profile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,331 @@
1
+ /**
2
+ * Generic query helpers to eliminate duplication across domain modules.
3
+ *
4
+ * - ensureUniqueSlugFor: replaces 5 copy-pasted slug uniqueness functions
5
+ * - USER_REF_SELECT: replaces 20+ inline user select shapes
6
+ * - normalizePagination / countRows: replaces identical pagination boilerplate in 15+ list functions
7
+ * - buildPartialUpdates: replaces identical update-builder blocks in 12+ update functions
8
+ */
9
+ import type { PgTable, PgColumn } from 'drizzle-orm/pg-core';
10
+ import type { SQL } from 'drizzle-orm';
11
+ import type { DB } from './types.js';
12
+ /** Standard user reference select shape. Use in Drizzle .select() calls. */
13
+ export declare const USER_REF_SELECT: {
14
+ readonly id: PgColumn<{
15
+ name: "id";
16
+ tableName: "users";
17
+ dataType: "string";
18
+ columnType: "PgUUID";
19
+ data: string;
20
+ driverParam: string;
21
+ notNull: true;
22
+ hasDefault: true;
23
+ isPrimaryKey: true;
24
+ isAutoincrement: false;
25
+ hasRuntimeDefault: false;
26
+ enumValues: undefined;
27
+ baseColumn: never;
28
+ identity: undefined;
29
+ generated: undefined;
30
+ }, {}, {}>;
31
+ readonly username: PgColumn<{
32
+ name: "username";
33
+ tableName: "users";
34
+ dataType: "string";
35
+ columnType: "PgVarchar";
36
+ data: string;
37
+ driverParam: string;
38
+ notNull: true;
39
+ hasDefault: false;
40
+ isPrimaryKey: false;
41
+ isAutoincrement: false;
42
+ hasRuntimeDefault: false;
43
+ enumValues: [string, ...string[]];
44
+ baseColumn: never;
45
+ identity: undefined;
46
+ generated: undefined;
47
+ }, {}, {
48
+ length: 64;
49
+ }>;
50
+ readonly displayName: PgColumn<{
51
+ name: "display_name";
52
+ tableName: "users";
53
+ dataType: "string";
54
+ columnType: "PgVarchar";
55
+ data: string;
56
+ driverParam: string;
57
+ notNull: false;
58
+ hasDefault: false;
59
+ isPrimaryKey: false;
60
+ isAutoincrement: false;
61
+ hasRuntimeDefault: false;
62
+ enumValues: [string, ...string[]];
63
+ baseColumn: never;
64
+ identity: undefined;
65
+ generated: undefined;
66
+ }, {}, {
67
+ length: 128;
68
+ }>;
69
+ readonly avatarUrl: PgColumn<{
70
+ name: "avatar_url";
71
+ tableName: "users";
72
+ dataType: "string";
73
+ columnType: "PgText";
74
+ data: string;
75
+ driverParam: string;
76
+ notNull: false;
77
+ hasDefault: false;
78
+ isPrimaryKey: false;
79
+ isAutoincrement: false;
80
+ hasRuntimeDefault: false;
81
+ enumValues: [string, ...string[]];
82
+ baseColumn: never;
83
+ identity: undefined;
84
+ generated: undefined;
85
+ }, {}, {}>;
86
+ };
87
+ /** Extended user ref with bio (for content detail author, follow lists) */
88
+ export declare const USER_REF_WITH_BIO_SELECT: {
89
+ readonly bio: PgColumn<{
90
+ name: "bio";
91
+ tableName: "users";
92
+ dataType: "string";
93
+ columnType: "PgText";
94
+ data: string;
95
+ driverParam: string;
96
+ notNull: false;
97
+ hasDefault: false;
98
+ isPrimaryKey: false;
99
+ isAutoincrement: false;
100
+ hasRuntimeDefault: false;
101
+ enumValues: [string, ...string[]];
102
+ baseColumn: never;
103
+ identity: undefined;
104
+ generated: undefined;
105
+ }, {}, {}>;
106
+ readonly id: PgColumn<{
107
+ name: "id";
108
+ tableName: "users";
109
+ dataType: "string";
110
+ columnType: "PgUUID";
111
+ data: string;
112
+ driverParam: string;
113
+ notNull: true;
114
+ hasDefault: true;
115
+ isPrimaryKey: true;
116
+ isAutoincrement: false;
117
+ hasRuntimeDefault: false;
118
+ enumValues: undefined;
119
+ baseColumn: never;
120
+ identity: undefined;
121
+ generated: undefined;
122
+ }, {}, {}>;
123
+ readonly username: PgColumn<{
124
+ name: "username";
125
+ tableName: "users";
126
+ dataType: "string";
127
+ columnType: "PgVarchar";
128
+ data: string;
129
+ driverParam: string;
130
+ notNull: true;
131
+ hasDefault: false;
132
+ isPrimaryKey: false;
133
+ isAutoincrement: false;
134
+ hasRuntimeDefault: false;
135
+ enumValues: [string, ...string[]];
136
+ baseColumn: never;
137
+ identity: undefined;
138
+ generated: undefined;
139
+ }, {}, {
140
+ length: 64;
141
+ }>;
142
+ readonly displayName: PgColumn<{
143
+ name: "display_name";
144
+ tableName: "users";
145
+ dataType: "string";
146
+ columnType: "PgVarchar";
147
+ data: string;
148
+ driverParam: string;
149
+ notNull: false;
150
+ hasDefault: false;
151
+ isPrimaryKey: false;
152
+ isAutoincrement: false;
153
+ hasRuntimeDefault: false;
154
+ enumValues: [string, ...string[]];
155
+ baseColumn: never;
156
+ identity: undefined;
157
+ generated: undefined;
158
+ }, {}, {
159
+ length: 128;
160
+ }>;
161
+ readonly avatarUrl: PgColumn<{
162
+ name: "avatar_url";
163
+ tableName: "users";
164
+ dataType: "string";
165
+ columnType: "PgText";
166
+ data: string;
167
+ driverParam: string;
168
+ notNull: false;
169
+ hasDefault: false;
170
+ isPrimaryKey: false;
171
+ isAutoincrement: false;
172
+ hasRuntimeDefault: false;
173
+ enumValues: [string, ...string[]];
174
+ baseColumn: never;
175
+ identity: undefined;
176
+ generated: undefined;
177
+ }, {}, {}>;
178
+ };
179
+ /** Extended user ref with headline (for content detail) */
180
+ export declare const USER_REF_WITH_HEADLINE_SELECT: {
181
+ readonly bio: PgColumn<{
182
+ name: "bio";
183
+ tableName: "users";
184
+ dataType: "string";
185
+ columnType: "PgText";
186
+ data: string;
187
+ driverParam: string;
188
+ notNull: false;
189
+ hasDefault: false;
190
+ isPrimaryKey: false;
191
+ isAutoincrement: false;
192
+ hasRuntimeDefault: false;
193
+ enumValues: [string, ...string[]];
194
+ baseColumn: never;
195
+ identity: undefined;
196
+ generated: undefined;
197
+ }, {}, {}>;
198
+ readonly headline: PgColumn<{
199
+ name: "headline";
200
+ tableName: "users";
201
+ dataType: "string";
202
+ columnType: "PgVarchar";
203
+ data: string;
204
+ driverParam: string;
205
+ notNull: false;
206
+ hasDefault: false;
207
+ isPrimaryKey: false;
208
+ isAutoincrement: false;
209
+ hasRuntimeDefault: false;
210
+ enumValues: [string, ...string[]];
211
+ baseColumn: never;
212
+ identity: undefined;
213
+ generated: undefined;
214
+ }, {}, {
215
+ length: 255;
216
+ }>;
217
+ readonly id: PgColumn<{
218
+ name: "id";
219
+ tableName: "users";
220
+ dataType: "string";
221
+ columnType: "PgUUID";
222
+ data: string;
223
+ driverParam: string;
224
+ notNull: true;
225
+ hasDefault: true;
226
+ isPrimaryKey: true;
227
+ isAutoincrement: false;
228
+ hasRuntimeDefault: false;
229
+ enumValues: undefined;
230
+ baseColumn: never;
231
+ identity: undefined;
232
+ generated: undefined;
233
+ }, {}, {}>;
234
+ readonly username: PgColumn<{
235
+ name: "username";
236
+ tableName: "users";
237
+ dataType: "string";
238
+ columnType: "PgVarchar";
239
+ data: string;
240
+ driverParam: string;
241
+ notNull: true;
242
+ hasDefault: false;
243
+ isPrimaryKey: false;
244
+ isAutoincrement: false;
245
+ hasRuntimeDefault: false;
246
+ enumValues: [string, ...string[]];
247
+ baseColumn: never;
248
+ identity: undefined;
249
+ generated: undefined;
250
+ }, {}, {
251
+ length: 64;
252
+ }>;
253
+ readonly displayName: PgColumn<{
254
+ name: "display_name";
255
+ tableName: "users";
256
+ dataType: "string";
257
+ columnType: "PgVarchar";
258
+ data: string;
259
+ driverParam: string;
260
+ notNull: false;
261
+ hasDefault: false;
262
+ isPrimaryKey: false;
263
+ isAutoincrement: false;
264
+ hasRuntimeDefault: false;
265
+ enumValues: [string, ...string[]];
266
+ baseColumn: never;
267
+ identity: undefined;
268
+ generated: undefined;
269
+ }, {}, {
270
+ length: 128;
271
+ }>;
272
+ readonly avatarUrl: PgColumn<{
273
+ name: "avatar_url";
274
+ tableName: "users";
275
+ dataType: "string";
276
+ columnType: "PgText";
277
+ data: string;
278
+ driverParam: string;
279
+ notNull: false;
280
+ hasDefault: false;
281
+ isPrimaryKey: false;
282
+ isAutoincrement: false;
283
+ hasRuntimeDefault: false;
284
+ enumValues: [string, ...string[]];
285
+ baseColumn: never;
286
+ identity: undefined;
287
+ generated: undefined;
288
+ }, {}, {}>;
289
+ };
290
+ /**
291
+ * Ensure a slug is unique for a given table. Appends a timestamp suffix if a collision is found.
292
+ *
293
+ * Replaces 5 identical copy-pasted functions (ensureUniqueSlug, ensureUniqueHubSlug,
294
+ * ensureUniqueProductSlug, ensureUniqueDocsSiteSlug, ensureUniquePathSlug).
295
+ *
296
+ * @param db - Drizzle database instance
297
+ * @param table - The Drizzle table to check against
298
+ * @param slugCol - The slug column reference (e.g. contentItems.slug)
299
+ * @param idCol - The id column reference (e.g. contentItems.id)
300
+ * @param slug - The desired slug
301
+ * @param fallbackPrefix - Prefix for auto-generated slugs when input is empty (e.g. 'untitled', 'hub', 'product')
302
+ * @param excludeId - Optional ID to exclude from the uniqueness check (for updates)
303
+ */
304
+ export declare function ensureUniqueSlugFor(db: DB, table: PgTable, slugCol: PgColumn, idCol: PgColumn, slug: string, fallbackPrefix: string, excludeId?: string): Promise<string>;
305
+ /** Pagination filter shape (matches the common pattern across all list functions) */
306
+ export interface PaginationOpts {
307
+ limit?: number;
308
+ offset?: number;
309
+ }
310
+ /** Normalize pagination options to safe values */
311
+ export declare function normalizePagination(opts: PaginationOpts): {
312
+ limit: number;
313
+ offset: number;
314
+ };
315
+ /**
316
+ * Execute a count query. Returns 0 if no results.
317
+ * Replaces the identical `db.select({ count: sql\`count(*)::int\` }).from(table).where(where)` pattern.
318
+ */
319
+ export declare function countRows(db: DB, table: PgTable, where?: SQL): Promise<number>;
320
+ /** Escape LIKE/ILIKE wildcard characters in a search term */
321
+ export declare function escapeLike(term: string): string;
322
+ /**
323
+ * Build a partial update object from input, filtering out undefined values.
324
+ * Always includes `updatedAt: new Date()`.
325
+ *
326
+ * @param input - The input object (from validated request body)
327
+ * @param fieldMap - Optional mapping from input keys to DB column names
328
+ * e.g. { durationMinutes: 'duration' }
329
+ */
330
+ export declare function buildPartialUpdates<TInput extends Record<string, unknown>>(input: TInput, fieldMap?: Partial<Record<keyof TInput & string, string>>): Record<string, unknown>;
331
+ //# sourceMappingURL=query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAEvC,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,YAAY,CAAC;AAIrC,4EAA4E;AAC5E,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAKlB,CAAC;AAEX,2EAA2E;AAC3E,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAG3B,CAAC;AAEX,2DAA2D;AAC3D,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAIhC,CAAC;AAIX;;;;;;;;;;;;;GAaG;AACH,wBAAsB,mBAAmB,CACvC,EAAE,EAAE,EAAE,EACN,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAE,QAAQ,EACf,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM,EACtB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAgBjB;AAID,qFAAqF;AACrF,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,kDAAkD;AAClD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,cAAc,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAK3F;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAC7B,EAAE,EAAE,EAAE,EACN,KAAK,EAAE,OAAO,EACd,KAAK,CAAC,EAAE,GAAG,GACV,OAAO,CAAC,MAAM,CAAC,CAMjB;AAID,6DAA6D;AAC7D,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C;AAID;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxE,KAAK,EAAE,MAAM,EACb,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,EAAE,MAAM,CAAC,CAAC,GACxD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASzB"}
package/dist/query.js ADDED
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Generic query helpers to eliminate duplication across domain modules.
3
+ *
4
+ * - ensureUniqueSlugFor: replaces 5 copy-pasted slug uniqueness functions
5
+ * - USER_REF_SELECT: replaces 20+ inline user select shapes
6
+ * - normalizePagination / countRows: replaces identical pagination boilerplate in 15+ list functions
7
+ * - buildPartialUpdates: replaces identical update-builder blocks in 12+ update functions
8
+ */
9
+ import { eq, and, ne, sql } from 'drizzle-orm';
10
+ import { users } from '@commonpub/schema';
11
+ // ---- USER_REF_SELECT ----
12
+ /** Standard user reference select shape. Use in Drizzle .select() calls. */
13
+ export const USER_REF_SELECT = {
14
+ id: users.id,
15
+ username: users.username,
16
+ displayName: users.displayName,
17
+ avatarUrl: users.avatarUrl,
18
+ };
19
+ /** Extended user ref with bio (for content detail author, follow lists) */
20
+ export const USER_REF_WITH_BIO_SELECT = {
21
+ ...USER_REF_SELECT,
22
+ bio: users.bio,
23
+ };
24
+ /** Extended user ref with headline (for content detail) */
25
+ export const USER_REF_WITH_HEADLINE_SELECT = {
26
+ ...USER_REF_SELECT,
27
+ bio: users.bio,
28
+ headline: users.headline,
29
+ };
30
+ // ---- ensureUniqueSlugFor ----
31
+ /**
32
+ * Ensure a slug is unique for a given table. Appends a timestamp suffix if a collision is found.
33
+ *
34
+ * Replaces 5 identical copy-pasted functions (ensureUniqueSlug, ensureUniqueHubSlug,
35
+ * ensureUniqueProductSlug, ensureUniqueDocsSiteSlug, ensureUniquePathSlug).
36
+ *
37
+ * @param db - Drizzle database instance
38
+ * @param table - The Drizzle table to check against
39
+ * @param slugCol - The slug column reference (e.g. contentItems.slug)
40
+ * @param idCol - The id column reference (e.g. contentItems.id)
41
+ * @param slug - The desired slug
42
+ * @param fallbackPrefix - Prefix for auto-generated slugs when input is empty (e.g. 'untitled', 'hub', 'product')
43
+ * @param excludeId - Optional ID to exclude from the uniqueness check (for updates)
44
+ */
45
+ export async function ensureUniqueSlugFor(db, table, slugCol, idCol, slug, fallbackPrefix, excludeId) {
46
+ if (!slug)
47
+ slug = `${fallbackPrefix}-${Date.now()}`;
48
+ const conditions = [eq(slugCol, slug)];
49
+ if (excludeId) {
50
+ conditions.push(ne(idCol, excludeId));
51
+ }
52
+ const existing = await db
53
+ .select({ id: idCol })
54
+ .from(table)
55
+ .where(and(...conditions))
56
+ .limit(1);
57
+ if (existing.length === 0)
58
+ return slug;
59
+ return `${slug}-${Date.now()}`;
60
+ }
61
+ /** Normalize pagination options to safe values */
62
+ export function normalizePagination(opts) {
63
+ return {
64
+ limit: Math.min(opts.limit ?? 20, 100),
65
+ offset: opts.offset ?? 0,
66
+ };
67
+ }
68
+ /**
69
+ * Execute a count query. Returns 0 if no results.
70
+ * Replaces the identical `db.select({ count: sql\`count(*)::int\` }).from(table).where(where)` pattern.
71
+ */
72
+ export async function countRows(db, table, where) {
73
+ const result = await db
74
+ .select({ count: sql `count(*)::int` })
75
+ .from(table)
76
+ .where(where);
77
+ return result[0]?.count ?? 0;
78
+ }
79
+ // ---- LIKE Escape ----
80
+ /** Escape LIKE/ILIKE wildcard characters in a search term */
81
+ export function escapeLike(term) {
82
+ return term.replace(/[%_\\]/g, '\\$&');
83
+ }
84
+ // ---- Partial Update Builder ----
85
+ /**
86
+ * Build a partial update object from input, filtering out undefined values.
87
+ * Always includes `updatedAt: new Date()`.
88
+ *
89
+ * @param input - The input object (from validated request body)
90
+ * @param fieldMap - Optional mapping from input keys to DB column names
91
+ * e.g. { durationMinutes: 'duration' }
92
+ */
93
+ export function buildPartialUpdates(input, fieldMap) {
94
+ const updates = { updatedAt: new Date() };
95
+ for (const [key, value] of Object.entries(input)) {
96
+ if (value !== undefined) {
97
+ const dbField = fieldMap?.[key] ?? key;
98
+ updates[dbField] = value;
99
+ }
100
+ }
101
+ return updates;
102
+ }
103
+ //# sourceMappingURL=query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { buildCspDirectives, buildCspHeader, getSecurityHeaders, getStaticCacheHeaders, generateNonce, RateLimitStore, DEFAULT_TIERS, getTierForPath, shouldSkipRateLimit, checkRateLimit, } from '@commonpub/infra/security';
2
+ export type { RateLimitTier, RateLimitResult } from '@commonpub/infra/security';
3
+ //# sourceMappingURL=security.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACrB,aAAa,EACb,cAAc,EACd,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,cAAc,GACf,MAAM,2BAA2B,CAAC;AACnC,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC"}
@@ -0,0 +1,3 @@
1
+ // Re-export from @commonpub/infra for backward compatibility
2
+ export { buildCspDirectives, buildCspHeader, getSecurityHeaders, getStaticCacheHeaders, generateNonce, RateLimitStore, DEFAULT_TIERS, getTierForPath, shouldSkipRateLimit, checkRateLimit, } from '@commonpub/infra/security';
3
+ //# sourceMappingURL=security.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.js","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACrB,aAAa,EACb,cAAc,EACd,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,cAAc,GACf,MAAM,2BAA2B,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { toggleLike, isLiked, listComments, createComment, deleteComment, toggleBookmark, onContentLiked, followUser, unfollowUser, isFollowing, listFollowers, listFollowing, createReport, listUserBookmarks, } from './social.js';
2
+ export type { FollowUserItem, BookmarkItem } from './social.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/social/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,OAAO,EACP,YAAY,EACZ,aAAa,EACb,aAAa,EACb,cAAc,EACd,cAAc,EACd,UAAU,EACV,YAAY,EACZ,WAAW,EACX,aAAa,EACb,aAAa,EACb,YAAY,EACZ,iBAAiB,GAClB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { toggleLike, isLiked, listComments, createComment, deleteComment, toggleBookmark, onContentLiked, followUser, unfollowUser, isFollowing, listFollowers, listFollowing, createReport, listUserBookmarks, } from './social.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/social/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,OAAO,EACP,YAAY,EACZ,aAAa,EACb,aAAa,EACb,cAAc,EACd,cAAc,EACd,UAAU,EACV,YAAY,EACZ,WAAW,EACX,aAAa,EACb,aAAa,EACb,YAAY,EACZ,iBAAiB,GAClB,MAAM,aAAa,CAAC"}