@reviewflow/sdk 0.0.0-stage → 6.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +15 -0
- package/README.md +86 -2
- package/build/files-node.mjs +70 -0
- package/build/git-node.mjs +1792 -0
- package/build/index-browser.es.js +3338 -0
- package/build/index-node.mjs +3338 -0
- package/package.json +136 -4
- package/src/api/pullRequest.ts +617 -0
- package/src/config/insertCheckoutEntry.ts +54 -0
- package/src/diff/diffPaths.ts +78 -0
- package/src/diff/impacts.ts +47 -0
- package/src/diff/readingOrder.ts +428 -0
- package/src/diff/themes.ts +105 -0
- package/src/diff/types.ts +141 -0
- package/src/files/editableFile.ts +163 -0
- package/src/files.ts +13 -0
- package/src/git/groupDiffPaths.ts +134 -0
- package/src/git/manifests.ts +96 -0
- package/src/git/moduleBindings.ts +571 -0
- package/src/git/pullRequestDiff.ts +159 -0
- package/src/git/readBranchDiff.ts +359 -0
- package/src/git/readImpacts.ts +797 -0
- package/src/git/readingOrder.ts +190 -0
- package/src/git/run.ts +213 -0
- package/src/git.ts +38 -0
- package/src/github/applySuggestions.ts +399 -0
- package/src/github/editPullRequest.ts +790 -0
- package/src/github/fetchCompareDiff.ts +21 -0
- package/src/github/imageProxies.ts +43 -0
- package/src/github/lineDiff.ts +145 -0
- package/src/github/prQuery.ts +298 -0
- package/src/github/pullRequestDetail.ts +1347 -0
- package/src/github/pullRequestHead.ts +65 -0
- package/src/github/pullRequestRevisions.ts +124 -0
- package/src/github/transport.ts +171 -0
- package/src/index.ts +35 -0
- package/src/reviewflow/board.ts +333 -0
- package/src/reviewflow/changedParts.ts +80 -0
- package/src/reviewflow/checksFromReviewflow.ts +75 -0
- package/src/reviewflow/client.ts +589 -0
- package/src/reviewflow/follow.ts +345 -0
- package/src/reviewflow/status.ts +17 -0
- package/src/reviewflow/stream.ts +199 -0
- package/src/types/entities.ts +8 -0
- package/src/types/ids.ts +1 -0
- package/src/types/reviewflow.ts +32 -0
- package/src/utils/pullRequestEdit.ts +108 -0
- package/src/utils/pullRequestPart.ts +12 -0
- package/src/utils/pullRequestReaction.ts +19 -0
- package/src/utils/pullRequestSuggestion.ts +148 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Copyright (c) 2026 Christophe Hurpeau <302891+christophehurpeau@users.noreply.github.com> (https://christophe.hurpeau.com)
|
|
2
|
+
|
|
3
|
+
Permission to use, copy, modify, and/or distribute this software for
|
|
4
|
+
any purpose with or without fee is hereby granted, provided that the
|
|
5
|
+
above copyright notice and this permission notice appear in all
|
|
6
|
+
copies.
|
|
7
|
+
|
|
8
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
|
9
|
+
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
|
10
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
|
11
|
+
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
|
12
|
+
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
|
13
|
+
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
14
|
+
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
15
|
+
PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,87 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @reviewflow/sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The pull request model behind the [reviewflow](https://github.com/christophehurpeau/reviewflow)
|
|
4
|
+
local app: diff and api types, pure utils, the GitHub layer behind a transport you
|
|
5
|
+
supply, the reviewflow api client, and (node only) reading a pull request diff
|
|
6
|
+
from a local git checkout.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
npm install @reviewflow/sdk
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
ESM only. The node entries need node `>=24.14.1`; the root entry also has a
|
|
15
|
+
browser build.
|
|
16
|
+
|
|
17
|
+
## Entry points
|
|
18
|
+
|
|
19
|
+
| Import | Runs on | What |
|
|
20
|
+
| ----------------------- | ------------- | --------------------------------------------------------------------------------- |
|
|
21
|
+
| `@reviewflow/sdk` | node, browser | types, utils, GitHub queries and edits, reviewflow api client and stream |
|
|
22
|
+
| `@reviewflow/sdk/git` | node | read a diff, reading order and impacts from a local checkout (runs `git`) |
|
|
23
|
+
| `@reviewflow/sdk/files` | node | read and save a text file in place, behind validation and a changed-on-disk check |
|
|
24
|
+
|
|
25
|
+
`@reviewflow/sdk/git` needs a `git` executable on `PATH`.
|
|
26
|
+
|
|
27
|
+
## Wiring
|
|
28
|
+
|
|
29
|
+
The sdk never authenticates nor picks an HTTP client: you inject them.
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import {
|
|
33
|
+
createGitHubTransport,
|
|
34
|
+
createReviewflowClient,
|
|
35
|
+
fetchPullRequestPart,
|
|
36
|
+
} from "@reviewflow/sdk";
|
|
37
|
+
|
|
38
|
+
// GitHub: you send the bytes, the sdk builds the GraphQL, REST and diff calls.
|
|
39
|
+
const transport = createGitHubTransport(
|
|
40
|
+
async ({ method, path, accept, body }) => {
|
|
41
|
+
const response = await fetch(`https://api.github.com/${path}`, {
|
|
42
|
+
method,
|
|
43
|
+
headers: { authorization: `Bearer ${token}`, accept },
|
|
44
|
+
body,
|
|
45
|
+
});
|
|
46
|
+
return { status: response.status, body: await response.text() };
|
|
47
|
+
},
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const detail = await fetchPullRequestPart(
|
|
51
|
+
transport,
|
|
52
|
+
{ ownerRepo: "octocat/hello-world", number: 1 },
|
|
53
|
+
"detail",
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
// reviewflow's read api, with a user's api token (`fetch` is injectable too).
|
|
57
|
+
const reviewflow = createReviewflowClient({
|
|
58
|
+
url: "https://reviewflow.example",
|
|
59
|
+
token: apiToken,
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
On node, `@reviewflow/sdk/git` reads the same pull request from a checkout and
|
|
64
|
+
falls back to GitHub through the same transport:
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
import { readPullRequestDiff } from "@reviewflow/sdk/git";
|
|
68
|
+
|
|
69
|
+
const diff = await readPullRequestDiff({
|
|
70
|
+
checkout: "/path/to/clone", // or null to read from GitHub only
|
|
71
|
+
transport,
|
|
72
|
+
ref: { ownerRepo: "octocat/hello-world", number: 1 },
|
|
73
|
+
head: headSha,
|
|
74
|
+
base: baseSha,
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## TypeScript
|
|
79
|
+
|
|
80
|
+
The `types` condition points at the TypeScript sources (`src/`), which import
|
|
81
|
+
each other with a `.ts` extension. Your `tsconfig.json` needs
|
|
82
|
+
`"allowImportingTsExtensions": true` (with `noEmit` or `emitDeclarationOnly`),
|
|
83
|
+
or the checker reports TS5097 inside this package.
|
|
84
|
+
|
|
85
|
+
## License
|
|
86
|
+
|
|
87
|
+
ISC
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
import { mkdirSync, realpathSync, writeFileSync, chmodSync, statSync, renameSync, unlinkSync, readFileSync } from 'node:fs';
|
|
3
|
+
import { dirname, join, basename } from 'node:path';
|
|
4
|
+
|
|
5
|
+
const isMissing = (error) => error.code === "ENOENT";
|
|
6
|
+
const readCurrent = (path) => {
|
|
7
|
+
try {
|
|
8
|
+
return readFileSync(path, "utf8");
|
|
9
|
+
} catch (error) {
|
|
10
|
+
if (isMissing(error)) return null;
|
|
11
|
+
throw error;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
const readEditableFile = (path) => {
|
|
15
|
+
const source = readCurrent(path);
|
|
16
|
+
return source === null ? { source: "", exists: false } : { source, exists: true };
|
|
17
|
+
};
|
|
18
|
+
const validationOf = async (validate, source) => {
|
|
19
|
+
try {
|
|
20
|
+
return await validate(source);
|
|
21
|
+
} catch (error) {
|
|
22
|
+
return { error: error instanceof Error ? error.message : String(error) };
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
const saveEditableFile = async ({
|
|
26
|
+
path,
|
|
27
|
+
source,
|
|
28
|
+
expectedSource,
|
|
29
|
+
validate,
|
|
30
|
+
trailingNewline = true
|
|
31
|
+
}) => {
|
|
32
|
+
const text = trailingNewline && source !== "" && !source.endsWith("\n") ? `${source}
|
|
33
|
+
` : source;
|
|
34
|
+
const validation = await validationOf(validate, text);
|
|
35
|
+
if ("error" in validation) {
|
|
36
|
+
return { status: "invalid", error: validation.error };
|
|
37
|
+
}
|
|
38
|
+
const current = readCurrent(path);
|
|
39
|
+
if (expectedSource !== void 0) {
|
|
40
|
+
const conflicts = expectedSource === null ? current !== null : (current ?? "") !== expectedSource;
|
|
41
|
+
if (conflicts) {
|
|
42
|
+
return {
|
|
43
|
+
status: "conflict",
|
|
44
|
+
source: current ?? "",
|
|
45
|
+
exists: current !== null
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
50
|
+
const target = current === null ? path : realpathSync(path);
|
|
51
|
+
const temporary = join(
|
|
52
|
+
dirname(target),
|
|
53
|
+
`.${basename(target)}.${String(process.pid)}.${randomBytes(4).toString("hex")}.tmp`
|
|
54
|
+
);
|
|
55
|
+
try {
|
|
56
|
+
writeFileSync(temporary, text);
|
|
57
|
+
if (current !== null) chmodSync(temporary, statSync(target).mode & 4095);
|
|
58
|
+
renameSync(temporary, target);
|
|
59
|
+
} catch (error) {
|
|
60
|
+
try {
|
|
61
|
+
unlinkSync(temporary);
|
|
62
|
+
} catch {
|
|
63
|
+
}
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
return { status: "saved", source: text, warnings: validation.warnings };
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export { readEditableFile, saveEditableFile };
|
|
70
|
+
//# sourceMappingURL=files-node.mjs.map
|