@buildinternet/releases-api-types 0.23.0 → 0.25.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 +1 -1
- package/src/api-types.ts +6 -0
- package/src/schemas/collections.ts +10 -0
- package/src/schemas/orgs.ts +10 -0
- package/src/schemas/products.ts +3 -0
- package/src/schemas/releases.ts +24 -1
- package/src/schemas/search.ts +6 -1
- package/src/schemas/sources.ts +32 -0
package/package.json
CHANGED
package/src/api-types.ts
CHANGED
|
@@ -64,6 +64,7 @@ import type {
|
|
|
64
64
|
SourceDetailSchema,
|
|
65
65
|
SourceFeedPaginationSchema,
|
|
66
66
|
SourceMutationResponseSchema,
|
|
67
|
+
AppStoreMaterializeResponseSchema,
|
|
67
68
|
SourceOrgRefSchema,
|
|
68
69
|
SourcePatchInputSchema,
|
|
69
70
|
CreateSourceBodySchema,
|
|
@@ -120,6 +121,7 @@ import type {
|
|
|
120
121
|
ReleaseLatestProductSchema,
|
|
121
122
|
ReleaseLatestItemSchema,
|
|
122
123
|
ReleaseLatestResponseSchema,
|
|
124
|
+
ReleaseCoverageSiblingSchema,
|
|
123
125
|
ReleaseCoverageRowSchema,
|
|
124
126
|
ReleaseCoverageResponseSchema,
|
|
125
127
|
LinkReleaseCoverageBodySchema,
|
|
@@ -288,6 +290,7 @@ export {
|
|
|
288
290
|
SourceDetailSchema,
|
|
289
291
|
SourceFeedPaginationSchema,
|
|
290
292
|
SourceMutationResponseSchema,
|
|
293
|
+
AppStoreMaterializeResponseSchema,
|
|
291
294
|
SourceOrgRefSchema,
|
|
292
295
|
SourcePatchInputSchema,
|
|
293
296
|
CreateSourceBodySchema,
|
|
@@ -370,6 +373,7 @@ export {
|
|
|
370
373
|
ReleaseLatestProductSchema,
|
|
371
374
|
ReleaseLatestItemSchema,
|
|
372
375
|
ReleaseLatestResponseSchema,
|
|
376
|
+
ReleaseCoverageSiblingSchema,
|
|
373
377
|
ReleaseCoverageRowSchema,
|
|
374
378
|
ReleaseCoverageResponseSchema,
|
|
375
379
|
LinkReleaseCoverageBodySchema,
|
|
@@ -546,6 +550,7 @@ export type SourceChangelogResponse = z.infer<typeof SourceChangelogResponseSche
|
|
|
546
550
|
export type SourceDetail = z.infer<typeof SourceDetailSchema>;
|
|
547
551
|
export type SourceFeedPagination = z.infer<typeof SourceFeedPaginationSchema>;
|
|
548
552
|
export type SourceMutationResponse = z.infer<typeof SourceMutationResponseSchema>;
|
|
553
|
+
export type AppStoreMaterializeResponse = z.infer<typeof AppStoreMaterializeResponseSchema>;
|
|
549
554
|
export type SourceOrgRef = z.infer<typeof SourceOrgRefSchema>;
|
|
550
555
|
export type SourceActivityResponse = z.infer<typeof SourceActivityResponseSchema>;
|
|
551
556
|
export type SourceHeatmapResponse = z.infer<typeof SourceHeatmapResponseSchema>;
|
|
@@ -700,6 +705,7 @@ export interface ReleaseDetail {
|
|
|
700
705
|
appStore?: { platform: "ios" | "macos"; iconUrl: string | null } | null;
|
|
701
706
|
}
|
|
702
707
|
|
|
708
|
+
export type ReleaseCoverageSibling = z.infer<typeof ReleaseCoverageSiblingSchema>;
|
|
703
709
|
export type ReleaseCoverageRow = z.infer<typeof ReleaseCoverageRowSchema>;
|
|
704
710
|
export type ReleaseCoverageResponse = z.infer<typeof ReleaseCoverageResponseSchema>;
|
|
705
711
|
export type LinkReleaseCoverageBody = z.infer<typeof LinkReleaseCoverageBodySchema>;
|
|
@@ -107,6 +107,16 @@ export const CollectionReleaseItemSchema = ReleaseItemSchema.extend({
|
|
|
107
107
|
* typecheck — clients should treat missing and `null` identically.
|
|
108
108
|
*/
|
|
109
109
|
product: z.object({ slug: z.string(), name: z.string() }).nullable().optional(),
|
|
110
|
+
/**
|
|
111
|
+
* Server-resolved grouping identity — `COALESCE(product.slug, source.slug)` /
|
|
112
|
+
* `COALESCE(product.name, source.name)`. The web release feeds key and label
|
|
113
|
+
* SDK/package-cluster rollups on these instead of reconstructing
|
|
114
|
+
* `product ?? source` client-side. Optional on the wire: older workers omit
|
|
115
|
+
* them, so clients must fall back to deriving from `product ?? source`. Never
|
|
116
|
+
* null when present (`source` is always set). #1234
|
|
117
|
+
*/
|
|
118
|
+
groupSlug: z.string().optional(),
|
|
119
|
+
groupName: z.string().optional(),
|
|
110
120
|
});
|
|
111
121
|
|
|
112
122
|
/** Cursor pagination shape matches `/v1/orgs/:slug/releases`. */
|
package/src/schemas/orgs.ts
CHANGED
|
@@ -348,6 +348,16 @@ export const OrgReleaseItemSchema = ReleaseItemSchema.extend({
|
|
|
348
348
|
* omit this field; treat `undefined` as `null`. #1217.
|
|
349
349
|
*/
|
|
350
350
|
product: z.object({ slug: z.string(), name: z.string() }).nullable().optional(),
|
|
351
|
+
/**
|
|
352
|
+
* Server-resolved grouping identity — `COALESCE(product.slug, source.slug)` /
|
|
353
|
+
* `COALESCE(product.name, source.name)`. The web releases feed keys and labels
|
|
354
|
+
* SDK/package-cluster rollups on these instead of reconstructing
|
|
355
|
+
* `product ?? source` client-side. Optional on the wire: older workers omit
|
|
356
|
+
* them, so clients must fall back to deriving from `product ?? source`. Never
|
|
357
|
+
* null when present (`source` is always set). #1234
|
|
358
|
+
*/
|
|
359
|
+
groupSlug: z.string().optional(),
|
|
360
|
+
groupName: z.string().optional(),
|
|
351
361
|
});
|
|
352
362
|
|
|
353
363
|
/** Cursor pagination shape for the org releases feed. */
|
package/src/schemas/products.ts
CHANGED
|
@@ -38,6 +38,8 @@ export type ProductCreateResponse = z.infer<typeof ProductCreateResponseSchema>;
|
|
|
38
38
|
* Per-product row returned by `GET /v1/products`. Adds `sourceCount` to
|
|
39
39
|
* the row shape but omits the internal `embeddedAt` / `deletedAt` columns
|
|
40
40
|
* (the list handler explicitly selects only the user-facing fields).
|
|
41
|
+
* `avatarUrl` (the product icon, e.g. an App Store app icon) is included so
|
|
42
|
+
* list surfaces can render the avatar without a per-row detail round-trip.
|
|
41
43
|
*/
|
|
42
44
|
export const ProductListItemSchema = z.object({
|
|
43
45
|
id: z.string(),
|
|
@@ -48,6 +50,7 @@ export const ProductListItemSchema = z.object({
|
|
|
48
50
|
description: z.string().nullable(),
|
|
49
51
|
category: CategorySchema.nullable(),
|
|
50
52
|
kind: z.enum(KIND_VALUES).nullable().optional(),
|
|
53
|
+
avatarUrl: z.string().nullable().optional(),
|
|
51
54
|
createdAt: z.string(),
|
|
52
55
|
sourceCount: z.number().int().min(0),
|
|
53
56
|
});
|
package/src/schemas/releases.ts
CHANGED
|
@@ -62,9 +62,31 @@ export const ReleaseLatestResponseSchema = z.object({
|
|
|
62
62
|
releases: z.array(ReleaseLatestItemSchema),
|
|
63
63
|
});
|
|
64
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Display fields for the counterpart release a coverage row points at —
|
|
67
|
+
* the canonical for a `coverage`-role response, or each rolled-up coverage
|
|
68
|
+
* release for a `canonical`-role response. Lets `GET /releases/:id/coverage`
|
|
69
|
+
* render a cluster without a follow-up `GET /releases/:id` per sibling.
|
|
70
|
+
* `null` when the counterpart is suppressed or its source was removed.
|
|
71
|
+
*
|
|
72
|
+
* Coverage-side rows are surfaced here on purpose, even though the
|
|
73
|
+
* `releases_visible` view (and thus `GET /releases/:id`) hides them — a
|
|
74
|
+
* cluster view's whole job is to show its members.
|
|
75
|
+
*/
|
|
76
|
+
export const ReleaseCoverageSiblingSchema = z.object({
|
|
77
|
+
id: z.string(),
|
|
78
|
+
version: z.string().nullable(),
|
|
79
|
+
title: z.string(),
|
|
80
|
+
sourceName: z.string(),
|
|
81
|
+
publishedAt: z.string().nullable(),
|
|
82
|
+
org: z.object({ slug: z.string(), name: z.string() }).nullable(),
|
|
83
|
+
});
|
|
84
|
+
|
|
65
85
|
/**
|
|
66
86
|
* Single row of the `release_coverage` join table. Drives the
|
|
67
|
-
* GET /releases/:id/coverage response.
|
|
87
|
+
* GET /releases/:id/coverage response. `sibling` carries the counterpart
|
|
88
|
+
* release's display fields (see {@link ReleaseCoverageSiblingSchema}); it is
|
|
89
|
+
* optional so an older server that doesn't populate it still validates.
|
|
68
90
|
*/
|
|
69
91
|
export const ReleaseCoverageRowSchema = z.object({
|
|
70
92
|
coverageId: z.string(),
|
|
@@ -72,6 +94,7 @@ export const ReleaseCoverageRowSchema = z.object({
|
|
|
72
94
|
reason: z.string().nullable(),
|
|
73
95
|
decidedBy: z.string(),
|
|
74
96
|
decidedAt: z.string(),
|
|
97
|
+
sibling: ReleaseCoverageSiblingSchema.nullable().optional(),
|
|
75
98
|
});
|
|
76
99
|
|
|
77
100
|
/**
|
package/src/schemas/search.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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 { AppStoreSourceInfoSchema, MediaItemSchema, ReleaseTypeSchema } from "./shared.js";
|
|
4
4
|
import { SourceTypeSchema } from "./sources.js";
|
|
5
5
|
import { LookupStatusSchema } from "./lookups.js";
|
|
6
6
|
|
|
@@ -66,6 +66,11 @@ export const SearchReleaseHitSchema = z.object({
|
|
|
66
66
|
// without re-validating; legacy rows occasionally drift from the
|
|
67
67
|
// canonical four-value set. Used by the web byline icon.
|
|
68
68
|
sourceType: z.string().optional(),
|
|
69
|
+
/**
|
|
70
|
+
* App Store platform + icon for `type: "appstore"` sources, null/absent
|
|
71
|
+
* otherwise. Powers the compact app-update treatment on the search card. #1206
|
|
72
|
+
*/
|
|
73
|
+
appStore: AppStoreSourceInfoSchema.nullable().optional(),
|
|
69
74
|
orgSlug: z.string().nullable(),
|
|
70
75
|
orgName: z.string().nullable().optional(),
|
|
71
76
|
/** Owning product slug — present when the source belongs to a product. Lets
|
package/src/schemas/sources.ts
CHANGED
|
@@ -194,6 +194,38 @@ export const SourceMutationResponseSchema = z.looseObject({
|
|
|
194
194
|
kind: z.enum(KIND_VALUES).nullable().optional(),
|
|
195
195
|
});
|
|
196
196
|
|
|
197
|
+
/**
|
|
198
|
+
* Response from `POST /v1/sources/appstore` — materializes an App Store listing
|
|
199
|
+
* into a curated Org → Product → Source → first Release (modeled on the GitHub
|
|
200
|
+
* coordinate `LookupResponse`).
|
|
201
|
+
*
|
|
202
|
+
* Unlike `SourceMutationResponse`, the `source` here is the **bare inserted (or
|
|
203
|
+
* idempotently looked-up) drizzle row** the materialize handler returns verbatim:
|
|
204
|
+
* no resolved `org { id, slug, name }` block and no `productSlug`. `loose` so the
|
|
205
|
+
* untyped timestamp/counter columns on the row pass through.
|
|
206
|
+
*
|
|
207
|
+
* `status: "indexed"` is a brand-new source (HTTP 201); `"existing"` is the
|
|
208
|
+
* idempotent hit on a prior materialize of the same trackId (HTTP 200).
|
|
209
|
+
*/
|
|
210
|
+
export const AppStoreMaterializeResponseSchema = z.object({
|
|
211
|
+
status: z.enum(["indexed", "existing"]),
|
|
212
|
+
source: z.looseObject({
|
|
213
|
+
id: z.string(),
|
|
214
|
+
slug: z.string(),
|
|
215
|
+
name: z.string(),
|
|
216
|
+
type: SourceTypeSchema,
|
|
217
|
+
url: z.string(),
|
|
218
|
+
orgId: z.string().nullable(),
|
|
219
|
+
productId: z.string().nullable(),
|
|
220
|
+
metadata: z.string().nullable(),
|
|
221
|
+
kind: z.enum(KIND_VALUES).nullable().optional(),
|
|
222
|
+
discovery: SourceDiscoverySchema.optional(),
|
|
223
|
+
isHidden: z.boolean().nullable().optional(),
|
|
224
|
+
createdAt: z.string().optional(),
|
|
225
|
+
}),
|
|
226
|
+
releaseCount: z.number(),
|
|
227
|
+
});
|
|
228
|
+
|
|
197
229
|
/** Body accepted by `PATCH /v1/sources/:slug`. */
|
|
198
230
|
export const SourcePatchInputSchema = z.object({
|
|
199
231
|
name: z.string().optional(),
|