@buildinternet/releases-api-types 0.13.0 → 0.15.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.13.0",
3
+ "version": "0.15.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",
@@ -17,7 +17,7 @@
17
17
  "README.md"
18
18
  ],
19
19
  "dependencies": {
20
- "@buildinternet/releases-core": "^0.19.0",
20
+ "@buildinternet/releases-core": "^0.20.0",
21
21
  "zod": "^4.3.6"
22
22
  },
23
23
  "publishConfig": {
package/src/api-types.ts CHANGED
@@ -133,7 +133,23 @@ export type ErrorResponse = z.infer<typeof ErrorResponseSchema>;
133
133
 
134
134
  export interface SitemapPayload {
135
135
  orgs: Array<{ slug: string; lastActivity: string | null }>;
136
- sources: Array<{ orgSlug: string; slug: string; latestDate: string | null }>;
136
+ sources: Array<{
137
+ orgSlug: string;
138
+ slug: string;
139
+ latestDate: string | null;
140
+ /**
141
+ * Whether this source has a stored GitHub CHANGELOG file. Used by the web
142
+ * sitemap to emit `/{org}/{src}/changelog` URLs only for sources where the
143
+ * route resolves (#875). Optional for backwards compatibility — older
144
+ * clients ignore it.
145
+ */
146
+ hasChangelog?: boolean;
147
+ /**
148
+ * Whether this source has any rolling or monthly highlight summaries.
149
+ * Drives `/{org}/{src}/highlights` sitemap emission (#875).
150
+ */
151
+ hasHighlights?: boolean;
152
+ }>;
137
153
  products: Array<{ orgSlug: string; slug: string }>;
138
154
  collections: Array<{ slug: string; updatedAt: string }>;
139
155
  }
@@ -219,12 +235,6 @@ export interface ReleaseDetail {
219
235
  titleGenerated?: string | null;
220
236
  /** AI-generated smart-brevity headline (#852, renamed in #860). Same fallback as `titleGenerated`. */
221
237
  titleShort?: string | null;
222
- /** @deprecated Use `summary`. Kept as an alias populated with the same value. */
223
- contentSummary: string | null;
224
- /** @deprecated Use `titleGenerated`. Kept as an alias populated with the same value. */
225
- contentTitle?: string | null;
226
- /** @deprecated Use `titleShort`. Kept as an alias populated with the same value. */
227
- contentTitleShort?: string | null;
228
238
  url: string | null;
229
239
  media: MediaItem[];
230
240
  publishedAt: string | null;
@@ -354,12 +364,6 @@ export interface SearchReleaseHit {
354
364
  titleGenerated?: string | null;
355
365
  /** AI-generated smart-brevity headline (#852, renamed in #860). Same caveat as titleGenerated. */
356
366
  titleShort?: string | null;
357
- /** @deprecated Use `titleGenerated`. Kept as an alias populated with the same value. */
358
- contentTitle?: string | null;
359
- /** @deprecated Use `titleShort`. Kept as an alias populated with the same value. */
360
- contentTitleShort?: string | null;
361
- /** @deprecated Use `summary`. Kept as an alias populated with the same value. */
362
- contentSummary?: string;
363
367
  /**
364
368
  * Full release body, media URLs hydrated through the MEDIA_ORIGIN proxy.
365
369
  * Present so the web can render the same markdown + thumbnail treatment
@@ -693,10 +697,71 @@ export interface TaxonomyProduct {
693
697
 
694
698
  export interface CategoryDetail {
695
699
  slug: string;
700
+ /**
701
+ * Display name — operator override from the `categories` table if present,
702
+ * otherwise `categoryDisplayName(slug)` from `@buildinternet/releases-core`.
703
+ */
704
+ name: string;
705
+ /**
706
+ * Operator-authored byline shown on the web category page. Null when no
707
+ * description has been set; clients render their own fallback copy.
708
+ */
709
+ description: string | null;
710
+ /**
711
+ * Alternative slugs that redirect to this canonical category. Empty when
712
+ * no aliases have been configured.
713
+ */
714
+ aliases: string[];
696
715
  orgs: TaxonomyOrg[];
697
716
  products: TaxonomyProduct[];
698
717
  }
699
718
 
719
+ /**
720
+ * Item shape on GET /v1/categories — the overview list. Categories are a
721
+ * fixed taxonomy (`CATEGORIES` in `@buildinternet/releases-core/categories`),
722
+ * so the API always returns every slug, including ones with zero members.
723
+ * `orgCount` counts orgs whose `category` matches; `productCount` counts
724
+ * products whose own `category` matches (overriding any parent-org category).
725
+ * Both counts pass through `organizations_public`, so on_demand and
726
+ * soft-deleted orgs are excluded. `description` comes from the optional
727
+ * `categories` metadata overlay; null when no override has been set.
728
+ */
729
+ export interface CategoryListItem {
730
+ slug: string;
731
+ name: string;
732
+ description: string | null;
733
+ aliases: string[];
734
+ orgCount: number;
735
+ productCount: number;
736
+ }
737
+
738
+ /**
739
+ * PATCH /v1/categories/:slug request body. All fields are optional. `name`
740
+ * and `description` accept `null` to clear the override; `aliases` replaces
741
+ * the full set when provided (pass `[]` to clear). The row is upserted —
742
+ * a category that has never been customized has no row in the table.
743
+ *
744
+ * Each alias must be a kebab-case slug not already in `CATEGORIES` and not
745
+ * claimed by another category row.
746
+ */
747
+ export interface UpdateCategoryRequest {
748
+ name?: string | null;
749
+ description?: string | null;
750
+ aliases?: string[];
751
+ }
752
+
753
+ /**
754
+ * Aggregated release feed row for a category rollup — same wire shape as
755
+ * `CollectionReleaseItem` (both surfaces aggregate releases across multiple
756
+ * orgs). Aliased rather than duplicated so renderers can treat them as one.
757
+ */
758
+ export type CategoryReleaseItem = CollectionReleaseItem;
759
+
760
+ export interface CategoryReleasesResponse {
761
+ releases: CategoryReleaseItem[];
762
+ pagination: { nextCursor: string | null; limit: number };
763
+ }
764
+
700
765
  export interface TagDetail {
701
766
  slug: string;
702
767
  name: string;
@@ -817,12 +882,6 @@ export interface ReleaseWithSource {
817
882
  titleGenerated?: string | null;
818
883
  /** AI-generated smart-brevity headline (#852, renamed in #860). */
819
884
  titleShort?: string | null;
820
- /** @deprecated Use `summary`. Kept as an alias populated with the same value. */
821
- contentSummary: string | null;
822
- /** @deprecated Use `titleGenerated`. Kept as an alias populated with the same value. */
823
- contentTitle?: string | null;
824
- /** @deprecated Use `titleShort`. Kept as an alias populated with the same value. */
825
- contentTitleShort?: string | null;
826
885
  url: string | null;
827
886
  contentHash: string | null;
828
887
  metadata: string | null;
@@ -847,12 +906,6 @@ export interface LatestRelease {
847
906
  titleGenerated?: string | null;
848
907
  /** AI-generated smart-brevity headline (#852, renamed in #860). */
849
908
  titleShort?: string | null;
850
- /** @deprecated Use `summary`. Kept as an alias populated with the same value. */
851
- contentSummary: string | null;
852
- /** @deprecated Use `titleGenerated`. Kept as an alias populated with the same value. */
853
- contentTitle?: string | null;
854
- /** @deprecated Use `titleShort`. Kept as an alias populated with the same value. */
855
- contentTitleShort?: string | null;
856
909
  media: MediaItem[];
857
910
  }
858
911
 
@@ -47,6 +47,12 @@ export const ReleaseItemSchema = z.object({
47
47
  summary: z.string(),
48
48
  content: z.string().optional(),
49
49
  publishedAt: z.string().nullable(),
50
+ // ISO timestamp of when the row was fetched/inserted — used by the feed
51
+ // cursor's tie-break (publishedAt|fetchedAt|id) so that same-`publishedAt`
52
+ // rows stay stably ordered across paginated requests. `.optional()` because
53
+ // not every endpoint that returns a ReleaseItem populates it (notably
54
+ // single-release reads).
55
+ fetchedAt: z.string().optional(),
50
56
  url: z.string().nullable(),
51
57
  media: z.array(MediaItemSchema).optional(),
52
58
  // `.optional()` — older API responses (mid-deploy or pinned old workers)
@@ -63,12 +69,6 @@ export const ReleaseItemSchema = z.object({
63
69
  // `.optional()` for the same mid-deploy / pinned-worker reason as `type`.
64
70
  titleGenerated: z.string().nullable().optional(),
65
71
  titleShort: z.string().nullable().optional(),
66
- /** @deprecated Use `titleGenerated`. Kept as an alias populated with the same value. */
67
- contentTitle: z.string().nullable().optional(),
68
- /** @deprecated Use `titleShort`. Kept as an alias populated with the same value. */
69
- contentTitleShort: z.string().nullable().optional(),
70
- /** @deprecated Use `summary`. Kept as an alias populated with the same value. */
71
- contentSummary: z.string().nullable().optional(),
72
72
  });
73
73
 
74
74
  export const ReleaseSummaryItemSchema = z.object({