jansathi-community-schema 0.8.0 → 0.9.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/enums.d.ts CHANGED
@@ -82,27 +82,11 @@ export declare const reactionTypeSchema: z.ZodEnum<{
82
82
  support: "support";
83
83
  }>;
84
84
  export type ReactionType = z.infer<typeof reactionTypeSchema>;
85
- /**
86
- * Connection (mutual friend) lifecycle.
87
- *
88
- * `pending` — requester sent it, recipient hasn't acted yet.
89
- * `accepted` — both sides confirmed; full visibility regardless of level.
90
- * `declined` — recipient rejected; surfaces as "you can't reconnect for X days" on the requester side.
91
- * `blocked` — either side blocked; permanently prevents reconnection.
92
- */
93
- export declare const CONNECTION_STATUS_VALUES: readonly ["pending", "accepted", "declined", "blocked"];
94
- export declare const connectionStatusSchema: z.ZodEnum<{
95
- pending: "pending";
96
- accepted: "accepted";
97
- declined: "declined";
98
- blocked: "blocked";
99
- }>;
100
- export type ConnectionStatus = z.infer<typeof connectionStatusSchema>;
101
85
  /**
102
86
  * Profile-level privacy (single toggle in Settings).
103
87
  *
104
88
  * `public` — anyone the area-proximity cascade reaches sees this user's posts.
105
- * `private` — only accepted Connections see this user's posts.
89
+ * `private` — only the viewer's followers see this user's posts.
106
90
  */
107
91
  export declare const PROFILE_PRIVACY_VALUES: readonly ["public", "private"];
108
92
  export declare const profilePrivacySchema: z.ZodEnum<{
@@ -110,23 +94,6 @@ export declare const profilePrivacySchema: z.ZodEnum<{
110
94
  private: "private";
111
95
  }>;
112
96
  export type ProfilePrivacy = z.infer<typeof profilePrivacySchema>;
113
- /**
114
- * Per-post audience override chosen by the author at compose time.
115
- *
116
- * `public` — anyone the area-proximity cascade reaches (default).
117
- * `connections` — only the author's accepted Connections see this post.
118
- *
119
- * Orthogonal to `ProfilePrivacy`: a public-profile user can mark
120
- * individual posts as `connections`-only; a private-profile user's
121
- * posts default to connections-only at the profile gate regardless of
122
- * this value. Effective visibility = most restrictive of the two.
123
- */
124
- export declare const POST_AUDIENCE_VALUES: readonly ["public", "connections"];
125
- export declare const postAudienceSchema: z.ZodEnum<{
126
- public: "public";
127
- connections: "connections";
128
- }>;
129
- export type PostAudience = z.infer<typeof postAudienceSchema>;
130
97
  /**
131
98
  * Reasons a piece of content can be reported. The list is deliberately
132
99
  * short — finer categorization can come from the optional `details`
@@ -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;;;;;;;;;;;;;;;;;;;;;;;GAuBG;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;;;;;GAKG;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;;;;;;;;;;GAUG;AACH,eAAO,MAAM,oBAAoB,oCAAqC,CAAC;AACvE,eAAO,MAAM,kBAAkB;;;EAA+B,CAAC;AAC/D,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAI9D;;;;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"}
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;;;;;;;;;;;;;;;;;;;;;;;GAuBG;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;;;;;GAKG;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
@@ -83,40 +83,15 @@ export const REACTION_TYPE_VALUES = [
83
83
  'support',
84
84
  ];
85
85
  export const reactionTypeSchema = z.enum(REACTION_TYPE_VALUES);
86
- // ─── Social graph ──────────────────────────────────────────────────────────
87
- /**
88
- * Connection (mutual friend) lifecycle.
89
- *
90
- * `pending` — requester sent it, recipient hasn't acted yet.
91
- * `accepted` — both sides confirmed; full visibility regardless of level.
92
- * `declined` — recipient rejected; surfaces as "you can't reconnect for X days" on the requester side.
93
- * `blocked` — either side blocked; permanently prevents reconnection.
94
- */
95
- export const CONNECTION_STATUS_VALUES = ['pending', 'accepted', 'declined', 'blocked'];
96
- export const connectionStatusSchema = z.enum(CONNECTION_STATUS_VALUES);
97
86
  // ─── Profile privacy ───────────────────────────────────────────────────────
98
87
  /**
99
88
  * Profile-level privacy (single toggle in Settings).
100
89
  *
101
90
  * `public` — anyone the area-proximity cascade reaches sees this user's posts.
102
- * `private` — only accepted Connections see this user's posts.
91
+ * `private` — only the viewer's followers see this user's posts.
103
92
  */
104
93
  export const PROFILE_PRIVACY_VALUES = ['public', 'private'];
105
94
  export const profilePrivacySchema = z.enum(PROFILE_PRIVACY_VALUES);
106
- // ─── Per-post audience ─────────────────────────────────────────────────────
107
- /**
108
- * Per-post audience override chosen by the author at compose time.
109
- *
110
- * `public` — anyone the area-proximity cascade reaches (default).
111
- * `connections` — only the author's accepted Connections see this post.
112
- *
113
- * Orthogonal to `ProfilePrivacy`: a public-profile user can mark
114
- * individual posts as `connections`-only; a private-profile user's
115
- * posts default to connections-only at the profile gate regardless of
116
- * this value. Effective visibility = most restrictive of the two.
117
- */
118
- export const POST_AUDIENCE_VALUES = ['public', 'connections'];
119
- export const postAudienceSchema = z.enum(POST_AUDIENCE_VALUES);
120
95
  // ─── Moderation ────────────────────────────────────────────────────────────
121
96
  /**
122
97
  * Reasons a piece of content can be reported. The list is deliberately
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,8EAA8E;AAE9E;;;;;;;;;;;;;;;;;;;;;;;GAuBG;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;;;;;GAKG;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;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,QAAQ,EAAE,aAAa,CAAU,CAAC;AACvE,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;AAG/D,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// ─── Feed viewport (viewer-side geographic filter) ─────────────────────────\n\n/**\n * Geographic scope the VIEWER chose for their feed — the area-proximity\n * cascade is gated by this value.\n *\n * Posts do NOT carry a per-post `visibilityLevel` any more. Every post\n * is implicitly global; visibility is purely a function of (a) the\n * author's `areaLineage` at write time and (b) the viewer's scope\n * choice here. The cascade walks from the viewer's locality outward\n * and includes any post whose author was inside the viewer's area at\n * ANY level the viewer's scope reaches.\n *\n * - `local` → locality + district + state + national matches\n * - `district` → district + state + national matches (no locality boost)\n * - `state` → state + national matches\n * - `national` → national matches\n * - `global` → all matches (de-facto same as `national` for an\n * India-only product, but kept for forward compat)\n *\n * Read-side ranking — see `feed.service.ts#tierBoost` — multiplies the\n * row's hotScore by an area-proximity factor: locality match 2.0,\n * district 1.2, state 0.9, national 0.7, distant 0.5. So local\n * content dominates at equal quality, while genuinely viral national\n * content still surfaces.\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 area-proximity cascade. `local` is the\n * deepest (most specific) feed scope, `global` the broadest. Higher\n * 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 the area-proximity cascade reaches sees this user's posts.\n * `private` — only accepted Connections see this user's posts.\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// ─── Per-post audience ─────────────────────────────────────────────────────\n\n/**\n * Per-post audience override chosen by the author at compose time.\n *\n * `public` — anyone the area-proximity cascade reaches (default).\n * `connections` — only the author's accepted Connections see this post.\n *\n * Orthogonal to `ProfilePrivacy`: a public-profile user can mark\n * individual posts as `connections`-only; a private-profile user's\n * posts default to connections-only at the profile gate regardless of\n * this value. Effective visibility = most restrictive of the two.\n */\nexport const POST_AUDIENCE_VALUES = ['public', 'connections'] as const;\nexport const postAudienceSchema = z.enum(POST_AUDIENCE_VALUES);\nexport type PostAudience = z.infer<typeof postAudienceSchema>;\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"]}
1
+ {"version":3,"file":"enums.js","sourceRoot":"","sources":["../src/enums.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,8EAA8E;AAE9E;;;;;;;;;;;;;;;;;;;;;;;GAuBG;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;;;;;GAKG;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// ─── Feed viewport (viewer-side geographic filter) ─────────────────────────\n\n/**\n * Geographic scope the VIEWER chose for their feed — the area-proximity\n * cascade is gated by this value.\n *\n * Posts do NOT carry a per-post `visibilityLevel` any more. Every post\n * is implicitly global; visibility is purely a function of (a) the\n * author's `areaLineage` at write time and (b) the viewer's scope\n * choice here. The cascade walks from the viewer's locality outward\n * and includes any post whose author was inside the viewer's area at\n * ANY level the viewer's scope reaches.\n *\n * - `local` → locality + district + state + national matches\n * - `district` → district + state + national matches (no locality boost)\n * - `state` → state + national matches\n * - `national` → national matches\n * - `global` → all matches (de-facto same as `national` for an\n * India-only product, but kept for forward compat)\n *\n * Read-side ranking — see `feed.service.ts#tierBoost` — multiplies the\n * row's hotScore by an area-proximity factor: locality match 2.0,\n * district 1.2, state 0.9, national 0.7, distant 0.5. So local\n * content dominates at equal quality, while genuinely viral national\n * content still surfaces.\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 area-proximity cascade. `local` is the\n * deepest (most specific) feed scope, `global` the broadest. Higher\n * 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// ─── Profile privacy ───────────────────────────────────────────────────────\n\n/**\n * Profile-level privacy (single toggle in Settings).\n *\n * `public` — anyone the area-proximity cascade reaches sees this user's posts.\n * `private` — only the viewer's followers see this user's posts.\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
@@ -153,10 +153,6 @@ export declare const feedItemSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
153
153
  localId: z.ZodOptional<z.ZodString>;
154
154
  localName: z.ZodOptional<z.ZodString>;
155
155
  }, z.core.$strip>;
156
- audience: z.ZodEnum<{
157
- public: "public";
158
- connections: "connections";
159
- }>;
160
156
  communityId: z.ZodOptional<z.ZodString>;
161
157
  upvoteCount: z.ZodNumber;
162
158
  commentCount: z.ZodNumber;
@@ -323,10 +319,6 @@ export declare const feedResponseSchema: z.ZodObject<{
323
319
  localId: z.ZodOptional<z.ZodString>;
324
320
  localName: z.ZodOptional<z.ZodString>;
325
321
  }, z.core.$strip>;
326
- audience: z.ZodEnum<{
327
- public: "public";
328
- connections: "connections";
329
- }>;
330
322
  communityId: z.ZodOptional<z.ZodString>;
331
323
  upvoteCount: z.ZodNumber;
332
324
  commentCount: z.ZodNumber;
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}
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/index.d.ts CHANGED
@@ -19,14 +19,14 @@ export { type CommunityCommentWire, type CreateCommentBody, communityCommentWire
19
19
  export { COMMUNITY_DISCOVER_SORT_VALUES, COMMUNITY_MEMBERSHIP_STATUS_VALUES, COMMUNITY_ROLE_VALUES, COMMUNITY_TYPE_VALUES, type CommunityDiscoverSort, type CommunityListQuery, type CommunityListResponse, type CommunityMembershipStatus, type CommunityMembersListResponse, type CommunityMemberWire, type CommunityRole, type CommunityType, type CommunityWire, type CreateCommunityBody, communityDiscoverSortSchema, communityListQuerySchema, communityListResponseSchema, communityMembershipStatusSchema, communityMembersListResponseSchema, communityMemberWireSchema, communityRoleSchema, communityTypeSchema, communityWireSchema, createCommunityBodySchema, type JoinCommunityResponse, joinCommunityResponseSchema, type UpdateCommunityBody, type UpdateMemberRoleBody, updateCommunityBodySchema, updateMemberRoleBodySchema, } from './community.js';
20
20
  export { COMMENT_MAX_BODY_CHARS, COMMENTS_PAGE_SIZE, COMMUNITIES_PAGE_SIZE, COMMUNITY_DESCRIPTION_MAX_CHARS, COMMUNITY_MEMBERS_PAGE_SIZE, COMMUNITY_NAME_MAX_CHARS, COMMUNITY_NAME_MIN_CHARS, COMMUNITY_SLUG_MAX_CHARS, COMMUNITY_SLUG_MIN_CHARS, COMMUNITY_SLUG_PATTERN, 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';
21
21
  export { type SetReactionBody, type SetReactionResponse, setReactionBodySchema, setReactionResponseSchema, type ToggleUpvoteResponse, toggleUpvoteResponseSchema, } from './engagement.js';
22
- export { CONNECTION_STATUS_VALUES, CONTENT_KIND_VALUES, type ConnectionStatus, type ContentKind, connectionStatusSchema, contentKindSchema, FEED_SORT_VALUES, type FeedSort, feedSortSchema, POST_AUDIENCE_VALUES, type PostAudience, PROFILE_PRIVACY_VALUES, type ProfilePrivacy, postAudienceSchema, 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 { CONTENT_KIND_VALUES, type ContentKind, 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';
23
23
  export { type DonateItemFeedItem, donateItemFeedItemSchema, type FeedItem, type FeedQueryParams, type FeedResponse, feedItemSchema, feedQueryParamsSchema, feedResponseSchema, type LostFoundFeedItem, lostFoundFeedItemSchema, type VoiceBoxFeedItem, voiceBoxFeedItemSchema, } from './feed.js';
24
24
  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';
25
25
  export { type PostImage, type PostVideo, postImageSchema, postVideoSchema, } from './media.js';
26
26
  export { type CommunityPostWire, type CreatePostBody, communityPostWireSchema, createPostBodySchema, type PostAuthorSnapshot, postAuthorSnapshotSchema, type RepostedSource, repostedSourceSchema, type UpdatePostBody, updatePostBodySchema, } from './post.js';
27
- export { type PeopleListItem, type PeopleListResponse, type PeopleQueryParams, type PublicProfileWire, peopleListItemSchema, peopleListResponseSchema, peopleQueryParamsSchema, publicProfileWireSchema, } from './profile.js';
27
+ export { type PeopleListItem, type PeopleListResponse, type PeopleQueryParams, type ProfileMutuals, type PublicProfileWire, peopleListItemSchema, peopleListResponseSchema, peopleQueryParamsSchema, profileMutualsSchema, publicProfileWireSchema, } from './profile.js';
28
28
  export { type ReportContentBody, type ReportContentKind, type ReportRecordWire, type ReportSubmissionResponse, type ReportUserBody, reportContentBodySchema, reportContentKindSchema, reportRecordWireSchema, reportSubmissionResponseSchema, reportUserBodySchema, } from './report.js';
29
29
  export { type CreateRepostBody, type CreateRepostResponse, createRepostBodySchema, createRepostResponseSchema, } from './repost.js';
30
30
  export { type BlockedUsersListResponse, type BlockedUserWire, blockedUsersListResponseSchema, blockedUserWireSchema, COMMUNITY_SETTINGS_DEFAULTS, type CommunitySettingsWire, communitySettingsWireSchema, type UpdateCommunitySettingsBody, updateCommunitySettingsBodySchema, } from './settings.js';
31
- export { type ConnectionDecisionBody, type ConnectionRecordWire, connectionDecisionBodySchema, connectionRecordWireSchema, type SendConnectionRequestResponse, sendConnectionRequestResponseSchema, type ToggleFollowResponse, toggleFollowResponseSchema, type ViewerSocialState, viewerSocialStateSchema, } from './social.js';
31
+ export { type ToggleFollowResponse, toggleFollowResponseSchema, type ViewerSocialState, viewerSocialStateSchema, } from './social.js';
32
32
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -25,7 +25,7 @@ export { COMMENT_MAX_BODY_CHARS, COMMENTS_PAGE_SIZE, COMMUNITIES_PAGE_SIZE, COMM
25
25
  // ─── Engagement (upvote + reactions) ───────────────────────────────────────
26
26
  export { setReactionBodySchema, setReactionResponseSchema, toggleUpvoteResponseSchema, } from './engagement.js';
27
27
  // ─── Enums ─────────────────────────────────────────────────────────────────
28
- export { CONNECTION_STATUS_VALUES, CONTENT_KIND_VALUES, connectionStatusSchema, contentKindSchema, FEED_SORT_VALUES, feedSortSchema, POST_AUDIENCE_VALUES, PROFILE_PRIVACY_VALUES, postAudienceSchema, profilePrivacySchema, REACTION_TYPE_VALUES, REPORT_REASON_VALUES, REPORT_STATUS_VALUES, reactionTypeSchema, reportReasonSchema, reportStatusSchema, VISIBILITY_LEVEL_RANK, VISIBILITY_LEVEL_VALUES, visibilityLevelSchema, } from './enums.js';
28
+ export { CONTENT_KIND_VALUES, 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';
29
29
  // ─── Feed (polymorphic union) ──────────────────────────────────────────────
30
30
  export { donateItemFeedItemSchema, feedItemSchema, feedQueryParamsSchema, feedResponseSchema, lostFoundFeedItemSchema, voiceBoxFeedItemSchema, } from './feed.js';
31
31
  // ─── Groups ────────────────────────────────────────────────────────────────
@@ -35,13 +35,13 @@ export { postImageSchema, postVideoSchema, } from './media.js';
35
35
  // ─── Post ──────────────────────────────────────────────────────────────────
36
36
  export { communityPostWireSchema, createPostBodySchema, postAuthorSnapshotSchema, repostedSourceSchema, updatePostBodySchema, } from './post.js';
37
37
  // ─── Profile + People list ─────────────────────────────────────────────────
38
- export { peopleListItemSchema, peopleListResponseSchema, peopleQueryParamsSchema, publicProfileWireSchema, } from './profile.js';
38
+ export { peopleListItemSchema, peopleListResponseSchema, peopleQueryParamsSchema, profileMutualsSchema, publicProfileWireSchema, } from './profile.js';
39
39
  // ─── Reports (moderation) ──────────────────────────────────────────────────
40
40
  export { reportContentBodySchema, reportContentKindSchema, reportRecordWireSchema, reportSubmissionResponseSchema, reportUserBodySchema, } from './report.js';
41
41
  // ─── Repost (quote / amplify) ──────────────────────────────────────────────
42
42
  export { createRepostBodySchema, createRepostResponseSchema, } from './repost.js';
43
43
  // ─── Settings ──────────────────────────────────────────────────────────────
44
44
  export { blockedUsersListResponseSchema, blockedUserWireSchema, COMMUNITY_SETTINGS_DEFAULTS, communitySettingsWireSchema, updateCommunitySettingsBodySchema, } from './settings.js';
45
- // ─── Social (follow + connection) ──────────────────────────────────────────
46
- export { connectionDecisionBodySchema, connectionRecordWireSchema, sendConnectionRequestResponseSchema, toggleFollowResponseSchema, viewerSocialStateSchema, } from './social.js';
45
+ // ─── Social (follow) ───────────────────────────────────────────────────────
46
+ export { toggleFollowResponseSchema, viewerSocialStateSchema, } from './social.js';
47
47
  //# 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":"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","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// ─── Communities ───────────────────────────────────────────────────────────\nexport {\n COMMUNITY_DISCOVER_SORT_VALUES,\n COMMUNITY_MEMBERSHIP_STATUS_VALUES,\n COMMUNITY_ROLE_VALUES,\n COMMUNITY_TYPE_VALUES,\n type CommunityDiscoverSort,\n type CommunityListQuery,\n type CommunityListResponse,\n type CommunityMembershipStatus,\n type CommunityMembersListResponse,\n type CommunityMemberWire,\n type CommunityRole,\n type CommunityType,\n type CommunityWire,\n type CreateCommunityBody,\n communityDiscoverSortSchema,\n communityListQuerySchema,\n communityListResponseSchema,\n communityMembershipStatusSchema,\n communityMembersListResponseSchema,\n communityMemberWireSchema,\n communityRoleSchema,\n communityTypeSchema,\n communityWireSchema,\n createCommunityBodySchema,\n type JoinCommunityResponse,\n joinCommunityResponseSchema,\n type UpdateCommunityBody,\n type UpdateMemberRoleBody,\n updateCommunityBodySchema,\n updateMemberRoleBodySchema,\n} from './community.js';\n\n// ─── Constants ─────────────────────────────────────────────────────────────\nexport {\n COMMENT_MAX_BODY_CHARS,\n COMMENTS_PAGE_SIZE,\n COMMUNITIES_PAGE_SIZE,\n COMMUNITY_DESCRIPTION_MAX_CHARS,\n COMMUNITY_MEMBERS_PAGE_SIZE,\n COMMUNITY_NAME_MAX_CHARS,\n COMMUNITY_NAME_MIN_CHARS,\n COMMUNITY_SLUG_MAX_CHARS,\n COMMUNITY_SLUG_MIN_CHARS,\n COMMUNITY_SLUG_PATTERN,\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 POST_AUDIENCE_VALUES,\n type PostAudience,\n PROFILE_PRIVACY_VALUES,\n type ProfilePrivacy,\n postAudienceSchema,\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// ─── 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// ─── 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// ─── Repost (quote / amplify) ──────────────────────────────────────────────\nexport {\n type CreateRepostBody,\n type CreateRepostResponse,\n createRepostBodySchema,\n createRepostResponseSchema,\n} from './repost.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"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","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// ─── Communities ───────────────────────────────────────────────────────────\nexport {\n COMMUNITY_DISCOVER_SORT_VALUES,\n COMMUNITY_MEMBERSHIP_STATUS_VALUES,\n COMMUNITY_ROLE_VALUES,\n COMMUNITY_TYPE_VALUES,\n type CommunityDiscoverSort,\n type CommunityListQuery,\n type CommunityListResponse,\n type CommunityMembershipStatus,\n type CommunityMembersListResponse,\n type CommunityMemberWire,\n type CommunityRole,\n type CommunityType,\n type CommunityWire,\n type CreateCommunityBody,\n communityDiscoverSortSchema,\n communityListQuerySchema,\n communityListResponseSchema,\n communityMembershipStatusSchema,\n communityMembersListResponseSchema,\n communityMemberWireSchema,\n communityRoleSchema,\n communityTypeSchema,\n communityWireSchema,\n createCommunityBodySchema,\n type JoinCommunityResponse,\n joinCommunityResponseSchema,\n type UpdateCommunityBody,\n type UpdateMemberRoleBody,\n updateCommunityBodySchema,\n updateMemberRoleBodySchema,\n} from './community.js';\n\n// ─── Constants ─────────────────────────────────────────────────────────────\nexport {\n COMMENT_MAX_BODY_CHARS,\n COMMENTS_PAGE_SIZE,\n COMMUNITIES_PAGE_SIZE,\n COMMUNITY_DESCRIPTION_MAX_CHARS,\n COMMUNITY_MEMBERS_PAGE_SIZE,\n COMMUNITY_NAME_MAX_CHARS,\n COMMUNITY_NAME_MIN_CHARS,\n COMMUNITY_SLUG_MAX_CHARS,\n COMMUNITY_SLUG_MIN_CHARS,\n COMMUNITY_SLUG_PATTERN,\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 CONTENT_KIND_VALUES,\n type ContentKind,\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// ─── Profile + People list ─────────────────────────────────────────────────\nexport {\n type PeopleListItem,\n type PeopleListResponse,\n type PeopleQueryParams,\n type ProfileMutuals,\n type PublicProfileWire,\n peopleListItemSchema,\n peopleListResponseSchema,\n peopleQueryParamsSchema,\n profileMutualsSchema,\n publicProfileWireSchema,\n} from './profile.js';\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// ─── Repost (quote / amplify) ──────────────────────────────────────────────\nexport {\n type CreateRepostBody,\n type CreateRepostResponse,\n createRepostBodySchema,\n createRepostResponseSchema,\n} from './repost.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) ───────────────────────────────────────────────────────\nexport {\n type ToggleFollowResponse,\n toggleFollowResponseSchema,\n type ViewerSocialState,\n viewerSocialStateSchema,\n} from './social.js';\n"]}
package/dist/post.d.ts CHANGED
@@ -101,10 +101,6 @@ export declare const communityPostWireSchema: z.ZodObject<{
101
101
  localId: z.ZodOptional<z.ZodString>;
102
102
  localName: z.ZodOptional<z.ZodString>;
103
103
  }, z.core.$strip>;
104
- audience: z.ZodEnum<{
105
- public: "public";
106
- connections: "connections";
107
- }>;
108
104
  communityId: z.ZodOptional<z.ZodString>;
109
105
  upvoteCount: z.ZodNumber;
110
106
  commentCount: z.ZodNumber;
@@ -165,10 +161,6 @@ export declare const createPostBodySchema: z.ZodObject<{
165
161
  bytes: z.ZodNumber;
166
162
  duration: z.ZodNumber;
167
163
  }, z.core.$strip>>>;
168
- audience: z.ZodDefault<z.ZodEnum<{
169
- public: "public";
170
- connections: "connections";
171
- }>>;
172
164
  communityId: z.ZodOptional<z.ZodString>;
173
165
  }, z.core.$strip>;
174
166
  export type CreatePostBody = z.infer<typeof createPostBodySchema>;
@@ -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;;;;;;;;;;;;;;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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA6DlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAIxE;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;iBAY/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"}
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAyDlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAIxE;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;iBAO/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 { contentKindSchema, postAudienceSchema } from './enums.js';
14
+ import { contentKindSchema } from './enums.js';
15
15
  import { postImageSchema, postVideoSchema } from './media.js';
16
16
  // ─── Author snapshot (denormalised on every post) ──────────────────────────
17
17
  /**
@@ -91,14 +91,10 @@ export const communityPostWireSchema = z.object({
91
91
  text: z.string().max(POST_MAX_BODY_CHARS),
92
92
  images: z.array(postImageSchema).max(POST_MAX_IMAGES),
93
93
  videos: z.array(postVideoSchema).max(POST_MAX_VIDEOS),
94
- // Authorship area + audience
94
+ // Authorship area
95
95
  /** Snapshot of where the author was at write time. Drives the
96
96
  * area-proximity cascade and ranking in feed.service. */
97
97
  areaLineage: areaLineageSnapshotSchema,
98
- /** Per-post audience override. Defaults to `public` on creation when
99
- * the client omits it. See `postAudienceSchema` in enums for the
100
- * full interaction with `ProfilePrivacy`. */
101
- audience: postAudienceSchema,
102
98
  /** When set, the post is scoped to a topical community and is NOT
103
99
  * surfaced via the geo cascade. The community feed adds an explicit
104
100
  * `communityId` filter to its read queries. Posts authored from the
@@ -150,11 +146,6 @@ export const createPostBodySchema = z.object({
150
146
  text: z.string().min(1).max(POST_MAX_BODY_CHARS),
151
147
  images: z.array(postImageSchema).max(POST_MAX_IMAGES).optional(),
152
148
  videos: z.array(postVideoSchema).max(POST_MAX_VIDEOS).optional(),
153
- /** Per-post audience selector chosen by the composer's privacy
154
- * pill. Optional; defaults to `public` on the server when omitted
155
- * (the schema applies the default so older clients keep working).
156
- * See `postAudienceSchema` for the public/connections semantics. */
157
- audience: postAudienceSchema.default('public'),
158
149
  /** When set, the post is scoped to a topical community. The author
159
150
  * must be an active member; non-members get a 403. */
160
151
  communityId: z.string().optional(),
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 { contentKindSchema, postAudienceSchema } 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 // Authorship area + audience\n /** Snapshot of where the author was at write time. Drives the\n * area-proximity cascade and ranking in feed.service. */\n areaLineage: areaLineageSnapshotSchema,\n /** Per-post audience override. Defaults to `public` on creation when\n * the client omits it. See `postAudienceSchema` in enums for the\n * full interaction with `ProfilePrivacy`. */\n audience: postAudienceSchema,\n /** When set, the post is scoped to a topical community and is NOT\n * surfaced via the geo cascade. The community feed adds an explicit\n * `communityId` filter to its read queries. Posts authored from the\n * global composer leave this null. */\n communityId: z.string().optional(),\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; the area lineage is resolved\n * server-side from the user's `currentLocation` (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 /** Per-post audience selector chosen by the composer's privacy\n * pill. Optional; defaults to `public` on the server when omitted\n * (the schema applies the default so older clients keep working).\n * See `postAudienceSchema` for the public/connections semantics. */\n audience: postAudienceSchema.default('public'),\n /** When set, the post is scoped to a topical community. The author\n * must be an active member; non-members get a 403. */\n communityId: z.string().optional(),\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":"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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 { contentKindSchema } 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 // Authorship area\n /** Snapshot of where the author was at write time. Drives the\n * area-proximity cascade and ranking in feed.service. */\n areaLineage: areaLineageSnapshotSchema,\n /** When set, the post is scoped to a topical community and is NOT\n * surfaced via the geo cascade. The community feed adds an explicit\n * `communityId` filter to its read queries. Posts authored from the\n * global composer leave this null. */\n communityId: z.string().optional(),\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; the area lineage is resolved\n * server-side from the user's `currentLocation` (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 /** When set, the post is scoped to a topical community. The author\n * must be an active member; non-members get a 403. */\n communityId: z.string().optional(),\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/profile.d.ts CHANGED
@@ -8,12 +8,27 @@
8
8
  * Privacy gating:
9
9
  * - `public` profile: the full shape is returned to any signed-in viewer.
10
10
  * - `private` profile: only `userId`, `displayName`, `avatarUrl`, and
11
- * the viewer's social state are returned to non-Connections. Posts
12
- * and counters are hidden until a Connection is accepted.
11
+ * the viewer's follow state are returned to non-followers. Posts and
12
+ * counters are hidden until the viewer follows the profile owner and
13
+ * the owner has accepted (TODO: follow-approval lifecycle — currently
14
+ * "private" simply hides counters/posts from anyone who isn't the
15
+ * owner).
13
16
  *
14
17
  * @module community-schema/profile
15
18
  */
16
19
  import { z } from 'zod';
20
+ /**
21
+ * Mini-row used in the "Followed by X, Y + N more" mutuals line on the
22
+ * profile header. The server picks up to 3 sample names + a count of
23
+ * the remaining mutuals so the row reads naturally without paginating
24
+ * the full mutuals list inline.
25
+ */
26
+ export declare const profileMutualsSchema: z.ZodObject<{
27
+ avatars: z.ZodArray<z.ZodNullable<z.ZodString>>;
28
+ sampleNames: z.ZodArray<z.ZodString>;
29
+ extraCount: z.ZodNumber;
30
+ }, z.core.$strip>;
31
+ export type ProfileMutuals = z.infer<typeof profileMutualsSchema>;
17
32
  export declare const publicProfileWireSchema: z.ZodObject<{
18
33
  userId: z.ZodString;
19
34
  displayName: z.ZodString;
@@ -28,21 +43,14 @@ export declare const publicProfileWireSchema: z.ZodObject<{
28
43
  postCount: z.ZodNumber;
29
44
  followerCount: z.ZodNumber;
30
45
  followingCount: z.ZodNumber;
31
- connectionCount: z.ZodNumber;
46
+ }, z.core.$strip>>;
47
+ mutuals: z.ZodOptional<z.ZodObject<{
48
+ avatars: z.ZodArray<z.ZodNullable<z.ZodString>>;
49
+ sampleNames: z.ZodArray<z.ZodString>;
50
+ extraCount: z.ZodNumber;
32
51
  }, z.core.$strip>>;
33
52
  viewer: z.ZodObject<{
34
53
  following: z.ZodBoolean;
35
- connectionStatus: z.ZodNullable<z.ZodEnum<{
36
- pending: "pending";
37
- accepted: "accepted";
38
- declined: "declined";
39
- blocked: "blocked";
40
- }>>;
41
- pendingDirection: z.ZodNullable<z.ZodEnum<{
42
- sent: "sent";
43
- received: "received";
44
- }>>;
45
- connectionId: z.ZodNullable<z.ZodString>;
46
54
  }, z.core.$strip>;
47
55
  }, z.core.$strip>;
48
56
  export type PublicProfileWire = z.infer<typeof publicProfileWireSchema>;
@@ -61,17 +69,6 @@ export declare const peopleListItemSchema: z.ZodObject<{
61
69
  }>;
62
70
  viewer: z.ZodObject<{
63
71
  following: z.ZodBoolean;
64
- connectionStatus: z.ZodNullable<z.ZodEnum<{
65
- pending: "pending";
66
- accepted: "accepted";
67
- declined: "declined";
68
- blocked: "blocked";
69
- }>>;
70
- pendingDirection: z.ZodNullable<z.ZodEnum<{
71
- sent: "sent";
72
- received: "received";
73
- }>>;
74
- connectionId: z.ZodNullable<z.ZodString>;
75
72
  }, z.core.$strip>;
76
73
  }, z.core.$strip>;
77
74
  export type PeopleListItem = z.infer<typeof peopleListItemSchema>;
@@ -100,17 +97,6 @@ export declare const peopleListResponseSchema: z.ZodObject<{
100
97
  }>;
101
98
  viewer: z.ZodObject<{
102
99
  following: z.ZodBoolean;
103
- connectionStatus: z.ZodNullable<z.ZodEnum<{
104
- pending: "pending";
105
- accepted: "accepted";
106
- declined: "declined";
107
- blocked: "blocked";
108
- }>>;
109
- pendingDirection: z.ZodNullable<z.ZodEnum<{
110
- sent: "sent";
111
- received: "received";
112
- }>>;
113
- connectionId: z.ZodNullable<z.ZodString>;
114
100
  }, z.core.$strip>;
115
101
  }, z.core.$strip>>;
116
102
  nextCursor: z.ZodNullable<z.ZodString>;
@@ -1 +1 @@
1
- {"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA4BlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAIxE;;;GAGG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;iBAO/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,eAAO,MAAM,uBAAuB;;;;;;;;;;;iBAQlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;iBAGnC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC"}
1
+ {"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB;;;;iBAW/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;iBAmClC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAIxE;;;GAGG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;iBAO/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,eAAO,MAAM,uBAAuB;;;;;;;;;;;iBAQlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;iBAGnC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC"}
package/dist/profile.js CHANGED
@@ -8,8 +8,11 @@
8
8
  * Privacy gating:
9
9
  * - `public` profile: the full shape is returned to any signed-in viewer.
10
10
  * - `private` profile: only `userId`, `displayName`, `avatarUrl`, and
11
- * the viewer's social state are returned to non-Connections. Posts
12
- * and counters are hidden until a Connection is accepted.
11
+ * the viewer's follow state are returned to non-followers. Posts and
12
+ * counters are hidden until the viewer follows the profile owner and
13
+ * the owner has accepted (TODO: follow-approval lifecycle — currently
14
+ * "private" simply hides counters/posts from anyone who isn't the
15
+ * owner).
13
16
  *
14
17
  * @module community-schema/profile
15
18
  */
@@ -17,27 +20,51 @@ import { z } from 'zod';
17
20
  import { PROFILE_MAX_BIO_CHARS } from './constants.js';
18
21
  import { profilePrivacySchema, visibilityLevelSchema } from './enums.js';
19
22
  import { viewerSocialStateSchema } from './social.js';
23
+ /**
24
+ * Mini-row used in the "Followed by X, Y + N more" mutuals line on the
25
+ * profile header. The server picks up to 3 sample names + a count of
26
+ * the remaining mutuals so the row reads naturally without paginating
27
+ * the full mutuals list inline.
28
+ */
29
+ export const profileMutualsSchema = z.object({
30
+ /** Avatar URLs (or single-letter fallbacks via `null`) for the sample
31
+ * mutuals — order is "show first" → "show last". Capped at 3. */
32
+ avatars: z.array(z.string().url().nullable()).max(3),
33
+ /** Display names matched 1:1 with `avatars` order. Empty when the
34
+ * viewer has no mutuals with the profile owner. */
35
+ sampleNames: z.array(z.string()).max(3),
36
+ /** How many additional mutuals exist beyond the sample. Used to
37
+ * render the trailing "+ N more" suffix. Zero when the sample IS
38
+ * the full list. */
39
+ extraCount: z.number().int().nonnegative(),
40
+ });
20
41
  export const publicProfileWireSchema = z.object({
21
42
  userId: z.string(),
22
43
  displayName: z.string(),
23
44
  avatarUrl: z.string().url().optional(),
24
45
  /** Author area at view time (resolved server-side). Hidden when
25
- * privacy is `private` and viewer is not a Connection. */
46
+ * privacy is `private` and the viewer is not the owner. */
26
47
  localName: z.string().optional(),
27
48
  /** Privacy of THIS profile (not the viewer's). Useful for the UI
28
49
  * to render a lock chip when the profile is private. */
29
50
  privacy: profilePrivacySchema,
30
51
  /** Short bio — present only when set by the user. */
31
52
  bio: z.string().max(PROFILE_MAX_BIO_CHARS).optional(),
32
- /** Engagement counters. Hidden on private profiles to non-Connections. */
53
+ /** Engagement counters. Hidden on private profiles when the viewer is
54
+ * not the owner. Three-tuple post-redesign: connections went away
55
+ * when the connection-request feature was removed in v0.9.0. */
33
56
  counters: z
34
57
  .object({
35
58
  postCount: z.number().int().nonnegative(),
36
59
  followerCount: z.number().int().nonnegative(),
37
60
  followingCount: z.number().int().nonnegative(),
38
- connectionCount: z.number().int().nonnegative(),
39
61
  })
40
62
  .optional(),
63
+ /** Mutual followees between the viewer and the profile owner. Renders
64
+ * the "Followed by X, Y + N more" line. Omitted for self-view (no
65
+ * point telling you about yourself) and when the viewer has no
66
+ * mutuals with the owner. */
67
+ mutuals: profileMutualsSchema.optional(),
41
68
  /** Per-viewer relationship state. Always present (never gated). */
42
69
  viewer: viewerSocialStateSchema,
43
70
  });
@@ -1 +1 @@
1
- {"version":3,"file":"profile.js","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAEtD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,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;IAEtC;+DAC2D;IAC3D,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAEhC;6DACyD;IACzD,OAAO,EAAE,oBAAoB;IAE7B,qDAAqD;IACrD,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC,QAAQ,EAAE;IAErD,0EAA0E;IAC1E,QAAQ,EAAE,CAAC;SACR,MAAM,CAAC;QACN,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;QACzC,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;QAC7C,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;QAC9C,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;KAChD,CAAC;SACD,QAAQ,EAAE;IAEb,mEAAmE;IACnE,MAAM,EAAE,uBAAuB;CAChC,CAAC,CAAC;AAGH,+EAA+E;AAE/E;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,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,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,OAAO,EAAE,oBAAoB;IAC7B,MAAM,EAAE,uBAAuB;CAChC,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,6CAA6C;IAC7C,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACxB;yEACqE;IACrE,KAAK,EAAE,qBAAqB,CAAC,QAAQ,EAAE;IACvC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,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,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/C,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,oBAAoB,CAAC;IACpC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAClC,CAAC,CAAC","sourcesContent":["/**\n * Public community-profile wire shape.\n *\n * What every viewer can see about another user's community presence.\n * Differs from the auth/UDP `User` shape — this view is purposely thin\n * and content-engagement-oriented (post count, follower count, …).\n *\n * Privacy gating:\n * - `public` profile: the full shape is returned to any signed-in viewer.\n * - `private` profile: only `userId`, `displayName`, `avatarUrl`, and\n * the viewer's social state are returned to non-Connections. Posts\n * and counters are hidden until a Connection is accepted.\n *\n * @module community-schema/profile\n */\n\nimport { z } from 'zod';\nimport { PROFILE_MAX_BIO_CHARS } from './constants.js';\nimport { profilePrivacySchema, visibilityLevelSchema } from './enums.js';\nimport { viewerSocialStateSchema } from './social.js';\n\nexport const publicProfileWireSchema = z.object({\n userId: z.string(),\n displayName: z.string(),\n avatarUrl: z.string().url().optional(),\n\n /** Author area at view time (resolved server-side). Hidden when\n * privacy is `private` and viewer is not a Connection. */\n localName: z.string().optional(),\n\n /** Privacy of THIS profile (not the viewer's). Useful for the UI\n * to render a lock chip when the profile is private. */\n privacy: profilePrivacySchema,\n\n /** Short bio — present only when set by the user. */\n bio: z.string().max(PROFILE_MAX_BIO_CHARS).optional(),\n\n /** Engagement counters. Hidden on private profiles to non-Connections. */\n counters: z\n .object({\n postCount: z.number().int().nonnegative(),\n followerCount: z.number().int().nonnegative(),\n followingCount: z.number().int().nonnegative(),\n connectionCount: z.number().int().nonnegative(),\n })\n .optional(),\n\n /** Per-viewer relationship state. Always present (never gated). */\n viewer: viewerSocialStateSchema,\n});\nexport type PublicProfileWire = z.infer<typeof publicProfileWireSchema>;\n\n// ─── People list ────────────────────────────────────────────────────────────\n\n/**\n * Lightweight row used in the People tab list. Fewer fields than the\n * full profile to keep the list response small.\n */\nexport const peopleListItemSchema = z.object({\n userId: z.string(),\n displayName: z.string(),\n avatarUrl: z.string().url().optional(),\n localName: z.string().optional(),\n privacy: profilePrivacySchema,\n viewer: viewerSocialStateSchema,\n});\nexport type PeopleListItem = z.infer<typeof peopleListItemSchema>;\n\nexport const peopleQueryParamsSchema = z.object({\n /** Free-text search across `displayName`. */\n q: z.string().optional(),\n /** Area-scope filter. When set, server filters to users whose primary\n * area lineage matches the viewer's lineage at the chosen level. */\n level: visibilityLevelSchema.optional(),\n cursor: z.string().optional(),\n pageSize: z.number().int().positive().max(50).optional(),\n});\nexport type PeopleQueryParams = z.infer<typeof peopleQueryParamsSchema>;\n\nexport const peopleListResponseSchema = z.object({\n items: z.array(peopleListItemSchema),\n nextCursor: z.string().nullable(),\n});\nexport type PeopleListResponse = z.infer<typeof peopleListResponseSchema>;\n"]}
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Public community-profile wire shape.\n *\n * What every viewer can see about another user's community presence.\n * Differs from the auth/UDP `User` shape — this view is purposely thin\n * and content-engagement-oriented (post count, follower count, …).\n *\n * Privacy gating:\n * - `public` profile: the full shape is returned to any signed-in viewer.\n * - `private` profile: only `userId`, `displayName`, `avatarUrl`, and\n * the viewer's follow state are returned to non-followers. Posts and\n * counters are hidden until the viewer follows the profile owner and\n * the owner has accepted (TODO: follow-approval lifecycle — currently\n * \"private\" simply hides counters/posts from anyone who isn't the\n * owner).\n *\n * @module community-schema/profile\n */\n\nimport { z } from 'zod';\nimport { PROFILE_MAX_BIO_CHARS } from './constants.js';\nimport { profilePrivacySchema, visibilityLevelSchema } from './enums.js';\nimport { viewerSocialStateSchema } from './social.js';\n\n/**\n * Mini-row used in the \"Followed by X, Y + N more\" mutuals line on the\n * profile header. The server picks up to 3 sample names + a count of\n * the remaining mutuals so the row reads naturally without paginating\n * the full mutuals list inline.\n */\nexport const profileMutualsSchema = z.object({\n /** Avatar URLs (or single-letter fallbacks via `null`) for the sample\n * mutuals — order is \"show first\" → \"show last\". Capped at 3. */\n avatars: z.array(z.string().url().nullable()).max(3),\n /** Display names matched 1:1 with `avatars` order. Empty when the\n * viewer has no mutuals with the profile owner. */\n sampleNames: z.array(z.string()).max(3),\n /** How many additional mutuals exist beyond the sample. Used to\n * render the trailing \"+ N more\" suffix. Zero when the sample IS\n * the full list. */\n extraCount: z.number().int().nonnegative(),\n});\nexport type ProfileMutuals = z.infer<typeof profileMutualsSchema>;\n\nexport const publicProfileWireSchema = z.object({\n userId: z.string(),\n displayName: z.string(),\n avatarUrl: z.string().url().optional(),\n\n /** Author area at view time (resolved server-side). Hidden when\n * privacy is `private` and the viewer is not the owner. */\n localName: z.string().optional(),\n\n /** Privacy of THIS profile (not the viewer's). Useful for the UI\n * to render a lock chip when the profile is private. */\n privacy: profilePrivacySchema,\n\n /** Short bio — present only when set by the user. */\n bio: z.string().max(PROFILE_MAX_BIO_CHARS).optional(),\n\n /** Engagement counters. Hidden on private profiles when the viewer is\n * not the owner. Three-tuple post-redesign: connections went away\n * when the connection-request feature was removed in v0.9.0. */\n counters: z\n .object({\n postCount: z.number().int().nonnegative(),\n followerCount: z.number().int().nonnegative(),\n followingCount: z.number().int().nonnegative(),\n })\n .optional(),\n\n /** Mutual followees between the viewer and the profile owner. Renders\n * the \"Followed by X, Y + N more\" line. Omitted for self-view (no\n * point telling you about yourself) and when the viewer has no\n * mutuals with the owner. */\n mutuals: profileMutualsSchema.optional(),\n\n /** Per-viewer relationship state. Always present (never gated). */\n viewer: viewerSocialStateSchema,\n});\nexport type PublicProfileWire = z.infer<typeof publicProfileWireSchema>;\n\n// ─── People list ────────────────────────────────────────────────────────────\n\n/**\n * Lightweight row used in the People tab list. Fewer fields than the\n * full profile to keep the list response small.\n */\nexport const peopleListItemSchema = z.object({\n userId: z.string(),\n displayName: z.string(),\n avatarUrl: z.string().url().optional(),\n localName: z.string().optional(),\n privacy: profilePrivacySchema,\n viewer: viewerSocialStateSchema,\n});\nexport type PeopleListItem = z.infer<typeof peopleListItemSchema>;\n\nexport const peopleQueryParamsSchema = z.object({\n /** Free-text search across `displayName`. */\n q: z.string().optional(),\n /** Area-scope filter. When set, server filters to users whose primary\n * area lineage matches the viewer's lineage at the chosen level. */\n level: visibilityLevelSchema.optional(),\n cursor: z.string().optional(),\n pageSize: z.number().int().positive().max(50).optional(),\n});\nexport type PeopleQueryParams = z.infer<typeof peopleQueryParamsSchema>;\n\nexport const peopleListResponseSchema = z.object({\n items: z.array(peopleListItemSchema),\n nextCursor: z.string().nullable(),\n});\nexport type PeopleListResponse = z.infer<typeof peopleListResponseSchema>;\n"]}
package/dist/repost.d.ts CHANGED
@@ -69,10 +69,6 @@ export declare const createRepostResponseSchema: z.ZodObject<{
69
69
  localId: z.ZodOptional<z.ZodString>;
70
70
  localName: z.ZodOptional<z.ZodString>;
71
71
  }, z.core.$strip>;
72
- audience: z.ZodEnum<{
73
- public: "public";
74
- connections: "connections";
75
- }>;
76
72
  communityId: z.ZodOptional<z.ZodString>;
77
73
  upvoteCount: z.ZodNumber;
78
74
  commentCount: z.ZodNumber;
@@ -1 +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;;;GAGG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;iBASjC,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"}
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;;;GAGG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;iBASjC,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"}
@@ -24,8 +24,6 @@ export declare const communitySettingsWireSchema: z.ZodObject<{
24
24
  blockedCount: z.ZodNumber;
25
25
  notifications: z.ZodObject<{
26
26
  onFollow: z.ZodBoolean;
27
- onConnectionRequest: z.ZodBoolean;
28
- onConnectionAccepted: z.ZodBoolean;
29
27
  onComment: z.ZodBoolean;
30
28
  onReply: z.ZodBoolean;
31
29
  onUpvote: z.ZodBoolean;
@@ -51,8 +49,6 @@ export declare const updateCommunitySettingsBodySchema: z.ZodObject<{
51
49
  bio: z.ZodOptional<z.ZodNullable<z.ZodString>>;
52
50
  notifications: z.ZodOptional<z.ZodObject<{
53
51
  onFollow: z.ZodOptional<z.ZodBoolean>;
54
- onConnectionRequest: z.ZodOptional<z.ZodBoolean>;
55
- onConnectionAccepted: z.ZodOptional<z.ZodBoolean>;
56
52
  onComment: z.ZodOptional<z.ZodBoolean>;
57
53
  onReply: z.ZodOptional<z.ZodBoolean>;
58
54
  onUpvote: z.ZodOptional<z.ZodBoolean>;
@@ -1 +1 @@
1
- {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;iBA4BtC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF;;;;;;;;GAQG;AACH,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;;;;iBAe5C,CAAC;AACH,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iCAAiC,CAAC,CAAC;AAI5F;;;;GAIG;AACH,eAAO,MAAM,qBAAqB;;;;;;iBAMhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,8BAA8B;;;;;;;;iBAEzC,CAAC;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC;AAItF,eAAO,MAAM,2BAA2B,EAAE,qBAczC,CAAC"}
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;iBAwBtC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF;;;;;;;;GAQG;AACH,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;;iBAa5C,CAAC;AACH,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iCAAiC,CAAC,CAAC;AAI5F;;;;GAIG;AACH,eAAO,MAAM,qBAAqB;;;;;;iBAMhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,8BAA8B;;;;;;;;iBAEzC,CAAC;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC;AAItF,eAAO,MAAM,2BAA2B,EAAE,qBAYzC,CAAC"}
package/dist/settings.js CHANGED
@@ -30,10 +30,6 @@ export const communitySettingsWireSchema = z.object({
30
30
  notifications: z.object({
31
31
  /** Notify me when someone follows me. */
32
32
  onFollow: z.boolean(),
33
- /** Notify me when someone sends me a connection request. */
34
- onConnectionRequest: z.boolean(),
35
- /** Notify me when someone accepts my connection request. */
36
- onConnectionAccepted: z.boolean(),
37
33
  /** Notify me when someone comments on my post / lost-found / voice-box. */
38
34
  onComment: z.boolean(),
39
35
  /** Notify me when someone replies to my comment. */
@@ -61,8 +57,6 @@ export const updateCommunitySettingsBodySchema = z.object({
61
57
  notifications: z
62
58
  .object({
63
59
  onFollow: z.boolean().optional(),
64
- onConnectionRequest: z.boolean().optional(),
65
- onConnectionAccepted: z.boolean().optional(),
66
60
  onComment: z.boolean().optional(),
67
61
  onReply: z.boolean().optional(),
68
62
  onUpvote: z.boolean().optional(),
@@ -94,8 +88,6 @@ export const COMMUNITY_SETTINGS_DEFAULTS = {
94
88
  blockedCount: 0,
95
89
  notifications: {
96
90
  onFollow: true,
97
- onConnectionRequest: true,
98
- onConnectionAccepted: true,
99
91
  onComment: true,
100
92
  onReply: true,
101
93
  onUpvote: false,
@@ -1 +1 @@
1
- {"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Community settings wire shape.\n *\n * Per-user preferences scoped to the community feature. Read from\n * `GET /api/v1/community/settings` and updated via\n * `PATCH /api/v1/community/settings`. Updates are partial — the client\n * sends only the fields it changes.\n *\n * Block list management has dedicated routes (POST / DELETE\n * `/settings/blocks/:userId`); only the COUNT is mirrored on the\n * settings shape so the Settings page can show \"N blocked users\"\n * without a second round-trip. The full list is read via\n * `GET /settings/blocks`.\n *\n * @module community-schema/settings\n */\n\nimport { z } from 'zod';\nimport { PROFILE_MAX_BIO_CHARS } from './constants.js';\nimport { profilePrivacySchema } from './enums.js';\n\nexport const communitySettingsWireSchema = z.object({\n /** Profile-level privacy toggle. */\n privacy: profilePrivacySchema,\n /** Free-text bio shown on the profile (nullable so the user can clear it). */\n bio: z.string().max(PROFILE_MAX_BIO_CHARS).nullable(),\n /** How many users the caller has blocked. The full list lives behind\n * `GET /settings/blocks` to keep this hot read small. */\n blockedCount: z.number().int().nonnegative(),\n /** Per-event notification toggles. The map is sparse: a missing key\n * means \"use the default\". */\n notifications: z.object({\n /** Notify me when someone follows me. */\n onFollow: z.boolean(),\n /** Notify me when someone sends me a connection request. */\n onConnectionRequest: z.boolean(),\n /** Notify me when someone accepts my connection request. */\n onConnectionAccepted: z.boolean(),\n /** Notify me when someone comments on my post / lost-found / voice-box. */\n onComment: z.boolean(),\n /** Notify me when someone replies to my comment. */\n onReply: z.boolean(),\n /** Notify me when someone upvotes my content. */\n onUpvote: z.boolean(),\n /** Notify me when someone reacts to my content. */\n onReaction: z.boolean(),\n /** Notify me about activity in groups I'm a member of. */\n onGroupActivity: z.boolean(),\n }),\n});\nexport type CommunitySettingsWire = z.infer<typeof communitySettingsWireSchema>;\n\n/**\n * PATCH body — every field optional. The server merges over the existing\n * settings. Notifications is a partial sub-shape so the client can\n * toggle one knob at a time.\n *\n * `bio` accepts `null` to clear; omit the key entirely to leave it\n * unchanged. Block list is NOT included here — see the dedicated\n * `/settings/blocks` routes.\n */\nexport const updateCommunitySettingsBodySchema = z.object({\n privacy: profilePrivacySchema.optional(),\n bio: z.string().max(PROFILE_MAX_BIO_CHARS).nullable().optional(),\n notifications: z\n .object({\n onFollow: z.boolean().optional(),\n onConnectionRequest: z.boolean().optional(),\n onConnectionAccepted: z.boolean().optional(),\n onComment: z.boolean().optional(),\n onReply: z.boolean().optional(),\n onUpvote: z.boolean().optional(),\n onReaction: z.boolean().optional(),\n onGroupActivity: z.boolean().optional(),\n })\n .optional(),\n});\nexport type UpdateCommunitySettingsBody = z.infer<typeof updateCommunitySettingsBodySchema>;\n\n// ─── Blocked users list ────────────────────────────────────────────────────\n\n/**\n * One row in `GET /settings/blocks`. Mirrors the PeopleListItem shape\n * minus the per-viewer social state (the caller's viewer state w.r.t.\n * a blocked user is always \"blocked\").\n */\nexport const blockedUserWireSchema = z.object({\n userId: z.string(),\n displayName: z.string(),\n avatarUrl: z.string().url().optional(),\n localName: z.string().optional(),\n blockedAt: z.string().datetime(),\n});\nexport type BlockedUserWire = z.infer<typeof blockedUserWireSchema>;\n\nexport const blockedUsersListResponseSchema = z.object({\n items: z.array(blockedUserWireSchema),\n});\nexport type BlockedUsersListResponse = z.infer<typeof blockedUsersListResponseSchema>;\n\n// ─── Defaults (used by the backend when a user has no settings doc yet) ────\n\nexport const COMMUNITY_SETTINGS_DEFAULTS: CommunitySettingsWire = {\n privacy: 'public',\n bio: null,\n blockedCount: 0,\n notifications: {\n onFollow: true,\n onConnectionRequest: true,\n onConnectionAccepted: true,\n onComment: true,\n onReply: true,\n onUpvote: false,\n onReaction: false,\n onGroupActivity: true,\n },\n};\n"]}
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Community settings wire shape.\n *\n * Per-user preferences scoped to the community feature. Read from\n * `GET /api/v1/community/settings` and updated via\n * `PATCH /api/v1/community/settings`. Updates are partial — the client\n * sends only the fields it changes.\n *\n * Block list management has dedicated routes (POST / DELETE\n * `/settings/blocks/:userId`); only the COUNT is mirrored on the\n * settings shape so the Settings page can show \"N blocked users\"\n * without a second round-trip. The full list is read via\n * `GET /settings/blocks`.\n *\n * @module community-schema/settings\n */\n\nimport { z } from 'zod';\nimport { PROFILE_MAX_BIO_CHARS } from './constants.js';\nimport { profilePrivacySchema } from './enums.js';\n\nexport const communitySettingsWireSchema = z.object({\n /** Profile-level privacy toggle. */\n privacy: profilePrivacySchema,\n /** Free-text bio shown on the profile (nullable so the user can clear it). */\n bio: z.string().max(PROFILE_MAX_BIO_CHARS).nullable(),\n /** How many users the caller has blocked. The full list lives behind\n * `GET /settings/blocks` to keep this hot read small. */\n blockedCount: z.number().int().nonnegative(),\n /** Per-event notification toggles. The map is sparse: a missing key\n * means \"use the default\". */\n notifications: z.object({\n /** Notify me when someone follows me. */\n onFollow: z.boolean(),\n /** Notify me when someone comments on my post / lost-found / voice-box. */\n onComment: z.boolean(),\n /** Notify me when someone replies to my comment. */\n onReply: z.boolean(),\n /** Notify me when someone upvotes my content. */\n onUpvote: z.boolean(),\n /** Notify me when someone reacts to my content. */\n onReaction: z.boolean(),\n /** Notify me about activity in groups I'm a member of. */\n onGroupActivity: z.boolean(),\n }),\n});\nexport type CommunitySettingsWire = z.infer<typeof communitySettingsWireSchema>;\n\n/**\n * PATCH body — every field optional. The server merges over the existing\n * settings. Notifications is a partial sub-shape so the client can\n * toggle one knob at a time.\n *\n * `bio` accepts `null` to clear; omit the key entirely to leave it\n * unchanged. Block list is NOT included here — see the dedicated\n * `/settings/blocks` routes.\n */\nexport const updateCommunitySettingsBodySchema = z.object({\n privacy: profilePrivacySchema.optional(),\n bio: z.string().max(PROFILE_MAX_BIO_CHARS).nullable().optional(),\n notifications: z\n .object({\n onFollow: z.boolean().optional(),\n onComment: z.boolean().optional(),\n onReply: z.boolean().optional(),\n onUpvote: z.boolean().optional(),\n onReaction: z.boolean().optional(),\n onGroupActivity: z.boolean().optional(),\n })\n .optional(),\n});\nexport type UpdateCommunitySettingsBody = z.infer<typeof updateCommunitySettingsBodySchema>;\n\n// ─── Blocked users list ────────────────────────────────────────────────────\n\n/**\n * One row in `GET /settings/blocks`. Mirrors the PeopleListItem shape\n * minus the per-viewer social state (the caller's viewer state w.r.t.\n * a blocked user is always \"blocked\").\n */\nexport const blockedUserWireSchema = z.object({\n userId: z.string(),\n displayName: z.string(),\n avatarUrl: z.string().url().optional(),\n localName: z.string().optional(),\n blockedAt: z.string().datetime(),\n});\nexport type BlockedUserWire = z.infer<typeof blockedUserWireSchema>;\n\nexport const blockedUsersListResponseSchema = z.object({\n items: z.array(blockedUserWireSchema),\n});\nexport type BlockedUsersListResponse = z.infer<typeof blockedUsersListResponseSchema>;\n\n// ─── Defaults (used by the backend when a user has no settings doc yet) ────\n\nexport const COMMUNITY_SETTINGS_DEFAULTS: CommunitySettingsWire = {\n privacy: 'public',\n bio: null,\n blockedCount: 0,\n notifications: {\n onFollow: true,\n onComment: true,\n onReply: true,\n onUpvote: false,\n onReaction: false,\n onGroupActivity: true,\n },\n};\n"]}
package/dist/social.d.ts CHANGED
@@ -1,42 +1,27 @@
1
1
  /**
2
- * Social graph wire shapes — follows and connections.
2
+ * Social graph wire shapes — follow only.
3
3
  *
4
- * Two distinct relationships:
4
+ * Single relationship now:
5
5
  *
6
- * Follow — one-way, no acceptance required (Twitter / Instagram).
7
- * The follower starts seeing the followee's posts in their
8
- * feed regardless of geo scope. Followee is notified.
6
+ * Follow — one-way, no acceptance required (Twitter / Instagram).
7
+ * The follower starts seeing the followee's posts in their
8
+ * feed regardless of geo scope. Followee is notified.
9
9
  *
10
- * Connection — mutual handshake (LinkedIn). Requester sends, recipient
11
- * accepts / declines. ACCEPTED connections bypass the
12
- * visibility-level cascade entirely: connected users
13
- * always see each other's posts no matter the level.
14
- * This is the "friend posts always visible" rule.
15
- *
16
- * The two surfaces don't overlap: a user can follow someone they're
17
- * not connected with, and they can be connected without following.
10
+ * The mutual-handshake "Connection" concept was removed in schema 0.9.0;
11
+ * the redesign aligns the social model with Instagram / Twitter where a
12
+ * one-way follow is the only relationship primitive. Connections-only
13
+ * post audiences and the connection-bypass on the feed visibility cascade
14
+ * went with it.
18
15
  *
19
16
  * @module community-schema/social
20
17
  */
21
18
  import { z } from 'zod';
22
19
  /**
23
20
  * The viewer's state w.r.t. a target user. Returned inline on profile
24
- * reads so the UI can render Follow / Connect buttons without a second
25
- * request.
21
+ * reads so the UI can render the Follow button without a second request.
26
22
  */
27
23
  export declare const viewerSocialStateSchema: z.ZodObject<{
28
24
  following: z.ZodBoolean;
29
- connectionStatus: z.ZodNullable<z.ZodEnum<{
30
- pending: "pending";
31
- accepted: "accepted";
32
- declined: "declined";
33
- blocked: "blocked";
34
- }>>;
35
- pendingDirection: z.ZodNullable<z.ZodEnum<{
36
- sent: "sent";
37
- received: "received";
38
- }>>;
39
- connectionId: z.ZodNullable<z.ZodString>;
40
25
  }, z.core.$strip>;
41
26
  export type ViewerSocialState = z.infer<typeof viewerSocialStateSchema>;
42
27
  /**
@@ -50,49 +35,4 @@ export declare const toggleFollowResponseSchema: z.ZodObject<{
50
35
  followerCount: z.ZodNumber;
51
36
  }, z.core.$strip>;
52
37
  export type ToggleFollowResponse = z.infer<typeof toggleFollowResponseSchema>;
53
- /**
54
- * Send a connection request. The endpoint is
55
- * `POST /api/v1/community/users/:id/connect`. The body is empty — the
56
- * relationship is identified by the path id + the authenticated caller.
57
- */
58
- export declare const sendConnectionRequestResponseSchema: z.ZodObject<{
59
- targetUserId: z.ZodString;
60
- status: z.ZodEnum<{
61
- pending: "pending";
62
- accepted: "accepted";
63
- declined: "declined";
64
- blocked: "blocked";
65
- }>;
66
- connectionId: z.ZodString;
67
- following: z.ZodBoolean;
68
- }, z.core.$strip>;
69
- export type SendConnectionRequestResponse = z.infer<typeof sendConnectionRequestResponseSchema>;
70
- /**
71
- * Body for `POST /api/v1/community/connections/:id/decision` (accept /
72
- * decline / block / unblock on an existing connection record).
73
- */
74
- export declare const connectionDecisionBodySchema: z.ZodObject<{
75
- decision: z.ZodEnum<{
76
- accept: "accept";
77
- decline: "decline";
78
- block: "block";
79
- unblock: "unblock";
80
- remove: "remove";
81
- }>;
82
- }, z.core.$strip>;
83
- export type ConnectionDecisionBody = z.infer<typeof connectionDecisionBodySchema>;
84
- export declare const connectionRecordWireSchema: z.ZodObject<{
85
- _id: z.ZodString;
86
- otherUserId: z.ZodString;
87
- status: z.ZodEnum<{
88
- pending: "pending";
89
- accepted: "accepted";
90
- declined: "declined";
91
- blocked: "blocked";
92
- }>;
93
- requestedByUserId: z.ZodString;
94
- createdAt: z.ZodString;
95
- acceptedAt: z.ZodNullable<z.ZodString>;
96
- }, z.core.$strip>;
97
- export type ConnectionRecordWire = z.infer<typeof connectionRecordWireSchema>;
98
38
  //# sourceMappingURL=social.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"social.d.ts","sourceRoot":"","sources":["../src/social.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB;;;;GAIG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;iBAuBlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE;;;;GAIG;AACH,eAAO,MAAM,0BAA0B;;;;iBAIrC,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAI9E;;;;GAIG;AACH,eAAO,MAAM,mCAAmC;;;;;;;;;;iBAc9C,CAAC;AACH,MAAM,MAAM,6BAA6B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mCAAmC,CAAC,CAAC;AAEhG;;;GAGG;AACH,eAAO,MAAM,4BAA4B;;;;;;;;iBAEvC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAElF,eAAO,MAAM,0BAA0B;;;;;;;;;;;;iBASrC,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC"}
1
+ {"version":3,"file":"social.d.ts","sourceRoot":"","sources":["../src/social.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;GAGG;AACH,eAAO,MAAM,uBAAuB;;iBAGlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE;;;;GAIG;AACH,eAAO,MAAM,0BAA0B;;;;iBAIrC,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC"}
package/dist/social.js CHANGED
@@ -1,54 +1,29 @@
1
1
  /**
2
- * Social graph wire shapes — follows and connections.
2
+ * Social graph wire shapes — follow only.
3
3
  *
4
- * Two distinct relationships:
4
+ * Single relationship now:
5
5
  *
6
- * Follow — one-way, no acceptance required (Twitter / Instagram).
7
- * The follower starts seeing the followee's posts in their
8
- * feed regardless of geo scope. Followee is notified.
6
+ * Follow — one-way, no acceptance required (Twitter / Instagram).
7
+ * The follower starts seeing the followee's posts in their
8
+ * feed regardless of geo scope. Followee is notified.
9
9
  *
10
- * Connection — mutual handshake (LinkedIn). Requester sends, recipient
11
- * accepts / declines. ACCEPTED connections bypass the
12
- * visibility-level cascade entirely: connected users
13
- * always see each other's posts no matter the level.
14
- * This is the "friend posts always visible" rule.
15
- *
16
- * The two surfaces don't overlap: a user can follow someone they're
17
- * not connected with, and they can be connected without following.
10
+ * The mutual-handshake "Connection" concept was removed in schema 0.9.0;
11
+ * the redesign aligns the social model with Instagram / Twitter where a
12
+ * one-way follow is the only relationship primitive. Connections-only
13
+ * post audiences and the connection-bypass on the feed visibility cascade
14
+ * went with it.
18
15
  *
19
16
  * @module community-schema/social
20
17
  */
21
18
  import { z } from 'zod';
22
- import { connectionStatusSchema } from './enums.js';
23
19
  // ─── Follow ─────────────────────────────────────────────────────────────────
24
20
  /**
25
21
  * The viewer's state w.r.t. a target user. Returned inline on profile
26
- * reads so the UI can render Follow / Connect buttons without a second
27
- * request.
22
+ * reads so the UI can render the Follow button without a second request.
28
23
  */
29
24
  export const viewerSocialStateSchema = z.object({
30
25
  /** True when the viewer is following the target. */
31
26
  following: z.boolean(),
32
- /** Connection status from the viewer's perspective:
33
- * - null → no connection record exists
34
- * - 'pending' → there is a pending request between them
35
- * - 'accepted' → they're connected
36
- * - 'declined' → previous request was declined
37
- * - 'blocked' → either side blocked the other
38
- */
39
- connectionStatus: connectionStatusSchema.nullable(),
40
- /** When connectionStatus === 'pending', identifies who has the action:
41
- * - 'sent' → viewer sent the request; awaiting target's accept
42
- * - 'received' → target sent the request; viewer must accept / decline
43
- * Null in all other states. */
44
- pendingDirection: z.enum(['sent', 'received']).nullable(),
45
- /** Connection record id, when ANY connection row exists between viewer
46
- * and target (pending / accepted / declined / blocked). Surfaced so
47
- * list rows can call POST /connections/:id/decision directly without
48
- * a follow-up "find my connection with this user" lookup — used by
49
- * the People-row Respond button to accept / decline an incoming
50
- * request in place. Null when no row exists. */
51
- connectionId: z.string().nullable(),
52
27
  });
53
28
  /**
54
29
  * Response when the viewer toggles follow on a target user. The endpoint
@@ -60,42 +35,4 @@ export const toggleFollowResponseSchema = z.object({
60
35
  following: z.boolean(),
61
36
  followerCount: z.number().int().nonnegative(),
62
37
  });
63
- // ─── Connection ────────────────────────────────────────────────────────────
64
- /**
65
- * Send a connection request. The endpoint is
66
- * `POST /api/v1/community/users/:id/connect`. The body is empty — the
67
- * relationship is identified by the path id + the authenticated caller.
68
- */
69
- export const sendConnectionRequestResponseSchema = z.object({
70
- targetUserId: z.string(),
71
- /** The status after the call. For a fresh request → 'pending'. For a
72
- * reciprocal request that auto-accepts → 'accepted'. */
73
- status: connectionStatusSchema,
74
- /** Connection record id after the call. Always present on success —
75
- * the request either created a row or matched an existing one. */
76
- connectionId: z.string(),
77
- /** True when the viewer is following the target after the call.
78
- * Sending a connection request implicitly creates a Follow (idempotent
79
- * — if the viewer was already following, this stays true with no extra
80
- * side effect). Surfaced so the client can flip the Follow button
81
- * state directly from the response. */
82
- following: z.boolean(),
83
- });
84
- /**
85
- * Body for `POST /api/v1/community/connections/:id/decision` (accept /
86
- * decline / block / unblock on an existing connection record).
87
- */
88
- export const connectionDecisionBodySchema = z.object({
89
- decision: z.enum(['accept', 'decline', 'block', 'unblock', 'remove']),
90
- });
91
- export const connectionRecordWireSchema = z.object({
92
- _id: z.string(),
93
- /** The "other" user from the viewer's perspective. */
94
- otherUserId: z.string(),
95
- status: connectionStatusSchema,
96
- /** Who initiated the request. Always the same regardless of viewer. */
97
- requestedByUserId: z.string(),
98
- createdAt: z.string().datetime(),
99
- acceptedAt: z.string().datetime().nullable(),
100
- });
101
38
  //# sourceMappingURL=social.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"social.js","sourceRoot":"","sources":["../src/social.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEpD,+EAA+E;AAE/E;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,oDAAoD;IACpD,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE;IACtB;;;;;;OAMG;IACH,gBAAgB,EAAE,sBAAsB,CAAC,QAAQ,EAAE;IACnD;;;oCAGgC;IAChC,gBAAgB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,EAAE;IACzD;;;;;qDAKiD;IACjD,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACpC,CAAC,CAAC;AAGH;;;;GAIG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC;IACjD,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;IACxB,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE;IACtB,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;CAC9C,CAAC,CAAC;AAGH,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,CAAC,MAAM,mCAAmC,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1D,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;IACxB;6DACyD;IACzD,MAAM,EAAE,sBAAsB;IAC9B;uEACmE;IACnE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;IACxB;;;;4CAIwC;IACxC,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE;CACvB,CAAC,CAAC;AAGH;;;GAGG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,CAAC,MAAM,CAAC;IACnD,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;CACtE,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC;IACjD,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,sDAAsD;IACtD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,MAAM,EAAE,sBAAsB;IAC9B,uEAAuE;IACvE,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE;IAC7B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;CAC7C,CAAC,CAAC","sourcesContent":["/**\n * Social graph wire shapes — follows and connections.\n *\n * Two distinct relationships:\n *\n * Follow — one-way, no acceptance required (Twitter / Instagram).\n * The follower starts seeing the followee's posts in their\n * feed regardless of geo scope. Followee is notified.\n *\n * Connection — mutual handshake (LinkedIn). Requester sends, recipient\n * accepts / declines. ACCEPTED connections bypass the\n * visibility-level cascade entirely: connected users\n * always see each other's posts no matter the level.\n * This is the \"friend posts always visible\" rule.\n *\n * The two surfaces don't overlap: a user can follow someone they're\n * not connected with, and they can be connected without following.\n *\n * @module community-schema/social\n */\n\nimport { z } from 'zod';\nimport { connectionStatusSchema } from './enums.js';\n\n// ─── Follow ─────────────────────────────────────────────────────────────────\n\n/**\n * The viewer's state w.r.t. a target user. Returned inline on profile\n * reads so the UI can render Follow / Connect buttons without a second\n * request.\n */\nexport const viewerSocialStateSchema = z.object({\n /** True when the viewer is following the target. */\n following: z.boolean(),\n /** Connection status from the viewer's perspective:\n * - null → no connection record exists\n * - 'pending' → there is a pending request between them\n * - 'accepted' → they're connected\n * - 'declined' → previous request was declined\n * - 'blocked' → either side blocked the other\n */\n connectionStatus: connectionStatusSchema.nullable(),\n /** When connectionStatus === 'pending', identifies who has the action:\n * - 'sent' → viewer sent the request; awaiting target's accept\n * - 'received' → target sent the request; viewer must accept / decline\n * Null in all other states. */\n pendingDirection: z.enum(['sent', 'received']).nullable(),\n /** Connection record id, when ANY connection row exists between viewer\n * and target (pending / accepted / declined / blocked). Surfaced so\n * list rows can call POST /connections/:id/decision directly without\n * a follow-up \"find my connection with this user\" lookup — used by\n * the People-row Respond button to accept / decline an incoming\n * request in place. Null when no row exists. */\n connectionId: z.string().nullable(),\n});\nexport type ViewerSocialState = z.infer<typeof viewerSocialStateSchema>;\n\n/**\n * Response when the viewer toggles follow on a target user. The endpoint\n * is `POST /api/v1/community/users/:id/follow` and is idempotent —\n * calling twice removes the follow.\n */\nexport const toggleFollowResponseSchema = z.object({\n targetUserId: z.string(),\n following: z.boolean(),\n followerCount: z.number().int().nonnegative(),\n});\nexport type ToggleFollowResponse = z.infer<typeof toggleFollowResponseSchema>;\n\n// ─── Connection ────────────────────────────────────────────────────────────\n\n/**\n * Send a connection request. The endpoint is\n * `POST /api/v1/community/users/:id/connect`. The body is empty — the\n * relationship is identified by the path id + the authenticated caller.\n */\nexport const sendConnectionRequestResponseSchema = z.object({\n targetUserId: z.string(),\n /** The status after the call. For a fresh request → 'pending'. For a\n * reciprocal request that auto-accepts → 'accepted'. */\n status: connectionStatusSchema,\n /** Connection record id after the call. Always present on success —\n * the request either created a row or matched an existing one. */\n connectionId: z.string(),\n /** True when the viewer is following the target after the call.\n * Sending a connection request implicitly creates a Follow (idempotent\n * — if the viewer was already following, this stays true with no extra\n * side effect). Surfaced so the client can flip the Follow button\n * state directly from the response. */\n following: z.boolean(),\n});\nexport type SendConnectionRequestResponse = z.infer<typeof sendConnectionRequestResponseSchema>;\n\n/**\n * Body for `POST /api/v1/community/connections/:id/decision` (accept /\n * decline / block / unblock on an existing connection record).\n */\nexport const connectionDecisionBodySchema = z.object({\n decision: z.enum(['accept', 'decline', 'block', 'unblock', 'remove']),\n});\nexport type ConnectionDecisionBody = z.infer<typeof connectionDecisionBodySchema>;\n\nexport const connectionRecordWireSchema = z.object({\n _id: z.string(),\n /** The \"other\" user from the viewer's perspective. */\n otherUserId: z.string(),\n status: connectionStatusSchema,\n /** Who initiated the request. Always the same regardless of viewer. */\n requestedByUserId: z.string(),\n createdAt: z.string().datetime(),\n acceptedAt: z.string().datetime().nullable(),\n});\nexport type ConnectionRecordWire = z.infer<typeof connectionRecordWireSchema>;\n"]}
1
+ {"version":3,"file":"social.js","sourceRoot":"","sources":["../src/social.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,+EAA+E;AAE/E;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,oDAAoD;IACpD,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE;CACvB,CAAC,CAAC;AAGH;;;;GAIG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC;IACjD,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;IACxB,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE;IACtB,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;CAC9C,CAAC,CAAC","sourcesContent":["/**\n * Social graph wire shapes — follow only.\n *\n * Single relationship now:\n *\n * Follow — one-way, no acceptance required (Twitter / Instagram).\n * The follower starts seeing the followee's posts in their\n * feed regardless of geo scope. Followee is notified.\n *\n * The mutual-handshake \"Connection\" concept was removed in schema 0.9.0;\n * the redesign aligns the social model with Instagram / Twitter where a\n * one-way follow is the only relationship primitive. Connections-only\n * post audiences and the connection-bypass on the feed visibility cascade\n * went with it.\n *\n * @module community-schema/social\n */\n\nimport { z } from 'zod';\n\n// ─── Follow ─────────────────────────────────────────────────────────────────\n\n/**\n * The viewer's state w.r.t. a target user. Returned inline on profile\n * reads so the UI can render the Follow button without a second request.\n */\nexport const viewerSocialStateSchema = z.object({\n /** True when the viewer is following the target. */\n following: z.boolean(),\n});\nexport type ViewerSocialState = z.infer<typeof viewerSocialStateSchema>;\n\n/**\n * Response when the viewer toggles follow on a target user. The endpoint\n * is `POST /api/v1/community/users/:id/follow` and is idempotent —\n * calling twice removes the follow.\n */\nexport const toggleFollowResponseSchema = z.object({\n targetUserId: z.string(),\n following: z.boolean(),\n followerCount: z.number().int().nonnegative(),\n});\nexport type ToggleFollowResponse = z.infer<typeof toggleFollowResponseSchema>;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jansathi-community-schema",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Shared Zod schemas + TypeScript types for the Jansathi hyperlocal community feature (feed, posts, engagement, social graph, groups, communities).",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",