@rocapine/community-core 0.5.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/lib/config.d.ts +4 -1
- package/lib/config.js +4 -0
- package/lib/hooks.js +1 -0
- package/lib/service.d.ts +4 -1
- package/lib/service.js +5 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,7 +24,9 @@ const config: CommunityConfig = {
|
|
|
24
24
|
|
|
25
25
|
// Product vocabulary
|
|
26
26
|
appName: "My App", // pushes, inbox, broadcast fallback title
|
|
27
|
-
|
|
27
|
+
// Shown when an author has no username yet. A function receives the host
|
|
28
|
+
// locale (`host.getLocale()`), e.g. (locale) => t("anonymous", { lng: locale }).
|
|
29
|
+
anonymousAuthorFallback: "Someone",
|
|
28
30
|
|
|
29
31
|
// Topics — nothing hardcoded. `id` resolves to `topics.<id>` in the UI
|
|
30
32
|
// package's i18n catalog (see packages/ui/README.md); the app supplies
|
package/lib/config.d.ts
CHANGED
|
@@ -59,7 +59,8 @@ export type CommunityFeedConfig = {
|
|
|
59
59
|
export type CommunityConfig = {
|
|
60
60
|
supabase: SupabaseClient | null;
|
|
61
61
|
appName: string;
|
|
62
|
-
|
|
62
|
+
/** Shown for authors without a display name. A function receives the host locale. */
|
|
63
|
+
anonymousAuthorFallback: string | ((locale: string) => string);
|
|
63
64
|
topics: CommunityTopicDef[];
|
|
64
65
|
modules: CommunityModules;
|
|
65
66
|
host?: CommunityHostAdapters;
|
|
@@ -73,6 +74,8 @@ export type ResolvedCommunityConfig = CommunityConfig & {
|
|
|
73
74
|
host: RequiredCommunityHostAdapters;
|
|
74
75
|
feed: CommunityFeedConfig;
|
|
75
76
|
requireClient(): SupabaseClient;
|
|
77
|
+
/** `anonymousAuthorFallback` resolved against `host.getLocale()`. */
|
|
78
|
+
authorFallback(): string;
|
|
76
79
|
composeTopics(): CommunityTopicDef[];
|
|
77
80
|
isOfficialTopic(id: string): boolean;
|
|
78
81
|
};
|
package/lib/config.js
CHANGED
|
@@ -40,6 +40,10 @@ function resolveConfig(config) {
|
|
|
40
40
|
}
|
|
41
41
|
return resolved.supabase;
|
|
42
42
|
},
|
|
43
|
+
authorFallback() {
|
|
44
|
+
const fallback = resolved.anonymousAuthorFallback;
|
|
45
|
+
return typeof fallback === "function" ? fallback(host.getLocale()) : fallback;
|
|
46
|
+
},
|
|
43
47
|
composeTopics() {
|
|
44
48
|
return resolved.topics.filter((topic) => !topic.officialOnly);
|
|
45
49
|
},
|
package/lib/hooks.js
CHANGED
package/lib/service.d.ts
CHANGED
|
@@ -124,19 +124,22 @@ export declare function deleteOwnComment(cfg: ResolvedCommunityConfig, commentId
|
|
|
124
124
|
* signature and translated to the Edge Function's expected `avatarPath` body
|
|
125
125
|
* key at the call site below.
|
|
126
126
|
*/
|
|
127
|
+
/** `username` is the display name shown on posts; `handle` the @handle. All fields are moderated server-side. */
|
|
127
128
|
export type UpdateProfileInput = {
|
|
129
|
+
username?: string;
|
|
128
130
|
handle?: string;
|
|
129
131
|
bio?: string;
|
|
130
132
|
avatarUrl?: string;
|
|
131
133
|
};
|
|
132
134
|
export type UpdateProfileResult = {
|
|
133
135
|
status: "ok";
|
|
136
|
+
username: string | null;
|
|
134
137
|
handle: string | null;
|
|
135
138
|
bio: string | null;
|
|
136
139
|
avatarUrl: string | null;
|
|
137
140
|
} | {
|
|
138
141
|
status: "rejected";
|
|
139
|
-
field: "handle" | "bio" | "avatar";
|
|
142
|
+
field: "username" | "handle" | "bio" | "avatar";
|
|
140
143
|
reason?: string;
|
|
141
144
|
} | {
|
|
142
145
|
status: "error";
|
package/lib/service.js
CHANGED
|
@@ -188,7 +188,7 @@ async function toFeedPosts(cfg, client, rows, uid) {
|
|
|
188
188
|
fetchPollData(cfg, rows.filter((r) => (r.poll_options ?? []).length > 0).map((r) => r.id), uid),
|
|
189
189
|
fetchReactionSummaries(cfg, postIds),
|
|
190
190
|
]);
|
|
191
|
-
return rows.map((r) => (0, models_1.mapPostRow)(r, uid, cfg.
|
|
191
|
+
return rows.map((r) => (0, models_1.mapPostRow)(r, uid, cfg.authorFallback(), cfg.topics, liked, pollData, reactionData, cfg.feed.transformPost));
|
|
192
192
|
}
|
|
193
193
|
/**
|
|
194
194
|
* One feed page, newest first. RLS already excludes other users' hidden and
|
|
@@ -249,7 +249,7 @@ async function fetchProfile(cfg, userId) {
|
|
|
249
249
|
.single();
|
|
250
250
|
if (error)
|
|
251
251
|
throw error;
|
|
252
|
-
return (0, models_1.mapProfileRow)(data, cfg.
|
|
252
|
+
return (0, models_1.mapProfileRow)(data, cfg.authorFallback());
|
|
253
253
|
}
|
|
254
254
|
/**
|
|
255
255
|
* One user's posts, newest first (no pinned ordering — a profile page is
|
|
@@ -327,7 +327,7 @@ async function fetchThread(cfg, postId) {
|
|
|
327
327
|
const { data, error } = await query;
|
|
328
328
|
if (error)
|
|
329
329
|
throw error;
|
|
330
|
-
return (data ?? []).map((r) => (0, models_1.mapCommentRow)(r, uid, cfg.
|
|
330
|
+
return (data ?? []).map((r) => (0, models_1.mapCommentRow)(r, uid, cfg.authorFallback()));
|
|
331
331
|
}
|
|
332
332
|
/**
|
|
333
333
|
* Insert a post as 'pending' (invisible to others until moderated). Returns id.
|
|
@@ -472,9 +472,9 @@ async function deleteOwnComment(cfg, commentId) {
|
|
|
472
472
|
*/
|
|
473
473
|
async function updateProfile(cfg, input) {
|
|
474
474
|
const client = cfg.requireClient();
|
|
475
|
-
const { handle, bio, avatarUrl } = input;
|
|
475
|
+
const { username, handle, bio, avatarUrl } = input;
|
|
476
476
|
const { data, error } = await client.functions.invoke("update-profile", {
|
|
477
|
-
body: { handle, bio, avatarPath: avatarUrl },
|
|
477
|
+
body: { username, handle, bio, avatarPath: avatarUrl },
|
|
478
478
|
});
|
|
479
479
|
if (!error)
|
|
480
480
|
return data;
|
package/package.json
CHANGED