@buildinternet/releases-api-types 0.19.0 → 0.21.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.19.0",
3
+ "version": "0.21.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",
@@ -18,7 +18,7 @@
18
18
  ],
19
19
  "dependencies": {
20
20
  "@buildinternet/releases-core": "^0.21.0",
21
- "zod": "^4.3.6"
21
+ "zod": "^4.4.3"
22
22
  },
23
23
  "publishConfig": {
24
24
  "access": "public"
package/src/api-types.ts CHANGED
@@ -16,6 +16,7 @@ import type {
16
16
  StatsSchema,
17
17
  ErrorResponseSchema,
18
18
  ReleaseTypeSchema,
19
+ ReleaseCompositionSchema,
19
20
  ReleaseItemSchema,
20
21
  ReleaseSummaryItemSchema,
21
22
  OverviewPageItemSchema,
@@ -59,6 +60,7 @@ import type {
59
60
  SourceListResponseSchema,
60
61
  SourceListResultSchema,
61
62
  SourceDetailSchema,
63
+ SourceFeedPaginationSchema,
62
64
  SourceMutationResponseSchema,
63
65
  SourceOrgRefSchema,
64
66
  SourcePatchInputSchema,
@@ -222,6 +224,7 @@ export {
222
224
  StatsSchema,
223
225
  ErrorResponseSchema,
224
226
  ReleaseTypeSchema,
227
+ ReleaseCompositionSchema,
225
228
  ReleaseItemSchema,
226
229
  ReleaseSummaryItemSchema,
227
230
  OverviewPageItemSchema,
@@ -266,6 +269,7 @@ export {
266
269
  SourceListResponseSchema,
267
270
  SourceListResultSchema,
268
271
  SourceDetailSchema,
272
+ SourceFeedPaginationSchema,
269
273
  SourceMutationResponseSchema,
270
274
  SourceOrgRefSchema,
271
275
  SourcePatchInputSchema,
@@ -506,6 +510,7 @@ export type CreateSourceBody = z.infer<typeof CreateSourceBodySchema>;
506
510
  export type ChangelogFileSummary = z.infer<typeof ChangelogFileSummarySchema>;
507
511
  export type SourceChangelogResponse = z.infer<typeof SourceChangelogResponseSchema>;
508
512
  export type SourceDetail = z.infer<typeof SourceDetailSchema>;
513
+ export type SourceFeedPagination = z.infer<typeof SourceFeedPaginationSchema>;
509
514
  export type SourceMutationResponse = z.infer<typeof SourceMutationResponseSchema>;
510
515
  export type SourceOrgRef = z.infer<typeof SourceOrgRefSchema>;
511
516
  export type SourceActivityResponse = z.infer<typeof SourceActivityResponseSchema>;
@@ -571,6 +576,7 @@ export interface OrgsRollupResponse extends ListResponse<OrgsRollupRow> {
571
576
  export type ReleaseType = z.infer<typeof ReleaseTypeSchema>;
572
577
 
573
578
  export type ReleaseItem = z.infer<typeof ReleaseItemSchema>;
579
+ export type ReleaseComposition = z.infer<typeof ReleaseCompositionSchema>;
574
580
 
575
581
  export interface ReleaseDetail {
576
582
  id: string;
@@ -599,6 +605,8 @@ export interface ReleaseDetail {
599
605
  org: { slug: string; name: string } | null;
600
606
  /** Release type. See {@link ReleaseType}. */
601
607
  type?: ReleaseType;
608
+ /** Per-category item counts from the AI release-content pass. See {@link ReleaseComposition}. */
609
+ composition?: ReleaseComposition | null;
602
610
  }
603
611
 
604
612
  export type ReleaseCoverageRow = z.infer<typeof ReleaseCoverageRowSchema>;
@@ -3,6 +3,7 @@ import {
3
3
  CategorySchema,
4
4
  ListResponseSchema,
5
5
  OverviewPageItemSchema,
6
+ PaginationSchema,
6
7
  ReleaseItemSchema,
7
8
  } from "./shared.js";
8
9
  import { SourceListItemSchema } from "./sources.js";
@@ -25,7 +26,28 @@ export const OrgListItemSchema = z.object({
25
26
  sparkline: z.array(z.number().int().min(0)).length(30),
26
27
  });
27
28
 
28
- export const OrgListResponseSchema = ListResponseSchema(OrgListItemSchema);
29
+ /**
30
+ * Per-request side-channel for the orgs list (#746). `emptyOrgCount` is the
31
+ * number of orgs that match the same `q` filter but have zero indexed
32
+ * releases — used to label a "Show empty orgs" toggle without a second
33
+ * round-trip. The value is scoped by the search term but independent of
34
+ * `?includeEmpty=` so the toggle CTA can render a count whether the current
35
+ * response included empty orgs or not.
36
+ */
37
+ export const OrgListMetaSchema = z.object({
38
+ emptyOrgCount: z.number().int().min(0),
39
+ });
40
+
41
+ /**
42
+ * `meta` is optional on the wire so older workers / pinned clients mid-deploy
43
+ * don't trip the schema check. New clients can treat missing as
44
+ * `emptyOrgCount: 0` (the toggle just won't render a count).
45
+ */
46
+ export const OrgListResponseSchema = z.object({
47
+ items: z.array(OrgListItemSchema),
48
+ pagination: PaginationSchema,
49
+ meta: OrgListMetaSchema.optional(),
50
+ });
29
51
 
30
52
  export const OrgAccountItemSchema = z.object({
31
53
  platform: z.string(),
@@ -78,6 +100,8 @@ export const UpdateOrgBodySchema = z.object({
78
100
  avatarUrl: z.string().nullable().optional(),
79
101
  tags: z.array(z.string()).optional(),
80
102
  aliases: z.array(z.string()).optional(),
103
+ /** Admin-only: pause/unpause all ingest for this org without touching sources (#1057). */
104
+ fetchPaused: z.boolean().optional(),
81
105
  });
82
106
 
83
107
  // Org detail's products query selects a strict subset of `ProductListItem` —
@@ -1,6 +1,9 @@
1
1
  import { z } from "zod";
2
2
  import { SOURCE_TYPES } from "@buildinternet/releases-core/source-enums";
3
- import { MediaItemSchema, ReleaseTypeSchema } from "./shared.js";
3
+ import { MediaItemSchema, ReleaseCompositionSchema, ReleaseTypeSchema } from "./shared.js";
4
+
5
+ // ReleaseCompositionSchema lives in ./shared.js (single source of truth) — both
6
+ // this file and ReleaseItemSchema reference it from there.
4
7
 
5
8
  /**
6
9
  * Per-row shape returned by `GET /v1/releases/latest`. Distinct from the
@@ -36,6 +39,7 @@ export const ReleaseLatestItemSchema = z.object({
36
39
  // same fields on the org / collection feeds. #958.
37
40
  contentChars: z.number().int().min(0).nullable().optional(),
38
41
  contentTokens: z.number().int().min(0).nullable().optional(),
42
+ composition: ReleaseCompositionSchema.nullable().optional(),
39
43
  });
40
44
 
41
45
  export const ReleaseLatestResponseSchema = z.object({
@@ -155,6 +159,7 @@ export const ReleaseDetailResponseSchema = z.object({
155
159
  sourceSlug: z.string().nullable(),
156
160
  sourceType: z.enum(SOURCE_TYPES).nullable(),
157
161
  org: ReleaseDetailOrgSchema.nullable(),
162
+ composition: ReleaseCompositionSchema.nullable(),
158
163
  });
159
164
 
160
165
  /**
@@ -177,6 +182,8 @@ export const UpdateReleaseBodySchema = z
177
182
  summary: z.string().nullable().optional(),
178
183
  titleGenerated: z.string().nullable().optional(),
179
184
  titleShort: z.string().nullable().optional(),
185
+ // `null` removes `$.composition` from metadata; an object replaces it.
186
+ composition: ReleaseCompositionSchema.nullable().optional(),
180
187
  })
181
188
  .strict();
182
189
 
@@ -46,6 +46,19 @@ export const StatsSchema = z.object({
46
46
 
47
47
  export const ReleaseTypeSchema = z.enum(RELEASE_TYPES);
48
48
 
49
+ /**
50
+ * Per-category item counts produced by the AI release-content pass and
51
+ * persisted on `releases.metadata.composition`. Surfaces as a chip on the
52
+ * release detail UI ("12 fixes · 3 features"); `null` when the row hasn't
53
+ * been through the AI pass yet, the body was empty/boilerplate, or all
54
+ * three counts came back zero (we filter that case out on the parse side).
55
+ */
56
+ export const ReleaseCompositionSchema = z.object({
57
+ bugs: z.number().int().min(0),
58
+ features: z.number().int().min(0),
59
+ enhancements: z.number().int().min(0),
60
+ });
61
+
49
62
  export const ReleaseItemSchema = z.object({
50
63
  id: z.string().optional(),
51
64
  version: z.string().nullable(),
@@ -89,6 +102,10 @@ export const ReleaseItemSchema = z.object({
89
102
  // when null. See #958.
90
103
  contentChars: z.number().int().min(0).nullable().optional(),
91
104
  contentTokens: z.number().int().min(0).nullable().optional(),
105
+ // Per-category item counts produced by the AI release-content pass and
106
+ // stored on `releases.metadata.composition`. `null`/`undefined` when the
107
+ // row hasn't been through the AI pass yet or the body was boilerplate.
108
+ composition: ReleaseCompositionSchema.nullable().optional(),
92
109
  });
93
110
 
94
111
  export const ReleaseSummaryItemSchema = z.object({
@@ -4,12 +4,7 @@ import {
4
4
  SOURCE_DISCOVERY,
5
5
  SOURCE_FETCH_PRIORITIES,
6
6
  } from "@buildinternet/releases-core/source-enums";
7
- import {
8
- ListResponseSchema,
9
- PaginationSchema,
10
- ReleaseItemSchema,
11
- ReleaseSummaryItemSchema,
12
- } from "./shared.js";
7
+ import { ListResponseSchema, ReleaseItemSchema, ReleaseSummaryItemSchema } from "./shared.js";
13
8
 
14
9
  export const SourceTypeSchema = z.enum(SOURCE_TYPES);
15
10
  export const SourceDiscoverySchema = z.enum(SOURCE_DISCOVERY);
@@ -105,6 +100,17 @@ const SourceDetailSummariesSchema = z.object({
105
100
  monthly: z.array(ReleaseSummaryItemSchema),
106
101
  });
107
102
 
103
+ /**
104
+ * Cursor pagination shape for the source detail's embedded release feed.
105
+ * Mirrors `OrgFeedPaginationSchema` and `CollectionFeedPaginationSchema` —
106
+ * release lists are feed-shaped (append-only, mutates between calls), so they
107
+ * use cursor pagination per the AGENTS.md convention.
108
+ */
109
+ export const SourceFeedPaginationSchema = z.object({
110
+ nextCursor: z.string().nullable(),
111
+ limit: z.number().int().min(1),
112
+ });
113
+
108
114
  /**
109
115
  * Resolved attribution block returned alongside a source row. `id` is
110
116
  * additive vs the legacy `{ slug, name }` shape — older clients that ignored
@@ -149,7 +155,7 @@ export const SourceDetailSchema = z.object({
149
155
  lastPolledAt: z.string().nullable(),
150
156
  trackingSince: z.string(),
151
157
  releases: z.array(ReleaseItemSchema),
152
- pagination: PaginationSchema,
158
+ pagination: SourceFeedPaginationSchema,
153
159
  summaries: SourceDetailSummariesSchema,
154
160
  });
155
161