@a9n-shoji/rvw 0.3.2 → 0.4.0-beta.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/CHANGELOG.md +9 -0
- package/README.md +41 -7
- package/dist/cli.mjs +910 -31
- package/dist/cli.mjs.map +4 -4
- package/dist/web/assets/{CommentThread-CMXtuZ98.js → CommentThread-dsad9VaW.js} +4 -4
- package/dist/web/assets/{DocumentViewer-D-UGIxCU.js → DocumentViewer-CN8CiQe9.js} +3 -3
- package/dist/web/assets/{MermaidSurface-Dt2_Hu6n.js → FileIcon-AhP8Ezk9.js} +94 -95
- package/dist/web/assets/{MarkdownTable-7Sm_sj1E.js → MarkdownTable-Clfr8wUw.js} +1 -1
- package/dist/web/assets/MermaidExpandedView-BjmXfluL.js +4 -0
- package/dist/web/assets/MermaidSurface-B2Z3pJme.js +2 -0
- package/dist/web/assets/StructureViewer-Ywjlwt8f.js +1 -0
- package/dist/web/assets/{WalkthroughViewer-CuJMrKOW.js → WalkthroughViewer-Ckb8Qlvj.js} +4 -4
- package/dist/web/assets/index-AVz95gz4.js +11 -0
- package/dist/web/assets/{index-BNcvGFlf.css → index-Dq83UXVE.css} +1 -1
- package/dist/web/index.html +5 -4
- package/migrations/014_structures.sql +13 -0
- package/migrations/015_structure_concurrency.sql +6 -0
- package/migrations/016_structure_retired_ids.sql +13 -0
- package/package.json +1 -1
- package/skills/rvw-structure/SKILL.md +154 -0
- package/skills/rvw-structure/agents/openai.yaml +4 -0
- package/skills/rvw-structure/references/structure-authoring.md +136 -0
- package/skills/rvw-walkthrough/SKILL.md +5 -0
- package/dist/web/assets/MermaidExpandedView-CyWRss2q.js +0 -4
- package/dist/web/assets/index-BwIKbLJ1.js +0 -11
package/dist/cli.mjs
CHANGED
|
@@ -6582,11 +6582,11 @@ var $ZodCIDRv6 = /* @__PURE__ */ $constructor("$ZodCIDRv6", (inst, def) => {
|
|
|
6582
6582
|
try {
|
|
6583
6583
|
if (parts.length !== 2)
|
|
6584
6584
|
throw new Error();
|
|
6585
|
-
const [address,
|
|
6586
|
-
if (!
|
|
6585
|
+
const [address, prefix3] = parts;
|
|
6586
|
+
if (!prefix3)
|
|
6587
6587
|
throw new Error();
|
|
6588
|
-
const prefixNum = Number(
|
|
6589
|
-
if (`${prefixNum}` !==
|
|
6588
|
+
const prefixNum = Number(prefix3);
|
|
6589
|
+
if (`${prefixNum}` !== prefix3)
|
|
6590
6590
|
throw new Error();
|
|
6591
6591
|
if (prefixNum < 0 || prefixNum > 128)
|
|
6592
6592
|
throw new Error();
|
|
@@ -14994,12 +14994,12 @@ function _includes(includes, params) {
|
|
|
14994
14994
|
});
|
|
14995
14995
|
}
|
|
14996
14996
|
// @__NO_SIDE_EFFECTS__
|
|
14997
|
-
function _startsWith(
|
|
14997
|
+
function _startsWith(prefix3, params) {
|
|
14998
14998
|
return new $ZodCheckStartsWith({
|
|
14999
14999
|
check: "string_format",
|
|
15000
15000
|
format: "starts_with",
|
|
15001
15001
|
...normalizeParams(params),
|
|
15002
|
-
prefix:
|
|
15002
|
+
prefix: prefix3
|
|
15003
15003
|
});
|
|
15004
15004
|
}
|
|
15005
15005
|
// @__NO_SIDE_EFFECTS__
|
|
@@ -18514,6 +18514,19 @@ config(en_default());
|
|
|
18514
18514
|
|
|
18515
18515
|
// src/infrastructure/db/database.ts
|
|
18516
18516
|
import { createHash, randomUUID } from "node:crypto";
|
|
18517
|
+
|
|
18518
|
+
// src/domain/models.ts
|
|
18519
|
+
var STRUCTURE_NODE_NOTATIONS = [
|
|
18520
|
+
"plain",
|
|
18521
|
+
"class",
|
|
18522
|
+
"database",
|
|
18523
|
+
"interface",
|
|
18524
|
+
"component",
|
|
18525
|
+
"external",
|
|
18526
|
+
"concept"
|
|
18527
|
+
];
|
|
18528
|
+
|
|
18529
|
+
// src/infrastructure/db/database.ts
|
|
18517
18530
|
import {
|
|
18518
18531
|
chmodSync,
|
|
18519
18532
|
closeSync,
|
|
@@ -18668,17 +18681,34 @@ function parseCommentUri(uri) {
|
|
|
18668
18681
|
return match2[1];
|
|
18669
18682
|
}
|
|
18670
18683
|
|
|
18684
|
+
// src/domain/structure-uri.ts
|
|
18685
|
+
var prefix = "rvw://structure/";
|
|
18686
|
+
var structureIdPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
18687
|
+
function formatStructureUri(id) {
|
|
18688
|
+
return `${prefix}${id}`;
|
|
18689
|
+
}
|
|
18690
|
+
function parseStructureUri(uri) {
|
|
18691
|
+
if (!uri.startsWith(prefix)) {
|
|
18692
|
+
throw new RvwError("INVALID_INPUT", "structure URI\u304C\u4E0D\u6B63\u3067\u3059\u3002");
|
|
18693
|
+
}
|
|
18694
|
+
const id = uri.slice(prefix.length);
|
|
18695
|
+
if (!structureIdPattern.test(id)) {
|
|
18696
|
+
throw new RvwError("INVALID_INPUT", "structure URI\u304C\u4E0D\u6B63\u3067\u3059\u3002");
|
|
18697
|
+
}
|
|
18698
|
+
return id;
|
|
18699
|
+
}
|
|
18700
|
+
|
|
18671
18701
|
// src/domain/walkthrough-uri.ts
|
|
18672
|
-
var
|
|
18702
|
+
var prefix2 = "rvw://walkthrough/";
|
|
18673
18703
|
var walkthroughIdPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
18674
18704
|
function formatWalkthroughUri(id) {
|
|
18675
|
-
return `${
|
|
18705
|
+
return `${prefix2}${id}`;
|
|
18676
18706
|
}
|
|
18677
18707
|
function parseWalkthroughUri(uri) {
|
|
18678
|
-
if (!uri.startsWith(
|
|
18708
|
+
if (!uri.startsWith(prefix2)) {
|
|
18679
18709
|
throw new RvwError("INVALID_INPUT", "walkthrough URI\u304C\u4E0D\u6B63\u3067\u3059\u3002");
|
|
18680
18710
|
}
|
|
18681
|
-
const id = uri.slice(
|
|
18711
|
+
const id = uri.slice(prefix2.length);
|
|
18682
18712
|
if (!walkthroughIdPattern.test(id)) {
|
|
18683
18713
|
throw new RvwError("INVALID_INPUT", "walkthrough URI\u304C\u4E0D\u6B63\u3067\u3059\u3002");
|
|
18684
18714
|
}
|
|
@@ -18746,6 +18776,37 @@ function stringRecordValue(row, key2) {
|
|
|
18746
18776
|
throw new RvwError("DATABASE_ERROR", `DB\u5217 ${key2} \u304C\u4E0D\u6B63\u3067\u3059\u3002`, { cause: error51 });
|
|
18747
18777
|
}
|
|
18748
18778
|
}
|
|
18779
|
+
function isRecord(value) {
|
|
18780
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
18781
|
+
}
|
|
18782
|
+
function isNullableString(value) {
|
|
18783
|
+
return value === null || typeof value === "string";
|
|
18784
|
+
}
|
|
18785
|
+
function isSourceAnchor(value) {
|
|
18786
|
+
return isRecord(value) && typeof value.path === "string" && (value.startLine === null || typeof value.startLine === "number") && (value.endLine === null || typeof value.endLine === "number");
|
|
18787
|
+
}
|
|
18788
|
+
function isStructureNode(value) {
|
|
18789
|
+
return isRecord(value) && typeof value.id === "string" && typeof value.label === "string" && isNullableString(value.description) && isNullableString(value.kind) && (value.notation === void 0 || STRUCTURE_NODE_NOTATIONS.some((notation) => notation === value.notation)) && (value.anchor === null || isSourceAnchor(value.anchor));
|
|
18790
|
+
}
|
|
18791
|
+
function isStructureEdge(value) {
|
|
18792
|
+
return isRecord(value) && typeof value.id === "string" && typeof value.from === "string" && typeof value.to === "string" && typeof value.label === "string" && typeof value.directed === "boolean" && Array.isArray(value.anchors) && value.anchors.every(isSourceAnchor);
|
|
18793
|
+
}
|
|
18794
|
+
function structureGraphValue(row) {
|
|
18795
|
+
try {
|
|
18796
|
+
const value = JSON.parse(stringValue(row, "graph_json"));
|
|
18797
|
+
const originNodeId = isRecord(value) && typeof value.originNodeId === "string" ? value.originNodeId : null;
|
|
18798
|
+
if (!isRecord(value) || originNodeId === null || !Array.isArray(value.nodes) || !value.nodes.every(isStructureNode) || !Array.isArray(value.edges) || !value.edges.every(isStructureEdge)) {
|
|
18799
|
+
throw new Error("invalid Structure graph");
|
|
18800
|
+
}
|
|
18801
|
+
return {
|
|
18802
|
+
originNodeId,
|
|
18803
|
+
nodes: value.nodes.map((node2) => ({ ...node2, notation: node2.notation ?? "plain" })),
|
|
18804
|
+
edges: value.edges
|
|
18805
|
+
};
|
|
18806
|
+
} catch (error51) {
|
|
18807
|
+
throw new RvwError("DATABASE_ERROR", "Structure graph_json\u304C\u4E0D\u6B63\u3067\u3059\u3002", { cause: error51 });
|
|
18808
|
+
}
|
|
18809
|
+
}
|
|
18749
18810
|
function mapPullRequest(row) {
|
|
18750
18811
|
return {
|
|
18751
18812
|
id: stringValue(row, "id"),
|
|
@@ -19130,6 +19191,11 @@ var RvwDatabase = class {
|
|
|
19130
19191
|
FROM walkthroughs
|
|
19131
19192
|
JOIN page ON page.id = walkthroughs.pull_request_id
|
|
19132
19193
|
GROUP BY walkthroughs.pull_request_id
|
|
19194
|
+
), structure_counts AS (
|
|
19195
|
+
SELECT structures.pull_request_id, COUNT(*) AS structure_count
|
|
19196
|
+
FROM structures
|
|
19197
|
+
JOIN page ON page.id = structures.pull_request_id
|
|
19198
|
+
GROUP BY structures.pull_request_id
|
|
19133
19199
|
)
|
|
19134
19200
|
SELECT
|
|
19135
19201
|
pr.id AS pull_request_id,
|
|
@@ -19143,10 +19209,12 @@ var RvwDatabase = class {
|
|
|
19143
19209
|
pr.github_is_draft,
|
|
19144
19210
|
COALESCE(comment_counts.unresolved_count, 0) AS unresolved_comment_count,
|
|
19145
19211
|
COALESCE(comment_counts.resolved_count, 0) AS resolved_comment_count,
|
|
19146
|
-
COALESCE(walkthrough_counts.walkthrough_count, 0) AS walkthrough_count
|
|
19212
|
+
COALESCE(walkthrough_counts.walkthrough_count, 0) AS walkthrough_count,
|
|
19213
|
+
COALESCE(structure_counts.structure_count, 0) AS structure_count
|
|
19147
19214
|
FROM page AS pr
|
|
19148
19215
|
LEFT JOIN comment_counts ON comment_counts.pull_request_id = pr.id
|
|
19149
19216
|
LEFT JOIN walkthrough_counts ON walkthrough_counts.pull_request_id = pr.id
|
|
19217
|
+
LEFT JOIN structure_counts ON structure_counts.pull_request_id = pr.id
|
|
19150
19218
|
ORDER BY pr.github_updated_at DESC, pr.id DESC`
|
|
19151
19219
|
).all(hideClosedOrMergedValue, limit, offset);
|
|
19152
19220
|
const totalRow = this.database.prepare(
|
|
@@ -19166,7 +19234,8 @@ var RvwDatabase = class {
|
|
|
19166
19234
|
githubIsDraft: nullableBoolean(row, "github_is_draft"),
|
|
19167
19235
|
unresolvedCommentCount: numberValue(row, "unresolved_comment_count"),
|
|
19168
19236
|
resolvedCommentCount: numberValue(row, "resolved_comment_count"),
|
|
19169
|
-
walkthroughCount: numberValue(row, "walkthrough_count")
|
|
19237
|
+
walkthroughCount: numberValue(row, "walkthrough_count"),
|
|
19238
|
+
structureCount: numberValue(row, "structure_count")
|
|
19170
19239
|
})),
|
|
19171
19240
|
total: numberValue(totalRow, "total")
|
|
19172
19241
|
};
|
|
@@ -19322,6 +19391,7 @@ var RvwDatabase = class {
|
|
|
19322
19391
|
const walkthroughReferences = this.database.prepare(
|
|
19323
19392
|
"SELECT count(*) AS count FROM walkthrough_references WHERE walkthrough_id IN (SELECT id FROM walkthroughs WHERE pull_request_id = ?)"
|
|
19324
19393
|
).get(pullRequestId);
|
|
19394
|
+
const structures = this.database.prepare("SELECT count(*) AS count FROM structures WHERE pull_request_id = ?").get(pullRequestId);
|
|
19325
19395
|
return {
|
|
19326
19396
|
comments: numberValue(comments, "count"),
|
|
19327
19397
|
posts: numberValue(posts, "count"),
|
|
@@ -19329,12 +19399,234 @@ var RvwDatabase = class {
|
|
|
19329
19399
|
targets: numberValue(targets, "count"),
|
|
19330
19400
|
walkthroughs: numberValue(walkthroughs, "count"),
|
|
19331
19401
|
walkthroughReferences: numberValue(walkthroughReferences, "count"),
|
|
19402
|
+
structures: numberValue(structures, "count"),
|
|
19332
19403
|
gitRefs
|
|
19333
19404
|
};
|
|
19334
19405
|
}
|
|
19335
19406
|
deletePullRequestHistory(pullRequestId) {
|
|
19336
19407
|
this.database.prepare("DELETE FROM comments WHERE pull_request_id = ?").run(pullRequestId);
|
|
19337
19408
|
this.database.prepare("DELETE FROM walkthroughs WHERE pull_request_id = ?").run(pullRequestId);
|
|
19409
|
+
this.database.prepare(
|
|
19410
|
+
`DELETE FROM structure_publish_idempotency
|
|
19411
|
+
WHERE structure_id IN (SELECT id FROM structures WHERE pull_request_id = ?)`
|
|
19412
|
+
).run(pullRequestId);
|
|
19413
|
+
this.database.prepare("DELETE FROM structures WHERE pull_request_id = ?").run(pullRequestId);
|
|
19414
|
+
}
|
|
19415
|
+
mapStructure(row) {
|
|
19416
|
+
const id = stringValue(row, "id");
|
|
19417
|
+
return {
|
|
19418
|
+
id,
|
|
19419
|
+
ref: formatStructureUri(id),
|
|
19420
|
+
pullRequestId: stringValue(row, "pull_request_id"),
|
|
19421
|
+
sourceOid: stringValue(row, "source_oid"),
|
|
19422
|
+
title: stringValue(row, "title"),
|
|
19423
|
+
scope: stringValue(row, "scope"),
|
|
19424
|
+
...structureGraphValue(row),
|
|
19425
|
+
createdAt: stringValue(row, "created_at"),
|
|
19426
|
+
updatedAt: stringValue(row, "updated_at")
|
|
19427
|
+
};
|
|
19428
|
+
}
|
|
19429
|
+
getStructure(id) {
|
|
19430
|
+
const row = this.database.prepare("SELECT * FROM structures WHERE id = ?").get(id);
|
|
19431
|
+
return row ? this.mapStructure(row) : null;
|
|
19432
|
+
}
|
|
19433
|
+
listStructures(pullRequestId) {
|
|
19434
|
+
return this.database.prepare(
|
|
19435
|
+
`SELECT id, pull_request_id, source_oid, title, scope, created_at, updated_at
|
|
19436
|
+
FROM structures
|
|
19437
|
+
WHERE pull_request_id = ?
|
|
19438
|
+
ORDER BY created_at DESC, id DESC`
|
|
19439
|
+
).all(pullRequestId).map((row) => ({
|
|
19440
|
+
id: stringValue(row, "id"),
|
|
19441
|
+
ref: formatStructureUri(stringValue(row, "id")),
|
|
19442
|
+
pullRequestId: stringValue(row, "pull_request_id"),
|
|
19443
|
+
sourceOid: stringValue(row, "source_oid"),
|
|
19444
|
+
title: stringValue(row, "title"),
|
|
19445
|
+
scope: stringValue(row, "scope"),
|
|
19446
|
+
createdAt: stringValue(row, "created_at"),
|
|
19447
|
+
updatedAt: stringValue(row, "updated_at")
|
|
19448
|
+
}));
|
|
19449
|
+
}
|
|
19450
|
+
createStructure(input) {
|
|
19451
|
+
let structureId;
|
|
19452
|
+
const graphJson = JSON.stringify({
|
|
19453
|
+
originNodeId: input.originNodeId,
|
|
19454
|
+
nodes: input.nodes,
|
|
19455
|
+
edges: input.edges
|
|
19456
|
+
});
|
|
19457
|
+
this.immediateTransaction(() => {
|
|
19458
|
+
const keyHash = hashIdempotencyKey(input.idempotencyKey);
|
|
19459
|
+
const existingRow = this.database.prepare("SELECT * FROM structure_publish_idempotency WHERE key_hash = ?").get(keyHash);
|
|
19460
|
+
if (existingRow) {
|
|
19461
|
+
if (stringValue(existingRow, "request_hash") !== input.idempotencyRequestHash) {
|
|
19462
|
+
throw new RvwError(
|
|
19463
|
+
"IDEMPOTENCY_CONFLICT",
|
|
19464
|
+
"\u540C\u3058idempotencyKey\u304C\u5225\u306EStructure publish\u306B\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059\u3002"
|
|
19465
|
+
);
|
|
19466
|
+
}
|
|
19467
|
+
const existingId = stringValue(existingRow, "structure_id");
|
|
19468
|
+
if (!this.getStructure(existingId)) {
|
|
19469
|
+
throw new RvwError(
|
|
19470
|
+
"IDEMPOTENCY_RESULT_DELETED",
|
|
19471
|
+
"\u3053\u306EidempotencyKey\u3067\u4F5C\u6210\u3057\u305FStructure\u306F\u65E2\u306B\u524A\u9664\u3055\u308C\u3066\u3044\u307E\u3059\u3002",
|
|
19472
|
+
{ details: { structureId: existingId } }
|
|
19473
|
+
);
|
|
19474
|
+
}
|
|
19475
|
+
structureId = existingId;
|
|
19476
|
+
return;
|
|
19477
|
+
}
|
|
19478
|
+
const id = randomUUID();
|
|
19479
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
19480
|
+
this.database.prepare(
|
|
19481
|
+
`INSERT INTO structures(
|
|
19482
|
+
id, pull_request_id, source_oid, title, scope, graph_json, created_at, updated_at
|
|
19483
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`
|
|
19484
|
+
).run(
|
|
19485
|
+
id,
|
|
19486
|
+
input.pullRequestId,
|
|
19487
|
+
input.sourceOid,
|
|
19488
|
+
input.title,
|
|
19489
|
+
input.scope,
|
|
19490
|
+
graphJson,
|
|
19491
|
+
now,
|
|
19492
|
+
now
|
|
19493
|
+
);
|
|
19494
|
+
this.database.prepare(
|
|
19495
|
+
`INSERT INTO structure_publish_idempotency(
|
|
19496
|
+
key_hash, request_hash, structure_id, created_at
|
|
19497
|
+
) VALUES (?, ?, ?, ?)`
|
|
19498
|
+
).run(keyHash, input.idempotencyRequestHash, id, now);
|
|
19499
|
+
this.incrementChangeSequence();
|
|
19500
|
+
structureId = id;
|
|
19501
|
+
});
|
|
19502
|
+
if (!structureId) {
|
|
19503
|
+
throw new RvwError("DATABASE_ERROR", "\u4FDD\u5B58\u3057\u305FStructure ID\u3092\u78BA\u5B9A\u3067\u304D\u307E\u305B\u3093\u3002");
|
|
19504
|
+
}
|
|
19505
|
+
const structure = this.getStructure(structureId);
|
|
19506
|
+
if (!structure) throw new RvwError("DATABASE_ERROR", "\u4FDD\u5B58\u3057\u305FStructure\u3092\u8AAD\u307F\u51FA\u305B\u307E\u305B\u3093\u3002");
|
|
19507
|
+
return structure;
|
|
19508
|
+
}
|
|
19509
|
+
updateStructure(id, expectedUpdatedAt2, input) {
|
|
19510
|
+
const currentUpdatedAt = Date.parse(expectedUpdatedAt2);
|
|
19511
|
+
const observedNow = Date.now();
|
|
19512
|
+
const now = new Date(
|
|
19513
|
+
Number.isNaN(currentUpdatedAt) ? observedNow : Math.max(observedNow, currentUpdatedAt + 1)
|
|
19514
|
+
).toISOString();
|
|
19515
|
+
const graphJson = JSON.stringify({
|
|
19516
|
+
originNodeId: input.originNodeId,
|
|
19517
|
+
nodes: input.nodes,
|
|
19518
|
+
edges: input.edges
|
|
19519
|
+
});
|
|
19520
|
+
this.immediateTransaction(() => {
|
|
19521
|
+
const current = this.getStructure(id);
|
|
19522
|
+
if (!current) {
|
|
19523
|
+
throw new RvwError("NOT_FOUND", "Structure\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002", { status: 404 });
|
|
19524
|
+
}
|
|
19525
|
+
if (current.updatedAt !== expectedUpdatedAt2) {
|
|
19526
|
+
throw new RvwError(
|
|
19527
|
+
"STRUCTURE_CONFLICT",
|
|
19528
|
+
"Structure\u304C\u53D6\u5F97\u5F8C\u306B\u66F4\u65B0\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u73FE\u5728\u5024\u3092\u8AAD\u307F\u76F4\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
19529
|
+
{
|
|
19530
|
+
status: 409,
|
|
19531
|
+
details: { expectedUpdatedAt: expectedUpdatedAt2, currentUpdatedAt: current.updatedAt }
|
|
19532
|
+
}
|
|
19533
|
+
);
|
|
19534
|
+
}
|
|
19535
|
+
const retiredNodeIds = new Set(
|
|
19536
|
+
this.database.prepare("SELECT node_id FROM structure_retired_node_ids WHERE structure_id = ?").all(id).map((row) => stringValue(row, "node_id"))
|
|
19537
|
+
);
|
|
19538
|
+
const retiredEdgeIds = new Set(
|
|
19539
|
+
this.database.prepare("SELECT edge_id FROM structure_retired_edge_ids WHERE structure_id = ?").all(id).map((row) => stringValue(row, "edge_id"))
|
|
19540
|
+
);
|
|
19541
|
+
const reusedNode = input.nodes.find((node2) => retiredNodeIds.has(node2.id));
|
|
19542
|
+
if (reusedNode) {
|
|
19543
|
+
throw new RvwError(
|
|
19544
|
+
"INVALID_INPUT",
|
|
19545
|
+
`\u524A\u9664\u6E08\u307F\u306EStructure Node ID\u306F\u518D\u5229\u7528\u3067\u304D\u307E\u305B\u3093: ${reusedNode.id}`
|
|
19546
|
+
);
|
|
19547
|
+
}
|
|
19548
|
+
const reusedEdge = input.edges.find((edge) => retiredEdgeIds.has(edge.id));
|
|
19549
|
+
if (reusedEdge) {
|
|
19550
|
+
throw new RvwError(
|
|
19551
|
+
"INVALID_INPUT",
|
|
19552
|
+
`\u524A\u9664\u6E08\u307F\u306EStructure Edge ID\u306F\u518D\u5229\u7528\u3067\u304D\u307E\u305B\u3093: ${reusedEdge.id}`
|
|
19553
|
+
);
|
|
19554
|
+
}
|
|
19555
|
+
const nextNodeIds = new Set(input.nodes.map((node2) => node2.id));
|
|
19556
|
+
const nextEdgeIds = new Set(input.edges.map((edge) => edge.id));
|
|
19557
|
+
const retiredAtThisUpdate = current.nodes.map((node2) => node2.id).filter((nodeId) => !nextNodeIds.has(nodeId));
|
|
19558
|
+
const retiredEdgesAtThisUpdate = current.edges.map((edge) => edge.id).filter((edgeId) => !nextEdgeIds.has(edgeId));
|
|
19559
|
+
const result = this.database.prepare(
|
|
19560
|
+
`UPDATE structures
|
|
19561
|
+
SET source_oid = ?, title = ?, scope = ?, graph_json = ?, updated_at = ?
|
|
19562
|
+
WHERE id = ? AND updated_at = ?`
|
|
19563
|
+
).run(input.sourceOid, input.title, input.scope, graphJson, now, id, expectedUpdatedAt2);
|
|
19564
|
+
if (Number(result.changes) === 0) {
|
|
19565
|
+
throw new RvwError(
|
|
19566
|
+
"STRUCTURE_CONFLICT",
|
|
19567
|
+
"Structure\u304C\u53D6\u5F97\u5F8C\u306B\u66F4\u65B0\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u73FE\u5728\u5024\u3092\u8AAD\u307F\u76F4\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
19568
|
+
{
|
|
19569
|
+
status: 409,
|
|
19570
|
+
details: { expectedUpdatedAt: expectedUpdatedAt2, currentUpdatedAt: current.updatedAt }
|
|
19571
|
+
}
|
|
19572
|
+
);
|
|
19573
|
+
}
|
|
19574
|
+
const retireNode = this.database.prepare(
|
|
19575
|
+
"INSERT OR IGNORE INTO structure_retired_node_ids(structure_id, node_id, retired_at) VALUES (?, ?, ?)"
|
|
19576
|
+
);
|
|
19577
|
+
for (const nodeId of retiredAtThisUpdate) retireNode.run(id, nodeId, now);
|
|
19578
|
+
const retireEdge = this.database.prepare(
|
|
19579
|
+
"INSERT OR IGNORE INTO structure_retired_edge_ids(structure_id, edge_id, retired_at) VALUES (?, ?, ?)"
|
|
19580
|
+
);
|
|
19581
|
+
for (const edgeId of retiredEdgesAtThisUpdate) retireEdge.run(id, edgeId, now);
|
|
19582
|
+
this.incrementChangeSequence();
|
|
19583
|
+
});
|
|
19584
|
+
const structure = this.getStructure(id);
|
|
19585
|
+
if (!structure) throw new RvwError("DATABASE_ERROR", "\u66F4\u65B0\u3057\u305FStructure\u3092\u8AAD\u307F\u51FA\u305B\u307E\u305B\u3093\u3002");
|
|
19586
|
+
return structure;
|
|
19587
|
+
}
|
|
19588
|
+
getStructureDeleteCounts(id) {
|
|
19589
|
+
const structure = this.getStructure(id);
|
|
19590
|
+
if (!structure) throw new RvwError("NOT_FOUND", "Structure\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002", { status: 404 });
|
|
19591
|
+
return {
|
|
19592
|
+
nodes: structure.nodes.length,
|
|
19593
|
+
edges: structure.edges.length,
|
|
19594
|
+
anchors: structure.nodes.filter((node2) => node2.anchor !== null).length + structure.edges.reduce((count, edge) => count + edge.anchors.length, 0)
|
|
19595
|
+
};
|
|
19596
|
+
}
|
|
19597
|
+
deleteStructure(id, expectedUpdatedAt2) {
|
|
19598
|
+
return this.immediateTransaction(() => {
|
|
19599
|
+
const structure = this.getStructure(id);
|
|
19600
|
+
if (!structure) {
|
|
19601
|
+
throw new RvwError("NOT_FOUND", "Structure\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002", { status: 404 });
|
|
19602
|
+
}
|
|
19603
|
+
if (structure.updatedAt !== expectedUpdatedAt2) {
|
|
19604
|
+
throw new RvwError(
|
|
19605
|
+
"STRUCTURE_CONFLICT",
|
|
19606
|
+
"Structure\u304Cpreview\u5F8C\u306B\u66F4\u65B0\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u73FE\u5728\u5024\u3092\u8AAD\u307F\u76F4\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
19607
|
+
{
|
|
19608
|
+
status: 409,
|
|
19609
|
+
details: { expectedUpdatedAt: expectedUpdatedAt2, currentUpdatedAt: structure.updatedAt }
|
|
19610
|
+
}
|
|
19611
|
+
);
|
|
19612
|
+
}
|
|
19613
|
+
const counts = this.getStructureDeleteCounts(id);
|
|
19614
|
+
const result = this.database.prepare("DELETE FROM structures WHERE id = ? AND updated_at = ?").run(id, expectedUpdatedAt2);
|
|
19615
|
+
if (Number(result.changes) === 0) {
|
|
19616
|
+
throw new RvwError(
|
|
19617
|
+
"STRUCTURE_CONFLICT",
|
|
19618
|
+
"Structure\u304Cpreview\u5F8C\u306B\u66F4\u65B0\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u73FE\u5728\u5024\u3092\u8AAD\u307F\u76F4\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
19619
|
+
{ status: 409, details: { expectedUpdatedAt: expectedUpdatedAt2 } }
|
|
19620
|
+
);
|
|
19621
|
+
}
|
|
19622
|
+
this.incrementChangeSequence();
|
|
19623
|
+
return {
|
|
19624
|
+
id: structure.id,
|
|
19625
|
+
ref: structure.ref,
|
|
19626
|
+
pullRequestId: structure.pullRequestId,
|
|
19627
|
+
counts
|
|
19628
|
+
};
|
|
19629
|
+
});
|
|
19338
19630
|
}
|
|
19339
19631
|
codeReferenceStorage(kind) {
|
|
19340
19632
|
return kind === "comment-post" ? { table: "comment_post_references", ownerColumn: "post_id" } : { table: "walkthrough_references", ownerColumn: "walkthrough_id" };
|
|
@@ -19895,7 +20187,7 @@ import path5 from "node:path";
|
|
|
19895
20187
|
import { TextDecoder as TextDecoder2 } from "node:util";
|
|
19896
20188
|
|
|
19897
20189
|
// src/shared/constants.ts
|
|
19898
|
-
var APP_VERSION = "0.
|
|
20190
|
+
var APP_VERSION = "0.4.0-beta.0";
|
|
19899
20191
|
var PROTOCOL_VERSION = 4;
|
|
19900
20192
|
var VIEWER_ID_HEADER = "x-rvw-viewer-id";
|
|
19901
20193
|
var VIEWER_OPEN_LEASE_HEADER = "x-rvw-viewer-open-lease";
|
|
@@ -19924,6 +20216,18 @@ var MAX_CODE_REFERENCE_PATH_CHARACTERS = 4096;
|
|
|
19924
20216
|
var MAX_CODE_REFERENCE_DESCRIPTION_CHARACTERS = 1e3;
|
|
19925
20217
|
var MAX_WALKTHROUGH_BODY_BYTES = 256 * 1024;
|
|
19926
20218
|
var MAX_WALKTHROUGH_TITLE_CHARACTERS = 200;
|
|
20219
|
+
var MAX_STRUCTURE_PAYLOAD_BYTES = 2 * 1024 * 1024;
|
|
20220
|
+
var MAX_STRUCTURE_TITLE_CHARACTERS = 200;
|
|
20221
|
+
var MAX_STRUCTURE_SCOPE_CHARACTERS = 4e3;
|
|
20222
|
+
var MAX_STRUCTURE_NODES = 50;
|
|
20223
|
+
var MAX_STRUCTURE_EDGES = 200;
|
|
20224
|
+
var MAX_STRUCTURE_EDGE_ANCHORS = 20;
|
|
20225
|
+
var MAX_STRUCTURE_SOURCE_ANCHORS = 400;
|
|
20226
|
+
var MAX_STRUCTURE_ID_CHARACTERS = 64;
|
|
20227
|
+
var STRUCTURE_ID_PATTERN = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/;
|
|
20228
|
+
var MAX_STRUCTURE_LABEL_CHARACTERS = 200;
|
|
20229
|
+
var MAX_STRUCTURE_DESCRIPTION_CHARACTERS = 2e3;
|
|
20230
|
+
var MAX_STRUCTURE_KIND_CHARACTERS = 100;
|
|
19927
20231
|
var MAX_SEARCH_QUERY_BYTES = 1024;
|
|
19928
20232
|
var MAX_SEARCH_RESULTS = 500;
|
|
19929
20233
|
var MAX_SEARCH_STDOUT_BYTES = 8 * 1024 * 1024;
|
|
@@ -20232,10 +20536,10 @@ var GitClient = class {
|
|
|
20232
20536
|
}
|
|
20233
20537
|
async ensurePullRequestObjects(input) {
|
|
20234
20538
|
const operationId = randomUUID2();
|
|
20235
|
-
const
|
|
20539
|
+
const prefix3 = `refs/rvw/tmp/${operationId}`;
|
|
20236
20540
|
try {
|
|
20237
20541
|
if (!await this.hasObject(input.cwd, input.headOid)) {
|
|
20238
|
-
const temporaryRef = `${
|
|
20542
|
+
const temporaryRef = `${prefix3}/head`;
|
|
20239
20543
|
await runProcess(
|
|
20240
20544
|
"git",
|
|
20241
20545
|
[
|
|
@@ -20260,7 +20564,7 @@ var GitClient = class {
|
|
|
20260
20564
|
}
|
|
20261
20565
|
}
|
|
20262
20566
|
if (!await this.hasObject(input.cwd, input.baseOid)) {
|
|
20263
|
-
const temporaryRef = `${
|
|
20567
|
+
const temporaryRef = `${prefix3}/base-tip`;
|
|
20264
20568
|
await runProcess(
|
|
20265
20569
|
"git",
|
|
20266
20570
|
[
|
|
@@ -20285,7 +20589,7 @@ var GitClient = class {
|
|
|
20285
20589
|
}
|
|
20286
20590
|
}
|
|
20287
20591
|
} finally {
|
|
20288
|
-
await this.deleteRefsByPrefix(input.cwd, `${
|
|
20592
|
+
await this.deleteRefsByPrefix(input.cwd, `${prefix3}/`).catch(() => void 0);
|
|
20289
20593
|
}
|
|
20290
20594
|
}
|
|
20291
20595
|
async mergeBase(cwd, baseOid, headOid) {
|
|
@@ -20350,14 +20654,14 @@ var GitClient = class {
|
|
|
20350
20654
|
return false;
|
|
20351
20655
|
}
|
|
20352
20656
|
}
|
|
20353
|
-
async listRefsByPrefix(cwd,
|
|
20354
|
-
const output = await runProcess("git", ["for-each-ref", "--format=%(refname)%00",
|
|
20657
|
+
async listRefsByPrefix(cwd, prefix3) {
|
|
20658
|
+
const output = await runProcess("git", ["for-each-ref", "--format=%(refname)%00", prefix3], {
|
|
20355
20659
|
cwd
|
|
20356
20660
|
});
|
|
20357
20661
|
return output.stdout.toString("utf8").split("\0").map((value) => value.trim()).filter(Boolean);
|
|
20358
20662
|
}
|
|
20359
|
-
async deleteRefsByPrefix(cwd,
|
|
20360
|
-
const refs = await this.listRefsByPrefix(cwd,
|
|
20663
|
+
async deleteRefsByPrefix(cwd, prefix3) {
|
|
20664
|
+
const refs = await this.listRefsByPrefix(cwd, prefix3);
|
|
20361
20665
|
if (refs.length === 0) return 0;
|
|
20362
20666
|
const input = ["start", ...refs.map((ref) => `delete ${ref}`), "prepare", "commit", ""].join(
|
|
20363
20667
|
"\n"
|
|
@@ -20366,8 +20670,8 @@ var GitClient = class {
|
|
|
20366
20670
|
return refs.length;
|
|
20367
20671
|
}
|
|
20368
20672
|
async replacePullRequestRefsForReset(cwd, number5, headOid) {
|
|
20369
|
-
const
|
|
20370
|
-
const existing = await this.listRefsByPrefix(cwd,
|
|
20673
|
+
const prefix3 = `refs/rvw/pr/${number5}/`;
|
|
20674
|
+
const existing = await this.listRefsByPrefix(cwd, prefix3);
|
|
20371
20675
|
const ref = this.commitRef(number5, headOid);
|
|
20372
20676
|
const commands = ["start"];
|
|
20373
20677
|
for (const ref2 of existing) {
|
|
@@ -23204,14 +23508,14 @@ function factorySpace(effects, ok2, type, max) {
|
|
|
23204
23508
|
function start(code) {
|
|
23205
23509
|
if (markdownSpace(code)) {
|
|
23206
23510
|
effects.enter(type);
|
|
23207
|
-
return
|
|
23511
|
+
return prefix3(code);
|
|
23208
23512
|
}
|
|
23209
23513
|
return ok2(code);
|
|
23210
23514
|
}
|
|
23211
|
-
function
|
|
23515
|
+
function prefix3(code) {
|
|
23212
23516
|
if (markdownSpace(code) && size++ < limit) {
|
|
23213
23517
|
effects.consume(code);
|
|
23214
|
-
return
|
|
23518
|
+
return prefix3;
|
|
23215
23519
|
}
|
|
23216
23520
|
effects.exit(type);
|
|
23217
23521
|
return ok2(code);
|
|
@@ -34510,7 +34814,7 @@ var LIMITED_QUIRKS_WITH_SYSTEM_ID_PUBLIC_ID_PREFIXES = [
|
|
|
34510
34814
|
"-//w3c//dtd html 4.01 transitional//"
|
|
34511
34815
|
];
|
|
34512
34816
|
function hasPrefix(publicId, prefixes) {
|
|
34513
|
-
return prefixes.some((
|
|
34817
|
+
return prefixes.some((prefix3) => publicId.startsWith(prefix3));
|
|
34514
34818
|
}
|
|
34515
34819
|
function isConforming(token) {
|
|
34516
34820
|
return token.name === VALID_DOCTYPE_NAME && token.publicId === null && (token.systemId === null || token.systemId === VALID_SYSTEM_ID);
|
|
@@ -42194,6 +42498,296 @@ var RvwService = class {
|
|
|
42194
42498
|
this.getPullRequest(pullRequestId);
|
|
42195
42499
|
return this.database.listWalkthroughs(pullRequestId);
|
|
42196
42500
|
}
|
|
42501
|
+
listStructures(pullRequestId) {
|
|
42502
|
+
this.getPullRequest(pullRequestId);
|
|
42503
|
+
return this.database.listStructures(pullRequestId);
|
|
42504
|
+
}
|
|
42505
|
+
listStructuresByReference(reference) {
|
|
42506
|
+
const pullRequest = this.resolveStoredPullRequest(reference);
|
|
42507
|
+
return { pullRequest, structures: this.database.listStructures(pullRequest.id) };
|
|
42508
|
+
}
|
|
42509
|
+
getStructure(pullRequestId, structureId) {
|
|
42510
|
+
this.getPullRequest(pullRequestId);
|
|
42511
|
+
const structure = this.database.getStructure(structureId);
|
|
42512
|
+
if (!structure || structure.pullRequestId !== pullRequestId) {
|
|
42513
|
+
throw new RvwError("NOT_FOUND", "Structure\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002", { status: 404 });
|
|
42514
|
+
}
|
|
42515
|
+
return structure;
|
|
42516
|
+
}
|
|
42517
|
+
getStructureByUri(uri) {
|
|
42518
|
+
const structure = this.database.getStructure(parseStructureUri(uri));
|
|
42519
|
+
if (!structure) {
|
|
42520
|
+
throw new RvwError("NOT_FOUND", "Structure\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002", { status: 404 });
|
|
42521
|
+
}
|
|
42522
|
+
return {
|
|
42523
|
+
pullRequest: this.getPullRequest(structure.pullRequestId),
|
|
42524
|
+
structure
|
|
42525
|
+
};
|
|
42526
|
+
}
|
|
42527
|
+
async validateSourceAnchor(pullRequest, sourceOid, anchor, subject, documents) {
|
|
42528
|
+
assertCodeReferencePath(anchor.path);
|
|
42529
|
+
const startLine = anchor.startLine ?? null;
|
|
42530
|
+
const endLine = anchor.endLine ?? null;
|
|
42531
|
+
assertLinePair(startLine, endLine);
|
|
42532
|
+
let contentPromise = documents.get(anchor.path);
|
|
42533
|
+
if (!contentPromise) {
|
|
42534
|
+
contentPromise = this.getDocument({
|
|
42535
|
+
kind: "repository-file",
|
|
42536
|
+
pullRequestId: pullRequest.id,
|
|
42537
|
+
sourceOid,
|
|
42538
|
+
path: anchor.path
|
|
42539
|
+
});
|
|
42540
|
+
documents.set(anchor.path, contentPromise);
|
|
42541
|
+
}
|
|
42542
|
+
const content3 = await contentPromise;
|
|
42543
|
+
if (content3.availability !== "available") {
|
|
42544
|
+
throw new RvwError("INVALID_INPUT", `${subject}\u306Esource\u3092\u8868\u793A\u3067\u304D\u307E\u305B\u3093: ${anchor.path}`);
|
|
42545
|
+
}
|
|
42546
|
+
this.validateLineRange(content3.text ?? "", startLine, endLine, subject);
|
|
42547
|
+
return { path: anchor.path, startLine, endLine };
|
|
42548
|
+
}
|
|
42549
|
+
assertStructureText(value, maximum, subject) {
|
|
42550
|
+
const normalized = value.trim();
|
|
42551
|
+
if (normalized.length === 0 || value.length > maximum) {
|
|
42552
|
+
throw new RvwError("INVALID_INPUT", `${subject}\u306F1\u301C${maximum}\u6587\u5B57\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`);
|
|
42553
|
+
}
|
|
42554
|
+
return normalized;
|
|
42555
|
+
}
|
|
42556
|
+
assertStructureId(value, subject) {
|
|
42557
|
+
if (!STRUCTURE_ID_PATTERN.test(value)) {
|
|
42558
|
+
throw new RvwError(
|
|
42559
|
+
"INVALID_INPUT",
|
|
42560
|
+
`${subject}\u306F\u82F1\u5B57\u3067\u59CB\u307E\u308B\u82F1\u6570\u5B57\u30FB_\u30FB-\u306E1\u301C${MAX_STRUCTURE_ID_CHARACTERS}\u6587\u5B57\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
42561
|
+
);
|
|
42562
|
+
}
|
|
42563
|
+
return value;
|
|
42564
|
+
}
|
|
42565
|
+
normalizeOptionalStructureText(value, maximum, subject) {
|
|
42566
|
+
if (value === null || value === void 0) return null;
|
|
42567
|
+
if (value.length > maximum) {
|
|
42568
|
+
throw new RvwError("INVALID_INPUT", `${subject}\u304C\u9577\u3059\u304E\u307E\u3059\u3002`);
|
|
42569
|
+
}
|
|
42570
|
+
return value.trim() || null;
|
|
42571
|
+
}
|
|
42572
|
+
async validateStructureContent(pullRequest, input) {
|
|
42573
|
+
await this.assertCommitAvailable(pullRequest, input.sourceOid);
|
|
42574
|
+
const title = this.assertStructureText(
|
|
42575
|
+
input.title,
|
|
42576
|
+
MAX_STRUCTURE_TITLE_CHARACTERS,
|
|
42577
|
+
"Structure title"
|
|
42578
|
+
);
|
|
42579
|
+
const scope = this.assertStructureText(
|
|
42580
|
+
input.scope,
|
|
42581
|
+
MAX_STRUCTURE_SCOPE_CHARACTERS,
|
|
42582
|
+
"Structure scope"
|
|
42583
|
+
);
|
|
42584
|
+
if (input.nodes.length < 1 || input.nodes.length > MAX_STRUCTURE_NODES) {
|
|
42585
|
+
throw new RvwError(
|
|
42586
|
+
"INVALID_INPUT",
|
|
42587
|
+
`Structure Node\u306F1\u301C${MAX_STRUCTURE_NODES}\u4EF6\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
42588
|
+
);
|
|
42589
|
+
}
|
|
42590
|
+
if (input.edges.length > MAX_STRUCTURE_EDGES) {
|
|
42591
|
+
throw new RvwError(
|
|
42592
|
+
"INVALID_INPUT",
|
|
42593
|
+
`Structure Edge\u306F${MAX_STRUCTURE_EDGES}\u4EF6\u4EE5\u4E0B\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
42594
|
+
);
|
|
42595
|
+
}
|
|
42596
|
+
const documents = /* @__PURE__ */ new Map();
|
|
42597
|
+
const nodeIds = /* @__PURE__ */ new Set();
|
|
42598
|
+
const nodes = [];
|
|
42599
|
+
for (const node2 of input.nodes) {
|
|
42600
|
+
const id = this.assertStructureId(node2.id, "Structure Node ID");
|
|
42601
|
+
if (nodeIds.has(id)) {
|
|
42602
|
+
throw new RvwError("INVALID_INPUT", `Structure Node ID\u304C\u91CD\u8907\u3057\u3066\u3044\u307E\u3059: ${id}`);
|
|
42603
|
+
}
|
|
42604
|
+
nodeIds.add(id);
|
|
42605
|
+
const label = this.assertStructureText(
|
|
42606
|
+
node2.label,
|
|
42607
|
+
MAX_STRUCTURE_LABEL_CHARACTERS,
|
|
42608
|
+
`Structure Node ${id} label`
|
|
42609
|
+
);
|
|
42610
|
+
const notation = node2.notation ?? "plain";
|
|
42611
|
+
if (!STRUCTURE_NODE_NOTATIONS.includes(notation)) {
|
|
42612
|
+
throw new RvwError("INVALID_INPUT", `Structure Node ${id} notation\u304C\u4E0D\u6B63\u3067\u3059\u3002`);
|
|
42613
|
+
}
|
|
42614
|
+
nodes.push({
|
|
42615
|
+
id,
|
|
42616
|
+
label,
|
|
42617
|
+
description: this.normalizeOptionalStructureText(
|
|
42618
|
+
node2.description,
|
|
42619
|
+
MAX_STRUCTURE_DESCRIPTION_CHARACTERS,
|
|
42620
|
+
`Structure Node ${id} description`
|
|
42621
|
+
),
|
|
42622
|
+
kind: this.normalizeOptionalStructureText(
|
|
42623
|
+
node2.kind,
|
|
42624
|
+
MAX_STRUCTURE_KIND_CHARACTERS,
|
|
42625
|
+
`Structure Node ${id} kind`
|
|
42626
|
+
),
|
|
42627
|
+
notation,
|
|
42628
|
+
anchor: node2.anchor ? await this.validateSourceAnchor(
|
|
42629
|
+
pullRequest,
|
|
42630
|
+
input.sourceOid,
|
|
42631
|
+
node2.anchor,
|
|
42632
|
+
`Structure Node ${id}`,
|
|
42633
|
+
documents
|
|
42634
|
+
) : null
|
|
42635
|
+
});
|
|
42636
|
+
}
|
|
42637
|
+
const edgeIds = /* @__PURE__ */ new Set();
|
|
42638
|
+
const edges = [];
|
|
42639
|
+
for (const edge of input.edges) {
|
|
42640
|
+
const id = this.assertStructureId(edge.id, "Structure Edge ID");
|
|
42641
|
+
if (edgeIds.has(id)) {
|
|
42642
|
+
throw new RvwError("INVALID_INPUT", `Structure Edge ID\u304C\u91CD\u8907\u3057\u3066\u3044\u307E\u3059: ${id}`);
|
|
42643
|
+
}
|
|
42644
|
+
edgeIds.add(id);
|
|
42645
|
+
if (!nodeIds.has(edge.from) || !nodeIds.has(edge.to)) {
|
|
42646
|
+
throw new RvwError(
|
|
42647
|
+
"INVALID_INPUT",
|
|
42648
|
+
`Structure Edge ${id} \u306Eendpoint\u304C\u5B58\u5728\u3057\u307E\u305B\u3093: ${edge.from} \u2192 ${edge.to}`
|
|
42649
|
+
);
|
|
42650
|
+
}
|
|
42651
|
+
if (typeof edge.directed !== "boolean") {
|
|
42652
|
+
throw new RvwError("INVALID_INPUT", `Structure Edge ${id} \u306Edirected\u304C\u5FC5\u8981\u3067\u3059\u3002`);
|
|
42653
|
+
}
|
|
42654
|
+
const anchors = edge.anchors ?? [];
|
|
42655
|
+
if (anchors.length > MAX_STRUCTURE_EDGE_ANCHORS) {
|
|
42656
|
+
throw new RvwError(
|
|
42657
|
+
"INVALID_INPUT",
|
|
42658
|
+
`Structure Edge ${id} \u306Eanchor\u306F${MAX_STRUCTURE_EDGE_ANCHORS}\u4EF6\u4EE5\u4E0B\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
42659
|
+
);
|
|
42660
|
+
}
|
|
42661
|
+
edges.push({
|
|
42662
|
+
id,
|
|
42663
|
+
from: edge.from,
|
|
42664
|
+
to: edge.to,
|
|
42665
|
+
label: this.assertStructureText(
|
|
42666
|
+
edge.label,
|
|
42667
|
+
MAX_STRUCTURE_LABEL_CHARACTERS,
|
|
42668
|
+
`Structure Edge ${id} label`
|
|
42669
|
+
),
|
|
42670
|
+
directed: edge.directed,
|
|
42671
|
+
anchors: await Promise.all(
|
|
42672
|
+
anchors.map(
|
|
42673
|
+
(anchor, index2) => this.validateSourceAnchor(
|
|
42674
|
+
pullRequest,
|
|
42675
|
+
input.sourceOid,
|
|
42676
|
+
anchor,
|
|
42677
|
+
`Structure Edge ${id} anchor ${index2 + 1}`,
|
|
42678
|
+
documents
|
|
42679
|
+
)
|
|
42680
|
+
)
|
|
42681
|
+
)
|
|
42682
|
+
});
|
|
42683
|
+
}
|
|
42684
|
+
if (typeof input.originNodeId !== "string") {
|
|
42685
|
+
throw new RvwError("INVALID_INPUT", "originNodeId\u304C\u5FC5\u8981\u3067\u3059\u3002");
|
|
42686
|
+
}
|
|
42687
|
+
const originNodeId = this.assertStructureId(input.originNodeId, "Structure originNodeId");
|
|
42688
|
+
if (!nodeIds.has(originNodeId)) {
|
|
42689
|
+
throw new RvwError("INVALID_INPUT", `originNodeId Node\u304C\u5B58\u5728\u3057\u307E\u305B\u3093: ${originNodeId}`);
|
|
42690
|
+
}
|
|
42691
|
+
const originNode = nodes.find((node2) => node2.id === originNodeId);
|
|
42692
|
+
if (originNode.anchor === null) {
|
|
42693
|
+
throw new RvwError("INVALID_INPUT", "Structure origin Node\u306B\u306Fsource anchor\u304C\u5FC5\u8981\u3067\u3059\u3002");
|
|
42694
|
+
}
|
|
42695
|
+
const neighbors = new Map(nodes.map((node2) => [node2.id, /* @__PURE__ */ new Set()]));
|
|
42696
|
+
for (const edge of edges) {
|
|
42697
|
+
neighbors.get(edge.from).add(edge.to);
|
|
42698
|
+
neighbors.get(edge.to).add(edge.from);
|
|
42699
|
+
}
|
|
42700
|
+
const reached = /* @__PURE__ */ new Set([originNodeId]);
|
|
42701
|
+
const queue = [originNodeId];
|
|
42702
|
+
while (queue.length > 0) {
|
|
42703
|
+
const current = queue.shift();
|
|
42704
|
+
for (const neighbor of neighbors.get(current) ?? []) {
|
|
42705
|
+
if (reached.has(neighbor)) continue;
|
|
42706
|
+
reached.add(neighbor);
|
|
42707
|
+
queue.push(neighbor);
|
|
42708
|
+
}
|
|
42709
|
+
}
|
|
42710
|
+
const disconnected = nodes.filter((node2) => !reached.has(node2.id)).map((node2) => node2.id);
|
|
42711
|
+
if (disconnected.length > 0) {
|
|
42712
|
+
throw new RvwError(
|
|
42713
|
+
"INVALID_INPUT",
|
|
42714
|
+
`Structure\u306E\u5168Node\u3092origin\u304B\u3089\u8FBF\u308C\u308B\u95A2\u4FC2graph\u306B\u3057\u3066\u304F\u3060\u3055\u3044: ${disconnected.join(", ")}`
|
|
42715
|
+
);
|
|
42716
|
+
}
|
|
42717
|
+
const anchorCount = nodes.filter((node2) => node2.anchor !== null).length + edges.reduce((count, edge) => count + edge.anchors.length, 0);
|
|
42718
|
+
if (anchorCount < 1) {
|
|
42719
|
+
throw new RvwError(
|
|
42720
|
+
"INVALID_INPUT",
|
|
42721
|
+
"Structure\u306B\u306Fsource anchor\u3092\u5C11\u306A\u304F\u3068\u30821\u4EF6\u542B\u3081\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
42722
|
+
);
|
|
42723
|
+
}
|
|
42724
|
+
if (anchorCount > MAX_STRUCTURE_SOURCE_ANCHORS) {
|
|
42725
|
+
throw new RvwError(
|
|
42726
|
+
"INVALID_INPUT",
|
|
42727
|
+
`Structure\u306Esource anchor\u306F\u5408\u8A08${MAX_STRUCTURE_SOURCE_ANCHORS}\u4EF6\u4EE5\u4E0B\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
42728
|
+
);
|
|
42729
|
+
}
|
|
42730
|
+
const graph = { originNodeId, nodes, edges };
|
|
42731
|
+
if (Buffer.byteLength(JSON.stringify(graph), "utf8") > MAX_STRUCTURE_PAYLOAD_BYTES) {
|
|
42732
|
+
throw new RvwError(
|
|
42733
|
+
"INVALID_INPUT",
|
|
42734
|
+
`Structure payload\u306F${MAX_STRUCTURE_PAYLOAD_BYTES} UTF-8 bytes\u4EE5\u4E0B\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
42735
|
+
);
|
|
42736
|
+
}
|
|
42737
|
+
return { sourceOid: input.sourceOid, title, scope, ...graph };
|
|
42738
|
+
}
|
|
42739
|
+
async publishStructure(input) {
|
|
42740
|
+
if (typeof input.idempotencyKey !== "string") {
|
|
42741
|
+
throw new RvwError("INVALID_INPUT", "idempotencyKey\u304C\u5FC5\u8981\u3067\u3059\u3002");
|
|
42742
|
+
}
|
|
42743
|
+
assertIdempotencyKey(input.idempotencyKey);
|
|
42744
|
+
const pullRequest = this.resolveStoredPullRequest(input.pullRequest);
|
|
42745
|
+
const content3 = await this.validateStructureContent(pullRequest, input);
|
|
42746
|
+
return await this.writeWithRetainedCommit(
|
|
42747
|
+
pullRequest,
|
|
42748
|
+
content3.sourceOid,
|
|
42749
|
+
"Structure",
|
|
42750
|
+
() => this.database.createStructure({
|
|
42751
|
+
pullRequestId: pullRequest.id,
|
|
42752
|
+
...content3,
|
|
42753
|
+
idempotencyKey: input.idempotencyKey,
|
|
42754
|
+
idempotencyRequestHash: idempotencyRequestHash({
|
|
42755
|
+
operation: "structure.publish",
|
|
42756
|
+
pullRequestId: pullRequest.id,
|
|
42757
|
+
content: content3
|
|
42758
|
+
})
|
|
42759
|
+
})
|
|
42760
|
+
);
|
|
42761
|
+
}
|
|
42762
|
+
async updateStructure(uri, input) {
|
|
42763
|
+
const { pullRequest, structure } = this.getStructureByUri(uri);
|
|
42764
|
+
if (typeof input.expectedUpdatedAt !== "string" || input.expectedUpdatedAt.length === 0) {
|
|
42765
|
+
throw new RvwError("INVALID_INPUT", "expectedUpdatedAt\u304C\u5FC5\u8981\u3067\u3059\u3002");
|
|
42766
|
+
}
|
|
42767
|
+
const content3 = await this.validateStructureContent(pullRequest, input);
|
|
42768
|
+
return await this.writeWithRetainedCommit(
|
|
42769
|
+
pullRequest,
|
|
42770
|
+
content3.sourceOid,
|
|
42771
|
+
"Structure",
|
|
42772
|
+
() => this.database.updateStructure(structure.id, input.expectedUpdatedAt, content3)
|
|
42773
|
+
);
|
|
42774
|
+
}
|
|
42775
|
+
getStructureDeletePreview(uri) {
|
|
42776
|
+
const { structure } = this.getStructureByUri(uri);
|
|
42777
|
+
return {
|
|
42778
|
+
structure,
|
|
42779
|
+
counts: this.database.getStructureDeleteCounts(structure.id),
|
|
42780
|
+
confirmationRequired: true
|
|
42781
|
+
};
|
|
42782
|
+
}
|
|
42783
|
+
deleteStructureByUri(uri, expectedUpdatedAt2) {
|
|
42784
|
+
const { structure } = this.getStructureByUri(uri);
|
|
42785
|
+
return this.database.deleteStructure(structure.id, expectedUpdatedAt2);
|
|
42786
|
+
}
|
|
42787
|
+
deleteStructure(pullRequestId, structureId, expectedUpdatedAt2) {
|
|
42788
|
+
this.getStructure(pullRequestId, structureId);
|
|
42789
|
+
return this.database.deleteStructure(structureId, expectedUpdatedAt2);
|
|
42790
|
+
}
|
|
42197
42791
|
getWalkthrough(pullRequestId, walkthroughId) {
|
|
42198
42792
|
this.getPullRequest(pullRequestId);
|
|
42199
42793
|
const walkthrough = this.database.getWalkthrough(walkthroughId);
|
|
@@ -42768,6 +43362,7 @@ import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
|
42768
43362
|
var skillNames = [
|
|
42769
43363
|
"rvw",
|
|
42770
43364
|
"rvw-walkthrough",
|
|
43365
|
+
"rvw-structure",
|
|
42771
43366
|
"rvw-watch-comments"
|
|
42772
43367
|
];
|
|
42773
43368
|
var INSTALL_METADATA_FILE = ".rvw-install.json";
|
|
@@ -46585,8 +47180,11 @@ var Hono2 = class extends Hono {
|
|
|
46585
47180
|
var nonEmptyString = external_exports.string().min(1);
|
|
46586
47181
|
var commentUri = external_exports.string().regex(/^rvw:\/\/comment\//);
|
|
46587
47182
|
var walkthroughUri = external_exports.string().regex(/^rvw:\/\/walkthrough\//);
|
|
47183
|
+
var structureUri = external_exports.string().regex(/^rvw:\/\/structure\//);
|
|
46588
47184
|
var nullableCommentLine = external_exports.number().int().positive().nullable().optional().default(null);
|
|
46589
47185
|
var idempotencyKey = external_exports.string().min(1).max(MAX_IDEMPOTENCY_KEY_CHARACTERS).optional();
|
|
47186
|
+
var requiredIdempotencyKey = external_exports.string().min(1).max(MAX_IDEMPOTENCY_KEY_CHARACTERS);
|
|
47187
|
+
var expectedUpdatedAt = external_exports.string().min(1).max(100);
|
|
46590
47188
|
var commentTargetInputSchema = external_exports.union([
|
|
46591
47189
|
external_exports.object({ kind: external_exports.literal("pull-request") }).strict(),
|
|
46592
47190
|
external_exports.object({
|
|
@@ -46709,6 +47307,151 @@ var walkthroughPublishInputSchema = walkthroughContentInputSchema.extend({
|
|
|
46709
47307
|
pullRequest: nonEmptyString
|
|
46710
47308
|
});
|
|
46711
47309
|
var walkthroughUpdateInputSchema = walkthroughContentInputSchema;
|
|
47310
|
+
var sourceAnchorInputSchema = external_exports.object({
|
|
47311
|
+
path: external_exports.string().min(1).max(MAX_CODE_REFERENCE_PATH_CHARACTERS),
|
|
47312
|
+
startLine: external_exports.number().int().positive().nullable().optional().default(null),
|
|
47313
|
+
endLine: external_exports.number().int().positive().nullable().optional().default(null)
|
|
47314
|
+
}).strict().superRefine((anchor, context) => {
|
|
47315
|
+
if (anchor.startLine === null !== (anchor.endLine === null)) {
|
|
47316
|
+
context.addIssue({
|
|
47317
|
+
code: "custom",
|
|
47318
|
+
message: "startLine\u3068endLine\u306F\u4E21\u65B9\u6307\u5B9A\u3059\u308B\u304B\u3001\u4E21\u65B9\u7701\u7565\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
47319
|
+
});
|
|
47320
|
+
return;
|
|
47321
|
+
}
|
|
47322
|
+
if (anchor.startLine !== null && anchor.endLine !== null && anchor.endLine < anchor.startLine) {
|
|
47323
|
+
context.addIssue({ code: "custom", message: "endLine\u306FstartLine\u4EE5\u4E0A\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002" });
|
|
47324
|
+
}
|
|
47325
|
+
});
|
|
47326
|
+
var structureNodeInputSchema = external_exports.object({
|
|
47327
|
+
id: external_exports.string().max(MAX_STRUCTURE_ID_CHARACTERS).regex(STRUCTURE_ID_PATTERN),
|
|
47328
|
+
label: external_exports.string().min(1).max(MAX_STRUCTURE_LABEL_CHARACTERS),
|
|
47329
|
+
description: external_exports.string().max(MAX_STRUCTURE_DESCRIPTION_CHARACTERS).nullable().optional().default(null),
|
|
47330
|
+
kind: external_exports.string().max(MAX_STRUCTURE_KIND_CHARACTERS).nullable().optional().default(null),
|
|
47331
|
+
notation: external_exports.enum(STRUCTURE_NODE_NOTATIONS).optional().default("plain"),
|
|
47332
|
+
anchor: sourceAnchorInputSchema.nullable().optional().default(null)
|
|
47333
|
+
}).strict();
|
|
47334
|
+
var structureEdgeInputSchema = external_exports.object({
|
|
47335
|
+
id: external_exports.string().max(MAX_STRUCTURE_ID_CHARACTERS).regex(STRUCTURE_ID_PATTERN),
|
|
47336
|
+
from: external_exports.string().max(MAX_STRUCTURE_ID_CHARACTERS).regex(STRUCTURE_ID_PATTERN),
|
|
47337
|
+
to: external_exports.string().max(MAX_STRUCTURE_ID_CHARACTERS).regex(STRUCTURE_ID_PATTERN),
|
|
47338
|
+
label: external_exports.string().min(1).max(MAX_STRUCTURE_LABEL_CHARACTERS),
|
|
47339
|
+
directed: external_exports.boolean(),
|
|
47340
|
+
anchors: external_exports.array(sourceAnchorInputSchema).max(MAX_STRUCTURE_EDGE_ANCHORS).optional().default([])
|
|
47341
|
+
}).strict();
|
|
47342
|
+
var structureContentShape = {
|
|
47343
|
+
sourceOid: external_exports.string().regex(GIT_OBJECT_ID_PATTERN),
|
|
47344
|
+
title: external_exports.string().min(1).max(MAX_STRUCTURE_TITLE_CHARACTERS),
|
|
47345
|
+
scope: external_exports.string().min(1).max(MAX_STRUCTURE_SCOPE_CHARACTERS),
|
|
47346
|
+
originNodeId: external_exports.string().max(MAX_STRUCTURE_ID_CHARACTERS).regex(STRUCTURE_ID_PATTERN),
|
|
47347
|
+
nodes: external_exports.array(structureNodeInputSchema).min(1).max(MAX_STRUCTURE_NODES),
|
|
47348
|
+
edges: external_exports.array(structureEdgeInputSchema).max(MAX_STRUCTURE_EDGES)
|
|
47349
|
+
};
|
|
47350
|
+
function refineStructureContent(value, context) {
|
|
47351
|
+
const nodeIds = /* @__PURE__ */ new Set();
|
|
47352
|
+
for (const [index2, node2] of value.nodes.entries()) {
|
|
47353
|
+
if (nodeIds.has(node2.id)) {
|
|
47354
|
+
context.addIssue({
|
|
47355
|
+
code: "custom",
|
|
47356
|
+
path: ["nodes", index2, "id"],
|
|
47357
|
+
message: "Node ID\u304C\u91CD\u8907\u3057\u3066\u3044\u307E\u3059\u3002"
|
|
47358
|
+
});
|
|
47359
|
+
}
|
|
47360
|
+
nodeIds.add(node2.id);
|
|
47361
|
+
}
|
|
47362
|
+
const edgeIds = /* @__PURE__ */ new Set();
|
|
47363
|
+
for (const [index2, edge] of value.edges.entries()) {
|
|
47364
|
+
if (edgeIds.has(edge.id)) {
|
|
47365
|
+
context.addIssue({
|
|
47366
|
+
code: "custom",
|
|
47367
|
+
path: ["edges", index2, "id"],
|
|
47368
|
+
message: "Edge ID\u304C\u91CD\u8907\u3057\u3066\u3044\u307E\u3059\u3002"
|
|
47369
|
+
});
|
|
47370
|
+
}
|
|
47371
|
+
edgeIds.add(edge.id);
|
|
47372
|
+
if (!nodeIds.has(edge.from)) {
|
|
47373
|
+
context.addIssue({
|
|
47374
|
+
code: "custom",
|
|
47375
|
+
path: ["edges", index2, "from"],
|
|
47376
|
+
message: "Edge\u306Efrom Node\u304C\u5B58\u5728\u3057\u307E\u305B\u3093\u3002"
|
|
47377
|
+
});
|
|
47378
|
+
}
|
|
47379
|
+
if (!nodeIds.has(edge.to)) {
|
|
47380
|
+
context.addIssue({
|
|
47381
|
+
code: "custom",
|
|
47382
|
+
path: ["edges", index2, "to"],
|
|
47383
|
+
message: "Edge\u306Eto Node\u304C\u5B58\u5728\u3057\u307E\u305B\u3093\u3002"
|
|
47384
|
+
});
|
|
47385
|
+
}
|
|
47386
|
+
}
|
|
47387
|
+
const originIndex = value.nodes.findIndex((node2) => node2.id === value.originNodeId);
|
|
47388
|
+
if (originIndex === -1) {
|
|
47389
|
+
context.addIssue({
|
|
47390
|
+
code: "custom",
|
|
47391
|
+
path: ["originNodeId"],
|
|
47392
|
+
message: "originNodeId Node\u304C\u5B58\u5728\u3057\u307E\u305B\u3093\u3002"
|
|
47393
|
+
});
|
|
47394
|
+
} else if (value.nodes[originIndex]?.anchor === null) {
|
|
47395
|
+
context.addIssue({
|
|
47396
|
+
code: "custom",
|
|
47397
|
+
path: ["nodes", originIndex, "anchor"],
|
|
47398
|
+
message: "origin Node\u306B\u306Fsource anchor\u304C\u5FC5\u8981\u3067\u3059\u3002"
|
|
47399
|
+
});
|
|
47400
|
+
}
|
|
47401
|
+
if (originIndex !== -1) {
|
|
47402
|
+
const neighbors = new Map(value.nodes.map((node2) => [node2.id, /* @__PURE__ */ new Set()]));
|
|
47403
|
+
for (const edge of value.edges) {
|
|
47404
|
+
if (!neighbors.has(edge.from) || !neighbors.has(edge.to)) continue;
|
|
47405
|
+
neighbors.get(edge.from).add(edge.to);
|
|
47406
|
+
neighbors.get(edge.to).add(edge.from);
|
|
47407
|
+
}
|
|
47408
|
+
const reached = /* @__PURE__ */ new Set([value.originNodeId]);
|
|
47409
|
+
const queue = [value.originNodeId];
|
|
47410
|
+
while (queue.length > 0) {
|
|
47411
|
+
const current = queue.shift();
|
|
47412
|
+
for (const neighbor of neighbors.get(current) ?? []) {
|
|
47413
|
+
if (reached.has(neighbor)) continue;
|
|
47414
|
+
reached.add(neighbor);
|
|
47415
|
+
queue.push(neighbor);
|
|
47416
|
+
}
|
|
47417
|
+
}
|
|
47418
|
+
const disconnected = value.nodes.filter((node2) => !reached.has(node2.id)).map((node2) => node2.id);
|
|
47419
|
+
if (disconnected.length > 0) {
|
|
47420
|
+
context.addIssue({
|
|
47421
|
+
code: "custom",
|
|
47422
|
+
path: ["nodes"],
|
|
47423
|
+
message: `\u5168Node\u3092origin\u304B\u3089\u8FBF\u308C\u308B\u95A2\u4FC2graph\u306B\u3057\u3066\u304F\u3060\u3055\u3044: ${disconnected.join(", ")}`
|
|
47424
|
+
});
|
|
47425
|
+
}
|
|
47426
|
+
}
|
|
47427
|
+
const anchorCount = value.nodes.filter((node2) => node2.anchor !== null).length + value.edges.reduce((count, edge) => count + edge.anchors.length, 0);
|
|
47428
|
+
if (anchorCount < 1) {
|
|
47429
|
+
context.addIssue({
|
|
47430
|
+
code: "custom",
|
|
47431
|
+
message: "Structure\u306B\u306Fsource anchor\u3092\u5C11\u306A\u304F\u3068\u30821\u4EF6\u542B\u3081\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
47432
|
+
});
|
|
47433
|
+
}
|
|
47434
|
+
if (anchorCount > MAX_STRUCTURE_SOURCE_ANCHORS) {
|
|
47435
|
+
context.addIssue({
|
|
47436
|
+
code: "custom",
|
|
47437
|
+
message: `Structure\u306Esource anchor\u306F\u5408\u8A08${MAX_STRUCTURE_SOURCE_ANCHORS}\u4EF6\u4EE5\u4E0B\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
47438
|
+
});
|
|
47439
|
+
}
|
|
47440
|
+
const graph = { originNodeId: value.originNodeId, nodes: value.nodes, edges: value.edges };
|
|
47441
|
+
if (Buffer.byteLength(JSON.stringify(graph), "utf8") > MAX_STRUCTURE_PAYLOAD_BYTES) {
|
|
47442
|
+
context.addIssue({
|
|
47443
|
+
code: "custom",
|
|
47444
|
+
message: `Structure payload\u306F${MAX_STRUCTURE_PAYLOAD_BYTES} UTF-8 bytes\u4EE5\u4E0B\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
47445
|
+
});
|
|
47446
|
+
}
|
|
47447
|
+
}
|
|
47448
|
+
var structureContentInputSchema = external_exports.object(structureContentShape).strict().superRefine(refineStructureContent);
|
|
47449
|
+
var structureUpdateInputSchema = external_exports.object({ expectedUpdatedAt, ...structureContentShape }).strict().superRefine(refineStructureContent);
|
|
47450
|
+
var structurePublishInputSchema = external_exports.object({
|
|
47451
|
+
pullRequest: nonEmptyString,
|
|
47452
|
+
idempotencyKey: requiredIdempotencyKey,
|
|
47453
|
+
...structureContentShape
|
|
47454
|
+
}).strict().superRefine(refineStructureContent);
|
|
46712
47455
|
var agentCommandInputSchemas = {
|
|
46713
47456
|
doctor: external_exports.object({ cwd: nonEmptyString }).strict(),
|
|
46714
47457
|
"pr.refresh": external_exports.object({ reference: nonEmptyString }).strict(),
|
|
@@ -46739,7 +47482,13 @@ var agentCommandInputSchemas = {
|
|
|
46739
47482
|
"walkthrough.publish": walkthroughPublishInputSchema,
|
|
46740
47483
|
"walkthrough.update": external_exports.object({ uri: walkthroughUri, content: walkthroughUpdateInputSchema }).strict(),
|
|
46741
47484
|
"walkthrough.delete.preview": external_exports.object({ uri: walkthroughUri }).strict(),
|
|
46742
|
-
"walkthrough.delete": external_exports.object({ uri: walkthroughUri, confirmed: external_exports.literal(true) }).strict()
|
|
47485
|
+
"walkthrough.delete": external_exports.object({ uri: walkthroughUri, confirmed: external_exports.literal(true) }).strict(),
|
|
47486
|
+
"structure.get": external_exports.object({ uri: structureUri }).strict(),
|
|
47487
|
+
"structure.list": external_exports.object({ reference: nonEmptyString }).strict(),
|
|
47488
|
+
"structure.publish": structurePublishInputSchema,
|
|
47489
|
+
"structure.update": external_exports.object({ uri: structureUri, content: structureUpdateInputSchema }).strict(),
|
|
47490
|
+
"structure.delete.preview": external_exports.object({ uri: structureUri }).strict(),
|
|
47491
|
+
"structure.delete": external_exports.object({ uri: structureUri, expectedUpdatedAt, confirmed: external_exports.literal(true) }).strict()
|
|
46743
47492
|
};
|
|
46744
47493
|
|
|
46745
47494
|
// src/server/schemas.ts
|
|
@@ -46772,6 +47521,7 @@ var openPullRequestSchema = external_exports.object({
|
|
|
46772
47521
|
cwd: external_exports.string().min(1)
|
|
46773
47522
|
});
|
|
46774
47523
|
var resetSchema = external_exports.object({ yes: external_exports.boolean() });
|
|
47524
|
+
var structureDeleteSchema = external_exports.object({ expectedUpdatedAt: external_exports.string().min(1).max(100) });
|
|
46775
47525
|
var viewerIdSchema = external_exports.uuid();
|
|
46776
47526
|
var viewerReleaseSchema = external_exports.object({ viewerId: viewerIdSchema });
|
|
46777
47527
|
var themePreferenceSchema = external_exports.object({ themePreference: external_exports.enum(themePreferences) });
|
|
@@ -47109,6 +47859,31 @@ function createApp(service, options) {
|
|
|
47109
47859
|
)
|
|
47110
47860
|
})
|
|
47111
47861
|
);
|
|
47862
|
+
app.get(
|
|
47863
|
+
"/api/pull-requests/:id/structures",
|
|
47864
|
+
(context) => context.json({
|
|
47865
|
+
ok: true,
|
|
47866
|
+
structures: service.listStructures(context.req.param("id"))
|
|
47867
|
+
})
|
|
47868
|
+
);
|
|
47869
|
+
app.get(
|
|
47870
|
+
"/api/pull-requests/:id/structures/:structureId",
|
|
47871
|
+
(context) => context.json({
|
|
47872
|
+
ok: true,
|
|
47873
|
+
structure: service.getStructure(context.req.param("id"), context.req.param("structureId"))
|
|
47874
|
+
})
|
|
47875
|
+
);
|
|
47876
|
+
app.delete("/api/pull-requests/:id/structures/:structureId", async (context) => {
|
|
47877
|
+
const input = structureDeleteSchema.parse(await context.req.json());
|
|
47878
|
+
return context.json({
|
|
47879
|
+
ok: true,
|
|
47880
|
+
deleted: service.deleteStructure(
|
|
47881
|
+
context.req.param("id"),
|
|
47882
|
+
context.req.param("structureId"),
|
|
47883
|
+
input.expectedUpdatedAt
|
|
47884
|
+
)
|
|
47885
|
+
});
|
|
47886
|
+
});
|
|
47112
47887
|
app.post("/api/comments", async (context) => {
|
|
47113
47888
|
const input = createCommentSchema.parse(await context.req.json());
|
|
47114
47889
|
return context.json(
|
|
@@ -47690,6 +48465,30 @@ async function dispatchAgentSocketRequest(service, rawRequest) {
|
|
|
47690
48465
|
const input = parseOperationInput("walkthrough.delete", request.input);
|
|
47691
48466
|
return service.deleteWalkthroughByUri(input.uri);
|
|
47692
48467
|
}
|
|
48468
|
+
case "structure.get": {
|
|
48469
|
+
const input = parseOperationInput("structure.get", request.input);
|
|
48470
|
+
return service.getStructureByUri(input.uri);
|
|
48471
|
+
}
|
|
48472
|
+
case "structure.list": {
|
|
48473
|
+
const input = parseOperationInput("structure.list", request.input);
|
|
48474
|
+
return service.listStructuresByReference(input.reference);
|
|
48475
|
+
}
|
|
48476
|
+
case "structure.publish": {
|
|
48477
|
+
const input = parseOperationInput("structure.publish", request.input);
|
|
48478
|
+
return await service.publishStructure(input);
|
|
48479
|
+
}
|
|
48480
|
+
case "structure.update": {
|
|
48481
|
+
const input = parseOperationInput("structure.update", request.input);
|
|
48482
|
+
return await service.updateStructure(input.uri, input.content);
|
|
48483
|
+
}
|
|
48484
|
+
case "structure.delete.preview": {
|
|
48485
|
+
const input = parseOperationInput("structure.delete.preview", request.input);
|
|
48486
|
+
return service.getStructureDeletePreview(input.uri);
|
|
48487
|
+
}
|
|
48488
|
+
case "structure.delete": {
|
|
48489
|
+
const input = parseOperationInput("structure.delete", request.input);
|
|
48490
|
+
return service.deleteStructureByUri(input.uri, input.expectedUpdatedAt);
|
|
48491
|
+
}
|
|
47693
48492
|
}
|
|
47694
48493
|
}
|
|
47695
48494
|
function parseResponse(value) {
|
|
@@ -47706,8 +48505,11 @@ function uncertainOutcome(operation, cause, timedOut = false) {
|
|
|
47706
48505
|
{
|
|
47707
48506
|
cause,
|
|
47708
48507
|
details: { agentSocketOutcomeUncertain: true, operation },
|
|
47709
|
-
suggestions: [
|
|
47710
|
-
"\
|
|
48508
|
+
suggestions: operation === "structure.publish" ? [
|
|
48509
|
+
"\u540C\u3058idempotencyKey\u3068\u540C\u3058payload\u3067publish\u3092\u518D\u5B9F\u884C\u3059\u308B\u3068\u3001\u65E2\u5B58\u306EStructure\u3078\u53CE\u675F\u3057\u307E\u3059\u3002",
|
|
48510
|
+
"rvw structure list <PR> --json\u3067\u3082stable URI\u3092\u78BA\u8A8D\u3067\u304D\u307E\u3059\u3002"
|
|
48511
|
+
] : [
|
|
48512
|
+
"\u73FE\u5728\u306E\u30B3\u30E1\u30F3\u30C8\u30FBWalkthrough\u30FBStructure\u30FBPR\u540C\u671F\u72B6\u614B\u3092\u8AAD\u307F\u76F4\u3057\u3001\u672A\u53CD\u6620\u306E\u5834\u5408\u3060\u3051\u518D\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
47711
48513
|
]
|
|
47712
48514
|
}
|
|
47713
48515
|
);
|
|
@@ -49313,6 +50115,11 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
|
|
|
49313
50115
|
"comment.resolve",
|
|
49314
50116
|
"comment.reopen",
|
|
49315
50117
|
"pullRequest.sync",
|
|
50118
|
+
"structure.list",
|
|
50119
|
+
"structure.read",
|
|
50120
|
+
"structure.publish",
|
|
50121
|
+
"structure.update",
|
|
50122
|
+
"structure.delete",
|
|
49316
50123
|
"walkthrough.read",
|
|
49317
50124
|
"walkthrough.publish",
|
|
49318
50125
|
"walkthrough.update",
|
|
@@ -49429,7 +50236,7 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
|
|
|
49429
50236
|
writeOutput(
|
|
49430
50237
|
options,
|
|
49431
50238
|
result2,
|
|
49432
|
-
`\u524A\u9664\u5BFE\u8C61: \u30B3\u30E1\u30F3\u30C8${preview.counts.comments}\u3001\u8FD4\u4FE1${preview.counts.posts}\u3001\u30B3\u30E1\u30F3\u30C8\u5185\u30B3\u30FC\u30C9\u53C2\u7167${preview.counts.commentReferences}\u3001\u5BFE\u8C61${preview.counts.targets}\u3001Walkthrough${preview.counts.walkthroughs}\u3001Walkthrough\u30B3\u30FC\u30C9\u53C2\u7167${preview.counts.walkthroughReferences}\u3001Git ref${preview.counts.gitRefs}
|
|
50239
|
+
`\u524A\u9664\u5BFE\u8C61: \u30B3\u30E1\u30F3\u30C8${preview.counts.comments}\u3001\u8FD4\u4FE1${preview.counts.posts}\u3001\u30B3\u30E1\u30F3\u30C8\u5185\u30B3\u30FC\u30C9\u53C2\u7167${preview.counts.commentReferences}\u3001\u5BFE\u8C61${preview.counts.targets}\u3001Walkthrough${preview.counts.walkthroughs}\u3001Walkthrough\u30B3\u30FC\u30C9\u53C2\u7167${preview.counts.walkthroughReferences}\u3001Structure${preview.counts.structures}\u3001Git ref${preview.counts.gitRefs}
|
|
49433
50240
|
\u7D9A\u884C\u3059\u308B\u306B\u306F --yes \u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
49434
50241
|
);
|
|
49435
50242
|
process.exitCode = 2;
|
|
@@ -49447,6 +50254,78 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
|
|
|
49447
50254
|
);
|
|
49448
50255
|
});
|
|
49449
50256
|
const comment3 = program2.command("comment").description("\u4FDD\u5B58\u6E08\u307F\u30B3\u30E1\u30F3\u30C8\u3092\u64CD\u4F5C");
|
|
50257
|
+
const structure = program2.command("structure").description("source anchor\u4ED8\u304DStructure\u3092\u7BA1\u7406");
|
|
50258
|
+
structure.command("publish").requiredOption("--stdin", "stdin\u304B\u3089JSON\u3092\u8AAD\u3080").requiredOption("--json", "JSON\u3067\u51FA\u529B").description("Structure\u3092\u767B\u9332\uFF08viewer\u306F\u958B\u304B\u305Anavigation\u3082\u5909\u66F4\u3057\u306A\u3044\uFF09").action(async () => {
|
|
50259
|
+
const input = structurePublishInputSchema.parse(await readStdinJson());
|
|
50260
|
+
const published = await callService(
|
|
50261
|
+
"structure.publish",
|
|
50262
|
+
input,
|
|
50263
|
+
async () => await getRuntime().service.publishStructure(input)
|
|
50264
|
+
);
|
|
50265
|
+
writeJson({ ok: true, structure: published });
|
|
50266
|
+
});
|
|
50267
|
+
structure.command("get").argument("<structure-uri>").requiredOption("--json", "JSON\u3067\u51FA\u529B").description("Structure\u306E\u73FE\u5728\u5185\u5BB9\u3092\u53D6\u5F97").action(async (uri) => {
|
|
50268
|
+
const result = await callService(
|
|
50269
|
+
"structure.get",
|
|
50270
|
+
{ uri },
|
|
50271
|
+
() => getRuntime().service.getStructureByUri(uri)
|
|
50272
|
+
);
|
|
50273
|
+
writeJson({ ok: true, ...result });
|
|
50274
|
+
});
|
|
50275
|
+
structure.command("list").argument("<pull-request>").requiredOption("--json", "JSON\u3067\u51FA\u529B").description("Pull Request\u306EStructure\u4E00\u89A7\u3068stable URI\u3092\u53D6\u5F97").action(async (reference) => {
|
|
50276
|
+
const result = await callService(
|
|
50277
|
+
"structure.list",
|
|
50278
|
+
{ reference },
|
|
50279
|
+
() => getRuntime().service.listStructuresByReference(reference)
|
|
50280
|
+
);
|
|
50281
|
+
writeJson({ ok: true, ...result });
|
|
50282
|
+
});
|
|
50283
|
+
structure.command("update").argument("<structure-uri>").requiredOption("--stdin", "stdin\u304B\u3089JSON\u3092\u8AAD\u3080").requiredOption("--json", "JSON\u3067\u51FA\u529B").description("Structure\u3092\u540C\u3058\u53C2\u7167\u306E\u307E\u307E\u5B8C\u5168\u7F6E\u63DB").action(async (uri) => {
|
|
50284
|
+
const content3 = structureUpdateInputSchema.parse(await readStdinJson());
|
|
50285
|
+
const updated = await callService(
|
|
50286
|
+
"structure.update",
|
|
50287
|
+
{ uri, content: content3 },
|
|
50288
|
+
async () => await getRuntime().service.updateStructure(uri, content3)
|
|
50289
|
+
);
|
|
50290
|
+
writeJson({ ok: true, structure: updated });
|
|
50291
|
+
});
|
|
50292
|
+
structure.command("delete").argument("<structure-uri>").option("--yes", "\u4E0D\u53EF\u9006\u306A\u524A\u9664\u3092\u78BA\u8A8D").option("--expected-updated-at <timestamp>", "preview\u3067\u53D6\u5F97\u3057\u305FupdatedAt").requiredOption("--json", "JSON\u3067\u51FA\u529B").description("Structure\u3092\u524A\u9664").action(
|
|
50293
|
+
async (uri, options) => {
|
|
50294
|
+
if (!options.yes) {
|
|
50295
|
+
const preview = await callService(
|
|
50296
|
+
"structure.delete.preview",
|
|
50297
|
+
{ uri },
|
|
50298
|
+
() => getRuntime().service.getStructureDeletePreview(uri)
|
|
50299
|
+
);
|
|
50300
|
+
writeJson({
|
|
50301
|
+
ok: false,
|
|
50302
|
+
error: {
|
|
50303
|
+
code: "STRUCTURE_DELETE_CONFIRMATION_REQUIRED",
|
|
50304
|
+
message: "structure delete\u306B\u306F--yes\u304C\u5FC5\u8981\u3067\u3059\u3002",
|
|
50305
|
+
suggestions: [
|
|
50306
|
+
`rvw structure delete ${uri} --yes --expected-updated-at '${preview.structure.updatedAt}' --json`
|
|
50307
|
+
]
|
|
50308
|
+
},
|
|
50309
|
+
...preview
|
|
50310
|
+
});
|
|
50311
|
+
process.exitCode = 2;
|
|
50312
|
+
return;
|
|
50313
|
+
}
|
|
50314
|
+
if (!options.expectedUpdatedAt) {
|
|
50315
|
+
throw new RvwError(
|
|
50316
|
+
"INVALID_INPUT",
|
|
50317
|
+
"confirmed structure delete\u306B\u306Fpreview\u306EexpectedUpdatedAt\u304C\u5FC5\u8981\u3067\u3059\u3002",
|
|
50318
|
+
{ suggestions: [`rvw structure delete ${uri} --json \u3067\u73FE\u5728\u5024\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002`] }
|
|
50319
|
+
);
|
|
50320
|
+
}
|
|
50321
|
+
const deleted = await callService(
|
|
50322
|
+
"structure.delete",
|
|
50323
|
+
{ uri, expectedUpdatedAt: options.expectedUpdatedAt, confirmed: true },
|
|
50324
|
+
() => getRuntime().service.deleteStructureByUri(uri, options.expectedUpdatedAt)
|
|
50325
|
+
);
|
|
50326
|
+
writeJson({ ok: true, deleted });
|
|
50327
|
+
}
|
|
50328
|
+
);
|
|
49450
50329
|
const walkthrough = program2.command("walkthrough").description("\u30B3\u30FC\u30C9\u53C2\u7167\u4ED8\u304Dwalkthrough\u3092\u7BA1\u7406");
|
|
49451
50330
|
walkthrough.command("publish").requiredOption("--stdin", "stdin\u304B\u3089JSON\u3092\u8AAD\u3080").requiredOption("--json", "JSON\u3067\u51FA\u529B").description("walkthrough\u3092\u767B\u9332\uFF08viewer\u306F\u958B\u304B\u305Anavigation\u3082\u5909\u66F4\u3057\u306A\u3044\uFF09").action(async () => {
|
|
49452
50331
|
const input = walkthroughPublishInputSchema.parse(await readStdinJson());
|