jansathi-community-schema 0.2.0 → 0.4.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.
- package/dist/comment.d.ts +1 -0
- package/dist/comment.d.ts.map +1 -1
- package/dist/engagement.d.ts +2 -0
- package/dist/engagement.d.ts.map +1 -1
- package/dist/enums.d.ts +6 -4
- package/dist/enums.d.ts.map +1 -1
- package/dist/enums.js +5 -4
- package/dist/enums.js.map +1 -1
- package/dist/feed.d.ts +141 -0
- package/dist/feed.d.ts.map +1 -1
- package/dist/feed.js +40 -0
- package/dist/feed.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/post.d.ts +58 -0
- package/dist/post.d.ts.map +1 -1
- package/dist/post.js +53 -2
- package/dist/post.js.map +1 -1
- package/dist/report.d.ts +2 -0
- package/dist/report.d.ts.map +1 -1
- package/dist/report.js +7 -1
- package/dist/report.js.map +1 -1
- package/dist/repost.d.ts +124 -0
- package/dist/repost.d.ts.map +1 -0
- package/dist/repost.js +47 -0
- package/dist/repost.js.map +1 -0
- package/package.json +1 -1
package/dist/comment.d.ts
CHANGED
package/dist/comment.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comment.d.ts","sourceRoot":"","sources":["../src/comment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,eAAO,MAAM,0BAA0B
|
|
1
|
+
{"version":3,"file":"comment.d.ts","sourceRoot":"","sources":["../src/comment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAkCrC,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAI9E,eAAO,MAAM,uBAAuB;;;iBAMlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAIxE,eAAO,MAAM,uBAAuB;;iBAElC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC"}
|
package/dist/engagement.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export declare const toggleUpvoteResponseSchema: z.ZodObject<{
|
|
|
22
22
|
post: "post";
|
|
23
23
|
lost_found: "lost_found";
|
|
24
24
|
voice_box: "voice_box";
|
|
25
|
+
donate_item: "donate_item";
|
|
25
26
|
}>;
|
|
26
27
|
contentId: z.ZodString;
|
|
27
28
|
upvoted: z.ZodBoolean;
|
|
@@ -52,6 +53,7 @@ export declare const setReactionResponseSchema: z.ZodObject<{
|
|
|
52
53
|
post: "post";
|
|
53
54
|
lost_found: "lost_found";
|
|
54
55
|
voice_box: "voice_box";
|
|
56
|
+
donate_item: "donate_item";
|
|
55
57
|
}>;
|
|
56
58
|
contentId: z.ZodString;
|
|
57
59
|
reaction: z.ZodNullable<z.ZodEnum<{
|
package/dist/engagement.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engagement.d.ts","sourceRoot":"","sources":["../src/engagement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB;;;;GAIG;AACH,eAAO,MAAM,0BAA0B
|
|
1
|
+
{"version":3,"file":"engagement.d.ts","sourceRoot":"","sources":["../src/engagement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB;;;;GAIG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;iBAQrC,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAI9E;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;iBAEhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;iBAOpC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC"}
|
package/dist/enums.d.ts
CHANGED
|
@@ -40,17 +40,19 @@ export type VisibilityLevel = z.infer<typeof visibilityLevelSchema>;
|
|
|
40
40
|
export declare const VISIBILITY_LEVEL_RANK: Record<VisibilityLevel, number>;
|
|
41
41
|
/**
|
|
42
42
|
* The kinds of items that show up in the feed. `post` is the new
|
|
43
|
-
* community-native kind; `lost_found` and `
|
|
44
|
-
* features surfaced into the feed via polymorphic
|
|
43
|
+
* community-native kind; `lost_found`, `voice_box`, and `donate_item`
|
|
44
|
+
* are existing legacy features surfaced into the feed via polymorphic
|
|
45
|
+
* union.
|
|
45
46
|
*
|
|
46
|
-
* Engagement (upvote / reaction / comment) is keyed by
|
|
47
|
+
* Engagement (upvote / reaction / comment / share) is keyed by
|
|
47
48
|
* (contentKind, contentId) so every kind gets the same engagement bar.
|
|
48
49
|
*/
|
|
49
|
-
export declare const CONTENT_KIND_VALUES: readonly ["post", "lost_found", "voice_box"];
|
|
50
|
+
export declare const CONTENT_KIND_VALUES: readonly ["post", "lost_found", "voice_box", "donate_item"];
|
|
50
51
|
export declare const contentKindSchema: z.ZodEnum<{
|
|
51
52
|
post: "post";
|
|
52
53
|
lost_found: "lost_found";
|
|
53
54
|
voice_box: "voice_box";
|
|
55
|
+
donate_item: "donate_item";
|
|
54
56
|
}>;
|
|
55
57
|
export type ContentKind = z.infer<typeof contentKindSchema>;
|
|
56
58
|
/**
|
package/dist/enums.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"enums.d.ts","sourceRoot":"","sources":["../src/enums.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,uBAAuB,+DAM1B,CAAC;AACX,eAAO,MAAM,qBAAqB;;;;;;EAAkC,CAAC;AACrE,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAMjE,CAAC;AAIF
|
|
1
|
+
{"version":3,"file":"enums.d.ts","sourceRoot":"","sources":["../src/enums.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,uBAAuB,+DAM1B,CAAC;AACX,eAAO,MAAM,qBAAqB;;;;;;EAAkC,CAAC;AACrE,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAMjE,CAAC;AAIF;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,6DAA8D,CAAC;AAC/F,eAAO,MAAM,iBAAiB;;;;;EAA8B,CAAC;AAC7D,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAI5D;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,qEAQvB,CAAC;AACX,eAAO,MAAM,kBAAkB;;;;;;;;EAA+B,CAAC;AAC/D,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAI9D;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,yDAA0D,CAAC;AAChG,eAAO,MAAM,sBAAsB;;;;;EAAmC,CAAC;AACvE,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAItE;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,gCAAiC,CAAC;AACrE,eAAO,MAAM,oBAAoB;;;EAAiC,CAAC;AACnE,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAIlE;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,yIAUvB,CAAC;AACX,eAAO,MAAM,kBAAkB;;;;;;;;;;EAA+B,CAAC;AAC/D,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,6CAA6C;AAC7C,eAAO,MAAM,oBAAoB,4DAA6D,CAAC;AAC/F,eAAO,MAAM,kBAAkB;;;;;EAA+B,CAAC;AAC/D,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAI9D;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,gCAAiC,CAAC;AAC/D,eAAO,MAAM,cAAc;;;;EAA2B,CAAC;AACvD,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC"}
|
package/dist/enums.js
CHANGED
|
@@ -47,13 +47,14 @@ export const VISIBILITY_LEVEL_RANK = {
|
|
|
47
47
|
// ─── Polymorphic content kind ───────────────────────────────────────────────
|
|
48
48
|
/**
|
|
49
49
|
* The kinds of items that show up in the feed. `post` is the new
|
|
50
|
-
* community-native kind; `lost_found` and `
|
|
51
|
-
* features surfaced into the feed via polymorphic
|
|
50
|
+
* community-native kind; `lost_found`, `voice_box`, and `donate_item`
|
|
51
|
+
* are existing legacy features surfaced into the feed via polymorphic
|
|
52
|
+
* union.
|
|
52
53
|
*
|
|
53
|
-
* Engagement (upvote / reaction / comment) is keyed by
|
|
54
|
+
* Engagement (upvote / reaction / comment / share) is keyed by
|
|
54
55
|
* (contentKind, contentId) so every kind gets the same engagement bar.
|
|
55
56
|
*/
|
|
56
|
-
export const CONTENT_KIND_VALUES = ['post', 'lost_found', 'voice_box'];
|
|
57
|
+
export const CONTENT_KIND_VALUES = ['post', 'lost_found', 'voice_box', 'donate_item'];
|
|
57
58
|
export const contentKindSchema = z.enum(CONTENT_KIND_VALUES);
|
|
58
59
|
// ─── Reactions ──────────────────────────────────────────────────────────────
|
|
59
60
|
/**
|
package/dist/enums.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"enums.js","sourceRoot":"","sources":["../src/enums.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,+EAA+E;AAE/E;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,OAAO;IACP,UAAU;IACV,OAAO;IACP,UAAU;IACV,QAAQ;CACA,CAAC;AACX,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;AAGrE;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAoC;IACpE,KAAK,EAAE,CAAC;IACR,QAAQ,EAAE,CAAC;IACX,KAAK,EAAE,CAAC;IACR,QAAQ,EAAE,CAAC;IACX,MAAM,EAAE,CAAC;CACV,CAAC;AAEF,+EAA+E;AAE/E
|
|
1
|
+
{"version":3,"file":"enums.js","sourceRoot":"","sources":["../src/enums.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,+EAA+E;AAE/E;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,OAAO;IACP,UAAU;IACV,OAAO;IACP,UAAU;IACV,QAAQ;CACA,CAAC;AACX,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;AAGrE;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAoC;IACpE,KAAK,EAAE,CAAC;IACR,QAAQ,EAAE,CAAC;IACX,KAAK,EAAE,CAAC;IACR,QAAQ,EAAE,CAAC;IACX,MAAM,EAAE,CAAC;CACV,CAAC;AAEF,+EAA+E;AAE/E;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,CAAU,CAAC;AAC/F,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;AAG7D,+EAA+E;AAE/E;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,MAAM;IACN,MAAM;IACN,MAAM;IACN,KAAK;IACL,KAAK;IACL,OAAO;IACP,SAAS;CACD,CAAC;AACX,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;AAG/D,8EAA8E;AAE9E;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,CAAU,CAAC;AAChG,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;AAGvE,8EAA8E;AAE9E;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAU,CAAC;AACrE,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;AAGnE,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,MAAM;IACN,YAAY;IACZ,aAAa;IACb,gBAAgB;IAChB,gBAAgB;IAChB,UAAU;IACV,WAAW;IACX,iBAAiB;IACjB,OAAO;CACC,CAAC;AACX,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;AAG/D,6CAA6C;AAC7C,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,CAAU,CAAC;AAC/F,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;AAG/D,8EAA8E;AAE9E;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAU,CAAC;AAC/D,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC","sourcesContent":["/**\n * Enum value arrays shared across the community feature.\n *\n * Each enum is exported as both a `*_VALUES` tuple and the corresponding\n * Zod schema so backend Mongoose models and frontend forms validate\n * against the exact same set.\n *\n * @module community-schema/enums\n */\n\nimport { z } from 'zod';\n\n// ─── Visibility scope ───────────────────────────────────────────────────────\n\n/**\n * The geographic level at which a piece of content is posted.\n *\n * Cascade-upward semantics: a viewer whose feed filter is set to L\n * sees every post at L and every BROADER level that matches their\n * area lineage. So:\n * - `local` → matches local + district + state + national + global within the viewer's locality / village / urbanBody / etc.\n * - `district` → matches district + state + national + global within the viewer's district\n * - `state` → matches state + national + global within the viewer's state\n * - `national` → matches national + global within the viewer's country\n * - `global` → matches global only\n *\n * The full meaning of \"local\" is \"anything below district\" — i.e., the\n * deepest area-lineage match (locality, village, urbanWard, …).\n */\nexport const VISIBILITY_LEVEL_VALUES = [\n 'local',\n 'district',\n 'state',\n 'national',\n 'global',\n] as const;\nexport const visibilityLevelSchema = z.enum(VISIBILITY_LEVEL_VALUES);\nexport type VisibilityLevel = z.infer<typeof visibilityLevelSchema>;\n\n/**\n * Numeric ranking used for the cascade-upward query and for sorting\n * filter chips. `local` is the deepest (most specific), `global` the\n * shallowest. Higher rank = broader scope.\n */\nexport const VISIBILITY_LEVEL_RANK: Record<VisibilityLevel, number> = {\n local: 0,\n district: 1,\n state: 2,\n national: 3,\n global: 4,\n};\n\n// ─── Polymorphic content kind ───────────────────────────────────────────────\n\n/**\n * The kinds of items that show up in the feed. `post` is the new\n * community-native kind; `lost_found`, `voice_box`, and `donate_item`\n * are existing legacy features surfaced into the feed via polymorphic\n * union.\n *\n * Engagement (upvote / reaction / comment / share) is keyed by\n * (contentKind, contentId) so every kind gets the same engagement bar.\n */\nexport const CONTENT_KIND_VALUES = ['post', 'lost_found', 'voice_box', 'donate_item'] as const;\nexport const contentKindSchema = z.enum(CONTENT_KIND_VALUES);\nexport type ContentKind = z.infer<typeof contentKindSchema>;\n\n// ─── Reactions ──────────────────────────────────────────────────────────────\n\n/**\n * Reaction types available on every feed item.\n *\n * `support` replaces Facebook's \"Care\" — better-suited to a civic /\n * hyperlocal context where reacting to a complaint or lost-and-found\n * post deserves a distinct \"I support you\" signal.\n */\nexport const REACTION_TYPE_VALUES = [\n 'like',\n 'love',\n 'haha',\n 'wow',\n 'sad',\n 'angry',\n 'support',\n] as const;\nexport const reactionTypeSchema = z.enum(REACTION_TYPE_VALUES);\nexport type ReactionType = z.infer<typeof reactionTypeSchema>;\n\n// ─── Social graph ──────────────────────────────────────────────────────────\n\n/**\n * Connection (mutual friend) lifecycle.\n *\n * `pending` — requester sent it, recipient hasn't acted yet.\n * `accepted` — both sides confirmed; full visibility regardless of level.\n * `declined` — recipient rejected; surfaces as \"you can't reconnect for X days\" on the requester side.\n * `blocked` — either side blocked; permanently prevents reconnection.\n */\nexport const CONNECTION_STATUS_VALUES = ['pending', 'accepted', 'declined', 'blocked'] as const;\nexport const connectionStatusSchema = z.enum(CONNECTION_STATUS_VALUES);\nexport type ConnectionStatus = z.infer<typeof connectionStatusSchema>;\n\n// ─── Profile privacy ───────────────────────────────────────────────────────\n\n/**\n * Profile-level privacy (single toggle in Settings).\n *\n * `public` — anyone in the matching geo scope sees this user's posts.\n * `private` — only accepted Connections see this user's posts. Visibility\n * level on each post still applies on top (a private post at\n * state level is visible only to Connections who are in the\n * same state).\n */\nexport const PROFILE_PRIVACY_VALUES = ['public', 'private'] as const;\nexport const profilePrivacySchema = z.enum(PROFILE_PRIVACY_VALUES);\nexport type ProfilePrivacy = z.infer<typeof profilePrivacySchema>;\n\n// ─── Moderation ────────────────────────────────────────────────────────────\n\n/**\n * Reasons a piece of content can be reported. The list is deliberately\n * short — finer categorization can come from the optional `details`\n * free-text field on a report.\n */\nexport const REPORT_REASON_VALUES = [\n 'spam',\n 'harassment',\n 'hate_speech',\n 'misinformation',\n 'sexual_content',\n 'violence',\n 'self_harm',\n 'illegal_content',\n 'other',\n] as const;\nexport const reportReasonSchema = z.enum(REPORT_REASON_VALUES);\nexport type ReportReason = z.infer<typeof reportReasonSchema>;\n\n/** Moderator decision states on a report. */\nexport const REPORT_STATUS_VALUES = ['pending', 'reviewing', 'actioned', 'dismissed'] as const;\nexport const reportStatusSchema = z.enum(REPORT_STATUS_VALUES);\nexport type ReportStatus = z.infer<typeof reportStatusSchema>;\n\n// ─── Feed sort ─────────────────────────────────────────────────────────────\n\n/**\n * Sort options exposed in the feed UI.\n *\n * `hot` — the default. Reddit-style score blending upvotes, comment count,\n * and recency. Best surface for civic / community engagement.\n * `new` — strict reverse-chronological. Useful when the viewer wants to\n * catch up on everything fresh.\n * `top` — highest upvote count over a configurable window (defaults to\n * 24 hours on the client).\n */\nexport const FEED_SORT_VALUES = ['hot', 'new', 'top'] as const;\nexport const feedSortSchema = z.enum(FEED_SORT_VALUES);\nexport type FeedSort = z.infer<typeof feedSortSchema>;\n"]}
|
package/dist/feed.d.ts
CHANGED
|
@@ -45,15 +45,50 @@ export declare const lostFoundFeedItemSchema: z.ZodObject<{
|
|
|
45
45
|
imageUrl: z.ZodOptional<z.ZodString>;
|
|
46
46
|
upvoteCount: z.ZodNumber;
|
|
47
47
|
commentCount: z.ZodNumber;
|
|
48
|
+
repostCount: z.ZodNumber;
|
|
48
49
|
reactionCounts: z.ZodRecord<z.ZodString, z.ZodNumber>;
|
|
49
50
|
createdAt: z.ZodString;
|
|
50
51
|
viewer: z.ZodOptional<z.ZodObject<{
|
|
51
52
|
upvoted: z.ZodBoolean;
|
|
52
53
|
reaction: z.ZodNullable<z.ZodString>;
|
|
53
54
|
isAuthor: z.ZodBoolean;
|
|
55
|
+
reposted: z.ZodBoolean;
|
|
54
56
|
}, z.core.$strip>>;
|
|
55
57
|
}, z.core.$strip>;
|
|
56
58
|
export type LostFoundFeedItem = z.infer<typeof lostFoundFeedItemSchema>;
|
|
59
|
+
/**
|
|
60
|
+
* Donated-item listing projected into the feed. Mirrors the engagement
|
|
61
|
+
* + author shape every feed card needs, plus the donate-item-specific
|
|
62
|
+
* fields the card renders (item name, category, condition, status).
|
|
63
|
+
*/
|
|
64
|
+
export declare const donateItemFeedItemSchema: z.ZodObject<{
|
|
65
|
+
_id: z.ZodString;
|
|
66
|
+
contentKind: z.ZodLiteral<"donate_item">;
|
|
67
|
+
author: z.ZodObject<{
|
|
68
|
+
userId: z.ZodString;
|
|
69
|
+
displayName: z.ZodString;
|
|
70
|
+
avatarUrl: z.ZodOptional<z.ZodString>;
|
|
71
|
+
localName: z.ZodOptional<z.ZodString>;
|
|
72
|
+
}, z.core.$strip>;
|
|
73
|
+
itemName: z.ZodString;
|
|
74
|
+
description: z.ZodOptional<z.ZodString>;
|
|
75
|
+
category: z.ZodString;
|
|
76
|
+
condition: z.ZodOptional<z.ZodString>;
|
|
77
|
+
imageUrl: z.ZodOptional<z.ZodString>;
|
|
78
|
+
status: z.ZodString;
|
|
79
|
+
upvoteCount: z.ZodNumber;
|
|
80
|
+
commentCount: z.ZodNumber;
|
|
81
|
+
repostCount: z.ZodNumber;
|
|
82
|
+
reactionCounts: z.ZodRecord<z.ZodString, z.ZodNumber>;
|
|
83
|
+
createdAt: z.ZodString;
|
|
84
|
+
viewer: z.ZodOptional<z.ZodObject<{
|
|
85
|
+
upvoted: z.ZodBoolean;
|
|
86
|
+
reaction: z.ZodNullable<z.ZodString>;
|
|
87
|
+
isAuthor: z.ZodBoolean;
|
|
88
|
+
reposted: z.ZodBoolean;
|
|
89
|
+
}, z.core.$strip>>;
|
|
90
|
+
}, z.core.$strip>;
|
|
91
|
+
export type DonateItemFeedItem = z.infer<typeof donateItemFeedItemSchema>;
|
|
57
92
|
/**
|
|
58
93
|
* Voice-box (complaint or suggestion) item projected into the feed.
|
|
59
94
|
*/
|
|
@@ -74,12 +109,14 @@ export declare const voiceBoxFeedItemSchema: z.ZodObject<{
|
|
|
74
109
|
description: z.ZodString;
|
|
75
110
|
upvoteCount: z.ZodNumber;
|
|
76
111
|
commentCount: z.ZodNumber;
|
|
112
|
+
repostCount: z.ZodNumber;
|
|
77
113
|
reactionCounts: z.ZodRecord<z.ZodString, z.ZodNumber>;
|
|
78
114
|
createdAt: z.ZodString;
|
|
79
115
|
viewer: z.ZodOptional<z.ZodObject<{
|
|
80
116
|
upvoted: z.ZodBoolean;
|
|
81
117
|
reaction: z.ZodNullable<z.ZodString>;
|
|
82
118
|
isAuthor: z.ZodBoolean;
|
|
119
|
+
reposted: z.ZodBoolean;
|
|
83
120
|
}, z.core.$strip>>;
|
|
84
121
|
}, z.core.$strip>;
|
|
85
122
|
export type VoiceBoxFeedItem = z.infer<typeof voiceBoxFeedItemSchema>;
|
|
@@ -125,7 +162,28 @@ export declare const feedItemSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
125
162
|
}, z.core.$strip>;
|
|
126
163
|
upvoteCount: z.ZodNumber;
|
|
127
164
|
commentCount: z.ZodNumber;
|
|
165
|
+
repostCount: z.ZodNumber;
|
|
128
166
|
reactionCounts: z.ZodRecord<z.ZodString, z.ZodNumber>;
|
|
167
|
+
repostOf: z.ZodOptional<z.ZodObject<{
|
|
168
|
+
contentKind: z.ZodEnum<{
|
|
169
|
+
post: "post";
|
|
170
|
+
lost_found: "lost_found";
|
|
171
|
+
voice_box: "voice_box";
|
|
172
|
+
donate_item: "donate_item";
|
|
173
|
+
}>;
|
|
174
|
+
_id: z.ZodString;
|
|
175
|
+
author: z.ZodObject<{
|
|
176
|
+
userId: z.ZodString;
|
|
177
|
+
displayName: z.ZodString;
|
|
178
|
+
avatarUrl: z.ZodOptional<z.ZodString>;
|
|
179
|
+
localName: z.ZodOptional<z.ZodString>;
|
|
180
|
+
}, z.core.$strip>;
|
|
181
|
+
title: z.ZodString;
|
|
182
|
+
body: z.ZodOptional<z.ZodString>;
|
|
183
|
+
imageUrl: z.ZodOptional<z.ZodString>;
|
|
184
|
+
kindBadge: z.ZodOptional<z.ZodString>;
|
|
185
|
+
createdAt: z.ZodString;
|
|
186
|
+
}, z.core.$strip>>;
|
|
129
187
|
createdAt: z.ZodString;
|
|
130
188
|
editedAt: z.ZodNullable<z.ZodString>;
|
|
131
189
|
deletedAt: z.ZodNullable<z.ZodString>;
|
|
@@ -133,6 +191,7 @@ export declare const feedItemSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
133
191
|
upvoted: z.ZodBoolean;
|
|
134
192
|
reaction: z.ZodNullable<z.ZodString>;
|
|
135
193
|
isAuthor: z.ZodBoolean;
|
|
194
|
+
reposted: z.ZodBoolean;
|
|
136
195
|
}, z.core.$strip>>;
|
|
137
196
|
}, z.core.$strip>, z.ZodObject<{
|
|
138
197
|
_id: z.ZodString;
|
|
@@ -152,12 +211,14 @@ export declare const feedItemSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
152
211
|
imageUrl: z.ZodOptional<z.ZodString>;
|
|
153
212
|
upvoteCount: z.ZodNumber;
|
|
154
213
|
commentCount: z.ZodNumber;
|
|
214
|
+
repostCount: z.ZodNumber;
|
|
155
215
|
reactionCounts: z.ZodRecord<z.ZodString, z.ZodNumber>;
|
|
156
216
|
createdAt: z.ZodString;
|
|
157
217
|
viewer: z.ZodOptional<z.ZodObject<{
|
|
158
218
|
upvoted: z.ZodBoolean;
|
|
159
219
|
reaction: z.ZodNullable<z.ZodString>;
|
|
160
220
|
isAuthor: z.ZodBoolean;
|
|
221
|
+
reposted: z.ZodBoolean;
|
|
161
222
|
}, z.core.$strip>>;
|
|
162
223
|
}, z.core.$strip>, z.ZodObject<{
|
|
163
224
|
_id: z.ZodString;
|
|
@@ -176,12 +237,40 @@ export declare const feedItemSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
176
237
|
description: z.ZodString;
|
|
177
238
|
upvoteCount: z.ZodNumber;
|
|
178
239
|
commentCount: z.ZodNumber;
|
|
240
|
+
repostCount: z.ZodNumber;
|
|
179
241
|
reactionCounts: z.ZodRecord<z.ZodString, z.ZodNumber>;
|
|
180
242
|
createdAt: z.ZodString;
|
|
181
243
|
viewer: z.ZodOptional<z.ZodObject<{
|
|
182
244
|
upvoted: z.ZodBoolean;
|
|
183
245
|
reaction: z.ZodNullable<z.ZodString>;
|
|
184
246
|
isAuthor: z.ZodBoolean;
|
|
247
|
+
reposted: z.ZodBoolean;
|
|
248
|
+
}, z.core.$strip>>;
|
|
249
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
250
|
+
_id: z.ZodString;
|
|
251
|
+
contentKind: z.ZodLiteral<"donate_item">;
|
|
252
|
+
author: z.ZodObject<{
|
|
253
|
+
userId: z.ZodString;
|
|
254
|
+
displayName: z.ZodString;
|
|
255
|
+
avatarUrl: z.ZodOptional<z.ZodString>;
|
|
256
|
+
localName: z.ZodOptional<z.ZodString>;
|
|
257
|
+
}, z.core.$strip>;
|
|
258
|
+
itemName: z.ZodString;
|
|
259
|
+
description: z.ZodOptional<z.ZodString>;
|
|
260
|
+
category: z.ZodString;
|
|
261
|
+
condition: z.ZodOptional<z.ZodString>;
|
|
262
|
+
imageUrl: z.ZodOptional<z.ZodString>;
|
|
263
|
+
status: z.ZodString;
|
|
264
|
+
upvoteCount: z.ZodNumber;
|
|
265
|
+
commentCount: z.ZodNumber;
|
|
266
|
+
repostCount: z.ZodNumber;
|
|
267
|
+
reactionCounts: z.ZodRecord<z.ZodString, z.ZodNumber>;
|
|
268
|
+
createdAt: z.ZodString;
|
|
269
|
+
viewer: z.ZodOptional<z.ZodObject<{
|
|
270
|
+
upvoted: z.ZodBoolean;
|
|
271
|
+
reaction: z.ZodNullable<z.ZodString>;
|
|
272
|
+
isAuthor: z.ZodBoolean;
|
|
273
|
+
reposted: z.ZodBoolean;
|
|
185
274
|
}, z.core.$strip>>;
|
|
186
275
|
}, z.core.$strip>], "contentKind">;
|
|
187
276
|
export type FeedItem = z.infer<typeof feedItemSchema>;
|
|
@@ -245,7 +334,28 @@ export declare const feedResponseSchema: z.ZodObject<{
|
|
|
245
334
|
}, z.core.$strip>;
|
|
246
335
|
upvoteCount: z.ZodNumber;
|
|
247
336
|
commentCount: z.ZodNumber;
|
|
337
|
+
repostCount: z.ZodNumber;
|
|
248
338
|
reactionCounts: z.ZodRecord<z.ZodString, z.ZodNumber>;
|
|
339
|
+
repostOf: z.ZodOptional<z.ZodObject<{
|
|
340
|
+
contentKind: z.ZodEnum<{
|
|
341
|
+
post: "post";
|
|
342
|
+
lost_found: "lost_found";
|
|
343
|
+
voice_box: "voice_box";
|
|
344
|
+
donate_item: "donate_item";
|
|
345
|
+
}>;
|
|
346
|
+
_id: z.ZodString;
|
|
347
|
+
author: z.ZodObject<{
|
|
348
|
+
userId: z.ZodString;
|
|
349
|
+
displayName: z.ZodString;
|
|
350
|
+
avatarUrl: z.ZodOptional<z.ZodString>;
|
|
351
|
+
localName: z.ZodOptional<z.ZodString>;
|
|
352
|
+
}, z.core.$strip>;
|
|
353
|
+
title: z.ZodString;
|
|
354
|
+
body: z.ZodOptional<z.ZodString>;
|
|
355
|
+
imageUrl: z.ZodOptional<z.ZodString>;
|
|
356
|
+
kindBadge: z.ZodOptional<z.ZodString>;
|
|
357
|
+
createdAt: z.ZodString;
|
|
358
|
+
}, z.core.$strip>>;
|
|
249
359
|
createdAt: z.ZodString;
|
|
250
360
|
editedAt: z.ZodNullable<z.ZodString>;
|
|
251
361
|
deletedAt: z.ZodNullable<z.ZodString>;
|
|
@@ -253,6 +363,7 @@ export declare const feedResponseSchema: z.ZodObject<{
|
|
|
253
363
|
upvoted: z.ZodBoolean;
|
|
254
364
|
reaction: z.ZodNullable<z.ZodString>;
|
|
255
365
|
isAuthor: z.ZodBoolean;
|
|
366
|
+
reposted: z.ZodBoolean;
|
|
256
367
|
}, z.core.$strip>>;
|
|
257
368
|
}, z.core.$strip>, z.ZodObject<{
|
|
258
369
|
_id: z.ZodString;
|
|
@@ -272,12 +383,14 @@ export declare const feedResponseSchema: z.ZodObject<{
|
|
|
272
383
|
imageUrl: z.ZodOptional<z.ZodString>;
|
|
273
384
|
upvoteCount: z.ZodNumber;
|
|
274
385
|
commentCount: z.ZodNumber;
|
|
386
|
+
repostCount: z.ZodNumber;
|
|
275
387
|
reactionCounts: z.ZodRecord<z.ZodString, z.ZodNumber>;
|
|
276
388
|
createdAt: z.ZodString;
|
|
277
389
|
viewer: z.ZodOptional<z.ZodObject<{
|
|
278
390
|
upvoted: z.ZodBoolean;
|
|
279
391
|
reaction: z.ZodNullable<z.ZodString>;
|
|
280
392
|
isAuthor: z.ZodBoolean;
|
|
393
|
+
reposted: z.ZodBoolean;
|
|
281
394
|
}, z.core.$strip>>;
|
|
282
395
|
}, z.core.$strip>, z.ZodObject<{
|
|
283
396
|
_id: z.ZodString;
|
|
@@ -296,12 +409,40 @@ export declare const feedResponseSchema: z.ZodObject<{
|
|
|
296
409
|
description: z.ZodString;
|
|
297
410
|
upvoteCount: z.ZodNumber;
|
|
298
411
|
commentCount: z.ZodNumber;
|
|
412
|
+
repostCount: z.ZodNumber;
|
|
413
|
+
reactionCounts: z.ZodRecord<z.ZodString, z.ZodNumber>;
|
|
414
|
+
createdAt: z.ZodString;
|
|
415
|
+
viewer: z.ZodOptional<z.ZodObject<{
|
|
416
|
+
upvoted: z.ZodBoolean;
|
|
417
|
+
reaction: z.ZodNullable<z.ZodString>;
|
|
418
|
+
isAuthor: z.ZodBoolean;
|
|
419
|
+
reposted: z.ZodBoolean;
|
|
420
|
+
}, z.core.$strip>>;
|
|
421
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
422
|
+
_id: z.ZodString;
|
|
423
|
+
contentKind: z.ZodLiteral<"donate_item">;
|
|
424
|
+
author: z.ZodObject<{
|
|
425
|
+
userId: z.ZodString;
|
|
426
|
+
displayName: z.ZodString;
|
|
427
|
+
avatarUrl: z.ZodOptional<z.ZodString>;
|
|
428
|
+
localName: z.ZodOptional<z.ZodString>;
|
|
429
|
+
}, z.core.$strip>;
|
|
430
|
+
itemName: z.ZodString;
|
|
431
|
+
description: z.ZodOptional<z.ZodString>;
|
|
432
|
+
category: z.ZodString;
|
|
433
|
+
condition: z.ZodOptional<z.ZodString>;
|
|
434
|
+
imageUrl: z.ZodOptional<z.ZodString>;
|
|
435
|
+
status: z.ZodString;
|
|
436
|
+
upvoteCount: z.ZodNumber;
|
|
437
|
+
commentCount: z.ZodNumber;
|
|
438
|
+
repostCount: z.ZodNumber;
|
|
299
439
|
reactionCounts: z.ZodRecord<z.ZodString, z.ZodNumber>;
|
|
300
440
|
createdAt: z.ZodString;
|
|
301
441
|
viewer: z.ZodOptional<z.ZodObject<{
|
|
302
442
|
upvoted: z.ZodBoolean;
|
|
303
443
|
reaction: z.ZodNullable<z.ZodString>;
|
|
304
444
|
isAuthor: z.ZodBoolean;
|
|
445
|
+
reposted: z.ZodBoolean;
|
|
305
446
|
}, z.core.$strip>>;
|
|
306
447
|
}, z.core.$strip>], "contentKind">>;
|
|
307
448
|
nextCursor: z.ZodNullable<z.ZodString>;
|
package/dist/feed.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feed.d.ts","sourceRoot":"","sources":["../src/feed.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAMhD;;;;GAIG;AACH,eAAO,MAAM,uBAAuB
|
|
1
|
+
{"version":3,"file":"feed.d.ts","sourceRoot":"","sources":["../src/feed.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAMhD;;;;GAIG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA4BlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE;;;;GAIG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiCnC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E;;GAEG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;iBAyBjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAItE,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kCAKzB,CAAC;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAItD,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;iBAShC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAG7B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAG9D,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
package/dist/feed.js
CHANGED
|
@@ -43,6 +43,7 @@ export const lostFoundFeedItemSchema = z.object({
|
|
|
43
43
|
/** Inherited engagement axis — same shape as posts. */
|
|
44
44
|
upvoteCount: z.number().int().nonnegative(),
|
|
45
45
|
commentCount: z.number().int().nonnegative(),
|
|
46
|
+
repostCount: z.number().int().nonnegative(),
|
|
46
47
|
reactionCounts: z.record(z.string(), z.number().int().nonnegative()),
|
|
47
48
|
createdAt: z.string().datetime(),
|
|
48
49
|
viewer: z
|
|
@@ -50,6 +51,42 @@ export const lostFoundFeedItemSchema = z.object({
|
|
|
50
51
|
upvoted: z.boolean(),
|
|
51
52
|
reaction: z.string().nullable(),
|
|
52
53
|
isAuthor: z.boolean(),
|
|
54
|
+
reposted: z.boolean(),
|
|
55
|
+
})
|
|
56
|
+
.optional(),
|
|
57
|
+
});
|
|
58
|
+
/**
|
|
59
|
+
* Donated-item listing projected into the feed. Mirrors the engagement
|
|
60
|
+
* + author shape every feed card needs, plus the donate-item-specific
|
|
61
|
+
* fields the card renders (item name, category, condition, status).
|
|
62
|
+
*/
|
|
63
|
+
export const donateItemFeedItemSchema = z.object({
|
|
64
|
+
_id: z.string(),
|
|
65
|
+
contentKind: z.literal('donate_item'),
|
|
66
|
+
author: postAuthorSnapshotSchema,
|
|
67
|
+
/** Display name of the item (maps to ReformItemDonation.itemName). */
|
|
68
|
+
itemName: z.string(),
|
|
69
|
+
description: z.string().optional(),
|
|
70
|
+
/** Free-text category (clothing / books / electronics / etc.). */
|
|
71
|
+
category: z.string(),
|
|
72
|
+
/** Free-text condition label (new / good / used / etc.). Optional. */
|
|
73
|
+
condition: z.string().optional(),
|
|
74
|
+
/** First photo if present — used as the card's hero image. */
|
|
75
|
+
imageUrl: z.string().url().optional(),
|
|
76
|
+
/** Donation lifecycle status (pending / verified / picked / etc.) so
|
|
77
|
+
* the card can show an appropriate badge. */
|
|
78
|
+
status: z.string(),
|
|
79
|
+
upvoteCount: z.number().int().nonnegative(),
|
|
80
|
+
commentCount: z.number().int().nonnegative(),
|
|
81
|
+
repostCount: z.number().int().nonnegative(),
|
|
82
|
+
reactionCounts: z.record(z.string(), z.number().int().nonnegative()),
|
|
83
|
+
createdAt: z.string().datetime(),
|
|
84
|
+
viewer: z
|
|
85
|
+
.object({
|
|
86
|
+
upvoted: z.boolean(),
|
|
87
|
+
reaction: z.string().nullable(),
|
|
88
|
+
isAuthor: z.boolean(),
|
|
89
|
+
reposted: z.boolean(),
|
|
53
90
|
})
|
|
54
91
|
.optional(),
|
|
55
92
|
});
|
|
@@ -66,6 +103,7 @@ export const voiceBoxFeedItemSchema = z.object({
|
|
|
66
103
|
description: z.string(),
|
|
67
104
|
upvoteCount: z.number().int().nonnegative(),
|
|
68
105
|
commentCount: z.number().int().nonnegative(),
|
|
106
|
+
repostCount: z.number().int().nonnegative(),
|
|
69
107
|
reactionCounts: z.record(z.string(), z.number().int().nonnegative()),
|
|
70
108
|
createdAt: z.string().datetime(),
|
|
71
109
|
viewer: z
|
|
@@ -73,6 +111,7 @@ export const voiceBoxFeedItemSchema = z.object({
|
|
|
73
111
|
upvoted: z.boolean(),
|
|
74
112
|
reaction: z.string().nullable(),
|
|
75
113
|
isAuthor: z.boolean(),
|
|
114
|
+
reposted: z.boolean(),
|
|
76
115
|
})
|
|
77
116
|
.optional(),
|
|
78
117
|
});
|
|
@@ -81,6 +120,7 @@ export const feedItemSchema = z.discriminatedUnion('contentKind', [
|
|
|
81
120
|
communityPostWireSchema,
|
|
82
121
|
lostFoundFeedItemSchema,
|
|
83
122
|
voiceBoxFeedItemSchema,
|
|
123
|
+
donateItemFeedItemSchema,
|
|
84
124
|
]);
|
|
85
125
|
// ─── Query + response ──────────────────────────────────────────────────────
|
|
86
126
|
export const feedQueryParamsSchema = z.object({
|
package/dist/feed.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feed.js","sourceRoot":"","sources":["../src/feed.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Feed wire shapes — polymorphic union of community posts, lost-and-\n * found reports, and voice-box (complaints + suggestions).\n *\n * The feed is a SINGLE list typed as `FeedItem = Post | LostFound | VoiceBox`.\n * The client discriminates on `contentKind` and renders the matching\n * card component.\n *\n * Strategy notes (server-side):\n * - Read-time fanout. The server runs ONE parallel query per kind\n * filtered by the same area-lineage match and the same cascade-\n * upward visibility rule, then merges and sorts by `hot` score.\n * - Cursor-based pagination. The cursor is opaque (base64 of\n * `<sortKey>|<_id>`) so we can swap sort algorithms without a\n * breaking change.\n * - LostFound / VoiceBox shapes are pruned to the fields the feed\n * card needs — they keep their richer detail-page shape in their\n * own schemas (lost-found-schema, voice-box-schema if/when those\n * get factored out).\n *\n * @module community-schema/feed\n */\n\nimport { z } from 'zod';\nimport { FEED_PAGE_SIZE } from './constants.js';\nimport { feedSortSchema, visibilityLevelSchema } from './enums.js';\nimport { communityPostWireSchema, postAuthorSnapshotSchema } from './post.js';\n\n// ─── Per-kind feed envelopes ───────────────────────────────────────────────\n\n/**\n * Lost-and-found item projected into the feed. Mirrors the engagement\n * + author shape every feed card needs, plus a small handful of\n * lost-found-specific fields used by the card.\n */\nexport const lostFoundFeedItemSchema = z.object({\n _id: z.string(),\n contentKind: z.literal('lost_found'),\n author: postAuthorSnapshotSchema,\n\n /** `'lost'` or `'found'` — drives the card chip colour. */\n kind: z.enum(['lost', 'found']),\n title: z.string(),\n description: z.string(),\n /** Single primary image rendered on the card. */\n imageUrl: z.string().url().optional(),\n\n /** Inherited engagement axis — same shape as posts. */\n upvoteCount: z.number().int().nonnegative(),\n commentCount: z.number().int().nonnegative(),\n reactionCounts: z.record(z.string(), z.number().int().nonnegative()),\n\n createdAt: z.string().datetime(),\n\n viewer: z\n .object({\n upvoted: z.boolean(),\n reaction: z.string().nullable(),\n isAuthor: z.boolean(),\n })\n .optional(),\n});\nexport type LostFoundFeedItem = z.infer<typeof lostFoundFeedItemSchema>;\n\n/**\n * Voice-box (complaint or suggestion) item projected into the feed.\n */\nexport const voiceBoxFeedItemSchema = z.object({\n _id: z.string(),\n contentKind: z.literal('voice_box'),\n author: postAuthorSnapshotSchema,\n\n /** `'complaint'` or `'suggestion'` — drives the card chip colour. */\n kind: z.enum(['complaint', 'suggestion']),\n title: z.string(),\n description: z.string(),\n\n upvoteCount: z.number().int().nonnegative(),\n commentCount: z.number().int().nonnegative(),\n reactionCounts: z.record(z.string(), z.number().int().nonnegative()),\n\n createdAt: z.string().datetime(),\n\n viewer: z\n .object({\n upvoted: z.boolean(),\n reaction: z.string().nullable(),\n isAuthor: z.boolean(),\n })\n .optional(),\n});\nexport type VoiceBoxFeedItem = z.infer<typeof voiceBoxFeedItemSchema>;\n\n// ─── Polymorphic union ─────────────────────────────────────────────────────\n\nexport const feedItemSchema = z.discriminatedUnion('contentKind', [\n communityPostWireSchema,\n lostFoundFeedItemSchema,\n voiceBoxFeedItemSchema,\n]);\nexport type FeedItem = z.infer<typeof feedItemSchema>;\n\n// ─── Query + response ──────────────────────────────────────────────────────\n\nexport const feedQueryParamsSchema = z.object({\n /** The viewer's chosen feed level. Cascade-upward semantics apply. */\n level: visibilityLevelSchema,\n /** Sort algorithm. Defaults to `hot` server-side when omitted. */\n sort: feedSortSchema.optional(),\n /** Opaque pagination cursor returned by the previous page. */\n cursor: z.string().optional(),\n /** Page size; defaults to `FEED_PAGE_SIZE` server-side. */\n pageSize: z.number().int().positive().max(50).optional(),\n});\nexport type FeedQueryParams = z.infer<typeof feedQueryParamsSchema>;\n\nexport const feedResponseSchema = z.object({\n items: z.array(feedItemSchema),\n nextCursor: z.string().nullable(),\n});\nexport type FeedResponse = z.infer<typeof feedResponseSchema>;\n\n// Re-export so consumers don't have to also import constants.ts.\nexport { FEED_PAGE_SIZE };\n"]}
|
|
1
|
+
{"version":3,"file":"feed.js","sourceRoot":"","sources":["../src/feed.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AAE9E,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC;IACpC,MAAM,EAAE,wBAAwB;IAEhC,2DAA2D;IAC3D,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,iDAAiD;IACjD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAErC,uDAAuD;IACvD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IAC3C,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IAC5C,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IAC3C,cAAc,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC;IAEpE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAEhC,MAAM,EAAE,CAAC;SACN,MAAM,CAAC;QACN,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;QACpB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC/B,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE;QACrB,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE;KACtB,CAAC;SACD,QAAQ,EAAE;CACd,CAAC,CAAC;AAGH;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;IACrC,MAAM,EAAE,wBAAwB;IAEhC,sEAAsE;IACtE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,kEAAkE;IAClE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,sEAAsE;IACtE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,8DAA8D;IAC9D,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACrC;kDAC8C;IAC9C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAElB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IAC3C,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IAC5C,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IAC3C,cAAc,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC;IAEpE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAEhC,MAAM,EAAE,CAAC;SACN,MAAM,CAAC;QACN,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;QACpB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC/B,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE;QACrB,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE;KACtB,CAAC;SACD,QAAQ,EAAE;CACd,CAAC,CAAC;AAGH;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;IACnC,MAAM,EAAE,wBAAwB;IAEhC,qEAAqE;IACrE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IACzC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IAEvB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IAC3C,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IAC5C,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IAC3C,cAAc,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC;IAEpE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAEhC,MAAM,EAAE,CAAC;SACN,MAAM,CAAC;QACN,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;QACpB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC/B,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE;QACrB,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE;KACtB,CAAC;SACD,QAAQ,EAAE;CACd,CAAC,CAAC;AAGH,8EAA8E;AAE9E,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,kBAAkB,CAAC,aAAa,EAAE;IAChE,uBAAuB;IACvB,uBAAuB;IACvB,sBAAsB;IACtB,wBAAwB;CACzB,CAAC,CAAC;AAGH,8EAA8E;AAE9E,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,sEAAsE;IACtE,KAAK,EAAE,qBAAqB;IAC5B,kEAAkE;IAClE,IAAI,EAAE,cAAc,CAAC,QAAQ,EAAE;IAC/B,8DAA8D;IAC9D,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,2DAA2D;IAC3D,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;CACzD,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC;IAC9B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAClC,CAAC,CAAC;AAGH,iEAAiE;AACjE,OAAO,EAAE,cAAc,EAAE,CAAC","sourcesContent":["/**\n * Feed wire shapes — polymorphic union of community posts, lost-and-\n * found reports, and voice-box (complaints + suggestions).\n *\n * The feed is a SINGLE list typed as `FeedItem = Post | LostFound | VoiceBox`.\n * The client discriminates on `contentKind` and renders the matching\n * card component.\n *\n * Strategy notes (server-side):\n * - Read-time fanout. The server runs ONE parallel query per kind\n * filtered by the same area-lineage match and the same cascade-\n * upward visibility rule, then merges and sorts by `hot` score.\n * - Cursor-based pagination. The cursor is opaque (base64 of\n * `<sortKey>|<_id>`) so we can swap sort algorithms without a\n * breaking change.\n * - LostFound / VoiceBox shapes are pruned to the fields the feed\n * card needs — they keep their richer detail-page shape in their\n * own schemas (lost-found-schema, voice-box-schema if/when those\n * get factored out).\n *\n * @module community-schema/feed\n */\n\nimport { z } from 'zod';\nimport { FEED_PAGE_SIZE } from './constants.js';\nimport { feedSortSchema, visibilityLevelSchema } from './enums.js';\nimport { communityPostWireSchema, postAuthorSnapshotSchema } from './post.js';\n\n// ─── Per-kind feed envelopes ───────────────────────────────────────────────\n\n/**\n * Lost-and-found item projected into the feed. Mirrors the engagement\n * + author shape every feed card needs, plus a small handful of\n * lost-found-specific fields used by the card.\n */\nexport const lostFoundFeedItemSchema = z.object({\n _id: z.string(),\n contentKind: z.literal('lost_found'),\n author: postAuthorSnapshotSchema,\n\n /** `'lost'` or `'found'` — drives the card chip colour. */\n kind: z.enum(['lost', 'found']),\n title: z.string(),\n description: z.string(),\n /** Single primary image rendered on the card. */\n imageUrl: z.string().url().optional(),\n\n /** Inherited engagement axis — same shape as posts. */\n upvoteCount: z.number().int().nonnegative(),\n commentCount: z.number().int().nonnegative(),\n repostCount: z.number().int().nonnegative(),\n reactionCounts: z.record(z.string(), z.number().int().nonnegative()),\n\n createdAt: z.string().datetime(),\n\n viewer: z\n .object({\n upvoted: z.boolean(),\n reaction: z.string().nullable(),\n isAuthor: z.boolean(),\n reposted: z.boolean(),\n })\n .optional(),\n});\nexport type LostFoundFeedItem = z.infer<typeof lostFoundFeedItemSchema>;\n\n/**\n * Donated-item listing projected into the feed. Mirrors the engagement\n * + author shape every feed card needs, plus the donate-item-specific\n * fields the card renders (item name, category, condition, status).\n */\nexport const donateItemFeedItemSchema = z.object({\n _id: z.string(),\n contentKind: z.literal('donate_item'),\n author: postAuthorSnapshotSchema,\n\n /** Display name of the item (maps to ReformItemDonation.itemName). */\n itemName: z.string(),\n description: z.string().optional(),\n /** Free-text category (clothing / books / electronics / etc.). */\n category: z.string(),\n /** Free-text condition label (new / good / used / etc.). Optional. */\n condition: z.string().optional(),\n /** First photo if present — used as the card's hero image. */\n imageUrl: z.string().url().optional(),\n /** Donation lifecycle status (pending / verified / picked / etc.) so\n * the card can show an appropriate badge. */\n status: z.string(),\n\n upvoteCount: z.number().int().nonnegative(),\n commentCount: z.number().int().nonnegative(),\n repostCount: z.number().int().nonnegative(),\n reactionCounts: z.record(z.string(), z.number().int().nonnegative()),\n\n createdAt: z.string().datetime(),\n\n viewer: z\n .object({\n upvoted: z.boolean(),\n reaction: z.string().nullable(),\n isAuthor: z.boolean(),\n reposted: z.boolean(),\n })\n .optional(),\n});\nexport type DonateItemFeedItem = z.infer<typeof donateItemFeedItemSchema>;\n\n/**\n * Voice-box (complaint or suggestion) item projected into the feed.\n */\nexport const voiceBoxFeedItemSchema = z.object({\n _id: z.string(),\n contentKind: z.literal('voice_box'),\n author: postAuthorSnapshotSchema,\n\n /** `'complaint'` or `'suggestion'` — drives the card chip colour. */\n kind: z.enum(['complaint', 'suggestion']),\n title: z.string(),\n description: z.string(),\n\n upvoteCount: z.number().int().nonnegative(),\n commentCount: z.number().int().nonnegative(),\n repostCount: z.number().int().nonnegative(),\n reactionCounts: z.record(z.string(), z.number().int().nonnegative()),\n\n createdAt: z.string().datetime(),\n\n viewer: z\n .object({\n upvoted: z.boolean(),\n reaction: z.string().nullable(),\n isAuthor: z.boolean(),\n reposted: z.boolean(),\n })\n .optional(),\n});\nexport type VoiceBoxFeedItem = z.infer<typeof voiceBoxFeedItemSchema>;\n\n// ─── Polymorphic union ─────────────────────────────────────────────────────\n\nexport const feedItemSchema = z.discriminatedUnion('contentKind', [\n communityPostWireSchema,\n lostFoundFeedItemSchema,\n voiceBoxFeedItemSchema,\n donateItemFeedItemSchema,\n]);\nexport type FeedItem = z.infer<typeof feedItemSchema>;\n\n// ─── Query + response ──────────────────────────────────────────────────────\n\nexport const feedQueryParamsSchema = z.object({\n /** The viewer's chosen feed level. Cascade-upward semantics apply. */\n level: visibilityLevelSchema,\n /** Sort algorithm. Defaults to `hot` server-side when omitted. */\n sort: feedSortSchema.optional(),\n /** Opaque pagination cursor returned by the previous page. */\n cursor: z.string().optional(),\n /** Page size; defaults to `FEED_PAGE_SIZE` server-side. */\n pageSize: z.number().int().positive().max(50).optional(),\n});\nexport type FeedQueryParams = z.infer<typeof feedQueryParamsSchema>;\n\nexport const feedResponseSchema = z.object({\n items: z.array(feedItemSchema),\n nextCursor: z.string().nullable(),\n});\nexport type FeedResponse = z.infer<typeof feedResponseSchema>;\n\n// Re-export so consumers don't have to also import constants.ts.\nexport { FEED_PAGE_SIZE };\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -19,12 +19,13 @@ export { type CommunityCommentWire, type CreateCommentBody, communityCommentWire
|
|
|
19
19
|
export { COMMENT_MAX_BODY_CHARS, COMMENTS_PAGE_SIZE, EDIT_GRACE_WINDOW_MS, FEED_PAGE_SIZE, GROUP_MAX_MEMBERS, GROUP_NAME_MAX_CHARS, GROUP_NAME_MIN_CHARS, PEOPLE_PAGE_SIZE, POST_MAX_BODY_CHARS, POST_MAX_IMAGE_BYTES, POST_MAX_IMAGES, POST_MAX_VIDEO_BYTES, POST_MAX_VIDEO_SECONDS, POST_MAX_VIDEOS, PROFILE_MAX_BIO_CHARS, REPLIES_PRELOAD_COUNT, } from './constants.js';
|
|
20
20
|
export { type SetReactionBody, type SetReactionResponse, setReactionBodySchema, setReactionResponseSchema, type ToggleUpvoteResponse, toggleUpvoteResponseSchema, } from './engagement.js';
|
|
21
21
|
export { CONNECTION_STATUS_VALUES, CONTENT_KIND_VALUES, type ConnectionStatus, type ContentKind, connectionStatusSchema, contentKindSchema, FEED_SORT_VALUES, type FeedSort, feedSortSchema, PROFILE_PRIVACY_VALUES, type ProfilePrivacy, profilePrivacySchema, REACTION_TYPE_VALUES, REPORT_REASON_VALUES, REPORT_STATUS_VALUES, type ReactionType, type ReportReason, type ReportStatus, reactionTypeSchema, reportReasonSchema, reportStatusSchema, VISIBILITY_LEVEL_RANK, VISIBILITY_LEVEL_VALUES, type VisibilityLevel, visibilityLevelSchema, } from './enums.js';
|
|
22
|
-
export { type FeedItem, type FeedQueryParams, type FeedResponse, feedItemSchema, feedQueryParamsSchema, feedResponseSchema, type LostFoundFeedItem, lostFoundFeedItemSchema, type VoiceBoxFeedItem, voiceBoxFeedItemSchema, } from './feed.js';
|
|
23
|
-
export { type AddGroupMembersBody, addGroupMembersBodySchema, type CommunityGroupWire, type CommunityGroupWithMembers, communityGroupWireSchema, communityGroupWithMembersSchema, type
|
|
22
|
+
export { type DonateItemFeedItem, donateItemFeedItemSchema, type FeedItem, type FeedQueryParams, type FeedResponse, feedItemSchema, feedQueryParamsSchema, feedResponseSchema, type LostFoundFeedItem, lostFoundFeedItemSchema, type VoiceBoxFeedItem, voiceBoxFeedItemSchema, } from './feed.js';
|
|
23
|
+
export { type AddGroupMembersBody, addGroupMembersBodySchema, type CommunityGroupWire, type CommunityGroupWithMembers, type CreateGroupBody, communityGroupWireSchema, communityGroupWithMembersSchema, createGroupBodySchema, type GroupMembersListResponse, type GroupMemberWire, type GroupRole, type GroupsListResponse, groupMembersListResponseSchema, groupMemberWireSchema, groupRoleSchema, groupsListResponseSchema, type UpdateGroupBody, updateGroupBodySchema, } from './group.js';
|
|
24
24
|
export { type PostImage, type PostVideo, postImageSchema, postVideoSchema, } from './media.js';
|
|
25
|
-
export { type CommunityPostWire, type CreatePostBody, communityPostWireSchema, createPostBodySchema, type PostAuthorSnapshot, postAuthorSnapshotSchema, type UpdatePostBody, updatePostBodySchema, } from './post.js';
|
|
25
|
+
export { type CommunityPostWire, type CreatePostBody, communityPostWireSchema, createPostBodySchema, type PostAuthorSnapshot, postAuthorSnapshotSchema, type RepostedSource, repostedSourceSchema, type UpdatePostBody, updatePostBodySchema, } from './post.js';
|
|
26
|
+
export { type CreateRepostBody, type CreateRepostResponse, createRepostBodySchema, createRepostResponseSchema, } from './repost.js';
|
|
26
27
|
export { type PeopleListItem, type PeopleListResponse, type PeopleQueryParams, type PublicProfileWire, peopleListItemSchema, peopleListResponseSchema, peopleQueryParamsSchema, publicProfileWireSchema, } from './profile.js';
|
|
27
28
|
export { type ReportContentBody, type ReportContentKind, type ReportRecordWire, type ReportSubmissionResponse, type ReportUserBody, reportContentBodySchema, reportContentKindSchema, reportRecordWireSchema, reportSubmissionResponseSchema, reportUserBodySchema, } from './report.js';
|
|
28
|
-
export { type
|
|
29
|
+
export { type BlockedUsersListResponse, type BlockedUserWire, blockedUsersListResponseSchema, blockedUserWireSchema, COMMUNITY_SETTINGS_DEFAULTS, type CommunitySettingsWire, communitySettingsWireSchema, type UpdateCommunitySettingsBody, updateCommunitySettingsBodySchema, } from './settings.js';
|
|
29
30
|
export { type ConnectionDecisionBody, type ConnectionRecordWire, connectionDecisionBodySchema, connectionRecordWireSchema, type SendConnectionRequestResponse, sendConnectionRequestResponseSchema, type ToggleFollowResponse, toggleFollowResponseSchema, type ViewerSocialState, viewerSocialStateSchema, } from './social.js';
|
|
30
31
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EACL,KAAK,mBAAmB,EACxB,yBAAyB,GAC1B,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,0BAA0B,EAC1B,uBAAuB,EACvB,KAAK,iBAAiB,EACtB,uBAAuB,GACxB,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,eAAe,EACf,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,qBAAqB,EACrB,yBAAyB,EACzB,KAAK,oBAAoB,EACzB,0BAA0B,GAC3B,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,sBAAsB,EACtB,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,QAAQ,EACb,cAAc,EACd,sBAAsB,EACtB,KAAK,cAAc,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,uBAAuB,EACvB,KAAK,eAAe,EACpB,qBAAqB,GACtB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,cAAc,EACd,qBAAqB,EACrB,kBAAkB,EAClB,KAAK,iBAAiB,EACtB,uBAAuB,EACvB,KAAK,gBAAgB,EACrB,sBAAsB,GACvB,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,KAAK,mBAAmB,EACxB,yBAAyB,EACzB,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,wBAAwB,EACxB,+BAA+B,EAC/B,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -25,19 +25,21 @@ export { setReactionBodySchema, setReactionResponseSchema, toggleUpvoteResponseS
|
|
|
25
25
|
// ─── Enums ─────────────────────────────────────────────────────────────────
|
|
26
26
|
export { CONNECTION_STATUS_VALUES, CONTENT_KIND_VALUES, connectionStatusSchema, contentKindSchema, FEED_SORT_VALUES, feedSortSchema, PROFILE_PRIVACY_VALUES, profilePrivacySchema, REACTION_TYPE_VALUES, REPORT_REASON_VALUES, REPORT_STATUS_VALUES, reactionTypeSchema, reportReasonSchema, reportStatusSchema, VISIBILITY_LEVEL_RANK, VISIBILITY_LEVEL_VALUES, visibilityLevelSchema, } from './enums.js';
|
|
27
27
|
// ─── Feed (polymorphic union) ──────────────────────────────────────────────
|
|
28
|
-
export { feedItemSchema, feedQueryParamsSchema, feedResponseSchema, lostFoundFeedItemSchema, voiceBoxFeedItemSchema, } from './feed.js';
|
|
28
|
+
export { donateItemFeedItemSchema, feedItemSchema, feedQueryParamsSchema, feedResponseSchema, lostFoundFeedItemSchema, voiceBoxFeedItemSchema, } from './feed.js';
|
|
29
29
|
// ─── Groups ────────────────────────────────────────────────────────────────
|
|
30
|
-
export { addGroupMembersBodySchema, communityGroupWireSchema, communityGroupWithMembersSchema, createGroupBodySchema,
|
|
30
|
+
export { addGroupMembersBodySchema, communityGroupWireSchema, communityGroupWithMembersSchema, createGroupBodySchema, groupMembersListResponseSchema, groupMemberWireSchema, groupRoleSchema, groupsListResponseSchema, updateGroupBodySchema, } from './group.js';
|
|
31
31
|
// ─── Media ─────────────────────────────────────────────────────────────────
|
|
32
32
|
export { postImageSchema, postVideoSchema, } from './media.js';
|
|
33
33
|
// ─── Post ──────────────────────────────────────────────────────────────────
|
|
34
|
-
export { communityPostWireSchema, createPostBodySchema, postAuthorSnapshotSchema, updatePostBodySchema, } from './post.js';
|
|
34
|
+
export { communityPostWireSchema, createPostBodySchema, postAuthorSnapshotSchema, repostedSourceSchema, updatePostBodySchema, } from './post.js';
|
|
35
|
+
// ─── Repost (quote / amplify) ──────────────────────────────────────────────
|
|
36
|
+
export { createRepostBodySchema, createRepostResponseSchema, } from './repost.js';
|
|
35
37
|
// ─── Profile + People list ─────────────────────────────────────────────────
|
|
36
38
|
export { peopleListItemSchema, peopleListResponseSchema, peopleQueryParamsSchema, publicProfileWireSchema, } from './profile.js';
|
|
37
39
|
// ─── Reports (moderation) ──────────────────────────────────────────────────
|
|
38
40
|
export { reportContentBodySchema, reportContentKindSchema, reportRecordWireSchema, reportSubmissionResponseSchema, reportUserBodySchema, } from './report.js';
|
|
39
41
|
// ─── Settings ──────────────────────────────────────────────────────────────
|
|
40
|
-
export {
|
|
42
|
+
export { blockedUsersListResponseSchema, blockedUserWireSchema, COMMUNITY_SETTINGS_DEFAULTS, communitySettingsWireSchema, updateCommunitySettingsBodySchema, } from './settings.js';
|
|
41
43
|
// ─── Social (follow + connection) ──────────────────────────────────────────
|
|
42
44
|
export { connectionDecisionBodySchema, connectionRecordWireSchema, sendConnectionRequestResponseSchema, toggleFollowResponseSchema, viewerSocialStateSchema, } from './social.js';
|
|
43
45
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,8EAA8E;AAC9E,OAAO,EAEL,yBAAyB,GAC1B,MAAM,WAAW,CAAC;AAEnB,8EAA8E;AAC9E,OAAO,EAGL,0BAA0B,EAC1B,uBAAuB,EAEvB,uBAAuB,GACxB,MAAM,cAAc,CAAC;AAEtB,8EAA8E;AAC9E,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,eAAe,EACf,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAExB,8EAA8E;AAC9E,OAAO,EAGL,qBAAqB,EACrB,yBAAyB,EAEzB,0BAA0B,GAC3B,MAAM,iBAAiB,CAAC;AAEzB,8EAA8E;AAC9E,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EAGnB,sBAAsB,EACtB,iBAAiB,EACjB,gBAAgB,EAEhB,cAAc,EACd,sBAAsB,EAEtB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EAIpB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,uBAAuB,EAEvB,qBAAqB,GACtB,MAAM,YAAY,CAAC;AAEpB,8EAA8E;AAC9E,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,8EAA8E;AAC9E,OAAO,EAEL,yBAAyB,GAC1B,MAAM,WAAW,CAAC;AAEnB,8EAA8E;AAC9E,OAAO,EAGL,0BAA0B,EAC1B,uBAAuB,EAEvB,uBAAuB,GACxB,MAAM,cAAc,CAAC;AAEtB,8EAA8E;AAC9E,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,eAAe,EACf,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAExB,8EAA8E;AAC9E,OAAO,EAGL,qBAAqB,EACrB,yBAAyB,EAEzB,0BAA0B,GAC3B,MAAM,iBAAiB,CAAC;AAEzB,8EAA8E;AAC9E,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EAGnB,sBAAsB,EACtB,iBAAiB,EACjB,gBAAgB,EAEhB,cAAc,EACd,sBAAsB,EAEtB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EAIpB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,uBAAuB,EAEvB,qBAAqB,GACtB,MAAM,YAAY,CAAC;AAEpB,8EAA8E;AAC9E,OAAO,EAEL,wBAAwB,EAIxB,cAAc,EACd,qBAAqB,EACrB,kBAAkB,EAElB,uBAAuB,EAEvB,sBAAsB,GACvB,MAAM,WAAW,CAAC;AAEnB,8EAA8E;AAC9E,OAAO,EAEL,yBAAyB,EAIzB,wBAAwB,EACxB,+BAA+B,EAC/B,qBAAqB,EAKrB,8BAA8B,EAC9B,qBAAqB,EACrB,eAAe,EACf,wBAAwB,EAExB,qBAAqB,GACtB,MAAM,YAAY,CAAC;AAEpB,8EAA8E;AAC9E,OAAO,EAGL,eAAe,EACf,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,8EAA8E;AAC9E,OAAO,EAGL,uBAAuB,EACvB,oBAAoB,EAEpB,wBAAwB,EAExB,oBAAoB,EAEpB,oBAAoB,GACrB,MAAM,WAAW,CAAC;AAEnB,8EAA8E;AAC9E,OAAO,EAGL,sBAAsB,EACtB,0BAA0B,GAC3B,MAAM,aAAa,CAAC;AAErB,8EAA8E;AAC9E,OAAO,EAKL,oBAAoB,EACpB,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,cAAc,CAAC;AAEtB,8EAA8E;AAC9E,OAAO,EAML,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,8BAA8B,EAC9B,oBAAoB,GACrB,MAAM,aAAa,CAAC;AAErB,8EAA8E;AAC9E,OAAO,EAGL,8BAA8B,EAC9B,qBAAqB,EACrB,2BAA2B,EAE3B,2BAA2B,EAE3B,iCAAiC,GAClC,MAAM,eAAe,CAAC;AAEvB,8EAA8E;AAC9E,OAAO,EAGL,4BAA4B,EAC5B,0BAA0B,EAE1B,mCAAmC,EAEnC,0BAA0B,EAE1B,uBAAuB,GACxB,MAAM,aAAa,CAAC","sourcesContent":["/**\n * community-schema — Shared Zod schemas + TypeScript types for the\n * Jansathi hyperlocal community feature (feed, posts, engagement,\n * social graph, groups, settings).\n *\n * Single source of truth consumed by reform-backend and every product\n * frontend. The schemas mirror MongoDB / Mongoose document shapes\n * 1:1 so the same Zod validation runs at the controller boundary on\n * the backend and in the form handlers on the client.\n *\n * Cascade-upward visibility semantics: a viewer whose feed level is L\n * sees posts at L and every BROADER level matching their area lineage.\n * See `./enums.ts#VISIBILITY_LEVEL_VALUES` for the level rank table.\n *\n * @module community-schema\n */\n\n// ─── Area lineage snapshot ─────────────────────────────────────────────────\nexport {\n type AreaLineageSnapshot,\n areaLineageSnapshotSchema,\n} from './area.js';\n\n// ─── Comment ───────────────────────────────────────────────────────────────\nexport {\n type CommunityCommentWire,\n type CreateCommentBody,\n communityCommentWireSchema,\n createCommentBodySchema,\n type UpdateCommentBody,\n updateCommentBodySchema,\n} from './comment.js';\n\n// ─── Constants ─────────────────────────────────────────────────────────────\nexport {\n COMMENT_MAX_BODY_CHARS,\n COMMENTS_PAGE_SIZE,\n EDIT_GRACE_WINDOW_MS,\n FEED_PAGE_SIZE,\n GROUP_MAX_MEMBERS,\n GROUP_NAME_MAX_CHARS,\n GROUP_NAME_MIN_CHARS,\n PEOPLE_PAGE_SIZE,\n POST_MAX_BODY_CHARS,\n POST_MAX_IMAGE_BYTES,\n POST_MAX_IMAGES,\n POST_MAX_VIDEO_BYTES,\n POST_MAX_VIDEO_SECONDS,\n POST_MAX_VIDEOS,\n PROFILE_MAX_BIO_CHARS,\n REPLIES_PRELOAD_COUNT,\n} from './constants.js';\n\n// ─── Engagement (upvote + reactions) ───────────────────────────────────────\nexport {\n type SetReactionBody,\n type SetReactionResponse,\n setReactionBodySchema,\n setReactionResponseSchema,\n type ToggleUpvoteResponse,\n toggleUpvoteResponseSchema,\n} from './engagement.js';\n\n// ─── Enums ─────────────────────────────────────────────────────────────────\nexport {\n CONNECTION_STATUS_VALUES,\n CONTENT_KIND_VALUES,\n type ConnectionStatus,\n type ContentKind,\n connectionStatusSchema,\n contentKindSchema,\n FEED_SORT_VALUES,\n type FeedSort,\n feedSortSchema,\n PROFILE_PRIVACY_VALUES,\n type ProfilePrivacy,\n profilePrivacySchema,\n REACTION_TYPE_VALUES,\n REPORT_REASON_VALUES,\n REPORT_STATUS_VALUES,\n type ReactionType,\n type ReportReason,\n type ReportStatus,\n reactionTypeSchema,\n reportReasonSchema,\n reportStatusSchema,\n VISIBILITY_LEVEL_RANK,\n VISIBILITY_LEVEL_VALUES,\n type VisibilityLevel,\n visibilityLevelSchema,\n} from './enums.js';\n\n// ─── Feed (polymorphic union) ──────────────────────────────────────────────\nexport {\n type DonateItemFeedItem,\n donateItemFeedItemSchema,\n type FeedItem,\n type FeedQueryParams,\n type FeedResponse,\n feedItemSchema,\n feedQueryParamsSchema,\n feedResponseSchema,\n type LostFoundFeedItem,\n lostFoundFeedItemSchema,\n type VoiceBoxFeedItem,\n voiceBoxFeedItemSchema,\n} from './feed.js';\n\n// ─── Groups ────────────────────────────────────────────────────────────────\nexport {\n type AddGroupMembersBody,\n addGroupMembersBodySchema,\n type CommunityGroupWire,\n type CommunityGroupWithMembers,\n type CreateGroupBody,\n communityGroupWireSchema,\n communityGroupWithMembersSchema,\n createGroupBodySchema,\n type GroupMembersListResponse,\n type GroupMemberWire,\n type GroupRole,\n type GroupsListResponse,\n groupMembersListResponseSchema,\n groupMemberWireSchema,\n groupRoleSchema,\n groupsListResponseSchema,\n type UpdateGroupBody,\n updateGroupBodySchema,\n} from './group.js';\n\n// ─── Media ─────────────────────────────────────────────────────────────────\nexport {\n type PostImage,\n type PostVideo,\n postImageSchema,\n postVideoSchema,\n} from './media.js';\n\n// ─── Post ──────────────────────────────────────────────────────────────────\nexport {\n type CommunityPostWire,\n type CreatePostBody,\n communityPostWireSchema,\n createPostBodySchema,\n type PostAuthorSnapshot,\n postAuthorSnapshotSchema,\n type RepostedSource,\n repostedSourceSchema,\n type UpdatePostBody,\n updatePostBodySchema,\n} from './post.js';\n\n// ─── Repost (quote / amplify) ──────────────────────────────────────────────\nexport {\n type CreateRepostBody,\n type CreateRepostResponse,\n createRepostBodySchema,\n createRepostResponseSchema,\n} from './repost.js';\n\n// ─── Profile + People list ─────────────────────────────────────────────────\nexport {\n type PeopleListItem,\n type PeopleListResponse,\n type PeopleQueryParams,\n type PublicProfileWire,\n peopleListItemSchema,\n peopleListResponseSchema,\n peopleQueryParamsSchema,\n publicProfileWireSchema,\n} from './profile.js';\n\n// ─── Reports (moderation) ──────────────────────────────────────────────────\nexport {\n type ReportContentBody,\n type ReportContentKind,\n type ReportRecordWire,\n type ReportSubmissionResponse,\n type ReportUserBody,\n reportContentBodySchema,\n reportContentKindSchema,\n reportRecordWireSchema,\n reportSubmissionResponseSchema,\n reportUserBodySchema,\n} from './report.js';\n\n// ─── Settings ──────────────────────────────────────────────────────────────\nexport {\n type BlockedUsersListResponse,\n type BlockedUserWire,\n blockedUsersListResponseSchema,\n blockedUserWireSchema,\n COMMUNITY_SETTINGS_DEFAULTS,\n type CommunitySettingsWire,\n communitySettingsWireSchema,\n type UpdateCommunitySettingsBody,\n updateCommunitySettingsBodySchema,\n} from './settings.js';\n\n// ─── Social (follow + connection) ──────────────────────────────────────────\nexport {\n type ConnectionDecisionBody,\n type ConnectionRecordWire,\n connectionDecisionBodySchema,\n connectionRecordWireSchema,\n type SendConnectionRequestResponse,\n sendConnectionRequestResponseSchema,\n type ToggleFollowResponse,\n toggleFollowResponseSchema,\n type ViewerSocialState,\n viewerSocialStateSchema,\n} from './social.js';\n"]}
|
package/dist/post.d.ts
CHANGED
|
@@ -26,6 +26,42 @@ export declare const postAuthorSnapshotSchema: z.ZodObject<{
|
|
|
26
26
|
localName: z.ZodOptional<z.ZodString>;
|
|
27
27
|
}, z.core.$strip>;
|
|
28
28
|
export type PostAuthorSnapshot = z.infer<typeof postAuthorSnapshotSchema>;
|
|
29
|
+
/**
|
|
30
|
+
* Compact embed shape used when a CommunityPost is a repost (caption +
|
|
31
|
+
* optional quote of another item). Modelled after Twitter's quote-tweet
|
|
32
|
+
* embed: byline + truncated text/title + first image + kind badge + the
|
|
33
|
+
* moment-of-creation timestamp.
|
|
34
|
+
*
|
|
35
|
+
* Engagement counts are intentionally NOT included — they'd drift
|
|
36
|
+
* relative to the live source. The card embeds this as a static teaser
|
|
37
|
+
* that links to the source for the live numbers.
|
|
38
|
+
*
|
|
39
|
+
* Backend snapshots these fields at repost-create time from the source
|
|
40
|
+
* row (post text / item title / first photo / status badge), so the
|
|
41
|
+
* embed survives source edits / soft-deletes / hides — the user's
|
|
42
|
+
* reaction at repost time is preserved.
|
|
43
|
+
*/
|
|
44
|
+
export declare const repostedSourceSchema: z.ZodObject<{
|
|
45
|
+
contentKind: z.ZodEnum<{
|
|
46
|
+
post: "post";
|
|
47
|
+
lost_found: "lost_found";
|
|
48
|
+
voice_box: "voice_box";
|
|
49
|
+
donate_item: "donate_item";
|
|
50
|
+
}>;
|
|
51
|
+
_id: z.ZodString;
|
|
52
|
+
author: z.ZodObject<{
|
|
53
|
+
userId: z.ZodString;
|
|
54
|
+
displayName: z.ZodString;
|
|
55
|
+
avatarUrl: z.ZodOptional<z.ZodString>;
|
|
56
|
+
localName: z.ZodOptional<z.ZodString>;
|
|
57
|
+
}, z.core.$strip>;
|
|
58
|
+
title: z.ZodString;
|
|
59
|
+
body: z.ZodOptional<z.ZodString>;
|
|
60
|
+
imageUrl: z.ZodOptional<z.ZodString>;
|
|
61
|
+
kindBadge: z.ZodOptional<z.ZodString>;
|
|
62
|
+
createdAt: z.ZodString;
|
|
63
|
+
}, z.core.$strip>;
|
|
64
|
+
export type RepostedSource = z.infer<typeof repostedSourceSchema>;
|
|
29
65
|
/**
|
|
30
66
|
* A community post as it appears in the feed and on the single-post
|
|
31
67
|
* page. Engagement counts are denormalised onto the document for
|
|
@@ -74,7 +110,28 @@ export declare const communityPostWireSchema: z.ZodObject<{
|
|
|
74
110
|
}, z.core.$strip>;
|
|
75
111
|
upvoteCount: z.ZodNumber;
|
|
76
112
|
commentCount: z.ZodNumber;
|
|
113
|
+
repostCount: z.ZodNumber;
|
|
77
114
|
reactionCounts: z.ZodRecord<z.ZodString, z.ZodNumber>;
|
|
115
|
+
repostOf: z.ZodOptional<z.ZodObject<{
|
|
116
|
+
contentKind: z.ZodEnum<{
|
|
117
|
+
post: "post";
|
|
118
|
+
lost_found: "lost_found";
|
|
119
|
+
voice_box: "voice_box";
|
|
120
|
+
donate_item: "donate_item";
|
|
121
|
+
}>;
|
|
122
|
+
_id: z.ZodString;
|
|
123
|
+
author: z.ZodObject<{
|
|
124
|
+
userId: z.ZodString;
|
|
125
|
+
displayName: z.ZodString;
|
|
126
|
+
avatarUrl: z.ZodOptional<z.ZodString>;
|
|
127
|
+
localName: z.ZodOptional<z.ZodString>;
|
|
128
|
+
}, z.core.$strip>;
|
|
129
|
+
title: z.ZodString;
|
|
130
|
+
body: z.ZodOptional<z.ZodString>;
|
|
131
|
+
imageUrl: z.ZodOptional<z.ZodString>;
|
|
132
|
+
kindBadge: z.ZodOptional<z.ZodString>;
|
|
133
|
+
createdAt: z.ZodString;
|
|
134
|
+
}, z.core.$strip>>;
|
|
78
135
|
createdAt: z.ZodString;
|
|
79
136
|
editedAt: z.ZodNullable<z.ZodString>;
|
|
80
137
|
deletedAt: z.ZodNullable<z.ZodString>;
|
|
@@ -82,6 +139,7 @@ export declare const communityPostWireSchema: z.ZodObject<{
|
|
|
82
139
|
upvoted: z.ZodBoolean;
|
|
83
140
|
reaction: z.ZodNullable<z.ZodString>;
|
|
84
141
|
isAuthor: z.ZodBoolean;
|
|
142
|
+
reposted: z.ZodBoolean;
|
|
85
143
|
}, z.core.$strip>>;
|
|
86
144
|
}, z.core.$strip>;
|
|
87
145
|
export type CommunityPostWire = z.infer<typeof communityPostWireSchema>;
|
package/dist/post.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"post.d.ts","sourceRoot":"","sources":["../src/post.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAQxB;;;;;;;;;GASG;AACH,eAAO,MAAM,wBAAwB;;;;;iBAWnC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAI1E;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB
|
|
1
|
+
{"version":3,"file":"post.d.ts","sourceRoot":"","sources":["../src/post.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAQxB;;;;;;;;;GASG;AACH,eAAO,MAAM,wBAAwB;;;;;iBAWnC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAI1E;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;iBAuB/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAIlE;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmDlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAIxE;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;iBAM/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;;;GAIG;AACH,eAAO,MAAM,oBAAoB;;iBAE/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
|
package/dist/post.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
import { z } from 'zod';
|
|
12
12
|
import { areaLineageSnapshotSchema } from './area.js';
|
|
13
13
|
import { POST_MAX_BODY_CHARS, POST_MAX_IMAGES, POST_MAX_VIDEOS } from './constants.js';
|
|
14
|
-
import { visibilityLevelSchema } from './enums.js';
|
|
14
|
+
import { contentKindSchema, visibilityLevelSchema } from './enums.js';
|
|
15
15
|
import { postImageSchema, postVideoSchema } from './media.js';
|
|
16
16
|
// ─── Author snapshot (denormalised on every post) ──────────────────────────
|
|
17
17
|
/**
|
|
@@ -36,6 +36,46 @@ export const postAuthorSnapshotSchema = z.object({
|
|
|
36
36
|
*/
|
|
37
37
|
localName: z.string().optional(),
|
|
38
38
|
});
|
|
39
|
+
// ─── Reposted source snapshot ──────────────────────────────────────────────
|
|
40
|
+
/**
|
|
41
|
+
* Compact embed shape used when a CommunityPost is a repost (caption +
|
|
42
|
+
* optional quote of another item). Modelled after Twitter's quote-tweet
|
|
43
|
+
* embed: byline + truncated text/title + first image + kind badge + the
|
|
44
|
+
* moment-of-creation timestamp.
|
|
45
|
+
*
|
|
46
|
+
* Engagement counts are intentionally NOT included — they'd drift
|
|
47
|
+
* relative to the live source. The card embeds this as a static teaser
|
|
48
|
+
* that links to the source for the live numbers.
|
|
49
|
+
*
|
|
50
|
+
* Backend snapshots these fields at repost-create time from the source
|
|
51
|
+
* row (post text / item title / first photo / status badge), so the
|
|
52
|
+
* embed survives source edits / soft-deletes / hides — the user's
|
|
53
|
+
* reaction at repost time is preserved.
|
|
54
|
+
*/
|
|
55
|
+
export const repostedSourceSchema = z.object({
|
|
56
|
+
/** Which kind was reposted. Lets the embed render the right icon. */
|
|
57
|
+
contentKind: contentKindSchema,
|
|
58
|
+
/** Source row's id — tap-embed navigates to its thread / detail page. */
|
|
59
|
+
_id: z.string(),
|
|
60
|
+
/** Author snapshot of the source at repost time. */
|
|
61
|
+
author: postAuthorSnapshotSchema,
|
|
62
|
+
/** Primary text. For posts: the body text (truncated). For lost_found /
|
|
63
|
+
* voice_box / donate_item: the title. */
|
|
64
|
+
title: z.string(),
|
|
65
|
+
/** Optional secondary line. For posts: unused. For legacy kinds: the
|
|
66
|
+
* description (truncated server-side). */
|
|
67
|
+
body: z.string().optional(),
|
|
68
|
+
/** First image if any. */
|
|
69
|
+
imageUrl: z.string().url().optional(),
|
|
70
|
+
/** Small kind-specific badge:
|
|
71
|
+
* - posts → undefined
|
|
72
|
+
* - lost_found → 'lost' | 'found'
|
|
73
|
+
* - voice_box → 'complaint' | 'suggestion'
|
|
74
|
+
* - donate_item → 'PENDING' | 'VERIFIED' | 'AT_CENTER' | 'DONATED'
|
|
75
|
+
*/
|
|
76
|
+
kindBadge: z.string().optional(),
|
|
77
|
+
createdAt: z.string().datetime(),
|
|
78
|
+
});
|
|
39
79
|
// ─── Wire shape — what the server returns ──────────────────────────────────
|
|
40
80
|
/**
|
|
41
81
|
* A community post as it appears in the feed and on the single-post
|
|
@@ -47,7 +87,7 @@ export const communityPostWireSchema = z.object({
|
|
|
47
87
|
_id: z.string(),
|
|
48
88
|
contentKind: z.literal('post'),
|
|
49
89
|
author: postAuthorSnapshotSchema,
|
|
50
|
-
// Body
|
|
90
|
+
// Body — for a repost, this carries the caption (may be empty).
|
|
51
91
|
text: z.string().max(POST_MAX_BODY_CHARS),
|
|
52
92
|
images: z.array(postImageSchema).max(POST_MAX_IMAGES),
|
|
53
93
|
videos: z.array(postVideoSchema).max(POST_MAX_VIDEOS),
|
|
@@ -57,8 +97,15 @@ export const communityPostWireSchema = z.object({
|
|
|
57
97
|
// Denormalised engagement counters (drive feed sort + card render)
|
|
58
98
|
upvoteCount: z.number().int().nonnegative(),
|
|
59
99
|
commentCount: z.number().int().nonnegative(),
|
|
100
|
+
/** How many times this post has been reposted. Incremented by the
|
|
101
|
+
* repost endpoint; reposts of reposts are blocked server-side. */
|
|
102
|
+
repostCount: z.number().int().nonnegative(),
|
|
60
103
|
/** Map of `ReactionType` → count, e.g. { like: 4, love: 1 }. */
|
|
61
104
|
reactionCounts: z.record(z.string(), z.number().int().nonnegative()),
|
|
105
|
+
/** Source-snapshot when this post is a repost. Absent on regular posts.
|
|
106
|
+
* The wrapper post owns its own engagement counters; this embed is
|
|
107
|
+
* a static teaser of the original at repost time. */
|
|
108
|
+
repostOf: repostedSourceSchema.optional(),
|
|
62
109
|
// Lifecycle
|
|
63
110
|
createdAt: z.string().datetime(),
|
|
64
111
|
/** Last edit timestamp, or null if never edited. Edit window is
|
|
@@ -75,6 +122,10 @@ export const communityPostWireSchema = z.object({
|
|
|
75
122
|
reaction: z.string().nullable(),
|
|
76
123
|
/** True when the viewer authored the post (controls edit / delete buttons). */
|
|
77
124
|
isAuthor: z.boolean(),
|
|
125
|
+
/** True when the viewer has already reposted this source. The
|
|
126
|
+
* client uses this to render the repost button as "already
|
|
127
|
+
* reposted" rather than as a fresh CTA. */
|
|
128
|
+
reposted: z.boolean(),
|
|
78
129
|
})
|
|
79
130
|
.optional(),
|
|
80
131
|
});
|
package/dist/post.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"post.js","sourceRoot":"","sources":["../src/post.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Community post wire shapes.\n *\n * A \"post\" is the native community content kind (text-primary + media).\n * Lost-and-found and voice-box items show up in the same feed via\n * polymorphic union; their shapes live in their own schema packages\n * and are projected into a `FeedItem` envelope (see `./feed.ts`).\n *\n * @module community-schema/post\n */\n\nimport { z } from 'zod';\nimport { areaLineageSnapshotSchema } from './area.js';\nimport { POST_MAX_BODY_CHARS, POST_MAX_IMAGES, POST_MAX_VIDEOS } from './constants.js';\nimport { visibilityLevelSchema } from './enums.js';\nimport { postImageSchema, postVideoSchema } from './media.js';\n\n// ─── Author snapshot (denormalised on every post) ──────────────────────────\n\n/**\n * The author's display info captured at post time. Denormalising\n * `displayName` / `avatarUrl` / `localName` here avoids a $lookup\n * against the User collection on every feed read — feed scans 20–40\n * posts per page and population would be a hot path.\n *\n * The User document remains the source of truth; a background job\n * (or a hook on User.findOneAndUpdate) refreshes recent posts when\n * a user changes their display name or avatar.\n */\nexport const postAuthorSnapshotSchema = z.object({\n userId: z.string(),\n displayName: z.string(),\n avatarUrl: z.string().url().optional(),\n /**\n * The author's \"local\" area label at post time, e.g. \"Rohini Sector 15\".\n * Powers the byline \"<DisplayName> · <localName> · <relativeTime>\".\n * Hidden when the author has a private profile and the viewer is\n * not an accepted Connection.\n */\n localName: z.string().optional(),\n});\nexport type PostAuthorSnapshot = z.infer<typeof postAuthorSnapshotSchema>;\n\n// ─── Wire shape — what the server returns ──────────────────────────────────\n\n/**\n * A community post as it appears in the feed and on the single-post\n * page. Engagement counts are denormalised onto the document for\n * fast feed sorting; the per-user reaction state (\"did I upvote this?\")\n * is computed at read time and returned in the `viewer` block.\n */\nexport const communityPostWireSchema = z.object({\n _id: z.string(),\n contentKind: z.literal('post'),\n author: postAuthorSnapshotSchema,\n\n // Body\n text: z.string().max(POST_MAX_BODY_CHARS),\n images: z.array(postImageSchema).max(POST_MAX_IMAGES),\n videos: z.array(postVideoSchema).max(POST_MAX_VIDEOS),\n\n // Audience\n visibilityLevel: visibilityLevelSchema,\n areaLineage: areaLineageSnapshotSchema,\n\n // Denormalised engagement counters (drive feed sort + card render)\n upvoteCount: z.number().int().nonnegative(),\n commentCount: z.number().int().nonnegative(),\n /** Map of `ReactionType` → count, e.g. { like: 4, love: 1 }. */\n reactionCounts: z.record(z.string(), z.number().int().nonnegative()),\n\n // Lifecycle\n createdAt: z.string().datetime(),\n /** Last edit timestamp, or null if never edited. Edit window is\n * enforced by the server at write time, not by this schema. */\n editedAt: z.string().datetime().nullable(),\n deletedAt: z.string().datetime().nullable(),\n\n // Per-viewer state (filled by the server at read time)\n viewer: z\n .object({\n upvoted: z.boolean(),\n /** The reaction the viewer chose, or null. Mutually exclusive\n * with `upvoted` is intentionally NOT enforced — they're two\n * separate axes per the product decision. */\n reaction: z.string().nullable(),\n /** True when the viewer authored the post (controls edit / delete buttons). */\n isAuthor: z.boolean(),\n })\n .optional(),\n});\nexport type CommunityPostWire = z.infer<typeof communityPostWireSchema>;\n\n// ─── Create / update bodies ────────────────────────────────────────────────\n\n/**\n * What the client sends to `POST /api/v1/community/posts`. The author\n * is taken from the authenticated request; visibility area is resolved\n * server-side from the user's primary area lineage (the client cannot\n * spoof a different area).\n */\nexport const createPostBodySchema = z.object({\n text: z.string().min(1).max(POST_MAX_BODY_CHARS),\n images: z.array(postImageSchema).max(POST_MAX_IMAGES).optional(),\n videos: z.array(postVideoSchema).max(POST_MAX_VIDEOS).optional(),\n /** Default chosen by the client is `local`; the server still validates. */\n visibilityLevel: visibilityLevelSchema,\n});\nexport type CreatePostBody = z.infer<typeof createPostBodySchema>;\n\n/**\n * What the client sends to `PATCH /api/v1/community/posts/:id`. Only\n * the text body is editable — media additions / removals require a new\n * post (matches Twitter / FB convention).\n */\nexport const updatePostBodySchema = z.object({\n text: z.string().min(1).max(POST_MAX_BODY_CHARS),\n});\nexport type UpdatePostBody = z.infer<typeof updatePostBodySchema>;\n"]}
|
|
1
|
+
{"version":3,"file":"post.js","sourceRoot":"","sources":["../src/post.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACvF,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE9D,8EAA8E;AAE9E;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACtC;;;;;OAKG;IACH,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACjC,CAAC,CAAC;AAGH,8EAA8E;AAE9E;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,qEAAqE;IACrE,WAAW,EAAE,iBAAiB;IAC9B,yEAAyE;IACzE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,oDAAoD;IACpD,MAAM,EAAE,wBAAwB;IAChC;8CAC0C;IAC1C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB;+CAC2C;IAC3C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,0BAA0B;IAC1B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACrC;;;;;OAKG;IACH,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACjC,CAAC,CAAC;AAGH,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IAC9B,MAAM,EAAE,wBAAwB;IAEhC,gEAAgE;IAChE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,mBAAmB,CAAC;IACzC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC;IACrD,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC;IAErD,WAAW;IACX,eAAe,EAAE,qBAAqB;IACtC,WAAW,EAAE,yBAAyB;IAEtC,mEAAmE;IACnE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IAC3C,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IAC5C;uEACmE;IACnE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IAC3C,gEAAgE;IAChE,cAAc,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC;IAEpE;;0DAEsD;IACtD,QAAQ,EAAE,oBAAoB,CAAC,QAAQ,EAAE;IAEzC,YAAY;IACZ,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC;oEACgE;IAChE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAC1C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAE3C,uDAAuD;IACvD,MAAM,EAAE,CAAC;SACN,MAAM,CAAC;QACN,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;QACpB;;sDAE8C;QAC9C,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC/B,+EAA+E;QAC/E,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE;QACrB;;oDAE4C;QAC5C,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE;KACtB,CAAC;SACD,QAAQ,EAAE;CACd,CAAC,CAAC;AAGH,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,mBAAmB,CAAC;IAChD,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,QAAQ,EAAE;IAChE,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,QAAQ,EAAE;IAChE,2EAA2E;IAC3E,eAAe,EAAE,qBAAqB;CACvC,CAAC,CAAC;AAGH;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,mBAAmB,CAAC;CACjD,CAAC,CAAC","sourcesContent":["/**\n * Community post wire shapes.\n *\n * A \"post\" is the native community content kind (text-primary + media).\n * Lost-and-found and voice-box items show up in the same feed via\n * polymorphic union; their shapes live in their own schema packages\n * and are projected into a `FeedItem` envelope (see `./feed.ts`).\n *\n * @module community-schema/post\n */\n\nimport { z } from 'zod';\nimport { areaLineageSnapshotSchema } from './area.js';\nimport { POST_MAX_BODY_CHARS, POST_MAX_IMAGES, POST_MAX_VIDEOS } from './constants.js';\nimport { contentKindSchema, visibilityLevelSchema } from './enums.js';\nimport { postImageSchema, postVideoSchema } from './media.js';\n\n// ─── Author snapshot (denormalised on every post) ──────────────────────────\n\n/**\n * The author's display info captured at post time. Denormalising\n * `displayName` / `avatarUrl` / `localName` here avoids a $lookup\n * against the User collection on every feed read — feed scans 20–40\n * posts per page and population would be a hot path.\n *\n * The User document remains the source of truth; a background job\n * (or a hook on User.findOneAndUpdate) refreshes recent posts when\n * a user changes their display name or avatar.\n */\nexport const postAuthorSnapshotSchema = z.object({\n userId: z.string(),\n displayName: z.string(),\n avatarUrl: z.string().url().optional(),\n /**\n * The author's \"local\" area label at post time, e.g. \"Rohini Sector 15\".\n * Powers the byline \"<DisplayName> · <localName> · <relativeTime>\".\n * Hidden when the author has a private profile and the viewer is\n * not an accepted Connection.\n */\n localName: z.string().optional(),\n});\nexport type PostAuthorSnapshot = z.infer<typeof postAuthorSnapshotSchema>;\n\n// ─── Reposted source snapshot ──────────────────────────────────────────────\n\n/**\n * Compact embed shape used when a CommunityPost is a repost (caption +\n * optional quote of another item). Modelled after Twitter's quote-tweet\n * embed: byline + truncated text/title + first image + kind badge + the\n * moment-of-creation timestamp.\n *\n * Engagement counts are intentionally NOT included — they'd drift\n * relative to the live source. The card embeds this as a static teaser\n * that links to the source for the live numbers.\n *\n * Backend snapshots these fields at repost-create time from the source\n * row (post text / item title / first photo / status badge), so the\n * embed survives source edits / soft-deletes / hides — the user's\n * reaction at repost time is preserved.\n */\nexport const repostedSourceSchema = z.object({\n /** Which kind was reposted. Lets the embed render the right icon. */\n contentKind: contentKindSchema,\n /** Source row's id — tap-embed navigates to its thread / detail page. */\n _id: z.string(),\n /** Author snapshot of the source at repost time. */\n author: postAuthorSnapshotSchema,\n /** Primary text. For posts: the body text (truncated). For lost_found /\n * voice_box / donate_item: the title. */\n title: z.string(),\n /** Optional secondary line. For posts: unused. For legacy kinds: the\n * description (truncated server-side). */\n body: z.string().optional(),\n /** First image if any. */\n imageUrl: z.string().url().optional(),\n /** Small kind-specific badge:\n * - posts → undefined\n * - lost_found → 'lost' | 'found'\n * - voice_box → 'complaint' | 'suggestion'\n * - donate_item → 'PENDING' | 'VERIFIED' | 'AT_CENTER' | 'DONATED'\n */\n kindBadge: z.string().optional(),\n createdAt: z.string().datetime(),\n});\nexport type RepostedSource = z.infer<typeof repostedSourceSchema>;\n\n// ─── Wire shape — what the server returns ──────────────────────────────────\n\n/**\n * A community post as it appears in the feed and on the single-post\n * page. Engagement counts are denormalised onto the document for\n * fast feed sorting; the per-user reaction state (\"did I upvote this?\")\n * is computed at read time and returned in the `viewer` block.\n */\nexport const communityPostWireSchema = z.object({\n _id: z.string(),\n contentKind: z.literal('post'),\n author: postAuthorSnapshotSchema,\n\n // Body — for a repost, this carries the caption (may be empty).\n text: z.string().max(POST_MAX_BODY_CHARS),\n images: z.array(postImageSchema).max(POST_MAX_IMAGES),\n videos: z.array(postVideoSchema).max(POST_MAX_VIDEOS),\n\n // Audience\n visibilityLevel: visibilityLevelSchema,\n areaLineage: areaLineageSnapshotSchema,\n\n // Denormalised engagement counters (drive feed sort + card render)\n upvoteCount: z.number().int().nonnegative(),\n commentCount: z.number().int().nonnegative(),\n /** How many times this post has been reposted. Incremented by the\n * repost endpoint; reposts of reposts are blocked server-side. */\n repostCount: z.number().int().nonnegative(),\n /** Map of `ReactionType` → count, e.g. { like: 4, love: 1 }. */\n reactionCounts: z.record(z.string(), z.number().int().nonnegative()),\n\n /** Source-snapshot when this post is a repost. Absent on regular posts.\n * The wrapper post owns its own engagement counters; this embed is\n * a static teaser of the original at repost time. */\n repostOf: repostedSourceSchema.optional(),\n\n // Lifecycle\n createdAt: z.string().datetime(),\n /** Last edit timestamp, or null if never edited. Edit window is\n * enforced by the server at write time, not by this schema. */\n editedAt: z.string().datetime().nullable(),\n deletedAt: z.string().datetime().nullable(),\n\n // Per-viewer state (filled by the server at read time)\n viewer: z\n .object({\n upvoted: z.boolean(),\n /** The reaction the viewer chose, or null. Mutually exclusive\n * with `upvoted` is intentionally NOT enforced — they're two\n * separate axes per the product decision. */\n reaction: z.string().nullable(),\n /** True when the viewer authored the post (controls edit / delete buttons). */\n isAuthor: z.boolean(),\n /** True when the viewer has already reposted this source. The\n * client uses this to render the repost button as \"already\n * reposted\" rather than as a fresh CTA. */\n reposted: z.boolean(),\n })\n .optional(),\n});\nexport type CommunityPostWire = z.infer<typeof communityPostWireSchema>;\n\n// ─── Create / update bodies ────────────────────────────────────────────────\n\n/**\n * What the client sends to `POST /api/v1/community/posts`. The author\n * is taken from the authenticated request; visibility area is resolved\n * server-side from the user's primary area lineage (the client cannot\n * spoof a different area).\n */\nexport const createPostBodySchema = z.object({\n text: z.string().min(1).max(POST_MAX_BODY_CHARS),\n images: z.array(postImageSchema).max(POST_MAX_IMAGES).optional(),\n videos: z.array(postVideoSchema).max(POST_MAX_VIDEOS).optional(),\n /** Default chosen by the client is `local`; the server still validates. */\n visibilityLevel: visibilityLevelSchema,\n});\nexport type CreatePostBody = z.infer<typeof createPostBodySchema>;\n\n/**\n * What the client sends to `PATCH /api/v1/community/posts/:id`. Only\n * the text body is editable — media additions / removals require a new\n * post (matches Twitter / FB convention).\n */\nexport const updatePostBodySchema = z.object({\n text: z.string().min(1).max(POST_MAX_BODY_CHARS),\n});\nexport type UpdatePostBody = z.infer<typeof updatePostBodySchema>;\n"]}
|
package/dist/report.d.ts
CHANGED
|
@@ -30,6 +30,7 @@ export declare const reportContentKindSchema: z.ZodEnum<{
|
|
|
30
30
|
post: "post";
|
|
31
31
|
lost_found: "lost_found";
|
|
32
32
|
voice_box: "voice_box";
|
|
33
|
+
donate_item: "donate_item";
|
|
33
34
|
comment: "comment";
|
|
34
35
|
}>;
|
|
35
36
|
export type ReportContentKind = z.infer<typeof reportContentKindSchema>;
|
|
@@ -42,6 +43,7 @@ export declare const reportContentBodySchema: z.ZodObject<{
|
|
|
42
43
|
post: "post";
|
|
43
44
|
lost_found: "lost_found";
|
|
44
45
|
voice_box: "voice_box";
|
|
46
|
+
donate_item: "donate_item";
|
|
45
47
|
comment: "comment";
|
|
46
48
|
}>;
|
|
47
49
|
contentId: z.ZodString;
|
package/dist/report.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB;;;;;;EAMlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAIxE;;;GAGG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;iBASlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE;;;GAGG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;iBAI/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAIlE;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBASjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE;;;;;;GAMG;AACH,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAGzC,CAAC;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC"}
|
package/dist/report.js
CHANGED
|
@@ -27,7 +27,13 @@ import { reportReasonSchema, reportStatusSchema } from './enums.js';
|
|
|
27
27
|
* are also reportable. Lives here — not in `enums.ts` — to keep the
|
|
28
28
|
* feed/post schemas free of the comment value.
|
|
29
29
|
*/
|
|
30
|
-
export const reportContentKindSchema = z.enum([
|
|
30
|
+
export const reportContentKindSchema = z.enum([
|
|
31
|
+
'post',
|
|
32
|
+
'lost_found',
|
|
33
|
+
'voice_box',
|
|
34
|
+
'donate_item',
|
|
35
|
+
'comment',
|
|
36
|
+
]);
|
|
31
37
|
// ─── Body shapes ───────────────────────────────────────────────────────────
|
|
32
38
|
/**
|
|
33
39
|
* Body for `POST /api/v1/community/reports`. Reports a piece of
|
package/dist/report.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEpE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEpE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,IAAI,CAAC;IAC5C,MAAM;IACN,YAAY;IACZ,WAAW;IACX,aAAa;IACb,SAAS;CACV,CAAC,CAAC;AAGH,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C;uDACmD;IACnD,WAAW,EAAE,uBAAuB;IACpC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,MAAM,EAAE,kBAAkB;IAC1B;2DACuD;IACvD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE;CACzC,CAAC,CAAC;AAGH;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;IACxB,MAAM,EAAE,kBAAkB;IAC1B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE;CACzC,CAAC,CAAC;AAGH,8EAA8E;AAE9E;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IAC1E,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACnC,MAAM,EAAE,kBAAkB;IAC1B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,MAAM,EAAE,kBAAkB;IAC1B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACjC,CAAC,CAAC;AAGH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC,MAAM,CAAC;IACrD,MAAM,EAAE,sBAAsB;IAC9B,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;CACrB,CAAC,CAAC","sourcesContent":["/**\n * Content + user reporting wire shapes for moderation.\n *\n * Any signed-in viewer can report:\n * - feed content (post / lost-found / voice-box)\n * - comments (one-level thread under a feed item)\n * - users (the profile + everything they author)\n *\n * Reports land in a moderation queue surfaced to admins; admin actions\n * are out of scope for this schema package.\n *\n * Endpoints:\n * POST /reports file a content report\n * POST /reports/user file a user report\n *\n * Both return a `ReportSubmissionResponse` carrying the resulting\n * record + a `created` flag so the UI can distinguish first-submission\n * from idempotent repeat (and toast accordingly).\n *\n * @module community-schema/report\n */\n\nimport { z } from 'zod';\nimport { reportReasonSchema, reportStatusSchema } from './enums.js';\n\n/**\n * The four kinds of community CONTENT that can be reported. Wider than\n * `contentKindSchema` (which covers only feed items) because comments\n * are also reportable. Lives here — not in `enums.ts` — to keep the\n * feed/post schemas free of the comment value.\n */\nexport const reportContentKindSchema = z.enum([\n 'post',\n 'lost_found',\n 'voice_box',\n 'donate_item',\n 'comment',\n]);\nexport type ReportContentKind = z.infer<typeof reportContentKindSchema>;\n\n// ─── Body shapes ───────────────────────────────────────────────────────────\n\n/**\n * Body for `POST /api/v1/community/reports`. Reports a piece of\n * content (post / lost-found / voice-box / comment).\n */\nexport const reportContentBodySchema = z.object({\n /** Still named `contentKind` for backward compat with 0.1.x callers;\n * semantically it now also includes 'comment'. */\n contentKind: reportContentKindSchema,\n contentId: z.string(),\n reason: reportReasonSchema,\n /** Free-text detail. Required when `reason === 'other'`, optional\n * otherwise (the server enforces the conditional). */\n details: z.string().max(2000).optional(),\n});\nexport type ReportContentBody = z.infer<typeof reportContentBodySchema>;\n\n/**\n * Body for `POST /api/v1/community/reports/user`. Reports a user's\n * profile / general behaviour rather than a specific piece of content.\n */\nexport const reportUserBodySchema = z.object({\n targetUserId: z.string(),\n reason: reportReasonSchema,\n details: z.string().max(2000).optional(),\n});\nexport type ReportUserBody = z.infer<typeof reportUserBodySchema>;\n\n// ─── Record + response shapes ──────────────────────────────────────────────\n\n/**\n * Mongo-side record of a single report, projected for wire.\n *\n * For content reports `targetKind` is one of the content kinds and\n * `contentId` holds the target; `targetUserId` is undefined. For user\n * reports `targetKind === 'user'`, `targetUserId` is set, and\n * `contentId` is an empty string (no content target).\n */\nexport const reportRecordWireSchema = z.object({\n _id: z.string(),\n targetKind: z.enum(['post', 'lost_found', 'voice_box', 'comment', 'user']),\n contentId: z.string(),\n targetUserId: z.string().optional(),\n reason: reportReasonSchema,\n details: z.string().nullable(),\n status: reportStatusSchema,\n createdAt: z.string().datetime(),\n});\nexport type ReportRecordWire = z.infer<typeof reportRecordWireSchema>;\n\n/**\n * Common response envelope for both `POST /reports` and\n * `POST /reports/user`. `created` is `true` on first submission and\n * `false` when the backend's idempotency check returned an existing\n * row — the client uses this to distinguish \"thanks for reporting\"\n * from \"you've already reported this\".\n */\nexport const reportSubmissionResponseSchema = z.object({\n record: reportRecordWireSchema,\n created: z.boolean(),\n});\nexport type ReportSubmissionResponse = z.infer<typeof reportSubmissionResponseSchema>;\n"]}
|
package/dist/repost.d.ts
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repost (quote / amplify) wire shapes.
|
|
3
|
+
*
|
|
4
|
+
* A repost is a CommunityPost with an optional caption that embeds the
|
|
5
|
+
* source via a snapshot. Modelled after Twitter's quote-tweet: the
|
|
6
|
+
* wrapper is its own post with own engagement; tapping the embed
|
|
7
|
+
* navigates to the source for live counts.
|
|
8
|
+
*
|
|
9
|
+
* Constraints enforced server-side:
|
|
10
|
+
* - At most one active repost per (viewer, sourceKind, sourceId).
|
|
11
|
+
* - Reposting a repost is blocked (no chains).
|
|
12
|
+
* - Caption may be empty (amplify-only) but the wrapper is still a
|
|
13
|
+
* full CommunityPost.
|
|
14
|
+
*
|
|
15
|
+
* @module community-schema/repost
|
|
16
|
+
*/
|
|
17
|
+
import { z } from 'zod';
|
|
18
|
+
/**
|
|
19
|
+
* Body for `POST /api/v1/community/reposts`. The wrapper post's text is
|
|
20
|
+
* the optional caption; visibility level is chosen by the reposter and
|
|
21
|
+
* may differ from the source's level (e.g. amplify a national post
|
|
22
|
+
* locally to flag it for your neighbours).
|
|
23
|
+
*/
|
|
24
|
+
export declare const createRepostBodySchema: z.ZodObject<{
|
|
25
|
+
sourceKind: z.ZodEnum<{
|
|
26
|
+
post: "post";
|
|
27
|
+
lost_found: "lost_found";
|
|
28
|
+
voice_box: "voice_box";
|
|
29
|
+
donate_item: "donate_item";
|
|
30
|
+
}>;
|
|
31
|
+
sourceId: z.ZodString;
|
|
32
|
+
caption: z.ZodOptional<z.ZodString>;
|
|
33
|
+
visibilityLevel: z.ZodEnum<{
|
|
34
|
+
local: "local";
|
|
35
|
+
district: "district";
|
|
36
|
+
state: "state";
|
|
37
|
+
national: "national";
|
|
38
|
+
global: "global";
|
|
39
|
+
}>;
|
|
40
|
+
}, z.core.$strip>;
|
|
41
|
+
export type CreateRepostBody = z.infer<typeof createRepostBodySchema>;
|
|
42
|
+
/**
|
|
43
|
+
* Response from a successful repost. The wrapper post is returned in
|
|
44
|
+
* full (same wire shape as a normal post, but with `repostOf` set) so
|
|
45
|
+
* the client can prepend it to the feed without a follow-up read.
|
|
46
|
+
*/
|
|
47
|
+
export declare const createRepostResponseSchema: z.ZodObject<{
|
|
48
|
+
post: z.ZodObject<{
|
|
49
|
+
_id: z.ZodString;
|
|
50
|
+
contentKind: z.ZodLiteral<"post">;
|
|
51
|
+
author: z.ZodObject<{
|
|
52
|
+
userId: z.ZodString;
|
|
53
|
+
displayName: z.ZodString;
|
|
54
|
+
avatarUrl: z.ZodOptional<z.ZodString>;
|
|
55
|
+
localName: z.ZodOptional<z.ZodString>;
|
|
56
|
+
}, z.core.$strip>;
|
|
57
|
+
text: z.ZodString;
|
|
58
|
+
images: z.ZodArray<z.ZodObject<{
|
|
59
|
+
url: z.ZodString;
|
|
60
|
+
thumbnailUrl: z.ZodOptional<z.ZodString>;
|
|
61
|
+
width: z.ZodNumber;
|
|
62
|
+
height: z.ZodNumber;
|
|
63
|
+
bytes: z.ZodNumber;
|
|
64
|
+
alt: z.ZodOptional<z.ZodString>;
|
|
65
|
+
}, z.core.$strip>>;
|
|
66
|
+
videos: z.ZodArray<z.ZodObject<{
|
|
67
|
+
url: z.ZodString;
|
|
68
|
+
thumbnailUrl: z.ZodString;
|
|
69
|
+
width: z.ZodNumber;
|
|
70
|
+
height: z.ZodNumber;
|
|
71
|
+
bytes: z.ZodNumber;
|
|
72
|
+
duration: z.ZodNumber;
|
|
73
|
+
}, z.core.$strip>>;
|
|
74
|
+
visibilityLevel: z.ZodEnum<{
|
|
75
|
+
local: "local";
|
|
76
|
+
district: "district";
|
|
77
|
+
state: "state";
|
|
78
|
+
national: "national";
|
|
79
|
+
global: "global";
|
|
80
|
+
}>;
|
|
81
|
+
areaLineage: z.ZodObject<{
|
|
82
|
+
countryId: z.ZodOptional<z.ZodString>;
|
|
83
|
+
stateId: z.ZodOptional<z.ZodString>;
|
|
84
|
+
districtId: z.ZodOptional<z.ZodString>;
|
|
85
|
+
localId: z.ZodOptional<z.ZodString>;
|
|
86
|
+
localName: z.ZodOptional<z.ZodString>;
|
|
87
|
+
}, z.core.$strip>;
|
|
88
|
+
upvoteCount: z.ZodNumber;
|
|
89
|
+
commentCount: z.ZodNumber;
|
|
90
|
+
repostCount: z.ZodNumber;
|
|
91
|
+
reactionCounts: z.ZodRecord<z.ZodString, z.ZodNumber>;
|
|
92
|
+
repostOf: z.ZodOptional<z.ZodObject<{
|
|
93
|
+
contentKind: z.ZodEnum<{
|
|
94
|
+
post: "post";
|
|
95
|
+
lost_found: "lost_found";
|
|
96
|
+
voice_box: "voice_box";
|
|
97
|
+
donate_item: "donate_item";
|
|
98
|
+
}>;
|
|
99
|
+
_id: z.ZodString;
|
|
100
|
+
author: z.ZodObject<{
|
|
101
|
+
userId: z.ZodString;
|
|
102
|
+
displayName: z.ZodString;
|
|
103
|
+
avatarUrl: z.ZodOptional<z.ZodString>;
|
|
104
|
+
localName: z.ZodOptional<z.ZodString>;
|
|
105
|
+
}, z.core.$strip>;
|
|
106
|
+
title: z.ZodString;
|
|
107
|
+
body: z.ZodOptional<z.ZodString>;
|
|
108
|
+
imageUrl: z.ZodOptional<z.ZodString>;
|
|
109
|
+
kindBadge: z.ZodOptional<z.ZodString>;
|
|
110
|
+
createdAt: z.ZodString;
|
|
111
|
+
}, z.core.$strip>>;
|
|
112
|
+
createdAt: z.ZodString;
|
|
113
|
+
editedAt: z.ZodNullable<z.ZodString>;
|
|
114
|
+
deletedAt: z.ZodNullable<z.ZodString>;
|
|
115
|
+
viewer: z.ZodOptional<z.ZodObject<{
|
|
116
|
+
upvoted: z.ZodBoolean;
|
|
117
|
+
reaction: z.ZodNullable<z.ZodString>;
|
|
118
|
+
isAuthor: z.ZodBoolean;
|
|
119
|
+
reposted: z.ZodBoolean;
|
|
120
|
+
}, z.core.$strip>>;
|
|
121
|
+
}, z.core.$strip>;
|
|
122
|
+
}, z.core.$strip>;
|
|
123
|
+
export type CreateRepostResponse = z.infer<typeof createRepostResponseSchema>;
|
|
124
|
+
//# sourceMappingURL=repost.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repost.d.ts","sourceRoot":"","sources":["../src/repost.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;iBAWjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE;;;;GAIG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAErC,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC"}
|
package/dist/repost.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repost (quote / amplify) wire shapes.
|
|
3
|
+
*
|
|
4
|
+
* A repost is a CommunityPost with an optional caption that embeds the
|
|
5
|
+
* source via a snapshot. Modelled after Twitter's quote-tweet: the
|
|
6
|
+
* wrapper is its own post with own engagement; tapping the embed
|
|
7
|
+
* navigates to the source for live counts.
|
|
8
|
+
*
|
|
9
|
+
* Constraints enforced server-side:
|
|
10
|
+
* - At most one active repost per (viewer, sourceKind, sourceId).
|
|
11
|
+
* - Reposting a repost is blocked (no chains).
|
|
12
|
+
* - Caption may be empty (amplify-only) but the wrapper is still a
|
|
13
|
+
* full CommunityPost.
|
|
14
|
+
*
|
|
15
|
+
* @module community-schema/repost
|
|
16
|
+
*/
|
|
17
|
+
import { z } from 'zod';
|
|
18
|
+
import { POST_MAX_BODY_CHARS } from './constants.js';
|
|
19
|
+
import { contentKindSchema, visibilityLevelSchema } from './enums.js';
|
|
20
|
+
import { communityPostWireSchema } from './post.js';
|
|
21
|
+
/**
|
|
22
|
+
* Body for `POST /api/v1/community/reposts`. The wrapper post's text is
|
|
23
|
+
* the optional caption; visibility level is chosen by the reposter and
|
|
24
|
+
* may differ from the source's level (e.g. amplify a national post
|
|
25
|
+
* locally to flag it for your neighbours).
|
|
26
|
+
*/
|
|
27
|
+
export const createRepostBodySchema = z.object({
|
|
28
|
+
/** Which kind is being reposted. */
|
|
29
|
+
sourceKind: contentKindSchema,
|
|
30
|
+
/** Source row's id. Server validates existence + not-already-a-repost
|
|
31
|
+
* + not-already-reposted-by-this-viewer. */
|
|
32
|
+
sourceId: z.string(),
|
|
33
|
+
/** Optional caption. Empty string = amplify only (still creates a
|
|
34
|
+
* wrapper post, just with no caption shown on the card). */
|
|
35
|
+
caption: z.string().max(POST_MAX_BODY_CHARS).optional(),
|
|
36
|
+
/** Visibility for the wrapper post. */
|
|
37
|
+
visibilityLevel: visibilityLevelSchema,
|
|
38
|
+
});
|
|
39
|
+
/**
|
|
40
|
+
* Response from a successful repost. The wrapper post is returned in
|
|
41
|
+
* full (same wire shape as a normal post, but with `repostOf` set) so
|
|
42
|
+
* the client can prepend it to the feed without a follow-up read.
|
|
43
|
+
*/
|
|
44
|
+
export const createRepostResponseSchema = z.object({
|
|
45
|
+
post: communityPostWireSchema,
|
|
46
|
+
});
|
|
47
|
+
//# sourceMappingURL=repost.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repost.js","sourceRoot":"","sources":["../src/repost.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,oCAAoC;IACpC,UAAU,EAAE,iBAAiB;IAC7B;iDAC6C;IAC7C,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB;iEAC6D;IAC7D,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC,QAAQ,EAAE;IACvD,uCAAuC;IACvC,eAAe,EAAE,qBAAqB;CACvC,CAAC,CAAC;AAGH;;;;GAIG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC;IACjD,IAAI,EAAE,uBAAuB;CAC9B,CAAC,CAAC","sourcesContent":["/**\n * Repost (quote / amplify) wire shapes.\n *\n * A repost is a CommunityPost with an optional caption that embeds the\n * source via a snapshot. Modelled after Twitter's quote-tweet: the\n * wrapper is its own post with own engagement; tapping the embed\n * navigates to the source for live counts.\n *\n * Constraints enforced server-side:\n * - At most one active repost per (viewer, sourceKind, sourceId).\n * - Reposting a repost is blocked (no chains).\n * - Caption may be empty (amplify-only) but the wrapper is still a\n * full CommunityPost.\n *\n * @module community-schema/repost\n */\n\nimport { z } from 'zod';\nimport { POST_MAX_BODY_CHARS } from './constants.js';\nimport { contentKindSchema, visibilityLevelSchema } from './enums.js';\nimport { communityPostWireSchema } from './post.js';\n\n/**\n * Body for `POST /api/v1/community/reposts`. The wrapper post's text is\n * the optional caption; visibility level is chosen by the reposter and\n * may differ from the source's level (e.g. amplify a national post\n * locally to flag it for your neighbours).\n */\nexport const createRepostBodySchema = z.object({\n /** Which kind is being reposted. */\n sourceKind: contentKindSchema,\n /** Source row's id. Server validates existence + not-already-a-repost\n * + not-already-reposted-by-this-viewer. */\n sourceId: z.string(),\n /** Optional caption. Empty string = amplify only (still creates a\n * wrapper post, just with no caption shown on the card). */\n caption: z.string().max(POST_MAX_BODY_CHARS).optional(),\n /** Visibility for the wrapper post. */\n visibilityLevel: visibilityLevelSchema,\n});\nexport type CreateRepostBody = z.infer<typeof createRepostBodySchema>;\n\n/**\n * Response from a successful repost. The wrapper post is returned in\n * full (same wire shape as a normal post, but with `repostOf` set) so\n * the client can prepend it to the feed without a follow-up read.\n */\nexport const createRepostResponseSchema = z.object({\n post: communityPostWireSchema,\n});\nexport type CreateRepostResponse = z.infer<typeof createRepostResponseSchema>;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jansathi-community-schema",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Shared Zod schemas + TypeScript types for the Jansathi hyperlocal community feature (feed, posts, engagement, social graph, groups).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|