@graphrefly/stack 0.1.0 → 0.1.1
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 +24 -12
- package/dist/grfs.js +40 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,14 +21,13 @@ GraphReFly repository you want to review:
|
|
|
21
21
|
```bash
|
|
22
22
|
pnpm add -D @graphrefly/stack
|
|
23
23
|
pnpm exec grfs init --graph-module src/application-graph.ts
|
|
24
|
-
git add .graphrefly-stack.json graphrefly-stack.blueprint.mjs
|
|
25
|
-
git commit -m "configure GraphReFly Stack"
|
|
26
24
|
|
|
27
25
|
BASE=<the commit immediately before your stack>
|
|
28
26
|
pnpm exec grfs review --repo . --base "$BASE" --head HEAD
|
|
29
27
|
```
|
|
30
28
|
|
|
31
|
-
|
|
29
|
+
The review command stays running and prints its loopback URL; it does not launch a browser
|
|
30
|
+
automatically. Open the printed URL (normally <http://127.0.0.1:4173>), then:
|
|
32
31
|
|
|
33
32
|
1. Select each commit discovered from the real linear Git range.
|
|
34
33
|
2. See the Blueprint and parent delta produced by the repository's installed GraphReFly 0.3.x
|
|
@@ -38,15 +37,28 @@ Open <http://127.0.0.1:4173>, then:
|
|
|
38
37
|
4. Expand repository evidence or commit lineage only when needed. No session, delivery, fixture, or
|
|
39
38
|
fake semantic-gate state appears in the generic review.
|
|
40
39
|
|
|
41
|
-
`
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
40
|
+
`--graph-module` means the repository's root Graph construction module, not the only Graph module
|
|
41
|
+
allowed in the repository. That root module may import, compose, and mount any number of Graphs and
|
|
42
|
+
subgraphs. The first version reviews one configured root Blueprint target at a time; selecting among
|
|
43
|
+
multiple independent application roots in a monorepo is roadmap work.
|
|
44
|
+
|
|
45
|
+
`grfs init` does not guess how an arbitrary application assembles that root Graph. You point it at
|
|
46
|
+
the module and export that already construct it once during onboarding. The command generates the
|
|
47
|
+
strict `.graphrefly-stack.json` config and a small deterministic
|
|
48
|
+
`graphrefly-stack.blueprint.mjs` adapter; both are ordinary source files that should be committed.
|
|
49
|
+
Use `--graph-export <name>` when the module does not export `createApplicationGraph`. JSON is the v1
|
|
50
|
+
configuration format; optional YAML and TOML authoring formats are deferred roadmap work and must
|
|
51
|
+
normalize to the same strict configuration contract before execution.
|
|
52
|
+
|
|
53
|
+
Initialization may happen after the stack already exists. The review snapshots the configured
|
|
54
|
+
adapter and supplies those same bounded bytes only inside isolated detached revisions where that
|
|
55
|
+
entrypoint did not exist yet; it does not rewrite repository history. The referenced root Graph
|
|
56
|
+
module must exist at every reviewed revision. Commit the config and adapter after onboarding so
|
|
57
|
+
future reviews have a Git-owned configuration witness.
|
|
58
|
+
|
|
59
|
+
The CLI executes the adapter at the base and every commit in permission-limited detached worktrees.
|
|
60
|
+
Each invocation calls the real GraphReFly `graph.blueprint()` API; Stack then parses, verifies,
|
|
61
|
+
renders, and diffs only with the installed runtime's public GraphReFly APIs.
|
|
50
62
|
|
|
51
63
|
## Generic repository contract
|
|
52
64
|
|
package/dist/grfs.js
CHANGED
|
@@ -8563,6 +8563,7 @@ var require_semver2 = __commonJS({
|
|
|
8563
8563
|
});
|
|
8564
8564
|
|
|
8565
8565
|
// packages/cli/dist/cli.js
|
|
8566
|
+
import { realpathSync } from "node:fs";
|
|
8566
8567
|
import { readFile as readFile7 } from "node:fs/promises";
|
|
8567
8568
|
import { resolve as resolve10 } from "node:path";
|
|
8568
8569
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
@@ -10149,7 +10150,7 @@ process.stdout.write(JSON.stringify(blueprint));
|
|
|
10149
10150
|
// packages/cli/dist/repository-review.js
|
|
10150
10151
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
10151
10152
|
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";
|
|
10153
|
+
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
10154
|
import { createRequire as createRequire2 } from "node:module";
|
|
10154
10155
|
import { basename as basename2, dirname as dirname5, parse, resolve as resolve8, sep as sep4 } from "node:path";
|
|
10155
10156
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
@@ -10283,6 +10284,7 @@ var reviewSchemaPath = runtimeAssetPath("contracts/repository/v1/review.schema.j
|
|
|
10283
10284
|
var configName2 = ".graphrefly-stack.json";
|
|
10284
10285
|
var lockCandidates = ["pnpm-lock.yaml", "package-lock.json", "yarn.lock"];
|
|
10285
10286
|
var maxReviewCommits = 64;
|
|
10287
|
+
var maxEntrypointBytes = 64 * 1024;
|
|
10286
10288
|
var RepositoryReviewError = class extends Error {
|
|
10287
10289
|
code;
|
|
10288
10290
|
constructor(code, message) {
|
|
@@ -10365,6 +10367,22 @@ function ensureInside(root, candidate) {
|
|
|
10365
10367
|
throw new RepositoryReviewError("ENTRYPOINT_ESCAPE", "Blueprint entrypoint escapes the worktree");
|
|
10366
10368
|
}
|
|
10367
10369
|
}
|
|
10370
|
+
async function readConfiguredEntrypoint(repository, entrypointPath) {
|
|
10371
|
+
const entrypoint = resolve8(repository, entrypointPath);
|
|
10372
|
+
ensureInside(repository, entrypoint);
|
|
10373
|
+
let canonicalEntrypoint;
|
|
10374
|
+
try {
|
|
10375
|
+
canonicalEntrypoint = await realpath3(entrypoint);
|
|
10376
|
+
} catch {
|
|
10377
|
+
throw new RepositoryReviewError("ENTRYPOINT_MISSING", "Configured Blueprint entrypoint is missing");
|
|
10378
|
+
}
|
|
10379
|
+
ensureInside(repository, canonicalEntrypoint);
|
|
10380
|
+
const source = await readFile6(canonicalEntrypoint);
|
|
10381
|
+
if (source.byteLength > maxEntrypointBytes) {
|
|
10382
|
+
throw new RepositoryReviewError("ENTRYPOINT_TOO_LARGE", `Configured Blueprint entrypoint exceeds ${maxEntrypointBytes} bytes`);
|
|
10383
|
+
}
|
|
10384
|
+
return source;
|
|
10385
|
+
}
|
|
10368
10386
|
function containsAbsolutePath(value) {
|
|
10369
10387
|
if (typeof value === "string")
|
|
10370
10388
|
return value.startsWith("/") || /^[A-Za-z]:[\\/]/u.test(value);
|
|
@@ -10416,7 +10434,7 @@ async function resolveTargetRuntime(repository) {
|
|
|
10416
10434
|
diffGraphBlueprints: graphModule.diffGraphBlueprints
|
|
10417
10435
|
};
|
|
10418
10436
|
}
|
|
10419
|
-
async function executeBlueprint(repository, revision, entrypointPath, runtime) {
|
|
10437
|
+
async function executeBlueprint(repository, revision, entrypointPath, entrypointSource, runtime) {
|
|
10420
10438
|
const worktreeRoot = resolve8(dirname5(repository), `.graphrefly-stack-review-${basename2(repository)}-${process.pid}`);
|
|
10421
10439
|
const worktree = resolve8(worktreeRoot, revision.slice(0, 16));
|
|
10422
10440
|
await mkdir5(worktreeRoot, { recursive: true });
|
|
@@ -10429,8 +10447,19 @@ async function executeBlueprint(repository, revision, entrypointPath, runtime) {
|
|
|
10429
10447
|
try {
|
|
10430
10448
|
await access2(entrypoint);
|
|
10431
10449
|
} catch {
|
|
10432
|
-
|
|
10450
|
+
let canonicalParent;
|
|
10451
|
+
try {
|
|
10452
|
+
canonicalParent = await realpath3(dirname5(entrypoint));
|
|
10453
|
+
} catch {
|
|
10454
|
+
throw new RepositoryReviewError("ENTRYPOINT_MISSING", `Blueprint entrypoint parent is missing at ${revision.slice(0, 12)}`);
|
|
10455
|
+
}
|
|
10456
|
+
ensureInside(canonicalWorktree, canonicalParent);
|
|
10457
|
+
await writeFile5(resolve8(canonicalParent, basename2(entrypoint)), entrypointSource, {
|
|
10458
|
+
flag: "wx"
|
|
10459
|
+
});
|
|
10433
10460
|
}
|
|
10461
|
+
const canonicalEntrypoint = await realpath3(entrypoint);
|
|
10462
|
+
ensureInside(canonicalWorktree, canonicalEntrypoint);
|
|
10434
10463
|
const worktreeNodeModules = resolve8(canonicalWorktree, "node_modules");
|
|
10435
10464
|
await rm4(worktreeNodeModules, { recursive: true, force: true });
|
|
10436
10465
|
await symlink(runtime.nodeModulesRoot, worktreeNodeModules, "dir");
|
|
@@ -10439,7 +10468,7 @@ async function executeBlueprint(repository, revision, entrypointPath, runtime) {
|
|
|
10439
10468
|
`--allow-fs-read=${canonicalWorktree}`,
|
|
10440
10469
|
`--allow-fs-read=${runtime.nodeModulesRoot}`,
|
|
10441
10470
|
"--disable-warning=ExperimentalWarning",
|
|
10442
|
-
|
|
10471
|
+
canonicalEntrypoint
|
|
10443
10472
|
], {
|
|
10444
10473
|
cwd: canonicalWorktree,
|
|
10445
10474
|
encoding: "utf8",
|
|
@@ -10552,6 +10581,7 @@ async function createRepositoryReview(options) {
|
|
|
10552
10581
|
throw new RepositoryReviewError("REPOSITORY_INVALID", "Repository must be a local Git worktree");
|
|
10553
10582
|
}
|
|
10554
10583
|
const config = await readRepositoryConfig(repository);
|
|
10584
|
+
const entrypointSource = await readConfiguredEntrypoint(repository, config.blueprint.entrypoint);
|
|
10555
10585
|
const git2 = new SystemGitAdapter();
|
|
10556
10586
|
let baseOid;
|
|
10557
10587
|
let headOid;
|
|
@@ -10595,7 +10625,7 @@ async function createRepositoryReview(options) {
|
|
|
10595
10625
|
await validateDependencyContinuity(repository, allRevisions, runtime.version);
|
|
10596
10626
|
const evidence = [];
|
|
10597
10627
|
for (const revision of allRevisions) {
|
|
10598
|
-
const blueprint = await executeBlueprint(repository, revision, config.blueprint.entrypoint, runtime);
|
|
10628
|
+
const blueprint = await executeBlueprint(repository, revision, config.blueprint.entrypoint, entrypointSource, runtime);
|
|
10599
10629
|
evidence.push({
|
|
10600
10630
|
oid: revision,
|
|
10601
10631
|
subject: gitText(repository, ["show", "-s", "--format=%s", revision]),
|
|
@@ -11079,7 +11109,11 @@ ${help}`);
|
|
|
11079
11109
|
process.once("SIGTERM", close);
|
|
11080
11110
|
return 0;
|
|
11081
11111
|
}
|
|
11082
|
-
var entry =
|
|
11112
|
+
var entry = "";
|
|
11113
|
+
try {
|
|
11114
|
+
entry = process.argv[1] ? pathToFileURL3(realpathSync(process.argv[1])).href : "";
|
|
11115
|
+
} catch {
|
|
11116
|
+
}
|
|
11083
11117
|
if (import.meta.url === entry) {
|
|
11084
11118
|
runCli().then((code) => {
|
|
11085
11119
|
process.exitCode = code;
|