@buildinternet/releases-api-types 0.24.0 → 0.26.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.24.0",
3
+ "version": "0.26.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
@@ -90,6 +90,7 @@ import type {
90
90
  DeleteSourceReleasesResponseSchema,
91
91
  InsertReleaseResponseSchema,
92
92
  BatchReleasesResponseSchema,
93
+ RawSnapshotResponseSchema,
93
94
  OversizedChangelogFileRowSchema,
94
95
  OversizedChangelogFilesResponseSchema,
95
96
  FetchableSourcesResponseSchema,
@@ -316,6 +317,7 @@ export {
316
317
  DeleteSourceReleasesResponseSchema,
317
318
  InsertReleaseResponseSchema,
318
319
  BatchReleasesResponseSchema,
320
+ RawSnapshotResponseSchema,
319
321
  OversizedChangelogFileRowSchema,
320
322
  OversizedChangelogFilesResponseSchema,
321
323
  FetchableSourcesResponseSchema,
@@ -572,6 +574,7 @@ export type DeleteSourceResponse = z.infer<typeof DeleteSourceResponseSchema>;
572
574
  export type DeleteSourceReleasesResponse = z.infer<typeof DeleteSourceReleasesResponseSchema>;
573
575
  export type InsertReleaseResponse = z.infer<typeof InsertReleaseResponseSchema>;
574
576
  export type BatchReleasesResponse = z.infer<typeof BatchReleasesResponseSchema>;
577
+ export type RawSnapshotResponse = z.infer<typeof RawSnapshotResponseSchema>;
575
578
  export type OversizedChangelogFileRow = z.infer<typeof OversizedChangelogFileRowSchema>;
576
579
  export type OversizedChangelogFilesResponse = z.infer<typeof OversizedChangelogFilesResponseSchema>;
577
580
  export type FetchableSourcesResponse = z.infer<typeof FetchableSourcesResponseSchema>;
@@ -703,6 +706,8 @@ export interface ReleaseDetail {
703
706
  composition?: ReleaseComposition | null;
704
707
  /** App Store platform + icon, present only when `sourceType === "appstore"`. */
705
708
  appStore?: { platform: "ios" | "macos"; iconUrl: string | null } | null;
709
+ /** Video provider tag, present only when `sourceType === "video"`. */
710
+ video?: { provider: "youtube" | "vimeo" | "wistia" } | null;
706
711
  }
707
712
 
708
713
  export type ReleaseCoverageSibling = z.infer<typeof ReleaseCoverageSiblingSchema>;
@@ -902,6 +907,7 @@ export type OverviewPlanAction = "missing" | "refresh" | "skip";
902
907
  export interface OverviewManifestRow {
903
908
  orgSlug: string;
904
909
  orgName: string;
910
+ orgCreatedAt: string;
905
911
  discovery: "curated" | "agent" | "on_demand";
906
912
  overviewUpdatedAt: string | null;
907
913
  overviewGeneratedAt: string | null;
@@ -7,6 +7,7 @@ import {
7
7
  OverviewPageItemSchema,
8
8
  PaginationSchema,
9
9
  ReleaseItemSchema,
10
+ VideoSourceInfoSchema,
10
11
  } from "./shared.js";
11
12
  import { SourceListItemSchema } from "./sources.js";
12
13
  import { ProductListItemSchema } from "./products.js";
@@ -20,6 +21,7 @@ export const OrgListItemSchema = z.object({
20
21
  description: z.string().nullable(),
21
22
  category: CategorySchema.nullable(),
22
23
  avatarUrl: z.string().nullable(),
24
+ featured: z.boolean(),
23
25
  sourceCount: z.number().int().min(0),
24
26
  releaseCount: z.number().int().min(0),
25
27
  recentReleaseCount: z.number().int().min(0),
@@ -108,11 +110,13 @@ export const UpdateOrgBodySchema = z.object({
108
110
  isHidden: z.boolean().optional(),
109
111
  /** Admin-only: opt the org into automatic AI content — org overviews AND per-release summaries (single backend flag `auto_generate_content`). */
110
112
  autoGenerateContent: z.boolean().optional(),
113
+ /** Admin-only: promote this org on the home-page featured rail. */
114
+ featured: z.boolean().optional(),
111
115
  });
112
116
 
113
117
  // Org detail's products query selects a strict subset of `ProductListItem` —
114
- // no category/orgId/createdAt because the parent already names the org and
115
- // the org detail UI doesn't surface those columns.
118
+ // no category/orgId because the parent already names the org; createdAt is
119
+ // included for age-based filtering by consumers.
116
120
  const OrgDetailProductSchema = ProductListItemSchema.pick({
117
121
  id: true,
118
122
  slug: true,
@@ -121,6 +125,7 @@ const OrgDetailProductSchema = ProductListItemSchema.pick({
121
125
  description: true,
122
126
  sourceCount: true,
123
127
  kind: true,
128
+ createdAt: true,
124
129
  }).extend({
125
130
  releaseCount: z.number().int().min(0),
126
131
  });
@@ -341,6 +346,7 @@ export const OrgReleaseItemSchema = ReleaseItemSchema.extend({
341
346
  name: z.string(),
342
347
  type: z.string(),
343
348
  appStore: AppStoreSourceInfoSchema.optional(),
349
+ video: VideoSourceInfoSchema.optional(),
344
350
  }),
345
351
  /**
346
352
  * Owning product, when the release's source is grouped under a product.
@@ -427,6 +433,8 @@ export const OrgDetailSchema = z.object({
427
433
  isHidden: z.boolean().optional(),
428
434
  /** Admin display flag: org is opted into automatic overviews + per-release summaries. Optional on the wire for older workers mid-deploy. */
429
435
  autoGenerateContent: z.boolean().optional(),
436
+ /** Admin display flag: org is promoted on the home-page featured rail. Optional on the wire for older workers mid-deploy. */
437
+ featured: z.boolean().optional(),
430
438
  /** Admin display flag: all ingest paused for this org. */
431
439
  fetchPaused: z.boolean().optional(),
432
440
  /** How the org row was created. `on_demand` orgs are excluded from overview generation regardless of `autoGenerateContent`. */
@@ -5,6 +5,7 @@ import {
5
5
  MediaItemSchema,
6
6
  ReleaseCompositionSchema,
7
7
  ReleaseTypeSchema,
8
+ VideoSourceInfoSchema,
8
9
  } from "./shared.js";
9
10
 
10
11
  // ReleaseCompositionSchema lives in ./shared.js (single source of truth) — both
@@ -200,6 +201,7 @@ export const ReleaseDetailResponseSchema = z.object({
200
201
  org: ReleaseDetailOrgSchema.nullable(),
201
202
  composition: ReleaseCompositionSchema.nullable(),
202
203
  appStore: AppStoreSourceInfoSchema.nullable().optional(),
204
+ video: VideoSourceInfoSchema.nullable().optional(),
203
205
  });
204
206
 
205
207
  /**
@@ -1,6 +1,11 @@
1
1
  import { z } from "zod";
2
2
  import { KIND_VALUES } from "@buildinternet/releases-core/kinds";
3
- import { MediaItemSchema, ReleaseTypeSchema } from "./shared.js";
3
+ import {
4
+ AppStoreSourceInfoSchema,
5
+ MediaItemSchema,
6
+ ReleaseTypeSchema,
7
+ VideoSourceInfoSchema,
8
+ } from "./shared.js";
4
9
  import { SourceTypeSchema } from "./sources.js";
5
10
  import { LookupStatusSchema } from "./lookups.js";
6
11
 
@@ -66,6 +71,16 @@ export const SearchReleaseHitSchema = z.object({
66
71
  // without re-validating; legacy rows occasionally drift from the
67
72
  // canonical four-value set. Used by the web byline icon.
68
73
  sourceType: z.string().optional(),
74
+ /**
75
+ * App Store platform + icon for `type: "appstore"` sources, null/absent
76
+ * otherwise. Powers the compact app-update treatment on the search card. #1206
77
+ */
78
+ appStore: AppStoreSourceInfoSchema.nullable().optional(),
79
+ /**
80
+ * Video provider tag for `type: "video"` sources, absent otherwise. Powers
81
+ * the thumbnail-forward video row on search cards. #video
82
+ */
83
+ video: VideoSourceInfoSchema.nullable().optional(),
69
84
  orgSlug: z.string().nullable(),
70
85
  orgName: z.string().nullable().optional(),
71
86
  /** Owning product slug — present when the source belongs to a product. Lets
@@ -22,6 +22,12 @@ export const AppStoreSourceInfoSchema = z.object({
22
22
  iconUrl: z.string().nullable(),
23
23
  });
24
24
 
25
+ /** Video provider tag, present only when `sourceType === "video"`. Thumbnail
26
+ * and watch URL reuse the release's existing `media[]` / `url`. */
27
+ export const VideoSourceInfoSchema = z.object({
28
+ provider: z.enum(["youtube", "vimeo", "wistia"]),
29
+ });
30
+
25
31
  export const PaginationSchema = z.object({
26
32
  page: z.number().int().min(1),
27
33
  pageSize: z.number().int().min(1),
@@ -559,6 +559,24 @@ export const BatchReleasesResponseSchema = z.object({
559
559
  total: z.number().int().min(0),
560
560
  });
561
561
 
562
+ // ── Raw page snapshot (POST /sources/:slug/raw-snapshot) ──
563
+
564
+ /**
565
+ * Response for `POST /v1/sources/:slug/raw-snapshot` (#1283). On a store or a
566
+ * content-hash dedup hit, all fields are present; `stored` is `false` for the
567
+ * dedup case. When the `RAW_SNAPSHOTS` bucket is unbound the capture soft-fails
568
+ * with `{ stored: false, reason: "no_binding" }` and the snapshot fields are
569
+ * omitted — capture is best-effort and never errors ingest.
570
+ */
571
+ export const RawSnapshotResponseSchema = z.object({
572
+ stored: z.boolean(),
573
+ r2Key: z.string().optional(),
574
+ contentHash: z.string().optional(),
575
+ bytes: z.number().int().min(0).optional(),
576
+ // Only set on the soft-fail path; bounded so consumers can branch on it.
577
+ reason: z.enum(["no_binding"]).optional(),
578
+ });
579
+
562
580
  // ── Oversized changelog files (GET /sources/changelog-files/oversized) ──
563
581
 
564
582
  /**