@buildinternet/releases-api-types 0.57.1 → 0.58.1
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 +3 -3
- package/src/api-types.ts +4 -2
- package/src/schemas/collections.ts +13 -1
- package/src/schemas/listing.ts +14 -2
- package/src/schemas/shared.ts +4 -0
- package/src/schemas/well-known.test.ts +61 -0
- package/src/schemas/well-known.ts +36 -2
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@buildinternet/releases-api-types",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Wire protocol — request/response types for the Releases
|
|
3
|
+
"version": "0.58.1",
|
|
4
|
+
"description": "Wire protocol — request/response types for the Releases Index API. Shared by web, workers, and clients.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"README.md"
|
|
18
18
|
],
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@buildinternet/releases-core": "^0.
|
|
20
|
+
"@buildinternet/releases-core": "^0.35.0",
|
|
21
21
|
"zod": "^4.4.3"
|
|
22
22
|
},
|
|
23
23
|
"publishConfig": {
|
package/src/api-types.ts
CHANGED
|
@@ -396,6 +396,7 @@ export {
|
|
|
396
396
|
ListingValidateBodySchema,
|
|
397
397
|
ListingActivateBodySchema,
|
|
398
398
|
ListingIssueSchema,
|
|
399
|
+
ListingSetupStepSchema,
|
|
399
400
|
ListingLocationSchema,
|
|
400
401
|
ListingOrgPointerSchema,
|
|
401
402
|
ListingValidationResultSchema,
|
|
@@ -419,6 +420,7 @@ export {
|
|
|
419
420
|
type ListingValidateBody,
|
|
420
421
|
type ListingActivateBody,
|
|
421
422
|
type ListingIssue,
|
|
423
|
+
type ListingSetupStep,
|
|
422
424
|
type ListingLocation,
|
|
423
425
|
type ListingValidationResult,
|
|
424
426
|
type ListingActivateResult,
|
|
@@ -2016,8 +2018,8 @@ export interface Session {
|
|
|
2016
2018
|
* it must never be reported as `"haiku"`. Surfaces on the detail GET.
|
|
2017
2019
|
*
|
|
2018
2020
|
* This is a logical role label, not the runtime model identifier. The
|
|
2019
|
-
* resolved Anthropic model string (e.g. `claude-sonnet-5`,
|
|
2020
|
-
* `claude-haiku-
|
|
2021
|
+
* resolved Anthropic model string (e.g. `claude-sonnet-5-5`,
|
|
2022
|
+
* `claude-haiku-5-5`) lives on `usage.model` when the session reported
|
|
2021
2023
|
* one — consult that field for the concrete model.
|
|
2022
2024
|
*/
|
|
2023
2025
|
agent?: "sonnet" | "haiku" | "coordinator" | "deterministic";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { ImportanceScoreSchema, ReleaseItemSchema } from "./shared.js";
|
|
2
|
+
import { ImportanceScoreSchema, ReleaseCompositionSchema, ReleaseItemSchema } from "./shared.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* One org as it appears inside a collection's preview list or detail page.
|
|
@@ -291,6 +291,18 @@ export const DigestCoveredReleaseSchema = z.object({
|
|
|
291
291
|
* marker on the collapsed "Releases covered" list.
|
|
292
292
|
*/
|
|
293
293
|
importance: ImportanceScoreSchema,
|
|
294
|
+
/**
|
|
295
|
+
* Per-category item counts from the AI release-content pass. Null when the
|
|
296
|
+
* row hasn't been summarized; optional for older servers. Powers the
|
|
297
|
+
* digest page's week-at-a-glance treemap.
|
|
298
|
+
*/
|
|
299
|
+
composition: ReleaseCompositionSchema.nullable().optional(),
|
|
300
|
+
/**
|
|
301
|
+
* ISO publish timestamp, as stored. Null when the source gave none;
|
|
302
|
+
* optional for older servers. A date-only source is stored at exactly
|
|
303
|
+
* `T00:00:00.000Z`. Powers the digest week replay's day placement.
|
|
304
|
+
*/
|
|
305
|
+
publishedAt: z.string().nullable().optional(),
|
|
294
306
|
});
|
|
295
307
|
|
|
296
308
|
/** One `###` section of a digest body, parsed server-side. */
|
package/src/schemas/listing.ts
CHANGED
|
@@ -24,15 +24,27 @@ export const ListingIssueSchema = z.strictObject({
|
|
|
24
24
|
});
|
|
25
25
|
export type ListingIssue = z.infer<typeof ListingIssueSchema>;
|
|
26
26
|
|
|
27
|
+
/** One follow-up the owner takes after declaring `publish: "push"`. */
|
|
28
|
+
export const ListingSetupStepSchema = z.strictObject({
|
|
29
|
+
id: z.enum(["verify", "token", "action"]),
|
|
30
|
+
title: z.string(),
|
|
31
|
+
detail: z.string(),
|
|
32
|
+
});
|
|
33
|
+
export type ListingSetupStep = z.infer<typeof ListingSetupStepSchema>;
|
|
34
|
+
|
|
27
35
|
export const ListingLocationSchema = z.strictObject({
|
|
28
36
|
/** The declared locator value (feed URL, github ref, url, appstore id, file). */
|
|
29
37
|
locator: z.string(),
|
|
30
|
-
kind: z.enum(["feed", "github", "appstore", "url", "file"]),
|
|
31
|
-
classification: z.enum(["tier1-live", "tier2-paused-review"]),
|
|
38
|
+
kind: z.enum(["feed", "github", "appstore", "url", "file", "push"]),
|
|
39
|
+
classification: z.enum(["tier1-live", "tier2-paused-review", "push-setup"]),
|
|
32
40
|
/** Plain-English "what this becomes" for the preview UI. */
|
|
33
41
|
becomes: z.string(),
|
|
34
42
|
/** Present when the locator is nested under a manifest product. */
|
|
35
43
|
productName: z.string().optional(),
|
|
44
|
+
/** Changelog file or glob. Present on `kind: "push"`. */
|
|
45
|
+
path: z.string().optional(),
|
|
46
|
+
/** Present on `kind: "push"`: verify ownership, mint a token, add the Action. */
|
|
47
|
+
setupSteps: z.array(ListingSetupStepSchema).optional(),
|
|
36
48
|
});
|
|
37
49
|
export type ListingLocation = z.infer<typeof ListingLocationSchema>;
|
|
38
50
|
|
package/src/schemas/shared.ts
CHANGED
|
@@ -87,6 +87,10 @@ export const ReleaseLocationItemSchema = z.object({
|
|
|
87
87
|
productId: z.string().nullable(),
|
|
88
88
|
/** Set once the locator has been promoted into a source, else null. */
|
|
89
89
|
sourceId: z.string().nullable(),
|
|
90
|
+
/** `"push"` when the owner publishes this changelog instead of us polling it. */
|
|
91
|
+
publish: z.literal("push").optional(),
|
|
92
|
+
/** Changelog file or glob. Present with `publish: "push"`. */
|
|
93
|
+
path: z.string().optional(),
|
|
90
94
|
});
|
|
91
95
|
|
|
92
96
|
export const PaginationSchema = z.object({
|
|
@@ -122,6 +122,67 @@ describe("releases.json v2 schemas", () => {
|
|
|
122
122
|
).toBe(false);
|
|
123
123
|
});
|
|
124
124
|
|
|
125
|
+
it("accepts a push-publish locator on github + path", () => {
|
|
126
|
+
expect(
|
|
127
|
+
ReleasesJsonDomainSchema.parse({
|
|
128
|
+
version: 2,
|
|
129
|
+
releases: [
|
|
130
|
+
{ github: "acme/docs", path: "changelog/**/*.mdx", publish: "push", title: "Docs" },
|
|
131
|
+
],
|
|
132
|
+
}),
|
|
133
|
+
).toEqual({
|
|
134
|
+
version: 2,
|
|
135
|
+
releases: [
|
|
136
|
+
{ github: "acme/docs", path: "changelog/**/*.mdx", publish: "push", title: "Docs" },
|
|
137
|
+
],
|
|
138
|
+
});
|
|
139
|
+
expect(
|
|
140
|
+
ReleasesJsonRepoSchema.safeParse({
|
|
141
|
+
version: 2,
|
|
142
|
+
releases: [{ github: "self", path: "CHANGELOG.md", publish: "push" }],
|
|
143
|
+
}).success,
|
|
144
|
+
).toBe(true);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it("rejects an incomplete or unsafe push-publish locator", () => {
|
|
148
|
+
expect(
|
|
149
|
+
ReleasesJsonDomainSchema.safeParse({
|
|
150
|
+
version: 2,
|
|
151
|
+
releases: [{ github: "acme/docs", publish: "push" }],
|
|
152
|
+
}).success,
|
|
153
|
+
).toBe(false);
|
|
154
|
+
expect(
|
|
155
|
+
ReleasesJsonDomainSchema.safeParse({
|
|
156
|
+
version: 2,
|
|
157
|
+
releases: [{ path: "CHANGELOG.md", publish: "push" }],
|
|
158
|
+
}).success,
|
|
159
|
+
).toBe(false);
|
|
160
|
+
expect(
|
|
161
|
+
ReleasesJsonDomainSchema.safeParse({
|
|
162
|
+
version: 2,
|
|
163
|
+
releases: [{ github: "acme/docs", path: "CHANGELOG.md" }],
|
|
164
|
+
}).success,
|
|
165
|
+
).toBe(false);
|
|
166
|
+
expect(
|
|
167
|
+
ReleasesJsonDomainSchema.safeParse({
|
|
168
|
+
version: 2,
|
|
169
|
+
releases: [{ github: "acme/docs", path: "CHANGELOG.md", publish: "poll" }],
|
|
170
|
+
}).success,
|
|
171
|
+
).toBe(false);
|
|
172
|
+
expect(
|
|
173
|
+
ReleasesJsonDomainSchema.safeParse({
|
|
174
|
+
version: 2,
|
|
175
|
+
releases: [{ github: "acme/docs", path: "../secrets", publish: "push" }],
|
|
176
|
+
}).success,
|
|
177
|
+
).toBe(false);
|
|
178
|
+
expect(
|
|
179
|
+
ReleasesJsonDomainSchema.safeParse({
|
|
180
|
+
version: 2,
|
|
181
|
+
releases: [{ github: "acme/docs", path: "/etc/passwd", publish: "push" }],
|
|
182
|
+
}).success,
|
|
183
|
+
).toBe(false);
|
|
184
|
+
});
|
|
185
|
+
|
|
125
186
|
it("allows github self only in repo files", () => {
|
|
126
187
|
expect(
|
|
127
188
|
ReleasesJsonDomainSchema.safeParse({ version: 2, releases: [{ github: "self" }] }).success,
|
|
@@ -17,6 +17,19 @@ const HttpsUrlSchema = z.url().startsWith("https://", "locator must be an https
|
|
|
17
17
|
/** Shared tag-array bounds — kept identical for org-level and product-level tags. */
|
|
18
18
|
const TagsSchema = z.array(z.string().min(1).max(60)).max(50);
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Changelog file or glob inside the declared repo (Action `changelog-path` /
|
|
22
|
+
* `changelog-glob`). Relative only — no scheme, no leading slash, no `..`.
|
|
23
|
+
*/
|
|
24
|
+
const PublishPathSchema = z
|
|
25
|
+
.string()
|
|
26
|
+
.min(1)
|
|
27
|
+
.max(200)
|
|
28
|
+
.regex(
|
|
29
|
+
/^(?!\/)(?!.*(?:^|\/)\.\.(?:\/|$))[A-Za-z0-9._~@%+\-/*?[\]{}]+$/,
|
|
30
|
+
"path must be a relative changelog file or glob",
|
|
31
|
+
);
|
|
32
|
+
|
|
20
33
|
const ReleaseLocationFields = {
|
|
21
34
|
url: HttpsUrlSchema.optional(),
|
|
22
35
|
feed: HttpsUrlSchema.optional(),
|
|
@@ -24,6 +37,13 @@ const ReleaseLocationFields = {
|
|
|
24
37
|
file: HttpsUrlSchema.optional(),
|
|
25
38
|
title: z.string().min(1).max(200).optional(),
|
|
26
39
|
canonical: z.boolean().optional(),
|
|
40
|
+
/**
|
|
41
|
+
* `"push"` means the owner publishes this changelog (GitHub Action / publish
|
|
42
|
+
* token) instead of us polling it. Requires `github` + `path`.
|
|
43
|
+
*/
|
|
44
|
+
publish: z.literal("push").optional(),
|
|
45
|
+
/** Required with `publish: "push"`. The file or glob the Action watches. */
|
|
46
|
+
path: PublishPathSchema.optional(),
|
|
27
47
|
};
|
|
28
48
|
|
|
29
49
|
function hasLocator(value: {
|
|
@@ -36,6 +56,12 @@ function hasLocator(value: {
|
|
|
36
56
|
return Boolean(value.url || value.feed || value.github || value.appstore || value.file);
|
|
37
57
|
}
|
|
38
58
|
|
|
59
|
+
/** `publish: "push"` is a mode on a github locator, not a locator by itself. */
|
|
60
|
+
function pushPublishComplete(value: { github?: string; publish?: "push"; path?: string }): boolean {
|
|
61
|
+
if (value.publish === "push") return Boolean(value.github && value.path);
|
|
62
|
+
return value.path === undefined;
|
|
63
|
+
}
|
|
64
|
+
|
|
39
65
|
/** A domain manifest can name a concrete GitHub repository, but never `self`. */
|
|
40
66
|
export const ReleasesJsonDomainReleaseSchema = z
|
|
41
67
|
.strictObject({
|
|
@@ -45,7 +71,11 @@ export const ReleasesJsonDomainReleaseSchema = z
|
|
|
45
71
|
.regex(/^[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+$/, "github must be owner/repo")
|
|
46
72
|
.optional(),
|
|
47
73
|
})
|
|
48
|
-
.refine(hasLocator, "at least one release locator is required")
|
|
74
|
+
.refine(hasLocator, "at least one release locator is required")
|
|
75
|
+
.refine(
|
|
76
|
+
pushPublishComplete,
|
|
77
|
+
'publish: "push" requires github (owner/repo) and path (changelog file or glob)',
|
|
78
|
+
);
|
|
49
79
|
|
|
50
80
|
/** A repo manifest additionally accepts `github: "self"`. */
|
|
51
81
|
export const ReleasesJsonRepoReleaseSchema = z
|
|
@@ -58,7 +88,11 @@ export const ReleasesJsonRepoReleaseSchema = z
|
|
|
58
88
|
])
|
|
59
89
|
.optional(),
|
|
60
90
|
})
|
|
61
|
-
.refine(hasLocator, "at least one release locator is required")
|
|
91
|
+
.refine(hasLocator, "at least one release locator is required")
|
|
92
|
+
.refine(
|
|
93
|
+
pushPublishComplete,
|
|
94
|
+
'publish: "push" requires github (owner/repo or "self") and path (changelog file or glob)',
|
|
95
|
+
);
|
|
62
96
|
|
|
63
97
|
function releasesArray<T extends z.ZodType>(item: T, max: number) {
|
|
64
98
|
return z
|