jansathi-community-schema 0.1.0 → 0.2.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.
@@ -1 +1 @@
1
- {"version":3,"file":"enums.d.ts","sourceRoot":"","sources":["../src/enums.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,uBAAuB,+DAM1B,CAAC;AACX,eAAO,MAAM,qBAAqB;;;;;;EAAkC,CAAC;AACrE,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAMjE,CAAC;AAIF;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,8CAA+C,CAAC;AAChF,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,yDAK3B,CAAC;AACX,eAAO,MAAM,sBAAsB;;;;;EAAmC,CAAC;AACvE,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAItE;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,gCAAiC,CAAC;AACrE,eAAO,MAAM,oBAAoB;;;EAAiC,CAAC;AACnE,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAIlE;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,yIAUvB,CAAC;AACX,eAAO,MAAM,kBAAkB;;;;;;;;;;EAA+B,CAAC;AAC/D,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,6CAA6C;AAC7C,eAAO,MAAM,oBAAoB,4DAKvB,CAAC;AACX,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;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,uBAAuB,+DAM1B,CAAC;AACX,eAAO,MAAM,qBAAqB;;;;;;EAAkC,CAAC;AACrE,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAMjE,CAAC;AAIF;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,8CAA+C,CAAC;AAChF,eAAO,MAAM,iBAAiB;;;;EAA8B,CAAC;AAC7D,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAI5D;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,qEAQvB,CAAC;AACX,eAAO,MAAM,kBAAkB;;;;;;;;EAA+B,CAAC;AAC/D,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAI9D;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,yDAA0D,CAAC;AAChG,eAAO,MAAM,sBAAsB;;;;;EAAmC,CAAC;AACvE,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAItE;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,gCAAiC,CAAC;AACrE,eAAO,MAAM,oBAAoB;;;EAAiC,CAAC;AACnE,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAIlE;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,yIAUvB,CAAC;AACX,eAAO,MAAM,kBAAkB;;;;;;;;;;EAA+B,CAAC;AAC/D,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,6CAA6C;AAC7C,eAAO,MAAM,oBAAoB,4DAA6D,CAAC;AAC/F,eAAO,MAAM,kBAAkB;;;;;EAA+B,CAAC;AAC/D,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAI9D;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,gCAAiC,CAAC;AAC/D,eAAO,MAAM,cAAc;;;;EAA2B,CAAC;AACvD,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC"}
package/dist/enums.js CHANGED
@@ -82,12 +82,7 @@ export const reactionTypeSchema = z.enum(REACTION_TYPE_VALUES);
82
82
  * `declined` — recipient rejected; surfaces as "you can't reconnect for X days" on the requester side.
83
83
  * `blocked` — either side blocked; permanently prevents reconnection.
84
84
  */
85
- export const CONNECTION_STATUS_VALUES = [
86
- 'pending',
87
- 'accepted',
88
- 'declined',
89
- 'blocked',
90
- ];
85
+ export const CONNECTION_STATUS_VALUES = ['pending', 'accepted', 'declined', 'blocked'];
91
86
  export const connectionStatusSchema = z.enum(CONNECTION_STATUS_VALUES);
92
87
  // ─── Profile privacy ───────────────────────────────────────────────────────
93
88
  /**
@@ -120,12 +115,7 @@ export const REPORT_REASON_VALUES = [
120
115
  ];
121
116
  export const reportReasonSchema = z.enum(REPORT_REASON_VALUES);
122
117
  /** Moderator decision states on a report. */
123
- export const REPORT_STATUS_VALUES = [
124
- 'pending',
125
- 'reviewing',
126
- 'actioned',
127
- 'dismissed',
128
- ];
118
+ export const REPORT_STATUS_VALUES = ['pending', 'reviewing', 'actioned', 'dismissed'];
129
119
  export const reportStatusSchema = z.enum(REPORT_STATUS_VALUES);
130
120
  // ─── Feed sort ─────────────────────────────────────────────────────────────
131
121
  /**
package/dist/enums.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"enums.js","sourceRoot":"","sources":["../src/enums.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,+EAA+E;AAE/E;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,OAAO;IACP,UAAU;IACV,OAAO;IACP,UAAU;IACV,QAAQ;CACA,CAAC;AACX,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;AAGrE;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAoC;IACpE,KAAK,EAAE,CAAC;IACR,QAAQ,EAAE,CAAC;IACX,KAAK,EAAE,CAAC;IACR,QAAQ,EAAE,CAAC;IACX,MAAM,EAAE,CAAC;CACV,CAAC;AAEF,+EAA+E;AAE/E;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,MAAM,EAAE,YAAY,EAAE,WAAW,CAAU,CAAC;AAChF,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;IACtC,SAAS;IACT,UAAU;IACV,UAAU;IACV,SAAS;CACD,CAAC;AACX,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;AAGvE,8EAA8E;AAE9E;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAU,CAAC;AACrE,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;AAGnE,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,MAAM;IACN,YAAY;IACZ,aAAa;IACb,gBAAgB;IAChB,gBAAgB;IAChB,UAAU;IACV,WAAW;IACX,iBAAiB;IACjB,OAAO;CACC,CAAC;AACX,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;AAG/D,6CAA6C;AAC7C,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,SAAS;IACT,WAAW;IACX,UAAU;IACV,WAAW;CACH,CAAC;AACX,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;AAG/D,8EAA8E;AAE9E;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAU,CAAC;AAC/D,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC","sourcesContent":["/**\n * Enum value arrays shared across the community feature.\n *\n * Each enum is exported as both a `*_VALUES` tuple and the corresponding\n * Zod schema so backend Mongoose models and frontend forms validate\n * against the exact same set.\n *\n * @module community-schema/enums\n */\n\nimport { z } from 'zod';\n\n// ─── Visibility scope ───────────────────────────────────────────────────────\n\n/**\n * The geographic level at which a piece of content is posted.\n *\n * Cascade-upward semantics: a viewer whose feed filter is set to L\n * sees every post at L and every BROADER level that matches their\n * area lineage. So:\n * - `local` → matches local + district + state + national + global within the viewer's locality / village / urbanBody / etc.\n * - `district` → matches district + state + national + global within the viewer's district\n * - `state` → matches state + national + global within the viewer's state\n * - `national` → matches national + global within the viewer's country\n * - `global` → matches global only\n *\n * The full meaning of \"local\" is \"anything below district\" — i.e., the\n * deepest area-lineage match (locality, village, urbanWard, …).\n */\nexport const VISIBILITY_LEVEL_VALUES = [\n 'local',\n 'district',\n 'state',\n 'national',\n 'global',\n] as const;\nexport const visibilityLevelSchema = z.enum(VISIBILITY_LEVEL_VALUES);\nexport type VisibilityLevel = z.infer<typeof visibilityLevelSchema>;\n\n/**\n * Numeric ranking used for the cascade-upward query and for sorting\n * filter chips. `local` is the deepest (most specific), `global` the\n * shallowest. Higher rank = broader scope.\n */\nexport const VISIBILITY_LEVEL_RANK: Record<VisibilityLevel, number> = {\n local: 0,\n district: 1,\n state: 2,\n national: 3,\n global: 4,\n};\n\n// ─── Polymorphic content kind ───────────────────────────────────────────────\n\n/**\n * The kinds of items that show up in the feed. `post` is the new\n * community-native kind; `lost_found` and `voice_box` are existing\n * features surfaced into the feed via polymorphic union.\n *\n * Engagement (upvote / reaction / comment) 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'] 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 = [\n 'pending',\n 'accepted',\n 'declined',\n 'blocked',\n] as const;\nexport const connectionStatusSchema = z.enum(CONNECTION_STATUS_VALUES);\nexport type ConnectionStatus = z.infer<typeof connectionStatusSchema>;\n\n// ─── Profile privacy ───────────────────────────────────────────────────────\n\n/**\n * Profile-level privacy (single toggle in Settings).\n *\n * `public` — anyone in the matching geo scope sees this user's posts.\n * `private` — only accepted Connections see this user's posts. Visibility\n * level on each post still applies on top (a private post at\n * state level is visible only to Connections who are in the\n * same state).\n */\nexport const PROFILE_PRIVACY_VALUES = ['public', 'private'] as const;\nexport const profilePrivacySchema = z.enum(PROFILE_PRIVACY_VALUES);\nexport type ProfilePrivacy = z.infer<typeof profilePrivacySchema>;\n\n// ─── Moderation ────────────────────────────────────────────────────────────\n\n/**\n * Reasons a piece of content can be reported. The list is deliberately\n * short — finer categorization can come from the optional `details`\n * free-text field on a report.\n */\nexport const REPORT_REASON_VALUES = [\n 'spam',\n 'harassment',\n 'hate_speech',\n 'misinformation',\n 'sexual_content',\n 'violence',\n 'self_harm',\n 'illegal_content',\n 'other',\n] as const;\nexport const reportReasonSchema = z.enum(REPORT_REASON_VALUES);\nexport type ReportReason = z.infer<typeof reportReasonSchema>;\n\n/** Moderator decision states on a report. */\nexport const REPORT_STATUS_VALUES = [\n 'pending',\n 'reviewing',\n 'actioned',\n 'dismissed',\n] 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,+EAA+E;AAE/E;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,OAAO;IACP,UAAU;IACV,OAAO;IACP,UAAU;IACV,QAAQ;CACA,CAAC;AACX,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;AAGrE;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAoC;IACpE,KAAK,EAAE,CAAC;IACR,QAAQ,EAAE,CAAC;IACX,KAAK,EAAE,CAAC;IACR,QAAQ,EAAE,CAAC;IACX,MAAM,EAAE,CAAC;CACV,CAAC;AAEF,+EAA+E;AAE/E;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,MAAM,EAAE,YAAY,EAAE,WAAW,CAAU,CAAC;AAChF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;AAG7D,+EAA+E;AAE/E;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,MAAM;IACN,MAAM;IACN,MAAM;IACN,KAAK;IACL,KAAK;IACL,OAAO;IACP,SAAS;CACD,CAAC;AACX,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;AAG/D,8EAA8E;AAE9E;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,CAAU,CAAC;AAChG,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;AAGvE,8EAA8E;AAE9E;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAU,CAAC;AACrE,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;AAGnE,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,MAAM;IACN,YAAY;IACZ,aAAa;IACb,gBAAgB;IAChB,gBAAgB;IAChB,UAAU;IACV,WAAW;IACX,iBAAiB;IACjB,OAAO;CACC,CAAC;AACX,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;AAG/D,6CAA6C;AAC7C,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,CAAU,CAAC;AAC/F,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;AAG/D,8EAA8E;AAE9E;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAU,CAAC;AAC/D,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC","sourcesContent":["/**\n * Enum value arrays shared across the community feature.\n *\n * Each enum is exported as both a `*_VALUES` tuple and the corresponding\n * Zod schema so backend Mongoose models and frontend forms validate\n * against the exact same set.\n *\n * @module community-schema/enums\n */\n\nimport { z } from 'zod';\n\n// ─── Visibility scope ───────────────────────────────────────────────────────\n\n/**\n * The geographic level at which a piece of content is posted.\n *\n * Cascade-upward semantics: a viewer whose feed filter is set to L\n * sees every post at L and every BROADER level that matches their\n * area lineage. So:\n * - `local` → matches local + district + state + national + global within the viewer's locality / village / urbanBody / etc.\n * - `district` → matches district + state + national + global within the viewer's district\n * - `state` → matches state + national + global within the viewer's state\n * - `national` → matches national + global within the viewer's country\n * - `global` → matches global only\n *\n * The full meaning of \"local\" is \"anything below district\" — i.e., the\n * deepest area-lineage match (locality, village, urbanWard, …).\n */\nexport const VISIBILITY_LEVEL_VALUES = [\n 'local',\n 'district',\n 'state',\n 'national',\n 'global',\n] as const;\nexport const visibilityLevelSchema = z.enum(VISIBILITY_LEVEL_VALUES);\nexport type VisibilityLevel = z.infer<typeof visibilityLevelSchema>;\n\n/**\n * Numeric ranking used for the cascade-upward query and for sorting\n * filter chips. `local` is the deepest (most specific), `global` the\n * shallowest. Higher rank = broader scope.\n */\nexport const VISIBILITY_LEVEL_RANK: Record<VisibilityLevel, number> = {\n local: 0,\n district: 1,\n state: 2,\n national: 3,\n global: 4,\n};\n\n// ─── Polymorphic content kind ───────────────────────────────────────────────\n\n/**\n * The kinds of items that show up in the feed. `post` is the new\n * community-native kind; `lost_found` and `voice_box` are existing\n * features surfaced into the feed via polymorphic union.\n *\n * Engagement (upvote / reaction / comment) 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'] as const;\nexport const contentKindSchema = z.enum(CONTENT_KIND_VALUES);\nexport type ContentKind = z.infer<typeof contentKindSchema>;\n\n// ─── Reactions ──────────────────────────────────────────────────────────────\n\n/**\n * Reaction types available on every feed item.\n *\n * `support` replaces Facebook's \"Care\" — better-suited to a civic /\n * hyperlocal context where reacting to a complaint or lost-and-found\n * post deserves a distinct \"I support you\" signal.\n */\nexport const REACTION_TYPE_VALUES = [\n 'like',\n 'love',\n 'haha',\n 'wow',\n 'sad',\n 'angry',\n 'support',\n] as const;\nexport const reactionTypeSchema = z.enum(REACTION_TYPE_VALUES);\nexport type ReactionType = z.infer<typeof reactionTypeSchema>;\n\n// ─── Social graph ──────────────────────────────────────────────────────────\n\n/**\n * Connection (mutual friend) lifecycle.\n *\n * `pending` — requester sent it, recipient hasn't acted yet.\n * `accepted` — both sides confirmed; full visibility regardless of level.\n * `declined` — recipient rejected; surfaces as \"you can't reconnect for X days\" on the requester side.\n * `blocked` — either side blocked; permanently prevents reconnection.\n */\nexport const CONNECTION_STATUS_VALUES = ['pending', 'accepted', 'declined', 'blocked'] as const;\nexport const connectionStatusSchema = z.enum(CONNECTION_STATUS_VALUES);\nexport type ConnectionStatus = z.infer<typeof connectionStatusSchema>;\n\n// ─── Profile privacy ───────────────────────────────────────────────────────\n\n/**\n * Profile-level privacy (single toggle in Settings).\n *\n * `public` — anyone in the matching geo scope sees this user's posts.\n * `private` — only accepted Connections see this user's posts. Visibility\n * level on each post still applies on top (a private post at\n * state level is visible only to Connections who are in the\n * same state).\n */\nexport const PROFILE_PRIVACY_VALUES = ['public', 'private'] as const;\nexport const profilePrivacySchema = z.enum(PROFILE_PRIVACY_VALUES);\nexport type ProfilePrivacy = z.infer<typeof profilePrivacySchema>;\n\n// ─── Moderation ────────────────────────────────────────────────────────────\n\n/**\n * Reasons a piece of content can be reported. The list is deliberately\n * short — finer categorization can come from the optional `details`\n * free-text field on a report.\n */\nexport const REPORT_REASON_VALUES = [\n 'spam',\n 'harassment',\n 'hate_speech',\n 'misinformation',\n 'sexual_content',\n 'violence',\n 'self_harm',\n 'illegal_content',\n 'other',\n] as const;\nexport const reportReasonSchema = z.enum(REPORT_REASON_VALUES);\nexport type ReportReason = z.infer<typeof reportReasonSchema>;\n\n/** Moderator decision states on a report. */\nexport const REPORT_STATUS_VALUES = ['pending', 'reviewing', 'actioned', 'dismissed'] as const;\nexport const reportStatusSchema = z.enum(REPORT_STATUS_VALUES);\nexport type ReportStatus = z.infer<typeof reportStatusSchema>;\n\n// ─── Feed sort ─────────────────────────────────────────────────────────────\n\n/**\n * Sort options exposed in the feed UI.\n *\n * `hot` — the default. Reddit-style score blending upvotes, comment count,\n * and recency. Best surface for civic / community engagement.\n * `new` — strict reverse-chronological. Useful when the viewer wants to\n * catch up on everything fresh.\n * `top` — highest upvote count over a configurable window (defaults to\n * 24 hours on the client).\n */\nexport const FEED_SORT_VALUES = ['hot', 'new', 'top'] as const;\nexport const feedSortSchema = z.enum(FEED_SORT_VALUES);\nexport type FeedSort = z.infer<typeof feedSortSchema>;\n"]}
package/dist/group.d.ts CHANGED
@@ -41,8 +41,119 @@ export declare const createGroupBodySchema: z.ZodObject<{
41
41
  memberUserIds: z.ZodArray<z.ZodString>;
42
42
  }, z.core.$strip>;
43
43
  export type CreateGroupBody = z.infer<typeof createGroupBodySchema>;
44
+ /**
45
+ * PATCH body for `/groups/:groupId`. All fields optional; sending
46
+ * `null` for `description` or `imageUrl` clears that field. Sending
47
+ * `name` requires the new value to satisfy the min/max constraints.
48
+ */
49
+ export declare const updateGroupBodySchema: z.ZodObject<{
50
+ name: z.ZodOptional<z.ZodString>;
51
+ description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
52
+ imageUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
53
+ }, z.core.$strip>;
54
+ export type UpdateGroupBody = z.infer<typeof updateGroupBodySchema>;
44
55
  export declare const addGroupMembersBodySchema: z.ZodObject<{
45
56
  userIds: z.ZodArray<z.ZodString>;
46
57
  }, z.core.$strip>;
47
58
  export type AddGroupMembersBody = z.infer<typeof addGroupMembersBodySchema>;
59
+ /**
60
+ * One row in `GET /groups/:groupId/members` or the inlined member list
61
+ * on `GET /groups/:groupId`. Carries display info so the roster
62
+ * renders without an N+1 profile fetch.
63
+ */
64
+ export declare const groupMemberWireSchema: z.ZodObject<{
65
+ userId: z.ZodString;
66
+ displayName: z.ZodString;
67
+ avatarUrl: z.ZodOptional<z.ZodString>;
68
+ localName: z.ZodOptional<z.ZodString>;
69
+ role: z.ZodEnum<{
70
+ owner: "owner";
71
+ admin: "admin";
72
+ member: "member";
73
+ }>;
74
+ joinedAt: z.ZodString;
75
+ }, z.core.$strip>;
76
+ export type GroupMemberWire = z.infer<typeof groupMemberWireSchema>;
77
+ /**
78
+ * `GET /groups/:groupId` returns the full group + the first page of
79
+ * members. Larger groups paginate the members via
80
+ * `GET /groups/:groupId/members?cursor=…`.
81
+ */
82
+ export declare const communityGroupWithMembersSchema: z.ZodObject<{
83
+ _id: z.ZodString;
84
+ conversationId: z.ZodString;
85
+ name: z.ZodString;
86
+ description: z.ZodOptional<z.ZodString>;
87
+ imageUrl: z.ZodOptional<z.ZodString>;
88
+ createdByUserId: z.ZodString;
89
+ memberCount: z.ZodNumber;
90
+ createdAt: z.ZodString;
91
+ viewer: z.ZodOptional<z.ZodObject<{
92
+ role: z.ZodEnum<{
93
+ owner: "owner";
94
+ admin: "admin";
95
+ member: "member";
96
+ }>;
97
+ joinedAt: z.ZodString;
98
+ }, z.core.$strip>>;
99
+ members: z.ZodArray<z.ZodObject<{
100
+ userId: z.ZodString;
101
+ displayName: z.ZodString;
102
+ avatarUrl: z.ZodOptional<z.ZodString>;
103
+ localName: z.ZodOptional<z.ZodString>;
104
+ role: z.ZodEnum<{
105
+ owner: "owner";
106
+ admin: "admin";
107
+ member: "member";
108
+ }>;
109
+ joinedAt: z.ZodString;
110
+ }, z.core.$strip>>;
111
+ membersNextCursor: z.ZodNullable<z.ZodString>;
112
+ }, z.core.$strip>;
113
+ export type CommunityGroupWithMembers = z.infer<typeof communityGroupWithMembersSchema>;
114
+ /**
115
+ * Response shape for `GET /groups` (groups the viewer is a member of)
116
+ * and `GET /groups/discover` (Phase 7+ — groups in viewer's geo scope).
117
+ *
118
+ * `nextCursor` is an opaque base64 string the client passes back to
119
+ * fetch the next page; null when the current page is the last.
120
+ */
121
+ export declare const groupsListResponseSchema: z.ZodObject<{
122
+ items: z.ZodArray<z.ZodObject<{
123
+ _id: z.ZodString;
124
+ conversationId: z.ZodString;
125
+ name: z.ZodString;
126
+ description: z.ZodOptional<z.ZodString>;
127
+ imageUrl: z.ZodOptional<z.ZodString>;
128
+ createdByUserId: z.ZodString;
129
+ memberCount: z.ZodNumber;
130
+ createdAt: z.ZodString;
131
+ viewer: z.ZodOptional<z.ZodObject<{
132
+ role: z.ZodEnum<{
133
+ owner: "owner";
134
+ admin: "admin";
135
+ member: "member";
136
+ }>;
137
+ joinedAt: z.ZodString;
138
+ }, z.core.$strip>>;
139
+ }, z.core.$strip>>;
140
+ nextCursor: z.ZodNullable<z.ZodString>;
141
+ }, z.core.$strip>;
142
+ export type GroupsListResponse = z.infer<typeof groupsListResponseSchema>;
143
+ export declare const groupMembersListResponseSchema: z.ZodObject<{
144
+ items: z.ZodArray<z.ZodObject<{
145
+ userId: z.ZodString;
146
+ displayName: z.ZodString;
147
+ avatarUrl: z.ZodOptional<z.ZodString>;
148
+ localName: z.ZodOptional<z.ZodString>;
149
+ role: z.ZodEnum<{
150
+ owner: "owner";
151
+ admin: "admin";
152
+ member: "member";
153
+ }>;
154
+ joinedAt: z.ZodString;
155
+ }, z.core.$strip>>;
156
+ nextCursor: z.ZodNullable<z.ZodString>;
157
+ }, z.core.$strip>;
158
+ export type GroupMembersListResponse = z.infer<typeof groupMembersListResponseSchema>;
48
159
  //# sourceMappingURL=group.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"group.d.ts","sourceRoot":"","sources":["../src/group.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,eAAO,MAAM,eAAe;;;;EAAuC,CAAC;AACpE,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;iBAmBnC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAI1E,eAAO,MAAM,qBAAqB;;;;iBAKhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAIpE,eAAO,MAAM,yBAAyB;;iBAEpC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC"}
1
+ {"version":3,"file":"group.d.ts","sourceRoot":"","sources":["../src/group.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,eAAe;;;;EAAuC,CAAC;AACpE,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;iBAmBnC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAI1E,eAAO,MAAM,qBAAqB;;;;iBAKhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAIpE;;;;GAIG;AACH,eAAO,MAAM,qBAAqB;;;;iBAIhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAIpE,eAAO,MAAM,yBAAyB;;iBAEpC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAI5E;;;;GAIG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;iBAOhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;;;GAIG;AACH,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAG1C,CAAC;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC;AAIxF;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;iBAGnC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;iBAGzC,CAAC;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC"}
package/dist/group.js CHANGED
@@ -10,7 +10,7 @@
10
10
  * @module community-schema/group
11
11
  */
12
12
  import { z } from 'zod';
13
- import { GROUP_MAX_MEMBERS, GROUP_NAME_MAX_CHARS, GROUP_NAME_MIN_CHARS, } from './constants.js';
13
+ import { GROUP_MAX_MEMBERS, GROUP_NAME_MAX_CHARS, GROUP_NAME_MIN_CHARS } from './constants.js';
14
14
  export const groupRoleSchema = z.enum(['owner', 'admin', 'member']);
15
15
  export const communityGroupWireSchema = z.object({
16
16
  _id: z.string(),
@@ -38,8 +38,58 @@ export const createGroupBodySchema = z.object({
38
38
  /** Initial member user ids (excluding the creator who becomes owner). */
39
39
  memberUserIds: z.array(z.string()).max(GROUP_MAX_MEMBERS - 1),
40
40
  });
41
+ // ─── Update body (owner / admin only) ──────────────────────────────────────
42
+ /**
43
+ * PATCH body for `/groups/:groupId`. All fields optional; sending
44
+ * `null` for `description` or `imageUrl` clears that field. Sending
45
+ * `name` requires the new value to satisfy the min/max constraints.
46
+ */
47
+ export const updateGroupBodySchema = z.object({
48
+ name: z.string().min(GROUP_NAME_MIN_CHARS).max(GROUP_NAME_MAX_CHARS).optional(),
49
+ description: z.string().max(500).nullable().optional(),
50
+ imageUrl: z.string().url().nullable().optional(),
51
+ });
41
52
  // ─── Add / remove members ──────────────────────────────────────────────────
42
53
  export const addGroupMembersBodySchema = z.object({
43
54
  userIds: z.array(z.string()).min(1).max(50),
44
55
  });
56
+ // ─── Member roster row ─────────────────────────────────────────────────────
57
+ /**
58
+ * One row in `GET /groups/:groupId/members` or the inlined member list
59
+ * on `GET /groups/:groupId`. Carries display info so the roster
60
+ * renders without an N+1 profile fetch.
61
+ */
62
+ export const groupMemberWireSchema = z.object({
63
+ userId: z.string(),
64
+ displayName: z.string(),
65
+ avatarUrl: z.string().url().optional(),
66
+ localName: z.string().optional(),
67
+ role: groupRoleSchema,
68
+ joinedAt: z.string().datetime(),
69
+ });
70
+ /**
71
+ * `GET /groups/:groupId` returns the full group + the first page of
72
+ * members. Larger groups paginate the members via
73
+ * `GET /groups/:groupId/members?cursor=…`.
74
+ */
75
+ export const communityGroupWithMembersSchema = communityGroupWireSchema.extend({
76
+ members: z.array(groupMemberWireSchema),
77
+ membersNextCursor: z.string().nullable(),
78
+ });
79
+ // ─── List response ─────────────────────────────────────────────────────────
80
+ /**
81
+ * Response shape for `GET /groups` (groups the viewer is a member of)
82
+ * and `GET /groups/discover` (Phase 7+ — groups in viewer's geo scope).
83
+ *
84
+ * `nextCursor` is an opaque base64 string the client passes back to
85
+ * fetch the next page; null when the current page is the last.
86
+ */
87
+ export const groupsListResponseSchema = z.object({
88
+ items: z.array(communityGroupWireSchema),
89
+ nextCursor: z.string().nullable(),
90
+ });
91
+ export const groupMembersListResponseSchema = z.object({
92
+ items: z.array(groupMemberWireSchema),
93
+ nextCursor: z.string().nullable(),
94
+ });
45
95
  //# sourceMappingURL=group.js.map
package/dist/group.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"group.js","sourceRoot":"","sources":["../src/group.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AAExB,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;AAGpE,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,8DAA8D;IAC9D,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE;IAC1B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,GAAG,CAAC,oBAAoB,CAAC;IACpE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IAC3C,kCAAkC;IAClC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACrC,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE;IAC3B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IAC3C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAEhC,+DAA+D;IAC/D,MAAM,EAAE,CAAC;SACN,MAAM,CAAC;QACN,IAAI,EAAE,eAAe;QACrB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KAChC,CAAC;SACD,QAAQ,EAAE;CACd,CAAC,CAAC;AAGH,+EAA+E;AAE/E,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,GAAG,CAAC,oBAAoB,CAAC;IACpE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IAC3C,yEAAyE;IACzE,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,iBAAiB,GAAG,CAAC,CAAC;CAC9D,CAAC,CAAC;AAGH,8EAA8E;AAE9E,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChD,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;CAC5C,CAAC,CAAC","sourcesContent":["/**\n * User-created group chat wire shapes for the Community → Chat tab.\n *\n * The community-scoped group chats are wire-compatible with the\n * generic `Conversation` shape on chat-server (so a community group\n * shows up in the inbox like any other conversation). What lives here\n * is the COMMUNITY-side metadata used to create + administer the group\n * before chat-server takes over.\n *\n * @module community-schema/group\n */\n\nimport { z } from 'zod';\nimport {\n GROUP_MAX_MEMBERS,\n GROUP_NAME_MAX_CHARS,\n GROUP_NAME_MIN_CHARS,\n} from './constants.js';\n\nexport const groupRoleSchema = z.enum(['owner', 'admin', 'member']);\nexport type GroupRole = z.infer<typeof groupRoleSchema>;\n\nexport const communityGroupWireSchema = z.object({\n _id: z.string(),\n /** The chat-server conversation id this group is bound to. */\n conversationId: z.string(),\n name: z.string().min(GROUP_NAME_MIN_CHARS).max(GROUP_NAME_MAX_CHARS),\n description: z.string().max(500).optional(),\n /** Group avatar / cover image. */\n imageUrl: z.string().url().optional(),\n createdByUserId: z.string(),\n memberCount: z.number().int().nonnegative(),\n createdAt: z.string().datetime(),\n\n /** Per-viewer state — included when the viewer is a member. */\n viewer: z\n .object({\n role: groupRoleSchema,\n joinedAt: z.string().datetime(),\n })\n .optional(),\n});\nexport type CommunityGroupWire = z.infer<typeof communityGroupWireSchema>;\n\n// ─── Create body ────────────────────────────────────────────────────────────\n\nexport const createGroupBodySchema = z.object({\n name: z.string().min(GROUP_NAME_MIN_CHARS).max(GROUP_NAME_MAX_CHARS),\n description: z.string().max(500).optional(),\n /** Initial member user ids (excluding the creator who becomes owner). */\n memberUserIds: z.array(z.string()).max(GROUP_MAX_MEMBERS - 1),\n});\nexport type CreateGroupBody = z.infer<typeof createGroupBodySchema>;\n\n// ─── Add / remove members ──────────────────────────────────────────────────\n\nexport const addGroupMembersBodySchema = z.object({\n userIds: z.array(z.string()).min(1).max(50),\n});\nexport type AddGroupMembersBody = z.infer<typeof addGroupMembersBodySchema>;\n"]}
1
+ {"version":3,"file":"group.js","sourceRoot":"","sources":["../src/group.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * User-created group chat wire shapes for the Community → Chat tab.\n *\n * The community-scoped group chats are wire-compatible with the\n * generic `Conversation` shape on chat-server (so a community group\n * shows up in the inbox like any other conversation). What lives here\n * is the COMMUNITY-side metadata used to create + administer the group\n * before chat-server takes over.\n *\n * @module community-schema/group\n */\n\nimport { z } from 'zod';\nimport { GROUP_MAX_MEMBERS, GROUP_NAME_MAX_CHARS, GROUP_NAME_MIN_CHARS } from './constants.js';\n\nexport const groupRoleSchema = z.enum(['owner', 'admin', 'member']);\nexport type GroupRole = z.infer<typeof groupRoleSchema>;\n\nexport const communityGroupWireSchema = z.object({\n _id: z.string(),\n /** The chat-server conversation id this group is bound to. */\n conversationId: z.string(),\n name: z.string().min(GROUP_NAME_MIN_CHARS).max(GROUP_NAME_MAX_CHARS),\n description: z.string().max(500).optional(),\n /** Group avatar / cover image. */\n imageUrl: z.string().url().optional(),\n createdByUserId: z.string(),\n memberCount: z.number().int().nonnegative(),\n createdAt: z.string().datetime(),\n\n /** Per-viewer state — included when the viewer is a member. */\n viewer: z\n .object({\n role: groupRoleSchema,\n joinedAt: z.string().datetime(),\n })\n .optional(),\n});\nexport type CommunityGroupWire = z.infer<typeof communityGroupWireSchema>;\n\n// ─── Create body ────────────────────────────────────────────────────────────\n\nexport const createGroupBodySchema = z.object({\n name: z.string().min(GROUP_NAME_MIN_CHARS).max(GROUP_NAME_MAX_CHARS),\n description: z.string().max(500).optional(),\n /** Initial member user ids (excluding the creator who becomes owner). */\n memberUserIds: z.array(z.string()).max(GROUP_MAX_MEMBERS - 1),\n});\nexport type CreateGroupBody = z.infer<typeof createGroupBodySchema>;\n\n// ─── Update body (owner / admin only) ──────────────────────────────────────\n\n/**\n * PATCH body for `/groups/:groupId`. All fields optional; sending\n * `null` for `description` or `imageUrl` clears that field. Sending\n * `name` requires the new value to satisfy the min/max constraints.\n */\nexport const updateGroupBodySchema = z.object({\n name: z.string().min(GROUP_NAME_MIN_CHARS).max(GROUP_NAME_MAX_CHARS).optional(),\n description: z.string().max(500).nullable().optional(),\n imageUrl: z.string().url().nullable().optional(),\n});\nexport type UpdateGroupBody = z.infer<typeof updateGroupBodySchema>;\n\n// ─── Add / remove members ──────────────────────────────────────────────────\n\nexport const addGroupMembersBodySchema = z.object({\n userIds: z.array(z.string()).min(1).max(50),\n});\nexport type AddGroupMembersBody = z.infer<typeof addGroupMembersBodySchema>;\n\n// ─── Member roster row ─────────────────────────────────────────────────────\n\n/**\n * One row in `GET /groups/:groupId/members` or the inlined member list\n * on `GET /groups/:groupId`. Carries display info so the roster\n * renders without an N+1 profile fetch.\n */\nexport const groupMemberWireSchema = z.object({\n userId: z.string(),\n displayName: z.string(),\n avatarUrl: z.string().url().optional(),\n localName: z.string().optional(),\n role: groupRoleSchema,\n joinedAt: z.string().datetime(),\n});\nexport type GroupMemberWire = z.infer<typeof groupMemberWireSchema>;\n\n/**\n * `GET /groups/:groupId` returns the full group + the first page of\n * members. Larger groups paginate the members via\n * `GET /groups/:groupId/members?cursor=…`.\n */\nexport const communityGroupWithMembersSchema = communityGroupWireSchema.extend({\n members: z.array(groupMemberWireSchema),\n membersNextCursor: z.string().nullable(),\n});\nexport type CommunityGroupWithMembers = z.infer<typeof communityGroupWithMembersSchema>;\n\n// ─── List response ─────────────────────────────────────────────────────────\n\n/**\n * Response shape for `GET /groups` (groups the viewer is a member of)\n * and `GET /groups/discover` (Phase 7+ — groups in viewer's geo scope).\n *\n * `nextCursor` is an opaque base64 string the client passes back to\n * fetch the next page; null when the current page is the last.\n */\nexport const groupsListResponseSchema = z.object({\n items: z.array(communityGroupWireSchema),\n nextCursor: z.string().nullable(),\n});\nexport type GroupsListResponse = z.infer<typeof groupsListResponseSchema>;\n\nexport const groupMembersListResponseSchema = z.object({\n items: z.array(groupMemberWireSchema),\n nextCursor: z.string().nullable(),\n});\nexport type GroupMembersListResponse = z.infer<typeof groupMembersListResponseSchema>;\n"]}
package/dist/index.d.ts CHANGED
@@ -15,16 +15,16 @@
15
15
  * @module community-schema
16
16
  */
17
17
  export { type AreaLineageSnapshot, areaLineageSnapshotSchema, } from './area.js';
18
- export { type CommunityCommentWire, communityCommentWireSchema, type CreateCommentBody, createCommentBodySchema, type UpdateCommentBody, updateCommentBodySchema, } from './comment.js';
18
+ export { type CommunityCommentWire, type CreateCommentBody, communityCommentWireSchema, createCommentBodySchema, type UpdateCommentBody, updateCommentBodySchema, } from './comment.js';
19
19
  export { COMMENT_MAX_BODY_CHARS, COMMENTS_PAGE_SIZE, EDIT_GRACE_WINDOW_MS, FEED_PAGE_SIZE, GROUP_MAX_MEMBERS, GROUP_NAME_MAX_CHARS, GROUP_NAME_MIN_CHARS, PEOPLE_PAGE_SIZE, POST_MAX_BODY_CHARS, POST_MAX_IMAGE_BYTES, POST_MAX_IMAGES, POST_MAX_VIDEO_BYTES, POST_MAX_VIDEO_SECONDS, POST_MAX_VIDEOS, PROFILE_MAX_BIO_CHARS, REPLIES_PRELOAD_COUNT, } from './constants.js';
20
- export { type SetReactionBody, setReactionBodySchema, type SetReactionResponse, setReactionResponseSchema, type ToggleUpvoteResponse, toggleUpvoteResponseSchema, } from './engagement.js';
21
- export { CONNECTION_STATUS_VALUES, type ConnectionStatus, connectionStatusSchema, CONTENT_KIND_VALUES, type ContentKind, contentKindSchema, FEED_SORT_VALUES, type FeedSort, feedSortSchema, PROFILE_PRIVACY_VALUES, type ProfilePrivacy, profilePrivacySchema, REACTION_TYPE_VALUES, type ReactionType, reactionTypeSchema, REPORT_REASON_VALUES, type ReportReason, reportReasonSchema, REPORT_STATUS_VALUES, type ReportStatus, reportStatusSchema, VISIBILITY_LEVEL_RANK, VISIBILITY_LEVEL_VALUES, type VisibilityLevel, visibilityLevelSchema, } from './enums.js';
20
+ export { type SetReactionBody, type SetReactionResponse, setReactionBodySchema, setReactionResponseSchema, type ToggleUpvoteResponse, toggleUpvoteResponseSchema, } from './engagement.js';
21
+ export { CONNECTION_STATUS_VALUES, CONTENT_KIND_VALUES, type ConnectionStatus, type ContentKind, connectionStatusSchema, contentKindSchema, FEED_SORT_VALUES, type FeedSort, feedSortSchema, PROFILE_PRIVACY_VALUES, type ProfilePrivacy, profilePrivacySchema, REACTION_TYPE_VALUES, REPORT_REASON_VALUES, REPORT_STATUS_VALUES, type ReactionType, type ReportReason, type ReportStatus, reactionTypeSchema, reportReasonSchema, reportStatusSchema, VISIBILITY_LEVEL_RANK, VISIBILITY_LEVEL_VALUES, type VisibilityLevel, visibilityLevelSchema, } from './enums.js';
22
22
  export { type FeedItem, type FeedQueryParams, type FeedResponse, feedItemSchema, feedQueryParamsSchema, feedResponseSchema, type LostFoundFeedItem, lostFoundFeedItemSchema, type VoiceBoxFeedItem, voiceBoxFeedItemSchema, } from './feed.js';
23
- export { type AddGroupMembersBody, addGroupMembersBodySchema, type CommunityGroupWire, communityGroupWireSchema, type CreateGroupBody, createGroupBodySchema, type GroupRole, groupRoleSchema, } from './group.js';
24
- export { type PostImage, postImageSchema, type PostVideo, postVideoSchema, } from './media.js';
25
- export { type CommunityPostWire, communityPostWireSchema, type CreatePostBody, createPostBodySchema, type PostAuthorSnapshot, postAuthorSnapshotSchema, type UpdatePostBody, updatePostBodySchema, } from './post.js';
26
- export { type PeopleListItem, type PeopleListResponse, type PeopleQueryParams, peopleListItemSchema, peopleListResponseSchema, peopleQueryParamsSchema, type PublicProfileWire, publicProfileWireSchema, } from './profile.js';
27
- export { type ReportContentBody, reportContentBodySchema, type ReportRecordWire, reportRecordWireSchema, } from './report.js';
28
- export { COMMUNITY_SETTINGS_DEFAULTS, type CommunitySettingsWire, communitySettingsWireSchema, type UpdateCommunitySettingsBody, updateCommunitySettingsBodySchema, } from './settings.js';
29
- export { type ConnectionDecisionBody, connectionDecisionBodySchema, type ConnectionRecordWire, connectionRecordWireSchema, type SendConnectionRequestResponse, sendConnectionRequestResponseSchema, type ToggleFollowResponse, toggleFollowResponseSchema, type ViewerSocialState, viewerSocialStateSchema, } from './social.js';
23
+ export { type AddGroupMembersBody, addGroupMembersBodySchema, type CommunityGroupWire, type CommunityGroupWithMembers, communityGroupWireSchema, communityGroupWithMembersSchema, type CreateGroupBody, createGroupBodySchema, type GroupMemberWire, type GroupMembersListResponse, groupMemberWireSchema, groupMembersListResponseSchema, type GroupRole, groupRoleSchema, type GroupsListResponse, groupsListResponseSchema, type UpdateGroupBody, updateGroupBodySchema, } from './group.js';
24
+ export { type PostImage, type PostVideo, postImageSchema, postVideoSchema, } from './media.js';
25
+ export { type CommunityPostWire, type CreatePostBody, communityPostWireSchema, createPostBodySchema, type PostAuthorSnapshot, postAuthorSnapshotSchema, type UpdatePostBody, updatePostBodySchema, } from './post.js';
26
+ export { type PeopleListItem, type PeopleListResponse, type PeopleQueryParams, type PublicProfileWire, peopleListItemSchema, peopleListResponseSchema, peopleQueryParamsSchema, publicProfileWireSchema, } from './profile.js';
27
+ export { type ReportContentBody, type ReportContentKind, type ReportRecordWire, type ReportSubmissionResponse, type ReportUserBody, reportContentBodySchema, reportContentKindSchema, reportRecordWireSchema, reportSubmissionResponseSchema, reportUserBodySchema, } from './report.js';
28
+ export { type BlockedUserWire, type BlockedUsersListResponse, blockedUserWireSchema, blockedUsersListResponseSchema, COMMUNITY_SETTINGS_DEFAULTS, type CommunitySettingsWire, communitySettingsWireSchema, type UpdateCommunitySettingsBody, updateCommunitySettingsBodySchema, } from './settings.js';
29
+ export { type ConnectionDecisionBody, type ConnectionRecordWire, connectionDecisionBodySchema, connectionRecordWireSchema, type SendConnectionRequestResponse, sendConnectionRequestResponseSchema, type ToggleFollowResponse, toggleFollowResponseSchema, type ViewerSocialState, viewerSocialStateSchema, } from './social.js';
30
30
  //# 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
@@ -23,11 +23,11 @@ export { COMMENT_MAX_BODY_CHARS, COMMENTS_PAGE_SIZE, EDIT_GRACE_WINDOW_MS, FEED_
23
23
  // ─── Engagement (upvote + reactions) ───────────────────────────────────────
24
24
  export { setReactionBodySchema, setReactionResponseSchema, toggleUpvoteResponseSchema, } from './engagement.js';
25
25
  // ─── Enums ─────────────────────────────────────────────────────────────────
26
- export { CONNECTION_STATUS_VALUES, connectionStatusSchema, CONTENT_KIND_VALUES, contentKindSchema, FEED_SORT_VALUES, feedSortSchema, PROFILE_PRIVACY_VALUES, profilePrivacySchema, REACTION_TYPE_VALUES, reactionTypeSchema, REPORT_REASON_VALUES, reportReasonSchema, REPORT_STATUS_VALUES, reportStatusSchema, VISIBILITY_LEVEL_RANK, VISIBILITY_LEVEL_VALUES, visibilityLevelSchema, } from './enums.js';
26
+ export { CONNECTION_STATUS_VALUES, CONTENT_KIND_VALUES, connectionStatusSchema, contentKindSchema, FEED_SORT_VALUES, feedSortSchema, PROFILE_PRIVACY_VALUES, profilePrivacySchema, REACTION_TYPE_VALUES, REPORT_REASON_VALUES, REPORT_STATUS_VALUES, reactionTypeSchema, reportReasonSchema, reportStatusSchema, VISIBILITY_LEVEL_RANK, VISIBILITY_LEVEL_VALUES, visibilityLevelSchema, } from './enums.js';
27
27
  // ─── Feed (polymorphic union) ──────────────────────────────────────────────
28
28
  export { feedItemSchema, feedQueryParamsSchema, feedResponseSchema, lostFoundFeedItemSchema, voiceBoxFeedItemSchema, } from './feed.js';
29
29
  // ─── Groups ────────────────────────────────────────────────────────────────
30
- export { addGroupMembersBodySchema, communityGroupWireSchema, createGroupBodySchema, groupRoleSchema, } from './group.js';
30
+ export { addGroupMembersBodySchema, communityGroupWireSchema, communityGroupWithMembersSchema, createGroupBodySchema, groupMemberWireSchema, groupMembersListResponseSchema, groupRoleSchema, groupsListResponseSchema, updateGroupBodySchema, } from './group.js';
31
31
  // ─── Media ─────────────────────────────────────────────────────────────────
32
32
  export { postImageSchema, postVideoSchema, } from './media.js';
33
33
  // ─── Post ──────────────────────────────────────────────────────────────────
@@ -35,9 +35,9 @@ export { communityPostWireSchema, createPostBodySchema, postAuthorSnapshotSchema
35
35
  // ─── Profile + People list ─────────────────────────────────────────────────
36
36
  export { peopleListItemSchema, peopleListResponseSchema, peopleQueryParamsSchema, publicProfileWireSchema, } from './profile.js';
37
37
  // ─── Reports (moderation) ──────────────────────────────────────────────────
38
- export { reportContentBodySchema, reportRecordWireSchema, } from './report.js';
38
+ export { reportContentBodySchema, reportContentKindSchema, reportRecordWireSchema, reportSubmissionResponseSchema, reportUserBodySchema, } from './report.js';
39
39
  // ─── Settings ──────────────────────────────────────────────────────────────
40
- export { COMMUNITY_SETTINGS_DEFAULTS, communitySettingsWireSchema, updateCommunitySettingsBodySchema, } from './settings.js';
40
+ export { blockedUserWireSchema, blockedUsersListResponseSchema, COMMUNITY_SETTINGS_DEFAULTS, communitySettingsWireSchema, updateCommunitySettingsBodySchema, } from './settings.js';
41
41
  // ─── Social (follow + connection) ──────────────────────────────────────────
42
42
  export { connectionDecisionBodySchema, connectionRecordWireSchema, sendConnectionRequestResponseSchema, toggleFollowResponseSchema, viewerSocialStateSchema, } from './social.js';
43
43
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,8EAA8E;AAC9E,OAAO,EAEL,yBAAyB,GAC1B,MAAM,WAAW,CAAC;AAEnB,8EAA8E;AAC9E,OAAO,EAEL,0BAA0B,EAE1B,uBAAuB,EAEvB,uBAAuB,GACxB,MAAM,cAAc,CAAC;AAEtB,8EAA8E;AAC9E,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,eAAe,EACf,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAExB,8EAA8E;AAC9E,OAAO,EAEL,qBAAqB,EAErB,yBAAyB,EAEzB,0BAA0B,GAC3B,MAAM,iBAAiB,CAAC;AAEzB,8EAA8E;AAC9E,OAAO,EACL,wBAAwB,EAExB,sBAAsB,EACtB,mBAAmB,EAEnB,iBAAiB,EACjB,gBAAgB,EAEhB,cAAc,EACd,sBAAsB,EAEtB,oBAAoB,EACpB,oBAAoB,EAEpB,kBAAkB,EAClB,oBAAoB,EAEpB,kBAAkB,EAClB,oBAAoB,EAEpB,kBAAkB,EAClB,qBAAqB,EACrB,uBAAuB,EAEvB,qBAAqB,GACtB,MAAM,YAAY,CAAC;AAEpB,8EAA8E;AAC9E,OAAO,EAIL,cAAc,EACd,qBAAqB,EACrB,kBAAkB,EAElB,uBAAuB,EAEvB,sBAAsB,GACvB,MAAM,WAAW,CAAC;AAEnB,8EAA8E;AAC9E,OAAO,EAEL,yBAAyB,EAEzB,wBAAwB,EAExB,qBAAqB,EAErB,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,8EAA8E;AAC9E,OAAO,EAEL,eAAe,EAEf,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,8EAA8E;AAC9E,OAAO,EAEL,uBAAuB,EAEvB,oBAAoB,EAEpB,wBAAwB,EAExB,oBAAoB,GACrB,MAAM,WAAW,CAAC;AAEnB,8EAA8E;AAC9E,OAAO,EAIL,oBAAoB,EACpB,wBAAwB,EACxB,uBAAuB,EAEvB,uBAAuB,GACxB,MAAM,cAAc,CAAC;AAEtB,8EAA8E;AAC9E,OAAO,EAEL,uBAAuB,EAEvB,sBAAsB,GACvB,MAAM,aAAa,CAAC;AAErB,8EAA8E;AAC9E,OAAO,EACL,2BAA2B,EAE3B,2BAA2B,EAE3B,iCAAiC,GAClC,MAAM,eAAe,CAAC;AAEvB,8EAA8E;AAC9E,OAAO,EAEL,4BAA4B,EAE5B,0BAA0B,EAE1B,mCAAmC,EAEnC,0BAA0B,EAE1B,uBAAuB,GACxB,MAAM,aAAa,CAAC","sourcesContent":["/**\n * community-schema — Shared Zod schemas + TypeScript types for the\n * Jansathi hyperlocal community feature (feed, posts, engagement,\n * social graph, groups, settings).\n *\n * Single source of truth consumed by reform-backend and every product\n * frontend. The schemas mirror MongoDB / Mongoose document shapes\n * 1:1 so the same Zod validation runs at the controller boundary on\n * the backend and in the form handlers on the client.\n *\n * Cascade-upward visibility semantics: a viewer whose feed level is L\n * sees posts at L and every BROADER level matching their area lineage.\n * See `./enums.ts#VISIBILITY_LEVEL_VALUES` for the level rank table.\n *\n * @module community-schema\n */\n\n// ─── Area lineage snapshot ─────────────────────────────────────────────────\nexport {\n type AreaLineageSnapshot,\n areaLineageSnapshotSchema,\n} from './area.js';\n\n// ─── Comment ───────────────────────────────────────────────────────────────\nexport {\n type CommunityCommentWire,\n communityCommentWireSchema,\n type CreateCommentBody,\n createCommentBodySchema,\n type UpdateCommentBody,\n updateCommentBodySchema,\n} from './comment.js';\n\n// ─── Constants ─────────────────────────────────────────────────────────────\nexport {\n COMMENT_MAX_BODY_CHARS,\n COMMENTS_PAGE_SIZE,\n EDIT_GRACE_WINDOW_MS,\n FEED_PAGE_SIZE,\n GROUP_MAX_MEMBERS,\n GROUP_NAME_MAX_CHARS,\n GROUP_NAME_MIN_CHARS,\n PEOPLE_PAGE_SIZE,\n POST_MAX_BODY_CHARS,\n POST_MAX_IMAGE_BYTES,\n POST_MAX_IMAGES,\n POST_MAX_VIDEO_BYTES,\n POST_MAX_VIDEO_SECONDS,\n POST_MAX_VIDEOS,\n PROFILE_MAX_BIO_CHARS,\n REPLIES_PRELOAD_COUNT,\n} from './constants.js';\n\n// ─── Engagement (upvote + reactions) ───────────────────────────────────────\nexport {\n type SetReactionBody,\n setReactionBodySchema,\n type SetReactionResponse,\n setReactionResponseSchema,\n type ToggleUpvoteResponse,\n toggleUpvoteResponseSchema,\n} from './engagement.js';\n\n// ─── Enums ─────────────────────────────────────────────────────────────────\nexport {\n CONNECTION_STATUS_VALUES,\n type ConnectionStatus,\n connectionStatusSchema,\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 type ReactionType,\n reactionTypeSchema,\n REPORT_REASON_VALUES,\n type ReportReason,\n reportReasonSchema,\n REPORT_STATUS_VALUES,\n type ReportStatus,\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 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 communityGroupWireSchema,\n type CreateGroupBody,\n createGroupBodySchema,\n type GroupRole,\n groupRoleSchema,\n} from './group.js';\n\n// ─── Media ─────────────────────────────────────────────────────────────────\nexport {\n type PostImage,\n postImageSchema,\n type PostVideo,\n postVideoSchema,\n} from './media.js';\n\n// ─── Post ──────────────────────────────────────────────────────────────────\nexport {\n type CommunityPostWire,\n communityPostWireSchema,\n type CreatePostBody,\n createPostBodySchema,\n type PostAuthorSnapshot,\n postAuthorSnapshotSchema,\n type UpdatePostBody,\n updatePostBodySchema,\n} from './post.js';\n\n// ─── Profile + People list ─────────────────────────────────────────────────\nexport {\n type PeopleListItem,\n type PeopleListResponse,\n type PeopleQueryParams,\n peopleListItemSchema,\n peopleListResponseSchema,\n peopleQueryParamsSchema,\n type PublicProfileWire,\n publicProfileWireSchema,\n} from './profile.js';\n\n// ─── Reports (moderation) ──────────────────────────────────────────────────\nexport {\n type ReportContentBody,\n reportContentBodySchema,\n type ReportRecordWire,\n reportRecordWireSchema,\n} from './report.js';\n\n// ─── Settings ──────────────────────────────────────────────────────────────\nexport {\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 connectionDecisionBodySchema,\n type ConnectionRecordWire,\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":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,8EAA8E;AAC9E,OAAO,EAEL,yBAAyB,GAC1B,MAAM,WAAW,CAAC;AAEnB,8EAA8E;AAC9E,OAAO,EAGL,0BAA0B,EAC1B,uBAAuB,EAEvB,uBAAuB,GACxB,MAAM,cAAc,CAAC;AAEtB,8EAA8E;AAC9E,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,eAAe,EACf,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAExB,8EAA8E;AAC9E,OAAO,EAGL,qBAAqB,EACrB,yBAAyB,EAEzB,0BAA0B,GAC3B,MAAM,iBAAiB,CAAC;AAEzB,8EAA8E;AAC9E,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EAGnB,sBAAsB,EACtB,iBAAiB,EACjB,gBAAgB,EAEhB,cAAc,EACd,sBAAsB,EAEtB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EAIpB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,uBAAuB,EAEvB,qBAAqB,GACtB,MAAM,YAAY,CAAC;AAEpB,8EAA8E;AAC9E,OAAO,EAIL,cAAc,EACd,qBAAqB,EACrB,kBAAkB,EAElB,uBAAuB,EAEvB,sBAAsB,GACvB,MAAM,WAAW,CAAC;AAEnB,8EAA8E;AAC9E,OAAO,EAEL,yBAAyB,EAGzB,wBAAwB,EACxB,+BAA+B,EAE/B,qBAAqB,EAGrB,qBAAqB,EACrB,8BAA8B,EAE9B,eAAe,EAEf,wBAAwB,EAExB,qBAAqB,GACtB,MAAM,YAAY,CAAC;AAEpB,8EAA8E;AAC9E,OAAO,EAGL,eAAe,EACf,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,8EAA8E;AAC9E,OAAO,EAGL,uBAAuB,EACvB,oBAAoB,EAEpB,wBAAwB,EAExB,oBAAoB,GACrB,MAAM,WAAW,CAAC;AAEnB,8EAA8E;AAC9E,OAAO,EAKL,oBAAoB,EACpB,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,cAAc,CAAC;AAEtB,8EAA8E;AAC9E,OAAO,EAML,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,8BAA8B,EAC9B,oBAAoB,GACrB,MAAM,aAAa,CAAC;AAErB,8EAA8E;AAC9E,OAAO,EAGL,qBAAqB,EACrB,8BAA8B,EAC9B,2BAA2B,EAE3B,2BAA2B,EAE3B,iCAAiC,GAClC,MAAM,eAAe,CAAC;AAEvB,8EAA8E;AAC9E,OAAO,EAGL,4BAA4B,EAC5B,0BAA0B,EAE1B,mCAAmC,EAEnC,0BAA0B,EAE1B,uBAAuB,GACxB,MAAM,aAAa,CAAC","sourcesContent":["/**\n * community-schema — Shared Zod schemas + TypeScript types for the\n * Jansathi hyperlocal community feature (feed, posts, engagement,\n * social graph, groups, settings).\n *\n * Single source of truth consumed by reform-backend and every product\n * frontend. The schemas mirror MongoDB / Mongoose document shapes\n * 1:1 so the same Zod validation runs at the controller boundary on\n * the backend and in the form handlers on the client.\n *\n * Cascade-upward visibility semantics: a viewer whose feed level is L\n * sees posts at L and every BROADER level matching their area lineage.\n * See `./enums.ts#VISIBILITY_LEVEL_VALUES` for the level rank table.\n *\n * @module community-schema\n */\n\n// ─── Area lineage snapshot ─────────────────────────────────────────────────\nexport {\n type AreaLineageSnapshot,\n areaLineageSnapshotSchema,\n} from './area.js';\n\n// ─── Comment ───────────────────────────────────────────────────────────────\nexport {\n type CommunityCommentWire,\n type CreateCommentBody,\n communityCommentWireSchema,\n createCommentBodySchema,\n type UpdateCommentBody,\n updateCommentBodySchema,\n} from './comment.js';\n\n// ─── Constants ─────────────────────────────────────────────────────────────\nexport {\n COMMENT_MAX_BODY_CHARS,\n COMMENTS_PAGE_SIZE,\n EDIT_GRACE_WINDOW_MS,\n FEED_PAGE_SIZE,\n GROUP_MAX_MEMBERS,\n GROUP_NAME_MAX_CHARS,\n GROUP_NAME_MIN_CHARS,\n PEOPLE_PAGE_SIZE,\n POST_MAX_BODY_CHARS,\n POST_MAX_IMAGE_BYTES,\n POST_MAX_IMAGES,\n POST_MAX_VIDEO_BYTES,\n POST_MAX_VIDEO_SECONDS,\n POST_MAX_VIDEOS,\n PROFILE_MAX_BIO_CHARS,\n REPLIES_PRELOAD_COUNT,\n} from './constants.js';\n\n// ─── Engagement (upvote + reactions) ───────────────────────────────────────\nexport {\n type SetReactionBody,\n type SetReactionResponse,\n setReactionBodySchema,\n setReactionResponseSchema,\n type ToggleUpvoteResponse,\n toggleUpvoteResponseSchema,\n} from './engagement.js';\n\n// ─── Enums ─────────────────────────────────────────────────────────────────\nexport {\n CONNECTION_STATUS_VALUES,\n CONTENT_KIND_VALUES,\n type ConnectionStatus,\n type ContentKind,\n connectionStatusSchema,\n contentKindSchema,\n FEED_SORT_VALUES,\n type FeedSort,\n feedSortSchema,\n PROFILE_PRIVACY_VALUES,\n type ProfilePrivacy,\n profilePrivacySchema,\n REACTION_TYPE_VALUES,\n REPORT_REASON_VALUES,\n REPORT_STATUS_VALUES,\n type ReactionType,\n type ReportReason,\n type ReportStatus,\n reactionTypeSchema,\n reportReasonSchema,\n reportStatusSchema,\n VISIBILITY_LEVEL_RANK,\n VISIBILITY_LEVEL_VALUES,\n type VisibilityLevel,\n visibilityLevelSchema,\n} from './enums.js';\n\n// ─── Feed (polymorphic union) ──────────────────────────────────────────────\nexport {\n type 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 communityGroupWireSchema,\n communityGroupWithMembersSchema,\n type CreateGroupBody,\n createGroupBodySchema,\n type GroupMemberWire,\n type GroupMembersListResponse,\n groupMemberWireSchema,\n groupMembersListResponseSchema,\n type GroupRole,\n groupRoleSchema,\n type GroupsListResponse,\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 UpdatePostBody,\n updatePostBodySchema,\n} from './post.js';\n\n// ─── Profile + People list ─────────────────────────────────────────────────\nexport {\n type PeopleListItem,\n type PeopleListResponse,\n type PeopleQueryParams,\n type PublicProfileWire,\n peopleListItemSchema,\n peopleListResponseSchema,\n peopleQueryParamsSchema,\n publicProfileWireSchema,\n} from './profile.js';\n\n// ─── Reports (moderation) ──────────────────────────────────────────────────\nexport {\n type ReportContentBody,\n type ReportContentKind,\n type ReportRecordWire,\n type ReportSubmissionResponse,\n type ReportUserBody,\n reportContentBodySchema,\n reportContentKindSchema,\n reportRecordWireSchema,\n reportSubmissionResponseSchema,\n reportUserBodySchema,\n} from './report.js';\n\n// ─── Settings ──────────────────────────────────────────────────────────────\nexport {\n type BlockedUserWire,\n type BlockedUsersListResponse,\n blockedUserWireSchema,\n blockedUsersListResponseSchema,\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 +1 @@
1
- {"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../src/media.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB;;;;;;GAMG;AACH,eAAO,MAAM,eAAe;;;;;;;iBAS1B,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD;;;;;;GAMG;AACH,eAAO,MAAM,eAAe;;;;;;;iBAQ1B,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC"}
1
+ {"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../src/media.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;GAMG;AACH,eAAO,MAAM,eAAe;;;;;;;iBAS1B,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD;;;;;;GAMG;AACH,eAAO,MAAM,eAAe;;;;;;;iBAQ1B,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC"}
package/dist/media.js CHANGED
@@ -13,7 +13,7 @@
13
13
  * @module community-schema/media
14
14
  */
15
15
  import { z } from 'zod';
16
- import { POST_MAX_IMAGE_BYTES, POST_MAX_VIDEO_BYTES, POST_MAX_VIDEO_SECONDS, } from './constants.js';
16
+ import { POST_MAX_IMAGE_BYTES, POST_MAX_VIDEO_BYTES, POST_MAX_VIDEO_SECONDS } from './constants.js';
17
17
  /**
18
18
  * An image attached to a community post.
19
19
  *
package/dist/media.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"media.js","sourceRoot":"","sources":["../src/media.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;AAExB;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IACrB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACzC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAClC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACnC,oEAAoE;IACpE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,oBAAoB,CAAC;IAC5D,mEAAmE;IACnE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;CACpC,CAAC,CAAC;AAGH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IACrB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IAC9B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAClC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACnC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,oBAAoB,CAAC;IAC5D,qEAAqE;IACrE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,sBAAsB,CAAC;CAC5D,CAAC,CAAC","sourcesContent":["/**\n * Media-asset wire shapes for community posts.\n *\n * Uploads land in the shared file service (same GCS bucket the rest of\n * Jansathi uses) and the result — a signed URL + thumbnail + a small\n * set of metadata — is what the post-create endpoint accepts.\n *\n * Why the wire shape carries width/height/duration: feed cards need\n * those to size the preview without loading the full asset (avoids\n * layout shift). Thumbnails are server-generated for videos and\n * server-compressed-variants for images.\n *\n * @module community-schema/media\n */\n\nimport { z } from 'zod';\nimport {\n POST_MAX_IMAGE_BYTES,\n POST_MAX_VIDEO_BYTES,\n POST_MAX_VIDEO_SECONDS,\n} from './constants.js';\n\n/**\n * An image attached to a community post.\n *\n * `width` / `height` are reported by the upload pipeline (sharp on the\n * backend or Image-API on the client) so the feed card can render an\n * intrinsic-size box and avoid CLS.\n */\nexport const postImageSchema = z.object({\n url: z.string().url(),\n thumbnailUrl: z.string().url().optional(),\n width: z.number().int().positive(),\n height: z.number().int().positive(),\n /** Original byte size at upload time. The pipeline rejects >cap. */\n bytes: z.number().int().positive().max(POST_MAX_IMAGE_BYTES),\n /** Author-supplied alt text. Optional but recommended for a11y. */\n alt: z.string().max(280).optional(),\n});\nexport type PostImage = z.infer<typeof postImageSchema>;\n\n/**\n * A video attached to a community post.\n *\n * Required `duration` is enforced at upload time so we never have to\n * probe the asset in the feed query. `thumbnailUrl` is a poster frame\n * extracted on the backend.\n */\nexport const postVideoSchema = z.object({\n url: z.string().url(),\n thumbnailUrl: z.string().url(),\n width: z.number().int().positive(),\n height: z.number().int().positive(),\n bytes: z.number().int().positive().max(POST_MAX_VIDEO_BYTES),\n /** Duration in seconds. Hard-capped per `POST_MAX_VIDEO_SECONDS`. */\n duration: z.number().positive().max(POST_MAX_VIDEO_SECONDS),\n});\nexport type PostVideo = z.infer<typeof postVideoSchema>;\n"]}
1
+ {"version":3,"file":"media.js","sourceRoot":"","sources":["../src/media.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAEpG;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IACrB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACzC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAClC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACnC,oEAAoE;IACpE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,oBAAoB,CAAC;IAC5D,mEAAmE;IACnE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;CACpC,CAAC,CAAC;AAGH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IACrB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IAC9B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAClC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACnC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,oBAAoB,CAAC;IAC5D,qEAAqE;IACrE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,sBAAsB,CAAC;CAC5D,CAAC,CAAC","sourcesContent":["/**\n * Media-asset wire shapes for community posts.\n *\n * Uploads land in the shared file service (same GCS bucket the rest of\n * Jansathi uses) and the result — a signed URL + thumbnail + a small\n * set of metadata — is what the post-create endpoint accepts.\n *\n * Why the wire shape carries width/height/duration: feed cards need\n * those to size the preview without loading the full asset (avoids\n * layout shift). Thumbnails are server-generated for videos and\n * server-compressed-variants for images.\n *\n * @module community-schema/media\n */\n\nimport { z } from 'zod';\nimport { POST_MAX_IMAGE_BYTES, POST_MAX_VIDEO_BYTES, POST_MAX_VIDEO_SECONDS } from './constants.js';\n\n/**\n * An image attached to a community post.\n *\n * `width` / `height` are reported by the upload pipeline (sharp on the\n * backend or Image-API on the client) so the feed card can render an\n * intrinsic-size box and avoid CLS.\n */\nexport const postImageSchema = z.object({\n url: z.string().url(),\n thumbnailUrl: z.string().url().optional(),\n width: z.number().int().positive(),\n height: z.number().int().positive(),\n /** Original byte size at upload time. The pipeline rejects >cap. */\n bytes: z.number().int().positive().max(POST_MAX_IMAGE_BYTES),\n /** Author-supplied alt text. Optional but recommended for a11y. */\n alt: z.string().max(280).optional(),\n});\nexport type PostImage = z.infer<typeof postImageSchema>;\n\n/**\n * A video attached to a community post.\n *\n * Required `duration` is enforced at upload time so we never have to\n * probe the asset in the feed query. `thumbnailUrl` is a poster frame\n * extracted on the backend.\n */\nexport const postVideoSchema = z.object({\n url: z.string().url(),\n thumbnailUrl: z.string().url(),\n width: z.number().int().positive(),\n height: z.number().int().positive(),\n bytes: z.number().int().positive().max(POST_MAX_VIDEO_BYTES),\n /** Duration in seconds. Hard-capped per `POST_MAX_VIDEO_SECONDS`. */\n duration: z.number().positive().max(POST_MAX_VIDEO_SECONDS),\n});\nexport type PostVideo = z.infer<typeof postVideoSchema>;\n"]}
@@ -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;AAYxB;;;;;;;;;GASG;AACH,eAAO,MAAM,wBAAwB;;;;;iBAWnC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAI1E;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuClC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAIxE;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;iBAM/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;;;GAIG;AACH,eAAO,MAAM,oBAAoB;;iBAE/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
1
+ {"version":3,"file":"post.d.ts","sourceRoot":"","sources":["../src/post.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAQxB;;;;;;;;;GASG;AACH,eAAO,MAAM,wBAAwB;;;;;iBAWnC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAI1E;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuClC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAIxE;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;iBAM/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;;;GAIG;AACH,eAAO,MAAM,oBAAoB;;iBAE/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
package/dist/post.js CHANGED
@@ -10,9 +10,9 @@
10
10
  */
11
11
  import { z } from 'zod';
12
12
  import { areaLineageSnapshotSchema } from './area.js';
13
- import { POST_MAX_BODY_CHARS, POST_MAX_IMAGES, POST_MAX_VIDEOS, } from './constants.js';
14
- import { postImageSchema, postVideoSchema } from './media.js';
13
+ import { POST_MAX_BODY_CHARS, POST_MAX_IMAGES, POST_MAX_VIDEOS } from './constants.js';
15
14
  import { visibilityLevelSchema } from './enums.js';
15
+ import { postImageSchema, postVideoSchema } from './media.js';
16
16
  // ─── Author snapshot (denormalised on every post) ──────────────────────────
17
17
  /**
18
18
  * The author's display info captured at post time. Denormalising
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 {\n POST_MAX_BODY_CHARS,\n POST_MAX_IMAGES,\n POST_MAX_VIDEOS,\n} from './constants.js';\nimport { postImageSchema, postVideoSchema } from './media.js';\nimport { visibilityLevelSchema } from './enums.js';\n\n// ─── Author snapshot (denormalised on every post) ──────────────────────────\n\n/**\n * The author's display info captured at post time. Denormalising\n * `displayName` / `avatarUrl` / `localName` here avoids a $lookup\n * against the User collection on every feed read — feed scans 20–40\n * posts per page and population would be a hot path.\n *\n * The User document remains the source of truth; a background job\n * (or a hook on User.findOneAndUpdate) refreshes recent posts when\n * a user changes their display name or avatar.\n */\nexport const postAuthorSnapshotSchema = z.object({\n userId: z.string(),\n displayName: z.string(),\n avatarUrl: z.string().url().optional(),\n /**\n * The author's \"local\" area label at post time, e.g. \"Rohini Sector 15\".\n * Powers the byline \"<DisplayName> · <localName> · <relativeTime>\".\n * Hidden when the author has a private profile and the viewer is\n * not an accepted Connection.\n */\n localName: z.string().optional(),\n});\nexport type PostAuthorSnapshot = z.infer<typeof postAuthorSnapshotSchema>;\n\n// ─── Wire shape — what the server returns ──────────────────────────────────\n\n/**\n * A community post as it appears in the feed and on the single-post\n * page. Engagement counts are denormalised onto the document for\n * fast feed sorting; the per-user reaction state (\"did I upvote this?\")\n * is computed at read time and returned in the `viewer` block.\n */\nexport const communityPostWireSchema = z.object({\n _id: z.string(),\n contentKind: z.literal('post'),\n author: postAuthorSnapshotSchema,\n\n // Body\n text: z.string().max(POST_MAX_BODY_CHARS),\n images: z.array(postImageSchema).max(POST_MAX_IMAGES),\n videos: z.array(postVideoSchema).max(POST_MAX_VIDEOS),\n\n // Audience\n visibilityLevel: visibilityLevelSchema,\n areaLineage: areaLineageSnapshotSchema,\n\n // Denormalised engagement counters (drive feed sort + card render)\n upvoteCount: z.number().int().nonnegative(),\n commentCount: z.number().int().nonnegative(),\n /** Map of `ReactionType` → count, e.g. { like: 4, love: 1 }. */\n reactionCounts: z.record(z.string(), z.number().int().nonnegative()),\n\n // Lifecycle\n createdAt: z.string().datetime(),\n /** Last edit timestamp, or null if never edited. Edit window is\n * enforced by the server at write time, not by this schema. */\n editedAt: z.string().datetime().nullable(),\n deletedAt: z.string().datetime().nullable(),\n\n // Per-viewer state (filled by the server at read time)\n viewer: z\n .object({\n upvoted: z.boolean(),\n /** The reaction the viewer chose, or null. Mutually exclusive\n * with `upvoted` is intentionally NOT enforced — they're two\n * separate axes per the product decision. */\n reaction: z.string().nullable(),\n /** True when the viewer authored the post (controls edit / delete buttons). */\n isAuthor: z.boolean(),\n })\n .optional(),\n});\nexport type CommunityPostWire = z.infer<typeof communityPostWireSchema>;\n\n// ─── Create / update bodies ────────────────────────────────────────────────\n\n/**\n * What the client sends to `POST /api/v1/community/posts`. The author\n * is taken from the authenticated request; visibility area is resolved\n * server-side from the user's primary area lineage (the client cannot\n * spoof a different area).\n */\nexport const createPostBodySchema = z.object({\n text: z.string().min(1).max(POST_MAX_BODY_CHARS),\n images: z.array(postImageSchema).max(POST_MAX_IMAGES).optional(),\n videos: z.array(postVideoSchema).max(POST_MAX_VIDEOS).optional(),\n /** Default chosen by the client is `local`; the server still validates. */\n visibilityLevel: visibilityLevelSchema,\n});\nexport type CreatePostBody = z.infer<typeof createPostBodySchema>;\n\n/**\n * What the client sends to `PATCH /api/v1/community/posts/:id`. Only\n * the text body is editable — media additions / removals require a new\n * post (matches Twitter / FB convention).\n */\nexport const updatePostBodySchema = z.object({\n text: z.string().min(1).max(POST_MAX_BODY_CHARS),\n});\nexport type UpdatePostBody = z.infer<typeof updatePostBodySchema>;\n"]}
1
+ {"version":3,"file":"post.js","sourceRoot":"","sources":["../src/post.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Community post wire shapes.\n *\n * A \"post\" is the native community content kind (text-primary + media).\n * Lost-and-found and voice-box items show up in the same feed via\n * polymorphic union; their shapes live in their own schema packages\n * and are projected into a `FeedItem` envelope (see `./feed.ts`).\n *\n * @module community-schema/post\n */\n\nimport { z } from 'zod';\nimport { areaLineageSnapshotSchema } from './area.js';\nimport { POST_MAX_BODY_CHARS, POST_MAX_IMAGES, POST_MAX_VIDEOS } from './constants.js';\nimport { visibilityLevelSchema } from './enums.js';\nimport { postImageSchema, postVideoSchema } from './media.js';\n\n// ─── Author snapshot (denormalised on every post) ──────────────────────────\n\n/**\n * The author's display info captured at post time. Denormalising\n * `displayName` / `avatarUrl` / `localName` here avoids a $lookup\n * against the User collection on every feed read — feed scans 20–40\n * posts per page and population would be a hot path.\n *\n * The User document remains the source of truth; a background job\n * (or a hook on User.findOneAndUpdate) refreshes recent posts when\n * a user changes their display name or avatar.\n */\nexport const postAuthorSnapshotSchema = z.object({\n userId: z.string(),\n displayName: z.string(),\n avatarUrl: z.string().url().optional(),\n /**\n * The author's \"local\" area label at post time, e.g. \"Rohini Sector 15\".\n * Powers the byline \"<DisplayName> · <localName> · <relativeTime>\".\n * Hidden when the author has a private profile and the viewer is\n * not an accepted Connection.\n */\n localName: z.string().optional(),\n});\nexport type PostAuthorSnapshot = z.infer<typeof postAuthorSnapshotSchema>;\n\n// ─── Wire shape — what the server returns ──────────────────────────────────\n\n/**\n * A community post as it appears in the feed and on the single-post\n * page. Engagement counts are denormalised onto the document for\n * fast feed sorting; the per-user reaction state (\"did I upvote this?\")\n * is computed at read time and returned in the `viewer` block.\n */\nexport const communityPostWireSchema = z.object({\n _id: z.string(),\n contentKind: z.literal('post'),\n author: postAuthorSnapshotSchema,\n\n // Body\n text: z.string().max(POST_MAX_BODY_CHARS),\n images: z.array(postImageSchema).max(POST_MAX_IMAGES),\n videos: z.array(postVideoSchema).max(POST_MAX_VIDEOS),\n\n // Audience\n visibilityLevel: visibilityLevelSchema,\n areaLineage: areaLineageSnapshotSchema,\n\n // Denormalised engagement counters (drive feed sort + card render)\n upvoteCount: z.number().int().nonnegative(),\n commentCount: z.number().int().nonnegative(),\n /** Map of `ReactionType` → count, e.g. { like: 4, love: 1 }. */\n reactionCounts: z.record(z.string(), z.number().int().nonnegative()),\n\n // Lifecycle\n createdAt: z.string().datetime(),\n /** Last edit timestamp, or null if never edited. Edit window is\n * enforced by the server at write time, not by this schema. */\n editedAt: z.string().datetime().nullable(),\n deletedAt: z.string().datetime().nullable(),\n\n // Per-viewer state (filled by the server at read time)\n viewer: z\n .object({\n upvoted: z.boolean(),\n /** The reaction the viewer chose, or null. Mutually exclusive\n * with `upvoted` is intentionally NOT enforced — they're two\n * separate axes per the product decision. */\n reaction: z.string().nullable(),\n /** True when the viewer authored the post (controls edit / delete buttons). */\n isAuthor: z.boolean(),\n })\n .optional(),\n});\nexport type CommunityPostWire = z.infer<typeof communityPostWireSchema>;\n\n// ─── Create / update bodies ────────────────────────────────────────────────\n\n/**\n * What the client sends to `POST /api/v1/community/posts`. The author\n * is taken from the authenticated request; visibility area is resolved\n * server-side from the user's primary area lineage (the client cannot\n * spoof a different area).\n */\nexport const createPostBodySchema = z.object({\n text: z.string().min(1).max(POST_MAX_BODY_CHARS),\n images: z.array(postImageSchema).max(POST_MAX_IMAGES).optional(),\n videos: z.array(postVideoSchema).max(POST_MAX_VIDEOS).optional(),\n /** Default chosen by the client is `local`; the server still validates. */\n visibilityLevel: visibilityLevelSchema,\n});\nexport type CreatePostBody = z.infer<typeof createPostBodySchema>;\n\n/**\n * What the client sends to `PATCH /api/v1/community/posts/:id`. Only\n * the text body is editable — media additions / removals require a new\n * post (matches Twitter / FB convention).\n */\nexport const updatePostBodySchema = z.object({\n text: z.string().min(1).max(POST_MAX_BODY_CHARS),\n});\nexport type UpdatePostBody = z.infer<typeof updatePostBodySchema>;\n"]}
package/dist/report.d.ts CHANGED
@@ -1,19 +1,48 @@
1
1
  /**
2
- * Content-reporting wire shapes for moderation.
2
+ * Content + user reporting wire shapes for moderation.
3
3
  *
4
- * Any signed-in viewer can report any piece of community content
5
- * (post / lost-found / voice-box / comment). Reports land in a
6
- * moderation queue surfaced to admins; admin actions are out of scope
7
- * for this schema package the admin endpoints live elsewhere.
4
+ * Any signed-in viewer can report:
5
+ * - feed content (post / lost-found / voice-box)
6
+ * - comments (one-level thread under a feed item)
7
+ * - users (the profile + everything they author)
8
+ *
9
+ * Reports land in a moderation queue surfaced to admins; admin actions
10
+ * are out of scope for this schema package.
11
+ *
12
+ * Endpoints:
13
+ * POST /reports file a content report
14
+ * POST /reports/user file a user report
15
+ *
16
+ * Both return a `ReportSubmissionResponse` carrying the resulting
17
+ * record + a `created` flag so the UI can distinguish first-submission
18
+ * from idempotent repeat (and toast accordingly).
8
19
  *
9
20
  * @module community-schema/report
10
21
  */
11
22
  import { z } from 'zod';
23
+ /**
24
+ * The four kinds of community CONTENT that can be reported. Wider than
25
+ * `contentKindSchema` (which covers only feed items) because comments
26
+ * are also reportable. Lives here — not in `enums.ts` — to keep the
27
+ * feed/post schemas free of the comment value.
28
+ */
29
+ export declare const reportContentKindSchema: z.ZodEnum<{
30
+ post: "post";
31
+ lost_found: "lost_found";
32
+ voice_box: "voice_box";
33
+ comment: "comment";
34
+ }>;
35
+ export type ReportContentKind = z.infer<typeof reportContentKindSchema>;
36
+ /**
37
+ * Body for `POST /api/v1/community/reports`. Reports a piece of
38
+ * content (post / lost-found / voice-box / comment).
39
+ */
12
40
  export declare const reportContentBodySchema: z.ZodObject<{
13
41
  contentKind: z.ZodEnum<{
14
42
  post: "post";
15
43
  lost_found: "lost_found";
16
44
  voice_box: "voice_box";
45
+ comment: "comment";
17
46
  }>;
18
47
  contentId: z.ZodString;
19
48
  reason: z.ZodEnum<{
@@ -30,14 +59,45 @@ export declare const reportContentBodySchema: z.ZodObject<{
30
59
  details: z.ZodOptional<z.ZodString>;
31
60
  }, z.core.$strip>;
32
61
  export type ReportContentBody = z.infer<typeof reportContentBodySchema>;
62
+ /**
63
+ * Body for `POST /api/v1/community/reports/user`. Reports a user's
64
+ * profile / general behaviour rather than a specific piece of content.
65
+ */
66
+ export declare const reportUserBodySchema: z.ZodObject<{
67
+ targetUserId: z.ZodString;
68
+ reason: z.ZodEnum<{
69
+ spam: "spam";
70
+ harassment: "harassment";
71
+ hate_speech: "hate_speech";
72
+ misinformation: "misinformation";
73
+ sexual_content: "sexual_content";
74
+ violence: "violence";
75
+ self_harm: "self_harm";
76
+ illegal_content: "illegal_content";
77
+ other: "other";
78
+ }>;
79
+ details: z.ZodOptional<z.ZodString>;
80
+ }, z.core.$strip>;
81
+ export type ReportUserBody = z.infer<typeof reportUserBodySchema>;
82
+ /**
83
+ * Mongo-side record of a single report, projected for wire.
84
+ *
85
+ * For content reports `targetKind` is one of the content kinds and
86
+ * `contentId` holds the target; `targetUserId` is undefined. For user
87
+ * reports `targetKind === 'user'`, `targetUserId` is set, and
88
+ * `contentId` is an empty string (no content target).
89
+ */
33
90
  export declare const reportRecordWireSchema: z.ZodObject<{
34
91
  _id: z.ZodString;
35
- contentKind: z.ZodEnum<{
92
+ targetKind: z.ZodEnum<{
36
93
  post: "post";
37
94
  lost_found: "lost_found";
38
95
  voice_box: "voice_box";
96
+ comment: "comment";
97
+ user: "user";
39
98
  }>;
40
99
  contentId: z.ZodString;
100
+ targetUserId: z.ZodOptional<z.ZodString>;
41
101
  reason: z.ZodEnum<{
42
102
  spam: "spam";
43
103
  harassment: "harassment";
@@ -59,4 +119,46 @@ export declare const reportRecordWireSchema: z.ZodObject<{
59
119
  createdAt: z.ZodString;
60
120
  }, z.core.$strip>;
61
121
  export type ReportRecordWire = z.infer<typeof reportRecordWireSchema>;
122
+ /**
123
+ * Common response envelope for both `POST /reports` and
124
+ * `POST /reports/user`. `created` is `true` on first submission and
125
+ * `false` when the backend's idempotency check returned an existing
126
+ * row — the client uses this to distinguish "thanks for reporting"
127
+ * from "you've already reported this".
128
+ */
129
+ export declare const reportSubmissionResponseSchema: z.ZodObject<{
130
+ record: z.ZodObject<{
131
+ _id: z.ZodString;
132
+ targetKind: z.ZodEnum<{
133
+ post: "post";
134
+ lost_found: "lost_found";
135
+ voice_box: "voice_box";
136
+ comment: "comment";
137
+ user: "user";
138
+ }>;
139
+ contentId: z.ZodString;
140
+ targetUserId: z.ZodOptional<z.ZodString>;
141
+ reason: z.ZodEnum<{
142
+ spam: "spam";
143
+ harassment: "harassment";
144
+ hate_speech: "hate_speech";
145
+ misinformation: "misinformation";
146
+ sexual_content: "sexual_content";
147
+ violence: "violence";
148
+ self_harm: "self_harm";
149
+ illegal_content: "illegal_content";
150
+ other: "other";
151
+ }>;
152
+ details: z.ZodNullable<z.ZodString>;
153
+ status: z.ZodEnum<{
154
+ pending: "pending";
155
+ reviewing: "reviewing";
156
+ actioned: "actioned";
157
+ dismissed: "dismissed";
158
+ }>;
159
+ createdAt: z.ZodString;
160
+ }, z.core.$strip>;
161
+ created: z.ZodBoolean;
162
+ }, z.core.$strip>;
163
+ export type ReportSubmissionResponse = z.infer<typeof reportSubmissionResponseSchema>;
62
164
  //# sourceMappingURL=report.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;iBAOlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAQjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB;;;;;EAAyD,CAAC;AAC9F,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAIxE;;;GAGG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;iBASlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE;;;GAGG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;iBAI/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAIlE;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBASjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE;;;;;;GAMG;AACH,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAGzC,CAAC;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC"}
package/dist/report.js CHANGED
@@ -1,30 +1,85 @@
1
1
  /**
2
- * Content-reporting wire shapes for moderation.
2
+ * Content + user reporting wire shapes for moderation.
3
3
  *
4
- * Any signed-in viewer can report any piece of community content
5
- * (post / lost-found / voice-box / comment). Reports land in a
6
- * moderation queue surfaced to admins; admin actions are out of scope
7
- * for this schema package the admin endpoints live elsewhere.
4
+ * Any signed-in viewer can report:
5
+ * - feed content (post / lost-found / voice-box)
6
+ * - comments (one-level thread under a feed item)
7
+ * - users (the profile + everything they author)
8
+ *
9
+ * Reports land in a moderation queue surfaced to admins; admin actions
10
+ * are out of scope for this schema package.
11
+ *
12
+ * Endpoints:
13
+ * POST /reports file a content report
14
+ * POST /reports/user file a user report
15
+ *
16
+ * Both return a `ReportSubmissionResponse` carrying the resulting
17
+ * record + a `created` flag so the UI can distinguish first-submission
18
+ * from idempotent repeat (and toast accordingly).
8
19
  *
9
20
  * @module community-schema/report
10
21
  */
11
22
  import { z } from 'zod';
12
- import { contentKindSchema, reportReasonSchema, reportStatusSchema } from './enums.js';
23
+ import { reportReasonSchema, reportStatusSchema } from './enums.js';
24
+ /**
25
+ * The four kinds of community CONTENT that can be reported. Wider than
26
+ * `contentKindSchema` (which covers only feed items) because comments
27
+ * are also reportable. Lives here — not in `enums.ts` — to keep the
28
+ * feed/post schemas free of the comment value.
29
+ */
30
+ export const reportContentKindSchema = z.enum(['post', 'lost_found', 'voice_box', 'comment']);
31
+ // ─── Body shapes ───────────────────────────────────────────────────────────
32
+ /**
33
+ * Body for `POST /api/v1/community/reports`. Reports a piece of
34
+ * content (post / lost-found / voice-box / comment).
35
+ */
13
36
  export const reportContentBodySchema = z.object({
14
- contentKind: contentKindSchema,
37
+ /** Still named `contentKind` for backward compat with 0.1.x callers;
38
+ * semantically it now also includes 'comment'. */
39
+ contentKind: reportContentKindSchema,
15
40
  contentId: z.string(),
16
41
  reason: reportReasonSchema,
17
42
  /** Free-text detail. Required when `reason === 'other'`, optional
18
- * otherwise (the server enforces the conditional via refine). */
43
+ * otherwise (the server enforces the conditional). */
44
+ details: z.string().max(2000).optional(),
45
+ });
46
+ /**
47
+ * Body for `POST /api/v1/community/reports/user`. Reports a user's
48
+ * profile / general behaviour rather than a specific piece of content.
49
+ */
50
+ export const reportUserBodySchema = z.object({
51
+ targetUserId: z.string(),
52
+ reason: reportReasonSchema,
19
53
  details: z.string().max(2000).optional(),
20
54
  });
55
+ // ─── Record + response shapes ──────────────────────────────────────────────
56
+ /**
57
+ * Mongo-side record of a single report, projected for wire.
58
+ *
59
+ * For content reports `targetKind` is one of the content kinds and
60
+ * `contentId` holds the target; `targetUserId` is undefined. For user
61
+ * reports `targetKind === 'user'`, `targetUserId` is set, and
62
+ * `contentId` is an empty string (no content target).
63
+ */
21
64
  export const reportRecordWireSchema = z.object({
22
65
  _id: z.string(),
23
- contentKind: contentKindSchema,
66
+ targetKind: z.enum(['post', 'lost_found', 'voice_box', 'comment', 'user']),
24
67
  contentId: z.string(),
68
+ targetUserId: z.string().optional(),
25
69
  reason: reportReasonSchema,
26
70
  details: z.string().nullable(),
27
71
  status: reportStatusSchema,
28
72
  createdAt: z.string().datetime(),
29
73
  });
74
+ /**
75
+ * Common response envelope for both `POST /reports` and
76
+ * `POST /reports/user`. `created` is `true` on first submission and
77
+ * `false` when the backend's idempotency check returned an existing
78
+ * row — the client uses this to distinguish "thanks for reporting"
79
+ * from "you've already reported this".
80
+ */
81
+ export const reportSubmissionResponseSchema = z.object({
82
+ record: reportRecordWireSchema,
83
+ created: z.boolean(),
84
+ });
30
85
  //# sourceMappingURL=report.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEvF,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,WAAW,EAAE,iBAAiB;IAC9B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,MAAM,EAAE,kBAAkB;IAC1B;sEACkE;IAClE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE;CACzC,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,WAAW,EAAE,iBAAiB;IAC9B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,MAAM,EAAE,kBAAkB;IAC1B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,MAAM,EAAE,kBAAkB;IAC1B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACjC,CAAC,CAAC","sourcesContent":["/**\n * Content-reporting wire shapes for moderation.\n *\n * Any signed-in viewer can report any piece of community content\n * (post / lost-found / voice-box / comment). Reports land in a\n * moderation queue surfaced to admins; admin actions are out of scope\n * for this schema package the admin endpoints live elsewhere.\n *\n * @module community-schema/report\n */\n\nimport { z } from 'zod';\nimport { contentKindSchema, reportReasonSchema, reportStatusSchema } from './enums.js';\n\nexport const reportContentBodySchema = z.object({\n contentKind: contentKindSchema,\n contentId: z.string(),\n reason: reportReasonSchema,\n /** Free-text detail. Required when `reason === 'other'`, optional\n * otherwise (the server enforces the conditional via refine). */\n details: z.string().max(2000).optional(),\n});\nexport type ReportContentBody = z.infer<typeof reportContentBodySchema>;\n\nexport const reportRecordWireSchema = z.object({\n _id: z.string(),\n contentKind: contentKindSchema,\n contentId: z.string(),\n reason: reportReasonSchema,\n details: z.string().nullable(),\n status: reportStatusSchema,\n createdAt: z.string().datetime(),\n});\nexport type ReportRecordWire = z.infer<typeof reportRecordWireSchema>;\n"]}
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEpE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC;AAG9F,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C;uDACmD;IACnD,WAAW,EAAE,uBAAuB;IACpC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,MAAM,EAAE,kBAAkB;IAC1B;2DACuD;IACvD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE;CACzC,CAAC,CAAC;AAGH;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;IACxB,MAAM,EAAE,kBAAkB;IAC1B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE;CACzC,CAAC,CAAC;AAGH,8EAA8E;AAE9E;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IAC1E,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACnC,MAAM,EAAE,kBAAkB;IAC1B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,MAAM,EAAE,kBAAkB;IAC1B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACjC,CAAC,CAAC;AAGH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC,MAAM,CAAC;IACrD,MAAM,EAAE,sBAAsB;IAC9B,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;CACrB,CAAC,CAAC","sourcesContent":["/**\n * Content + user reporting wire shapes for moderation.\n *\n * Any signed-in viewer can report:\n * - feed content (post / lost-found / voice-box)\n * - comments (one-level thread under a feed item)\n * - users (the profile + everything they author)\n *\n * Reports land in a moderation queue surfaced to admins; admin actions\n * are out of scope for this schema package.\n *\n * Endpoints:\n * POST /reports file a content report\n * POST /reports/user file a user report\n *\n * Both return a `ReportSubmissionResponse` carrying the resulting\n * record + a `created` flag so the UI can distinguish first-submission\n * from idempotent repeat (and toast accordingly).\n *\n * @module community-schema/report\n */\n\nimport { z } from 'zod';\nimport { reportReasonSchema, reportStatusSchema } from './enums.js';\n\n/**\n * The four kinds of community CONTENT that can be reported. Wider than\n * `contentKindSchema` (which covers only feed items) because comments\n * are also reportable. Lives here — not in `enums.ts` — to keep the\n * feed/post schemas free of the comment value.\n */\nexport const reportContentKindSchema = z.enum(['post', 'lost_found', 'voice_box', 'comment']);\nexport type ReportContentKind = z.infer<typeof reportContentKindSchema>;\n\n// ─── Body shapes ───────────────────────────────────────────────────────────\n\n/**\n * Body for `POST /api/v1/community/reports`. Reports a piece of\n * content (post / lost-found / voice-box / comment).\n */\nexport const reportContentBodySchema = z.object({\n /** Still named `contentKind` for backward compat with 0.1.x callers;\n * semantically it now also includes 'comment'. */\n contentKind: reportContentKindSchema,\n contentId: z.string(),\n reason: reportReasonSchema,\n /** Free-text detail. Required when `reason === 'other'`, optional\n * otherwise (the server enforces the conditional). */\n details: z.string().max(2000).optional(),\n});\nexport type ReportContentBody = z.infer<typeof reportContentBodySchema>;\n\n/**\n * Body for `POST /api/v1/community/reports/user`. Reports a user's\n * profile / general behaviour rather than a specific piece of content.\n */\nexport const reportUserBodySchema = z.object({\n targetUserId: z.string(),\n reason: reportReasonSchema,\n details: z.string().max(2000).optional(),\n});\nexport type ReportUserBody = z.infer<typeof reportUserBodySchema>;\n\n// ─── Record + response shapes ──────────────────────────────────────────────\n\n/**\n * Mongo-side record of a single report, projected for wire.\n *\n * For content reports `targetKind` is one of the content kinds and\n * `contentId` holds the target; `targetUserId` is undefined. For user\n * reports `targetKind === 'user'`, `targetUserId` is set, and\n * `contentId` is an empty string (no content target).\n */\nexport const reportRecordWireSchema = z.object({\n _id: z.string(),\n targetKind: z.enum(['post', 'lost_found', 'voice_box', 'comment', 'user']),\n contentId: z.string(),\n targetUserId: z.string().optional(),\n reason: reportReasonSchema,\n details: z.string().nullable(),\n status: reportStatusSchema,\n createdAt: z.string().datetime(),\n});\nexport type ReportRecordWire = z.infer<typeof reportRecordWireSchema>;\n\n/**\n * Common response envelope for both `POST /reports` and\n * `POST /reports/user`. `created` is `true` on first submission and\n * `false` when the backend's idempotency check returned an existing\n * row — the client uses this to distinguish \"thanks for reporting\"\n * from \"you've already reported this\".\n */\nexport const reportSubmissionResponseSchema = z.object({\n record: reportRecordWireSchema,\n created: z.boolean(),\n});\nexport type ReportSubmissionResponse = z.infer<typeof reportSubmissionResponseSchema>;\n"]}
@@ -6,6 +6,12 @@
6
6
  * `PATCH /api/v1/community/settings`. Updates are partial — the client
7
7
  * sends only the fields it changes.
8
8
  *
9
+ * Block list management has dedicated routes (POST / DELETE
10
+ * `/settings/blocks/:userId`); only the COUNT is mirrored on the
11
+ * settings shape so the Settings page can show "N blocked users"
12
+ * without a second round-trip. The full list is read via
13
+ * `GET /settings/blocks`.
14
+ *
9
15
  * @module community-schema/settings
10
16
  */
11
17
  import { z } from 'zod';
@@ -21,6 +27,8 @@ export declare const communitySettingsWireSchema: z.ZodObject<{
21
27
  national: "national";
22
28
  global: "global";
23
29
  }>;
30
+ bio: z.ZodNullable<z.ZodString>;
31
+ blockedCount: z.ZodNumber;
24
32
  notifications: z.ZodObject<{
25
33
  onFollow: z.ZodBoolean;
26
34
  onConnectionRequest: z.ZodBoolean;
@@ -37,6 +45,10 @@ export type CommunitySettingsWire = z.infer<typeof communitySettingsWireSchema>;
37
45
  * PATCH body — every field optional. The server merges over the existing
38
46
  * settings. Notifications is a partial sub-shape so the client can
39
47
  * toggle one knob at a time.
48
+ *
49
+ * `bio` accepts `null` to clear; omit the key entirely to leave it
50
+ * unchanged. Block list is NOT included here — see the dedicated
51
+ * `/settings/blocks` routes.
40
52
  */
41
53
  export declare const updateCommunitySettingsBodySchema: z.ZodObject<{
42
54
  privacy: z.ZodOptional<z.ZodEnum<{
@@ -50,6 +62,7 @@ export declare const updateCommunitySettingsBodySchema: z.ZodObject<{
50
62
  national: "national";
51
63
  global: "global";
52
64
  }>>;
65
+ bio: z.ZodOptional<z.ZodNullable<z.ZodString>>;
53
66
  notifications: z.ZodOptional<z.ZodObject<{
54
67
  onFollow: z.ZodOptional<z.ZodBoolean>;
55
68
  onConnectionRequest: z.ZodOptional<z.ZodBoolean>;
@@ -62,5 +75,28 @@ export declare const updateCommunitySettingsBodySchema: z.ZodObject<{
62
75
  }, z.core.$strip>>;
63
76
  }, z.core.$strip>;
64
77
  export type UpdateCommunitySettingsBody = z.infer<typeof updateCommunitySettingsBodySchema>;
78
+ /**
79
+ * One row in `GET /settings/blocks`. Mirrors the PeopleListItem shape
80
+ * minus the per-viewer social state (the caller's viewer state w.r.t.
81
+ * a blocked user is always "blocked").
82
+ */
83
+ export declare const blockedUserWireSchema: z.ZodObject<{
84
+ userId: z.ZodString;
85
+ displayName: z.ZodString;
86
+ avatarUrl: z.ZodOptional<z.ZodString>;
87
+ localName: z.ZodOptional<z.ZodString>;
88
+ blockedAt: z.ZodString;
89
+ }, z.core.$strip>;
90
+ export type BlockedUserWire = z.infer<typeof blockedUserWireSchema>;
91
+ export declare const blockedUsersListResponseSchema: z.ZodObject<{
92
+ items: z.ZodArray<z.ZodObject<{
93
+ userId: z.ZodString;
94
+ displayName: z.ZodString;
95
+ avatarUrl: z.ZodOptional<z.ZodString>;
96
+ localName: z.ZodOptional<z.ZodString>;
97
+ blockedAt: z.ZodString;
98
+ }, z.core.$strip>>;
99
+ }, z.core.$strip>;
100
+ export type BlockedUsersListResponse = z.infer<typeof blockedUsersListResponseSchema>;
65
101
  export declare const COMMUNITY_SETTINGS_DEFAULTS: CommunitySettingsWire;
66
102
  //# sourceMappingURL=settings.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;iBAyBtC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF;;;;GAIG;AACH,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;;;;;;;;;;iBAe5C,CAAC;AACH,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAC/C,OAAO,iCAAiC,CACzC,CAAC;AAIF,eAAO,MAAM,2BAA2B,EAAE,qBAazC,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;;;;;;;;;;;;;;;;;;;;;;;;iBA8BtC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF;;;;;;;;GAQG;AACH,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;;;;;;;;;;;iBAgB5C,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,qBAezC,CAAC"}
package/dist/settings.js CHANGED
@@ -6,15 +6,27 @@
6
6
  * `PATCH /api/v1/community/settings`. Updates are partial — the client
7
7
  * sends only the fields it changes.
8
8
  *
9
+ * Block list management has dedicated routes (POST / DELETE
10
+ * `/settings/blocks/:userId`); only the COUNT is mirrored on the
11
+ * settings shape so the Settings page can show "N blocked users"
12
+ * without a second round-trip. The full list is read via
13
+ * `GET /settings/blocks`.
14
+ *
9
15
  * @module community-schema/settings
10
16
  */
11
17
  import { z } from 'zod';
18
+ import { PROFILE_MAX_BIO_CHARS } from './constants.js';
12
19
  import { profilePrivacySchema, visibilityLevelSchema } from './enums.js';
13
20
  export const communitySettingsWireSchema = z.object({
14
21
  /** Profile-level privacy toggle. */
15
22
  privacy: profilePrivacySchema,
16
23
  /** Default visibility level chosen in the post composer. */
17
24
  defaultPostVisibility: visibilityLevelSchema,
25
+ /** Free-text bio shown on the profile (nullable so the user can clear it). */
26
+ bio: z.string().max(PROFILE_MAX_BIO_CHARS).nullable(),
27
+ /** How many users the caller has blocked. The full list lives behind
28
+ * `GET /settings/blocks` to keep this hot read small. */
29
+ blockedCount: z.number().int().nonnegative(),
18
30
  /** Per-event notification toggles. The map is sparse: a missing key
19
31
  * means "use the default". */
20
32
  notifications: z.object({
@@ -40,10 +52,15 @@ export const communitySettingsWireSchema = z.object({
40
52
  * PATCH body — every field optional. The server merges over the existing
41
53
  * settings. Notifications is a partial sub-shape so the client can
42
54
  * toggle one knob at a time.
55
+ *
56
+ * `bio` accepts `null` to clear; omit the key entirely to leave it
57
+ * unchanged. Block list is NOT included here — see the dedicated
58
+ * `/settings/blocks` routes.
43
59
  */
44
60
  export const updateCommunitySettingsBodySchema = z.object({
45
61
  privacy: profilePrivacySchema.optional(),
46
62
  defaultPostVisibility: visibilityLevelSchema.optional(),
63
+ bio: z.string().max(PROFILE_MAX_BIO_CHARS).nullable().optional(),
47
64
  notifications: z
48
65
  .object({
49
66
  onFollow: z.boolean().optional(),
@@ -57,10 +74,28 @@ export const updateCommunitySettingsBodySchema = z.object({
57
74
  })
58
75
  .optional(),
59
76
  });
77
+ // ─── Blocked users list ────────────────────────────────────────────────────
78
+ /**
79
+ * One row in `GET /settings/blocks`. Mirrors the PeopleListItem shape
80
+ * minus the per-viewer social state (the caller's viewer state w.r.t.
81
+ * a blocked user is always "blocked").
82
+ */
83
+ export const blockedUserWireSchema = z.object({
84
+ userId: z.string(),
85
+ displayName: z.string(),
86
+ avatarUrl: z.string().url().optional(),
87
+ localName: z.string().optional(),
88
+ blockedAt: z.string().datetime(),
89
+ });
90
+ export const blockedUsersListResponseSchema = z.object({
91
+ items: z.array(blockedUserWireSchema),
92
+ });
60
93
  // ─── Defaults (used by the backend when a user has no settings doc yet) ────
61
94
  export const COMMUNITY_SETTINGS_DEFAULTS = {
62
95
  privacy: 'public',
63
96
  defaultPostVisibility: 'local',
97
+ bio: null,
98
+ blockedCount: 0,
64
99
  notifications: {
65
100
  onFollow: true,
66
101
  onConnectionRequest: true,
@@ -1 +1 @@
1
- {"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEzE,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC,MAAM,CAAC;IAClD,oCAAoC;IACpC,OAAO,EAAE,oBAAoB;IAC7B,4DAA4D;IAC5D,qBAAqB,EAAE,qBAAqB;IAC5C;mCAC+B;IAC/B,aAAa,EAAE,CAAC,CAAC,MAAM,CAAC;QACtB,yCAAyC;QACzC,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE;QACrB,4DAA4D;QAC5D,mBAAmB,EAAE,CAAC,CAAC,OAAO,EAAE;QAChC,4DAA4D;QAC5D,oBAAoB,EAAE,CAAC,CAAC,OAAO,EAAE;QACjC,2EAA2E;QAC3E,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE;QACtB,oDAAoD;QACpD,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;QACpB,iDAAiD;QACjD,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE;QACrB,mDAAmD;QACnD,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE;QACvB,0DAA0D;QAC1D,eAAe,EAAE,CAAC,CAAC,OAAO,EAAE;KAC7B,CAAC;CACH,CAAC,CAAC;AAGH;;;;GAIG;AACH,MAAM,CAAC,MAAM,iCAAiC,GAAG,CAAC,CAAC,MAAM,CAAC;IACxD,OAAO,EAAE,oBAAoB,CAAC,QAAQ,EAAE;IACxC,qBAAqB,EAAE,qBAAqB,CAAC,QAAQ,EAAE;IACvD,aAAa,EAAE,CAAC;SACb,MAAM,CAAC;QACN,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;QAChC,mBAAmB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;QAC3C,oBAAoB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;QAC5C,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;QACjC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;QAC/B,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;QAChC,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;QAClC,eAAe,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;KACxC,CAAC;SACD,QAAQ,EAAE;CACd,CAAC,CAAC;AAKH,8EAA8E;AAE9E,MAAM,CAAC,MAAM,2BAA2B,GAA0B;IAChE,OAAO,EAAE,QAAQ;IACjB,qBAAqB,EAAE,OAAO;IAC9B,aAAa,EAAE;QACb,QAAQ,EAAE,IAAI;QACd,mBAAmB,EAAE,IAAI;QACzB,oBAAoB,EAAE,IAAI;QAC1B,SAAS,EAAE,IAAI;QACf,OAAO,EAAE,IAAI;QACb,QAAQ,EAAE,KAAK;QACf,UAAU,EAAE,KAAK;QACjB,eAAe,EAAE,IAAI;KACtB;CACF,CAAC","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 * @module community-schema/settings\n */\n\nimport { z } from 'zod';\nimport { profilePrivacySchema, visibilityLevelSchema } from './enums.js';\n\nexport const communitySettingsWireSchema = z.object({\n /** Profile-level privacy toggle. */\n privacy: profilePrivacySchema,\n /** Default visibility level chosen in the post composer. */\n defaultPostVisibility: visibilityLevelSchema,\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 */\nexport const updateCommunitySettingsBodySchema = z.object({\n privacy: profilePrivacySchema.optional(),\n defaultPostVisibility: visibilityLevelSchema.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<\n typeof updateCommunitySettingsBodySchema\n>;\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 defaultPostVisibility: 'local',\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, visibilityLevelSchema } from './enums.js';\n\nexport const communitySettingsWireSchema = z.object({\n /** Profile-level privacy toggle. */\n privacy: profilePrivacySchema,\n /** Default visibility level chosen in the post composer. */\n defaultPostVisibility: visibilityLevelSchema,\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 defaultPostVisibility: visibilityLevelSchema.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 defaultPostVisibility: 'local',\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 +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;;;;;;;;;;;;iBAgBlC,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;;;;;;;;iBAK9C,CAAC;AACH,MAAM,MAAM,6BAA6B,GAAG,CAAC,CAAC,KAAK,CACjD,OAAO,mCAAmC,CAC3C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,4BAA4B;;;;;;;;iBAEvC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAC1C,OAAO,4BAA4B,CACpC,CAAC;AAEF,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;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB;;;;GAIG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;iBAgBlC,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;;;;;;;;iBAK9C,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 +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;CAC1D,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;CAC/B,CAAC,CAAC;AAKH;;;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;AAKH,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});\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});\nexport type SendConnectionRequestResponse = z.infer<\n typeof sendConnectionRequestResponseSchema\n>;\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<\n typeof connectionDecisionBodySchema\n>;\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;;;;;;;;;;;;;;;;;;;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;CAC1D,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;CAC/B,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});\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});\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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jansathi-community-schema",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Shared Zod schemas + TypeScript types for the Jansathi hyperlocal community feature (feed, posts, engagement, social graph, groups).",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",