ctxr-cli 0.24.0 → 0.26.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 +59 -4
- package/dist/commands/land.d.ts +50 -0
- package/dist/commands/land.d.ts.map +1 -0
- package/dist/commands/land.js +414 -0
- package/dist/commands/land.js.map +1 -0
- package/dist/commands/publish-check.d.ts +12 -0
- package/dist/commands/publish-check.d.ts.map +1 -1
- package/dist/commands/publish-check.js +38 -7
- package/dist/commands/publish-check.js.map +1 -1
- package/dist/commands/publish-urls.d.ts +7 -0
- package/dist/commands/publish-urls.d.ts.map +1 -1
- package/dist/commands/publish-urls.js +13 -5
- package/dist/commands/publish-urls.js.map +1 -1
- package/dist/commands/review-list.d.ts +34 -0
- package/dist/commands/review-list.d.ts.map +1 -0
- package/dist/commands/review-list.js +49 -0
- package/dist/commands/review-list.js.map +1 -0
- package/dist/commands/serve.d.ts +3 -6
- package/dist/commands/serve.d.ts.map +1 -1
- package/dist/commands/serve.js +81 -48
- package/dist/commands/serve.js.map +1 -1
- package/dist/config/schema.d.ts +40 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +39 -0
- package/dist/config/schema.js.map +1 -1
- package/dist/core/approval/decision.d.ts +73 -0
- package/dist/core/approval/decision.d.ts.map +1 -0
- package/dist/core/approval/decision.js +166 -0
- package/dist/core/approval/decision.js.map +1 -0
- package/dist/core/approval/file-diff.d.ts +32 -0
- package/dist/core/approval/file-diff.d.ts.map +1 -0
- package/dist/core/approval/file-diff.js +83 -0
- package/dist/core/approval/file-diff.js.map +1 -0
- package/dist/core/approval/identity.d.ts +34 -0
- package/dist/core/approval/identity.d.ts.map +1 -0
- package/dist/core/approval/identity.js +105 -0
- package/dist/core/approval/identity.js.map +1 -0
- package/dist/core/approval/landing-record.d.ts +17 -0
- package/dist/core/approval/landing-record.d.ts.map +1 -0
- package/dist/core/approval/landing-record.js +30 -0
- package/dist/core/approval/landing-record.js.map +1 -0
- package/dist/core/approval/resolver.d.ts +15 -0
- package/dist/core/approval/resolver.d.ts.map +1 -0
- package/dist/core/approval/resolver.js +41 -0
- package/dist/core/approval/resolver.js.map +1 -0
- package/dist/core/approval/sessions.d.ts +36 -0
- package/dist/core/approval/sessions.d.ts.map +1 -0
- package/dist/core/approval/sessions.js +76 -0
- package/dist/core/approval/sessions.js.map +1 -0
- package/dist/core/browse/approve.d.ts +48 -0
- package/dist/core/browse/approve.d.ts.map +1 -0
- package/dist/core/browse/approve.js +284 -0
- package/dist/core/browse/approve.js.map +1 -0
- package/dist/core/browse/memo.d.ts +7 -0
- package/dist/core/browse/memo.d.ts.map +1 -0
- package/dist/core/browse/memo.js +56 -0
- package/dist/core/browse/memo.js.map +1 -0
- package/dist/core/browse/review.d.ts +22 -0
- package/dist/core/browse/review.d.ts.map +1 -0
- package/dist/core/browse/review.js +58 -0
- package/dist/core/browse/review.js.map +1 -0
- package/dist/core/browse/serving-state.d.ts +45 -0
- package/dist/core/browse/serving-state.d.ts.map +1 -0
- package/dist/core/browse/serving-state.js +108 -0
- package/dist/core/browse/serving-state.js.map +1 -0
- package/dist/core/checks/organize-checks.js +2 -2
- package/dist/core/checks/organize-checks.js.map +1 -1
- package/dist/core/errors.d.ts +24 -0
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +55 -0
- package/dist/core/errors.js.map +1 -1
- package/dist/core/forge/credentials.d.ts +69 -0
- package/dist/core/forge/credentials.d.ts.map +1 -0
- package/dist/core/forge/credentials.js +197 -0
- package/dist/core/forge/credentials.js.map +1 -0
- package/dist/core/forge/github.d.ts +73 -0
- package/dist/core/forge/github.d.ts.map +1 -0
- package/dist/core/forge/github.js +101 -0
- package/dist/core/forge/github.js.map +1 -0
- package/dist/core/git/exec.d.ts +15 -0
- package/dist/core/git/exec.d.ts.map +1 -1
- package/dist/core/git/exec.js +48 -1
- package/dist/core/git/exec.js.map +1 -1
- package/dist/core/graph/diff-block.d.ts.map +1 -1
- package/dist/core/graph/diff-block.js +13 -4
- package/dist/core/graph/diff-block.js.map +1 -1
- package/dist/core/graph/diff-document.d.ts +3 -2
- package/dist/core/graph/diff-document.d.ts.map +1 -1
- package/dist/core/graph/diff-document.js +2 -4
- package/dist/core/graph/diff-document.js.map +1 -1
- package/dist/core/publish/lifespan.d.ts +5 -5
- package/dist/core/publish/lifespan.d.ts.map +1 -1
- package/dist/core/publish/lifespan.js +13 -8
- package/dist/core/publish/lifespan.js.map +1 -1
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +26 -0
- package/dist/run.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/templates/approve/approve-button.md +1 -0
- package/templates/approve/author-heading.md +1 -0
- package/templates/approve/author-note.md +1 -0
- package/templates/approve/comment-label.md +1 -0
- package/templates/approve/comment-required.md +1 -0
- package/templates/approve/commits-heading.md +1 -0
- package/templates/approve/decision-heading.md +1 -0
- package/templates/approve/decision-note.md +1 -0
- package/templates/approve/diff-binary.md +1 -0
- package/templates/approve/diff-empty.md +1 -0
- package/templates/approve/diff-heading.md +1 -0
- package/templates/approve/facts-heading.md +1 -0
- package/templates/approve/forge-unreachable.md +1 -0
- package/templates/approve/github-app-manifest.json +15 -0
- package/templates/approve/head-missing.md +1 -0
- package/templates/approve/index-empty.md +1 -0
- package/templates/approve/index-heading.md +1 -0
- package/templates/approve/index-intro.md +1 -0
- package/templates/approve/landed.md +1 -0
- package/templates/approve/moved-head.md +1 -0
- package/templates/approve/no-pull.md +1 -0
- package/templates/approve/not-open.md +1 -0
- package/templates/approve/pages-heading.md +1 -0
- package/templates/approve/pages-note.md +1 -0
- package/templates/approve/record-failed.md +1 -0
- package/templates/approve/request-changes-button.md +1 -0
- package/templates/approve/state-line.md +1 -0
- package/templates/graph/knowledge-changes/archived-item.md +1 -0
- package/templates/graph/knowledge-changes/dangling-item.md +1 -0
- package/templates/graph/knowledge-changes/reason-ambiguous.md +1 -0
- package/templates/graph/knowledge-changes/reason-not_found.md +1 -0
- package/templates/graph/review/moved-head.md +1 -0
- package/templates/land/resolver.md +12 -0
- package/templates/serve/style.css +63 -0
- package/templates/skills/ctxr-land.md +37 -31
- package/templates/skills/ctxr-publish.md +25 -1
- package/templates/skills/ctxr-second-opinion/run.mjs +28 -17
- package/templates/skills/ctxr-second-opinion.md +19 -14
- package/templates/skills/ctxr-session-lifecycle.md +9 -0
- package/templates/skills/ctxr-submit.md +4 -2
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { createPrivateKey, sign } from 'node:crypto';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { ForgeCredentialsError } from '../errors.js';
|
|
4
|
+
export const APP_ID_VAR = 'CONTEXTURE_GITHUB_APP_ID';
|
|
5
|
+
export const APP_KEY_FILE_VAR = 'CONTEXTURE_GITHUB_APP_PRIVATE_KEY_FILE';
|
|
6
|
+
export const APP_KEY_VAR = 'CONTEXTURE_GITHUB_APP_PRIVATE_KEY';
|
|
7
|
+
/** `owner/repo`, when the store's `origin` is not a github.com URL this module can read — a mirror, a proxy, a test server. */
|
|
8
|
+
export const APP_REPOSITORY_VAR = 'CONTEXTURE_GITHUB_REPOSITORY';
|
|
9
|
+
/** The API base; github.com's unless a GitHub-compatible test server is named. */
|
|
10
|
+
export const API_URL_VAR = 'CONTEXTURE_GITHUB_API_URL';
|
|
11
|
+
const DEFAULT_API_URL = 'https://api.github.com';
|
|
12
|
+
/** design.md D3: a token is replaced once less than this much of its life remains. */
|
|
13
|
+
const REFRESH_MARGIN_MS = 5 * 60 * 1000;
|
|
14
|
+
/** The credential source a command's forge calls go through, resolved from the command's own environment. */
|
|
15
|
+
export function credentialsFor(env, cwd) {
|
|
16
|
+
return resolveForgeCredentials({ env: env.env, git: env.git, cwd, now: () => env.now() });
|
|
17
|
+
}
|
|
18
|
+
export function ghCredentials(env) {
|
|
19
|
+
return {
|
|
20
|
+
kind: 'gh',
|
|
21
|
+
env: async () => env,
|
|
22
|
+
botLogin: async () => null,
|
|
23
|
+
gitToken: async () => null,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
const set = (value) => value !== undefined && value !== '';
|
|
27
|
+
/**
|
|
28
|
+
* change-approval spec ("The recording identity may be a GitHub App with
|
|
29
|
+
* credentials from the environment only"): App mode when the App ID and exactly
|
|
30
|
+
* one key source are set, `gh` mode when none of them is, and a refusal for
|
|
31
|
+
* anything in between — never a guessed precedence (design.md D1).
|
|
32
|
+
*/
|
|
33
|
+
export async function resolveForgeCredentials(opts) {
|
|
34
|
+
const appId = opts.env[APP_ID_VAR];
|
|
35
|
+
const keyFile = opts.env[APP_KEY_FILE_VAR];
|
|
36
|
+
const keyText = opts.env[APP_KEY_VAR];
|
|
37
|
+
if (!set(appId) && !set(keyFile) && !set(keyText))
|
|
38
|
+
return ghCredentials(opts.env);
|
|
39
|
+
if (set(keyFile) && set(keyText)) {
|
|
40
|
+
throw new ForgeCredentialsError(`Both ${APP_KEY_FILE_VAR} and ${APP_KEY_VAR} are set; set one of them.`, [APP_KEY_FILE_VAR, APP_KEY_VAR]);
|
|
41
|
+
}
|
|
42
|
+
if (!set(appId))
|
|
43
|
+
throw new ForgeCredentialsError(`A GitHub App private key is set, but ${APP_ID_VAR} is not.`, [APP_ID_VAR]);
|
|
44
|
+
if (!set(keyFile) && !set(keyText)) {
|
|
45
|
+
throw new ForgeCredentialsError(`${APP_ID_VAR} is set, but neither ${APP_KEY_FILE_VAR} nor ${APP_KEY_VAR} is.`, [APP_KEY_FILE_VAR, APP_KEY_VAR]);
|
|
46
|
+
}
|
|
47
|
+
if (/\s/.test(appId))
|
|
48
|
+
throw new ForgeCredentialsError(`${APP_ID_VAR} must be the App's ID or client ID.`, [APP_ID_VAR]);
|
|
49
|
+
let pem;
|
|
50
|
+
if (set(keyFile)) {
|
|
51
|
+
try {
|
|
52
|
+
pem = await readFile(keyFile, 'utf8');
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
throw new ForgeCredentialsError(`${APP_KEY_FILE_VAR} names "${keyFile}", which cannot be read (${err.code ?? 'error'}).`, [APP_KEY_FILE_VAR]);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
pem = keyText;
|
|
60
|
+
}
|
|
61
|
+
let key;
|
|
62
|
+
try {
|
|
63
|
+
key = createPrivateKey(pem);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
throw new ForgeCredentialsError('The GitHub App private key is not a readable PEM private key.', [set(keyFile) ? APP_KEY_FILE_VAR : APP_KEY_VAR]);
|
|
67
|
+
}
|
|
68
|
+
if (key.asymmetricKeyType !== 'rsa') {
|
|
69
|
+
throw new ForgeCredentialsError('The GitHub App private key must be an RSA key, as GitHub generates.', [set(keyFile) ? APP_KEY_FILE_VAR : APP_KEY_VAR]);
|
|
70
|
+
}
|
|
71
|
+
return createAppCredentials({
|
|
72
|
+
appId,
|
|
73
|
+
key,
|
|
74
|
+
env: opts.env,
|
|
75
|
+
git: opts.git,
|
|
76
|
+
cwd: opts.cwd,
|
|
77
|
+
fetch: opts.fetch ?? ((url, init) => fetch(url, init)),
|
|
78
|
+
now: opts.now ?? (() => new Date()),
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/** design.md D3: RS256, `iat` backdated 60 s for clock skew, `exp` nine minutes out (GitHub allows ten). */
|
|
82
|
+
export function appAssertion(appId, key, now) {
|
|
83
|
+
const seconds = Math.floor(now.getTime() / 1000);
|
|
84
|
+
const encode = (value) => Buffer.from(JSON.stringify(value)).toString('base64url');
|
|
85
|
+
const header = encode({ alg: 'RS256', typ: 'JWT' });
|
|
86
|
+
// A numeric App ID goes in as a number; a client ID ("Iv1…") as the string it is. GitHub accepts either.
|
|
87
|
+
const payload = encode({ iat: seconds - 60, exp: seconds + 9 * 60, iss: /^\d+$/.test(appId) ? Number(appId) : appId });
|
|
88
|
+
const signature = sign('sha256', Buffer.from(`${header}.${payload}`), key).toString('base64url');
|
|
89
|
+
return `${header}.${payload}.${signature}`;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* design.md D2: `owner/repo` from a github.com remote, https or ssh, with or
|
|
93
|
+
* without `.git`. Anything else is not something App mode can address.
|
|
94
|
+
*/
|
|
95
|
+
export function githubRepositoryOf(remoteUrl) {
|
|
96
|
+
const patterns = [
|
|
97
|
+
/^https:\/\/(?:[^@/]+@)?github\.com\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/,
|
|
98
|
+
/^ssh:\/\/git@github\.com(?::\d+)?\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/,
|
|
99
|
+
/^git@github\.com:([^/]+)\/([^/]+?)(?:\.git)?\/?$/,
|
|
100
|
+
];
|
|
101
|
+
for (const pattern of patterns) {
|
|
102
|
+
const match = pattern.exec(remoteUrl.trim());
|
|
103
|
+
if (match !== null)
|
|
104
|
+
return `${match[1]}/${match[2]}`;
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
function createAppCredentials(inputs) {
|
|
109
|
+
const apiUrl = (inputs.env[API_URL_VAR] || DEFAULT_API_URL).replace(/\/+$/, '');
|
|
110
|
+
let cached = null;
|
|
111
|
+
let inFlight = null;
|
|
112
|
+
let slug = null;
|
|
113
|
+
async function appCall(method, route) {
|
|
114
|
+
const response = await inputs.fetch(`${apiUrl}${route}`, {
|
|
115
|
+
method,
|
|
116
|
+
headers: {
|
|
117
|
+
Authorization: `Bearer ${appAssertion(inputs.appId, inputs.key, inputs.now())}`,
|
|
118
|
+
Accept: 'application/vnd.github+json',
|
|
119
|
+
'X-GitHub-Api-Version': '2022-11-28',
|
|
120
|
+
'User-Agent': 'ctxr',
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
if (response.ok)
|
|
124
|
+
return response.json();
|
|
125
|
+
const detail = (await response.text().catch(() => '')).slice(0, 300);
|
|
126
|
+
return { __status: response.status, __detail: detail };
|
|
127
|
+
}
|
|
128
|
+
function failed(value) {
|
|
129
|
+
if (typeof value === 'object' && value !== null && '__status' in value) {
|
|
130
|
+
const v = value;
|
|
131
|
+
return { status: v.__status, detail: v.__detail };
|
|
132
|
+
}
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
async function repository() {
|
|
136
|
+
const explicit = inputs.env[APP_REPOSITORY_VAR];
|
|
137
|
+
if (set(explicit)) {
|
|
138
|
+
if (!/^[^/\s]+\/[^/\s]+$/.test(explicit))
|
|
139
|
+
throw new ForgeCredentialsError(`${APP_REPOSITORY_VAR} must be "owner/repo".`, [APP_REPOSITORY_VAR]);
|
|
140
|
+
return explicit;
|
|
141
|
+
}
|
|
142
|
+
const remote = await inputs.git.run(['remote', 'get-url', 'origin'], { cwd: inputs.cwd, allowFailure: true });
|
|
143
|
+
const repo = remote.exitCode === 0 ? githubRepositoryOf(remote.stdout) : null;
|
|
144
|
+
if (repo === null) {
|
|
145
|
+
throw new ForgeCredentialsError(`GitHub App mode needs a github.com "origin" remote, and this store's is "${remote.stdout.trim() || 'not set'}". Set ${APP_REPOSITORY_VAR} to name the repository.`, [APP_REPOSITORY_VAR]);
|
|
146
|
+
}
|
|
147
|
+
return repo;
|
|
148
|
+
}
|
|
149
|
+
async function mint() {
|
|
150
|
+
const repo = await repository();
|
|
151
|
+
const installation = await appCall('GET', `/repos/${repo}/installation`);
|
|
152
|
+
const missing = failed(installation);
|
|
153
|
+
if (missing !== null) {
|
|
154
|
+
if (missing.status === 404) {
|
|
155
|
+
throw new ForgeCredentialsError(`GitHub App ${inputs.appId} is not installed on ${repo}. Install it on that repository.`, [APP_ID_VAR]);
|
|
156
|
+
}
|
|
157
|
+
throw new ForgeCredentialsError(`GitHub refused GitHub App ${inputs.appId} (HTTP ${missing.status}): ${missing.detail}`, [APP_ID_VAR]);
|
|
158
|
+
}
|
|
159
|
+
const id = installation.id;
|
|
160
|
+
const issued = await appCall('POST', `/app/installations/${id}/access_tokens`);
|
|
161
|
+
const refused = failed(issued);
|
|
162
|
+
if (refused !== null) {
|
|
163
|
+
throw new ForgeCredentialsError(`GitHub would not issue an installation token for ${repo} (HTTP ${refused.status}): ${refused.detail}`, [APP_ID_VAR]);
|
|
164
|
+
}
|
|
165
|
+
const { token, expires_at: expiresAt } = issued;
|
|
166
|
+
cached = { token, expiresAt: Date.parse(expiresAt) };
|
|
167
|
+
return token;
|
|
168
|
+
}
|
|
169
|
+
/** design.md D3: reuse while at least five minutes remain; one refresh in flight, however many callers ask. */
|
|
170
|
+
async function token() {
|
|
171
|
+
if (cached !== null && cached.expiresAt - inputs.now().getTime() >= REFRESH_MARGIN_MS)
|
|
172
|
+
return cached.token;
|
|
173
|
+
inFlight ??= mint().finally(() => {
|
|
174
|
+
inFlight = null;
|
|
175
|
+
});
|
|
176
|
+
return inFlight;
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
kind: 'github-app',
|
|
180
|
+
async env() {
|
|
181
|
+
return { ...inputs.env, GH_TOKEN: await token() };
|
|
182
|
+
},
|
|
183
|
+
async botLogin() {
|
|
184
|
+
if (slug === null) {
|
|
185
|
+
const app = await appCall('GET', '/app');
|
|
186
|
+
const refused = failed(app);
|
|
187
|
+
if (refused !== null) {
|
|
188
|
+
throw new ForgeCredentialsError(`GitHub refused GitHub App ${inputs.appId}'s signed assertion (HTTP ${refused.status}): ${refused.detail}`, [APP_ID_VAR]);
|
|
189
|
+
}
|
|
190
|
+
slug = app.slug;
|
|
191
|
+
}
|
|
192
|
+
return `${slug}[bot]`;
|
|
193
|
+
},
|
|
194
|
+
gitToken: token,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../../src/core/forge/credentials.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { CredentialKind, ForgeCredentials } from './credentials.js';
|
|
2
|
+
/**
|
|
3
|
+
* approve-from-the-review-page (design.md D10): the forge, read and written
|
|
4
|
+
* through `gh api` — the only module that spawns `gh`. Core code rather than
|
|
5
|
+
* a revived `forge` adapter kind: there is one forge, and
|
|
6
|
+
* session-keeps-only-what-git-cannot-do removed the seam for a second.
|
|
7
|
+
*
|
|
8
|
+
* `{owner}` and `{repo}` are `gh`'s own placeholders, filled from the
|
|
9
|
+
* repository `cwd` sits in, so no remote URL is parsed here. `gh` reads its
|
|
10
|
+
* credential (`GH_TOKEN`, or its own credential file) from the process that
|
|
11
|
+
* runs it; nothing here touches a token.
|
|
12
|
+
*/
|
|
13
|
+
export interface PullRequest {
|
|
14
|
+
number: number;
|
|
15
|
+
state: 'open' | 'closed';
|
|
16
|
+
merged: boolean;
|
|
17
|
+
title: string;
|
|
18
|
+
body: string;
|
|
19
|
+
url: string;
|
|
20
|
+
author: string;
|
|
21
|
+
headRef: string;
|
|
22
|
+
headSha: string;
|
|
23
|
+
baseRef: string;
|
|
24
|
+
/** null while the forge is still computing it. */
|
|
25
|
+
mergeable: boolean | null;
|
|
26
|
+
mergeCommitSha: string | null;
|
|
27
|
+
}
|
|
28
|
+
export interface Review {
|
|
29
|
+
author: string;
|
|
30
|
+
state: string;
|
|
31
|
+
body: string;
|
|
32
|
+
commitId: string | null;
|
|
33
|
+
submittedAt: string | null;
|
|
34
|
+
}
|
|
35
|
+
export interface IssueComment {
|
|
36
|
+
author: string;
|
|
37
|
+
body: string;
|
|
38
|
+
createdAt: string;
|
|
39
|
+
}
|
|
40
|
+
export type ReviewEvent = 'APPROVE' | 'REQUEST_CHANGES' | 'COMMENT';
|
|
41
|
+
export type MergeMethod = 'squash' | 'merge' | 'rebase';
|
|
42
|
+
export interface ForgeClient {
|
|
43
|
+
/** The credential kind behind every call — reported by commands, never the credential itself. */
|
|
44
|
+
credential: CredentialKind;
|
|
45
|
+
login(): Promise<string>;
|
|
46
|
+
pull(number: number): Promise<PullRequest>;
|
|
47
|
+
openPulls(): Promise<PullRequest[]>;
|
|
48
|
+
reviews(number: number): Promise<Review[]>;
|
|
49
|
+
comments(number: number): Promise<IssueComment[]>;
|
|
50
|
+
createReview(number: number, input: {
|
|
51
|
+
event: ReviewEvent;
|
|
52
|
+
body: string;
|
|
53
|
+
commitId: string;
|
|
54
|
+
}): Promise<void>;
|
|
55
|
+
createComment(number: number, body: string): Promise<void>;
|
|
56
|
+
merge(number: number, input: {
|
|
57
|
+
method: MergeMethod;
|
|
58
|
+
sha: string;
|
|
59
|
+
}): Promise<void>;
|
|
60
|
+
}
|
|
61
|
+
/** A `gh api` call that did not succeed. `status` is the HTTP status when `gh` reported one. */
|
|
62
|
+
export declare class ForgeRequestError extends Error {
|
|
63
|
+
readonly status: number | null;
|
|
64
|
+
constructor(endpoint: string, status: number | null, detail: string);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* `credentials` supplies the environment of every `gh` call: the caller's own
|
|
68
|
+
* for `gh`'s credential, or with `GH_TOKEN` set to a fresh installation token
|
|
69
|
+
* for a GitHub App (github-app-recording-identity D3) — fetched per call, so a
|
|
70
|
+
* long-running server never uses an expired one.
|
|
71
|
+
*/
|
|
72
|
+
export declare function createGhForgeClient(cwd: string, credentials: ForgeCredentials): ForgeClient;
|
|
73
|
+
//# sourceMappingURL=github.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../../src/core/forge/github.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAIzE;;;;;;;;;;GAUG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,GAAG,QAAQ,CAAC;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,MAAM;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,iBAAiB,GAAG,SAAS,CAAC;AACpE,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAExD,MAAM,WAAW,WAAW;IAC1B,iGAAiG;IACjG,UAAU,EAAE,cAAc,CAAC;IAC3B,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IACzB,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC3C,SAAS,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IACpC,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAClD,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,KAAK,EAAE,WAAW,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3G,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,MAAM,EAAE,WAAW,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnF;AAED,gGAAgG;AAChG,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,YAAY,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,EAIlE;CACF;AAkCD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,GAAG,WAAW,CAuE3F"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
const execFileAsync = promisify(execFile);
|
|
4
|
+
/** A `gh api` call that did not succeed. `status` is the HTTP status when `gh` reported one. */
|
|
5
|
+
export class ForgeRequestError extends Error {
|
|
6
|
+
status;
|
|
7
|
+
constructor(endpoint, status, detail) {
|
|
8
|
+
super(`forge request ${endpoint} failed${status === null ? '' : ` (HTTP ${status})`}: ${detail}`);
|
|
9
|
+
this.name = 'ForgeRequestError';
|
|
10
|
+
this.status = status;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function toPull(raw) {
|
|
14
|
+
return {
|
|
15
|
+
number: raw.number,
|
|
16
|
+
state: raw.state,
|
|
17
|
+
merged: raw.merged ?? (raw.merged_at !== undefined && raw.merged_at !== null),
|
|
18
|
+
title: raw.title,
|
|
19
|
+
body: raw.body ?? '',
|
|
20
|
+
url: raw.html_url,
|
|
21
|
+
author: raw.user?.login ?? '',
|
|
22
|
+
headRef: raw.head.ref,
|
|
23
|
+
headSha: raw.head.sha,
|
|
24
|
+
baseRef: raw.base.ref,
|
|
25
|
+
mergeable: raw.mergeable ?? null,
|
|
26
|
+
mergeCommitSha: raw.merge_commit_sha ?? null,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* `credentials` supplies the environment of every `gh` call: the caller's own
|
|
31
|
+
* for `gh`'s credential, or with `GH_TOKEN` set to a fresh installation token
|
|
32
|
+
* for a GitHub App (github-app-recording-identity D3) — fetched per call, so a
|
|
33
|
+
* long-running server never uses an expired one.
|
|
34
|
+
*/
|
|
35
|
+
export function createGhForgeClient(cwd, credentials) {
|
|
36
|
+
async function api(endpoint, opts = {}) {
|
|
37
|
+
const env = await credentials.env();
|
|
38
|
+
const args = ['api', endpoint];
|
|
39
|
+
if (opts.method !== undefined)
|
|
40
|
+
args.push('--method', opts.method);
|
|
41
|
+
if (opts.input !== undefined)
|
|
42
|
+
args.push('--input', '-');
|
|
43
|
+
try {
|
|
44
|
+
const child = execFileAsync('gh', args, { cwd, env: env, maxBuffer: 64 * 1024 * 1024 });
|
|
45
|
+
if (opts.input !== undefined)
|
|
46
|
+
child.child.stdin?.end(JSON.stringify(opts.input));
|
|
47
|
+
const { stdout } = await child;
|
|
48
|
+
return stdout.trim() === '' ? null : JSON.parse(stdout);
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
const e = err;
|
|
52
|
+
const detail = (e.stderr ?? '').trim() || (e.stdout ?? '').trim() || (e.message ?? String(err));
|
|
53
|
+
const status = /\(HTTP (\d{3})\)/.exec(detail)?.[1];
|
|
54
|
+
throw new ForgeRequestError(endpoint, status === undefined ? null : Number.parseInt(status, 10), detail);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const repo = 'repos/{owner}/{repo}';
|
|
58
|
+
return {
|
|
59
|
+
credential: credentials.kind,
|
|
60
|
+
async login() {
|
|
61
|
+
// An installation token cannot call GET /user; an App's login is its bot login (change-approval spec).
|
|
62
|
+
const bot = await credentials.botLogin();
|
|
63
|
+
if (bot !== null)
|
|
64
|
+
return bot;
|
|
65
|
+
return (await api('user')).login;
|
|
66
|
+
},
|
|
67
|
+
async pull(number) {
|
|
68
|
+
return toPull((await api(`${repo}/pulls/${number}`)));
|
|
69
|
+
},
|
|
70
|
+
async openPulls() {
|
|
71
|
+
return (await api(`${repo}/pulls?state=open&per_page=100`)).map(toPull);
|
|
72
|
+
},
|
|
73
|
+
async reviews(number) {
|
|
74
|
+
const raw = (await api(`${repo}/pulls/${number}/reviews?per_page=100`));
|
|
75
|
+
return raw.map((r) => ({
|
|
76
|
+
author: r.user?.login ?? '',
|
|
77
|
+
state: r.state,
|
|
78
|
+
body: r.body ?? '',
|
|
79
|
+
commitId: r.commit_id ?? null,
|
|
80
|
+
submittedAt: r.submitted_at ?? null,
|
|
81
|
+
}));
|
|
82
|
+
},
|
|
83
|
+
async comments(number) {
|
|
84
|
+
const raw = (await api(`${repo}/issues/${number}/comments?per_page=100`));
|
|
85
|
+
return raw.map((c) => ({ author: c.user?.login ?? '', body: c.body ?? '', createdAt: c.created_at }));
|
|
86
|
+
},
|
|
87
|
+
async createReview(number, input) {
|
|
88
|
+
await api(`${repo}/pulls/${number}/reviews`, {
|
|
89
|
+
method: 'POST',
|
|
90
|
+
input: { event: input.event, body: input.body, commit_id: input.commitId },
|
|
91
|
+
});
|
|
92
|
+
},
|
|
93
|
+
async createComment(number, body) {
|
|
94
|
+
await api(`${repo}/issues/${number}/comments`, { method: 'POST', input: { body } });
|
|
95
|
+
},
|
|
96
|
+
async merge(number, input) {
|
|
97
|
+
await api(`${repo}/pulls/${number}/merge`, { method: 'PUT', input: { merge_method: input.method, sha: input.sha } });
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=github.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.js","sourceRoot":"","sources":["../../../src/core/forge/github.ts"],"names":[],"mappings":"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"}
|
package/dist/core/git/exec.d.ts
CHANGED
|
@@ -20,6 +20,12 @@ export interface GitRunOptions {
|
|
|
20
20
|
cwd: string;
|
|
21
21
|
/** When true, a non-zero exit resolves with the result instead of throwing. */
|
|
22
22
|
allowFailure?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* github-app-recording-identity (D4): the whole environment for this one git
|
|
25
|
+
* process, in place of this process's own — how `ctxr land` hands a token to
|
|
26
|
+
* a credential helper without writing it anywhere.
|
|
27
|
+
*/
|
|
28
|
+
env?: Readonly<Record<string, string | undefined>>;
|
|
23
29
|
}
|
|
24
30
|
export interface GitRunner {
|
|
25
31
|
run(args: readonly string[], opts: GitRunOptions): Promise<GitResult>;
|
|
@@ -35,4 +41,13 @@ export declare function createExecFileGitRunner(): GitRunner;
|
|
|
35
41
|
* written. An id the object store does not hold rejects, naming it.
|
|
36
42
|
*/
|
|
37
43
|
export declare function readBlobs(cwd: string, objectIds: readonly string[]): Promise<Map<string, string>>;
|
|
44
|
+
/**
|
|
45
|
+
* approve-from-the-review-page (design.md D5): the stable patch identity of
|
|
46
|
+
* every commit in `range` (`<base>..<head>`), oldest first — `git log -p`
|
|
47
|
+
* piped into `git patch-id --stable`, two processes and no shell. Two ranges
|
|
48
|
+
* with equal lists carry the same changes commit for commit, whatever base
|
|
49
|
+
* each was applied to. Rejects when either process fails, as for an unknown
|
|
50
|
+
* commit; the caller treats that as "not the same".
|
|
51
|
+
*/
|
|
52
|
+
export declare function patchIds(cwd: string, range: string): Promise<string[]>;
|
|
38
53
|
//# sourceMappingURL=exec.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../../src/core/git/exec.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,+EAA+E;IAC/E,YAAY,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../../src/core/git/exec.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,+EAA+E;IAC/E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;OAIG;IACH,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;CACpD;AAED,MAAM,WAAW,SAAS;IACxB,GAAG,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;CACvE;AAUD,wBAAgB,uBAAuB,IAAI,SAAS,CAmBnD;AAED;;;;;;;;GAQG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CA+BvG;AAED;;;;;;;GAOG;AACH,wBAAsB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAoC5E"}
|
package/dist/core/git/exec.js
CHANGED
|
@@ -12,7 +12,11 @@ export function createExecFileGitRunner() {
|
|
|
12
12
|
return {
|
|
13
13
|
async run(args, opts) {
|
|
14
14
|
try {
|
|
15
|
-
const { stdout, stderr } = await execFileAsync('git', [...args], {
|
|
15
|
+
const { stdout, stderr } = await execFileAsync('git', [...args], {
|
|
16
|
+
cwd: opts.cwd,
|
|
17
|
+
maxBuffer: MAX_OUTPUT_BYTES,
|
|
18
|
+
...(opts.env === undefined ? {} : { env: opts.env }),
|
|
19
|
+
});
|
|
16
20
|
return { stdout, stderr, exitCode: 0 };
|
|
17
21
|
}
|
|
18
22
|
catch (err) {
|
|
@@ -68,4 +72,47 @@ export async function readBlobs(cwd, objectIds) {
|
|
|
68
72
|
}
|
|
69
73
|
return blobs;
|
|
70
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* approve-from-the-review-page (design.md D5): the stable patch identity of
|
|
77
|
+
* every commit in `range` (`<base>..<head>`), oldest first — `git log -p`
|
|
78
|
+
* piped into `git patch-id --stable`, two processes and no shell. Two ranges
|
|
79
|
+
* with equal lists carry the same changes commit for commit, whatever base
|
|
80
|
+
* each was applied to. Rejects when either process fails, as for an unknown
|
|
81
|
+
* commit; the caller treats that as "not the same".
|
|
82
|
+
*/
|
|
83
|
+
export async function patchIds(cwd, range) {
|
|
84
|
+
const order = await new Promise((resolve, reject) => {
|
|
85
|
+
execFile('git', ['rev-list', '--reverse', '--no-merges', range], { cwd, maxBuffer: MAX_OUTPUT_BYTES }, (err, stdout) => err ? reject(err) : resolve(stdout));
|
|
86
|
+
});
|
|
87
|
+
const commits = order.split('\n').filter(Boolean);
|
|
88
|
+
if (commits.length === 0)
|
|
89
|
+
return [];
|
|
90
|
+
const byCommit = await new Promise((resolve, reject) => {
|
|
91
|
+
const log = spawn('git', ['log', '-p', '--no-merges', '--no-color', '--format=commit %H', range], { cwd, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
92
|
+
const patchId = spawn('git', ['patch-id', '--stable'], { cwd, stdio: ['pipe', 'pipe', 'pipe'] });
|
|
93
|
+
log.stdout.pipe(patchId.stdin);
|
|
94
|
+
const chunks = [];
|
|
95
|
+
patchId.stdout.on('data', (chunk) => chunks.push(chunk));
|
|
96
|
+
log.on('error', reject);
|
|
97
|
+
patchId.on('error', reject);
|
|
98
|
+
// Both exit codes, whichever process closes last: patch-id can finish before log's close
|
|
99
|
+
// event arrives, and judging then read a successful log as a failed one.
|
|
100
|
+
const closed = (child) => new Promise((done) => child.on('close', done));
|
|
101
|
+
Promise.all([closed(log), closed(patchId)]).then(([logCode, patchCode]) => {
|
|
102
|
+
if (logCode !== 0 || patchCode !== 0) {
|
|
103
|
+
reject(new Error(`git patch-id over ${range} failed`));
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const map = new Map();
|
|
107
|
+
for (const line of Buffer.concat(chunks).toString('utf8').split('\n')) {
|
|
108
|
+
const [id, commit] = line.trim().split(' ');
|
|
109
|
+
if (id && commit)
|
|
110
|
+
map.set(commit, id);
|
|
111
|
+
}
|
|
112
|
+
resolve(map);
|
|
113
|
+
}, reject);
|
|
114
|
+
});
|
|
115
|
+
// A commit with an empty patch has no patch id; it still counts, as an empty one.
|
|
116
|
+
return commits.map((commit) => byCommit.get(commit) ?? '');
|
|
117
|
+
}
|
|
71
118
|
//# sourceMappingURL=exec.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../../../src/core/git/exec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../../../src/core/git/exec.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff-block.d.ts","sourceRoot":"","sources":["../../../src/core/graph/diff-block.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"diff-block.d.ts","sourceRoot":"","sources":["../../../src/core/graph/diff-block.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAyD1D,qIAAqI;AACrI,wBAAgB,WAAW,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,GAAG,MAAM,EAAE,CAIlE;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,GAAG,MAAM,CAKnG"}
|
|
@@ -15,7 +15,15 @@ import { isEmptyDelta } from './diff.js';
|
|
|
15
15
|
function template(name) {
|
|
16
16
|
return packagedTemplate('graph/knowledge-changes', name);
|
|
17
17
|
}
|
|
18
|
-
|
|
18
|
+
/** The reasons a dangling link carries a template for; any other reason is written as the delta names it. */
|
|
19
|
+
const REASON_TEMPLATES = new Set(['not_found', 'ambiguous']);
|
|
20
|
+
function reasonText(reason) {
|
|
21
|
+
return REASON_TEMPLATES.has(reason) ? template(`reason-${reason}`) : reason;
|
|
22
|
+
}
|
|
23
|
+
/** Fills `__TOKEN__` slots; a function replacement, so a `$` in a path is never read as a pattern. */
|
|
24
|
+
function fill(text, values) {
|
|
25
|
+
return Object.entries(values).reduce((out, [token, value]) => out.replaceAll(`__${token}__`, () => value), text);
|
|
26
|
+
}
|
|
19
27
|
function code(text) {
|
|
20
28
|
const longest = Math.max(0, ...[...text.matchAll(/`+/g)].map((match) => match[0].length));
|
|
21
29
|
const fence = '`'.repeat(longest + 1);
|
|
@@ -28,13 +36,14 @@ function bodyLines(delta) {
|
|
|
28
36
|
const lines = counts.split('\n');
|
|
29
37
|
if (delta.dangling.introduced.length > 0) {
|
|
30
38
|
lines.push('', ...template('dangling').split('\n'), '');
|
|
31
|
-
for (const d of delta.dangling.introduced)
|
|
32
|
-
lines.push(
|
|
39
|
+
for (const d of delta.dangling.introduced) {
|
|
40
|
+
lines.push(fill(template('dangling-item'), { FROM: code(d.from), TARGET: code(d.target), REASON: reasonText(d.reason) }));
|
|
41
|
+
}
|
|
33
42
|
}
|
|
34
43
|
if (delta.notes.archived.length > 0) {
|
|
35
44
|
lines.push('', ...template('archived').split('\n'), '');
|
|
36
45
|
for (const r of delta.notes.archived)
|
|
37
|
-
lines.push(
|
|
46
|
+
lines.push(fill(template('archived-item'), { FROM: code(r.from), TO: code(r.to) }));
|
|
38
47
|
}
|
|
39
48
|
return lines;
|
|
40
49
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff-block.js","sourceRoot":"","sources":["../../../src/core/graph/diff-block.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACpE,OAAO,EAAE,YAAY,EAAmB,MAAM,WAAW,CAAC;AAE1D;;;;;;;;;;;GAWG;AACH,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,gBAAgB,CAAC,yBAAyB,EAAE,IAAI,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"diff-block.js","sourceRoot":"","sources":["../../../src/core/graph/diff-block.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,7 +10,8 @@ import { type GraphDelta } from './diff.js';
|
|
|
10
10
|
* The document is a list of parts rather than one string because the review
|
|
11
11
|
* view renders markdown with `html: false`: a `<details>` group is emitted by
|
|
12
12
|
* the caller around its rendered markdown, not parsed out of it. `toMarkdown`
|
|
13
|
-
*
|
|
13
|
+
* writes each group under a `##` heading instead, because its reader is a
|
|
14
|
+
* terminal, where a literal `<details>` tag is noise.
|
|
14
15
|
*/
|
|
15
16
|
export type DiffDocumentPart = {
|
|
16
17
|
kind: 'markdown';
|
|
@@ -31,7 +32,7 @@ export declare const MAX_DIAGRAM_EDGES = 50;
|
|
|
31
32
|
/** D8: added links solid, removed links dashed, nodes labelled by stem; edge types label a typed link. */
|
|
32
33
|
export declare function renderDiagram(added: readonly GraphEdge[], removed: readonly GraphEdge[]): string | null;
|
|
33
34
|
export declare function renderDiffParts(delta: GraphDelta, options?: DiffDocumentOptions): DiffDocumentPart[];
|
|
34
|
-
/** The parts as one markdown document,
|
|
35
|
+
/** The parts as one markdown document, each group under a `##` heading naming it and its count. */
|
|
35
36
|
export declare function toMarkdown(parts: readonly DiffDocumentPart[]): string;
|
|
36
37
|
export declare function renderDiffDocument(delta: GraphDelta, options?: DiffDocumentOptions): string;
|
|
37
38
|
//# sourceMappingURL=diff-document.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff-document.d.ts","sourceRoot":"","sources":["../../../src/core/graph/diff-document.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAE1D
|
|
1
|
+
{"version":3,"file":"diff-document.d.ts","sourceRoot":"","sources":["../../../src/core/graph/diff-document.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAE1D;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvH,MAAM,WAAW,mBAAmB;IAClC,wGAAwG;IACxG,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC9C,sEAAsE;IACtE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,4GAA4G;AAC5G,eAAO,MAAM,iBAAiB,KAAK,CAAC;AA8BpC,0GAA0G;AAC1G,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,EAAE,OAAO,EAAE,SAAS,SAAS,EAAE,GAAG,MAAM,GAAG,IAAI,CAsBvG;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,GAAE,mBAAwB,GAAG,gBAAgB,EAAE,CAuExG;AAED,mGAAmG;AACnG,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,gBAAgB,EAAE,GAAG,MAAM,CAErE;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,GAAE,mBAAwB,GAAG,MAAM,CAE/F"}
|
|
@@ -107,11 +107,9 @@ export function renderDiffParts(delta, options = {}) {
|
|
|
107
107
|
}
|
|
108
108
|
return parts;
|
|
109
109
|
}
|
|
110
|
-
/** The parts as one markdown document,
|
|
110
|
+
/** The parts as one markdown document, each group under a `##` heading naming it and its count. */
|
|
111
111
|
export function toMarkdown(parts) {
|
|
112
|
-
return parts
|
|
113
|
-
.map((part) => part.kind === 'markdown' ? part.text : ['<details>', `<summary>${part.summary}</summary>`, '', part.text, '', '</details>'].join('\n'))
|
|
114
|
-
.join('\n\n');
|
|
112
|
+
return parts.map((part) => (part.kind === 'markdown' ? part.text : [`## ${part.summary}`, '', part.text].join('\n'))).join('\n\n');
|
|
115
113
|
}
|
|
116
114
|
export function renderDiffDocument(delta, options = {}) {
|
|
117
115
|
return `${toMarkdown(renderDiffParts(delta, options))}\n`;
|