@graphrefly/stack 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -24
- package/dist/assets/contracts/repository/v1/review-bundle.schema.json +49 -0
- package/dist/assets/contracts/repository/v1/review-decision-request.schema.json +15 -0
- package/dist/assets/contracts/repository/v1/review-decision.schema.json +52 -0
- package/dist/assets/contracts/repository/v1/review.schema.json +2 -1
- package/dist/grfs.js +360 -32
- package/dist/review/assets/{abnfDiagram-VRR7QNED-5JVeQ-ZW.js → abnfDiagram-VRR7QNED-DxGYeLns.js} +1 -1
- package/dist/review/assets/{architectureDiagram-ZJ3FMSHR-BnEvDO7X.js → architectureDiagram-ZJ3FMSHR-CoaG1PSB.js} +1 -1
- package/dist/review/assets/{chunk-EX3LRPZG-BrpCa9zr.js → chunk-EX3LRPZG-C1ZhSVKp.js} +1 -1
- package/dist/review/assets/{chunk-MOJQB5TN-BshP08Ez.js → chunk-MOJQB5TN-Ct40HB9X.js} +1 -1
- package/dist/review/assets/{chunk-PUDLZKDR-HkwEqIVB.js → chunk-PUDLZKDR-C2Is490W.js} +1 -1
- package/dist/review/assets/{chunk-V7JOEXUC-CswDacm3.js → chunk-V7JOEXUC-Z3n_IPe-.js} +1 -1
- package/dist/review/assets/{classDiagram-OUVF2IWQ-U8e_ZvC4.js → classDiagram-OUVF2IWQ-BVlewphI.js} +1 -1
- package/dist/review/assets/{classDiagram-v2-EOCWNBFH-U8e_ZvC4.js → classDiagram-v2-EOCWNBFH-BVlewphI.js} +1 -1
- package/dist/review/assets/{cynefinDiagram-TSTJHNR4-CfYu2mB5.js → cynefinDiagram-TSTJHNR4-Cjm1OFIk.js} +1 -1
- package/dist/review/assets/{dagre-VKFMJZFB-BvyihZfA.js → dagre-VKFMJZFB-EvQo1qj2.js} +1 -1
- package/dist/review/assets/{diagram-G47NLZAW-qFNMv5An.js → diagram-G47NLZAW-k0H6Hccx.js} +1 -1
- package/dist/review/assets/{diagram-NH7WQ7WH-CsvacND9.js → diagram-NH7WQ7WH-VUneNb0M.js} +1 -1
- package/dist/review/assets/{diagram-OA4YK3LP-qFtWcyNi.js → diagram-OA4YK3LP-tUGLM6tT.js} +1 -1
- package/dist/review/assets/{diagram-WEI45ONY-C5nYGL8t.js → diagram-WEI45ONY-aN8naqL-.js} +1 -1
- package/dist/review/assets/{ebnfDiagram-CCIWWBDH-D_0nhpry.js → ebnfDiagram-CCIWWBDH-PjAeMUc1.js} +1 -1
- package/dist/review/assets/{erDiagram-Q63AITRT-CIS7hpdK.js → erDiagram-Q63AITRT-CkxN3vs2.js} +1 -1
- package/dist/review/assets/{flowDiagram-23GEKE2U-Df5sjnlg.js → flowDiagram-23GEKE2U-ChS1-2Qo.js} +1 -1
- package/dist/review/assets/index-CUaeHlgA.js +64 -0
- package/dist/review/assets/index-Cfj-JRmr.css +1 -0
- package/dist/review/assets/{infoDiagram-FWYZ7A6U-CT7TZgi6.js → infoDiagram-FWYZ7A6U-CcLr4Fgp.js} +1 -1
- package/dist/review/assets/{ishikawaDiagram-FXEZZL3T-BUpotH7r.js → ishikawaDiagram-FXEZZL3T-p7DbRTIs.js} +1 -1
- package/dist/review/assets/{kanban-definition-HUTT4EX6-e-emfNuh.js → kanban-definition-HUTT4EX6-BgXdqTkK.js} +1 -1
- package/dist/review/assets/{mindmap-definition-LN4V7U3C-ClSEPrvR.js → mindmap-definition-LN4V7U3C-zdfirl2I.js} +1 -1
- package/dist/review/assets/{pegDiagram-2B236MQR-Ck_v89jl.js → pegDiagram-2B236MQR-ScPkpaWR.js} +1 -1
- package/dist/review/assets/{pieDiagram-ENE6RG2P-C63dxyZj.js → pieDiagram-ENE6RG2P-BAQHg9fC.js} +1 -1
- package/dist/review/assets/{railroadDiagram-RFXS5EU6-DYI7CPMt.js → railroadDiagram-RFXS5EU6-DV8AQwDM.js} +1 -1
- package/dist/review/assets/{requirementDiagram-TGXJPOKE-BMW46SXM.js → requirementDiagram-TGXJPOKE-CnPqfxpt.js} +1 -1
- package/dist/review/assets/{sequenceDiagram-DBY2YBRQ-DVtyVuxr.js → sequenceDiagram-DBY2YBRQ-Bl7q6mbL.js} +1 -1
- package/dist/review/assets/{stateDiagram-2N3HPSRC-BM1s-zUo.js → stateDiagram-2N3HPSRC-iIZcI3Ny.js} +1 -1
- package/dist/review/assets/{stateDiagram-v2-6OUMAXLB-BEfolAkc.js → stateDiagram-v2-6OUMAXLB-Ct4036z_.js} +1 -1
- package/dist/review/assets/{swimlanes-5IMT3BWC-Bnu9mzxz.js → swimlanes-5IMT3BWC-DQR9TtlF.js} +1 -1
- package/dist/review/assets/{swimlanesDiagram-G3AALYLV-DlNNBK53.js → swimlanesDiagram-G3AALYLV-LS62ia1i.js} +1 -1
- package/dist/review/assets/{timeline-definition-FHXFAJF6-CwlO71Lp.js → timeline-definition-FHXFAJF6-Dm738Pbf.js} +1 -1
- package/dist/review/assets/{vennDiagram-L72KCM5P-DZxbcc_O.js → vennDiagram-L72KCM5P-DBxm9_YT.js} +1 -1
- package/dist/review/assets/{wardleyDiagram-EHGQE667-DGQto3hn.js → wardleyDiagram-EHGQE667-CKwVekAc.js} +1 -1
- package/dist/review/assets/{xychartDiagram-FW5EYKEG-BfD1lSXX.js → xychartDiagram-FW5EYKEG-TVh8_sN-.js} +1 -1
- package/dist/review/index.html +2 -2
- package/package.json +1 -1
- package/dist/review/assets/index-Bt3i8n39.css +0 -1
- package/dist/review/assets/index-CqjR4YYp.js +0 -64
package/dist/grfs.js
CHANGED
|
@@ -2980,7 +2980,7 @@ var require_compile = __commonJS({
|
|
|
2980
2980
|
const schOrFunc = root.refs[ref];
|
|
2981
2981
|
if (schOrFunc)
|
|
2982
2982
|
return schOrFunc;
|
|
2983
|
-
let _sch =
|
|
2983
|
+
let _sch = resolve12.call(this, root, ref);
|
|
2984
2984
|
if (_sch === void 0) {
|
|
2985
2985
|
const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
|
|
2986
2986
|
const { schemaId } = this.opts;
|
|
@@ -3007,7 +3007,7 @@ var require_compile = __commonJS({
|
|
|
3007
3007
|
function sameSchemaEnv(s1, s2) {
|
|
3008
3008
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
3009
3009
|
}
|
|
3010
|
-
function
|
|
3010
|
+
function resolve12(root, ref) {
|
|
3011
3011
|
let sch;
|
|
3012
3012
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
3013
3013
|
ref = sch;
|
|
@@ -3638,7 +3638,7 @@ var require_fast_uri = __commonJS({
|
|
|
3638
3638
|
}
|
|
3639
3639
|
return uri;
|
|
3640
3640
|
}
|
|
3641
|
-
function
|
|
3641
|
+
function resolve12(baseURI, relativeURI, options) {
|
|
3642
3642
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3643
3643
|
const resolved = resolveComponent(parse2(baseURI, schemelessOptions), parse2(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
3644
3644
|
schemelessOptions.skipEscape = true;
|
|
@@ -3896,7 +3896,7 @@ var require_fast_uri = __commonJS({
|
|
|
3896
3896
|
var fastUri = {
|
|
3897
3897
|
SCHEMES,
|
|
3898
3898
|
normalize,
|
|
3899
|
-
resolve:
|
|
3899
|
+
resolve: resolve12,
|
|
3900
3900
|
resolveComponent,
|
|
3901
3901
|
equal,
|
|
3902
3902
|
serialize: serialize2,
|
|
@@ -8563,8 +8563,9 @@ var require_semver2 = __commonJS({
|
|
|
8563
8563
|
});
|
|
8564
8564
|
|
|
8565
8565
|
// packages/cli/dist/cli.js
|
|
8566
|
-
import {
|
|
8567
|
-
import {
|
|
8566
|
+
import { realpathSync } from "node:fs";
|
|
8567
|
+
import { readFile as readFile8 } from "node:fs/promises";
|
|
8568
|
+
import { resolve as resolve11 } from "node:path";
|
|
8568
8569
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
8569
8570
|
|
|
8570
8571
|
// packages/contracts/dist/index.js
|
|
@@ -8626,6 +8627,8 @@ function sha256Jcs(value) {
|
|
|
8626
8627
|
// packages/contracts/dist/repository-review.js
|
|
8627
8628
|
var REPOSITORY_CONFIG_SCHEMA = "graphrefly.stack.repository.v1";
|
|
8628
8629
|
var REPOSITORY_REVIEW_SCHEMA = "graphrefly.stack.review.v1";
|
|
8630
|
+
var REPOSITORY_REVIEW_DECISION_SCHEMA = "graphrefly.stack.repository-review-decision.v1";
|
|
8631
|
+
var REPOSITORY_REVIEW_BUNDLE_SCHEMA = "graphrefly.stack.repository-review-bundle.v1";
|
|
8629
8632
|
var SUPPORTED_GRAPHREFLY_RANGE = ">=0.3.0 <0.4.0";
|
|
8630
8633
|
|
|
8631
8634
|
// packages/contracts/dist/index.js
|
|
@@ -10149,7 +10152,7 @@ process.stdout.write(JSON.stringify(blueprint));
|
|
|
10149
10152
|
// packages/cli/dist/repository-review.js
|
|
10150
10153
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
10151
10154
|
import { createHash as createHash6 } from "node:crypto";
|
|
10152
|
-
import { access as access2, mkdir as mkdir5, readFile as readFile6, realpath as realpath3, rm as rm4, symlink } from "node:fs/promises";
|
|
10155
|
+
import { access as access2, mkdir as mkdir5, readFile as readFile6, realpath as realpath3, rm as rm4, symlink, writeFile as writeFile5 } from "node:fs/promises";
|
|
10153
10156
|
import { createRequire as createRequire2 } from "node:module";
|
|
10154
10157
|
import { basename as basename2, dirname as dirname5, parse, resolve as resolve8, sep as sep4 } from "node:path";
|
|
10155
10158
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
@@ -10283,6 +10286,7 @@ var reviewSchemaPath = runtimeAssetPath("contracts/repository/v1/review.schema.j
|
|
|
10283
10286
|
var configName2 = ".graphrefly-stack.json";
|
|
10284
10287
|
var lockCandidates = ["pnpm-lock.yaml", "package-lock.json", "yarn.lock"];
|
|
10285
10288
|
var maxReviewCommits = 64;
|
|
10289
|
+
var maxEntrypointBytes = 64 * 1024;
|
|
10286
10290
|
var RepositoryReviewError = class extends Error {
|
|
10287
10291
|
code;
|
|
10288
10292
|
constructor(code, message) {
|
|
@@ -10365,6 +10369,22 @@ function ensureInside(root, candidate) {
|
|
|
10365
10369
|
throw new RepositoryReviewError("ENTRYPOINT_ESCAPE", "Blueprint entrypoint escapes the worktree");
|
|
10366
10370
|
}
|
|
10367
10371
|
}
|
|
10372
|
+
async function readConfiguredEntrypoint(repository, entrypointPath) {
|
|
10373
|
+
const entrypoint = resolve8(repository, entrypointPath);
|
|
10374
|
+
ensureInside(repository, entrypoint);
|
|
10375
|
+
let canonicalEntrypoint;
|
|
10376
|
+
try {
|
|
10377
|
+
canonicalEntrypoint = await realpath3(entrypoint);
|
|
10378
|
+
} catch {
|
|
10379
|
+
throw new RepositoryReviewError("ENTRYPOINT_MISSING", "Configured Blueprint entrypoint is missing");
|
|
10380
|
+
}
|
|
10381
|
+
ensureInside(repository, canonicalEntrypoint);
|
|
10382
|
+
const source = await readFile6(canonicalEntrypoint);
|
|
10383
|
+
if (source.byteLength > maxEntrypointBytes) {
|
|
10384
|
+
throw new RepositoryReviewError("ENTRYPOINT_TOO_LARGE", `Configured Blueprint entrypoint exceeds ${maxEntrypointBytes} bytes`);
|
|
10385
|
+
}
|
|
10386
|
+
return source;
|
|
10387
|
+
}
|
|
10368
10388
|
function containsAbsolutePath(value) {
|
|
10369
10389
|
if (typeof value === "string")
|
|
10370
10390
|
return value.startsWith("/") || /^[A-Za-z]:[\\/]/u.test(value);
|
|
@@ -10416,7 +10436,7 @@ async function resolveTargetRuntime(repository) {
|
|
|
10416
10436
|
diffGraphBlueprints: graphModule.diffGraphBlueprints
|
|
10417
10437
|
};
|
|
10418
10438
|
}
|
|
10419
|
-
async function executeBlueprint(repository, revision, entrypointPath, runtime) {
|
|
10439
|
+
async function executeBlueprint(repository, revision, entrypointPath, entrypointSource, runtime) {
|
|
10420
10440
|
const worktreeRoot = resolve8(dirname5(repository), `.graphrefly-stack-review-${basename2(repository)}-${process.pid}`);
|
|
10421
10441
|
const worktree = resolve8(worktreeRoot, revision.slice(0, 16));
|
|
10422
10442
|
await mkdir5(worktreeRoot, { recursive: true });
|
|
@@ -10429,8 +10449,19 @@ async function executeBlueprint(repository, revision, entrypointPath, runtime) {
|
|
|
10429
10449
|
try {
|
|
10430
10450
|
await access2(entrypoint);
|
|
10431
10451
|
} catch {
|
|
10432
|
-
|
|
10452
|
+
let canonicalParent;
|
|
10453
|
+
try {
|
|
10454
|
+
canonicalParent = await realpath3(dirname5(entrypoint));
|
|
10455
|
+
} catch {
|
|
10456
|
+
throw new RepositoryReviewError("ENTRYPOINT_MISSING", `Blueprint entrypoint parent is missing at ${revision.slice(0, 12)}`);
|
|
10457
|
+
}
|
|
10458
|
+
ensureInside(canonicalWorktree, canonicalParent);
|
|
10459
|
+
await writeFile5(resolve8(canonicalParent, basename2(entrypoint)), entrypointSource, {
|
|
10460
|
+
flag: "wx"
|
|
10461
|
+
});
|
|
10433
10462
|
}
|
|
10463
|
+
const canonicalEntrypoint = await realpath3(entrypoint);
|
|
10464
|
+
ensureInside(canonicalWorktree, canonicalEntrypoint);
|
|
10434
10465
|
const worktreeNodeModules = resolve8(canonicalWorktree, "node_modules");
|
|
10435
10466
|
await rm4(worktreeNodeModules, { recursive: true, force: true });
|
|
10436
10467
|
await symlink(runtime.nodeModulesRoot, worktreeNodeModules, "dir");
|
|
@@ -10439,7 +10470,7 @@ async function executeBlueprint(repository, revision, entrypointPath, runtime) {
|
|
|
10439
10470
|
`--allow-fs-read=${canonicalWorktree}`,
|
|
10440
10471
|
`--allow-fs-read=${runtime.nodeModulesRoot}`,
|
|
10441
10472
|
"--disable-warning=ExperimentalWarning",
|
|
10442
|
-
|
|
10473
|
+
canonicalEntrypoint
|
|
10443
10474
|
], {
|
|
10444
10475
|
cwd: canonicalWorktree,
|
|
10445
10476
|
encoding: "utf8",
|
|
@@ -10543,6 +10574,27 @@ async function validateReview(review) {
|
|
|
10543
10574
|
throw new RepositoryReviewError("REVIEW_SCHEMA_INVALID", `Repository review failed validation: ${JSON.stringify(validate.errors)}`);
|
|
10544
10575
|
}
|
|
10545
10576
|
}
|
|
10577
|
+
function reviewHeadLabel(repository, requested, headOid) {
|
|
10578
|
+
try {
|
|
10579
|
+
const symbolic = gitText(repository, ["rev-parse", "--symbolic-full-name", requested]);
|
|
10580
|
+
if (symbolic.startsWith("refs/heads/"))
|
|
10581
|
+
return symbolic.slice("refs/heads/".length);
|
|
10582
|
+
} catch {
|
|
10583
|
+
}
|
|
10584
|
+
try {
|
|
10585
|
+
const branch = gitText(repository, [
|
|
10586
|
+
"for-each-ref",
|
|
10587
|
+
"--format=%(refname:short)",
|
|
10588
|
+
"--points-at",
|
|
10589
|
+
headOid,
|
|
10590
|
+
"refs/heads"
|
|
10591
|
+
]).split("\n").find(Boolean);
|
|
10592
|
+
if (branch !== void 0)
|
|
10593
|
+
return branch;
|
|
10594
|
+
} catch {
|
|
10595
|
+
}
|
|
10596
|
+
return headOid.slice(0, 12);
|
|
10597
|
+
}
|
|
10546
10598
|
async function createRepositoryReview(options) {
|
|
10547
10599
|
let repository;
|
|
10548
10600
|
try {
|
|
@@ -10552,6 +10604,7 @@ async function createRepositoryReview(options) {
|
|
|
10552
10604
|
throw new RepositoryReviewError("REPOSITORY_INVALID", "Repository must be a local Git worktree");
|
|
10553
10605
|
}
|
|
10554
10606
|
const config = await readRepositoryConfig(repository);
|
|
10607
|
+
const entrypointSource = await readConfiguredEntrypoint(repository, config.blueprint.entrypoint);
|
|
10555
10608
|
const git2 = new SystemGitAdapter();
|
|
10556
10609
|
let baseOid;
|
|
10557
10610
|
let headOid;
|
|
@@ -10595,7 +10648,7 @@ async function createRepositoryReview(options) {
|
|
|
10595
10648
|
await validateDependencyContinuity(repository, allRevisions, runtime.version);
|
|
10596
10649
|
const evidence = [];
|
|
10597
10650
|
for (const revision of allRevisions) {
|
|
10598
|
-
const blueprint = await executeBlueprint(repository, revision, config.blueprint.entrypoint, runtime);
|
|
10651
|
+
const blueprint = await executeBlueprint(repository, revision, config.blueprint.entrypoint, entrypointSource, runtime);
|
|
10599
10652
|
evidence.push({
|
|
10600
10653
|
oid: revision,
|
|
10601
10654
|
subject: gitText(repository, ["show", "-s", "--format=%s", revision]),
|
|
@@ -10626,6 +10679,7 @@ async function createRepositoryReview(options) {
|
|
|
10626
10679
|
source: "generic-repository",
|
|
10627
10680
|
repository: {
|
|
10628
10681
|
label: basename2(repository),
|
|
10682
|
+
headLabel: reviewHeadLabel(repository, options.head, headOid),
|
|
10629
10683
|
graphreflyVersion: runtime.version,
|
|
10630
10684
|
entrypoint: config.blueprint.entrypoint,
|
|
10631
10685
|
baseOid,
|
|
@@ -10643,7 +10697,172 @@ async function createRepositoryReview(options) {
|
|
|
10643
10697
|
import { createReadStream } from "node:fs";
|
|
10644
10698
|
import { stat as stat4 } from "node:fs/promises";
|
|
10645
10699
|
import { createServer } from "node:http";
|
|
10646
|
-
import { extname, resolve as
|
|
10700
|
+
import { extname, resolve as resolve10, sep as sep6 } from "node:path";
|
|
10701
|
+
|
|
10702
|
+
// packages/cli/dist/repository-review-state.js
|
|
10703
|
+
import { randomUUID } from "node:crypto";
|
|
10704
|
+
import { lstat, mkdir as mkdir6, readdir, readFile as readFile7, realpath as realpath4, rename, writeFile as writeFile6 } from "node:fs/promises";
|
|
10705
|
+
import { resolve as resolve9, sep as sep5 } from "node:path";
|
|
10706
|
+
var schemaPaths = [
|
|
10707
|
+
"contracts/repository/v1/repository-config.schema.json",
|
|
10708
|
+
"contracts/repository/v1/review.schema.json",
|
|
10709
|
+
"contracts/repository/v1/review-decision-request.schema.json",
|
|
10710
|
+
"contracts/repository/v1/review-decision.schema.json",
|
|
10711
|
+
"contracts/repository/v1/review-bundle.schema.json"
|
|
10712
|
+
];
|
|
10713
|
+
var RepositoryReviewStateError = class extends Error {
|
|
10714
|
+
code;
|
|
10715
|
+
constructor(code, message) {
|
|
10716
|
+
super(message);
|
|
10717
|
+
this.code = code;
|
|
10718
|
+
this.name = "RepositoryReviewStateError";
|
|
10719
|
+
}
|
|
10720
|
+
};
|
|
10721
|
+
async function validators() {
|
|
10722
|
+
const schemas2 = await Promise.all(schemaPaths.map(async (path) => JSON.parse(await readFile7(runtimeAssetPath(path), "utf8"))));
|
|
10723
|
+
const ajv = createStrictAjv();
|
|
10724
|
+
for (const schema of schemas2)
|
|
10725
|
+
ajv.addSchema(schema);
|
|
10726
|
+
return {
|
|
10727
|
+
request: ajv.getSchema("urn:graphrefly-stack:schema:repository-review-decision-request:v1"),
|
|
10728
|
+
decision: ajv.getSchema("urn:graphrefly-stack:schema:repository-review-decision:v1"),
|
|
10729
|
+
bundle: ajv.getSchema("urn:graphrefly-stack:schema:repository-review-bundle:v1")
|
|
10730
|
+
};
|
|
10731
|
+
}
|
|
10732
|
+
async function safeDirectory(path, parent) {
|
|
10733
|
+
try {
|
|
10734
|
+
const current = await lstat(path);
|
|
10735
|
+
if (!current.isDirectory() || current.isSymbolicLink()) {
|
|
10736
|
+
throw new RepositoryReviewStateError("REVIEW_STATE_PATH_UNSAFE", "Local review state path must be a real directory");
|
|
10737
|
+
}
|
|
10738
|
+
} catch (error) {
|
|
10739
|
+
if (error instanceof RepositoryReviewStateError)
|
|
10740
|
+
throw error;
|
|
10741
|
+
if (error.code !== "ENOENT")
|
|
10742
|
+
throw error;
|
|
10743
|
+
await mkdir6(path, { recursive: false, mode: 448 });
|
|
10744
|
+
}
|
|
10745
|
+
const canonical = await realpath4(path);
|
|
10746
|
+
if (!canonical.startsWith(`${parent}${sep5}`)) {
|
|
10747
|
+
throw new RepositoryReviewStateError("REVIEW_STATE_PATH_UNSAFE", "Local review state escaped the Git common directory");
|
|
10748
|
+
}
|
|
10749
|
+
return canonical;
|
|
10750
|
+
}
|
|
10751
|
+
async function repositoryReviewStateRoot(repository) {
|
|
10752
|
+
const commonDirectory = await realpath4(gitText(repository, ["rev-parse", "--path-format=absolute", "--git-common-dir"]));
|
|
10753
|
+
return safeDirectory(resolve9(commonDirectory, "grfs"), commonDirectory);
|
|
10754
|
+
}
|
|
10755
|
+
async function decisionsDirectory(repository) {
|
|
10756
|
+
const root = await repositoryReviewStateRoot(repository);
|
|
10757
|
+
return safeDirectory(resolve9(root, "reviews"), root);
|
|
10758
|
+
}
|
|
10759
|
+
function blueprintHashFor(review, commitOid) {
|
|
10760
|
+
const commit = review.commits.find((candidate) => candidate.oid === commitOid);
|
|
10761
|
+
const hash2 = commit?.blueprint.hash;
|
|
10762
|
+
if (typeof hash2 !== "object" || hash2 === null)
|
|
10763
|
+
return void 0;
|
|
10764
|
+
return typeof hash2.value === "string" ? hash2.value : void 0;
|
|
10765
|
+
}
|
|
10766
|
+
function matchesCurrentReview(review, record) {
|
|
10767
|
+
const commit = review.commits.find((candidate) => candidate.oid === record.target.commitOid);
|
|
10768
|
+
return commit !== void 0 && record.target.baseOid === review.repository.baseOid && record.target.headOid === review.repository.headOid && record.target.parentOid === commit.parentOid && record.target.blueprintHash === blueprintHashFor(review, commit.oid);
|
|
10769
|
+
}
|
|
10770
|
+
async function readRepositoryReviewDecisions(repository, review) {
|
|
10771
|
+
const directory = await decisionsDirectory(repository);
|
|
10772
|
+
const { decision: validate } = await validators();
|
|
10773
|
+
if (validate === void 0)
|
|
10774
|
+
throw new Error("Repository review decision validator unavailable");
|
|
10775
|
+
const entries = (await readdir(directory, { withFileTypes: true })).filter((entry2) => entry2.isFile() && entry2.name.endsWith(".json")).map((entry2) => entry2.name).sort();
|
|
10776
|
+
const records = [];
|
|
10777
|
+
for (const entry2 of entries) {
|
|
10778
|
+
let value;
|
|
10779
|
+
try {
|
|
10780
|
+
value = JSON.parse(await readFile7(resolve9(directory, entry2), "utf8"));
|
|
10781
|
+
} catch {
|
|
10782
|
+
throw new RepositoryReviewStateError("REVIEW_STATE_INVALID", `Local review record is not valid JSON: ${entry2}`);
|
|
10783
|
+
}
|
|
10784
|
+
if (!validate(value)) {
|
|
10785
|
+
throw new RepositoryReviewStateError("REVIEW_STATE_INVALID", `Local review record failed validation: ${entry2}`);
|
|
10786
|
+
}
|
|
10787
|
+
const record = value;
|
|
10788
|
+
if (matchesCurrentReview(review, record))
|
|
10789
|
+
records.push(record);
|
|
10790
|
+
}
|
|
10791
|
+
return records.sort((left, right) => left.recordedAt.localeCompare(right.recordedAt));
|
|
10792
|
+
}
|
|
10793
|
+
async function writeRepositoryReviewDecision(repository, review, input) {
|
|
10794
|
+
const { request: validateRequest, decision: validateDecision } = await validators();
|
|
10795
|
+
if (validateRequest === void 0 || validateDecision === void 0) {
|
|
10796
|
+
throw new Error("Repository review decision validators unavailable");
|
|
10797
|
+
}
|
|
10798
|
+
if (!validateRequest(input)) {
|
|
10799
|
+
throw new RepositoryReviewStateError("REVIEW_DECISION_INVALID", `Review decision request failed validation: ${JSON.stringify(validateRequest.errors)}`);
|
|
10800
|
+
}
|
|
10801
|
+
const request = input;
|
|
10802
|
+
const reviewerLabel = request.reviewerLabel.trim();
|
|
10803
|
+
const summary = request.summary.trim();
|
|
10804
|
+
if (reviewerLabel.length === 0) {
|
|
10805
|
+
throw new RepositoryReviewStateError("REVIEW_DECISION_INVALID", "Reviewer name cannot be blank");
|
|
10806
|
+
}
|
|
10807
|
+
const commit = review.commits.find((candidate) => candidate.oid === request.commitOid);
|
|
10808
|
+
const blueprintHash = blueprintHashFor(review, request.commitOid);
|
|
10809
|
+
if (commit === void 0 || blueprintHash === void 0) {
|
|
10810
|
+
throw new RepositoryReviewStateError("REVIEW_TARGET_STALE", "The selected commit is not part of the current review range");
|
|
10811
|
+
}
|
|
10812
|
+
const record = {
|
|
10813
|
+
schema: REPOSITORY_REVIEW_DECISION_SCHEMA,
|
|
10814
|
+
id: randomUUID(),
|
|
10815
|
+
target: {
|
|
10816
|
+
baseOid: review.repository.baseOid,
|
|
10817
|
+
headOid: review.repository.headOid,
|
|
10818
|
+
parentOid: commit.parentOid,
|
|
10819
|
+
commitOid: commit.oid,
|
|
10820
|
+
blueprintHash
|
|
10821
|
+
},
|
|
10822
|
+
decision: request.decision,
|
|
10823
|
+
reviewerLabel,
|
|
10824
|
+
summary,
|
|
10825
|
+
recordedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10826
|
+
identityVerified: false
|
|
10827
|
+
};
|
|
10828
|
+
if (!validateDecision(record)) {
|
|
10829
|
+
throw new Error(`Generated review decision failed validation: ${JSON.stringify(validateDecision.errors)}`);
|
|
10830
|
+
}
|
|
10831
|
+
const directory = await decisionsDirectory(repository);
|
|
10832
|
+
const destination = resolve9(directory, `${record.id}.json`);
|
|
10833
|
+
const temporary = resolve9(directory, `.${record.id}.tmp`);
|
|
10834
|
+
await writeFile6(temporary, `${JSON.stringify(record, null, 2)}
|
|
10835
|
+
`, {
|
|
10836
|
+
encoding: "utf8",
|
|
10837
|
+
flag: "wx",
|
|
10838
|
+
mode: 384
|
|
10839
|
+
});
|
|
10840
|
+
await rename(temporary, destination);
|
|
10841
|
+
return record;
|
|
10842
|
+
}
|
|
10843
|
+
async function createRepositoryReviewBundle(repository, review) {
|
|
10844
|
+
const records = await readRepositoryReviewDecisions(repository, review);
|
|
10845
|
+
const bundle = {
|
|
10846
|
+
schema: REPOSITORY_REVIEW_BUNDLE_SCHEMA,
|
|
10847
|
+
repository: {
|
|
10848
|
+
label: review.repository.label,
|
|
10849
|
+
baseOid: review.repository.baseOid,
|
|
10850
|
+
headOid: review.repository.headOid
|
|
10851
|
+
},
|
|
10852
|
+
artifacts: records.map((record) => ({
|
|
10853
|
+
path: `reviews/${record.id}.json`,
|
|
10854
|
+
hash: { algorithm: "sha256", value: sha256Jcs(record) },
|
|
10855
|
+
record
|
|
10856
|
+
}))
|
|
10857
|
+
};
|
|
10858
|
+
const { bundle: validate } = await validators();
|
|
10859
|
+
if (validate === void 0 || !validate(bundle)) {
|
|
10860
|
+
throw new Error(`Generated review bundle failed validation: ${JSON.stringify(validate?.errors)}`);
|
|
10861
|
+
}
|
|
10862
|
+
return bundle;
|
|
10863
|
+
}
|
|
10864
|
+
|
|
10865
|
+
// packages/cli/dist/review-server.js
|
|
10647
10866
|
var defaultReviewDist = runtimeReviewDist();
|
|
10648
10867
|
var contentTypes = {
|
|
10649
10868
|
".css": "text/css; charset=utf-8",
|
|
@@ -10652,6 +10871,32 @@ var contentTypes = {
|
|
|
10652
10871
|
".json": "application/json; charset=utf-8",
|
|
10653
10872
|
".svg": "image/svg+xml"
|
|
10654
10873
|
};
|
|
10874
|
+
async function readJsonBody(request) {
|
|
10875
|
+
const maximumBytes = 32 * 1024;
|
|
10876
|
+
const declaredLength = Number(request.headers["content-length"] ?? "0");
|
|
10877
|
+
if (Number.isFinite(declaredLength) && declaredLength > maximumBytes) {
|
|
10878
|
+
throw new RepositoryReviewStateError("REVIEW_DECISION_TOO_LARGE", "Review decision request exceeds 32 KiB");
|
|
10879
|
+
}
|
|
10880
|
+
const chunks = [];
|
|
10881
|
+
let size = 0;
|
|
10882
|
+
for await (const chunk of request) {
|
|
10883
|
+
const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
10884
|
+
size += bytes.length;
|
|
10885
|
+
if (size > maximumBytes) {
|
|
10886
|
+
throw new RepositoryReviewStateError("REVIEW_DECISION_TOO_LARGE", "Review decision request exceeds 32 KiB");
|
|
10887
|
+
}
|
|
10888
|
+
chunks.push(bytes);
|
|
10889
|
+
}
|
|
10890
|
+
try {
|
|
10891
|
+
return JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
10892
|
+
} catch {
|
|
10893
|
+
throw new RepositoryReviewStateError("REVIEW_DECISION_INVALID", "Review decision request is not valid JSON");
|
|
10894
|
+
}
|
|
10895
|
+
}
|
|
10896
|
+
function sendJson(response, status, value) {
|
|
10897
|
+
response.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
10898
|
+
response.writeHead(status).end(JSON.stringify(value));
|
|
10899
|
+
}
|
|
10655
10900
|
function safeAssetPath(distDir, requestUrl) {
|
|
10656
10901
|
let pathname;
|
|
10657
10902
|
try {
|
|
@@ -10660,23 +10905,58 @@ function safeAssetPath(distDir, requestUrl) {
|
|
|
10660
10905
|
return null;
|
|
10661
10906
|
}
|
|
10662
10907
|
const relative2 = pathname === "/" ? "index.html" : pathname.replace(/^\/+/, "");
|
|
10663
|
-
const candidate =
|
|
10664
|
-
return candidate === distDir || candidate.startsWith(`${distDir}${
|
|
10908
|
+
const candidate = resolve10(distDir, relative2);
|
|
10909
|
+
return candidate === distDir || candidate.startsWith(`${distDir}${sep6}`) ? candidate : null;
|
|
10665
10910
|
}
|
|
10666
10911
|
async function startReviewServer(options = {}) {
|
|
10667
10912
|
const host = options.host ?? "127.0.0.1";
|
|
10668
10913
|
const port = options.port ?? 4173;
|
|
10669
|
-
const distDir =
|
|
10670
|
-
const evidenceBundlePath = options.evidenceBundlePath === void 0 ? void 0 :
|
|
10914
|
+
const distDir = resolve10(options.distDir ?? defaultReviewDist);
|
|
10915
|
+
const evidenceBundlePath = options.evidenceBundlePath === void 0 ? void 0 : resolve10(options.evidenceBundlePath);
|
|
10671
10916
|
const server = createServer(async (request, response) => {
|
|
10672
10917
|
response.setHeader("Cache-Control", "no-store");
|
|
10673
10918
|
response.setHeader("Content-Security-Policy", "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'");
|
|
10674
10919
|
response.setHeader("X-Content-Type-Options", "nosniff");
|
|
10920
|
+
const pathname = new URL(request.url ?? "/", "http://localhost").pathname;
|
|
10921
|
+
if (pathname === "/api/review-decisions" && request.method === "POST") {
|
|
10922
|
+
const state = options.repositoryReviewState;
|
|
10923
|
+
if (state === void 0) {
|
|
10924
|
+
response.writeHead(404).end("Local review state unavailable");
|
|
10925
|
+
return;
|
|
10926
|
+
}
|
|
10927
|
+
const expectedOrigin = request.headers.host === void 0 ? void 0 : `http://${request.headers.host}`;
|
|
10928
|
+
if (request.headers.origin !== expectedOrigin || request.headers["x-graphrefly-review"] !== "1") {
|
|
10929
|
+
response.writeHead(403).end("Same-origin review action required");
|
|
10930
|
+
return;
|
|
10931
|
+
}
|
|
10932
|
+
if (!request.headers["content-type"]?.startsWith("application/json")) {
|
|
10933
|
+
response.writeHead(415).end("application/json required");
|
|
10934
|
+
return;
|
|
10935
|
+
}
|
|
10936
|
+
try {
|
|
10937
|
+
const input = await readJsonBody(request);
|
|
10938
|
+
const record = await writeRepositoryReviewDecision(state.repository, state.review, input);
|
|
10939
|
+
sendJson(response, 201, record);
|
|
10940
|
+
} catch (error) {
|
|
10941
|
+
if (error instanceof RepositoryReviewStateError) {
|
|
10942
|
+
sendJson(response, error.code === "REVIEW_TARGET_STALE" ? 409 : 400, {
|
|
10943
|
+
code: error.code,
|
|
10944
|
+
message: error.message
|
|
10945
|
+
});
|
|
10946
|
+
} else {
|
|
10947
|
+
sendJson(response, 500, {
|
|
10948
|
+
code: "REVIEW_STATE_FAILED",
|
|
10949
|
+
message: "Local review state could not be updated"
|
|
10950
|
+
});
|
|
10951
|
+
}
|
|
10952
|
+
}
|
|
10953
|
+
return;
|
|
10954
|
+
}
|
|
10675
10955
|
if (request.method !== "GET" && request.method !== "HEAD") {
|
|
10676
10956
|
response.writeHead(405).end("Method not allowed");
|
|
10677
10957
|
return;
|
|
10678
10958
|
}
|
|
10679
|
-
if (
|
|
10959
|
+
if (pathname === "/api/review-data") {
|
|
10680
10960
|
if (options.reviewData === void 0) {
|
|
10681
10961
|
response.writeHead(404).end("Review data unavailable");
|
|
10682
10962
|
return;
|
|
@@ -10689,7 +10969,47 @@ async function startReviewServer(options = {}) {
|
|
|
10689
10969
|
response.end(JSON.stringify(options.reviewData));
|
|
10690
10970
|
return;
|
|
10691
10971
|
}
|
|
10692
|
-
if (
|
|
10972
|
+
if (pathname === "/api/review-decisions") {
|
|
10973
|
+
const state = options.repositoryReviewState;
|
|
10974
|
+
if (state === void 0) {
|
|
10975
|
+
response.writeHead(404).end("Local review state unavailable");
|
|
10976
|
+
return;
|
|
10977
|
+
}
|
|
10978
|
+
try {
|
|
10979
|
+
const records = await readRepositoryReviewDecisions(state.repository, state.review);
|
|
10980
|
+
response.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
10981
|
+
response.writeHead(200);
|
|
10982
|
+
if (request.method === "HEAD")
|
|
10983
|
+
response.end();
|
|
10984
|
+
else
|
|
10985
|
+
response.end(JSON.stringify(records));
|
|
10986
|
+
} catch {
|
|
10987
|
+
response.writeHead(500).end("Local review state unavailable");
|
|
10988
|
+
}
|
|
10989
|
+
return;
|
|
10990
|
+
}
|
|
10991
|
+
if (pathname === "/api/review-decisions/export") {
|
|
10992
|
+
const state = options.repositoryReviewState;
|
|
10993
|
+
if (state === void 0) {
|
|
10994
|
+
response.writeHead(404).end("Portable review bundle unavailable");
|
|
10995
|
+
return;
|
|
10996
|
+
}
|
|
10997
|
+
try {
|
|
10998
|
+
const bundle = await createRepositoryReviewBundle(state.repository, state.review);
|
|
10999
|
+
response.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
11000
|
+
response.setHeader("Content-Disposition", 'attachment; filename="graphrefly-stack-reviews.json"');
|
|
11001
|
+
response.writeHead(200);
|
|
11002
|
+
if (request.method === "HEAD")
|
|
11003
|
+
response.end();
|
|
11004
|
+
else
|
|
11005
|
+
response.end(`${JSON.stringify(bundle, null, 2)}
|
|
11006
|
+
`);
|
|
11007
|
+
} catch {
|
|
11008
|
+
response.writeHead(500).end("Portable review bundle unavailable");
|
|
11009
|
+
}
|
|
11010
|
+
return;
|
|
11011
|
+
}
|
|
11012
|
+
if (pathname === "/api/evidence-bundle") {
|
|
10693
11013
|
if (evidenceBundlePath === void 0) {
|
|
10694
11014
|
response.writeHead(404).end("Portable evidence bundle unavailable");
|
|
10695
11015
|
return;
|
|
@@ -10753,11 +11073,11 @@ Usage:
|
|
|
10753
11073
|
grfs review [--bundle <path>] [--fixture <runtime-suite.json>] [--host 127.0.0.1] [--port 4173]
|
|
10754
11074
|
grfs export [--fixture <runtime-suite.json>] [--plan-run <path>] [--replan-run <path>] [--output <path>] --json
|
|
10755
11075
|
`;
|
|
10756
|
-
var defaultFixtureOutput =
|
|
10757
|
-
var defaultRuntimeSuite =
|
|
11076
|
+
var defaultFixtureOutput = resolve11(".private/fixtures/refresh-token-rotation-v1");
|
|
11077
|
+
var defaultRuntimeSuite = resolve11(defaultFixtureOutput, ".graphrefly-stack/runtime-suite.json");
|
|
10758
11078
|
function isWithin(root, candidate) {
|
|
10759
|
-
const normalizedRoot =
|
|
10760
|
-
const normalizedCandidate =
|
|
11079
|
+
const normalizedRoot = resolve11(root);
|
|
11080
|
+
const normalizedCandidate = resolve11(candidate);
|
|
10761
11081
|
return normalizedCandidate === normalizedRoot || normalizedCandidate.startsWith(`${normalizedRoot}/`);
|
|
10762
11082
|
}
|
|
10763
11083
|
function commandFrom(argv) {
|
|
@@ -10806,12 +11126,12 @@ function caseFrom(runtime, caseId) {
|
|
|
10806
11126
|
return runtime.cases.find((fixtureCase) => fixtureCase.caseId === caseId);
|
|
10807
11127
|
}
|
|
10808
11128
|
async function readJson2(path) {
|
|
10809
|
-
return JSON.parse(await
|
|
11129
|
+
return JSON.parse(await readFile8(path, "utf8"));
|
|
10810
11130
|
}
|
|
10811
11131
|
async function readLiveRun(path, kind) {
|
|
10812
11132
|
if (path === void 0)
|
|
10813
11133
|
return void 0;
|
|
10814
|
-
const value = await readJson2(
|
|
11134
|
+
const value = await readJson2(resolve11(path));
|
|
10815
11135
|
if (value.schema !== "urn:graphrefly-stack:live-run:v1" || value.kind !== kind || value.mode !== "live" || typeof value.provenance !== "object" || value.provenance === null) {
|
|
10816
11136
|
throw new Error(`Invalid ${kind} live-run artifact`);
|
|
10817
11137
|
}
|
|
@@ -10925,14 +11245,14 @@ ${help}`);
|
|
|
10925
11245
|
}
|
|
10926
11246
|
}
|
|
10927
11247
|
if (command === "fixture-create") {
|
|
10928
|
-
const output =
|
|
10929
|
-
if (!isWithin(
|
|
11248
|
+
const output = resolve11(readOption(argv, "--output") ?? defaultFixtureOutput);
|
|
11249
|
+
if (!isWithin(resolve11(".private"), output)) {
|
|
10930
11250
|
return failure(command, json, "OUTPUT_OUTSIDE_PRIVATE_ROOT", output, "replay");
|
|
10931
11251
|
}
|
|
10932
11252
|
const runtime = await createFlagshipFixture(output, argv.includes("--force"));
|
|
10933
11253
|
success(command, "replay", {
|
|
10934
11254
|
repository: runtime.repository,
|
|
10935
|
-
runtimeSuite:
|
|
11255
|
+
runtimeSuite: resolve11(output, ".graphrefly-stack/runtime-suite.json"),
|
|
10936
11256
|
refs: runtime.refs
|
|
10937
11257
|
}, json);
|
|
10938
11258
|
return 0;
|
|
@@ -10983,8 +11303,8 @@ ${help}`);
|
|
|
10983
11303
|
}
|
|
10984
11304
|
if (command === "export") {
|
|
10985
11305
|
const runtime = await readRuntimeSuite(readOption(argv, "--fixture") ?? defaultRuntimeSuite);
|
|
10986
|
-
const requestedOutput =
|
|
10987
|
-
if (!isWithin(
|
|
11306
|
+
const requestedOutput = resolve11(readOption(argv, "--output") ?? resolve11(".private/exports/refresh-token-rotation-v1"));
|
|
11307
|
+
if (!isWithin(resolve11(".private"), requestedOutput) && !isWithin(resolve11("evidence/runs"), requestedOutput)) {
|
|
10988
11308
|
return failure(command, json, "OUTPUT_OUTSIDE_EVIDENCE_ROOT", requestedOutput);
|
|
10989
11309
|
}
|
|
10990
11310
|
const liveRuns = {
|
|
@@ -11006,6 +11326,7 @@ ${help}`);
|
|
|
11006
11326
|
}
|
|
11007
11327
|
let reviewData;
|
|
11008
11328
|
let evidenceBundlePath;
|
|
11329
|
+
let repositoryReviewState;
|
|
11009
11330
|
const repository = readOption(argv, "--repo");
|
|
11010
11331
|
const base = readOption(argv, "--base");
|
|
11011
11332
|
const head = readOption(argv, "--head");
|
|
@@ -11019,7 +11340,9 @@ ${help}`);
|
|
|
11019
11340
|
return failure(command, json, "REVIEW_SOURCE_CONFLICT", "Generic repository review cannot be mixed with fixture or bundle input");
|
|
11020
11341
|
}
|
|
11021
11342
|
try {
|
|
11022
|
-
|
|
11343
|
+
const repositoryReview = await createRepositoryReview({ repository, base, head });
|
|
11344
|
+
reviewData = repositoryReview;
|
|
11345
|
+
repositoryReviewState = { repository: resolve11(repository), review: repositoryReview };
|
|
11023
11346
|
} catch (error) {
|
|
11024
11347
|
if (error instanceof RepositoryReviewError) {
|
|
11025
11348
|
return failure(command, json, error.code, error.message);
|
|
@@ -11070,7 +11393,8 @@ ${help}`);
|
|
|
11070
11393
|
host,
|
|
11071
11394
|
port,
|
|
11072
11395
|
reviewData,
|
|
11073
|
-
evidenceBundlePath
|
|
11396
|
+
evidenceBundlePath,
|
|
11397
|
+
repositoryReviewState
|
|
11074
11398
|
});
|
|
11075
11399
|
process.stderr.write(`GraphReFly Stack review shell (${CORE_ARCHITECTURE.version}) listening at ${running.url}
|
|
11076
11400
|
`);
|
|
@@ -11079,7 +11403,11 @@ ${help}`);
|
|
|
11079
11403
|
process.once("SIGTERM", close);
|
|
11080
11404
|
return 0;
|
|
11081
11405
|
}
|
|
11082
|
-
var entry =
|
|
11406
|
+
var entry = "";
|
|
11407
|
+
try {
|
|
11408
|
+
entry = process.argv[1] ? pathToFileURL3(realpathSync(process.argv[1])).href : "";
|
|
11409
|
+
} catch {
|
|
11410
|
+
}
|
|
11083
11411
|
if (import.meta.url === entry) {
|
|
11084
11412
|
runCli().then((code) => {
|
|
11085
11413
|
process.exitCode = code;
|
package/dist/review/assets/{abnfDiagram-VRR7QNED-5JVeQ-ZW.js → abnfDiagram-VRR7QNED-DxGYeLns.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{m as e}from"./src-BMa7vLb8.js";import{n as t}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import"./chunk-WYO6CB5R-C36byBU-.js";import"./index-
|
|
1
|
+
import{m as e}from"./src-BMa7vLb8.js";import{n as t}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import"./chunk-WYO6CB5R-C36byBU-.js";import"./index-CUaeHlgA.js";import{m as n,t as r}from"./mermaid-parser.core-BJLV4lM2.js";import{n as i,r as a,t as o}from"./chunk-MOJQB5TN-Ct40HB9X.js";import{t as s}from"./chunk-JWPE2WC7-DVXcaiue.js";var c=n().RailroadAbnf.parser.LangiumParser,l=t(e=>{let t=e.alternatives.map(u);return t.length===1?t[0]:{type:`choice`,alternatives:t}},`transformAlternation`),u=t(e=>{let t=e.elements.map(f);return t.length===1?t[0]:{type:`sequence`,elements:t}},`transformConcatenation`),d=t(e=>{if(e.includes(`*`)){let[t,n]=e.split(`*`);return{min:t?parseInt(t,10):0,max:n?parseInt(n,10):1/0}}let t=parseInt(e,10);return{min:t,max:t}},`parseRepeat`),f=t(e=>{let t=p(e.primary);if(!e.repeat)return t;let{min:n,max:r}=d(e.repeat);return n===0&&r===1?{type:`optional`,element:t}:{type:`repetition`,element:t,min:n,max:r}},`transformElement`),p=t(e=>{switch(e.$type){case`AbnfStringLiteral`:return{type:`terminal`,value:e.value};case`AbnfNumVal`:return{type:`terminal`,value:e.value};case`AbnfRuleName`:return{type:`nonterminal`,name:e.name};case`AbnfGroup`:return l(e.element);case`AbnfOptionalGroup`:return{type:`optional`,element:l(e.element)};default:throw Error(`Unsupported ABNF primary node: ${e.$type}`)}},`transformPrimary`),m=t(e=>({name:e.name,definition:l(e.definition)}),`transformRule`),h=t(e=>{s(e,o),e.title&&o.setTitle(e.title),e.rules.map(e=>o.addRule(m(e)))},`populateDb`),g={parser:{parse:t(t=>{o.clear(),e.debug(`[ABNF Parser] Starting Langium parse`);let n=c.parse(t);if(n.lexerErrors.length>0||n.parserErrors.length>0)throw new r(n);let i=n.value;e.debug(`[ABNF Parser] Parsed rules:`,i.rules.length),h(i),e.debug(`[ABNF Parser] Parse complete`)},`parse`),parser:{yy:o}},db:o,renderer:a,styles:i};export{g as diagram};
|