founder-schema 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -0
- package/dist/access/capabilities.d.ts +34 -0
- package/dist/access/capabilities.d.ts.map +1 -0
- package/dist/access/capabilities.js +35 -0
- package/dist/access/capabilities.js.map +1 -0
- package/dist/access/permissions.d.ts +20 -1
- package/dist/access/permissions.d.ts.map +1 -1
- package/dist/access/permissions.js +4 -0
- package/dist/access/permissions.js.map +1 -1
- package/dist/core/errors.d.ts +39 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +63 -0
- package/dist/core/errors.js.map +1 -1
- package/dist/core/limits.d.ts +12 -0
- package/dist/core/limits.d.ts.map +1 -1
- package/dist/core/limits.js +13 -0
- package/dist/core/limits.js.map +1 -1
- package/dist/core/responses.d.ts +53 -0
- package/dist/core/responses.d.ts.map +1 -1
- package/dist/core/responses.js +7 -0
- package/dist/core/responses.js.map +1 -1
- package/dist/core/validation.d.ts +6 -0
- package/dist/core/validation.d.ts.map +1 -1
- package/dist/core/validation.js +6 -0
- package/dist/core/validation.js.map +1 -1
- package/dist/domains/audit/audit.d.ts +47 -3
- package/dist/domains/audit/audit.d.ts.map +1 -1
- package/dist/domains/audit/audit.js +40 -4
- package/dist/domains/audit/audit.js.map +1 -1
- package/dist/domains/communities/communities.d.ts +1537 -0
- package/dist/domains/communities/communities.d.ts.map +1 -0
- package/dist/domains/communities/communities.js +464 -0
- package/dist/domains/communities/communities.js.map +1 -0
- package/dist/domains/feed/feed.d.ts +996 -45
- package/dist/domains/feed/feed.d.ts.map +1 -1
- package/dist/domains/feed/feed.js +197 -10
- package/dist/domains/feed/feed.js.map +1 -1
- package/dist/domains/media/media.d.ts +7 -1
- package/dist/domains/media/media.d.ts.map +1 -1
- package/dist/domains/media/media.js +5 -0
- package/dist/domains/media/media.js.map +1 -1
- package/dist/domains/members/members.d.ts +6 -0
- package/dist/domains/members/members.d.ts.map +1 -1
- package/dist/domains/members/members.js +5 -0
- package/dist/domains/members/members.js.map +1 -1
- package/dist/domains/moderation/moderation.d.ts +6 -4
- package/dist/domains/moderation/moderation.d.ts.map +1 -1
- package/dist/domains/moderation/moderation.js +9 -2
- package/dist/domains/moderation/moderation.js.map +1 -1
- package/dist/domains/notifications/notifications.d.ts +133 -4
- package/dist/domains/notifications/notifications.d.ts.map +1 -1
- package/dist/domains/notifications/notifications.js +80 -3
- package/dist/domains/notifications/notifications.js.map +1 -1
- package/dist/domains/team/team.d.ts +22 -0
- package/dist/domains/team/team.d.ts.map +1 -1
- package/dist/domains/team/team.js +22 -0
- package/dist/domains/team/team.js.map +1 -1
- package/dist/domains/uploads/uploads.d.ts +1 -0
- package/dist/domains/uploads/uploads.d.ts.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -39,12 +39,13 @@ import { z } from 'zod';
|
|
|
39
39
|
* What an upload is for. It decides the sizes made and where it may be attached.
|
|
40
40
|
* Append only: every stored upload names one.
|
|
41
41
|
*/
|
|
42
|
-
export declare const MEDIA_PURPOSE_VALUES: readonly ["post", "avatar", "product_logo", "product_screenshot"];
|
|
42
|
+
export declare const MEDIA_PURPOSE_VALUES: readonly ["post", "avatar", "product_logo", "product_screenshot", "community_icon"];
|
|
43
43
|
export declare const mediaPurposeSchema: z.ZodEnum<{
|
|
44
44
|
post: "post";
|
|
45
45
|
avatar: "avatar";
|
|
46
46
|
product_logo: "product_logo";
|
|
47
47
|
product_screenshot: "product_screenshot";
|
|
48
|
+
community_icon: "community_icon";
|
|
48
49
|
}>;
|
|
49
50
|
export type MediaPurpose = z.infer<typeof mediaPurposeSchema>;
|
|
50
51
|
/**
|
|
@@ -82,6 +83,9 @@ export type MediaUploadContentType = z.infer<typeof mediaUploadContentTypeSchema
|
|
|
82
83
|
* - product_screenshot: as a post's image (long edge, aspect kept); a phone
|
|
83
84
|
* screenshot is tall, a desktop one wide. An animated GIF (a short demo)
|
|
84
85
|
* stays animated, within the same limits as a post's.
|
|
86
|
+
* - community_icon (0.9.0): as a product logo, a SQUARE fitted, never
|
|
87
|
+
* cropped. 96 for the "in <community>" chip, 256 for a card, 512 for the
|
|
88
|
+
* community page. It belongs to the community, not its uploader.
|
|
85
89
|
*
|
|
86
90
|
* A client shrinks a photo to the largest size here before uploading: anything
|
|
87
91
|
* bigger is thrown away by the server anyway, and costs the member data.
|
|
@@ -91,6 +95,7 @@ export declare const MEDIA_SIZES: {
|
|
|
91
95
|
readonly avatar: readonly [192, 512];
|
|
92
96
|
readonly product_logo: readonly [96, 256, 512];
|
|
93
97
|
readonly product_screenshot: readonly [540, 1080, 2048];
|
|
98
|
+
readonly community_icon: readonly [96, 256, 512];
|
|
94
99
|
};
|
|
95
100
|
/** The most sizes any purpose stores: the bound on `variants`. */
|
|
96
101
|
export declare const MEDIA_VARIANTS_MAX: number;
|
|
@@ -152,6 +157,7 @@ export declare const uploadedMediaSchema: z.ZodObject<{
|
|
|
152
157
|
avatar: "avatar";
|
|
153
158
|
product_logo: "product_logo";
|
|
154
159
|
product_screenshot: "product_screenshot";
|
|
160
|
+
community_icon: "community_icon";
|
|
155
161
|
}>;
|
|
156
162
|
expiresAt: z.ZodISODateTime;
|
|
157
163
|
}, z.core.$strip>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../../../src/domains/media/media.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;GAGG;AACH,eAAO,MAAM,oBAAoB,
|
|
1
|
+
{"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../../../src/domains/media/media.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;GAGG;AACH,eAAO,MAAM,oBAAoB,qFAMvB,CAAC;AACX,eAAO,MAAM,kBAAkB;;;;;;EAA+B,CAAC;AAC/D,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B,iEAK7B,CAAC;AACX,eAAO,MAAM,4BAA4B;;;;;EAAqC,CAAC;AAC/E,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAElF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,WAAW;;;;;;CAMoC,CAAC;AAE7D,kEAAkE;AAClE,eAAO,MAAM,kBAAkB,QAE9B,CAAC;AAEF,mCAAmC;AACnC,eAAO,MAAM,kBAAkB;;;;iBAI7B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;iBAO3B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;iBAG9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC"}
|
|
@@ -45,6 +45,7 @@ export const MEDIA_PURPOSE_VALUES = [
|
|
|
45
45
|
'avatar',
|
|
46
46
|
'product_logo',
|
|
47
47
|
'product_screenshot',
|
|
48
|
+
'community_icon',
|
|
48
49
|
];
|
|
49
50
|
export const mediaPurposeSchema = z.enum(MEDIA_PURPOSE_VALUES);
|
|
50
51
|
/**
|
|
@@ -81,6 +82,9 @@ export const mediaUploadContentTypeSchema = z.enum(MEDIA_UPLOAD_CONTENT_TYPES);
|
|
|
81
82
|
* - product_screenshot: as a post's image (long edge, aspect kept); a phone
|
|
82
83
|
* screenshot is tall, a desktop one wide. An animated GIF (a short demo)
|
|
83
84
|
* stays animated, within the same limits as a post's.
|
|
85
|
+
* - community_icon (0.9.0): as a product logo, a SQUARE fitted, never
|
|
86
|
+
* cropped. 96 for the "in <community>" chip, 256 for a card, 512 for the
|
|
87
|
+
* community page. It belongs to the community, not its uploader.
|
|
84
88
|
*
|
|
85
89
|
* A client shrinks a photo to the largest size here before uploading: anything
|
|
86
90
|
* bigger is thrown away by the server anyway, and costs the member data.
|
|
@@ -90,6 +94,7 @@ export const MEDIA_SIZES = {
|
|
|
90
94
|
avatar: [192, 512],
|
|
91
95
|
product_logo: [96, 256, 512],
|
|
92
96
|
product_screenshot: [540, 1080, 2048],
|
|
97
|
+
community_icon: [96, 256, 512],
|
|
93
98
|
};
|
|
94
99
|
/** The most sizes any purpose stores: the bound on `variants`. */
|
|
95
100
|
export const MEDIA_VARIANTS_MAX = Math.max(...Object.values(MEDIA_SIZES).map((sizes) => sizes.length));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media.js","sourceRoot":"","sources":["../../../src/domains/media/media.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,MAAM;IACN,QAAQ;IACR,cAAc;IACd,oBAAoB;
|
|
1
|
+
{"version":3,"file":"media.js","sourceRoot":"","sources":["../../../src/domains/media/media.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,MAAM;IACN,QAAQ;IACR,cAAc;IACd,oBAAoB;IACpB,gBAAgB;CACR,CAAC;AACX,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;AAG/D;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,YAAY;IACZ,WAAW;IACX,YAAY;IACZ,WAAW;CACH,CAAC;AACX,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;AAG/E;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,IAAI,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC;IACvB,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,YAAY,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC;IAC5B,kBAAkB,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC;IACrC,cAAc,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC;CAC4B,CAAC;AAE7D,kEAAkE;AAClE,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC,GAAG,CACxC,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAC3D,CAAC;AAEF,mCAAmC;AACnC,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;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,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE;CACb,CAAC,CAAC;AAGH;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE;IACZ,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,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC;IACpE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC,QAAQ,EAAE;CAC9D,CAAC,CAAC;AAGH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,gBAAgB,CAAC,MAAM,CAAC;IACzD,OAAO,EAAE,kBAAkB;IAC3B,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE;CAC5B,CAAC,CAAC","sourcesContent":["/**\n * founder-schema — Media: what an uploaded image becomes\n *\n * THE PIPELINE, end to end (0.5.0):\n *\n * 1. The client shrinks the photo (long edge at most the largest size in\n * `MEDIA_SIZES`, WebP or JPEG) and asks for an upload slot:\n * `POST /api/v1/uploads/presign` with a purpose, a content type and the\n * exact byte count (`uploadPresignBodySchema`).\n * 2. It PUTs the bytes straight to storage, with the headers it was given.\n * Nothing passes through the API server.\n * 3. It calls `POST /api/v1/uploads/:mediaId/complete`. The server checks the\n * file, decodes it fully, applies the photo's rotation, REMOVES EVERY\n * PIECE OF METADATA (GPS position, camera, timestamps), re-encodes it as\n * WebP at each size in `MEDIA_SIZES`, deletes the raw upload, and answers\n * with `uploadedMediaSchema`.\n * 4. A post (`attachedMediaSchema`), the avatar (`setAvatarBodySchema`,\n * onboarding's `avatarMediaId`), or a product's logo and screenshots\n * (`setProductLogoBodySchema`, `setProductScreenshotsBodySchema`, 0.6.0)\n * takes the media id. One upload is used once, by its owner, for the\n * purpose it was uploaded for.\n *\n * A product's images belong to the PRODUCT, not to whoever on the team uploaded\n * them: they stay when that person leaves or deletes their account, and go when\n * the product is deleted.\n *\n * What nobody sees: the raw upload. It sits in a folder the CDN cannot reach\n * and is deleted when processing finishes, or by storage itself after a day.\n * Only the re-encoded sizes are ever served.\n *\n * An image never attached is deleted after `MEDIA_UNATTACHED_TTL_HOURS`; a\n * deleted post's images, a replaced avatar, and an erased account's images are\n * deleted from storage by the server, so a copied link stops working.\n *\n * @module founder-schema/domains/media\n */\n\nimport { z } from 'zod';\nimport { MEDIA_PLACEHOLDER_MAX } from '../../core/limits.js';\n\n/**\n * What an upload is for. It decides the sizes made and where it may be attached.\n * Append only: every stored upload names one.\n */\nexport const MEDIA_PURPOSE_VALUES = [\n 'post',\n 'avatar',\n 'product_logo',\n 'product_screenshot',\n 'community_icon',\n] as const;\nexport const mediaPurposeSchema = z.enum(MEDIA_PURPOSE_VALUES);\nexport type MediaPurpose = z.infer<typeof mediaPurposeSchema>;\n\n/**\n * The content types a member may upload. Every one is decoded and re-encoded\n * to WebP before anyone sees it, so this list is about what the server can\n * DECODE safely, not what it serves.\n *\n * Not HEIC: an iPhone's photo picker converts HEIC to JPEG for the web, and a\n * client that shrinks the photo first re-encodes it anyway. SVG never: it is a\n * document that can carry script, not an image.\n */\nexport const MEDIA_UPLOAD_CONTENT_TYPES = [\n 'image/jpeg',\n 'image/png',\n 'image/webp',\n 'image/gif',\n] as const;\nexport const mediaUploadContentTypeSchema = z.enum(MEDIA_UPLOAD_CONTENT_TYPES);\nexport type MediaUploadContentType = z.infer<typeof mediaUploadContentTypeSchema>;\n\n/**\n * The sizes each purpose is stored at, smallest first.\n *\n * - post: the LONG edge, aspect kept. 540 for a feed card on a plain screen,\n * 1080 for the same card on a phone's dense screen, 2048 for the full-screen\n * view. An image smaller than a size is never enlarged, so a small image\n * has fewer sizes.\n * - avatar: a SQUARE, cropped around the most interesting region (usually a\n * face). 192 for every small circle (bylines, lists, chat) up to 64 CSS\n * pixels on a 3x screen, 512 for a profile header.\n * - product_logo: a SQUARE, but NEVER CROPPED: the whole logo is fitted\n * inside it and the rest is transparent, because cropping a wordmark the\n * way an avatar is cropped cuts letters off. Transparency is kept. 96 for\n * the product chip on a post (32 CSS pixels at 3x), 256 for a Discover card,\n * 512 for the product page.\n * - product_screenshot: as a post's image (long edge, aspect kept); a phone\n * screenshot is tall, a desktop one wide. An animated GIF (a short demo)\n * stays animated, within the same limits as a post's.\n * - community_icon (0.9.0): as a product logo, a SQUARE fitted, never\n * cropped. 96 for the \"in <community>\" chip, 256 for a card, 512 for the\n * community page. It belongs to the community, not its uploader.\n *\n * A client shrinks a photo to the largest size here before uploading: anything\n * bigger is thrown away by the server anyway, and costs the member data.\n */\nexport const MEDIA_SIZES = {\n post: [540, 1080, 2048],\n avatar: [192, 512],\n product_logo: [96, 256, 512],\n product_screenshot: [540, 1080, 2048],\n community_icon: [96, 256, 512],\n} as const satisfies Record<MediaPurpose, readonly number[]>;\n\n/** The most sizes any purpose stores: the bound on `variants`. */\nexport const MEDIA_VARIANTS_MAX = Math.max(\n ...Object.values(MEDIA_SIZES).map((sizes) => sizes.length),\n);\n\n/** One stored size of an image. */\nexport const mediaVariantSchema = z.object({\n width: z.number().int().positive(),\n height: z.number().int().positive(),\n url: z.url(),\n});\nexport type MediaVariant = z.infer<typeof mediaVariantSchema>;\n\n/**\n * A processed image, as every read shows it.\n *\n * `variants` is a ready-made `srcset`: smallest first, each with its own pixel\n * width. `url`, `width` and `height` repeat the largest one, so a client that\n * ignores `variants` still renders correctly and can reserve the image's box\n * from the aspect ratio before it loads (no layout shift).\n *\n * `placeholder` is a ThumbHash (base64): a ~30 character blurred preview a\n * client can paint instantly while the image loads.\n *\n * URLs point at our media CDN. They come from our own pipeline, never from a\n * member, so a plain `z.url()`.\n */\nexport const mediaImageSchema = z.object({\n id: z.string(),\n url: z.url(),\n width: z.number().int().positive(),\n height: z.number().int().positive(),\n variants: z.array(mediaVariantSchema).min(1).max(MEDIA_VARIANTS_MAX),\n placeholder: z.string().max(MEDIA_PLACEHOLDER_MAX).optional(),\n});\nexport type MediaImage = z.infer<typeof mediaImageSchema>;\n\n/**\n * `POST /api/v1/uploads/:mediaId/complete` answers with this: the image as it\n * will appear, not yet attached to anything.\n *\n * `expiresAt` is when the server deletes it if it is still unattached\n * (`MEDIA_UNATTACHED_TTL_HOURS` after the slot was issued). A composer left\n * open longer than that must upload again.\n */\nexport const uploadedMediaSchema = mediaImageSchema.extend({\n purpose: mediaPurposeSchema,\n expiresAt: z.iso.datetime(),\n});\nexport type UploadedMedia = z.infer<typeof uploadedMediaSchema>;\n"]}
|
|
@@ -163,7 +163,13 @@ export declare const memberDetailSchema: z.ZodObject<{
|
|
|
163
163
|
support_agent: "support_agent";
|
|
164
164
|
}>>;
|
|
165
165
|
canResetMpin: z.ZodBoolean;
|
|
166
|
+
grantableCapabilities: z.ZodArray<z.ZodEnum<{
|
|
167
|
+
create_communities: "create_communities";
|
|
168
|
+
}>>;
|
|
166
169
|
}, z.core.$strip>;
|
|
170
|
+
capabilities: z.ZodArray<z.ZodEnum<{
|
|
171
|
+
create_communities: "create_communities";
|
|
172
|
+
}>>;
|
|
167
173
|
mpinSet: z.ZodBoolean;
|
|
168
174
|
}, z.core.$strip>;
|
|
169
175
|
export type MemberDetail = z.infer<typeof memberDetailSchema>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"members.d.ts","sourceRoot":"","sources":["../../../src/domains/members/members.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"members.d.ts","sourceRoot":"","sources":["../../../src/domains/members/members.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAiBxB,iFAAiF;AACjF,eAAO,MAAM,oBAAoB,kCAAmC,CAAC;AACrE,eAAO,MAAM,kBAAkB;;;EAA+B,CAAC;AAC/D,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,sCAAsC;AACtC,eAAO,MAAM,kBAAkB;;iBAAyC,CAAC;AACzE,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D;;;;GAIG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;iBAKrC,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAC9E,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAEnF,gCAAgC;AAChC,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;iBAa9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;iBAAuC,CAAC;AAC9E,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E,6BAA6B;AAC7B,eAAO,MAAM,gBAAgB;;;;;;;iBAK3B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,qCAAqC;AACrC,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA4B7B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,sFAAsF;AACtF,eAAO,MAAM,uBAAuB;;iBAElC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC"}
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
* @module founder-schema/domains/members
|
|
31
31
|
*/
|
|
32
32
|
import { z } from 'zod';
|
|
33
|
+
import { capabilitySchema } from '../../access/capabilities.js';
|
|
33
34
|
import { platformRoleSchema } from '../../access/roles.js';
|
|
34
35
|
import { emptyStringToUndefined, objectIdSchema, optionalTrimmedString, paginationQuerySchema, usernameSchema, } from '../../core/common.js';
|
|
35
36
|
import { MEMBER_SEARCH_MAX, SUSPENSION_REASON_MAX, SUSPENSION_REASON_MIN, } from '../../core/limits.js';
|
|
@@ -95,7 +96,11 @@ export const memberDetailSchema = memberSummarySchema.extend({
|
|
|
95
96
|
grantableRoles: z.array(platformRoleSchema),
|
|
96
97
|
/** May clear this member's forgotten MPIN (superadmin, someone else). */
|
|
97
98
|
canResetMpin: z.boolean(),
|
|
99
|
+
/** Capabilities the asker may grant or revoke on this member (never their own) (0.9.0). */
|
|
100
|
+
grantableCapabilities: z.array(capabilitySchema),
|
|
98
101
|
}),
|
|
102
|
+
/** The capabilities they hold (0.9.0), e.g. `create_communities`. */
|
|
103
|
+
capabilities: z.array(capabilitySchema),
|
|
99
104
|
/** Whether they have set an MPIN. Only meaningful for staff. */
|
|
100
105
|
mpinSet: z.boolean(),
|
|
101
106
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"members.js","sourceRoot":"","sources":["../../../src/domains/members/members.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"members.js","sourceRoot":"","sources":["../../../src/domains/members/members.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * founder-schema: the staff member directory\n *\n * GET /api/v1/members ?q&status&role&limit&cursor\n * GET /api/v1/members/:memberId one member, as staff see them\n * POST /api/v1/members/:memberId/suspension { reason } suspend\n * DELETE /api/v1/members/:memberId/suspension lift it\n *\n * Every staff role has a Members tab: a moderator looks up who wrote\n * something, a support agent finds the person who wrote in, a manager decides\n * on a suspension. What each sees is the server's call, per field: a\n * moderator gets no email (`email: null`), because finding a member's\n * address is support's job, not moderation's.\n *\n * A SUSPENDED member cannot use the product at all, on any device, from the\n * next request on (every call answers `ACCOUNT_SUSPENDED`); their posts stay\n * up unless moderated separately, and a staff role they were acting in is\n * switched off. Lifting it restores everything else.\n *\n * SEARCH (`q`) finds people by the start of their name or handle among listed\n * founders, or by their exact email among everyone (only for a role that may\n * see emails: a moderator's email search finds nothing). It returns up to\n * `limit` matches in one page (type more to narrow), not a pageable list. Who may suspend whom is the access policy's: never\n * yourself, never a superadmin, and a manager never a fellow manager.\n *\n * Each detail carries a `viewer` block of what the asking staff member may do\n * to THIS member, worked out by the server, so the screen shows only the\n * buttons that will work.\n *\n * @module founder-schema/domains/members\n */\n\nimport { z } from 'zod';\nimport { capabilitySchema } from '../../access/capabilities.js';\nimport { platformRoleSchema } from '../../access/roles.js';\nimport {\n emptyStringToUndefined,\n objectIdSchema,\n optionalTrimmedString,\n paginationQuerySchema,\n usernameSchema,\n} from '../../core/common.js';\nimport {\n MEMBER_SEARCH_MAX,\n SUSPENSION_REASON_MAX,\n SUSPENSION_REASON_MIN,\n} from '../../core/limits.js';\nimport { paginatedSchema } from '../../core/responses.js';\n\n/** What staff can see an account's state as. A deleted account is not listed. */\nexport const MEMBER_STATUS_VALUES = ['active', 'suspended'] as const;\nexport const memberStatusSchema = z.enum(MEMBER_STATUS_VALUES);\nexport type MemberStatus = z.infer<typeof memberStatusSchema>;\n\n/** `:memberId` in the paths above. */\nexport const memberParamsSchema = z.object({ memberId: objectIdSchema });\nexport type MemberParams = z.infer<typeof memberParamsSchema>;\n\n/**\n * The directory's query. `q` is a name or handle prefix, or a whole email\n * address (anything with an `@` is matched as an email, exactly). An emptied\n * box is \"no search\", not an error.\n */\nexport const memberDirectoryQuerySchema = paginationQuerySchema.extend({\n q: optionalTrimmedString(MEMBER_SEARCH_MAX),\n status: z.preprocess(emptyStringToUndefined, memberStatusSchema.optional()),\n /** Only people holding this staff role. */\n role: z.preprocess(emptyStringToUndefined, platformRoleSchema.optional()),\n});\nexport type MemberDirectoryQuery = z.infer<typeof memberDirectoryQuerySchema>;\nexport type MemberDirectoryQueryInput = z.input<typeof memberDirectoryQuerySchema>;\n\n/** One row of the directory. */\nexport const memberSummarySchema = z.object({\n id: objectIdSchema,\n displayName: z.string(),\n /** Null when they have no founder profile (never finished onboarding). */\n username: usernameSchema.nullable(),\n avatarUrl: z.url().nullable(),\n /** Null when the asking role may not see it. */\n email: z.string().nullable(),\n status: memberStatusSchema,\n /** Staff roles held, highest first. Empty for an ordinary member. */\n roles: z.array(platformRoleSchema),\n joinedAt: z.iso.datetime(),\n lastActiveAt: z.iso.datetime().nullable(),\n});\nexport type MemberSummary = z.infer<typeof memberSummarySchema>;\n\nexport const memberDirectoryPageSchema = paginatedSchema(memberSummarySchema);\nexport type MemberDirectoryPage = z.infer<typeof memberDirectoryPageSchema>;\n\n/** A suspension in force. */\nexport const suspensionSchema = z.object({\n since: z.iso.datetime(),\n reason: z.string(),\n /** Who suspended them, by name at the time. */\n by: z.object({ id: objectIdSchema, displayName: z.string() }).nullable(),\n});\nexport type Suspension = z.infer<typeof suspensionSchema>;\n\n/** One member, as staff see them. */\nexport const memberDetailSchema = memberSummarySchema.extend({\n headline: z.string().nullable(),\n /** Their city, as declared on their profile. */\n city: z.string().nullable(),\n counts: z.object({\n posts: z.number().int().min(0),\n polls: z.number().int().min(0),\n comments: z.number().int().min(0),\n /** Reports filed about their posts, polls and comments that are still up. */\n reportsAgainst: z.number().int().min(0),\n /** Tickets they have raised. */\n tickets: z.number().int().min(0),\n }),\n suspension: suspensionSchema.nullable(),\n /** What the asking staff member may do to this member. */\n viewer: z.object({\n canSuspend: z.boolean(),\n /** Roles the asker may grant or revoke on this member (never their own). */\n grantableRoles: z.array(platformRoleSchema),\n /** May clear this member's forgotten MPIN (superadmin, someone else). */\n canResetMpin: z.boolean(),\n /** Capabilities the asker may grant or revoke on this member (never their own) (0.9.0). */\n grantableCapabilities: z.array(capabilitySchema),\n }),\n /** The capabilities they hold (0.9.0), e.g. `create_communities`. */\n capabilities: z.array(capabilitySchema),\n /** Whether they have set an MPIN. Only meaningful for staff. */\n mpinSet: z.boolean(),\n});\nexport type MemberDetail = z.infer<typeof memberDetailSchema>;\n\n/** `POST /members/:memberId/suspension`. The reason is on record in the audit log. */\nexport const suspendMemberBodySchema = z.object({\n reason: z.string().trim().min(SUSPENSION_REASON_MIN).max(SUSPENSION_REASON_MAX),\n});\nexport type SuspendMemberBody = z.infer<typeof suspendMemberBodySchema>;\n"]}
|
|
@@ -53,8 +53,8 @@ export type ModerationContextKind = z.infer<typeof moderationContextKindSchema>;
|
|
|
53
53
|
/** Where a post, poll, comment, product or review stands. */
|
|
54
54
|
export declare const MODERATION_STATE_VALUES: readonly ["visible", "hidden", "removed"];
|
|
55
55
|
export declare const moderationStateSchema: z.ZodEnum<{
|
|
56
|
-
visible: "visible";
|
|
57
56
|
hidden: "hidden";
|
|
57
|
+
visible: "visible";
|
|
58
58
|
removed: "removed";
|
|
59
59
|
}>;
|
|
60
60
|
export type ModerationState = z.infer<typeof moderationStateSchema>;
|
|
@@ -101,6 +101,7 @@ export declare const moderationItemSchema: z.ZodObject<{
|
|
|
101
101
|
id: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
102
102
|
}, z.core.$strip>;
|
|
103
103
|
excerpt: z.ZodString;
|
|
104
|
+
asReported: z.ZodOptional<z.ZodString>;
|
|
104
105
|
author: z.ZodObject<{
|
|
105
106
|
id: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
106
107
|
displayName: z.ZodString;
|
|
@@ -108,8 +109,8 @@ export declare const moderationItemSchema: z.ZodObject<{
|
|
|
108
109
|
}, z.core.$strip>;
|
|
109
110
|
createdAt: z.ZodISODateTime;
|
|
110
111
|
state: z.ZodEnum<{
|
|
111
|
-
visible: "visible";
|
|
112
112
|
hidden: "hidden";
|
|
113
|
+
visible: "visible";
|
|
113
114
|
removed: "removed";
|
|
114
115
|
}>;
|
|
115
116
|
reports: z.ZodObject<{
|
|
@@ -158,6 +159,7 @@ export declare const moderationPageSchema: z.ZodObject<{
|
|
|
158
159
|
id: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
159
160
|
}, z.core.$strip>;
|
|
160
161
|
excerpt: z.ZodString;
|
|
162
|
+
asReported: z.ZodOptional<z.ZodString>;
|
|
161
163
|
author: z.ZodObject<{
|
|
162
164
|
id: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
163
165
|
displayName: z.ZodString;
|
|
@@ -165,8 +167,8 @@ export declare const moderationPageSchema: z.ZodObject<{
|
|
|
165
167
|
}, z.core.$strip>;
|
|
166
168
|
createdAt: z.ZodISODateTime;
|
|
167
169
|
state: z.ZodEnum<{
|
|
168
|
-
visible: "visible";
|
|
169
170
|
hidden: "hidden";
|
|
171
|
+
visible: "visible";
|
|
170
172
|
removed: "removed";
|
|
171
173
|
}>;
|
|
172
174
|
reports: z.ZodObject<{
|
|
@@ -201,8 +203,8 @@ export declare const moderationContentQuerySchema: z.ZodObject<{
|
|
|
201
203
|
limit: z.ZodPreprocess<z.ZodDefault<z.ZodCoercedNumber<unknown>>, unknown>;
|
|
202
204
|
cursor: z.ZodOptional<z.ZodString>;
|
|
203
205
|
state: z.ZodPreprocess<z.ZodDefault<z.ZodEnum<{
|
|
204
|
-
visible: "visible";
|
|
205
206
|
hidden: "hidden";
|
|
207
|
+
visible: "visible";
|
|
206
208
|
removed: "removed";
|
|
207
209
|
}>>, unknown>;
|
|
208
210
|
}, z.core.$strip>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"moderation.d.ts","sourceRoot":"","sources":["../../../src/domains/moderation/moderation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAWxB;;;GAGG;AACH,eAAO,MAAM,8BAA8B,sCAAuC,CAAC;AACnF,eAAO,MAAM,2BAA2B;;;;EAAyC,CAAC;AAClF,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF,6DAA6D;AAC7D,eAAO,MAAM,uBAAuB,2CAA4C,CAAC;AACjF,eAAO,MAAM,qBAAqB;;;;EAAkC,CAAC;AACrE,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,wBAAwB,mDAAoD,CAAC;AAC1F,eAAO,MAAM,sBAAsB;;;;;EAAmC,CAAC;AACvE,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE;;;;;;GAMG;AACH,eAAO,MAAM,iCAAiC;;;;;;CAM4B,CAAC;AAI3E,wEAAwE;AACxE,eAAO,MAAM,oBAAoB
|
|
1
|
+
{"version":3,"file":"moderation.d.ts","sourceRoot":"","sources":["../../../src/domains/moderation/moderation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAWxB;;;GAGG;AACH,eAAO,MAAM,8BAA8B,sCAAuC,CAAC;AACnF,eAAO,MAAM,2BAA2B;;;;EAAyC,CAAC;AAClF,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF,6DAA6D;AAC7D,eAAO,MAAM,uBAAuB,2CAA4C,CAAC;AACjF,eAAO,MAAM,qBAAqB;;;;EAAkC,CAAC;AACrE,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,wBAAwB,mDAAoD,CAAC;AAC1F,eAAO,MAAM,sBAAsB;;;;;EAAmC,CAAC;AACvE,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE;;;;;;GAMG;AACH,eAAO,MAAM,iCAAiC;;;;;;CAM4B,CAAC;AAI3E,wEAAwE;AACxE,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA8C/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAwC,CAAC;AAC1E,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,wDAAwD;AACxD,eAAO,MAAM,4BAA4B;;;;;;;;iBAEvC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAClF,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAEvF,+EAA+E;AAC/E,eAAO,MAAM,4BAA4B;;;;;;;;;iBAGvC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAElF,2DAA2D;AAC3D,eAAO,MAAM,4BAA4B;;;;;;;;iBAIvC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC"}
|
|
@@ -78,10 +78,17 @@ export const moderationItemSchema = z.object({
|
|
|
78
78
|
*/
|
|
79
79
|
content: z.object({ kind: moderationContextKindSchema, id: objectIdSchema }),
|
|
80
80
|
/**
|
|
81
|
-
* Its first words, cut to `MODERATION_EXCERPT_MAX`: a poll's
|
|
82
|
-
* product's name and tagline, a review's stars and text.
|
|
81
|
+
* Its first words AS THEY ARE NOW, cut to `MODERATION_EXCERPT_MAX`: a poll's
|
|
82
|
+
* question, a product's name and tagline, a review's stars and text.
|
|
83
83
|
*/
|
|
84
84
|
excerpt: z.string(),
|
|
85
|
+
/**
|
|
86
|
+
* The words as they were when first reported, when the author has edited
|
|
87
|
+
* them since (0.8.0): both are shown, so an edit can neither hide what was
|
|
88
|
+
* reported nor slip new words past a moderator judging the old ones.
|
|
89
|
+
* Absent when unedited since the report.
|
|
90
|
+
*/
|
|
91
|
+
asReported: z.string().optional(),
|
|
85
92
|
/** Who wrote it; for a product, its owner. */
|
|
86
93
|
author: z.object({
|
|
87
94
|
id: objectIdSchema,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"moderation.js","sourceRoot":"","sources":["../../../src/domains/moderation/moderation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * founder-schema: moderation\n *\n * GET /api/v1/moderation/queue ?limit&cursor\n * what members reported and nobody has decided on, oldest report first\n * GET /api/v1/moderation/content ?state&limit&cursor\n * by state, newest first: visible is posts and polls by when posted;\n * hidden and removed also hold comments (so a hidden comment can be\n * found and put back), by when hidden or removed\n * A decision that changes nothing (hiding what is already hidden, removing\n * what its author deleted) leaves the reports open and writes nothing: for\n * those, dismiss.\n * POST /api/v1/moderation/:contentKind/:contentId/decision { action, note? }\n * decide on one post, poll, comment, product or review; answers the\n * item as it now is\n *\n * PRODUCTS AND REVIEWS (0.6.0) are reported and decided here too. A product is\n * hidden or restored, never removed by staff (it is its team's work; hiding\n * takes it out of Discover and off every page but its team's). A review is\n * hidden, restored or removed like a comment. The hidden and removed lists\n * hold them too, so a hidden product can be found and put back.\n *\n * ONE ITEM PER THING, NOT PER REPORT. Five members reporting one post is one\n * row with five reports, so a moderator decides once. The queue's order is\n * the oldest open report first: whoever has waited longest is seen first, and\n * a pile-on cannot jump the line.\n *\n * THE DECISIONS\n * dismiss it stays up; its open reports close as dismissed\n * hide out of every feed and thread, kept, restorable; reports actioned\n * restore a hidden item goes back up\n * remove deleted as its author deleting it would (counts move), not\n * restorable from here; reports actioned\n * Every decision on someone else's content is written to the audit log, with\n * the note when there is one.\n *\n * A report's `note` was written by a member: untrusted text, shown as text.\n *\n * @module founder-schema/domains/moderation\n */\n\nimport { z } from 'zod';\nimport {\n emptyStringToUndefined,\n objectIdSchema,\n optionalTrimmedString,\n paginationQuerySchema,\n} from '../../core/common.js';\nimport { MODERATION_NOTE_MAX } from '../../core/limits.js';\nimport { paginatedSchema } from '../../core/responses.js';\nimport { type ReportTargetKind, reportReasonSchema, reportTargetKindSchema } from '../feed/feed.js';\n\n/**\n * Where something is read in the app: a post or poll, or a product page (for a\n * product, and for a review of it).\n */\nexport const MODERATION_CONTEXT_KIND_VALUES = ['post', 'poll', 'product'] as const;\nexport const moderationContextKindSchema = z.enum(MODERATION_CONTEXT_KIND_VALUES);\nexport type ModerationContextKind = z.infer<typeof moderationContextKindSchema>;\n\n/** Where a post, poll, comment, product or review stands. */\nexport const MODERATION_STATE_VALUES = ['visible', 'hidden', 'removed'] as const;\nexport const moderationStateSchema = z.enum(MODERATION_STATE_VALUES);\nexport type ModerationState = z.infer<typeof moderationStateSchema>;\n\nexport const MODERATION_ACTION_VALUES = ['dismiss', 'hide', 'restore', 'remove'] as const;\nexport const moderationActionSchema = z.enum(MODERATION_ACTION_VALUES);\nexport type ModerationAction = z.infer<typeof moderationActionSchema>;\n\n/**\n * Which decisions apply to which kind of thing: everything, except that a\n * product is never removed by staff (it is its team's work; hiding it takes it\n * out of Discover and off every page but its team's). The decision dialog\n * offers these, and the server refuses anything else with\n * `MODERATION_ACTION_INVALID`. Exhaustive by type.\n */\nexport const MODERATION_ACTIONS_BY_TARGET_KIND = {\n post: MODERATION_ACTION_VALUES,\n poll: MODERATION_ACTION_VALUES,\n comment: MODERATION_ACTION_VALUES,\n review: MODERATION_ACTION_VALUES,\n product: ['dismiss', 'hide', 'restore'],\n} as const satisfies Record<ReportTargetKind, readonly ModerationAction[]>;\n\nconst count = z.number().int().min(0);\n\n/** One post, poll, comment, product or review as moderation sees it. */\nexport const moderationItemSchema = z.object({\n target: z.object({ kind: reportTargetKindSchema, id: objectIdSchema }),\n /**\n * Where it is read in the app: the post or poll itself, or the one a comment\n * is on; the product page for a product or a review.\n */\n content: z.object({ kind: moderationContextKindSchema, id: objectIdSchema }),\n /**\n * Its first words, cut to `MODERATION_EXCERPT_MAX`: a poll's question, a\n * product's name and tagline, a review's stars and text.\n */\n excerpt: z.string(),\n /** Who wrote it; for a product, its owner. */\n author: z.object({\n id: objectIdSchema,\n displayName: z.string(),\n avatarUrl: z.url().nullable(),\n }),\n createdAt: z.iso.datetime(),\n state: moderationStateSchema,\n reports: z.object({\n /** Reports nobody has decided on. */\n open: count,\n /** Every report ever filed about it. */\n total: count,\n /** Why it was reported, among the open ones, most-given first. */\n reasons: z.array(z.object({ reason: reportReasonSchema, count })),\n /** The reporters' notes, among the open ones, newest first (a few, not all). */\n notes: z.array(z.string()),\n /** When the oldest open report was filed. Null when none is open. */\n oldestOpenAt: z.iso.datetime().nullable(),\n }),\n /** What the asking staff member may do to it now. */\n viewer: z.object({\n canDismiss: z.boolean(),\n canHide: z.boolean(),\n canRestore: z.boolean(),\n canRemove: z.boolean(),\n }),\n});\nexport type ModerationItem = z.infer<typeof moderationItemSchema>;\n\nexport const moderationPageSchema = paginatedSchema(moderationItemSchema);\nexport type ModerationPage = z.infer<typeof moderationPageSchema>;\n\n/** `GET /moderation/content`. Visible when not said. */\nexport const moderationContentQuerySchema = paginationQuerySchema.extend({\n state: z.preprocess(emptyStringToUndefined, moderationStateSchema.default('visible')),\n});\nexport type ModerationContentQuery = z.infer<typeof moderationContentQuerySchema>;\nexport type ModerationContentQueryInput = z.input<typeof moderationContentQuerySchema>;\n\n/** `POST /moderation/:contentKind/:contentId/decision`: what is decided on. */\nexport const moderationTargetParamsSchema = z.object({\n contentKind: reportTargetKindSchema,\n contentId: objectIdSchema,\n});\nexport type ModerationTargetParams = z.infer<typeof moderationTargetParamsSchema>;\n\n/** `POST /moderation/:contentKind/:contentId/decision`. */\nexport const moderationDecisionBodySchema = z.object({\n action: moderationActionSchema,\n /** Why, for the audit log. Optional: an obvious spam removal needs no essay. */\n note: optionalTrimmedString(MODERATION_NOTE_MAX),\n});\nexport type ModerationDecisionBody = z.infer<typeof moderationDecisionBodySchema>;\n"]}
|
|
1
|
+
{"version":3,"file":"moderation.js","sourceRoot":"","sources":["../../../src/domains/moderation/moderation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * founder-schema: moderation\n *\n * GET /api/v1/moderation/queue ?limit&cursor\n * what members reported and nobody has decided on, oldest report first\n * GET /api/v1/moderation/content ?state&limit&cursor\n * by state, newest first: visible is posts and polls by when posted;\n * hidden and removed also hold comments (so a hidden comment can be\n * found and put back), by when hidden or removed\n * A decision that changes nothing (hiding what is already hidden, removing\n * what its author deleted) leaves the reports open and writes nothing: for\n * those, dismiss.\n * POST /api/v1/moderation/:contentKind/:contentId/decision { action, note? }\n * decide on one post, poll, comment, product or review; answers the\n * item as it now is\n *\n * PRODUCTS AND REVIEWS (0.6.0) are reported and decided here too. A product is\n * hidden or restored, never removed by staff (it is its team's work; hiding\n * takes it out of Discover and off every page but its team's). A review is\n * hidden, restored or removed like a comment. The hidden and removed lists\n * hold them too, so a hidden product can be found and put back.\n *\n * ONE ITEM PER THING, NOT PER REPORT. Five members reporting one post is one\n * row with five reports, so a moderator decides once. The queue's order is\n * the oldest open report first: whoever has waited longest is seen first, and\n * a pile-on cannot jump the line.\n *\n * THE DECISIONS\n * dismiss it stays up; its open reports close as dismissed\n * hide out of every feed and thread, kept, restorable; reports actioned\n * restore a hidden item goes back up\n * remove deleted as its author deleting it would (counts move), not\n * restorable from here; reports actioned\n * Every decision on someone else's content is written to the audit log, with\n * the note when there is one.\n *\n * A report's `note` was written by a member: untrusted text, shown as text.\n *\n * @module founder-schema/domains/moderation\n */\n\nimport { z } from 'zod';\nimport {\n emptyStringToUndefined,\n objectIdSchema,\n optionalTrimmedString,\n paginationQuerySchema,\n} from '../../core/common.js';\nimport { MODERATION_NOTE_MAX } from '../../core/limits.js';\nimport { paginatedSchema } from '../../core/responses.js';\nimport { type ReportTargetKind, reportReasonSchema, reportTargetKindSchema } from '../feed/feed.js';\n\n/**\n * Where something is read in the app: a post or poll, or a product page (for a\n * product, and for a review of it).\n */\nexport const MODERATION_CONTEXT_KIND_VALUES = ['post', 'poll', 'product'] as const;\nexport const moderationContextKindSchema = z.enum(MODERATION_CONTEXT_KIND_VALUES);\nexport type ModerationContextKind = z.infer<typeof moderationContextKindSchema>;\n\n/** Where a post, poll, comment, product or review stands. */\nexport const MODERATION_STATE_VALUES = ['visible', 'hidden', 'removed'] as const;\nexport const moderationStateSchema = z.enum(MODERATION_STATE_VALUES);\nexport type ModerationState = z.infer<typeof moderationStateSchema>;\n\nexport const MODERATION_ACTION_VALUES = ['dismiss', 'hide', 'restore', 'remove'] as const;\nexport const moderationActionSchema = z.enum(MODERATION_ACTION_VALUES);\nexport type ModerationAction = z.infer<typeof moderationActionSchema>;\n\n/**\n * Which decisions apply to which kind of thing: everything, except that a\n * product is never removed by staff (it is its team's work; hiding it takes it\n * out of Discover and off every page but its team's). The decision dialog\n * offers these, and the server refuses anything else with\n * `MODERATION_ACTION_INVALID`. Exhaustive by type.\n */\nexport const MODERATION_ACTIONS_BY_TARGET_KIND = {\n post: MODERATION_ACTION_VALUES,\n poll: MODERATION_ACTION_VALUES,\n comment: MODERATION_ACTION_VALUES,\n review: MODERATION_ACTION_VALUES,\n product: ['dismiss', 'hide', 'restore'],\n} as const satisfies Record<ReportTargetKind, readonly ModerationAction[]>;\n\nconst count = z.number().int().min(0);\n\n/** One post, poll, comment, product or review as moderation sees it. */\nexport const moderationItemSchema = z.object({\n target: z.object({ kind: reportTargetKindSchema, id: objectIdSchema }),\n /**\n * Where it is read in the app: the post or poll itself, or the one a comment\n * is on; the product page for a product or a review.\n */\n content: z.object({ kind: moderationContextKindSchema, id: objectIdSchema }),\n /**\n * Its first words AS THEY ARE NOW, cut to `MODERATION_EXCERPT_MAX`: a poll's\n * question, a product's name and tagline, a review's stars and text.\n */\n excerpt: z.string(),\n /**\n * The words as they were when first reported, when the author has edited\n * them since (0.8.0): both are shown, so an edit can neither hide what was\n * reported nor slip new words past a moderator judging the old ones.\n * Absent when unedited since the report.\n */\n asReported: z.string().optional(),\n /** Who wrote it; for a product, its owner. */\n author: z.object({\n id: objectIdSchema,\n displayName: z.string(),\n avatarUrl: z.url().nullable(),\n }),\n createdAt: z.iso.datetime(),\n state: moderationStateSchema,\n reports: z.object({\n /** Reports nobody has decided on. */\n open: count,\n /** Every report ever filed about it. */\n total: count,\n /** Why it was reported, among the open ones, most-given first. */\n reasons: z.array(z.object({ reason: reportReasonSchema, count })),\n /** The reporters' notes, among the open ones, newest first (a few, not all). */\n notes: z.array(z.string()),\n /** When the oldest open report was filed. Null when none is open. */\n oldestOpenAt: z.iso.datetime().nullable(),\n }),\n /** What the asking staff member may do to it now. */\n viewer: z.object({\n canDismiss: z.boolean(),\n canHide: z.boolean(),\n canRestore: z.boolean(),\n canRemove: z.boolean(),\n }),\n});\nexport type ModerationItem = z.infer<typeof moderationItemSchema>;\n\nexport const moderationPageSchema = paginatedSchema(moderationItemSchema);\nexport type ModerationPage = z.infer<typeof moderationPageSchema>;\n\n/** `GET /moderation/content`. Visible when not said. */\nexport const moderationContentQuerySchema = paginationQuerySchema.extend({\n state: z.preprocess(emptyStringToUndefined, moderationStateSchema.default('visible')),\n});\nexport type ModerationContentQuery = z.infer<typeof moderationContentQuerySchema>;\nexport type ModerationContentQueryInput = z.input<typeof moderationContentQuerySchema>;\n\n/** `POST /moderation/:contentKind/:contentId/decision`: what is decided on. */\nexport const moderationTargetParamsSchema = z.object({\n contentKind: reportTargetKindSchema,\n contentId: objectIdSchema,\n});\nexport type ModerationTargetParams = z.infer<typeof moderationTargetParamsSchema>;\n\n/** `POST /moderation/:contentKind/:contentId/decision`. */\nexport const moderationDecisionBodySchema = z.object({\n action: moderationActionSchema,\n /** Why, for the audit log. Optional: an obvious spam removal needs no essay. */\n note: optionalTrimmedString(MODERATION_NOTE_MAX),\n});\nexport type ModerationDecisionBody = z.infer<typeof moderationDecisionBodySchema>;\n"]}
|
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
*
|
|
6
6
|
* - ONE ROW PER RECIPIENT, written when the event happens.
|
|
7
7
|
* - REPEATS MERGE: a second comment on your post updates the same row
|
|
8
|
-
* ("
|
|
9
|
-
* events it holds and `actor` the latest.
|
|
8
|
+
* ("2 new comments, latest from Asha"), it never adds one. `count` is how
|
|
9
|
+
* many events it holds and `actor` the latest. A member repeating the same
|
|
10
|
+
* act (reacting, taking it back, reacting again) does not ring it again.
|
|
10
11
|
* - THE ACTOR IS LOOKED UP WHEN READ, never copied in: a renamed member shows
|
|
11
12
|
* their new name, and a deleted one shows as null ("A former member").
|
|
12
13
|
* - PREFERENCES ARE CHECKED before writing (Jansathi stores them and never
|
|
@@ -39,8 +40,20 @@ import { z } from 'zod';
|
|
|
39
40
|
* review_reply a product's team answered your review
|
|
40
41
|
* feedback_helpful a team marked your feedback as having helped
|
|
41
42
|
* tester_confirmed a team confirmed you tested their product
|
|
43
|
+
* post_reaction someone reacted to your post or poll (0.8.0)
|
|
44
|
+
* comment_reaction someone reacted to your comment (0.8.0)
|
|
45
|
+
* repost someone reposted your post or poll (0.8.0)
|
|
46
|
+
* community_join_request someone asked to join a community you moderate (0.9.0)
|
|
47
|
+
* community_request_approved your request to join was approved (always delivered)
|
|
48
|
+
* community_invite a community invited you (always delivered)
|
|
49
|
+
* community_announcement a community you are in pinned an announcement for everyone
|
|
50
|
+
* community_suggestion_decided your community suggestion was approved or declined (always delivered)
|
|
51
|
+
*
|
|
52
|
+
* The three 0.8.0 kinds merge per target like the others. A reaction counts
|
|
53
|
+
* once: changing it to another type is not a new event, and taking it back
|
|
54
|
+
* does not take the event back.
|
|
42
55
|
*/
|
|
43
|
-
export declare const NOTIFICATION_KIND_VALUES: readonly ["comment_on_post", "reply_to_comment", "product_invite", "product_invite_accepted", "product_review", "review_reply", "feedback_helpful", "tester_confirmed"];
|
|
56
|
+
export declare const NOTIFICATION_KIND_VALUES: readonly ["comment_on_post", "reply_to_comment", "product_invite", "product_invite_accepted", "product_review", "review_reply", "feedback_helpful", "tester_confirmed", "post_reaction", "comment_reaction", "repost", "community_join_request", "community_request_approved", "community_invite", "community_announcement", "community_suggestion_decided"];
|
|
44
57
|
export declare const notificationKindSchema: z.ZodEnum<{
|
|
45
58
|
feedback_helpful: "feedback_helpful";
|
|
46
59
|
tester_confirmed: "tester_confirmed";
|
|
@@ -50,15 +63,26 @@ export declare const notificationKindSchema: z.ZodEnum<{
|
|
|
50
63
|
product_invite_accepted: "product_invite_accepted";
|
|
51
64
|
product_review: "product_review";
|
|
52
65
|
review_reply: "review_reply";
|
|
66
|
+
post_reaction: "post_reaction";
|
|
67
|
+
comment_reaction: "comment_reaction";
|
|
68
|
+
repost: "repost";
|
|
69
|
+
community_join_request: "community_join_request";
|
|
70
|
+
community_request_approved: "community_request_approved";
|
|
71
|
+
community_invite: "community_invite";
|
|
72
|
+
community_announcement: "community_announcement";
|
|
73
|
+
community_suggestion_decided: "community_suggestion_decided";
|
|
53
74
|
}>;
|
|
54
75
|
export type NotificationKind = z.infer<typeof notificationKindSchema>;
|
|
55
76
|
/** The switches a member has, each covering one or more kinds. */
|
|
56
|
-
export declare const NOTIFICATION_PREFERENCE_VALUES: readonly ["comments", "replies", "productActivity", "recognition"];
|
|
77
|
+
export declare const NOTIFICATION_PREFERENCE_VALUES: readonly ["comments", "replies", "productActivity", "recognition", "reactions", "reposts", "communities"];
|
|
57
78
|
export declare const notificationPreferenceSchema: z.ZodEnum<{
|
|
79
|
+
communities: "communities";
|
|
58
80
|
comments: "comments";
|
|
59
81
|
replies: "replies";
|
|
60
82
|
productActivity: "productActivity";
|
|
61
83
|
recognition: "recognition";
|
|
84
|
+
reactions: "reactions";
|
|
85
|
+
reposts: "reposts";
|
|
62
86
|
}>;
|
|
63
87
|
export type NotificationPreference = z.infer<typeof notificationPreferenceSchema>;
|
|
64
88
|
/**
|
|
@@ -74,6 +98,14 @@ export declare const NOTIFICATION_PREFERENCE_OF: {
|
|
|
74
98
|
readonly review_reply: "productActivity";
|
|
75
99
|
readonly feedback_helpful: "recognition";
|
|
76
100
|
readonly tester_confirmed: "recognition";
|
|
101
|
+
readonly post_reaction: "reactions";
|
|
102
|
+
readonly comment_reaction: "reactions";
|
|
103
|
+
readonly repost: "reposts";
|
|
104
|
+
readonly community_join_request: "communities";
|
|
105
|
+
readonly community_request_approved: null;
|
|
106
|
+
readonly community_invite: null;
|
|
107
|
+
readonly community_announcement: "communities";
|
|
108
|
+
readonly community_suggestion_decided: null;
|
|
77
109
|
};
|
|
78
110
|
/**
|
|
79
111
|
* One row of the bell. Which of the optional targets are present depends on
|
|
@@ -87,6 +119,19 @@ export declare const NOTIFICATION_PREFERENCE_OF: {
|
|
|
87
119
|
* review_reply product, reviewId
|
|
88
120
|
* feedback_helpful product, content, commentId
|
|
89
121
|
* tester_confirmed product
|
|
122
|
+
* post_reaction content, reaction
|
|
123
|
+
* comment_reaction content, commentId, reaction, excerpt (your comment)
|
|
124
|
+
* repost content (yours, the one reposted), repostId (the latest repost, to read their words)
|
|
125
|
+
* community_join_request community
|
|
126
|
+
* community_request_approved community
|
|
127
|
+
* community_invite community
|
|
128
|
+
* community_announcement community, content (the pinned post or poll)
|
|
129
|
+
* community_suggestion_decided suggestion, community (once approved)
|
|
130
|
+
*
|
|
131
|
+
* Any row about something inside a community also carries `community`
|
|
132
|
+
* (0.9.0), whatever its kind. When the recipient leaves the community, is
|
|
133
|
+
* removed or is banned, its rows about that community lose their content,
|
|
134
|
+
* comment, excerpt and repost: what they could read there, they no longer can.
|
|
90
135
|
*
|
|
91
136
|
* A target that no longer exists (a deleted post, product or review) is
|
|
92
137
|
* absent rather than pointing at a 404; the row still says what happened.
|
|
@@ -102,6 +147,14 @@ export declare const notificationSchema: z.ZodObject<{
|
|
|
102
147
|
product_invite_accepted: "product_invite_accepted";
|
|
103
148
|
product_review: "product_review";
|
|
104
149
|
review_reply: "review_reply";
|
|
150
|
+
post_reaction: "post_reaction";
|
|
151
|
+
comment_reaction: "comment_reaction";
|
|
152
|
+
repost: "repost";
|
|
153
|
+
community_join_request: "community_join_request";
|
|
154
|
+
community_request_approved: "community_request_approved";
|
|
155
|
+
community_invite: "community_invite";
|
|
156
|
+
community_announcement: "community_announcement";
|
|
157
|
+
community_suggestion_decided: "community_suggestion_decided";
|
|
105
158
|
}>;
|
|
106
159
|
actor: z.ZodNullable<z.ZodObject<{
|
|
107
160
|
userId: z.ZodString;
|
|
@@ -126,10 +179,41 @@ export declare const notificationSchema: z.ZodObject<{
|
|
|
126
179
|
logoUrl: z.ZodOptional<z.ZodURL>;
|
|
127
180
|
}, z.core.$strip>>;
|
|
128
181
|
reviewId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
|
|
182
|
+
repostId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
|
|
183
|
+
community: z.ZodOptional<z.ZodObject<{
|
|
184
|
+
id: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
185
|
+
slug: z.ZodString;
|
|
186
|
+
name: z.ZodString;
|
|
187
|
+
iconUrl: z.ZodOptional<z.ZodURL>;
|
|
188
|
+
visibility: z.ZodEnum<{
|
|
189
|
+
public: "public";
|
|
190
|
+
private: "private";
|
|
191
|
+
hidden: "hidden";
|
|
192
|
+
}>;
|
|
193
|
+
archived: z.ZodOptional<z.ZodBoolean>;
|
|
194
|
+
}, z.core.$strip>>;
|
|
195
|
+
suggestion: z.ZodOptional<z.ZodObject<{
|
|
196
|
+
id: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
197
|
+
name: z.ZodString;
|
|
198
|
+
status: z.ZodEnum<{
|
|
199
|
+
approved: "approved";
|
|
200
|
+
declined: "declined";
|
|
201
|
+
}>;
|
|
202
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
203
|
+
}, z.core.$strip>>;
|
|
129
204
|
role: z.ZodOptional<z.ZodEnum<{
|
|
130
205
|
team: "team";
|
|
131
206
|
cofounder: "cofounder";
|
|
132
207
|
}>>;
|
|
208
|
+
reaction: z.ZodOptional<z.ZodEnum<{
|
|
209
|
+
support: "support";
|
|
210
|
+
like: "like";
|
|
211
|
+
celebrate: "celebrate";
|
|
212
|
+
insightful: "insightful";
|
|
213
|
+
curious: "curious";
|
|
214
|
+
love: "love";
|
|
215
|
+
haha: "haha";
|
|
216
|
+
}>>;
|
|
133
217
|
excerpt: z.ZodOptional<z.ZodString>;
|
|
134
218
|
readAt: z.ZodNullable<z.ZodISODateTime>;
|
|
135
219
|
lastAt: z.ZodISODateTime;
|
|
@@ -148,6 +232,14 @@ export declare const notificationPageSchema: z.ZodObject<{
|
|
|
148
232
|
product_invite_accepted: "product_invite_accepted";
|
|
149
233
|
product_review: "product_review";
|
|
150
234
|
review_reply: "review_reply";
|
|
235
|
+
post_reaction: "post_reaction";
|
|
236
|
+
comment_reaction: "comment_reaction";
|
|
237
|
+
repost: "repost";
|
|
238
|
+
community_join_request: "community_join_request";
|
|
239
|
+
community_request_approved: "community_request_approved";
|
|
240
|
+
community_invite: "community_invite";
|
|
241
|
+
community_announcement: "community_announcement";
|
|
242
|
+
community_suggestion_decided: "community_suggestion_decided";
|
|
151
243
|
}>;
|
|
152
244
|
actor: z.ZodNullable<z.ZodObject<{
|
|
153
245
|
userId: z.ZodString;
|
|
@@ -172,10 +264,41 @@ export declare const notificationPageSchema: z.ZodObject<{
|
|
|
172
264
|
logoUrl: z.ZodOptional<z.ZodURL>;
|
|
173
265
|
}, z.core.$strip>>;
|
|
174
266
|
reviewId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
|
|
267
|
+
repostId: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
|
|
268
|
+
community: z.ZodOptional<z.ZodObject<{
|
|
269
|
+
id: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
270
|
+
slug: z.ZodString;
|
|
271
|
+
name: z.ZodString;
|
|
272
|
+
iconUrl: z.ZodOptional<z.ZodURL>;
|
|
273
|
+
visibility: z.ZodEnum<{
|
|
274
|
+
public: "public";
|
|
275
|
+
private: "private";
|
|
276
|
+
hidden: "hidden";
|
|
277
|
+
}>;
|
|
278
|
+
archived: z.ZodOptional<z.ZodBoolean>;
|
|
279
|
+
}, z.core.$strip>>;
|
|
280
|
+
suggestion: z.ZodOptional<z.ZodObject<{
|
|
281
|
+
id: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
282
|
+
name: z.ZodString;
|
|
283
|
+
status: z.ZodEnum<{
|
|
284
|
+
approved: "approved";
|
|
285
|
+
declined: "declined";
|
|
286
|
+
}>;
|
|
287
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
288
|
+
}, z.core.$strip>>;
|
|
175
289
|
role: z.ZodOptional<z.ZodEnum<{
|
|
176
290
|
team: "team";
|
|
177
291
|
cofounder: "cofounder";
|
|
178
292
|
}>>;
|
|
293
|
+
reaction: z.ZodOptional<z.ZodEnum<{
|
|
294
|
+
support: "support";
|
|
295
|
+
like: "like";
|
|
296
|
+
celebrate: "celebrate";
|
|
297
|
+
insightful: "insightful";
|
|
298
|
+
curious: "curious";
|
|
299
|
+
love: "love";
|
|
300
|
+
haha: "haha";
|
|
301
|
+
}>>;
|
|
179
302
|
excerpt: z.ZodOptional<z.ZodString>;
|
|
180
303
|
readAt: z.ZodNullable<z.ZodISODateTime>;
|
|
181
304
|
lastAt: z.ZodISODateTime;
|
|
@@ -199,6 +322,9 @@ export declare const notificationPreferencesSchema: z.ZodObject<{
|
|
|
199
322
|
replies: z.ZodBoolean;
|
|
200
323
|
productActivity: z.ZodBoolean;
|
|
201
324
|
recognition: z.ZodBoolean;
|
|
325
|
+
reactions: z.ZodBoolean;
|
|
326
|
+
reposts: z.ZodBoolean;
|
|
327
|
+
communities: z.ZodBoolean;
|
|
202
328
|
}, z.core.$strip>;
|
|
203
329
|
export type NotificationPreferences = z.infer<typeof notificationPreferencesSchema>;
|
|
204
330
|
/** Only the switches that changed; no defaults (a patch states what was sent). */
|
|
@@ -207,6 +333,9 @@ export declare const updateNotificationPreferencesBodySchema: z.ZodObject<{
|
|
|
207
333
|
replies: z.ZodOptional<z.ZodBoolean>;
|
|
208
334
|
productActivity: z.ZodOptional<z.ZodBoolean>;
|
|
209
335
|
recognition: z.ZodOptional<z.ZodBoolean>;
|
|
336
|
+
reactions: z.ZodOptional<z.ZodBoolean>;
|
|
337
|
+
reposts: z.ZodOptional<z.ZodBoolean>;
|
|
338
|
+
communities: z.ZodOptional<z.ZodBoolean>;
|
|
210
339
|
}, z.core.$strip>;
|
|
211
340
|
export type UpdateNotificationPreferencesBody = z.infer<typeof updateNotificationPreferencesBodySchema>;
|
|
212
341
|
//# sourceMappingURL=notifications.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../../../src/domains/notifications/notifications.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../../../src/domains/notifications/notifications.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,wBAAwB,8VAiB3B,CAAC;AACX,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;EAAmC,CAAC;AACvE,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,kEAAkE;AAClE,eAAO,MAAM,8BAA8B,2GAQjC,CAAC;AACX,eAAO,MAAM,4BAA4B;;;;;;;;EAAyC,CAAC;AACnF,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAElF;;;GAGG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;CAiBqC,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmD7B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAsC,CAAC;AAC1E,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,iBAAiB;AACjB,eAAO,MAAM,6BAA6B;;iBAExC,CAAC;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAEpF,eAAO,MAAM,wBAAwB;;iBAA+C,CAAC;AACrF,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,+CAA+C;AAC/C,eAAO,MAAM,6BAA6B;;;;;;;;iBAWxC,CAAC;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAEpF,kFAAkF;AAClF,eAAO,MAAM,uCAAuC;;;;;;;;iBAQlD,CAAC;AACH,MAAM,MAAM,iCAAiC,GAAG,CAAC,CAAC,KAAK,CACrD,OAAO,uCAAuC,CAC/C,CAAC"}
|