@buildinternet/releases-api-types 0.59.0 → 0.60.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/README.md +14 -6
- package/dist/api-types.d.ts +1168 -0
- package/dist/api-types.d.ts.map +1 -0
- package/dist/api-types.js +134 -0
- package/dist/schemas/account-profile.d.ts +29 -0
- package/dist/schemas/account-profile.d.ts.map +1 -0
- package/dist/schemas/account-profile.js +24 -0
- package/dist/schemas/ai-models.d.ts +67 -0
- package/dist/schemas/ai-models.d.ts.map +1 -0
- package/{src/schemas/ai-models.ts → dist/schemas/ai-models.js} +25 -31
- package/dist/schemas/api-keys.d.ts +71 -0
- package/dist/schemas/api-keys.d.ts.map +1 -0
- package/dist/schemas/api-keys.js +32 -0
- package/dist/schemas/classifications.d.ts +134 -0
- package/dist/schemas/classifications.d.ts.map +1 -0
- package/dist/schemas/classifications.js +96 -0
- package/dist/schemas/collections.d.ts +605 -0
- package/dist/schemas/collections.d.ts.map +1 -0
- package/dist/schemas/collections.js +320 -0
- package/dist/schemas/datasets.d.ts +34 -0
- package/dist/schemas/datasets.d.ts.map +1 -0
- package/dist/schemas/datasets.js +11 -0
- package/dist/schemas/errors.d.ts +43 -0
- package/dist/schemas/errors.d.ts.map +1 -0
- package/dist/schemas/errors.js +61 -0
- package/dist/schemas/feedback.d.ts +134 -0
- package/dist/schemas/feedback.d.ts.map +1 -0
- package/dist/schemas/feedback.js +76 -0
- package/dist/schemas/follows.d.ts +154 -0
- package/dist/schemas/follows.d.ts.map +1 -0
- package/dist/schemas/follows.js +42 -0
- package/dist/schemas/listing.d.ts +374 -0
- package/dist/schemas/listing.d.ts.map +1 -0
- package/dist/schemas/listing.js +175 -0
- package/dist/schemas/lookups.d.ts +285 -0
- package/dist/schemas/lookups.d.ts.map +1 -0
- package/{src/schemas/lookups.ts → dist/schemas/lookups.js} +67 -80
- package/dist/schemas/marketing-classifier.d.ts +32 -0
- package/dist/schemas/marketing-classifier.d.ts.map +1 -0
- package/{src/schemas/marketing-classifier.ts → dist/schemas/marketing-classifier.js} +14 -18
- package/dist/schemas/orgs.d.ts +950 -0
- package/dist/schemas/orgs.d.ts.map +1 -0
- package/dist/schemas/orgs.js +473 -0
- package/dist/schemas/overviews.d.ts +205 -0
- package/dist/schemas/overviews.d.ts.map +1 -0
- package/{src/schemas/overviews.ts → dist/schemas/overviews.js} +41 -54
- package/dist/schemas/products.d.ts +595 -0
- package/dist/schemas/products.d.ts.map +1 -0
- package/{src/schemas/products.ts → dist/schemas/products.js} +113 -136
- package/dist/schemas/publish-tokens.d.ts +55 -0
- package/dist/schemas/publish-tokens.d.ts.map +1 -0
- package/{src/schemas/publish-tokens.ts → dist/schemas/publish-tokens.js} +18 -29
- package/dist/schemas/recommendations.d.ts +52 -0
- package/dist/schemas/recommendations.d.ts.map +1 -0
- package/dist/schemas/recommendations.js +58 -0
- package/dist/schemas/related.d.ts +331 -0
- package/dist/schemas/related.d.ts.map +1 -0
- package/dist/schemas/related.js +115 -0
- package/dist/schemas/releases.d.ts +623 -0
- package/dist/schemas/releases.d.ts.map +1 -0
- package/dist/schemas/releases.js +414 -0
- package/dist/schemas/resolve.d.ts +259 -0
- package/dist/schemas/resolve.d.ts.map +1 -0
- package/{src/schemas/resolve.ts → dist/schemas/resolve.js} +2 -5
- package/dist/schemas/search.d.ts +475 -0
- package/dist/schemas/search.d.ts.map +1 -0
- package/dist/schemas/search.js +258 -0
- package/dist/schemas/semantic-alert-summary.d.ts +54 -0
- package/dist/schemas/semantic-alert-summary.d.ts.map +1 -0
- package/dist/schemas/semantic-alert-summary.js +57 -0
- package/dist/schemas/semantic-alerts.d.ts +41 -0
- package/dist/schemas/semantic-alerts.d.ts.map +1 -0
- package/dist/schemas/semantic-alerts.js +42 -0
- package/dist/schemas/shared.d.ts +247 -0
- package/dist/schemas/shared.d.ts.map +1 -0
- package/dist/schemas/shared.js +248 -0
- package/dist/schemas/site-notice.d.ts +35 -0
- package/dist/schemas/site-notice.d.ts.map +1 -0
- package/{src/schemas/site-notice.ts → dist/schemas/site-notice.js} +14 -18
- package/dist/schemas/sitemap.d.ts +97 -0
- package/dist/schemas/sitemap.d.ts.map +1 -0
- package/dist/schemas/sitemap.js +107 -0
- package/dist/schemas/sources.d.ts +1145 -0
- package/dist/schemas/sources.d.ts.map +1 -0
- package/dist/schemas/sources.js +645 -0
- package/dist/schemas/stats.d.ts +82 -0
- package/dist/schemas/stats.d.ts.map +1 -0
- package/dist/schemas/stats.js +59 -0
- package/dist/schemas/taxonomy.d.ts +344 -0
- package/dist/schemas/taxonomy.d.ts.map +1 -0
- package/{src/schemas/taxonomy.ts → dist/schemas/taxonomy.js} +47 -58
- package/dist/schemas/webhooks.d.ts +618 -0
- package/dist/schemas/webhooks.d.ts.map +1 -0
- package/dist/schemas/webhooks.js +191 -0
- package/dist/schemas/well-known.d.ts +302 -0
- package/dist/schemas/well-known.d.ts.map +1 -0
- package/dist/schemas/well-known.js +192 -0
- package/dist/schemas/workspace-integrations.d.ts +27 -0
- package/dist/schemas/workspace-integrations.d.ts.map +1 -0
- package/dist/schemas/workspace-integrations.js +22 -0
- package/package.json +16 -5
- package/src/api-types.ts +0 -2229
- package/src/schemas/account-profile.ts +0 -28
- package/src/schemas/ai-models.test.ts +0 -29
- package/src/schemas/classifications.ts +0 -109
- package/src/schemas/collections.ts +0 -346
- package/src/schemas/datasets.ts +0 -31
- package/src/schemas/errors.test.ts +0 -55
- package/src/schemas/errors.ts +0 -81
- package/src/schemas/feedback.ts +0 -56
- package/src/schemas/listing.ts +0 -226
- package/src/schemas/orgs.ts +0 -533
- package/src/schemas/recommendations.ts +0 -39
- package/src/schemas/related.ts +0 -126
- package/src/schemas/releases.ts +0 -449
- package/src/schemas/search.ts +0 -274
- package/src/schemas/semantic-alert-summary.ts +0 -65
- package/src/schemas/shared.notice.test.ts +0 -36
- package/src/schemas/shared.ts +0 -267
- package/src/schemas/site-notice.test.ts +0 -67
- package/src/schemas/sitemap.ts +0 -117
- package/src/schemas/sources.ts +0 -674
- package/src/schemas/stats.ts +0 -62
- package/src/schemas/well-known.test.ts +0 -264
- package/src/schemas/well-known.ts +0 -252
- package/src/schemas/workspace-integrations.ts +0 -26
package/src/schemas/releases.ts
DELETED
|
@@ -1,449 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { SOURCE_TYPES } from "@buildinternet/releases-core/source-enums";
|
|
3
|
-
import { BREAKING_LEVELS } from "@buildinternet/releases-core/breaking";
|
|
4
|
-
import { KIND_VALUES } from "@buildinternet/releases-core/kinds";
|
|
5
|
-
import {
|
|
6
|
-
AppStoreSourceInfoSchema,
|
|
7
|
-
ImportanceScoreSchema,
|
|
8
|
-
MediaItemSchema,
|
|
9
|
-
ReleaseCompositionSchema,
|
|
10
|
-
ReleaseThumbnailSchema,
|
|
11
|
-
ReleaseTypeSchema,
|
|
12
|
-
VideoSourceInfoSchema,
|
|
13
|
-
} from "./shared.js";
|
|
14
|
-
|
|
15
|
-
// ReleaseCompositionSchema lives in ./shared.js (single source of truth) — both
|
|
16
|
-
// this file and ReleaseItemSchema reference it from there.
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Per-row shape returned by `GET /v1/releases/latest`. Distinct from the
|
|
20
|
-
* shared `ReleaseItemSchema` because the latest-feed handler joins the
|
|
21
|
-
* source row in and exposes it as a nested `source` object instead of
|
|
22
|
-
* leaving the caller to do a second lookup.
|
|
23
|
-
*
|
|
24
|
-
* `type` is required here — the latest handler reads it directly from
|
|
25
|
-
* `releases.type` (NOT NULL with DB-default `'feature'`), so mid-deploy
|
|
26
|
-
* degrade-gracefully nullability doesn't apply on this path.
|
|
27
|
-
*/
|
|
28
|
-
export const ReleaseLatestSourceSchema = z.object({
|
|
29
|
-
slug: z.string(),
|
|
30
|
-
name: z.string(),
|
|
31
|
-
type: z.enum(SOURCE_TYPES),
|
|
32
|
-
orgSlug: z.string().nullable(),
|
|
33
|
-
/** Owning org's display name (e.g. "Cloudflare"), distinct from the source
|
|
34
|
-
* name. Null when the source has no org. Additive — older responses omit it. */
|
|
35
|
-
orgName: z.string().nullable().optional(),
|
|
36
|
-
/** Owning org's explicit avatar URL (`organizations.avatar_url`), when set.
|
|
37
|
-
* Null/absent when the org has no stored avatar — clients fall back to the
|
|
38
|
-
* GitHub handle below, then an initial. Additive — older responses omit it. */
|
|
39
|
-
orgAvatarUrl: z.string().nullable().optional(),
|
|
40
|
-
/** Owning org's GitHub handle, used to derive `github.com/<handle>.png` as the
|
|
41
|
-
* avatar fallback when `orgAvatarUrl` is unset. Additive — older responses omit it. */
|
|
42
|
-
orgGithubHandle: z.string().nullable().optional(),
|
|
43
|
-
/** Source classification (`sdk`, `platform`, `docs`, …) from `sources.kind`.
|
|
44
|
-
* Null when the source has no explicit kind — resolve against the product's
|
|
45
|
-
* kind via `resolveSourceKind`. Additive — older responses omit it. Lets read
|
|
46
|
-
* surfaces (e.g. the digest email) deprioritize/cluster SDK releases the way
|
|
47
|
-
* the web sources table does. */
|
|
48
|
-
kind: z.enum(KIND_VALUES).nullable().optional(),
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
export const ReleaseLatestProductSchema = z.object({
|
|
52
|
-
slug: z.string(),
|
|
53
|
-
name: z.string(),
|
|
54
|
-
/** Product classification from `products.kind`; the fallback `resolveSourceKind`
|
|
55
|
-
* consults when the source itself has no kind. Additive — older responses omit it. */
|
|
56
|
-
kind: z.enum(KIND_VALUES).nullable().optional(),
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
export const ReleaseLatestItemSchema = z.object({
|
|
60
|
-
id: z.string(),
|
|
61
|
-
version: z.string().nullable(),
|
|
62
|
-
type: ReleaseTypeSchema,
|
|
63
|
-
title: z.string(),
|
|
64
|
-
summary: z.string().nullable(),
|
|
65
|
-
titleGenerated: z.string().nullable(),
|
|
66
|
-
titleShort: z.string().nullable(),
|
|
67
|
-
/**
|
|
68
|
-
* Machine-readable breaking-change level (#1696, surfaced on read paths in
|
|
69
|
-
* #1710). `.optional()` for mid-deploy / pinned-worker tolerance and because
|
|
70
|
-
* rows predating the column omit it; absent or `"unknown"` means not
|
|
71
|
-
* classified (the fail-open default). List paths carry `breaking` only —
|
|
72
|
-
* `migrationNotes` stays detail-route-only to keep list payloads slim.
|
|
73
|
-
*/
|
|
74
|
-
breaking: z.enum(BREAKING_LEVELS).optional(),
|
|
75
|
-
importance: ImportanceScoreSchema,
|
|
76
|
-
publishedAt: z.string().nullable(),
|
|
77
|
-
/** Original source URL. Primary citation link; `webUrl` is the releases.sh copy. */
|
|
78
|
-
url: z.string().nullable(),
|
|
79
|
-
/**
|
|
80
|
-
* releases.sh detail-page URL (friendly form: ID + current title slug).
|
|
81
|
-
* Secondary to `url`. Additive — older servers and the digest-cron path omit it.
|
|
82
|
-
*/
|
|
83
|
-
webUrl: z.string().optional(),
|
|
84
|
-
media: z.array(MediaItemSchema),
|
|
85
|
-
source: ReleaseLatestSourceSchema,
|
|
86
|
-
/**
|
|
87
|
-
* Owning product, when the release's source is grouped under a product.
|
|
88
|
-
* `null` when the source has no `product_id`. Additive — older API responses
|
|
89
|
-
* omit this field; treat `undefined` as `null`. #1217.
|
|
90
|
-
*/
|
|
91
|
-
product: ReleaseLatestProductSchema.nullable().optional(),
|
|
92
|
-
/**
|
|
93
|
-
* Server-resolved grouping identity — `product.slug ?? source.slug` /
|
|
94
|
-
* `product.name ?? source.name`. The web releases feed keys and labels
|
|
95
|
-
* SDK/package-cluster rollups on these instead of reconstructing
|
|
96
|
-
* `product ?? source` client-side; the digest email mirrors that. Optional on
|
|
97
|
-
* the wire: older workers omit them, so clients fall back to deriving from
|
|
98
|
-
* `product ?? source`. Never null when present (`source` is always set). #1234
|
|
99
|
-
*/
|
|
100
|
-
groupSlug: z.string().optional(),
|
|
101
|
-
groupName: z.string().optional(),
|
|
102
|
-
coverageCount: z.number().int().min(0).optional(),
|
|
103
|
-
// Cached release-body size hint — see {@link ReleaseItemSchema} for the
|
|
104
|
-
// same fields on the org / collection feeds. #958.
|
|
105
|
-
contentChars: z.number().int().min(0).nullable().optional(),
|
|
106
|
-
contentTokens: z.number().int().min(0).nullable().optional(),
|
|
107
|
-
composition: ReleaseCompositionSchema.nullable().optional(),
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
export const ReleaseLatestResponseSchema = z.object({
|
|
111
|
-
releases: z.array(ReleaseLatestItemSchema),
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Display fields for the counterpart release a coverage row points at —
|
|
116
|
-
* the canonical for a `coverage`-role response, or each rolled-up coverage
|
|
117
|
-
* release for a `canonical`-role response. Lets `GET /releases/:id/coverage`
|
|
118
|
-
* render a cluster without a follow-up `GET /releases/:id` per sibling.
|
|
119
|
-
* `null` when the counterpart is suppressed or its source was removed.
|
|
120
|
-
*
|
|
121
|
-
* Coverage-side rows are surfaced here on purpose, even though the
|
|
122
|
-
* `releases_visible` view (and thus `GET /releases/:id`) hides them — a
|
|
123
|
-
* cluster view's whole job is to show its members.
|
|
124
|
-
*/
|
|
125
|
-
export const ReleaseCoverageSiblingSchema = z.object({
|
|
126
|
-
id: z.string(),
|
|
127
|
-
version: z.string().nullable(),
|
|
128
|
-
title: z.string(),
|
|
129
|
-
sourceName: z.string(),
|
|
130
|
-
publishedAt: z.string().nullable(),
|
|
131
|
-
org: z.object({ slug: z.string(), name: z.string() }).nullable(),
|
|
132
|
-
/** First image/gif thumbnail for the counterpart release; null when it has
|
|
133
|
-
* none. Optional so an older server that omits it still validates. */
|
|
134
|
-
thumbnail: ReleaseThumbnailSchema.nullable().optional(),
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Single row of the `release_coverage` join table. Drives the
|
|
139
|
-
* GET /releases/:id/coverage response. `sibling` carries the counterpart
|
|
140
|
-
* release's display fields (see {@link ReleaseCoverageSiblingSchema}); it is
|
|
141
|
-
* optional so an older server that doesn't populate it still validates.
|
|
142
|
-
*/
|
|
143
|
-
export const ReleaseCoverageRowSchema = z.object({
|
|
144
|
-
coverageId: z.string(),
|
|
145
|
-
canonicalId: z.string(),
|
|
146
|
-
reason: z.string().nullable(),
|
|
147
|
-
decidedBy: z.string(),
|
|
148
|
-
decidedAt: z.string(),
|
|
149
|
-
sibling: ReleaseCoverageSiblingSchema.nullable().optional(),
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Discriminated by `role`:
|
|
154
|
-
* - `standalone` — release is neither canonical nor coverage of anything.
|
|
155
|
-
* - `coverage` — release is coverage rolling up to `canonical`.
|
|
156
|
-
* - `canonical` — release is the canonical row; `covers` enumerates rollups.
|
|
157
|
-
*/
|
|
158
|
-
export const ReleaseCoverageResponseSchema = z.discriminatedUnion("role", [
|
|
159
|
-
z.object({
|
|
160
|
-
role: z.literal("standalone"),
|
|
161
|
-
canonical: z.null(),
|
|
162
|
-
covers: z.array(z.never()).length(0),
|
|
163
|
-
}),
|
|
164
|
-
z.object({
|
|
165
|
-
role: z.literal("coverage"),
|
|
166
|
-
canonical: ReleaseCoverageRowSchema,
|
|
167
|
-
covers: z.array(z.never()).length(0),
|
|
168
|
-
}),
|
|
169
|
-
z.object({
|
|
170
|
-
role: z.literal("canonical"),
|
|
171
|
-
canonical: z.null(),
|
|
172
|
-
covers: z.array(ReleaseCoverageRowSchema),
|
|
173
|
-
}),
|
|
174
|
-
]);
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Body accepted by `POST /v1/releases/:id/coverage`. `decidedBy` MUST be
|
|
178
|
-
* prefixed with `human:` or `agent:` so the audit trail records who linked
|
|
179
|
-
* the rows; the handler enforces this with a regex.
|
|
180
|
-
*/
|
|
181
|
-
export const LinkReleaseCoverageBodySchema = z.object({
|
|
182
|
-
coverageIds: z.array(z.string()).min(1),
|
|
183
|
-
reason: z.string().nullable().optional(),
|
|
184
|
-
decidedBy: z.string().regex(/^(human:|agent:)/),
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
export const LinkReleaseCoverageResponseSchema = z.object({
|
|
188
|
-
canonicalId: z.string(),
|
|
189
|
-
coverageIds: z.array(z.string()),
|
|
190
|
-
linked: z.number().int().min(0),
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Response for `DELETE /v1/releases/:id/coverage`. Idempotent — the handler
|
|
195
|
-
* returns `{ unlinked: false }` when the release isn't in a cluster, so the
|
|
196
|
-
* remote client can skip a brittle error-message sniff.
|
|
197
|
-
*/
|
|
198
|
-
export const UnlinkReleaseCoverageResponseSchema = z.object({
|
|
199
|
-
unlinked: z.boolean(),
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Row returned by `GET /v1/releases?hasMedia=true`. Internal/admin escape
|
|
204
|
-
* hatch consumed by the `media backfill` CLI command.
|
|
205
|
-
*/
|
|
206
|
-
export const ReleaseWithMediaRowSchema = z.object({
|
|
207
|
-
id: z.string(),
|
|
208
|
-
sourceId: z.string(),
|
|
209
|
-
media: z.string().nullable(),
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
export const ReleasesWithMediaResponseSchema = z.array(ReleaseWithMediaRowSchema);
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Nested org context joined into the `GET /v1/releases/:id` response.
|
|
216
|
-
* Both fields are nullable — releases whose source has no org attached
|
|
217
|
-
* return `null` for this object entirely.
|
|
218
|
-
*/
|
|
219
|
-
export const ReleaseDetailOrgSchema = z.object({
|
|
220
|
-
slug: z.string(),
|
|
221
|
-
name: z.string(),
|
|
222
|
-
/**
|
|
223
|
-
* Resolved org avatar URL (the `organizations.avatar_url` column). `null`
|
|
224
|
-
* when the org has no stored avatar. Additive — older servers omit it, so
|
|
225
|
-
* treat `undefined` as `null`. Mirrors the `orgAvatarUrl` field on the
|
|
226
|
-
* related-rail feed.
|
|
227
|
-
*/
|
|
228
|
-
avatarUrl: z.string().nullable().optional(),
|
|
229
|
-
/**
|
|
230
|
-
* How the org was created. Additive — older servers omit it; treat
|
|
231
|
-
* `undefined` as `"curated"`. Used by the web to emit `noindex` on
|
|
232
|
-
* on-demand-materialized org pages.
|
|
233
|
-
*/
|
|
234
|
-
discovery: z.enum(["curated", "agent", "on_demand"]).optional(),
|
|
235
|
-
/**
|
|
236
|
-
* Whether the org is hidden from public listings. Additive — older servers
|
|
237
|
-
* omit it; treat `undefined` as `false`. Used by the web to emit `noindex`.
|
|
238
|
-
*/
|
|
239
|
-
isHidden: z.boolean().optional(),
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Full release detail returned by `GET /v1/releases/:id`. Joins source
|
|
244
|
-
* name/slug/type and a nullable org object; media is parsed from the raw
|
|
245
|
-
* JSON stored in D1 and typed URLs are rewritten to the CDN origin. The
|
|
246
|
-
* route only surfaces non-suppressed, non-coverage rows (filtered via the
|
|
247
|
-
* `releases_visible` view).
|
|
248
|
-
*/
|
|
249
|
-
export const ReleaseDetailResponseSchema = z.object({
|
|
250
|
-
id: z.string(),
|
|
251
|
-
sourceId: z.string(),
|
|
252
|
-
version: z.string().nullable(),
|
|
253
|
-
type: ReleaseTypeSchema,
|
|
254
|
-
title: z.string(),
|
|
255
|
-
content: z.string(),
|
|
256
|
-
summary: z.string().nullable(),
|
|
257
|
-
titleGenerated: z.string().nullable(),
|
|
258
|
-
titleShort: z.string().nullable(),
|
|
259
|
-
/**
|
|
260
|
-
* Machine-readable breaking-change level (#1696, surfaced on read paths in
|
|
261
|
-
* #1710). `.optional()` — rows predating the column omit it; absent or
|
|
262
|
-
* `"unknown"` means not classified (the fail-open default). Mirrors
|
|
263
|
-
* `ReleaseDetail.breaking` in api-types.ts.
|
|
264
|
-
*/
|
|
265
|
-
breaking: z.enum(BREAKING_LEVELS).optional(),
|
|
266
|
-
importance: ImportanceScoreSchema,
|
|
267
|
-
/**
|
|
268
|
-
* Explicit upgrade/migration steps lifted from the body (#1696); omitted
|
|
269
|
-
* when the body gives none. Detail-route-only — list paths never carry it.
|
|
270
|
-
*/
|
|
271
|
-
migrationNotes: z.string().nullable().optional(),
|
|
272
|
-
/** Original source URL. Primary citation link; `webUrl` is the releases.sh copy. */
|
|
273
|
-
url: z.string().nullable(),
|
|
274
|
-
/**
|
|
275
|
-
* releases.sh detail-page URL, `https://releases.sh/release/rel_<id>-<slug>`
|
|
276
|
-
* (immutable ID + current title slug). Secondary to `url`. Additive — older
|
|
277
|
-
* servers omit it.
|
|
278
|
-
*/
|
|
279
|
-
webUrl: z.string().optional(),
|
|
280
|
-
contentHash: z.string().nullable(),
|
|
281
|
-
media: z.array(MediaItemSchema),
|
|
282
|
-
publishedAt: z.string().nullable(),
|
|
283
|
-
suppressed: z.boolean().nullable(),
|
|
284
|
-
suppressedReason: z.string().nullable(),
|
|
285
|
-
prerelease: z.boolean().nullable(),
|
|
286
|
-
fetchedAt: z.string().nullable(),
|
|
287
|
-
sourceName: z.string().nullable(),
|
|
288
|
-
sourceSlug: z.string().nullable(),
|
|
289
|
-
sourceType: z.enum(SOURCE_TYPES).nullable(),
|
|
290
|
-
org: ReleaseDetailOrgSchema.nullable(),
|
|
291
|
-
/**
|
|
292
|
-
* Owning product, when the release's source is grouped under a product
|
|
293
|
-
* (`sources.product_id`). `null` when the source has no product. Additive —
|
|
294
|
-
* older servers omit this field; treat `undefined` as `null`. Reuses the
|
|
295
|
-
* `{ slug, name }` shape from the latest feed.
|
|
296
|
-
*/
|
|
297
|
-
product: ReleaseLatestProductSchema.nullable().optional(),
|
|
298
|
-
composition: ReleaseCompositionSchema.nullable(),
|
|
299
|
-
appStore: AppStoreSourceInfoSchema.nullable().optional(),
|
|
300
|
-
video: VideoSourceInfoSchema.nullable().optional(),
|
|
301
|
-
/**
|
|
302
|
-
* Whether the release's source is hidden from public listings. Additive —
|
|
303
|
-
* older servers omit it; treat `undefined` as `false`. Used by the web to
|
|
304
|
-
* emit `noindex` on pages whose source is an on-demand-materialized stub.
|
|
305
|
-
*/
|
|
306
|
-
sourceIsHidden: z.boolean().optional(),
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
/**
|
|
310
|
-
* Body accepted by `PATCH /v1/releases/:id`. All fields are optional;
|
|
311
|
-
* omitted fields are not updated. The nullable string columns (`version`,
|
|
312
|
-
* `url`, `publishedAt`, `contentHash`) accept a string or `null`. AI-generated
|
|
313
|
-
* fields (`summary`, `titleGenerated`, `titleShort`) accept `null` to
|
|
314
|
-
* explicitly clear the stored value. Non-whitelisted fields are rejected
|
|
315
|
-
* via `.strict()` — the handler also re-runs the field-set check after
|
|
316
|
-
* sanitization so an empty update payload still 400s.
|
|
317
|
-
*/
|
|
318
|
-
/**
|
|
319
|
-
* `error.details` on a 409 from `PATCH /v1/releases/:id` when the new `url`
|
|
320
|
-
* collides with `UNIQUE(source_id, url)`. Additive: older servers omit `details`.
|
|
321
|
-
*/
|
|
322
|
-
export const ReleaseUrlConflictDetailsSchema = z
|
|
323
|
-
.object({
|
|
324
|
-
releaseId: z
|
|
325
|
-
.string()
|
|
326
|
-
.describe("Id of the existing release that already stores this URL on the same source."),
|
|
327
|
-
})
|
|
328
|
-
.describe("Structured details for a release URL conflict (409).");
|
|
329
|
-
|
|
330
|
-
export const UpdateReleaseBodySchema = z
|
|
331
|
-
.object({
|
|
332
|
-
title: z.string().optional(),
|
|
333
|
-
content: z.string().optional(),
|
|
334
|
-
version: z.string().nullable().optional(),
|
|
335
|
-
url: z.string().nullable().optional(),
|
|
336
|
-
publishedAt: z.string().nullable().optional(),
|
|
337
|
-
contentHash: z.string().nullable().optional(),
|
|
338
|
-
summary: z.string().nullable().optional(),
|
|
339
|
-
titleGenerated: z.string().nullable().optional(),
|
|
340
|
-
titleShort: z.string().nullable().optional(),
|
|
341
|
-
// `null` removes `$.composition` from metadata; an object replaces it.
|
|
342
|
-
composition: ReleaseCompositionSchema.nullable().optional(),
|
|
343
|
-
// Replace the release's stored `media[]` wholesale (curator manual edit).
|
|
344
|
-
// Items whose `url` is not already an R2/`media.releases.sh` origin are run
|
|
345
|
-
// through the ingest R2 mirror (`processMediaForR2`) so posters/images land
|
|
346
|
-
// in `released-media` and get `r2Key`/`r2Url` stamped — same path as ingest.
|
|
347
|
-
// Reuses the shared `MediaItemSchema` (type/url/alt/r2Url/r2Key/linkUrl).
|
|
348
|
-
media: z.array(MediaItemSchema).optional(),
|
|
349
|
-
})
|
|
350
|
-
.strict();
|
|
351
|
-
|
|
352
|
-
/**
|
|
353
|
-
* Response returned by `PATCH /v1/releases/:id`. The handler returns the raw
|
|
354
|
-
* Drizzle row from the `releases` table — distinct from the augmented
|
|
355
|
-
* `ReleaseDetailResponseSchema` shape served by `GET /v1/releases/:id`, which
|
|
356
|
-
* adds joined source/org metadata and parses `media` from raw JSON. Clients
|
|
357
|
-
* that need the augmented shape after an edit should re-fetch via GET.
|
|
358
|
-
*/
|
|
359
|
-
export const ReleasePatchResponseSchema = z.object({
|
|
360
|
-
id: z.string(),
|
|
361
|
-
sourceId: z.string(),
|
|
362
|
-
version: z.string().nullable(),
|
|
363
|
-
type: ReleaseTypeSchema,
|
|
364
|
-
title: z.string(),
|
|
365
|
-
content: z.string(),
|
|
366
|
-
summary: z.string().nullable(),
|
|
367
|
-
titleGenerated: z.string().nullable(),
|
|
368
|
-
titleShort: z.string().nullable(),
|
|
369
|
-
url: z.string().nullable(),
|
|
370
|
-
contentHash: z.string().nullable(),
|
|
371
|
-
metadata: z.string().nullable(),
|
|
372
|
-
// Raw JSON string of the media array — not parsed at this endpoint.
|
|
373
|
-
media: z.string().nullable(),
|
|
374
|
-
publishedAt: z.string().nullable(),
|
|
375
|
-
prerelease: z.boolean().nullable(),
|
|
376
|
-
suppressed: z.boolean().nullable(),
|
|
377
|
-
suppressedReason: z.string().nullable(),
|
|
378
|
-
fetchedAt: z.string().nullable(),
|
|
379
|
-
embeddedAt: z.string().nullable(),
|
|
380
|
-
});
|
|
381
|
-
|
|
382
|
-
/** Response returned by `DELETE /v1/releases/:id`. */
|
|
383
|
-
export const ReleaseDeleteResponseSchema = z.object({
|
|
384
|
-
deleted: z.literal(true),
|
|
385
|
-
});
|
|
386
|
-
|
|
387
|
-
/** Body accepted by `DELETE /v1/releases/batch`. */
|
|
388
|
-
export const ReleaseBatchDeleteBodySchema = z.object({
|
|
389
|
-
releaseIds: z.array(z.string()).min(1),
|
|
390
|
-
});
|
|
391
|
-
|
|
392
|
-
/** Response returned by `DELETE /v1/releases/batch`. */
|
|
393
|
-
export const ReleaseBatchDeleteResponseSchema = z.object({
|
|
394
|
-
deleted: z.number().int().min(0),
|
|
395
|
-
});
|
|
396
|
-
|
|
397
|
-
/**
|
|
398
|
-
* Body accepted by `POST /v1/releases/batch-suppress`. When `suppressed` is
|
|
399
|
-
* true the optional `reason` is stored in `suppressed_reason`; when false the
|
|
400
|
-
* reason is cleared.
|
|
401
|
-
*/
|
|
402
|
-
export const ReleaseBatchSuppressBodySchema = z.object({
|
|
403
|
-
releaseIds: z.array(z.string()).min(1),
|
|
404
|
-
suppressed: z.boolean(),
|
|
405
|
-
reason: z.string().optional(),
|
|
406
|
-
});
|
|
407
|
-
|
|
408
|
-
/** Response returned by `POST /v1/releases/batch-suppress`. */
|
|
409
|
-
export const ReleaseBatchSuppressResponseSchema = z.object({
|
|
410
|
-
updated: z.number().int().min(0),
|
|
411
|
-
});
|
|
412
|
-
|
|
413
|
-
/** Response returned by `POST /v1/releases/:id/suppress`. */
|
|
414
|
-
export const ReleaseSuppressResponseSchema = z.object({
|
|
415
|
-
suppressed: z.literal(true),
|
|
416
|
-
});
|
|
417
|
-
|
|
418
|
-
/** Response returned by `POST /v1/releases/:id/unsuppress`. */
|
|
419
|
-
export const ReleaseUnsuppressResponseSchema = z.object({
|
|
420
|
-
unsuppressed: z.literal(true),
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
/**
|
|
424
|
-
* Body accepted by `POST /v1/releases/:id/suppress`. The `reason` field
|
|
425
|
-
* is optional; when omitted the stored `suppressed_reason` is set to null.
|
|
426
|
-
*/
|
|
427
|
-
export const ReleaseSuppressBodySchema = z.object({
|
|
428
|
-
reason: z.string().optional(),
|
|
429
|
-
});
|
|
430
|
-
|
|
431
|
-
/**
|
|
432
|
-
* WebSocket message schema for the `GET /v1/releases/stream` endpoint.
|
|
433
|
-
* Each message is a JSON object with one of the following shapes:
|
|
434
|
-
* - `{ type: "ready", seq: number }` — sent on connect to give the caller
|
|
435
|
-
* the current head sequence number for later resume.
|
|
436
|
-
* - `{ type: "release.created", seq: number, release: object }` — a new
|
|
437
|
-
* release was indexed; `release` carries the full release row.
|
|
438
|
-
* - `{ type: "snapshot_gap" }` — the requested `since` sequence fell
|
|
439
|
-
* behind the oldest buffered event; the client must REST-backfill.
|
|
440
|
-
*/
|
|
441
|
-
export const ReleaseStreamMessageSchema = z.discriminatedUnion("type", [
|
|
442
|
-
z.object({ type: z.literal("ready"), seq: z.number().int() }),
|
|
443
|
-
z.object({
|
|
444
|
-
type: z.literal("release.created"),
|
|
445
|
-
seq: z.number().int(),
|
|
446
|
-
release: z.record(z.string(), z.unknown()),
|
|
447
|
-
}),
|
|
448
|
-
z.object({ type: z.literal("snapshot_gap") }),
|
|
449
|
-
]);
|