@emeryld/rrroutes-export 1.0.9 → 1.0.11
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 +4 -0
- package/dist/exportFinalizedLeaves.changelog.d.ts +7 -1
- package/dist/index.cjs +121 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +121 -17
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -72,11 +72,13 @@ Settings:
|
|
|
72
72
|
Behavior summary:
|
|
73
73
|
|
|
74
74
|
- Resolves commit path from `from..to` (chronological).
|
|
75
|
+
- Builds commit-aware module path candidates (current path + extension variants + rename history).
|
|
75
76
|
- Filters commits to those touching module tree/relevant config files.
|
|
76
77
|
- Ensures tip commit is always included.
|
|
77
78
|
- Creates a temp git worktree per selected commit.
|
|
78
79
|
- For TypeScript module entries, compiles the commit snapshot to JS and imports emitted output.
|
|
79
80
|
- For JavaScript module entries, imports directly from worktree.
|
|
81
|
+
- If module entrypoint cannot be resolved for a commit, changelog uses an empty snapshot for that commit (timeline continuity).
|
|
80
82
|
- Exports snapshots, then computes adjacent diffs:
|
|
81
83
|
- route events (`route_added`, `route_removed`, `schema_changed`, `cfg_changed`)
|
|
82
84
|
- source-object events (`source_object_added`, `source_object_removed`, `source_schema_changed`)
|
|
@@ -85,6 +87,7 @@ Runtime progress logs:
|
|
|
85
87
|
|
|
86
88
|
- `rrroutes-export-changelog` now prints step-by-step progress (window resolution, commit filtering, per-commit snapshot progress, diff totals, output writing, cleanup).
|
|
87
89
|
- Changelog logs include compile lifecycle details: selected tsconfig, cache hit/miss, emitted entry path.
|
|
90
|
+
- Changelog logs include per-commit module resolution and unresolved-entry fallback messages.
|
|
88
91
|
- Bundle script prints stage logs for snapshot export + changelog export.
|
|
89
92
|
|
|
90
93
|
Troubleshooting historical TS imports:
|
|
@@ -92,6 +95,7 @@ Troubleshooting historical TS imports:
|
|
|
92
95
|
- Changelog execution no longer relies on direct Node runtime loading of TS sources.
|
|
93
96
|
- Historical imports like `./x.js` pointing to `x.ts` are handled by snapshot compilation.
|
|
94
97
|
- If tsconfig auto-discovery fails, pass `--tsconfig`.
|
|
98
|
+
- If entrypoint path moved across history, changelog resolves rename history automatically.
|
|
95
99
|
|
|
96
100
|
## Recommended end-to-end script
|
|
97
101
|
|
|
@@ -32,6 +32,7 @@ type CommitSnapshot = {
|
|
|
32
32
|
commit: ChangelogCommit;
|
|
33
33
|
routesByKey: Record<string, RouteSnapshot>;
|
|
34
34
|
sourceObjectsById: Record<string, SourceObjectSnapshot>;
|
|
35
|
+
unresolvedModule?: boolean;
|
|
35
36
|
};
|
|
36
37
|
type DiffOp = 'added' | 'removed' | 'changed';
|
|
37
38
|
export type SchemaPathDelta = {
|
|
@@ -96,6 +97,7 @@ export type FinalizedLeavesChangelogExport = {
|
|
|
96
97
|
from: string;
|
|
97
98
|
to: string;
|
|
98
99
|
selectedCommitCount: number;
|
|
100
|
+
unresolvedModuleCommits?: string[];
|
|
99
101
|
};
|
|
100
102
|
commits: ChangelogCommit[];
|
|
101
103
|
byRoute: Record<string, RouteChangeEvent[]>;
|
|
@@ -123,7 +125,9 @@ declare function resolveCommitWindow(cwd: string, from?: string, to?: string): P
|
|
|
123
125
|
to: string;
|
|
124
126
|
}>;
|
|
125
127
|
declare function resolveCommitPath(cwd: string, fromCommit: string, toCommit: string): Promise<string[]>;
|
|
126
|
-
declare function
|
|
128
|
+
declare function buildModulePathCandidates(repoRoot: string, toCommit: string, requestedModuleRel: string): Promise<string[]>;
|
|
129
|
+
declare function resolveModulePathForCommit(repoRoot: string, commitSha: string, candidates: readonly string[]): Promise<string | undefined>;
|
|
130
|
+
declare function filterCommits(cwd: string, commits: string[], moduleCandidates: readonly string[], tsconfigRel?: string): Promise<string[]>;
|
|
127
131
|
declare function buildSourceIdentity(section: ChangelogSchemaSection, value: Record<string, unknown>): SourceIdentity;
|
|
128
132
|
declare function toRouteSnapshots(payload: FinalizedLeavesExport): Record<string, RouteSnapshot>;
|
|
129
133
|
declare function toSourceObjectSnapshots(routesByKey: Record<string, RouteSnapshot>): Record<string, SourceObjectSnapshot>;
|
|
@@ -160,6 +164,8 @@ export declare const __private: {
|
|
|
160
164
|
resolveCommitWindow: typeof resolveCommitWindow;
|
|
161
165
|
resolveCommitPath: typeof resolveCommitPath;
|
|
162
166
|
filterCommits: typeof filterCommits;
|
|
167
|
+
buildModulePathCandidates: typeof buildModulePathCandidates;
|
|
168
|
+
resolveModulePathForCommit: typeof resolveModulePathForCommit;
|
|
163
169
|
resolveSnapshotTsconfig: typeof resolveSnapshotTsconfig;
|
|
164
170
|
toEmittedModulePath: typeof toEmittedModulePath;
|
|
165
171
|
buildCompileCacheKey: typeof buildCompileCacheKey;
|
package/dist/index.cjs
CHANGED
|
@@ -1411,6 +1411,7 @@ var CHANGESET_CFG_FIELDS = [
|
|
|
1411
1411
|
"feed"
|
|
1412
1412
|
];
|
|
1413
1413
|
var SCHEMA_SECTIONS = ["params", "query", "body", "output"];
|
|
1414
|
+
var MODULE_EXTENSIONS = [".ts", ".tsx", ".mts", ".cts", ".js", ".mjs", ".cjs"];
|
|
1414
1415
|
var SOURCE_KEY_BY_SECTION = {
|
|
1415
1416
|
params: "paramsSchema",
|
|
1416
1417
|
query: "querySchema",
|
|
@@ -1525,6 +1526,65 @@ async function resolveCommitPath(cwd, fromCommit, toCommit) {
|
|
|
1525
1526
|
const commits = pathRaw.split("\n").map((item) => item.trim()).filter(Boolean);
|
|
1526
1527
|
return [fromCommit, ...commits];
|
|
1527
1528
|
}
|
|
1529
|
+
function modulePathStem(modulePath) {
|
|
1530
|
+
const normalized = normalizePath(modulePath).replace(/^\/+/, "");
|
|
1531
|
+
for (const ext of MODULE_EXTENSIONS) {
|
|
1532
|
+
if (normalized.endsWith(ext)) {
|
|
1533
|
+
return normalized.slice(0, -ext.length);
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
return normalized;
|
|
1537
|
+
}
|
|
1538
|
+
function extensionVariants(pathLike) {
|
|
1539
|
+
const stem = modulePathStem(pathLike);
|
|
1540
|
+
return MODULE_EXTENSIONS.map((ext) => `${stem}${ext}`);
|
|
1541
|
+
}
|
|
1542
|
+
async function buildModulePathCandidates(repoRoot, toCommit, requestedModuleRel) {
|
|
1543
|
+
const requested = normalizePath(requestedModuleRel).replace(/^\/+/, "");
|
|
1544
|
+
const out = [];
|
|
1545
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1546
|
+
const pushCandidate = (value) => {
|
|
1547
|
+
const normalized = normalizePath(value).replace(/^\/+/, "");
|
|
1548
|
+
if (!normalized) return;
|
|
1549
|
+
if (seen.has(normalized)) return;
|
|
1550
|
+
seen.add(normalized);
|
|
1551
|
+
out.push(normalized);
|
|
1552
|
+
};
|
|
1553
|
+
pushCandidate(requested);
|
|
1554
|
+
extensionVariants(requested).forEach(pushCandidate);
|
|
1555
|
+
const history = await runGit(repoRoot, [
|
|
1556
|
+
"log",
|
|
1557
|
+
"--follow",
|
|
1558
|
+
"--name-only",
|
|
1559
|
+
"--format=",
|
|
1560
|
+
toCommit,
|
|
1561
|
+
"--",
|
|
1562
|
+
requested
|
|
1563
|
+
]);
|
|
1564
|
+
history.split("\n").map((item) => item.trim()).filter(Boolean).forEach((candidate) => {
|
|
1565
|
+
pushCandidate(candidate);
|
|
1566
|
+
extensionVariants(candidate).forEach(pushCandidate);
|
|
1567
|
+
});
|
|
1568
|
+
return out;
|
|
1569
|
+
}
|
|
1570
|
+
async function commitHasPath(repoRoot, commitSha, candidatePath) {
|
|
1571
|
+
try {
|
|
1572
|
+
await execFile("git", ["cat-file", "-e", `${commitSha}:${candidatePath}`], {
|
|
1573
|
+
cwd: repoRoot
|
|
1574
|
+
});
|
|
1575
|
+
return true;
|
|
1576
|
+
} catch {
|
|
1577
|
+
return false;
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
async function resolveModulePathForCommit(repoRoot, commitSha, candidates) {
|
|
1581
|
+
for (const candidate of candidates) {
|
|
1582
|
+
if (await commitHasPath(repoRoot, commitSha, candidate)) {
|
|
1583
|
+
return candidate;
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
return void 0;
|
|
1587
|
+
}
|
|
1528
1588
|
function parentDirectories(relativePath) {
|
|
1529
1589
|
const clean = normalizePath(relativePath).replace(/^\/+/, "");
|
|
1530
1590
|
const dir = import_node_path4.default.posix.dirname(clean);
|
|
@@ -1536,8 +1596,11 @@ function parentDirectories(relativePath) {
|
|
|
1536
1596
|
}
|
|
1537
1597
|
return out;
|
|
1538
1598
|
}
|
|
1539
|
-
function buildRelevantConfigFiles(
|
|
1540
|
-
const dirs = new Set(
|
|
1599
|
+
function buildRelevantConfigFiles(moduleCandidates, tsconfigRel) {
|
|
1600
|
+
const dirs = /* @__PURE__ */ new Set();
|
|
1601
|
+
for (const moduleRel of moduleCandidates) {
|
|
1602
|
+
parentDirectories(moduleRel).forEach((item) => dirs.add(item));
|
|
1603
|
+
}
|
|
1541
1604
|
if (tsconfigRel) {
|
|
1542
1605
|
parentDirectories(tsconfigRel).forEach((item) => dirs.add(item));
|
|
1543
1606
|
dirs.add(import_node_path4.default.posix.dirname(normalizePath(tsconfigRel)));
|
|
@@ -1550,7 +1613,7 @@ function buildRelevantConfigFiles(moduleRel, tsconfigRel) {
|
|
|
1550
1613
|
}
|
|
1551
1614
|
return files;
|
|
1552
1615
|
}
|
|
1553
|
-
async function commitTouchedRelevantPaths(cwd, commit,
|
|
1616
|
+
async function commitTouchedRelevantPaths(cwd, commit, moduleCandidates, tsconfigRel) {
|
|
1554
1617
|
const changed = await runGit(cwd, [
|
|
1555
1618
|
"show",
|
|
1556
1619
|
"--pretty=format:",
|
|
@@ -1559,27 +1622,35 @@ async function commitTouchedRelevantPaths(cwd, commit, moduleRel, tsconfigRel) {
|
|
|
1559
1622
|
commit
|
|
1560
1623
|
]);
|
|
1561
1624
|
const changedFiles = changed.split("\n").map((item) => normalizePath(item.trim()).replace(/^\/+/, "")).filter(Boolean);
|
|
1562
|
-
const
|
|
1563
|
-
|
|
1625
|
+
const moduleFiles = Array.from(
|
|
1626
|
+
new Set(moduleCandidates.map((item) => normalizePath(item).replace(/^\/+/, "")))
|
|
1627
|
+
);
|
|
1628
|
+
const moduleDirs = Array.from(
|
|
1629
|
+
new Set(
|
|
1630
|
+
moduleFiles.map((item) => normalizePath(import_node_path4.default.posix.dirname(item)).replace(/^\/+/, "")).filter((item) => item && item !== ".")
|
|
1631
|
+
)
|
|
1632
|
+
);
|
|
1564
1633
|
const tsconfigFile = tsconfigRel ? normalizePath(tsconfigRel).replace(/^\/+/, "") : void 0;
|
|
1565
|
-
const configFiles = buildRelevantConfigFiles(
|
|
1634
|
+
const configFiles = buildRelevantConfigFiles(moduleFiles, tsconfigFile);
|
|
1566
1635
|
return changedFiles.some((file) => {
|
|
1567
|
-
if (file
|
|
1568
|
-
|
|
1569
|
-
|
|
1636
|
+
if (moduleFiles.includes(file)) return true;
|
|
1637
|
+
for (const moduleDir of moduleDirs) {
|
|
1638
|
+
if (file === moduleDir || file.startsWith(`${moduleDir}/`)) {
|
|
1639
|
+
return true;
|
|
1640
|
+
}
|
|
1570
1641
|
}
|
|
1571
1642
|
if (tsconfigFile && file === tsconfigFile) return true;
|
|
1572
1643
|
return configFiles.has(file);
|
|
1573
1644
|
});
|
|
1574
1645
|
}
|
|
1575
|
-
async function filterCommits(cwd, commits,
|
|
1646
|
+
async function filterCommits(cwd, commits, moduleCandidates, tsconfigRel) {
|
|
1576
1647
|
if (commits.length <= 1) {
|
|
1577
1648
|
return commits;
|
|
1578
1649
|
}
|
|
1579
1650
|
const keep = [commits[0]];
|
|
1580
1651
|
for (let i = 1; i < commits.length; i += 1) {
|
|
1581
1652
|
const commit = commits[i];
|
|
1582
|
-
if (await commitTouchedRelevantPaths(cwd, commit,
|
|
1653
|
+
if (await commitTouchedRelevantPaths(cwd, commit, moduleCandidates, tsconfigRel)) {
|
|
1583
1654
|
keep.push(commit);
|
|
1584
1655
|
}
|
|
1585
1656
|
}
|
|
@@ -2013,6 +2084,7 @@ async function compileSnapshotEntry(options) {
|
|
|
2013
2084
|
declarationMap: false,
|
|
2014
2085
|
sourceMap: false,
|
|
2015
2086
|
inlineSourceMap: false,
|
|
2087
|
+
inlineSources: false,
|
|
2016
2088
|
composite: false,
|
|
2017
2089
|
incremental: false,
|
|
2018
2090
|
tsBuildInfoFile: void 0,
|
|
@@ -2045,12 +2117,31 @@ ${message}`
|
|
|
2045
2117
|
async function loadSnapshotExport(options) {
|
|
2046
2118
|
return loadChangelogInput(options.entryPath, options.exportName);
|
|
2047
2119
|
}
|
|
2048
|
-
async function createSnapshot(repoRoot,
|
|
2120
|
+
async function createSnapshot(repoRoot, moduleCandidates, exportName, commit, tempRoot, tsconfigRel, exportOptions, log) {
|
|
2049
2121
|
const worktreeDir = import_node_path4.default.join(tempRoot, `wt-${commit.sha.slice(0, 12)}`);
|
|
2050
2122
|
await runGit(repoRoot, ["worktree", "add", "--detach", worktreeDir, commit.sha]);
|
|
2051
2123
|
try {
|
|
2052
2124
|
await ensureWorktreeDependencies(repoRoot, worktreeDir);
|
|
2053
|
-
const
|
|
2125
|
+
const resolvedModuleRel = await resolveModulePathForCommit(
|
|
2126
|
+
repoRoot,
|
|
2127
|
+
commit.sha,
|
|
2128
|
+
moduleCandidates
|
|
2129
|
+
);
|
|
2130
|
+
if (!resolvedModuleRel) {
|
|
2131
|
+
log?.(
|
|
2132
|
+
`[changelog] unresolved module for commit ${commit.sha.slice(0, 12)}; using empty snapshot`
|
|
2133
|
+
);
|
|
2134
|
+
return {
|
|
2135
|
+
commit,
|
|
2136
|
+
routesByKey: {},
|
|
2137
|
+
sourceObjectsById: {},
|
|
2138
|
+
unresolvedModule: true
|
|
2139
|
+
};
|
|
2140
|
+
}
|
|
2141
|
+
log?.(
|
|
2142
|
+
`[changelog] resolved module for commit ${commit.sha.slice(0, 12)}: ${resolvedModuleRel}`
|
|
2143
|
+
);
|
|
2144
|
+
const modulePath = import_node_path4.default.resolve(worktreeDir, resolvedModuleRel);
|
|
2054
2145
|
let snapshotRuntimePath = modulePath;
|
|
2055
2146
|
let resolvedTsconfigPath;
|
|
2056
2147
|
if (isTypeScriptModule(modulePath)) {
|
|
@@ -2065,7 +2156,7 @@ async function createSnapshot(repoRoot, moduleRel, exportName, commit, tempRoot,
|
|
|
2065
2156
|
);
|
|
2066
2157
|
snapshotRuntimePath = await compileSnapshotEntry({
|
|
2067
2158
|
worktreeDir,
|
|
2068
|
-
moduleRel,
|
|
2159
|
+
moduleRel: resolvedModuleRel,
|
|
2069
2160
|
modulePath,
|
|
2070
2161
|
tsconfigPath: resolvedTsconfigPath,
|
|
2071
2162
|
commitSha: commit.sha,
|
|
@@ -2322,12 +2413,18 @@ async function exportFinalizedLeavesChangelog(options) {
|
|
|
2322
2413
|
log("[changelog] resolving commit window");
|
|
2323
2414
|
const window = await resolveCommitWindow(repoRoot, options.from, options.to);
|
|
2324
2415
|
log(`[changelog] window: ${window.from.slice(0, 12)}..${window.to.slice(0, 12)}`);
|
|
2416
|
+
const moduleCandidates = await buildModulePathCandidates(
|
|
2417
|
+
repoRoot,
|
|
2418
|
+
window.to,
|
|
2419
|
+
modulePathRelative
|
|
2420
|
+
);
|
|
2421
|
+
log(`[changelog] module candidates discovered: ${moduleCandidates.length}`);
|
|
2325
2422
|
const allCommits = await resolveCommitPath(repoRoot, window.from, window.to);
|
|
2326
2423
|
log(`[changelog] commits in ancestry path: ${allCommits.length}`);
|
|
2327
2424
|
const selectedCommitShas = await filterCommits(
|
|
2328
2425
|
repoRoot,
|
|
2329
2426
|
allCommits,
|
|
2330
|
-
|
|
2427
|
+
moduleCandidates,
|
|
2331
2428
|
tsconfigRelative
|
|
2332
2429
|
);
|
|
2333
2430
|
log(`[changelog] commits after path filter: ${selectedCommitShas.length}`);
|
|
@@ -2344,6 +2441,7 @@ async function exportFinalizedLeavesChangelog(options) {
|
|
|
2344
2441
|
log(`[changelog] temp workspace: ${tempRoot}`);
|
|
2345
2442
|
try {
|
|
2346
2443
|
const snapshots = [];
|
|
2444
|
+
const unresolvedModuleCommits = [];
|
|
2347
2445
|
for (let index = 0; index < commits.length; index += 1) {
|
|
2348
2446
|
const commit = commits[index];
|
|
2349
2447
|
log(
|
|
@@ -2352,7 +2450,7 @@ async function exportFinalizedLeavesChangelog(options) {
|
|
|
2352
2450
|
snapshots.push(
|
|
2353
2451
|
await createSnapshot(
|
|
2354
2452
|
repoRoot,
|
|
2355
|
-
|
|
2453
|
+
moduleCandidates,
|
|
2356
2454
|
exportName,
|
|
2357
2455
|
commit,
|
|
2358
2456
|
tempRoot,
|
|
@@ -2361,6 +2459,9 @@ async function exportFinalizedLeavesChangelog(options) {
|
|
|
2361
2459
|
log
|
|
2362
2460
|
)
|
|
2363
2461
|
);
|
|
2462
|
+
if (snapshots[snapshots.length - 1]?.unresolvedModule) {
|
|
2463
|
+
unresolvedModuleCommits.push(commit.sha);
|
|
2464
|
+
}
|
|
2364
2465
|
}
|
|
2365
2466
|
const routeEvents = [];
|
|
2366
2467
|
const sourceEvents = [];
|
|
@@ -2385,7 +2486,8 @@ async function exportFinalizedLeavesChangelog(options) {
|
|
|
2385
2486
|
exportName,
|
|
2386
2487
|
from: window.from,
|
|
2387
2488
|
to: window.to,
|
|
2388
|
-
selectedCommitCount: commits.length
|
|
2489
|
+
selectedCommitCount: commits.length,
|
|
2490
|
+
unresolvedModuleCommits: unresolvedModuleCommits.length > 0 ? unresolvedModuleCommits : void 0
|
|
2389
2491
|
},
|
|
2390
2492
|
commits,
|
|
2391
2493
|
byRoute: routeRecordByKey(routeEvents),
|
|
@@ -2412,6 +2514,8 @@ var __private = {
|
|
|
2412
2514
|
resolveCommitWindow,
|
|
2413
2515
|
resolveCommitPath,
|
|
2414
2516
|
filterCommits,
|
|
2517
|
+
buildModulePathCandidates,
|
|
2518
|
+
resolveModulePathForCommit,
|
|
2415
2519
|
resolveSnapshotTsconfig,
|
|
2416
2520
|
toEmittedModulePath,
|
|
2417
2521
|
buildCompileCacheKey,
|