@buildinternet/releases-api-types 0.31.0 → 0.32.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buildinternet/releases-api-types",
3
- "version": "0.31.0",
3
+ "version": "0.32.0",
4
4
  "description": "Wire protocol — request/response types for the Releases registry API. Shared by web, workers, and clients.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/api-types.ts CHANGED
@@ -748,7 +748,16 @@ export interface ReleaseDetail {
748
748
  sourceName: string;
749
749
  sourceSlug: string;
750
750
  sourceType: string;
751
- org: { slug: string; name: string } | null;
751
+ /**
752
+ * Owning org. `avatarUrl` is the resolved `organizations.avatar_url`
753
+ * (nullable; `.optional()` for mid-deploy / pinned-worker tolerance).
754
+ */
755
+ org: { slug: string; name: string; avatarUrl?: string | null } | null;
756
+ /**
757
+ * Owning product, when the source is grouped under one (`sources.product_id`).
758
+ * `null` when ungrouped; `.optional()` so older servers that omit it still type.
759
+ */
760
+ product?: { slug: string; name: string } | null;
752
761
  /** Release type. See {@link ReleaseType}. */
753
762
  type?: ReleaseType;
754
763
  /** Per-category item counts from the AI release-content pass. See {@link ReleaseComposition}. */
@@ -786,6 +795,46 @@ export type ReleaseStreamMessage = z.infer<typeof ReleaseStreamMessageSchema>;
786
795
 
787
796
  export type ReleaseSummaryItem = z.infer<typeof ReleaseSummaryItemSchema>;
788
797
 
798
+ // ── Follows ──
799
+
800
+ /** What a user can follow. */
801
+ export type FollowTarget = "org" | "product";
802
+
803
+ /** A user's follow, enriched for rendering (returned by GET /v1/me/follows). */
804
+ export interface Follow {
805
+ targetType: FollowTarget;
806
+ targetId: string;
807
+ name: string;
808
+ slug: string;
809
+ avatarUrl: string | null;
810
+ /** Owning org slug for product follows (null for org follows). */
811
+ orgSlug: string | null;
812
+ createdAt: string;
813
+ }
814
+
815
+ /** GET /v1/me/follows response. */
816
+ export interface FollowsListResponse {
817
+ follows: Follow[];
818
+ }
819
+
820
+ /** POST /v1/me/follows request body. */
821
+ export interface FollowRequest {
822
+ targetType: FollowTarget;
823
+ targetId: string;
824
+ }
825
+
826
+ /** POST/DELETE /v1/me/follows response. */
827
+ export interface FollowMutationResponse {
828
+ success: true;
829
+ following: boolean;
830
+ }
831
+
832
+ /**
833
+ * GET /v1/me/feed response — the personalized release feed. Reuses the same item
834
+ * shape as /v1/releases/latest (ReleaseLatestItem) inside the standard list envelope.
835
+ */
836
+ export type PersonalizedFeedResponse = ListResponse<ReleaseLatestItem>;
837
+
789
838
  // ── Search ──
790
839
 
791
840
  export type SearchOrgHit = z.infer<typeof SearchOrgHitSchema>;
@@ -168,6 +168,13 @@ export const ReleasesWithMediaResponseSchema = z.array(ReleaseWithMediaRowSchema
168
168
  export const ReleaseDetailOrgSchema = z.object({
169
169
  slug: z.string(),
170
170
  name: z.string(),
171
+ /**
172
+ * Resolved org avatar URL (the `organizations.avatar_url` column). `null`
173
+ * when the org has no stored avatar. Additive — older servers omit it, so
174
+ * treat `undefined` as `null`. Mirrors the `orgAvatarUrl` field on the
175
+ * related-rail feed.
176
+ */
177
+ avatarUrl: z.string().nullable().optional(),
171
178
  });
172
179
 
173
180
  /**
@@ -199,6 +206,13 @@ export const ReleaseDetailResponseSchema = z.object({
199
206
  sourceSlug: z.string().nullable(),
200
207
  sourceType: z.enum(SOURCE_TYPES).nullable(),
201
208
  org: ReleaseDetailOrgSchema.nullable(),
209
+ /**
210
+ * Owning product, when the release's source is grouped under a product
211
+ * (`sources.product_id`). `null` when the source has no product. Additive —
212
+ * older servers omit this field; treat `undefined` as `null`. Reuses the
213
+ * `{ slug, name }` shape from the latest feed.
214
+ */
215
+ product: ReleaseLatestProductSchema.nullable().optional(),
202
216
  composition: ReleaseCompositionSchema.nullable(),
203
217
  appStore: AppStoreSourceInfoSchema.nullable().optional(),
204
218
  video: VideoSourceInfoSchema.nullable().optional(),