@a9n-shoji/rvw 0.3.2 → 0.4.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 +27 -0
- package/README.md +41 -7
- package/dist/cli.mjs +989 -45
- package/dist/cli.mjs.map +4 -4
- package/dist/web/assets/{CommentThread-CMXtuZ98.js → CommentThread-dsad9VaW.js} +4 -4
- package/dist/web/assets/DocumentViewer-CPq2FCqU.js +1414 -0
- 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-CyDDQwHl.js +1 -0
- package/dist/web/assets/{WalkthroughViewer-CuJMrKOW.js → WalkthroughViewer-c3XUP0RH.js} +4 -4
- package/dist/web/assets/index-CWOtOTHG.js +11 -0
- package/dist/web/assets/index-D_e3Zku8.css +1 -0
- 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 +152 -0
- package/skills/rvw-structure/agents/openai.yaml +4 -0
- package/skills/rvw-structure/references/structure-authoring.md +144 -0
- package/skills/rvw-walkthrough/SKILL.md +5 -0
- package/dist/web/assets/DocumentViewer-D-UGIxCU.js +0 -1417
- package/dist/web/assets/MermaidExpandedView-CyWRss2q.js +0 -4
- package/dist/web/assets/index-BNcvGFlf.css +0 -1
- 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";
|
|
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);
|
|
@@ -28162,10 +28466,17 @@ function placeMutableDocumentComment(anchor, currentText) {
|
|
|
28162
28466
|
return range ? { outdated: false, range } : { outdated: true, range: null };
|
|
28163
28467
|
}
|
|
28164
28468
|
|
|
28165
|
-
// src/domain/
|
|
28166
|
-
function
|
|
28469
|
+
// src/domain/source-reference.ts
|
|
28470
|
+
function sourceAnchorFingerprint(sourceOid, reference) {
|
|
28167
28471
|
return JSON.stringify([sourceOid, reference.path, reference.startLine, reference.endLine]);
|
|
28168
28472
|
}
|
|
28473
|
+
function structureSourceAnchor(structure, locator) {
|
|
28474
|
+
if (locator.kind === "node") {
|
|
28475
|
+
return structure.nodes.find((node2) => node2.id === locator.nodeId)?.anchor ?? null;
|
|
28476
|
+
}
|
|
28477
|
+
const edge = structure.edges.find((candidate) => candidate.id === locator.edgeId);
|
|
28478
|
+
return edge?.anchors[locator.anchorIndex] ?? null;
|
|
28479
|
+
}
|
|
28169
28480
|
|
|
28170
28481
|
// src/domain/source-excerpt.ts
|
|
28171
28482
|
var SOURCE_EXCERPT_CONTEXT_LINES = 20;
|
|
@@ -34510,7 +34821,7 @@ var LIMITED_QUIRKS_WITH_SYSTEM_ID_PUBLIC_ID_PREFIXES = [
|
|
|
34510
34821
|
"-//w3c//dtd html 4.01 transitional//"
|
|
34511
34822
|
];
|
|
34512
34823
|
function hasPrefix(publicId, prefixes) {
|
|
34513
|
-
return prefixes.some((
|
|
34824
|
+
return prefixes.some((prefix3) => publicId.startsWith(prefix3));
|
|
34514
34825
|
}
|
|
34515
34826
|
function isConforming(token) {
|
|
34516
34827
|
return token.name === VALID_DOCTYPE_NAME && token.publicId === null && (token.systemId === null || token.systemId === VALID_SYSTEM_ID);
|
|
@@ -42194,6 +42505,296 @@ var RvwService = class {
|
|
|
42194
42505
|
this.getPullRequest(pullRequestId);
|
|
42195
42506
|
return this.database.listWalkthroughs(pullRequestId);
|
|
42196
42507
|
}
|
|
42508
|
+
listStructures(pullRequestId) {
|
|
42509
|
+
this.getPullRequest(pullRequestId);
|
|
42510
|
+
return this.database.listStructures(pullRequestId);
|
|
42511
|
+
}
|
|
42512
|
+
listStructuresByReference(reference) {
|
|
42513
|
+
const pullRequest = this.resolveStoredPullRequest(reference);
|
|
42514
|
+
return { pullRequest, structures: this.database.listStructures(pullRequest.id) };
|
|
42515
|
+
}
|
|
42516
|
+
getStructure(pullRequestId, structureId) {
|
|
42517
|
+
this.getPullRequest(pullRequestId);
|
|
42518
|
+
const structure = this.database.getStructure(structureId);
|
|
42519
|
+
if (!structure || structure.pullRequestId !== pullRequestId) {
|
|
42520
|
+
throw new RvwError("NOT_FOUND", "Structure\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002", { status: 404 });
|
|
42521
|
+
}
|
|
42522
|
+
return structure;
|
|
42523
|
+
}
|
|
42524
|
+
getStructureByUri(uri) {
|
|
42525
|
+
const structure = this.database.getStructure(parseStructureUri(uri));
|
|
42526
|
+
if (!structure) {
|
|
42527
|
+
throw new RvwError("NOT_FOUND", "Structure\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002", { status: 404 });
|
|
42528
|
+
}
|
|
42529
|
+
return {
|
|
42530
|
+
pullRequest: this.getPullRequest(structure.pullRequestId),
|
|
42531
|
+
structure
|
|
42532
|
+
};
|
|
42533
|
+
}
|
|
42534
|
+
async validateSourceAnchor(pullRequest, sourceOid, anchor, subject, documents) {
|
|
42535
|
+
assertCodeReferencePath(anchor.path);
|
|
42536
|
+
const startLine = anchor.startLine ?? null;
|
|
42537
|
+
const endLine = anchor.endLine ?? null;
|
|
42538
|
+
assertLinePair(startLine, endLine);
|
|
42539
|
+
let contentPromise = documents.get(anchor.path);
|
|
42540
|
+
if (!contentPromise) {
|
|
42541
|
+
contentPromise = this.getDocument({
|
|
42542
|
+
kind: "repository-file",
|
|
42543
|
+
pullRequestId: pullRequest.id,
|
|
42544
|
+
sourceOid,
|
|
42545
|
+
path: anchor.path
|
|
42546
|
+
});
|
|
42547
|
+
documents.set(anchor.path, contentPromise);
|
|
42548
|
+
}
|
|
42549
|
+
const content3 = await contentPromise;
|
|
42550
|
+
if (content3.availability !== "available") {
|
|
42551
|
+
throw new RvwError("INVALID_INPUT", `${subject}\u306Esource\u3092\u8868\u793A\u3067\u304D\u307E\u305B\u3093: ${anchor.path}`);
|
|
42552
|
+
}
|
|
42553
|
+
this.validateLineRange(content3.text ?? "", startLine, endLine, subject);
|
|
42554
|
+
return { path: anchor.path, startLine, endLine };
|
|
42555
|
+
}
|
|
42556
|
+
assertStructureText(value, maximum, subject) {
|
|
42557
|
+
const normalized = value.trim();
|
|
42558
|
+
if (normalized.length === 0 || value.length > maximum) {
|
|
42559
|
+
throw new RvwError("INVALID_INPUT", `${subject}\u306F1\u301C${maximum}\u6587\u5B57\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`);
|
|
42560
|
+
}
|
|
42561
|
+
return normalized;
|
|
42562
|
+
}
|
|
42563
|
+
assertStructureId(value, subject) {
|
|
42564
|
+
if (!STRUCTURE_ID_PATTERN.test(value)) {
|
|
42565
|
+
throw new RvwError(
|
|
42566
|
+
"INVALID_INPUT",
|
|
42567
|
+
`${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`
|
|
42568
|
+
);
|
|
42569
|
+
}
|
|
42570
|
+
return value;
|
|
42571
|
+
}
|
|
42572
|
+
normalizeOptionalStructureText(value, maximum, subject) {
|
|
42573
|
+
if (value === null || value === void 0) return null;
|
|
42574
|
+
if (value.length > maximum) {
|
|
42575
|
+
throw new RvwError("INVALID_INPUT", `${subject}\u304C\u9577\u3059\u304E\u307E\u3059\u3002`);
|
|
42576
|
+
}
|
|
42577
|
+
return value.trim() || null;
|
|
42578
|
+
}
|
|
42579
|
+
async validateStructureContent(pullRequest, input) {
|
|
42580
|
+
await this.assertCommitAvailable(pullRequest, input.sourceOid);
|
|
42581
|
+
const title = this.assertStructureText(
|
|
42582
|
+
input.title,
|
|
42583
|
+
MAX_STRUCTURE_TITLE_CHARACTERS,
|
|
42584
|
+
"Structure title"
|
|
42585
|
+
);
|
|
42586
|
+
const scope = this.assertStructureText(
|
|
42587
|
+
input.scope,
|
|
42588
|
+
MAX_STRUCTURE_SCOPE_CHARACTERS,
|
|
42589
|
+
"Structure scope"
|
|
42590
|
+
);
|
|
42591
|
+
if (input.nodes.length < 1 || input.nodes.length > MAX_STRUCTURE_NODES) {
|
|
42592
|
+
throw new RvwError(
|
|
42593
|
+
"INVALID_INPUT",
|
|
42594
|
+
`Structure Node\u306F1\u301C${MAX_STRUCTURE_NODES}\u4EF6\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
42595
|
+
);
|
|
42596
|
+
}
|
|
42597
|
+
if (input.edges.length > MAX_STRUCTURE_EDGES) {
|
|
42598
|
+
throw new RvwError(
|
|
42599
|
+
"INVALID_INPUT",
|
|
42600
|
+
`Structure Edge\u306F${MAX_STRUCTURE_EDGES}\u4EF6\u4EE5\u4E0B\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
42601
|
+
);
|
|
42602
|
+
}
|
|
42603
|
+
const documents = /* @__PURE__ */ new Map();
|
|
42604
|
+
const nodeIds = /* @__PURE__ */ new Set();
|
|
42605
|
+
const nodes = [];
|
|
42606
|
+
for (const node2 of input.nodes) {
|
|
42607
|
+
const id = this.assertStructureId(node2.id, "Structure Node ID");
|
|
42608
|
+
if (nodeIds.has(id)) {
|
|
42609
|
+
throw new RvwError("INVALID_INPUT", `Structure Node ID\u304C\u91CD\u8907\u3057\u3066\u3044\u307E\u3059: ${id}`);
|
|
42610
|
+
}
|
|
42611
|
+
nodeIds.add(id);
|
|
42612
|
+
const label = this.assertStructureText(
|
|
42613
|
+
node2.label,
|
|
42614
|
+
MAX_STRUCTURE_LABEL_CHARACTERS,
|
|
42615
|
+
`Structure Node ${id} label`
|
|
42616
|
+
);
|
|
42617
|
+
const notation = node2.notation ?? "plain";
|
|
42618
|
+
if (!STRUCTURE_NODE_NOTATIONS.includes(notation)) {
|
|
42619
|
+
throw new RvwError("INVALID_INPUT", `Structure Node ${id} notation\u304C\u4E0D\u6B63\u3067\u3059\u3002`);
|
|
42620
|
+
}
|
|
42621
|
+
nodes.push({
|
|
42622
|
+
id,
|
|
42623
|
+
label,
|
|
42624
|
+
description: this.normalizeOptionalStructureText(
|
|
42625
|
+
node2.description,
|
|
42626
|
+
MAX_STRUCTURE_DESCRIPTION_CHARACTERS,
|
|
42627
|
+
`Structure Node ${id} description`
|
|
42628
|
+
),
|
|
42629
|
+
kind: this.normalizeOptionalStructureText(
|
|
42630
|
+
node2.kind,
|
|
42631
|
+
MAX_STRUCTURE_KIND_CHARACTERS,
|
|
42632
|
+
`Structure Node ${id} kind`
|
|
42633
|
+
),
|
|
42634
|
+
notation,
|
|
42635
|
+
anchor: node2.anchor ? await this.validateSourceAnchor(
|
|
42636
|
+
pullRequest,
|
|
42637
|
+
input.sourceOid,
|
|
42638
|
+
node2.anchor,
|
|
42639
|
+
`Structure Node ${id}`,
|
|
42640
|
+
documents
|
|
42641
|
+
) : null
|
|
42642
|
+
});
|
|
42643
|
+
}
|
|
42644
|
+
const edgeIds = /* @__PURE__ */ new Set();
|
|
42645
|
+
const edges = [];
|
|
42646
|
+
for (const edge of input.edges) {
|
|
42647
|
+
const id = this.assertStructureId(edge.id, "Structure Edge ID");
|
|
42648
|
+
if (edgeIds.has(id)) {
|
|
42649
|
+
throw new RvwError("INVALID_INPUT", `Structure Edge ID\u304C\u91CD\u8907\u3057\u3066\u3044\u307E\u3059: ${id}`);
|
|
42650
|
+
}
|
|
42651
|
+
edgeIds.add(id);
|
|
42652
|
+
if (!nodeIds.has(edge.from) || !nodeIds.has(edge.to)) {
|
|
42653
|
+
throw new RvwError(
|
|
42654
|
+
"INVALID_INPUT",
|
|
42655
|
+
`Structure Edge ${id} \u306Eendpoint\u304C\u5B58\u5728\u3057\u307E\u305B\u3093: ${edge.from} \u2192 ${edge.to}`
|
|
42656
|
+
);
|
|
42657
|
+
}
|
|
42658
|
+
if (typeof edge.directed !== "boolean") {
|
|
42659
|
+
throw new RvwError("INVALID_INPUT", `Structure Edge ${id} \u306Edirected\u304C\u5FC5\u8981\u3067\u3059\u3002`);
|
|
42660
|
+
}
|
|
42661
|
+
const anchors = edge.anchors ?? [];
|
|
42662
|
+
if (anchors.length > MAX_STRUCTURE_EDGE_ANCHORS) {
|
|
42663
|
+
throw new RvwError(
|
|
42664
|
+
"INVALID_INPUT",
|
|
42665
|
+
`Structure Edge ${id} \u306Eanchor\u306F${MAX_STRUCTURE_EDGE_ANCHORS}\u4EF6\u4EE5\u4E0B\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
42666
|
+
);
|
|
42667
|
+
}
|
|
42668
|
+
edges.push({
|
|
42669
|
+
id,
|
|
42670
|
+
from: edge.from,
|
|
42671
|
+
to: edge.to,
|
|
42672
|
+
label: this.assertStructureText(
|
|
42673
|
+
edge.label,
|
|
42674
|
+
MAX_STRUCTURE_LABEL_CHARACTERS,
|
|
42675
|
+
`Structure Edge ${id} label`
|
|
42676
|
+
),
|
|
42677
|
+
directed: edge.directed,
|
|
42678
|
+
anchors: await Promise.all(
|
|
42679
|
+
anchors.map(
|
|
42680
|
+
(anchor, index2) => this.validateSourceAnchor(
|
|
42681
|
+
pullRequest,
|
|
42682
|
+
input.sourceOid,
|
|
42683
|
+
anchor,
|
|
42684
|
+
`Structure Edge ${id} anchor ${index2 + 1}`,
|
|
42685
|
+
documents
|
|
42686
|
+
)
|
|
42687
|
+
)
|
|
42688
|
+
)
|
|
42689
|
+
});
|
|
42690
|
+
}
|
|
42691
|
+
if (typeof input.originNodeId !== "string") {
|
|
42692
|
+
throw new RvwError("INVALID_INPUT", "originNodeId\u304C\u5FC5\u8981\u3067\u3059\u3002");
|
|
42693
|
+
}
|
|
42694
|
+
const originNodeId = this.assertStructureId(input.originNodeId, "Structure originNodeId");
|
|
42695
|
+
if (!nodeIds.has(originNodeId)) {
|
|
42696
|
+
throw new RvwError("INVALID_INPUT", `originNodeId Node\u304C\u5B58\u5728\u3057\u307E\u305B\u3093: ${originNodeId}`);
|
|
42697
|
+
}
|
|
42698
|
+
const originNode = nodes.find((node2) => node2.id === originNodeId);
|
|
42699
|
+
if (originNode.anchor === null) {
|
|
42700
|
+
throw new RvwError("INVALID_INPUT", "Structure origin Node\u306B\u306Fsource anchor\u304C\u5FC5\u8981\u3067\u3059\u3002");
|
|
42701
|
+
}
|
|
42702
|
+
const neighbors = new Map(nodes.map((node2) => [node2.id, /* @__PURE__ */ new Set()]));
|
|
42703
|
+
for (const edge of edges) {
|
|
42704
|
+
neighbors.get(edge.from).add(edge.to);
|
|
42705
|
+
neighbors.get(edge.to).add(edge.from);
|
|
42706
|
+
}
|
|
42707
|
+
const reached = /* @__PURE__ */ new Set([originNodeId]);
|
|
42708
|
+
const queue = [originNodeId];
|
|
42709
|
+
while (queue.length > 0) {
|
|
42710
|
+
const current = queue.shift();
|
|
42711
|
+
for (const neighbor of neighbors.get(current) ?? []) {
|
|
42712
|
+
if (reached.has(neighbor)) continue;
|
|
42713
|
+
reached.add(neighbor);
|
|
42714
|
+
queue.push(neighbor);
|
|
42715
|
+
}
|
|
42716
|
+
}
|
|
42717
|
+
const disconnected = nodes.filter((node2) => !reached.has(node2.id)).map((node2) => node2.id);
|
|
42718
|
+
if (disconnected.length > 0) {
|
|
42719
|
+
throw new RvwError(
|
|
42720
|
+
"INVALID_INPUT",
|
|
42721
|
+
`Structure\u306E\u5168Node\u3092origin\u304B\u3089\u8FBF\u308C\u308B\u95A2\u4FC2graph\u306B\u3057\u3066\u304F\u3060\u3055\u3044: ${disconnected.join(", ")}`
|
|
42722
|
+
);
|
|
42723
|
+
}
|
|
42724
|
+
const anchorCount = nodes.filter((node2) => node2.anchor !== null).length + edges.reduce((count, edge) => count + edge.anchors.length, 0);
|
|
42725
|
+
if (anchorCount < 1) {
|
|
42726
|
+
throw new RvwError(
|
|
42727
|
+
"INVALID_INPUT",
|
|
42728
|
+
"Structure\u306B\u306Fsource anchor\u3092\u5C11\u306A\u304F\u3068\u30821\u4EF6\u542B\u3081\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
42729
|
+
);
|
|
42730
|
+
}
|
|
42731
|
+
if (anchorCount > MAX_STRUCTURE_SOURCE_ANCHORS) {
|
|
42732
|
+
throw new RvwError(
|
|
42733
|
+
"INVALID_INPUT",
|
|
42734
|
+
`Structure\u306Esource anchor\u306F\u5408\u8A08${MAX_STRUCTURE_SOURCE_ANCHORS}\u4EF6\u4EE5\u4E0B\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
42735
|
+
);
|
|
42736
|
+
}
|
|
42737
|
+
const graph = { originNodeId, nodes, edges };
|
|
42738
|
+
if (Buffer.byteLength(JSON.stringify(graph), "utf8") > MAX_STRUCTURE_PAYLOAD_BYTES) {
|
|
42739
|
+
throw new RvwError(
|
|
42740
|
+
"INVALID_INPUT",
|
|
42741
|
+
`Structure payload\u306F${MAX_STRUCTURE_PAYLOAD_BYTES} UTF-8 bytes\u4EE5\u4E0B\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
42742
|
+
);
|
|
42743
|
+
}
|
|
42744
|
+
return { sourceOid: input.sourceOid, title, scope, ...graph };
|
|
42745
|
+
}
|
|
42746
|
+
async publishStructure(input) {
|
|
42747
|
+
if (typeof input.idempotencyKey !== "string") {
|
|
42748
|
+
throw new RvwError("INVALID_INPUT", "idempotencyKey\u304C\u5FC5\u8981\u3067\u3059\u3002");
|
|
42749
|
+
}
|
|
42750
|
+
assertIdempotencyKey(input.idempotencyKey);
|
|
42751
|
+
const pullRequest = this.resolveStoredPullRequest(input.pullRequest);
|
|
42752
|
+
const content3 = await this.validateStructureContent(pullRequest, input);
|
|
42753
|
+
return await this.writeWithRetainedCommit(
|
|
42754
|
+
pullRequest,
|
|
42755
|
+
content3.sourceOid,
|
|
42756
|
+
"Structure",
|
|
42757
|
+
() => this.database.createStructure({
|
|
42758
|
+
pullRequestId: pullRequest.id,
|
|
42759
|
+
...content3,
|
|
42760
|
+
idempotencyKey: input.idempotencyKey,
|
|
42761
|
+
idempotencyRequestHash: idempotencyRequestHash({
|
|
42762
|
+
operation: "structure.publish",
|
|
42763
|
+
pullRequestId: pullRequest.id,
|
|
42764
|
+
content: content3
|
|
42765
|
+
})
|
|
42766
|
+
})
|
|
42767
|
+
);
|
|
42768
|
+
}
|
|
42769
|
+
async updateStructure(uri, input) {
|
|
42770
|
+
const { pullRequest, structure } = this.getStructureByUri(uri);
|
|
42771
|
+
if (typeof input.expectedUpdatedAt !== "string" || input.expectedUpdatedAt.length === 0) {
|
|
42772
|
+
throw new RvwError("INVALID_INPUT", "expectedUpdatedAt\u304C\u5FC5\u8981\u3067\u3059\u3002");
|
|
42773
|
+
}
|
|
42774
|
+
const content3 = await this.validateStructureContent(pullRequest, input);
|
|
42775
|
+
return await this.writeWithRetainedCommit(
|
|
42776
|
+
pullRequest,
|
|
42777
|
+
content3.sourceOid,
|
|
42778
|
+
"Structure",
|
|
42779
|
+
() => this.database.updateStructure(structure.id, input.expectedUpdatedAt, content3)
|
|
42780
|
+
);
|
|
42781
|
+
}
|
|
42782
|
+
getStructureDeletePreview(uri) {
|
|
42783
|
+
const { structure } = this.getStructureByUri(uri);
|
|
42784
|
+
return {
|
|
42785
|
+
structure,
|
|
42786
|
+
counts: this.database.getStructureDeleteCounts(structure.id),
|
|
42787
|
+
confirmationRequired: true
|
|
42788
|
+
};
|
|
42789
|
+
}
|
|
42790
|
+
deleteStructureByUri(uri, expectedUpdatedAt2) {
|
|
42791
|
+
const { structure } = this.getStructureByUri(uri);
|
|
42792
|
+
return this.database.deleteStructure(structure.id, expectedUpdatedAt2);
|
|
42793
|
+
}
|
|
42794
|
+
deleteStructure(pullRequestId, structureId, expectedUpdatedAt2) {
|
|
42795
|
+
this.getStructure(pullRequestId, structureId);
|
|
42796
|
+
return this.database.deleteStructure(structureId, expectedUpdatedAt2);
|
|
42797
|
+
}
|
|
42197
42798
|
getWalkthrough(pullRequestId, walkthroughId) {
|
|
42198
42799
|
this.getPullRequest(pullRequestId);
|
|
42199
42800
|
const walkthrough = this.database.getWalkthrough(walkthroughId);
|
|
@@ -42202,7 +42803,7 @@ var RvwService = class {
|
|
|
42202
42803
|
}
|
|
42203
42804
|
return walkthrough;
|
|
42204
42805
|
}
|
|
42205
|
-
async
|
|
42806
|
+
async sourceReferenceFallbackTarget(pullRequest, sourceOid, filePath) {
|
|
42206
42807
|
const diffBaseOid = await this.git.firstParent(pullRequest.localRepositoryPath, sourceOid);
|
|
42207
42808
|
if (!diffBaseOid) {
|
|
42208
42809
|
return {
|
|
@@ -42233,22 +42834,47 @@ var RvwService = class {
|
|
|
42233
42834
|
status: 404
|
|
42234
42835
|
});
|
|
42235
42836
|
}
|
|
42236
|
-
const referenceFingerprint =
|
|
42837
|
+
const referenceFingerprint = sourceAnchorFingerprint(walkthrough.sourceOid, reference);
|
|
42838
|
+
return await this.resolveSourceAnchor(
|
|
42839
|
+
pullRequest,
|
|
42840
|
+
walkthrough.sourceOid,
|
|
42841
|
+
reference,
|
|
42842
|
+
referenceFingerprint
|
|
42843
|
+
);
|
|
42844
|
+
}
|
|
42845
|
+
async resolveStructureSource(pullRequestId, structureId, locator) {
|
|
42846
|
+
const pullRequest = this.getPullRequest(pullRequestId);
|
|
42847
|
+
const structure = this.getStructure(pullRequestId, structureId);
|
|
42848
|
+
const anchor = structureSourceAnchor(structure, locator);
|
|
42849
|
+
if (!anchor) {
|
|
42850
|
+
throw new RvwError("NOT_FOUND", "Structure\u306E\u53C2\u7167\u5143claim\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002", {
|
|
42851
|
+
status: 404
|
|
42852
|
+
});
|
|
42853
|
+
}
|
|
42854
|
+
const resolution = await this.resolveSourceAnchor(
|
|
42855
|
+
pullRequest,
|
|
42856
|
+
structure.sourceOid,
|
|
42857
|
+
anchor,
|
|
42858
|
+
sourceAnchorFingerprint(structure.sourceOid, anchor)
|
|
42859
|
+
);
|
|
42860
|
+
return { ...resolution, resolvedAnchor: anchor };
|
|
42861
|
+
}
|
|
42862
|
+
async resolveSourceAnchor(pullRequest, sourceOid, reference, referenceFingerprint) {
|
|
42237
42863
|
const sourceDocument = await this.getDocument({
|
|
42238
42864
|
kind: "repository-file",
|
|
42239
|
-
pullRequestId,
|
|
42240
|
-
sourceOid
|
|
42865
|
+
pullRequestId: pullRequest.id,
|
|
42866
|
+
sourceOid,
|
|
42241
42867
|
path: reference.path
|
|
42242
42868
|
});
|
|
42243
42869
|
const latestHeadOid = pullRequest.latestHeadOid;
|
|
42244
42870
|
let latestPath = reference.path;
|
|
42245
42871
|
let latestDocument;
|
|
42246
|
-
if (
|
|
42872
|
+
if (sourceOid === latestHeadOid) {
|
|
42247
42873
|
latestDocument = sourceDocument;
|
|
42248
42874
|
} else {
|
|
42249
42875
|
latestDocument = await this.getDocument({
|
|
42250
42876
|
kind: "repository-file",
|
|
42251
|
-
pullRequestId,
|
|
42877
|
+
pullRequestId: pullRequest.id,
|
|
42252
42878
|
sourceOid: latestHeadOid,
|
|
42253
42879
|
path: reference.path
|
|
42254
42880
|
});
|
|
@@ -42257,7 +42883,7 @@ var RvwService = class {
|
|
|
42257
42883
|
...new Set(
|
|
42258
42884
|
(await this.git.changedFilesWithCopies(
|
|
42259
42885
|
pullRequest.localRepositoryPath,
|
|
42260
|
-
|
|
42886
|
+
sourceOid,
|
|
42261
42887
|
latestHeadOid
|
|
42262
42888
|
)).filter(
|
|
42263
42889
|
(candidate) => (candidate.status.startsWith("R") || candidate.status.startsWith("C")) && candidate.oldPath === reference.path && candidate.newPath !== null
|
|
@@ -42267,7 +42893,7 @@ var RvwService = class {
|
|
|
42267
42893
|
latestPath = successorPaths.length === 1 ? successorPaths[0] : null;
|
|
42268
42894
|
latestDocument = latestPath === null ? null : await this.getDocument({
|
|
42269
42895
|
kind: "repository-file",
|
|
42270
|
-
pullRequestId,
|
|
42896
|
+
pullRequestId: pullRequest.id,
|
|
42271
42897
|
sourceOid: latestHeadOid,
|
|
42272
42898
|
path: latestPath
|
|
42273
42899
|
});
|
|
@@ -42285,7 +42911,7 @@ var RvwService = class {
|
|
|
42285
42911
|
if (resolvedToLatest && latestPath !== null && latestDocument !== null) {
|
|
42286
42912
|
return {
|
|
42287
42913
|
outcome: "latest",
|
|
42288
|
-
anchorSourceOid:
|
|
42914
|
+
anchorSourceOid: sourceOid,
|
|
42289
42915
|
latestHeadOid,
|
|
42290
42916
|
referenceFingerprint,
|
|
42291
42917
|
target: {
|
|
@@ -42302,9 +42928,9 @@ var RvwService = class {
|
|
|
42302
42928
|
document: latestDocument
|
|
42303
42929
|
};
|
|
42304
42930
|
}
|
|
42305
|
-
const targetFile = await this.
|
|
42931
|
+
const targetFile = await this.sourceReferenceFallbackTarget(
|
|
42306
42932
|
pullRequest,
|
|
42307
|
-
|
|
42933
|
+
sourceOid,
|
|
42308
42934
|
reference.path
|
|
42309
42935
|
);
|
|
42310
42936
|
const latestFile = latestFileExists && latestPath !== null ? {
|
|
@@ -42317,7 +42943,7 @@ var RvwService = class {
|
|
|
42317
42943
|
} : null;
|
|
42318
42944
|
return {
|
|
42319
42945
|
outcome: "source-fallback",
|
|
42320
|
-
anchorSourceOid:
|
|
42946
|
+
anchorSourceOid: sourceOid,
|
|
42321
42947
|
latestHeadOid,
|
|
42322
42948
|
referenceFingerprint,
|
|
42323
42949
|
target: {
|
|
@@ -42768,6 +43394,7 @@ import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
|
42768
43394
|
var skillNames = [
|
|
42769
43395
|
"rvw",
|
|
42770
43396
|
"rvw-walkthrough",
|
|
43397
|
+
"rvw-structure",
|
|
42771
43398
|
"rvw-watch-comments"
|
|
42772
43399
|
];
|
|
42773
43400
|
var INSTALL_METADATA_FILE = ".rvw-install.json";
|
|
@@ -46585,8 +47212,11 @@ var Hono2 = class extends Hono {
|
|
|
46585
47212
|
var nonEmptyString = external_exports.string().min(1);
|
|
46586
47213
|
var commentUri = external_exports.string().regex(/^rvw:\/\/comment\//);
|
|
46587
47214
|
var walkthroughUri = external_exports.string().regex(/^rvw:\/\/walkthrough\//);
|
|
47215
|
+
var structureUri = external_exports.string().regex(/^rvw:\/\/structure\//);
|
|
46588
47216
|
var nullableCommentLine = external_exports.number().int().positive().nullable().optional().default(null);
|
|
46589
47217
|
var idempotencyKey = external_exports.string().min(1).max(MAX_IDEMPOTENCY_KEY_CHARACTERS).optional();
|
|
47218
|
+
var requiredIdempotencyKey = external_exports.string().min(1).max(MAX_IDEMPOTENCY_KEY_CHARACTERS);
|
|
47219
|
+
var expectedUpdatedAt = external_exports.string().min(1).max(100);
|
|
46590
47220
|
var commentTargetInputSchema = external_exports.union([
|
|
46591
47221
|
external_exports.object({ kind: external_exports.literal("pull-request") }).strict(),
|
|
46592
47222
|
external_exports.object({
|
|
@@ -46709,6 +47339,151 @@ var walkthroughPublishInputSchema = walkthroughContentInputSchema.extend({
|
|
|
46709
47339
|
pullRequest: nonEmptyString
|
|
46710
47340
|
});
|
|
46711
47341
|
var walkthroughUpdateInputSchema = walkthroughContentInputSchema;
|
|
47342
|
+
var sourceAnchorInputSchema = external_exports.object({
|
|
47343
|
+
path: external_exports.string().min(1).max(MAX_CODE_REFERENCE_PATH_CHARACTERS),
|
|
47344
|
+
startLine: external_exports.number().int().positive().nullable().optional().default(null),
|
|
47345
|
+
endLine: external_exports.number().int().positive().nullable().optional().default(null)
|
|
47346
|
+
}).strict().superRefine((anchor, context) => {
|
|
47347
|
+
if (anchor.startLine === null !== (anchor.endLine === null)) {
|
|
47348
|
+
context.addIssue({
|
|
47349
|
+
code: "custom",
|
|
47350
|
+
message: "startLine\u3068endLine\u306F\u4E21\u65B9\u6307\u5B9A\u3059\u308B\u304B\u3001\u4E21\u65B9\u7701\u7565\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
47351
|
+
});
|
|
47352
|
+
return;
|
|
47353
|
+
}
|
|
47354
|
+
if (anchor.startLine !== null && anchor.endLine !== null && anchor.endLine < anchor.startLine) {
|
|
47355
|
+
context.addIssue({ code: "custom", message: "endLine\u306FstartLine\u4EE5\u4E0A\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002" });
|
|
47356
|
+
}
|
|
47357
|
+
});
|
|
47358
|
+
var structureNodeInputSchema = external_exports.object({
|
|
47359
|
+
id: external_exports.string().max(MAX_STRUCTURE_ID_CHARACTERS).regex(STRUCTURE_ID_PATTERN),
|
|
47360
|
+
label: external_exports.string().min(1).max(MAX_STRUCTURE_LABEL_CHARACTERS),
|
|
47361
|
+
description: external_exports.string().max(MAX_STRUCTURE_DESCRIPTION_CHARACTERS).nullable().optional().default(null),
|
|
47362
|
+
kind: external_exports.string().max(MAX_STRUCTURE_KIND_CHARACTERS).nullable().optional().default(null),
|
|
47363
|
+
notation: external_exports.enum(STRUCTURE_NODE_NOTATIONS).optional().default("plain"),
|
|
47364
|
+
anchor: sourceAnchorInputSchema.nullable().optional().default(null)
|
|
47365
|
+
}).strict();
|
|
47366
|
+
var structureEdgeInputSchema = external_exports.object({
|
|
47367
|
+
id: external_exports.string().max(MAX_STRUCTURE_ID_CHARACTERS).regex(STRUCTURE_ID_PATTERN),
|
|
47368
|
+
from: external_exports.string().max(MAX_STRUCTURE_ID_CHARACTERS).regex(STRUCTURE_ID_PATTERN),
|
|
47369
|
+
to: external_exports.string().max(MAX_STRUCTURE_ID_CHARACTERS).regex(STRUCTURE_ID_PATTERN),
|
|
47370
|
+
label: external_exports.string().min(1).max(MAX_STRUCTURE_LABEL_CHARACTERS),
|
|
47371
|
+
directed: external_exports.boolean(),
|
|
47372
|
+
anchors: external_exports.array(sourceAnchorInputSchema).max(MAX_STRUCTURE_EDGE_ANCHORS).optional().default([])
|
|
47373
|
+
}).strict();
|
|
47374
|
+
var structureContentShape = {
|
|
47375
|
+
sourceOid: external_exports.string().regex(GIT_OBJECT_ID_PATTERN),
|
|
47376
|
+
title: external_exports.string().min(1).max(MAX_STRUCTURE_TITLE_CHARACTERS),
|
|
47377
|
+
scope: external_exports.string().min(1).max(MAX_STRUCTURE_SCOPE_CHARACTERS),
|
|
47378
|
+
originNodeId: external_exports.string().max(MAX_STRUCTURE_ID_CHARACTERS).regex(STRUCTURE_ID_PATTERN),
|
|
47379
|
+
nodes: external_exports.array(structureNodeInputSchema).min(1).max(MAX_STRUCTURE_NODES),
|
|
47380
|
+
edges: external_exports.array(structureEdgeInputSchema).max(MAX_STRUCTURE_EDGES)
|
|
47381
|
+
};
|
|
47382
|
+
function refineStructureContent(value, context) {
|
|
47383
|
+
const nodeIds = /* @__PURE__ */ new Set();
|
|
47384
|
+
for (const [index2, node2] of value.nodes.entries()) {
|
|
47385
|
+
if (nodeIds.has(node2.id)) {
|
|
47386
|
+
context.addIssue({
|
|
47387
|
+
code: "custom",
|
|
47388
|
+
path: ["nodes", index2, "id"],
|
|
47389
|
+
message: "Node ID\u304C\u91CD\u8907\u3057\u3066\u3044\u307E\u3059\u3002"
|
|
47390
|
+
});
|
|
47391
|
+
}
|
|
47392
|
+
nodeIds.add(node2.id);
|
|
47393
|
+
}
|
|
47394
|
+
const edgeIds = /* @__PURE__ */ new Set();
|
|
47395
|
+
for (const [index2, edge] of value.edges.entries()) {
|
|
47396
|
+
if (edgeIds.has(edge.id)) {
|
|
47397
|
+
context.addIssue({
|
|
47398
|
+
code: "custom",
|
|
47399
|
+
path: ["edges", index2, "id"],
|
|
47400
|
+
message: "Edge ID\u304C\u91CD\u8907\u3057\u3066\u3044\u307E\u3059\u3002"
|
|
47401
|
+
});
|
|
47402
|
+
}
|
|
47403
|
+
edgeIds.add(edge.id);
|
|
47404
|
+
if (!nodeIds.has(edge.from)) {
|
|
47405
|
+
context.addIssue({
|
|
47406
|
+
code: "custom",
|
|
47407
|
+
path: ["edges", index2, "from"],
|
|
47408
|
+
message: "Edge\u306Efrom Node\u304C\u5B58\u5728\u3057\u307E\u305B\u3093\u3002"
|
|
47409
|
+
});
|
|
47410
|
+
}
|
|
47411
|
+
if (!nodeIds.has(edge.to)) {
|
|
47412
|
+
context.addIssue({
|
|
47413
|
+
code: "custom",
|
|
47414
|
+
path: ["edges", index2, "to"],
|
|
47415
|
+
message: "Edge\u306Eto Node\u304C\u5B58\u5728\u3057\u307E\u305B\u3093\u3002"
|
|
47416
|
+
});
|
|
47417
|
+
}
|
|
47418
|
+
}
|
|
47419
|
+
const originIndex = value.nodes.findIndex((node2) => node2.id === value.originNodeId);
|
|
47420
|
+
if (originIndex === -1) {
|
|
47421
|
+
context.addIssue({
|
|
47422
|
+
code: "custom",
|
|
47423
|
+
path: ["originNodeId"],
|
|
47424
|
+
message: "originNodeId Node\u304C\u5B58\u5728\u3057\u307E\u305B\u3093\u3002"
|
|
47425
|
+
});
|
|
47426
|
+
} else if (value.nodes[originIndex]?.anchor === null) {
|
|
47427
|
+
context.addIssue({
|
|
47428
|
+
code: "custom",
|
|
47429
|
+
path: ["nodes", originIndex, "anchor"],
|
|
47430
|
+
message: "origin Node\u306B\u306Fsource anchor\u304C\u5FC5\u8981\u3067\u3059\u3002"
|
|
47431
|
+
});
|
|
47432
|
+
}
|
|
47433
|
+
if (originIndex !== -1) {
|
|
47434
|
+
const neighbors = new Map(value.nodes.map((node2) => [node2.id, /* @__PURE__ */ new Set()]));
|
|
47435
|
+
for (const edge of value.edges) {
|
|
47436
|
+
if (!neighbors.has(edge.from) || !neighbors.has(edge.to)) continue;
|
|
47437
|
+
neighbors.get(edge.from).add(edge.to);
|
|
47438
|
+
neighbors.get(edge.to).add(edge.from);
|
|
47439
|
+
}
|
|
47440
|
+
const reached = /* @__PURE__ */ new Set([value.originNodeId]);
|
|
47441
|
+
const queue = [value.originNodeId];
|
|
47442
|
+
while (queue.length > 0) {
|
|
47443
|
+
const current = queue.shift();
|
|
47444
|
+
for (const neighbor of neighbors.get(current) ?? []) {
|
|
47445
|
+
if (reached.has(neighbor)) continue;
|
|
47446
|
+
reached.add(neighbor);
|
|
47447
|
+
queue.push(neighbor);
|
|
47448
|
+
}
|
|
47449
|
+
}
|
|
47450
|
+
const disconnected = value.nodes.filter((node2) => !reached.has(node2.id)).map((node2) => node2.id);
|
|
47451
|
+
if (disconnected.length > 0) {
|
|
47452
|
+
context.addIssue({
|
|
47453
|
+
code: "custom",
|
|
47454
|
+
path: ["nodes"],
|
|
47455
|
+
message: `\u5168Node\u3092origin\u304B\u3089\u8FBF\u308C\u308B\u95A2\u4FC2graph\u306B\u3057\u3066\u304F\u3060\u3055\u3044: ${disconnected.join(", ")}`
|
|
47456
|
+
});
|
|
47457
|
+
}
|
|
47458
|
+
}
|
|
47459
|
+
const anchorCount = value.nodes.filter((node2) => node2.anchor !== null).length + value.edges.reduce((count, edge) => count + edge.anchors.length, 0);
|
|
47460
|
+
if (anchorCount < 1) {
|
|
47461
|
+
context.addIssue({
|
|
47462
|
+
code: "custom",
|
|
47463
|
+
message: "Structure\u306B\u306Fsource anchor\u3092\u5C11\u306A\u304F\u3068\u30821\u4EF6\u542B\u3081\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
47464
|
+
});
|
|
47465
|
+
}
|
|
47466
|
+
if (anchorCount > MAX_STRUCTURE_SOURCE_ANCHORS) {
|
|
47467
|
+
context.addIssue({
|
|
47468
|
+
code: "custom",
|
|
47469
|
+
message: `Structure\u306Esource anchor\u306F\u5408\u8A08${MAX_STRUCTURE_SOURCE_ANCHORS}\u4EF6\u4EE5\u4E0B\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
47470
|
+
});
|
|
47471
|
+
}
|
|
47472
|
+
const graph = { originNodeId: value.originNodeId, nodes: value.nodes, edges: value.edges };
|
|
47473
|
+
if (Buffer.byteLength(JSON.stringify(graph), "utf8") > MAX_STRUCTURE_PAYLOAD_BYTES) {
|
|
47474
|
+
context.addIssue({
|
|
47475
|
+
code: "custom",
|
|
47476
|
+
message: `Structure payload\u306F${MAX_STRUCTURE_PAYLOAD_BYTES} UTF-8 bytes\u4EE5\u4E0B\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
47477
|
+
});
|
|
47478
|
+
}
|
|
47479
|
+
}
|
|
47480
|
+
var structureContentInputSchema = external_exports.object(structureContentShape).strict().superRefine(refineStructureContent);
|
|
47481
|
+
var structureUpdateInputSchema = external_exports.object({ expectedUpdatedAt, ...structureContentShape }).strict().superRefine(refineStructureContent);
|
|
47482
|
+
var structurePublishInputSchema = external_exports.object({
|
|
47483
|
+
pullRequest: nonEmptyString,
|
|
47484
|
+
idempotencyKey: requiredIdempotencyKey,
|
|
47485
|
+
...structureContentShape
|
|
47486
|
+
}).strict().superRefine(refineStructureContent);
|
|
46712
47487
|
var agentCommandInputSchemas = {
|
|
46713
47488
|
doctor: external_exports.object({ cwd: nonEmptyString }).strict(),
|
|
46714
47489
|
"pr.refresh": external_exports.object({ reference: nonEmptyString }).strict(),
|
|
@@ -46739,7 +47514,13 @@ var agentCommandInputSchemas = {
|
|
|
46739
47514
|
"walkthrough.publish": walkthroughPublishInputSchema,
|
|
46740
47515
|
"walkthrough.update": external_exports.object({ uri: walkthroughUri, content: walkthroughUpdateInputSchema }).strict(),
|
|
46741
47516
|
"walkthrough.delete.preview": external_exports.object({ uri: walkthroughUri }).strict(),
|
|
46742
|
-
"walkthrough.delete": external_exports.object({ uri: walkthroughUri, confirmed: external_exports.literal(true) }).strict()
|
|
47517
|
+
"walkthrough.delete": external_exports.object({ uri: walkthroughUri, confirmed: external_exports.literal(true) }).strict(),
|
|
47518
|
+
"structure.get": external_exports.object({ uri: structureUri }).strict(),
|
|
47519
|
+
"structure.list": external_exports.object({ reference: nonEmptyString }).strict(),
|
|
47520
|
+
"structure.publish": structurePublishInputSchema,
|
|
47521
|
+
"structure.update": external_exports.object({ uri: structureUri, content: structureUpdateInputSchema }).strict(),
|
|
47522
|
+
"structure.delete.preview": external_exports.object({ uri: structureUri }).strict(),
|
|
47523
|
+
"structure.delete": external_exports.object({ uri: structureUri, expectedUpdatedAt, confirmed: external_exports.literal(true) }).strict()
|
|
46743
47524
|
};
|
|
46744
47525
|
|
|
46745
47526
|
// src/server/schemas.ts
|
|
@@ -46772,6 +47553,7 @@ var openPullRequestSchema = external_exports.object({
|
|
|
46772
47553
|
cwd: external_exports.string().min(1)
|
|
46773
47554
|
});
|
|
46774
47555
|
var resetSchema = external_exports.object({ yes: external_exports.boolean() });
|
|
47556
|
+
var structureDeleteSchema = external_exports.object({ expectedUpdatedAt: external_exports.string().min(1).max(100) });
|
|
46775
47557
|
var viewerIdSchema = external_exports.uuid();
|
|
46776
47558
|
var viewerReleaseSchema = external_exports.object({ viewerId: viewerIdSchema });
|
|
46777
47559
|
var themePreferenceSchema = external_exports.object({ themePreference: external_exports.enum(themePreferences) });
|
|
@@ -46817,6 +47599,7 @@ var editCommentPostSchema = external_exports.object({
|
|
|
46817
47599
|
|
|
46818
47600
|
// src/server/app.ts
|
|
46819
47601
|
var oidSchema = external_exports.string().regex(GIT_OBJECT_ID_PATTERN);
|
|
47602
|
+
var nonnegativeIndexSchema = external_exports.coerce.number().int().nonnegative();
|
|
46820
47603
|
var svgAssetContentSecurityPolicy = "default-src 'none'; style-src 'unsafe-inline'; base-uri 'none'; form-action 'none'; sandbox";
|
|
46821
47604
|
function requiredQuery(value, name) {
|
|
46822
47605
|
if (!value) throw new RvwError("INVALID_INPUT", `${name} query\u304C\u5FC5\u8981\u3067\u3059\u3002`);
|
|
@@ -46825,6 +47608,23 @@ function requiredQuery(value, name) {
|
|
|
46825
47608
|
function oidQuery(value, name) {
|
|
46826
47609
|
return oidSchema.parse(requiredQuery(value, name));
|
|
46827
47610
|
}
|
|
47611
|
+
function structureSourceLocator(query) {
|
|
47612
|
+
if (query.locatorKind === "node") {
|
|
47613
|
+
return { kind: "node", nodeId: requiredQuery(query.nodeId, "nodeId") };
|
|
47614
|
+
}
|
|
47615
|
+
if (query.locatorKind === "edge") {
|
|
47616
|
+
const anchorIndex = nonnegativeIndexSchema.safeParse(query.anchorIndex);
|
|
47617
|
+
if (!anchorIndex.success) {
|
|
47618
|
+
throw new RvwError("INVALID_INPUT", "anchorIndex query\u306F0\u4EE5\u4E0A\u306E\u6574\u6570\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002");
|
|
47619
|
+
}
|
|
47620
|
+
return {
|
|
47621
|
+
kind: "edge",
|
|
47622
|
+
edgeId: requiredQuery(query.edgeId, "edgeId"),
|
|
47623
|
+
anchorIndex: anchorIndex.data
|
|
47624
|
+
};
|
|
47625
|
+
}
|
|
47626
|
+
throw new RvwError("INVALID_INPUT", "locatorKind query\u306Fnode\u307E\u305F\u306Fedge\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002");
|
|
47627
|
+
}
|
|
46828
47628
|
function isWriteMethod(method) {
|
|
46829
47629
|
return method === "POST" || method === "PUT" || method === "PATCH" || method === "DELETE";
|
|
46830
47630
|
}
|
|
@@ -47109,6 +47909,46 @@ function createApp(service, options) {
|
|
|
47109
47909
|
)
|
|
47110
47910
|
})
|
|
47111
47911
|
);
|
|
47912
|
+
app.get(
|
|
47913
|
+
"/api/pull-requests/:id/structures",
|
|
47914
|
+
(context) => context.json({
|
|
47915
|
+
ok: true,
|
|
47916
|
+
structures: service.listStructures(context.req.param("id"))
|
|
47917
|
+
})
|
|
47918
|
+
);
|
|
47919
|
+
app.get(
|
|
47920
|
+
"/api/pull-requests/:id/structures/:structureId",
|
|
47921
|
+
(context) => context.json({
|
|
47922
|
+
ok: true,
|
|
47923
|
+
structure: service.getStructure(context.req.param("id"), context.req.param("structureId"))
|
|
47924
|
+
})
|
|
47925
|
+
);
|
|
47926
|
+
app.get("/api/pull-requests/:id/structures/:structureId/anchors/resolve", async (context) => {
|
|
47927
|
+
return context.json({
|
|
47928
|
+
ok: true,
|
|
47929
|
+
resolution: await service.resolveStructureSource(
|
|
47930
|
+
context.req.param("id"),
|
|
47931
|
+
context.req.param("structureId"),
|
|
47932
|
+
structureSourceLocator({
|
|
47933
|
+
locatorKind: context.req.query("locatorKind"),
|
|
47934
|
+
nodeId: context.req.query("nodeId"),
|
|
47935
|
+
edgeId: context.req.query("edgeId"),
|
|
47936
|
+
anchorIndex: context.req.query("anchorIndex")
|
|
47937
|
+
})
|
|
47938
|
+
)
|
|
47939
|
+
});
|
|
47940
|
+
});
|
|
47941
|
+
app.delete("/api/pull-requests/:id/structures/:structureId", async (context) => {
|
|
47942
|
+
const input = structureDeleteSchema.parse(await context.req.json());
|
|
47943
|
+
return context.json({
|
|
47944
|
+
ok: true,
|
|
47945
|
+
deleted: service.deleteStructure(
|
|
47946
|
+
context.req.param("id"),
|
|
47947
|
+
context.req.param("structureId"),
|
|
47948
|
+
input.expectedUpdatedAt
|
|
47949
|
+
)
|
|
47950
|
+
});
|
|
47951
|
+
});
|
|
47112
47952
|
app.post("/api/comments", async (context) => {
|
|
47113
47953
|
const input = createCommentSchema.parse(await context.req.json());
|
|
47114
47954
|
return context.json(
|
|
@@ -47690,6 +48530,30 @@ async function dispatchAgentSocketRequest(service, rawRequest) {
|
|
|
47690
48530
|
const input = parseOperationInput("walkthrough.delete", request.input);
|
|
47691
48531
|
return service.deleteWalkthroughByUri(input.uri);
|
|
47692
48532
|
}
|
|
48533
|
+
case "structure.get": {
|
|
48534
|
+
const input = parseOperationInput("structure.get", request.input);
|
|
48535
|
+
return service.getStructureByUri(input.uri);
|
|
48536
|
+
}
|
|
48537
|
+
case "structure.list": {
|
|
48538
|
+
const input = parseOperationInput("structure.list", request.input);
|
|
48539
|
+
return service.listStructuresByReference(input.reference);
|
|
48540
|
+
}
|
|
48541
|
+
case "structure.publish": {
|
|
48542
|
+
const input = parseOperationInput("structure.publish", request.input);
|
|
48543
|
+
return await service.publishStructure(input);
|
|
48544
|
+
}
|
|
48545
|
+
case "structure.update": {
|
|
48546
|
+
const input = parseOperationInput("structure.update", request.input);
|
|
48547
|
+
return await service.updateStructure(input.uri, input.content);
|
|
48548
|
+
}
|
|
48549
|
+
case "structure.delete.preview": {
|
|
48550
|
+
const input = parseOperationInput("structure.delete.preview", request.input);
|
|
48551
|
+
return service.getStructureDeletePreview(input.uri);
|
|
48552
|
+
}
|
|
48553
|
+
case "structure.delete": {
|
|
48554
|
+
const input = parseOperationInput("structure.delete", request.input);
|
|
48555
|
+
return service.deleteStructureByUri(input.uri, input.expectedUpdatedAt);
|
|
48556
|
+
}
|
|
47693
48557
|
}
|
|
47694
48558
|
}
|
|
47695
48559
|
function parseResponse(value) {
|
|
@@ -47706,8 +48570,11 @@ function uncertainOutcome(operation, cause, timedOut = false) {
|
|
|
47706
48570
|
{
|
|
47707
48571
|
cause,
|
|
47708
48572
|
details: { agentSocketOutcomeUncertain: true, operation },
|
|
47709
|
-
suggestions: [
|
|
47710
|
-
"\
|
|
48573
|
+
suggestions: operation === "structure.publish" ? [
|
|
48574
|
+
"\u540C\u3058idempotencyKey\u3068\u540C\u3058payload\u3067publish\u3092\u518D\u5B9F\u884C\u3059\u308B\u3068\u3001\u65E2\u5B58\u306EStructure\u3078\u53CE\u675F\u3057\u307E\u3059\u3002",
|
|
48575
|
+
"rvw structure list <PR> --json\u3067\u3082stable URI\u3092\u78BA\u8A8D\u3067\u304D\u307E\u3059\u3002"
|
|
48576
|
+
] : [
|
|
48577
|
+
"\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
48578
|
]
|
|
47712
48579
|
}
|
|
47713
48580
|
);
|
|
@@ -49313,6 +50180,11 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
|
|
|
49313
50180
|
"comment.resolve",
|
|
49314
50181
|
"comment.reopen",
|
|
49315
50182
|
"pullRequest.sync",
|
|
50183
|
+
"structure.list",
|
|
50184
|
+
"structure.read",
|
|
50185
|
+
"structure.publish",
|
|
50186
|
+
"structure.update",
|
|
50187
|
+
"structure.delete",
|
|
49316
50188
|
"walkthrough.read",
|
|
49317
50189
|
"walkthrough.publish",
|
|
49318
50190
|
"walkthrough.update",
|
|
@@ -49429,7 +50301,7 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
|
|
|
49429
50301
|
writeOutput(
|
|
49430
50302
|
options,
|
|
49431
50303
|
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}
|
|
50304
|
+
`\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
50305
|
\u7D9A\u884C\u3059\u308B\u306B\u306F --yes \u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
49434
50306
|
);
|
|
49435
50307
|
process.exitCode = 2;
|
|
@@ -49447,6 +50319,78 @@ function createProgram(runtimeFactory = defaultRuntimeFactory) {
|
|
|
49447
50319
|
);
|
|
49448
50320
|
});
|
|
49449
50321
|
const comment3 = program2.command("comment").description("\u4FDD\u5B58\u6E08\u307F\u30B3\u30E1\u30F3\u30C8\u3092\u64CD\u4F5C");
|
|
50322
|
+
const structure = program2.command("structure").description("source anchor\u4ED8\u304DStructure\u3092\u7BA1\u7406");
|
|
50323
|
+
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 () => {
|
|
50324
|
+
const input = structurePublishInputSchema.parse(await readStdinJson());
|
|
50325
|
+
const published = await callService(
|
|
50326
|
+
"structure.publish",
|
|
50327
|
+
input,
|
|
50328
|
+
async () => await getRuntime().service.publishStructure(input)
|
|
50329
|
+
);
|
|
50330
|
+
writeJson({ ok: true, structure: published });
|
|
50331
|
+
});
|
|
50332
|
+
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) => {
|
|
50333
|
+
const result = await callService(
|
|
50334
|
+
"structure.get",
|
|
50335
|
+
{ uri },
|
|
50336
|
+
() => getRuntime().service.getStructureByUri(uri)
|
|
50337
|
+
);
|
|
50338
|
+
writeJson({ ok: true, ...result });
|
|
50339
|
+
});
|
|
50340
|
+
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) => {
|
|
50341
|
+
const result = await callService(
|
|
50342
|
+
"structure.list",
|
|
50343
|
+
{ reference },
|
|
50344
|
+
() => getRuntime().service.listStructuresByReference(reference)
|
|
50345
|
+
);
|
|
50346
|
+
writeJson({ ok: true, ...result });
|
|
50347
|
+
});
|
|
50348
|
+
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) => {
|
|
50349
|
+
const content3 = structureUpdateInputSchema.parse(await readStdinJson());
|
|
50350
|
+
const updated = await callService(
|
|
50351
|
+
"structure.update",
|
|
50352
|
+
{ uri, content: content3 },
|
|
50353
|
+
async () => await getRuntime().service.updateStructure(uri, content3)
|
|
50354
|
+
);
|
|
50355
|
+
writeJson({ ok: true, structure: updated });
|
|
50356
|
+
});
|
|
50357
|
+
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(
|
|
50358
|
+
async (uri, options) => {
|
|
50359
|
+
if (!options.yes) {
|
|
50360
|
+
const preview = await callService(
|
|
50361
|
+
"structure.delete.preview",
|
|
50362
|
+
{ uri },
|
|
50363
|
+
() => getRuntime().service.getStructureDeletePreview(uri)
|
|
50364
|
+
);
|
|
50365
|
+
writeJson({
|
|
50366
|
+
ok: false,
|
|
50367
|
+
error: {
|
|
50368
|
+
code: "STRUCTURE_DELETE_CONFIRMATION_REQUIRED",
|
|
50369
|
+
message: "structure delete\u306B\u306F--yes\u304C\u5FC5\u8981\u3067\u3059\u3002",
|
|
50370
|
+
suggestions: [
|
|
50371
|
+
`rvw structure delete ${uri} --yes --expected-updated-at '${preview.structure.updatedAt}' --json`
|
|
50372
|
+
]
|
|
50373
|
+
},
|
|
50374
|
+
...preview
|
|
50375
|
+
});
|
|
50376
|
+
process.exitCode = 2;
|
|
50377
|
+
return;
|
|
50378
|
+
}
|
|
50379
|
+
if (!options.expectedUpdatedAt) {
|
|
50380
|
+
throw new RvwError(
|
|
50381
|
+
"INVALID_INPUT",
|
|
50382
|
+
"confirmed structure delete\u306B\u306Fpreview\u306EexpectedUpdatedAt\u304C\u5FC5\u8981\u3067\u3059\u3002",
|
|
50383
|
+
{ suggestions: [`rvw structure delete ${uri} --json \u3067\u73FE\u5728\u5024\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002`] }
|
|
50384
|
+
);
|
|
50385
|
+
}
|
|
50386
|
+
const deleted = await callService(
|
|
50387
|
+
"structure.delete",
|
|
50388
|
+
{ uri, expectedUpdatedAt: options.expectedUpdatedAt, confirmed: true },
|
|
50389
|
+
() => getRuntime().service.deleteStructureByUri(uri, options.expectedUpdatedAt)
|
|
50390
|
+
);
|
|
50391
|
+
writeJson({ ok: true, deleted });
|
|
50392
|
+
}
|
|
50393
|
+
);
|
|
49450
50394
|
const walkthrough = program2.command("walkthrough").description("\u30B3\u30FC\u30C9\u53C2\u7167\u4ED8\u304Dwalkthrough\u3092\u7BA1\u7406");
|
|
49451
50395
|
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
50396
|
const input = walkthroughPublishInputSchema.parse(await readStdinJson());
|