@a9n-shoji/rvw 0.4.1 → 0.4.3
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/CHANGELOG.md +26 -0
- package/dist/cli.mjs +526 -147
- package/dist/cli.mjs.map +3 -3
- package/dist/web/assets/DocumentViewer-CWTnSlpG.js +1420 -0
- package/dist/web/assets/{FileIcon-AhP8Ezk9.js → FileIcon-wDKKQgGv.js} +94 -94
- package/dist/web/assets/{MarkdownTable-Clfr8wUw.js → MarkdownTable-IiPLNTUX.js} +1 -1
- package/dist/web/assets/{MermaidExpandedView-BjmXfluL.js → MermaidExpandedView-BT6F4F2R.js} +2 -2
- package/dist/web/assets/{MermaidSurface-B2Z3pJme.js → MermaidSurface-CKiZv7R8.js} +1 -1
- package/dist/web/assets/{StructureViewer-B0fkdcLj.js → StructureViewer-EKDvAQ2a.js} +2 -2
- package/dist/web/assets/{WalkthroughPanel-BGgWu0bA.js → WalkthroughPanel-D2KqSIf9.js} +20 -20
- package/dist/web/assets/WalkthroughViewer-BDb-99Qk.js +43 -0
- package/dist/web/assets/{index-B3zKWMdE.css → index-B0xRoLW2.css} +1 -1
- package/dist/web/assets/index-DC6BgBp4.js +11 -0
- package/dist/web/index.html +5 -5
- package/migrations/017_domain_revisions.sql +14 -0
- package/package.json +1 -1
- package/dist/web/assets/DocumentViewer-cnnF6CLV.js +0 -1420
- package/dist/web/assets/WalkthroughViewer-DdPfdT2-.js +0 -43
- package/dist/web/assets/index-qmzlYGCz.js +0 -11
package/dist/cli.mjs
CHANGED
|
@@ -18947,6 +18947,13 @@ function secureNewPath(targetPath, expectedMode, label, chmod = chmodSync) {
|
|
|
18947
18947
|
}
|
|
18948
18948
|
assertSecureExistingPath(targetPath, expectedMode, label);
|
|
18949
18949
|
}
|
|
18950
|
+
var domainRevisionMetaKeys = {
|
|
18951
|
+
pullRequests: "revision_pull_requests",
|
|
18952
|
+
pullRequestContent: "revision_pull_request_content",
|
|
18953
|
+
comments: "revision_comments",
|
|
18954
|
+
walkthroughs: "revision_walkthroughs",
|
|
18955
|
+
structures: "revision_structures"
|
|
18956
|
+
};
|
|
18950
18957
|
var RvwDatabase = class {
|
|
18951
18958
|
filePath;
|
|
18952
18959
|
configuredPath;
|
|
@@ -19090,10 +19097,69 @@ var RvwDatabase = class {
|
|
|
19090
19097
|
).run();
|
|
19091
19098
|
return this.getChangeSequence();
|
|
19092
19099
|
}
|
|
19100
|
+
incrementDomainRevisions(domains) {
|
|
19101
|
+
const uniqueDomains = [...new Set(domains)];
|
|
19102
|
+
this.incrementChangeSequence();
|
|
19103
|
+
const increment2 = this.database.prepare(
|
|
19104
|
+
"UPDATE app_meta SET value = CAST(CAST(value AS INTEGER) + 1 AS TEXT) WHERE key = ?"
|
|
19105
|
+
);
|
|
19106
|
+
for (const domain2 of uniqueDomains) increment2.run(domainRevisionMetaKeys[domain2]);
|
|
19107
|
+
return this.getChangeSequence();
|
|
19108
|
+
}
|
|
19093
19109
|
getChangeSequence() {
|
|
19094
19110
|
const row = this.database.prepare("SELECT value FROM app_meta WHERE key = 'change_sequence'").get();
|
|
19095
19111
|
return Number(stringValue(row, "value"));
|
|
19096
19112
|
}
|
|
19113
|
+
getRevisionSnapshot() {
|
|
19114
|
+
const rows = this.database.prepare(
|
|
19115
|
+
`SELECT key, value
|
|
19116
|
+
FROM app_meta
|
|
19117
|
+
WHERE key IN (
|
|
19118
|
+
'change_sequence',
|
|
19119
|
+
'revision_pull_requests',
|
|
19120
|
+
'revision_pull_request_content',
|
|
19121
|
+
'revision_comments',
|
|
19122
|
+
'revision_walkthroughs',
|
|
19123
|
+
'revision_structures'
|
|
19124
|
+
)`
|
|
19125
|
+
).all();
|
|
19126
|
+
const values = new Map(rows.map((row) => [stringValue(row, "key"), stringValue(row, "value")]));
|
|
19127
|
+
const value = (key2) => {
|
|
19128
|
+
const raw3 = values.get(key2);
|
|
19129
|
+
if (raw3 === void 0) throw new RvwError("DATABASE_ERROR", `revision\u304C\u3042\u308A\u307E\u305B\u3093: ${key2}`);
|
|
19130
|
+
return Number(raw3);
|
|
19131
|
+
};
|
|
19132
|
+
return {
|
|
19133
|
+
changeSequence: value("change_sequence"),
|
|
19134
|
+
revisions: {
|
|
19135
|
+
pullRequests: value(domainRevisionMetaKeys.pullRequests),
|
|
19136
|
+
pullRequestContent: value(domainRevisionMetaKeys.pullRequestContent),
|
|
19137
|
+
comments: value(domainRevisionMetaKeys.comments),
|
|
19138
|
+
walkthroughs: value(domainRevisionMetaKeys.walkthroughs),
|
|
19139
|
+
structures: value(domainRevisionMetaKeys.structures)
|
|
19140
|
+
}
|
|
19141
|
+
};
|
|
19142
|
+
}
|
|
19143
|
+
getDomainRevisions() {
|
|
19144
|
+
return this.getRevisionSnapshot().revisions;
|
|
19145
|
+
}
|
|
19146
|
+
getPullRequestRevisionSnapshot(id) {
|
|
19147
|
+
this.database.exec("BEGIN");
|
|
19148
|
+
try {
|
|
19149
|
+
const result = {
|
|
19150
|
+
pullRequest: this.getPullRequest(id),
|
|
19151
|
+
revisionSnapshot: this.getRevisionSnapshot()
|
|
19152
|
+
};
|
|
19153
|
+
this.database.exec("COMMIT");
|
|
19154
|
+
return result;
|
|
19155
|
+
} catch (error51) {
|
|
19156
|
+
try {
|
|
19157
|
+
this.database.exec("ROLLBACK");
|
|
19158
|
+
} catch {
|
|
19159
|
+
}
|
|
19160
|
+
throw error51;
|
|
19161
|
+
}
|
|
19162
|
+
}
|
|
19097
19163
|
getCommentWatchDatabaseId() {
|
|
19098
19164
|
const row = this.database.prepare("SELECT value FROM app_meta WHERE key = 'comment_watch_database_id'").get();
|
|
19099
19165
|
if (!row) throw new RvwError("DATABASE_ERROR", "comment watch\u306Edatabase ID\u304C\u3042\u308A\u307E\u305B\u3093\u3002");
|
|
@@ -19246,7 +19312,19 @@ var RvwDatabase = class {
|
|
|
19246
19312
|
const statement = this.database.prepare(
|
|
19247
19313
|
"UPDATE pull_requests SET github_state = ?, github_is_draft = ? WHERE id = ?"
|
|
19248
19314
|
);
|
|
19315
|
+
let changed = false;
|
|
19249
19316
|
for (const update of updates) {
|
|
19317
|
+
const current = this.getPullRequest(update.pullRequestId);
|
|
19318
|
+
if (!current) {
|
|
19319
|
+
throw new RvwError(
|
|
19320
|
+
"PR_NOT_FOUND",
|
|
19321
|
+
`Pull Request\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093: ${update.pullRequestId}`,
|
|
19322
|
+
{ status: 404 }
|
|
19323
|
+
);
|
|
19324
|
+
}
|
|
19325
|
+
if (current.githubState === update.state && current.githubIsDraft === update.isDraft) {
|
|
19326
|
+
continue;
|
|
19327
|
+
}
|
|
19250
19328
|
const result = statement.run(update.state, update.isDraft ? 1 : 0, update.pullRequestId);
|
|
19251
19329
|
if (Number(result.changes) !== 1) {
|
|
19252
19330
|
throw new RvwError(
|
|
@@ -19255,18 +19333,24 @@ var RvwDatabase = class {
|
|
|
19255
19333
|
{ status: 404 }
|
|
19256
19334
|
);
|
|
19257
19335
|
}
|
|
19336
|
+
changed = true;
|
|
19258
19337
|
}
|
|
19259
|
-
this.
|
|
19338
|
+
if (changed) this.incrementDomainRevisions(["pullRequests"]);
|
|
19260
19339
|
});
|
|
19261
19340
|
}
|
|
19262
19341
|
updateRepositoryLocation(id, repository) {
|
|
19342
|
+
const existing = this.getPullRequest(id);
|
|
19343
|
+
if (!existing) throw new RvwError("PR_NOT_FOUND", "Pull Request\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002");
|
|
19344
|
+
if (existing.localRepositoryPath === repository.localRepositoryPath && existing.gitCommonDir === repository.gitCommonDir) {
|
|
19345
|
+
return existing;
|
|
19346
|
+
}
|
|
19263
19347
|
this.immediateTransaction(() => {
|
|
19264
19348
|
const result = this.database.prepare(
|
|
19265
19349
|
"UPDATE pull_requests SET local_repository_path = ?, git_common_dir = ?, updated_at = ? WHERE id = ?"
|
|
19266
19350
|
).run(repository.localRepositoryPath, repository.gitCommonDir, (/* @__PURE__ */ new Date()).toISOString(), id);
|
|
19267
19351
|
if (Number(result.changes) === 0)
|
|
19268
19352
|
throw new RvwError("PR_NOT_FOUND", "Pull Request\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002");
|
|
19269
|
-
this.
|
|
19353
|
+
this.incrementDomainRevisions(["pullRequests"]);
|
|
19270
19354
|
});
|
|
19271
19355
|
const pullRequest = this.getPullRequest(id);
|
|
19272
19356
|
if (!pullRequest) throw new RvwError("PR_NOT_FOUND", "Pull Request\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002");
|
|
@@ -19276,6 +19360,8 @@ var RvwDatabase = class {
|
|
|
19276
19360
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
19277
19361
|
const existing = this.findPullRequestByIdentity(github.owner, github.repository, github.number);
|
|
19278
19362
|
const id = existing?.id ?? randomUUID();
|
|
19363
|
+
const contentChanged = !existing || existing.latestTitle !== github.title || existing.latestBody !== github.body;
|
|
19364
|
+
const semanticChanged = !existing || existing.url !== github.url || existing.latestAuthorLogin !== github.authorLogin || existing.latestHeadRepositoryOwner !== github.headRepositoryOwner || existing.latestHeadRepositoryName !== github.headRepositoryName || existing.localRepositoryPath !== repository.localRepositoryPath || existing.gitCommonDir !== repository.gitCommonDir || contentChanged || existing.latestBaseRefName !== github.baseRefName || existing.latestHeadRefName !== github.headRefName || existing.latestBaseOid !== github.baseOid || existing.latestComparisonBaseOid !== comparisonBaseOid || existing.latestHeadOid !== github.headOid || existing.githubCreatedAt !== github.createdAt || existing.githubUpdatedAt !== github.updatedAt || existing.githubState !== github.state || existing.githubIsDraft !== github.isDraft;
|
|
19279
19365
|
this.database.prepare(
|
|
19280
19366
|
`INSERT INTO pull_requests(
|
|
19281
19367
|
id, host, owner, repository, number, github_url,
|
|
@@ -19329,16 +19415,19 @@ var RvwDatabase = class {
|
|
|
19329
19415
|
github.isDraft ? 1 : 0,
|
|
19330
19416
|
now,
|
|
19331
19417
|
existing?.createdAt ?? now,
|
|
19332
|
-
now,
|
|
19418
|
+
semanticChanged ? now : existing.updatedAt,
|
|
19333
19419
|
comparisonBaseOid
|
|
19334
19420
|
);
|
|
19335
|
-
return id;
|
|
19421
|
+
return { id, semanticChanged, contentChanged };
|
|
19336
19422
|
}
|
|
19337
19423
|
upsertPullRequest(github, repository, comparisonBaseOid) {
|
|
19338
19424
|
const id = this.immediateTransaction(() => {
|
|
19339
|
-
const
|
|
19340
|
-
|
|
19341
|
-
|
|
19425
|
+
const write = this.writePullRequest(github, repository, comparisonBaseOid);
|
|
19426
|
+
const domains = [];
|
|
19427
|
+
if (write.semanticChanged) domains.push("pullRequests");
|
|
19428
|
+
if (write.contentChanged) domains.push("pullRequestContent");
|
|
19429
|
+
if (domains.length > 0) this.incrementDomainRevisions(domains);
|
|
19430
|
+
return write.id;
|
|
19342
19431
|
});
|
|
19343
19432
|
const pullRequest = this.getPullRequest(id);
|
|
19344
19433
|
if (!pullRequest)
|
|
@@ -19347,10 +19436,14 @@ var RvwDatabase = class {
|
|
|
19347
19436
|
}
|
|
19348
19437
|
syncPullRequestAndComments(github, repository, comparisonBaseOid, updates) {
|
|
19349
19438
|
const id = this.immediateTransaction(() => {
|
|
19350
|
-
const
|
|
19351
|
-
this.applyCommentUpdates(updates, github.headOid);
|
|
19352
|
-
|
|
19353
|
-
|
|
19439
|
+
const write = this.writePullRequest(github, repository, comparisonBaseOid);
|
|
19440
|
+
const commentsChanged = this.applyCommentUpdates(updates, github.headOid);
|
|
19441
|
+
const domains = [];
|
|
19442
|
+
if (write.semanticChanged) domains.push("pullRequests");
|
|
19443
|
+
if (write.contentChanged) domains.push("pullRequestContent");
|
|
19444
|
+
if (commentsChanged) domains.push("comments");
|
|
19445
|
+
if (domains.length > 0) this.incrementDomainRevisions(domains);
|
|
19446
|
+
return write.id;
|
|
19354
19447
|
});
|
|
19355
19448
|
const pullRequest = this.getPullRequest(id);
|
|
19356
19449
|
if (!pullRequest)
|
|
@@ -19359,10 +19452,16 @@ var RvwDatabase = class {
|
|
|
19359
19452
|
}
|
|
19360
19453
|
resetPullRequest(github, repository, comparisonBaseOid) {
|
|
19361
19454
|
const id = this.immediateTransaction(() => {
|
|
19362
|
-
const
|
|
19363
|
-
this.deletePullRequestHistory(
|
|
19364
|
-
this.
|
|
19365
|
-
|
|
19455
|
+
const write = this.writePullRequest(github, repository, comparisonBaseOid);
|
|
19456
|
+
this.deletePullRequestHistory(write.id);
|
|
19457
|
+
this.incrementDomainRevisions([
|
|
19458
|
+
"pullRequests",
|
|
19459
|
+
"pullRequestContent",
|
|
19460
|
+
"comments",
|
|
19461
|
+
"walkthroughs",
|
|
19462
|
+
"structures"
|
|
19463
|
+
]);
|
|
19464
|
+
return write.id;
|
|
19366
19465
|
});
|
|
19367
19466
|
const pullRequest = this.getPullRequest(id);
|
|
19368
19467
|
if (!pullRequest)
|
|
@@ -19496,7 +19595,7 @@ var RvwDatabase = class {
|
|
|
19496
19595
|
key_hash, request_hash, structure_id, created_at
|
|
19497
19596
|
) VALUES (?, ?, ?, ?)`
|
|
19498
19597
|
).run(keyHash, input.idempotencyRequestHash, id, now);
|
|
19499
|
-
this.
|
|
19598
|
+
this.incrementDomainRevisions(["structures"]);
|
|
19500
19599
|
structureId = id;
|
|
19501
19600
|
});
|
|
19502
19601
|
if (!structureId) {
|
|
@@ -19579,7 +19678,7 @@ var RvwDatabase = class {
|
|
|
19579
19678
|
"INSERT OR IGNORE INTO structure_retired_edge_ids(structure_id, edge_id, retired_at) VALUES (?, ?, ?)"
|
|
19580
19679
|
);
|
|
19581
19680
|
for (const edgeId of retiredEdgesAtThisUpdate) retireEdge.run(id, edgeId, now);
|
|
19582
|
-
this.
|
|
19681
|
+
this.incrementDomainRevisions(["structures"]);
|
|
19583
19682
|
});
|
|
19584
19683
|
const structure = this.getStructure(id);
|
|
19585
19684
|
if (!structure) throw new RvwError("DATABASE_ERROR", "\u66F4\u65B0\u3057\u305FStructure\u3092\u8AAD\u307F\u51FA\u305B\u307E\u305B\u3093\u3002");
|
|
@@ -19619,7 +19718,7 @@ var RvwDatabase = class {
|
|
|
19619
19718
|
{ status: 409, details: { expectedUpdatedAt: expectedUpdatedAt2 } }
|
|
19620
19719
|
);
|
|
19621
19720
|
}
|
|
19622
|
-
this.
|
|
19721
|
+
this.incrementDomainRevisions(["structures"]);
|
|
19623
19722
|
return {
|
|
19624
19723
|
id: structure.id,
|
|
19625
19724
|
ref: structure.ref,
|
|
@@ -19715,7 +19814,7 @@ var RvwDatabase = class {
|
|
|
19715
19814
|
now
|
|
19716
19815
|
);
|
|
19717
19816
|
this.insertCodeReferences("walkthrough", id, input.references);
|
|
19718
|
-
this.
|
|
19817
|
+
this.incrementDomainRevisions(["walkthroughs"]);
|
|
19719
19818
|
});
|
|
19720
19819
|
const walkthrough = this.getWalkthrough(id);
|
|
19721
19820
|
if (!walkthrough) {
|
|
@@ -19742,7 +19841,7 @@ var RvwDatabase = class {
|
|
|
19742
19841
|
}
|
|
19743
19842
|
this.database.prepare("DELETE FROM walkthrough_references WHERE walkthrough_id = ?").run(id);
|
|
19744
19843
|
this.insertCodeReferences("walkthrough", id, input.references);
|
|
19745
|
-
this.
|
|
19844
|
+
this.incrementDomainRevisions(["walkthroughs"]);
|
|
19746
19845
|
});
|
|
19747
19846
|
const walkthrough = this.getWalkthrough(id);
|
|
19748
19847
|
if (!walkthrough) {
|
|
@@ -19778,7 +19877,9 @@ var RvwDatabase = class {
|
|
|
19778
19877
|
WHERE id IN (SELECT comment_id FROM comment_targets WHERE walkthrough_id = ?)`
|
|
19779
19878
|
).run(id);
|
|
19780
19879
|
this.database.prepare("DELETE FROM walkthroughs WHERE id = ?").run(id);
|
|
19781
|
-
this.
|
|
19880
|
+
this.incrementDomainRevisions(
|
|
19881
|
+
counts.comments === 0 ? ["walkthroughs"] : ["walkthroughs", "comments"]
|
|
19882
|
+
);
|
|
19782
19883
|
return {
|
|
19783
19884
|
id: walkthrough.id,
|
|
19784
19885
|
ref: walkthrough.ref,
|
|
@@ -19816,7 +19917,7 @@ var RvwDatabase = class {
|
|
|
19816
19917
|
post_id, comment_ref, pull_request_url, created_at
|
|
19817
19918
|
) VALUES (?, ?, ?, ?)`
|
|
19818
19919
|
).run(postId, formatCommentUri(id), pullRequest.url, now);
|
|
19819
|
-
this.
|
|
19920
|
+
this.incrementDomainRevisions(["comments"]);
|
|
19820
19921
|
});
|
|
19821
19922
|
const comment3 = this.getComment(id);
|
|
19822
19923
|
if (!comment3) throw new RvwError("DATABASE_ERROR", "\u4FDD\u5B58\u3057\u305F\u30B3\u30E1\u30F3\u30C8\u3092\u8AAD\u307F\u51FA\u305B\u307E\u305B\u3093\u3002");
|
|
@@ -19935,7 +20036,7 @@ var RvwDatabase = class {
|
|
|
19935
20036
|
FROM comments c
|
|
19936
20037
|
JOIN comment_targets t ON t.comment_id = c.id
|
|
19937
20038
|
LEFT JOIN walkthroughs w ON w.id = t.walkthrough_id
|
|
19938
|
-
WHERE c.pull_request_id = ?${where} ORDER BY c.updated_at DESC`
|
|
20039
|
+
WHERE c.pull_request_id = ?${where} ORDER BY c.updated_at DESC, c.id DESC`
|
|
19939
20040
|
).all(pullRequestId).map((row) => this.mapComment(row));
|
|
19940
20041
|
}
|
|
19941
20042
|
listCommentPage(pullRequestId, resolved, limit, offset) {
|
|
@@ -20061,7 +20162,7 @@ var RvwDatabase = class {
|
|
|
20061
20162
|
).run(idempotencyKeyHash, idempotencyRequestHash2, id, now);
|
|
20062
20163
|
}
|
|
20063
20164
|
this.database.prepare("UPDATE comments SET updated_at = ? WHERE id = ?").run(now, commentId);
|
|
20064
|
-
if (incrementSequence) this.
|
|
20165
|
+
if (incrementSequence) this.incrementDomainRevisions(["comments"]);
|
|
20065
20166
|
result = {
|
|
20066
20167
|
id,
|
|
20067
20168
|
commentId,
|
|
@@ -20096,7 +20197,7 @@ var RvwDatabase = class {
|
|
|
20096
20197
|
this.database.prepare("DELETE FROM comment_post_references WHERE post_id = ?").run(postId);
|
|
20097
20198
|
this.insertCodeReferences("comment-post", postId, references);
|
|
20098
20199
|
this.database.prepare("UPDATE comments SET updated_at = ? WHERE id = ?").run(now, commentId);
|
|
20099
|
-
this.
|
|
20200
|
+
this.incrementDomainRevisions(["comments"]);
|
|
20100
20201
|
});
|
|
20101
20202
|
const post = this.getCommentPost(postId);
|
|
20102
20203
|
if (!post) {
|
|
@@ -20128,7 +20229,7 @@ var RvwDatabase = class {
|
|
|
20128
20229
|
this.immediateTransaction(() => {
|
|
20129
20230
|
this.database.prepare("DELETE FROM comment_posts WHERE id = ? AND comment_id = ?").run(postId, commentId);
|
|
20130
20231
|
this.database.prepare("UPDATE comments SET updated_at = ? WHERE id = ?").run(now, commentId);
|
|
20131
|
-
this.
|
|
20232
|
+
this.incrementDomainRevisions(["comments"]);
|
|
20132
20233
|
});
|
|
20133
20234
|
return { commentId, postId };
|
|
20134
20235
|
}
|
|
@@ -20138,7 +20239,7 @@ var RvwDatabase = class {
|
|
|
20138
20239
|
const result = this.database.prepare("UPDATE comments SET resolved_at = ?, updated_at = ? WHERE id = ?").run(resolved ? now : null, now, commentId);
|
|
20139
20240
|
if (Number(result.changes) === 0)
|
|
20140
20241
|
throw new RvwError("COMMENT_NOT_FOUND", "\u30B3\u30E1\u30F3\u30C8\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002");
|
|
20141
|
-
if (incrementSequence) this.
|
|
20242
|
+
if (incrementSequence) this.incrementDomainRevisions(["comments"]);
|
|
20142
20243
|
};
|
|
20143
20244
|
if (incrementSequence) this.immediateTransaction(write);
|
|
20144
20245
|
else write();
|
|
@@ -20153,14 +20254,18 @@ var RvwDatabase = class {
|
|
|
20153
20254
|
}
|
|
20154
20255
|
this.immediateTransaction(() => {
|
|
20155
20256
|
this.database.prepare("DELETE FROM comments WHERE id = ?").run(commentId);
|
|
20156
|
-
this.
|
|
20257
|
+
this.incrementDomainRevisions(["comments"]);
|
|
20157
20258
|
});
|
|
20158
20259
|
return { id: comment3.id, ref: comment3.ref };
|
|
20159
20260
|
}
|
|
20160
20261
|
applyCommentUpdates(updates, relatedCommitOid) {
|
|
20262
|
+
let changed = false;
|
|
20161
20263
|
for (const update of updates) {
|
|
20264
|
+
const current = this.getComment(update.commentId);
|
|
20265
|
+
if (!current) throw new RvwError("COMMENT_NOT_FOUND", "\u30B3\u30E1\u30F3\u30C8\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002");
|
|
20162
20266
|
if (update.reply.trim().length > 0) {
|
|
20163
|
-
|
|
20267
|
+
const existingPostIds = new Set(current.posts.map(({ id }) => id));
|
|
20268
|
+
const reply = this.insertReply(
|
|
20164
20269
|
update.commentId,
|
|
20165
20270
|
{
|
|
20166
20271
|
body: update.reply,
|
|
@@ -20173,11 +20278,14 @@ var RvwDatabase = class {
|
|
|
20173
20278
|
},
|
|
20174
20279
|
false
|
|
20175
20280
|
);
|
|
20176
|
-
|
|
20177
|
-
|
|
20281
|
+
if (!existingPostIds.has(reply.id)) changed = true;
|
|
20282
|
+
}
|
|
20283
|
+
if (update.resolve && current.resolvedAt === null) {
|
|
20284
|
+
this.setCommentResolved(update.commentId, true, false);
|
|
20285
|
+
changed = true;
|
|
20178
20286
|
}
|
|
20179
|
-
if (update.resolve) this.setCommentResolved(update.commentId, true, false);
|
|
20180
20287
|
}
|
|
20288
|
+
return changed;
|
|
20181
20289
|
}
|
|
20182
20290
|
};
|
|
20183
20291
|
|
|
@@ -20187,12 +20295,13 @@ import path5 from "node:path";
|
|
|
20187
20295
|
import { TextDecoder as TextDecoder2 } from "node:util";
|
|
20188
20296
|
|
|
20189
20297
|
// src/shared/constants.ts
|
|
20190
|
-
var APP_VERSION = "0.4.
|
|
20298
|
+
var APP_VERSION = "0.4.3";
|
|
20191
20299
|
var PROTOCOL_VERSION = 4;
|
|
20192
20300
|
var VIEWER_ID_HEADER = "x-rvw-viewer-id";
|
|
20193
20301
|
var VIEWER_OPEN_LEASE_HEADER = "x-rvw-viewer-open-lease";
|
|
20194
20302
|
var VIEWER_OPEN_LEASE_QUERY = "viewerLease";
|
|
20195
20303
|
var GIT_OBJECT_ID_PATTERN = /^[0-9a-f]{40,64}$/i;
|
|
20304
|
+
var CONTENT_FINGERPRINT_PATTERN = /^[0-9a-f]{64}$/;
|
|
20196
20305
|
var MAX_TEXT_DOCUMENT_BYTES = 1024 * 1024;
|
|
20197
20306
|
var MAX_MARKDOWN_ASSET_BYTES = 5 * 1024 * 1024;
|
|
20198
20307
|
var MAX_GITHUB_ATTACHMENT_BYTES = 10 * 1024 * 1024;
|
|
@@ -28386,6 +28495,9 @@ ${normalizeLf(body3)}`;
|
|
|
28386
28495
|
function hashDocument(value) {
|
|
28387
28496
|
return createHash2("sha256").update(normalizeLf(value), "utf8").digest("hex");
|
|
28388
28497
|
}
|
|
28498
|
+
function pullRequestContentFingerprint(title, body3) {
|
|
28499
|
+
return hashDocument(buildPullRequestMarkdown(title, body3));
|
|
28500
|
+
}
|
|
28389
28501
|
function selectedLineText(value, startLine, endLine) {
|
|
28390
28502
|
const lines2 = normalizeLf(value).split("\n");
|
|
28391
28503
|
if (startLine < 1 || endLine < startLine || endLine > lines2.length) return null;
|
|
@@ -41706,6 +41818,20 @@ function assertCodeReferencePath(filePath) {
|
|
|
41706
41818
|
throw new RvwError("INVALID_INPUT", `code reference\u306Epath\u304C\u4E0D\u6B63\u3067\u3059: ${filePath}`);
|
|
41707
41819
|
}
|
|
41708
41820
|
}
|
|
41821
|
+
async function mapWithConcurrency(values, concurrency, mapper) {
|
|
41822
|
+
const results = new Array(values.length);
|
|
41823
|
+
let nextIndex = 0;
|
|
41824
|
+
const worker = async () => {
|
|
41825
|
+
while (nextIndex < values.length) {
|
|
41826
|
+
const index2 = nextIndex++;
|
|
41827
|
+
results[index2] = await mapper(values[index2], index2);
|
|
41828
|
+
}
|
|
41829
|
+
};
|
|
41830
|
+
await Promise.all(
|
|
41831
|
+
Array.from({ length: Math.min(concurrency, values.length) }, async () => await worker())
|
|
41832
|
+
);
|
|
41833
|
+
return results;
|
|
41834
|
+
}
|
|
41709
41835
|
var RvwService = class {
|
|
41710
41836
|
constructor(database, git, github) {
|
|
41711
41837
|
this.database = database;
|
|
@@ -42093,7 +42219,10 @@ var RvwService = class {
|
|
|
42093
42219
|
});
|
|
42094
42220
|
}
|
|
42095
42221
|
async getPullRequestView(id) {
|
|
42096
|
-
const pullRequest = this.
|
|
42222
|
+
const { pullRequest, revisionSnapshot } = this.database.getPullRequestRevisionSnapshot(id);
|
|
42223
|
+
if (!pullRequest) {
|
|
42224
|
+
throw new RvwError("PR_NOT_FOUND", "Pull Request\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002", { status: 404 });
|
|
42225
|
+
}
|
|
42097
42226
|
const commits = await this.git.commits(
|
|
42098
42227
|
pullRequest.localRepositoryPath,
|
|
42099
42228
|
pullRequest.latestComparisonBaseOid,
|
|
@@ -42101,11 +42230,30 @@ var RvwService = class {
|
|
|
42101
42230
|
);
|
|
42102
42231
|
return {
|
|
42103
42232
|
pullRequest,
|
|
42233
|
+
pullRequestContentFingerprint: pullRequestContentFingerprint(
|
|
42234
|
+
pullRequest.latestTitle,
|
|
42235
|
+
pullRequest.latestBody
|
|
42236
|
+
),
|
|
42104
42237
|
comparisonBaseOid: pullRequest.latestComparisonBaseOid,
|
|
42105
42238
|
headOid: pullRequest.latestHeadOid,
|
|
42106
|
-
commits
|
|
42239
|
+
commits,
|
|
42240
|
+
...revisionSnapshot
|
|
42107
42241
|
};
|
|
42108
42242
|
}
|
|
42243
|
+
assertPullRequestContentFingerprint(pullRequest, expectedFingerprint) {
|
|
42244
|
+
const actualFingerprint = pullRequestContentFingerprint(
|
|
42245
|
+
pullRequest.latestTitle,
|
|
42246
|
+
pullRequest.latestBody
|
|
42247
|
+
);
|
|
42248
|
+
if (expectedFingerprint !== void 0 && expectedFingerprint !== actualFingerprint) {
|
|
42249
|
+
throw new RvwError("STALE_CONTENT", "Pull Request\u672C\u6587\u304C\u66F4\u65B0\u3055\u308C\u3066\u3044\u307E\u3059\u3002", {
|
|
42250
|
+
status: 409,
|
|
42251
|
+
details: { expectedFingerprint, actualFingerprint },
|
|
42252
|
+
suggestions: ["\u6700\u65B0\u306EPull Request\u672C\u6587\u3092\u518D\u53D6\u5F97\u3057\u3066\u304F\u3060\u3055\u3044\u3002"]
|
|
42253
|
+
});
|
|
42254
|
+
}
|
|
42255
|
+
return actualFingerprint;
|
|
42256
|
+
}
|
|
42109
42257
|
async assertCommitAvailable(pullRequest, oid) {
|
|
42110
42258
|
if (!GIT_OBJECT_ID_PATTERN.test(oid) || !await this.git.hasObject(pullRequest.localRepositoryPath, oid)) {
|
|
42111
42259
|
throw new RvwError("COMMIT_NOT_FOUND", `Git commit\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093: ${oid}`, { status: 404 });
|
|
@@ -42162,6 +42310,26 @@ var RvwService = class {
|
|
|
42162
42310
|
);
|
|
42163
42311
|
return { ref, ...content3 };
|
|
42164
42312
|
}
|
|
42313
|
+
async getDocumentWithContentFingerprint(ref, expectedFingerprint) {
|
|
42314
|
+
if (ref.kind !== "pull-request-markdown") {
|
|
42315
|
+
return { document: await this.getDocument(ref), pullRequestContentFingerprint: null };
|
|
42316
|
+
}
|
|
42317
|
+
const pullRequest = this.getPullRequest(ref.pullRequestId);
|
|
42318
|
+
const fingerprint = this.assertPullRequestContentFingerprint(pullRequest, expectedFingerprint);
|
|
42319
|
+
const text5 = buildPullRequestMarkdown(pullRequest.latestTitle, pullRequest.latestBody);
|
|
42320
|
+
return {
|
|
42321
|
+
document: {
|
|
42322
|
+
ref,
|
|
42323
|
+
availability: "available",
|
|
42324
|
+
text: text5,
|
|
42325
|
+
byteLength: Buffer.byteLength(text5, "utf8"),
|
|
42326
|
+
entryKind: "virtual",
|
|
42327
|
+
normalizedLineEndings: false,
|
|
42328
|
+
oid: null
|
|
42329
|
+
},
|
|
42330
|
+
pullRequestContentFingerprint: fingerprint
|
|
42331
|
+
};
|
|
42332
|
+
}
|
|
42165
42333
|
async getRepositoryAsset(pullRequestId, sourceOid, filePath) {
|
|
42166
42334
|
const pullRequest = this.getPullRequest(pullRequestId);
|
|
42167
42335
|
await this.assertCommitAvailable(pullRequest, sourceOid);
|
|
@@ -42189,7 +42357,7 @@ var RvwService = class {
|
|
|
42189
42357
|
]);
|
|
42190
42358
|
return { ref, old, new: next2 };
|
|
42191
42359
|
}
|
|
42192
|
-
async search(pullRequestId, oid, query, options) {
|
|
42360
|
+
async search(pullRequestId, oid, query, options, expectedPullRequestContentFingerprint) {
|
|
42193
42361
|
const queryBytes = Buffer.byteLength(query, "utf8");
|
|
42194
42362
|
if (queryBytes === 0 || queryBytes > MAX_SEARCH_QUERY_BYTES || query.includes("\n") || query.includes("\r")) {
|
|
42195
42363
|
throw new RvwError(
|
|
@@ -42198,6 +42366,10 @@ var RvwService = class {
|
|
|
42198
42366
|
);
|
|
42199
42367
|
}
|
|
42200
42368
|
const pullRequest = this.getPullRequest(pullRequestId);
|
|
42369
|
+
const contentFingerprint = this.assertPullRequestContentFingerprint(
|
|
42370
|
+
pullRequest,
|
|
42371
|
+
expectedPullRequestContentFingerprint
|
|
42372
|
+
);
|
|
42201
42373
|
await this.assertCommitAvailable(pullRequest, oid);
|
|
42202
42374
|
const prMarkdown = buildPullRequestMarkdown(pullRequest.latestTitle, pullRequest.latestBody);
|
|
42203
42375
|
const results = [];
|
|
@@ -42223,6 +42395,7 @@ var RvwService = class {
|
|
|
42223
42395
|
});
|
|
42224
42396
|
}
|
|
42225
42397
|
return {
|
|
42398
|
+
pullRequestContentFingerprint: contentFingerprint,
|
|
42226
42399
|
results,
|
|
42227
42400
|
matchCount: results.reduce((count, result) => count + result.matches.length, 0),
|
|
42228
42401
|
truncated: gitResult.truncated || results.length >= MAX_SEARCH_RESULTS && (gitResult.results.length > 0 || prMarkdown.split("\n").some((line) => findFixedStringMatches(line, query, options).length > 0)),
|
|
@@ -42550,19 +42723,22 @@ var RvwService = class {
|
|
|
42550
42723
|
return this.database.listStructures(pullRequestId);
|
|
42551
42724
|
}
|
|
42552
42725
|
async listFileStructureReferences(pullRequestId, targetSourceOid, targetPath) {
|
|
42553
|
-
const pullRequest = this.getPullRequest(pullRequestId);
|
|
42554
42726
|
assertCodeReferencePath(targetPath);
|
|
42727
|
+
const index2 = await this.listFileStructureReferenceIndex(pullRequestId, targetSourceOid);
|
|
42728
|
+
return index2.entries.find(({ path: candidate }) => candidate === targetPath)?.references ?? [];
|
|
42729
|
+
}
|
|
42730
|
+
async listFileStructureReferenceIndex(pullRequestId, targetSourceOid) {
|
|
42731
|
+
const pullRequest = this.getPullRequest(pullRequestId);
|
|
42555
42732
|
const structures = this.database.listStructures(pullRequestId).flatMap((summary) => {
|
|
42556
42733
|
const structure = this.database.getStructure(summary.id);
|
|
42557
42734
|
return structure?.pullRequestId === pullRequestId ? [structure] : [];
|
|
42558
42735
|
});
|
|
42736
|
+
if (structures.length === 0) return { sourceOid: targetSourceOid, entries: [] };
|
|
42559
42737
|
await this.assertCommitAvailable(pullRequest, targetSourceOid);
|
|
42560
|
-
const
|
|
42561
|
-
(
|
|
42562
|
-
(entry) => entry.path
|
|
42563
|
-
)
|
|
42738
|
+
const treePaths = (await this.git.tree(pullRequest.localRepositoryPath, targetSourceOid)).map(
|
|
42739
|
+
(entry) => entry.path
|
|
42564
42740
|
);
|
|
42565
|
-
|
|
42741
|
+
const targetPaths = new Set(treePaths);
|
|
42566
42742
|
const successorIndexes = /* @__PURE__ */ new Map();
|
|
42567
42743
|
const successorIndex = (sourceOid) => {
|
|
42568
42744
|
const key2 = JSON.stringify([sourceOid, targetSourceOid]);
|
|
@@ -42593,26 +42769,37 @@ var RvwService = class {
|
|
|
42593
42769
|
return targetPaths.has(successor) ? successor : null;
|
|
42594
42770
|
});
|
|
42595
42771
|
};
|
|
42596
|
-
const
|
|
42772
|
+
const referencesByPath = /* @__PURE__ */ new Map();
|
|
42597
42773
|
for (const structure of structures) {
|
|
42598
|
-
const
|
|
42599
|
-
|
|
42600
|
-
|
|
42601
|
-
|
|
42602
|
-
|
|
42603
|
-
|
|
42604
|
-
|
|
42605
|
-
|
|
42606
|
-
|
|
42607
|
-
|
|
42608
|
-
|
|
42609
|
-
|
|
42610
|
-
|
|
42611
|
-
|
|
42612
|
-
|
|
42613
|
-
|
|
42774
|
+
const matchingNodeIdsByPath = /* @__PURE__ */ new Map();
|
|
42775
|
+
for (const node2 of structure.nodes) {
|
|
42776
|
+
if (!node2.anchor) continue;
|
|
42777
|
+
const resolvedPath = await resolvePath(structure.sourceOid, node2.anchor.path);
|
|
42778
|
+
if (!resolvedPath) continue;
|
|
42779
|
+
const nodeIds = matchingNodeIdsByPath.get(resolvedPath) ?? /* @__PURE__ */ new Set();
|
|
42780
|
+
nodeIds.add(node2.id);
|
|
42781
|
+
matchingNodeIdsByPath.set(resolvedPath, nodeIds);
|
|
42782
|
+
}
|
|
42783
|
+
for (const [resolvedPath, matchingNodeIds] of matchingNodeIdsByPath) {
|
|
42784
|
+
const targetNode = closestMatchingStructureNode(structure, matchingNodeIds);
|
|
42785
|
+
if (!targetNode) continue;
|
|
42786
|
+
const references = referencesByPath.get(resolvedPath) ?? [];
|
|
42787
|
+
references.push({
|
|
42788
|
+
structure: structureSummary(structure),
|
|
42789
|
+
targetNodeId: targetNode.id,
|
|
42790
|
+
targetNodeLabel: targetNode.label,
|
|
42791
|
+
matchingNodeCount: matchingNodeIds.size
|
|
42792
|
+
});
|
|
42793
|
+
referencesByPath.set(resolvedPath, references);
|
|
42794
|
+
}
|
|
42614
42795
|
}
|
|
42615
|
-
return
|
|
42796
|
+
return {
|
|
42797
|
+
sourceOid: targetSourceOid,
|
|
42798
|
+
entries: treePaths.flatMap((path11) => {
|
|
42799
|
+
const references = referencesByPath.get(path11);
|
|
42800
|
+
return references ? [{ path: path11, references }] : [];
|
|
42801
|
+
})
|
|
42802
|
+
};
|
|
42616
42803
|
}
|
|
42617
42804
|
listStructuresByReference(reference) {
|
|
42618
42805
|
const pullRequest = this.resolveStoredPullRequest(reference);
|
|
@@ -43318,40 +43505,54 @@ var RvwService = class {
|
|
|
43318
43505
|
}
|
|
43319
43506
|
return { ...placeMutableDocumentComment(comment3.target, walkthrough.body), path: null };
|
|
43320
43507
|
}
|
|
43321
|
-
async resolveRepositoryCommentPath(pullRequest, source, destinationOid) {
|
|
43508
|
+
async resolveRepositoryCommentPath(pullRequest, source, destinationOid, context) {
|
|
43322
43509
|
if (source.sourceOid === destinationOid) {
|
|
43323
43510
|
return { path: source.path, deleted: false };
|
|
43324
43511
|
}
|
|
43325
|
-
const
|
|
43326
|
-
|
|
43327
|
-
|
|
43328
|
-
|
|
43329
|
-
|
|
43512
|
+
const key2 = JSON.stringify([source.sourceOid, destinationOid]);
|
|
43513
|
+
let changesPromise = context.changedFiles.get(key2);
|
|
43514
|
+
if (!changesPromise) {
|
|
43515
|
+
changesPromise = this.git.changedFiles(
|
|
43516
|
+
pullRequest.localRepositoryPath,
|
|
43517
|
+
source.sourceOid,
|
|
43518
|
+
destinationOid
|
|
43519
|
+
);
|
|
43520
|
+
context.changedFiles.set(key2, changesPromise);
|
|
43521
|
+
}
|
|
43522
|
+
const changes = await changesPromise;
|
|
43330
43523
|
const change = changes.find((candidate) => candidate.oldPath === source.path);
|
|
43331
43524
|
if (change?.kind === "deleted" || change && change.newPath === null) {
|
|
43332
43525
|
return { path: source.path, deleted: true };
|
|
43333
43526
|
}
|
|
43334
43527
|
return { path: change?.newPath ?? source.path, deleted: false };
|
|
43335
43528
|
}
|
|
43336
|
-
async placeRepositoryCommentAtPath(pullRequest, source, destinationOid, destinationPath) {
|
|
43337
|
-
const destinationContent = await this.
|
|
43338
|
-
|
|
43339
|
-
|
|
43340
|
-
|
|
43341
|
-
|
|
43342
|
-
|
|
43529
|
+
async placeRepositoryCommentAtPath(pullRequest, source, destinationOid, destinationPath, context) {
|
|
43530
|
+
const destinationContent = await this.getPlacementDocument(
|
|
43531
|
+
pullRequest,
|
|
43532
|
+
{
|
|
43533
|
+
kind: "repository-file",
|
|
43534
|
+
pullRequestId: pullRequest.id,
|
|
43535
|
+
sourceOid: destinationOid,
|
|
43536
|
+
path: destinationPath
|
|
43537
|
+
},
|
|
43538
|
+
context
|
|
43539
|
+
);
|
|
43343
43540
|
if (source.startLine === null || source.endLine === null) {
|
|
43344
43541
|
return destinationContent.availability === "missing" ? { outdated: true, range: null, path: destinationPath } : { outdated: false, range: null, path: destinationPath };
|
|
43345
43542
|
}
|
|
43346
43543
|
if (destinationContent.availability !== "available") {
|
|
43347
43544
|
return { outdated: true, range: null, path: destinationPath };
|
|
43348
43545
|
}
|
|
43349
|
-
const sourceContent = await this.
|
|
43350
|
-
|
|
43351
|
-
|
|
43352
|
-
|
|
43353
|
-
|
|
43354
|
-
|
|
43546
|
+
const sourceContent = await this.getPlacementDocument(
|
|
43547
|
+
pullRequest,
|
|
43548
|
+
{
|
|
43549
|
+
kind: "repository-file",
|
|
43550
|
+
pullRequestId: pullRequest.id,
|
|
43551
|
+
sourceOid: source.sourceOid,
|
|
43552
|
+
path: source.path
|
|
43553
|
+
},
|
|
43554
|
+
context
|
|
43555
|
+
);
|
|
43355
43556
|
if (sourceContent.availability !== "available") {
|
|
43356
43557
|
return { outdated: true, range: null, path: destinationPath };
|
|
43357
43558
|
}
|
|
@@ -43364,55 +43565,171 @@ var RvwService = class {
|
|
|
43364
43565
|
return range ? { outdated: false, range, path: destinationPath } : { outdated: true, range: null, path: destinationPath };
|
|
43365
43566
|
}
|
|
43366
43567
|
async placeComment(comment3, destination) {
|
|
43367
|
-
|
|
43568
|
+
const pullRequest = this.getPullRequest(comment3.pullRequestId);
|
|
43569
|
+
return await this.placeCommentForDestination(
|
|
43570
|
+
comment3,
|
|
43571
|
+
pullRequest,
|
|
43572
|
+
{ kind: "document", ref: destination },
|
|
43573
|
+
this.createCommentPlacementRequestContext()
|
|
43574
|
+
);
|
|
43575
|
+
}
|
|
43576
|
+
createCommentPlacementRequestContext() {
|
|
43577
|
+
return {
|
|
43578
|
+
commitAvailability: /* @__PURE__ */ new Map(),
|
|
43579
|
+
changedFiles: /* @__PURE__ */ new Map(),
|
|
43580
|
+
documents: /* @__PURE__ */ new Map()
|
|
43581
|
+
};
|
|
43582
|
+
}
|
|
43583
|
+
async assertPlacementCommitAvailable(pullRequest, oid, context) {
|
|
43584
|
+
let available = context.commitAvailability.get(oid);
|
|
43585
|
+
if (!available) {
|
|
43586
|
+
available = this.assertCommitAvailable(pullRequest, oid);
|
|
43587
|
+
context.commitAvailability.set(oid, available);
|
|
43588
|
+
}
|
|
43589
|
+
await available;
|
|
43590
|
+
}
|
|
43591
|
+
async getPlacementDocument(pullRequest, ref, context) {
|
|
43592
|
+
const key2 = JSON.stringify(ref);
|
|
43593
|
+
let document3 = context.documents.get(key2);
|
|
43594
|
+
if (!document3) {
|
|
43595
|
+
document3 = (async () => {
|
|
43596
|
+
if (ref.kind === "pull-request-markdown") {
|
|
43597
|
+
const text5 = buildPullRequestMarkdown(pullRequest.latestTitle, pullRequest.latestBody);
|
|
43598
|
+
return {
|
|
43599
|
+
ref,
|
|
43600
|
+
availability: "available",
|
|
43601
|
+
text: text5,
|
|
43602
|
+
byteLength: Buffer.byteLength(text5, "utf8"),
|
|
43603
|
+
entryKind: "virtual",
|
|
43604
|
+
normalizedLineEndings: false,
|
|
43605
|
+
oid: null
|
|
43606
|
+
};
|
|
43607
|
+
}
|
|
43608
|
+
await this.assertPlacementCommitAvailable(pullRequest, ref.sourceOid, context);
|
|
43609
|
+
const content3 = await this.git.readDocument(
|
|
43610
|
+
pullRequest.localRepositoryPath,
|
|
43611
|
+
ref.sourceOid,
|
|
43612
|
+
ref.path
|
|
43613
|
+
);
|
|
43614
|
+
return { ref, ...content3 };
|
|
43615
|
+
})();
|
|
43616
|
+
context.documents.set(key2, document3);
|
|
43617
|
+
}
|
|
43618
|
+
return await document3;
|
|
43619
|
+
}
|
|
43620
|
+
async placeCommentForDestination(comment3, pullRequest, destination, context) {
|
|
43621
|
+
if (destination.kind === "walkthrough") {
|
|
43622
|
+
return this.placeWalkthroughComment(comment3, destination.walkthroughId);
|
|
43623
|
+
}
|
|
43624
|
+
if (destination.kind === "commit") {
|
|
43625
|
+
await this.assertPlacementCommitAvailable(pullRequest, destination.oid, context);
|
|
43626
|
+
}
|
|
43627
|
+
const documentDestination = destination.kind === "document" ? destination.ref : null;
|
|
43628
|
+
const destinationOid = destination.kind === "commit" ? destination.oid : documentDestination?.kind === "repository-file" ? documentDestination.sourceOid : null;
|
|
43629
|
+
if (documentDestination !== null && comment3.pullRequestId !== documentDestination.pullRequestId) {
|
|
43368
43630
|
return { outdated: true, range: null, path: null };
|
|
43369
43631
|
}
|
|
43370
43632
|
if (comment3.target.kind === "pull-request") return { outdated: false, range: null, path: null };
|
|
43371
43633
|
if (comment3.target.kind === "walkthrough") {
|
|
43372
43634
|
return this.placeWalkthroughComment(comment3);
|
|
43373
43635
|
}
|
|
43374
|
-
const pullRequest = this.getPullRequest(comment3.pullRequestId);
|
|
43375
43636
|
if (comment3.target.documentKind === "pull-request-markdown") {
|
|
43376
|
-
return destination.kind === "pull-request-markdown" ? this.placePullRequestMarkdownComment(comment3, pullRequest) : { outdated: true, range: null, path: null };
|
|
43637
|
+
return destination.kind === "commit" || documentDestination?.kind === "pull-request-markdown" ? this.placePullRequestMarkdownComment(comment3, pullRequest) : { outdated: true, range: null, path: null };
|
|
43377
43638
|
}
|
|
43378
|
-
if (
|
|
43639
|
+
if (destinationOid === null) return { outdated: true, range: null, path: null };
|
|
43379
43640
|
const source = comment3.target;
|
|
43641
|
+
await this.assertPlacementCommitAvailable(pullRequest, source.sourceOid, context);
|
|
43380
43642
|
const resolved = await this.resolveRepositoryCommentPath(
|
|
43381
43643
|
pullRequest,
|
|
43382
43644
|
source,
|
|
43383
|
-
|
|
43645
|
+
destinationOid,
|
|
43646
|
+
context
|
|
43384
43647
|
);
|
|
43385
43648
|
if (resolved.deleted) return { outdated: true, range: null, path: source.path };
|
|
43386
|
-
if (resolved.path !==
|
|
43649
|
+
if (documentDestination?.kind === "repository-file" && resolved.path !== documentDestination.path) {
|
|
43387
43650
|
return { outdated: true, range: null, path: resolved.path };
|
|
43388
43651
|
}
|
|
43389
43652
|
return await this.placeRepositoryCommentAtPath(
|
|
43390
43653
|
pullRequest,
|
|
43391
43654
|
source,
|
|
43392
|
-
|
|
43393
|
-
resolved.path
|
|
43655
|
+
destinationOid,
|
|
43656
|
+
resolved.path,
|
|
43657
|
+
context
|
|
43394
43658
|
);
|
|
43395
43659
|
}
|
|
43396
43660
|
async placeCommentAtCommit(comment3, destinationOid) {
|
|
43397
43661
|
const pullRequest = this.getPullRequest(comment3.pullRequestId);
|
|
43398
|
-
await this.
|
|
43399
|
-
|
|
43400
|
-
if (comment3.target.kind === "walkthrough") {
|
|
43401
|
-
return this.placeWalkthroughComment(comment3);
|
|
43402
|
-
}
|
|
43403
|
-
if (comment3.target.documentKind === "pull-request-markdown") {
|
|
43404
|
-
return this.placePullRequestMarkdownComment(comment3, pullRequest);
|
|
43405
|
-
}
|
|
43406
|
-
const source = comment3.target;
|
|
43407
|
-
const resolved = await this.resolveRepositoryCommentPath(pullRequest, source, destinationOid);
|
|
43408
|
-
if (resolved.deleted) return { outdated: true, range: null, path: source.path };
|
|
43409
|
-
return await this.placeRepositoryCommentAtPath(
|
|
43662
|
+
return await this.placeCommentForDestination(
|
|
43663
|
+
comment3,
|
|
43410
43664
|
pullRequest,
|
|
43411
|
-
|
|
43412
|
-
|
|
43413
|
-
resolved.path
|
|
43665
|
+
{ kind: "commit", oid: destinationOid },
|
|
43666
|
+
this.createCommentPlacementRequestContext()
|
|
43414
43667
|
);
|
|
43415
43668
|
}
|
|
43669
|
+
async resolveCommentPlacements(pullRequestId, commentIds, destinations, expectedPullRequestContentFingerprint) {
|
|
43670
|
+
const pullRequest = this.getPullRequest(pullRequestId);
|
|
43671
|
+
const contentFingerprint = this.assertPullRequestContentFingerprint(
|
|
43672
|
+
pullRequest,
|
|
43673
|
+
expectedPullRequestContentFingerprint
|
|
43674
|
+
);
|
|
43675
|
+
const uniqueCommentIds = [...new Set(commentIds)];
|
|
43676
|
+
const comments = [];
|
|
43677
|
+
const missingCommentIds = [];
|
|
43678
|
+
for (const commentId of uniqueCommentIds) {
|
|
43679
|
+
const comment3 = this.database.getComment(commentId);
|
|
43680
|
+
if (!comment3) {
|
|
43681
|
+
missingCommentIds.push(commentId);
|
|
43682
|
+
continue;
|
|
43683
|
+
}
|
|
43684
|
+
if (comment3.pullRequestId !== pullRequestId) {
|
|
43685
|
+
throw new RvwError(
|
|
43686
|
+
"INVALID_INPUT",
|
|
43687
|
+
`\u5225\u306EPull Request\u306E\u30B3\u30E1\u30F3\u30C8\u306F\u4E00\u62EC\u89E3\u6C7A\u3067\u304D\u307E\u305B\u3093: ${commentId}`
|
|
43688
|
+
);
|
|
43689
|
+
}
|
|
43690
|
+
comments.push(comment3);
|
|
43691
|
+
}
|
|
43692
|
+
const context = this.createCommentPlacementRequestContext();
|
|
43693
|
+
if (comments.length > 0) {
|
|
43694
|
+
for (const destination of destinations) {
|
|
43695
|
+
if (destination.kind === "commit") {
|
|
43696
|
+
await this.assertPlacementCommitAvailable(pullRequest, destination.oid, context);
|
|
43697
|
+
} else if (destination.kind === "document" && destination.ref.kind === "repository-file") {
|
|
43698
|
+
await this.assertPlacementCommitAvailable(
|
|
43699
|
+
pullRequest,
|
|
43700
|
+
destination.ref.sourceOid,
|
|
43701
|
+
context
|
|
43702
|
+
);
|
|
43703
|
+
}
|
|
43704
|
+
}
|
|
43705
|
+
}
|
|
43706
|
+
return {
|
|
43707
|
+
pullRequestContentFingerprint: contentFingerprint,
|
|
43708
|
+
comments: await mapWithConcurrency(comments, 4, async (comment3) => {
|
|
43709
|
+
const placements = [];
|
|
43710
|
+
const failures = [];
|
|
43711
|
+
for (const destination of destinations) {
|
|
43712
|
+
try {
|
|
43713
|
+
placements.push({
|
|
43714
|
+
destination,
|
|
43715
|
+
placement: await this.placeCommentForDestination(
|
|
43716
|
+
comment3,
|
|
43717
|
+
pullRequest,
|
|
43718
|
+
destination,
|
|
43719
|
+
context
|
|
43720
|
+
)
|
|
43721
|
+
});
|
|
43722
|
+
} catch (error51) {
|
|
43723
|
+
const placementError = asRvwError(error51);
|
|
43724
|
+
if (placementError.code !== "COMMIT_NOT_FOUND") throw error51;
|
|
43725
|
+
failures.push({ destination, error: placementError.toJSON() });
|
|
43726
|
+
}
|
|
43727
|
+
}
|
|
43728
|
+
return { commentId: comment3.id, placements, failures };
|
|
43729
|
+
}),
|
|
43730
|
+
missingCommentIds
|
|
43731
|
+
};
|
|
43732
|
+
}
|
|
43416
43733
|
async getResetPreview(pullRequestId) {
|
|
43417
43734
|
const pullRequest = this.getPullRequest(pullRequestId);
|
|
43418
43735
|
const refs = await this.git.listRefsByPrefix(
|
|
@@ -47710,9 +48027,30 @@ var editCommentPostSchema = external_exports.object({
|
|
|
47710
48027
|
body: external_exports.string().min(1).refine((value) => Buffer.byteLength(value, "utf8") <= MAX_COMMENT_BODY_BYTES),
|
|
47711
48028
|
references: external_exports.array(codeReferenceInputSchema).optional()
|
|
47712
48029
|
});
|
|
48030
|
+
var placementDocumentRefSchema = external_exports.discriminatedUnion("kind", [
|
|
48031
|
+
external_exports.object({ kind: external_exports.literal("pull-request-markdown"), pullRequestId: external_exports.uuid() }),
|
|
48032
|
+
external_exports.object({
|
|
48033
|
+
kind: external_exports.literal("repository-file"),
|
|
48034
|
+
pullRequestId: external_exports.uuid(),
|
|
48035
|
+
sourceOid: external_exports.string().regex(GIT_OBJECT_ID_PATTERN),
|
|
48036
|
+
path: external_exports.string().min(1)
|
|
48037
|
+
})
|
|
48038
|
+
]);
|
|
48039
|
+
var resolveCommentPlacementsSchema = external_exports.object({
|
|
48040
|
+
commentIds: external_exports.array(external_exports.uuid()),
|
|
48041
|
+
expectedPullRequestContentFingerprint: external_exports.string().regex(CONTENT_FINGERPRINT_PATTERN).optional(),
|
|
48042
|
+
destinations: external_exports.array(
|
|
48043
|
+
external_exports.union([
|
|
48044
|
+
external_exports.object({ kind: external_exports.literal("document"), ref: placementDocumentRefSchema }),
|
|
48045
|
+
external_exports.object({ kind: external_exports.literal("commit"), oid: external_exports.string().regex(GIT_OBJECT_ID_PATTERN) }),
|
|
48046
|
+
external_exports.object({ kind: external_exports.literal("walkthrough"), walkthroughId: external_exports.uuid() })
|
|
48047
|
+
])
|
|
48048
|
+
).min(1).max(4)
|
|
48049
|
+
});
|
|
47713
48050
|
|
|
47714
48051
|
// src/server/app.ts
|
|
47715
48052
|
var oidSchema = external_exports.string().regex(GIT_OBJECT_ID_PATTERN);
|
|
48053
|
+
var contentFingerprintSchema = external_exports.string().regex(CONTENT_FINGERPRINT_PATTERN);
|
|
47716
48054
|
var nonnegativeIndexSchema = external_exports.coerce.number().int().nonnegative();
|
|
47717
48055
|
var svgAssetContentSecurityPolicy = "default-src 'none'; style-src 'unsafe-inline'; base-uri 'none'; form-action 'none'; sandbox";
|
|
47718
48056
|
function requiredQuery(value, name) {
|
|
@@ -47722,6 +48060,9 @@ function requiredQuery(value, name) {
|
|
|
47722
48060
|
function oidQuery(value, name) {
|
|
47723
48061
|
return oidSchema.parse(requiredQuery(value, name));
|
|
47724
48062
|
}
|
|
48063
|
+
function optionalContentFingerprint(value) {
|
|
48064
|
+
return value === void 0 ? void 0 : contentFingerprintSchema.parse(value);
|
|
48065
|
+
}
|
|
47725
48066
|
function structureSourceLocator(query) {
|
|
47726
48067
|
if (query.locatorKind === "node") {
|
|
47727
48068
|
return { kind: "node", nodeId: requiredQuery(query.nodeId, "nodeId") };
|
|
@@ -47831,7 +48172,7 @@ function createApp(service, options) {
|
|
|
47831
48172
|
rawViewerLease === void 0 ? void 0 : viewerIdSchema.parse(rawViewerLease)
|
|
47832
48173
|
);
|
|
47833
48174
|
}
|
|
47834
|
-
return context.json({ ok: true,
|
|
48175
|
+
return context.json({ ok: true, ...service.database.getRevisionSnapshot() });
|
|
47835
48176
|
});
|
|
47836
48177
|
app.post("/api/meta/viewers/release", async (context) => {
|
|
47837
48178
|
const input = viewerReleaseSchema.parse(await context.req.json());
|
|
@@ -47872,10 +48213,10 @@ function createApp(service, options) {
|
|
|
47872
48213
|
...await service.openPullRequest(input.reference, input.cwd)
|
|
47873
48214
|
});
|
|
47874
48215
|
});
|
|
47875
|
-
app.post(
|
|
47876
|
-
"
|
|
47877
|
-
|
|
47878
|
-
);
|
|
48216
|
+
app.post("/api/pull-requests/:id/refresh", async (context) => {
|
|
48217
|
+
const result = await service.refreshPullRequest(context.req.param("id"));
|
|
48218
|
+
return context.json({ ok: true, ...result });
|
|
48219
|
+
});
|
|
47879
48220
|
app.post("/api/pull-requests/:id/reset", async (context) => {
|
|
47880
48221
|
const input = resetSchema.parse(await context.req.json());
|
|
47881
48222
|
if (!input.yes) {
|
|
@@ -47913,7 +48254,13 @@ function createApp(service, options) {
|
|
|
47913
48254
|
});
|
|
47914
48255
|
app.get("/api/pull-requests/:id/document", async (context) => {
|
|
47915
48256
|
const ref = documentRefFromQuery(context.req.param("id"), context.req.query());
|
|
47916
|
-
return context.json({
|
|
48257
|
+
return context.json({
|
|
48258
|
+
ok: true,
|
|
48259
|
+
...await service.getDocumentWithContentFingerprint(
|
|
48260
|
+
ref,
|
|
48261
|
+
optionalContentFingerprint(context.req.query("expectedPullRequestContentFingerprint"))
|
|
48262
|
+
)
|
|
48263
|
+
});
|
|
47917
48264
|
});
|
|
47918
48265
|
app.on(["GET", "HEAD"], "/api/pull-requests/:id/markdown-asset", async (context) => {
|
|
47919
48266
|
const sourceOid = oidQuery(context.req.query("sourceOid"), "sourceOid");
|
|
@@ -47972,10 +48319,16 @@ function createApp(service, options) {
|
|
|
47972
48319
|
const wholeWord = parseBooleanQuery(context.req.query("wholeWord"), "wholeWord");
|
|
47973
48320
|
return context.json({
|
|
47974
48321
|
ok: true,
|
|
47975
|
-
...await service.search(
|
|
47976
|
-
|
|
47977
|
-
|
|
47978
|
-
|
|
48322
|
+
...await service.search(
|
|
48323
|
+
context.req.param("id"),
|
|
48324
|
+
oid,
|
|
48325
|
+
query,
|
|
48326
|
+
{
|
|
48327
|
+
matchCase,
|
|
48328
|
+
wholeWord
|
|
48329
|
+
},
|
|
48330
|
+
optionalContentFingerprint(context.req.query("expectedPullRequestContentFingerprint"))
|
|
48331
|
+
)
|
|
47979
48332
|
});
|
|
47980
48333
|
});
|
|
47981
48334
|
app.get("/api/pull-requests/:id/comments", (context) => {
|
|
@@ -48042,6 +48395,13 @@ function createApp(service, options) {
|
|
|
48042
48395
|
)
|
|
48043
48396
|
});
|
|
48044
48397
|
});
|
|
48398
|
+
app.get("/api/pull-requests/:id/structure-reference-index", async (context) => {
|
|
48399
|
+
const sourceOid = oidQuery(context.req.query("sourceOid"), "sourceOid");
|
|
48400
|
+
return context.json({
|
|
48401
|
+
ok: true,
|
|
48402
|
+
index: await service.listFileStructureReferenceIndex(context.req.param("id"), sourceOid)
|
|
48403
|
+
});
|
|
48404
|
+
});
|
|
48045
48405
|
app.get(
|
|
48046
48406
|
"/api/pull-requests/:id/structures/:structureId",
|
|
48047
48407
|
(context) => context.json({
|
|
@@ -48095,43 +48455,51 @@ function createApp(service, options) {
|
|
|
48095
48455
|
});
|
|
48096
48456
|
app.post("/api/comments/:id/posts", async (context) => {
|
|
48097
48457
|
const input = replySchema.parse(await context.req.json());
|
|
48458
|
+
const commentId = context.req.param("id");
|
|
48459
|
+
const post = await service.replyToComment(commentId, {
|
|
48460
|
+
body: input.body,
|
|
48461
|
+
...input.relatedCommitOid === void 0 ? {} : { relatedCommitOid: input.relatedCommitOid },
|
|
48462
|
+
...input.authorLabel === void 0 ? {} : { authorLabel: input.authorLabel },
|
|
48463
|
+
lastModifiedBy: "human",
|
|
48464
|
+
...input.references === void 0 ? {} : { references: input.references }
|
|
48465
|
+
});
|
|
48098
48466
|
return context.json(
|
|
48099
48467
|
{
|
|
48100
48468
|
ok: true,
|
|
48101
|
-
post
|
|
48102
|
-
|
|
48103
|
-
...input.relatedCommitOid === void 0 ? {} : { relatedCommitOid: input.relatedCommitOid },
|
|
48104
|
-
...input.authorLabel === void 0 ? {} : { authorLabel: input.authorLabel },
|
|
48105
|
-
lastModifiedBy: "human",
|
|
48106
|
-
...input.references === void 0 ? {} : { references: input.references }
|
|
48107
|
-
})
|
|
48469
|
+
post,
|
|
48470
|
+
comment: service.database.getComment(commentId)
|
|
48108
48471
|
},
|
|
48109
48472
|
201
|
|
48110
48473
|
);
|
|
48111
48474
|
});
|
|
48112
48475
|
app.patch("/api/comments/:id/posts/:postId", async (context) => {
|
|
48113
48476
|
const input = editCommentPostSchema.parse(await context.req.json());
|
|
48477
|
+
const commentId = context.req.param("id");
|
|
48478
|
+
const post = input.references === void 0 ? await service.updateCommentPost(
|
|
48479
|
+
commentId,
|
|
48480
|
+
context.req.param("postId"),
|
|
48481
|
+
input.body,
|
|
48482
|
+
"human"
|
|
48483
|
+
) : await service.editCommentPost(commentId, context.req.param("postId"), {
|
|
48484
|
+
body: input.body,
|
|
48485
|
+
references: input.references,
|
|
48486
|
+
lastModifiedBy: "human"
|
|
48487
|
+
});
|
|
48114
48488
|
return context.json({
|
|
48115
48489
|
ok: true,
|
|
48116
|
-
post
|
|
48117
|
-
|
|
48118
|
-
context.req.param("postId"),
|
|
48119
|
-
input.body,
|
|
48120
|
-
"human"
|
|
48121
|
-
) : await service.editCommentPost(context.req.param("id"), context.req.param("postId"), {
|
|
48122
|
-
body: input.body,
|
|
48123
|
-
references: input.references,
|
|
48124
|
-
lastModifiedBy: "human"
|
|
48125
|
-
})
|
|
48490
|
+
post,
|
|
48491
|
+
comment: service.database.getComment(commentId)
|
|
48126
48492
|
});
|
|
48127
48493
|
});
|
|
48128
|
-
app.delete(
|
|
48129
|
-
"
|
|
48130
|
-
(
|
|
48494
|
+
app.delete("/api/comments/:id/posts/:postId", (context) => {
|
|
48495
|
+
const commentId = context.req.param("id");
|
|
48496
|
+
const deleted = service.deleteReply(commentId, context.req.param("postId"));
|
|
48497
|
+
return context.json({
|
|
48131
48498
|
ok: true,
|
|
48132
|
-
deleted
|
|
48133
|
-
|
|
48134
|
-
|
|
48499
|
+
deleted,
|
|
48500
|
+
comment: service.database.getComment(commentId)
|
|
48501
|
+
});
|
|
48502
|
+
});
|
|
48135
48503
|
app.post(
|
|
48136
48504
|
"/api/comments/:id/resolve",
|
|
48137
48505
|
(context) => context.json({ ok: true, comment: service.setCommentResolved(context.req.param("id"), true) })
|
|
@@ -48144,6 +48512,18 @@ function createApp(service, options) {
|
|
|
48144
48512
|
"/api/comments/:id",
|
|
48145
48513
|
(context) => context.json({ ok: true, deleted: service.deleteComment(context.req.param("id")) })
|
|
48146
48514
|
);
|
|
48515
|
+
app.post("/api/pull-requests/:pullRequestId/comment-placements/resolve", async (context) => {
|
|
48516
|
+
const input = resolveCommentPlacementsSchema.parse(await context.req.json());
|
|
48517
|
+
return context.json({
|
|
48518
|
+
ok: true,
|
|
48519
|
+
...await service.resolveCommentPlacements(
|
|
48520
|
+
context.req.param("pullRequestId"),
|
|
48521
|
+
input.commentIds,
|
|
48522
|
+
input.destinations,
|
|
48523
|
+
input.expectedPullRequestContentFingerprint
|
|
48524
|
+
)
|
|
48525
|
+
});
|
|
48526
|
+
});
|
|
48147
48527
|
app.get("/api/comments/:id/placement", async (context) => {
|
|
48148
48528
|
const comment3 = service.database.getComment(context.req.param("id"));
|
|
48149
48529
|
if (!comment3)
|
|
@@ -48155,22 +48535,21 @@ function createApp(service, options) {
|
|
|
48155
48535
|
placement: { outdated: true, range: null, path: null }
|
|
48156
48536
|
});
|
|
48157
48537
|
}
|
|
48538
|
+
let destination;
|
|
48158
48539
|
if (context.req.query("kind") === "commit") {
|
|
48159
48540
|
const oid = oidQuery(context.req.query("oid"), "oid");
|
|
48160
|
-
|
|
48161
|
-
|
|
48162
|
-
placement: await service.placeCommentAtCommit(comment3, oid)
|
|
48163
|
-
});
|
|
48164
|
-
}
|
|
48165
|
-
if (context.req.query("kind") === "walkthrough") {
|
|
48541
|
+
destination = { kind: "commit", oid };
|
|
48542
|
+
} else if (context.req.query("kind") === "walkthrough") {
|
|
48166
48543
|
const walkthroughId = requiredQuery(context.req.query("walkthroughId"), "walkthroughId");
|
|
48167
|
-
|
|
48168
|
-
|
|
48169
|
-
|
|
48170
|
-
|
|
48544
|
+
destination = { kind: "walkthrough", walkthroughId };
|
|
48545
|
+
} else {
|
|
48546
|
+
destination = {
|
|
48547
|
+
kind: "document",
|
|
48548
|
+
ref: documentRefFromQuery(pullRequestId, context.req.query())
|
|
48549
|
+
};
|
|
48171
48550
|
}
|
|
48172
|
-
const
|
|
48173
|
-
return context.json({ ok: true, placement
|
|
48551
|
+
const placement = destination.kind === "commit" ? await service.placeCommentAtCommit(comment3, destination.oid) : destination.kind === "walkthrough" ? service.placeWalkthroughComment(comment3, destination.walkthroughId) : await service.placeComment(comment3, destination.ref);
|
|
48552
|
+
return context.json({ ok: true, placement });
|
|
48174
48553
|
});
|
|
48175
48554
|
if (options.staticDirectory && existsSync4(options.staticDirectory)) {
|
|
48176
48555
|
app.use("*", serveStatic({ root: options.staticDirectory }));
|