@emeryld/rrroutes-export 1.0.8 → 1.0.10
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 +20 -0
- package/dist/exportFinalizedLeaves.changelog.cli.d.ts +2 -0
- package/dist/exportFinalizedLeaves.changelog.d.ts +34 -1
- package/dist/index.cjs +320 -84
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +320 -84
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1340,9 +1340,11 @@ async function runExportFinalizedLeavesCli(argv) {
|
|
|
1340
1340
|
import fs2 from "fs/promises";
|
|
1341
1341
|
import os from "os";
|
|
1342
1342
|
import path4 from "path";
|
|
1343
|
+
import crypto from "crypto";
|
|
1343
1344
|
import { execFile as execFileCallback, spawn as spawn2 } from "child_process";
|
|
1344
1345
|
import { promisify } from "util";
|
|
1345
1346
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
1347
|
+
import ts2 from "typescript";
|
|
1346
1348
|
var execFile = promisify(execFileCallback);
|
|
1347
1349
|
var CHANGESET_CFG_FIELDS = [
|
|
1348
1350
|
"summary",
|
|
@@ -1355,6 +1357,7 @@ var CHANGESET_CFG_FIELDS = [
|
|
|
1355
1357
|
"feed"
|
|
1356
1358
|
];
|
|
1357
1359
|
var SCHEMA_SECTIONS = ["params", "query", "body", "output"];
|
|
1360
|
+
var MODULE_EXTENSIONS = [".ts", ".tsx", ".mts", ".cts", ".js", ".mjs", ".cjs"];
|
|
1358
1361
|
var SOURCE_KEY_BY_SECTION = {
|
|
1359
1362
|
params: "paramsSchema",
|
|
1360
1363
|
query: "querySchema",
|
|
@@ -1469,6 +1472,65 @@ async function resolveCommitPath(cwd, fromCommit, toCommit) {
|
|
|
1469
1472
|
const commits = pathRaw.split("\n").map((item) => item.trim()).filter(Boolean);
|
|
1470
1473
|
return [fromCommit, ...commits];
|
|
1471
1474
|
}
|
|
1475
|
+
function modulePathStem(modulePath) {
|
|
1476
|
+
const normalized = normalizePath(modulePath).replace(/^\/+/, "");
|
|
1477
|
+
for (const ext of MODULE_EXTENSIONS) {
|
|
1478
|
+
if (normalized.endsWith(ext)) {
|
|
1479
|
+
return normalized.slice(0, -ext.length);
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
return normalized;
|
|
1483
|
+
}
|
|
1484
|
+
function extensionVariants(pathLike) {
|
|
1485
|
+
const stem = modulePathStem(pathLike);
|
|
1486
|
+
return MODULE_EXTENSIONS.map((ext) => `${stem}${ext}`);
|
|
1487
|
+
}
|
|
1488
|
+
async function buildModulePathCandidates(repoRoot, toCommit, requestedModuleRel) {
|
|
1489
|
+
const requested = normalizePath(requestedModuleRel).replace(/^\/+/, "");
|
|
1490
|
+
const out = [];
|
|
1491
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1492
|
+
const pushCandidate = (value) => {
|
|
1493
|
+
const normalized = normalizePath(value).replace(/^\/+/, "");
|
|
1494
|
+
if (!normalized) return;
|
|
1495
|
+
if (seen.has(normalized)) return;
|
|
1496
|
+
seen.add(normalized);
|
|
1497
|
+
out.push(normalized);
|
|
1498
|
+
};
|
|
1499
|
+
pushCandidate(requested);
|
|
1500
|
+
extensionVariants(requested).forEach(pushCandidate);
|
|
1501
|
+
const history = await runGit(repoRoot, [
|
|
1502
|
+
"log",
|
|
1503
|
+
"--follow",
|
|
1504
|
+
"--name-only",
|
|
1505
|
+
"--format=",
|
|
1506
|
+
toCommit,
|
|
1507
|
+
"--",
|
|
1508
|
+
requested
|
|
1509
|
+
]);
|
|
1510
|
+
history.split("\n").map((item) => item.trim()).filter(Boolean).forEach((candidate) => {
|
|
1511
|
+
pushCandidate(candidate);
|
|
1512
|
+
extensionVariants(candidate).forEach(pushCandidate);
|
|
1513
|
+
});
|
|
1514
|
+
return out;
|
|
1515
|
+
}
|
|
1516
|
+
async function commitHasPath(repoRoot, commitSha, candidatePath) {
|
|
1517
|
+
try {
|
|
1518
|
+
await execFile("git", ["cat-file", "-e", `${commitSha}:${candidatePath}`], {
|
|
1519
|
+
cwd: repoRoot
|
|
1520
|
+
});
|
|
1521
|
+
return true;
|
|
1522
|
+
} catch {
|
|
1523
|
+
return false;
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
async function resolveModulePathForCommit(repoRoot, commitSha, candidates) {
|
|
1527
|
+
for (const candidate of candidates) {
|
|
1528
|
+
if (await commitHasPath(repoRoot, commitSha, candidate)) {
|
|
1529
|
+
return candidate;
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
return void 0;
|
|
1533
|
+
}
|
|
1472
1534
|
function parentDirectories(relativePath) {
|
|
1473
1535
|
const clean = normalizePath(relativePath).replace(/^\/+/, "");
|
|
1474
1536
|
const dir = path4.posix.dirname(clean);
|
|
@@ -1480,8 +1542,11 @@ function parentDirectories(relativePath) {
|
|
|
1480
1542
|
}
|
|
1481
1543
|
return out;
|
|
1482
1544
|
}
|
|
1483
|
-
function buildRelevantConfigFiles(
|
|
1484
|
-
const dirs = new Set(
|
|
1545
|
+
function buildRelevantConfigFiles(moduleCandidates, tsconfigRel) {
|
|
1546
|
+
const dirs = /* @__PURE__ */ new Set();
|
|
1547
|
+
for (const moduleRel of moduleCandidates) {
|
|
1548
|
+
parentDirectories(moduleRel).forEach((item) => dirs.add(item));
|
|
1549
|
+
}
|
|
1485
1550
|
if (tsconfigRel) {
|
|
1486
1551
|
parentDirectories(tsconfigRel).forEach((item) => dirs.add(item));
|
|
1487
1552
|
dirs.add(path4.posix.dirname(normalizePath(tsconfigRel)));
|
|
@@ -1494,7 +1559,7 @@ function buildRelevantConfigFiles(moduleRel, tsconfigRel) {
|
|
|
1494
1559
|
}
|
|
1495
1560
|
return files;
|
|
1496
1561
|
}
|
|
1497
|
-
async function commitTouchedRelevantPaths(cwd, commit,
|
|
1562
|
+
async function commitTouchedRelevantPaths(cwd, commit, moduleCandidates, tsconfigRel) {
|
|
1498
1563
|
const changed = await runGit(cwd, [
|
|
1499
1564
|
"show",
|
|
1500
1565
|
"--pretty=format:",
|
|
@@ -1503,27 +1568,35 @@ async function commitTouchedRelevantPaths(cwd, commit, moduleRel, tsconfigRel) {
|
|
|
1503
1568
|
commit
|
|
1504
1569
|
]);
|
|
1505
1570
|
const changedFiles = changed.split("\n").map((item) => normalizePath(item.trim()).replace(/^\/+/, "")).filter(Boolean);
|
|
1506
|
-
const
|
|
1507
|
-
|
|
1571
|
+
const moduleFiles = Array.from(
|
|
1572
|
+
new Set(moduleCandidates.map((item) => normalizePath(item).replace(/^\/+/, "")))
|
|
1573
|
+
);
|
|
1574
|
+
const moduleDirs = Array.from(
|
|
1575
|
+
new Set(
|
|
1576
|
+
moduleFiles.map((item) => normalizePath(path4.posix.dirname(item)).replace(/^\/+/, "")).filter((item) => item && item !== ".")
|
|
1577
|
+
)
|
|
1578
|
+
);
|
|
1508
1579
|
const tsconfigFile = tsconfigRel ? normalizePath(tsconfigRel).replace(/^\/+/, "") : void 0;
|
|
1509
|
-
const configFiles = buildRelevantConfigFiles(
|
|
1580
|
+
const configFiles = buildRelevantConfigFiles(moduleFiles, tsconfigFile);
|
|
1510
1581
|
return changedFiles.some((file) => {
|
|
1511
|
-
if (file
|
|
1512
|
-
|
|
1513
|
-
|
|
1582
|
+
if (moduleFiles.includes(file)) return true;
|
|
1583
|
+
for (const moduleDir of moduleDirs) {
|
|
1584
|
+
if (file === moduleDir || file.startsWith(`${moduleDir}/`)) {
|
|
1585
|
+
return true;
|
|
1586
|
+
}
|
|
1514
1587
|
}
|
|
1515
1588
|
if (tsconfigFile && file === tsconfigFile) return true;
|
|
1516
1589
|
return configFiles.has(file);
|
|
1517
1590
|
});
|
|
1518
1591
|
}
|
|
1519
|
-
async function filterCommits(cwd, commits,
|
|
1592
|
+
async function filterCommits(cwd, commits, moduleCandidates, tsconfigRel) {
|
|
1520
1593
|
if (commits.length <= 1) {
|
|
1521
1594
|
return commits;
|
|
1522
1595
|
}
|
|
1523
1596
|
const keep = [commits[0]];
|
|
1524
1597
|
for (let i = 1; i < commits.length; i += 1) {
|
|
1525
1598
|
const commit = commits[i];
|
|
1526
|
-
if (await commitTouchedRelevantPaths(cwd, commit,
|
|
1599
|
+
if (await commitTouchedRelevantPaths(cwd, commit, moduleCandidates, tsconfigRel)) {
|
|
1527
1600
|
keep.push(commit);
|
|
1528
1601
|
}
|
|
1529
1602
|
}
|
|
@@ -1825,96 +1898,232 @@ async function pathExists(filePath) {
|
|
|
1825
1898
|
return false;
|
|
1826
1899
|
}
|
|
1827
1900
|
}
|
|
1828
|
-
|
|
1829
|
-
const
|
|
1830
|
-
|
|
1831
|
-
|
|
1901
|
+
function isTypeScriptModule(modulePath) {
|
|
1902
|
+
const ext = path4.extname(modulePath).toLowerCase();
|
|
1903
|
+
return ext === ".ts" || ext === ".tsx" || ext === ".mts" || ext === ".cts";
|
|
1904
|
+
}
|
|
1905
|
+
function isJavaScriptModule(modulePath) {
|
|
1906
|
+
const ext = path4.extname(modulePath).toLowerCase();
|
|
1907
|
+
return ext === ".js" || ext === ".mjs" || ext === ".cjs";
|
|
1908
|
+
}
|
|
1909
|
+
async function resolveSnapshotTsconfig(worktreeDir, modulePath, tsconfigOverride) {
|
|
1910
|
+
if (tsconfigOverride) {
|
|
1911
|
+
const resolved = path4.resolve(worktreeDir, tsconfigOverride);
|
|
1912
|
+
if (!await pathExists(resolved)) {
|
|
1913
|
+
throw new Error(`tsconfig not found: ${resolved}`);
|
|
1914
|
+
}
|
|
1915
|
+
return resolved;
|
|
1916
|
+
}
|
|
1917
|
+
let current = path4.dirname(modulePath);
|
|
1918
|
+
const normalizedRoot = normalizePath(path4.resolve(worktreeDir));
|
|
1919
|
+
while (true) {
|
|
1920
|
+
const candidate = path4.join(current, "tsconfig.json");
|
|
1921
|
+
if (await pathExists(candidate)) {
|
|
1922
|
+
return candidate;
|
|
1923
|
+
}
|
|
1924
|
+
const parent = path4.dirname(current);
|
|
1925
|
+
if (parent === current) break;
|
|
1926
|
+
if (!normalizePath(parent).startsWith(normalizedRoot)) break;
|
|
1927
|
+
current = parent;
|
|
1928
|
+
}
|
|
1929
|
+
throw new Error(
|
|
1930
|
+
`Unable to resolve tsconfig for TypeScript module: ${modulePath}. Pass --tsconfig to override.`
|
|
1931
|
+
);
|
|
1932
|
+
}
|
|
1933
|
+
function toEmittedModulePath(moduleRel) {
|
|
1934
|
+
const normalized = normalizePath(moduleRel);
|
|
1935
|
+
if (normalized.endsWith(".mts")) return normalized.slice(0, -4) + ".mjs";
|
|
1936
|
+
if (normalized.endsWith(".cts")) return normalized.slice(0, -4) + ".cjs";
|
|
1937
|
+
if (normalized.endsWith(".tsx")) return normalized.slice(0, -4) + ".js";
|
|
1938
|
+
if (normalized.endsWith(".ts")) return normalized.slice(0, -3) + ".js";
|
|
1939
|
+
return normalized;
|
|
1940
|
+
}
|
|
1941
|
+
function buildCompileCacheKey(commitSha, moduleRel, tsconfigPath, tsconfigStat) {
|
|
1942
|
+
return crypto.createHash("sha1").update(commitSha).update("\n").update(normalizePath(moduleRel)).update("\n").update(normalizePath(tsconfigPath)).update("\n").update(String(tsconfigStat.mtimeMs)).update("\n").update(String(tsconfigStat.size)).digest("hex");
|
|
1943
|
+
}
|
|
1944
|
+
async function collectFilesRecursive(rootDir) {
|
|
1945
|
+
const files = [];
|
|
1832
1946
|
const walk = async (dir) => {
|
|
1833
1947
|
const entries = await fs2.readdir(dir, { withFileTypes: true });
|
|
1834
1948
|
for (const entry of entries) {
|
|
1949
|
+
const target = path4.join(dir, entry.name);
|
|
1835
1950
|
if (entry.isDirectory()) {
|
|
1836
|
-
|
|
1837
|
-
await walk(path4.join(dir, entry.name));
|
|
1951
|
+
await walk(target);
|
|
1838
1952
|
continue;
|
|
1839
1953
|
}
|
|
1840
|
-
if (
|
|
1841
|
-
|
|
1842
|
-
filesToScan.push(path4.join(dir, entry.name));
|
|
1843
|
-
}
|
|
1844
|
-
};
|
|
1845
|
-
await walk(worktreeDir);
|
|
1846
|
-
const importRegexes = [
|
|
1847
|
-
/\\bfrom\\s+['\"](\\.[^'\"]+\\.js)['\"]/g,
|
|
1848
|
-
/\\bimport\\(\\s*['\"](\\.[^'\"]+\\.js)['\"]\\s*\\)/g,
|
|
1849
|
-
/\\brequire\\(\\s*['\"](\\.[^'\"]+\\.js)['\"]\\s*\\)/g
|
|
1850
|
-
];
|
|
1851
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1852
|
-
for (const filePath of filesToScan) {
|
|
1853
|
-
const content = await fs2.readFile(filePath, "utf8");
|
|
1854
|
-
for (const regex of importRegexes) {
|
|
1855
|
-
regex.lastIndex = 0;
|
|
1856
|
-
let match = regex.exec(content);
|
|
1857
|
-
while (match) {
|
|
1858
|
-
const specifier = match[1];
|
|
1859
|
-
const resolvedJs = path4.resolve(path4.dirname(filePath), specifier);
|
|
1860
|
-
if (seen.has(resolvedJs)) {
|
|
1861
|
-
match = regex.exec(content);
|
|
1862
|
-
continue;
|
|
1863
|
-
}
|
|
1864
|
-
seen.add(resolvedJs);
|
|
1865
|
-
if (await pathExists(resolvedJs)) {
|
|
1866
|
-
match = regex.exec(content);
|
|
1867
|
-
continue;
|
|
1868
|
-
}
|
|
1869
|
-
const tsCandidates = [
|
|
1870
|
-
resolvedJs.replace(/\\.js$/, ".ts"),
|
|
1871
|
-
resolvedJs.replace(/\\.js$/, ".mts"),
|
|
1872
|
-
resolvedJs.replace(/\\.js$/, ".tsx")
|
|
1873
|
-
];
|
|
1874
|
-
let targetTs;
|
|
1875
|
-
for (const candidate of tsCandidates) {
|
|
1876
|
-
if (await pathExists(candidate)) {
|
|
1877
|
-
targetTs = candidate;
|
|
1878
|
-
break;
|
|
1879
|
-
}
|
|
1880
|
-
}
|
|
1881
|
-
if (targetTs) {
|
|
1882
|
-
const relImport = normalizePath(path4.relative(path4.dirname(resolvedJs), targetTs));
|
|
1883
|
-
const importPath = relImport.startsWith(".") ? relImport : `./${relImport}`;
|
|
1884
|
-
const shim = `export * from '${importPath}'
|
|
1885
|
-
import * as __all from '${importPath}'
|
|
1886
|
-
export default ('default' in __all ? __all.default : __all)
|
|
1887
|
-
`;
|
|
1888
|
-
await fs2.mkdir(path4.dirname(resolvedJs), { recursive: true });
|
|
1889
|
-
await fs2.writeFile(resolvedJs, shim, "utf8");
|
|
1890
|
-
shimWrites.push(resolvedJs);
|
|
1891
|
-
}
|
|
1892
|
-
match = regex.exec(content);
|
|
1954
|
+
if (entry.isFile()) {
|
|
1955
|
+
files.push(target);
|
|
1893
1956
|
}
|
|
1894
1957
|
}
|
|
1958
|
+
};
|
|
1959
|
+
if (await pathExists(rootDir)) {
|
|
1960
|
+
await walk(rootDir);
|
|
1961
|
+
}
|
|
1962
|
+
return files;
|
|
1963
|
+
}
|
|
1964
|
+
function suffixMatchScore(candidate, wanted) {
|
|
1965
|
+
const left = normalizePath(candidate).split("/");
|
|
1966
|
+
const right = normalizePath(wanted).split("/");
|
|
1967
|
+
let score = 0;
|
|
1968
|
+
while (score < left.length && score < right.length) {
|
|
1969
|
+
const a = left[left.length - 1 - score];
|
|
1970
|
+
const b = right[right.length - 1 - score];
|
|
1971
|
+
if (a !== b) break;
|
|
1972
|
+
score += 1;
|
|
1973
|
+
}
|
|
1974
|
+
return score;
|
|
1975
|
+
}
|
|
1976
|
+
async function resolveEmittedEntryPath(emitRoot, moduleRel) {
|
|
1977
|
+
const expected = path4.resolve(emitRoot, toEmittedModulePath(moduleRel));
|
|
1978
|
+
if (await pathExists(expected)) {
|
|
1979
|
+
return expected;
|
|
1980
|
+
}
|
|
1981
|
+
const wantedRel = toEmittedModulePath(moduleRel);
|
|
1982
|
+
const wantedBase = path4.posix.basename(normalizePath(wantedRel));
|
|
1983
|
+
const files = await collectFilesRecursive(emitRoot);
|
|
1984
|
+
const candidates = files.filter(
|
|
1985
|
+
(file) => path4.posix.basename(normalizePath(file)) === wantedBase
|
|
1986
|
+
);
|
|
1987
|
+
if (candidates.length === 0) {
|
|
1988
|
+
return void 0;
|
|
1895
1989
|
}
|
|
1896
|
-
|
|
1990
|
+
candidates.sort(
|
|
1991
|
+
(a, b) => suffixMatchScore(b, wantedRel) - suffixMatchScore(a, wantedRel)
|
|
1992
|
+
);
|
|
1993
|
+
return candidates[0];
|
|
1897
1994
|
}
|
|
1898
|
-
async function
|
|
1995
|
+
async function compileSnapshotEntry(options) {
|
|
1996
|
+
const log = options.log ?? (() => void 0);
|
|
1997
|
+
const tsconfigStat = await fs2.stat(options.tsconfigPath);
|
|
1998
|
+
const cacheKey = buildCompileCacheKey(
|
|
1999
|
+
options.commitSha,
|
|
2000
|
+
options.moduleRel,
|
|
2001
|
+
options.tsconfigPath,
|
|
2002
|
+
{ mtimeMs: tsconfigStat.mtimeMs, size: tsconfigStat.size }
|
|
2003
|
+
);
|
|
2004
|
+
const emitRoot = path4.join(options.cacheRoot, cacheKey, "dist");
|
|
2005
|
+
let emittedEntry = path4.resolve(emitRoot, toEmittedModulePath(options.moduleRel));
|
|
2006
|
+
if (!options.noCache && await pathExists(emittedEntry)) {
|
|
2007
|
+
log(`[changelog] compile cache hit: ${options.commitSha.slice(0, 12)}`);
|
|
2008
|
+
return emittedEntry;
|
|
2009
|
+
}
|
|
2010
|
+
log(
|
|
2011
|
+
`[changelog] compile cache ${options.noCache ? "disabled" : "miss"}: ${options.commitSha.slice(0, 12)}`
|
|
2012
|
+
);
|
|
2013
|
+
await fs2.rm(path4.join(options.cacheRoot, cacheKey), { recursive: true, force: true }).catch(
|
|
2014
|
+
() => void 0
|
|
2015
|
+
);
|
|
2016
|
+
await fs2.mkdir(emitRoot, { recursive: true });
|
|
2017
|
+
const readResult = ts2.readConfigFile(options.tsconfigPath, ts2.sys.readFile);
|
|
2018
|
+
if (readResult.error) {
|
|
2019
|
+
throw new Error(ts2.flattenDiagnosticMessageText(readResult.error.messageText, "\n"));
|
|
2020
|
+
}
|
|
2021
|
+
const parsed = ts2.parseJsonConfigFileContent(
|
|
2022
|
+
readResult.config,
|
|
2023
|
+
ts2.sys,
|
|
2024
|
+
path4.dirname(options.tsconfigPath)
|
|
2025
|
+
);
|
|
2026
|
+
const compilerOptions = {
|
|
2027
|
+
...parsed.options,
|
|
2028
|
+
noEmit: false,
|
|
2029
|
+
declaration: false,
|
|
2030
|
+
declarationMap: false,
|
|
2031
|
+
sourceMap: false,
|
|
2032
|
+
inlineSourceMap: false,
|
|
2033
|
+
composite: false,
|
|
2034
|
+
incremental: false,
|
|
2035
|
+
tsBuildInfoFile: void 0,
|
|
2036
|
+
outDir: emitRoot
|
|
2037
|
+
};
|
|
2038
|
+
const program = ts2.createProgram([options.modulePath], compilerOptions);
|
|
2039
|
+
const emitResult = program.emit();
|
|
2040
|
+
const diagnostics = ts2.getPreEmitDiagnostics(program).concat(emitResult.diagnostics).filter((diagnostic) => diagnostic.category === ts2.DiagnosticCategory.Error);
|
|
2041
|
+
if (diagnostics.length > 0) {
|
|
2042
|
+
const host = {
|
|
2043
|
+
getCanonicalFileName: (fileName) => fileName,
|
|
2044
|
+
getCurrentDirectory: () => options.worktreeDir,
|
|
2045
|
+
getNewLine: () => "\n"
|
|
2046
|
+
};
|
|
2047
|
+
const message = ts2.formatDiagnosticsWithColorAndContext(diagnostics.slice(0, 20), host);
|
|
2048
|
+
throw new Error(
|
|
2049
|
+
`TypeScript snapshot compile failed for ${options.moduleRel} at ${options.commitSha.slice(0, 12)}:
|
|
2050
|
+
${message}`
|
|
2051
|
+
);
|
|
2052
|
+
}
|
|
2053
|
+
emittedEntry = await resolveEmittedEntryPath(emitRoot, options.moduleRel) ?? emittedEntry;
|
|
2054
|
+
if (!await pathExists(emittedEntry)) {
|
|
2055
|
+
throw new Error(
|
|
2056
|
+
`Compiled snapshot entry was not emitted: ${emittedEntry}. Check module/tsconfig compatibility.`
|
|
2057
|
+
);
|
|
2058
|
+
}
|
|
2059
|
+
log(`[changelog] compiled snapshot entry: ${emittedEntry}`);
|
|
2060
|
+
return emittedEntry;
|
|
2061
|
+
}
|
|
2062
|
+
async function loadSnapshotExport(options) {
|
|
2063
|
+
return loadChangelogInput(options.entryPath, options.exportName);
|
|
2064
|
+
}
|
|
2065
|
+
async function createSnapshot(repoRoot, moduleCandidates, exportName, commit, tempRoot, tsconfigRel, exportOptions, log) {
|
|
1899
2066
|
const worktreeDir = path4.join(tempRoot, `wt-${commit.sha.slice(0, 12)}`);
|
|
1900
2067
|
await runGit(repoRoot, ["worktree", "add", "--detach", worktreeDir, commit.sha]);
|
|
1901
2068
|
try {
|
|
1902
2069
|
await ensureWorktreeDependencies(repoRoot, worktreeDir);
|
|
1903
|
-
const
|
|
1904
|
-
|
|
2070
|
+
const resolvedModuleRel = await resolveModulePathForCommit(
|
|
2071
|
+
repoRoot,
|
|
2072
|
+
commit.sha,
|
|
2073
|
+
moduleCandidates
|
|
2074
|
+
);
|
|
2075
|
+
if (!resolvedModuleRel) {
|
|
1905
2076
|
log?.(
|
|
1906
|
-
`[changelog]
|
|
2077
|
+
`[changelog] unresolved module for commit ${commit.sha.slice(0, 12)}; using empty snapshot`
|
|
1907
2078
|
);
|
|
2079
|
+
return {
|
|
2080
|
+
commit,
|
|
2081
|
+
routesByKey: {},
|
|
2082
|
+
sourceObjectsById: {},
|
|
2083
|
+
unresolvedModule: true
|
|
2084
|
+
};
|
|
1908
2085
|
}
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
2086
|
+
log?.(
|
|
2087
|
+
`[changelog] resolved module for commit ${commit.sha.slice(0, 12)}: ${resolvedModuleRel}`
|
|
2088
|
+
);
|
|
2089
|
+
const modulePath = path4.resolve(worktreeDir, resolvedModuleRel);
|
|
2090
|
+
let snapshotRuntimePath = modulePath;
|
|
2091
|
+
let resolvedTsconfigPath;
|
|
2092
|
+
if (isTypeScriptModule(modulePath)) {
|
|
2093
|
+
resolvedTsconfigPath = await resolveSnapshotTsconfig(
|
|
2094
|
+
worktreeDir,
|
|
2095
|
+
modulePath,
|
|
2096
|
+
tsconfigRel
|
|
2097
|
+
);
|
|
2098
|
+
log?.(`[changelog] using tsconfig: ${resolvedTsconfigPath}`);
|
|
2099
|
+
const compileCacheRoot = path4.resolve(
|
|
2100
|
+
exportOptions?.cacheDir ?? path4.join(os.tmpdir(), "rrroutes-export-changelog-cache")
|
|
2101
|
+
);
|
|
2102
|
+
snapshotRuntimePath = await compileSnapshotEntry({
|
|
2103
|
+
worktreeDir,
|
|
2104
|
+
moduleRel: resolvedModuleRel,
|
|
2105
|
+
modulePath,
|
|
2106
|
+
tsconfigPath: resolvedTsconfigPath,
|
|
2107
|
+
commitSha: commit.sha,
|
|
2108
|
+
cacheRoot: compileCacheRoot,
|
|
2109
|
+
noCache: exportOptions?.noCache,
|
|
2110
|
+
log
|
|
2111
|
+
});
|
|
2112
|
+
} else if (!isJavaScriptModule(modulePath)) {
|
|
2113
|
+
throw new Error(
|
|
2114
|
+
`Unsupported module extension for changelog snapshots: ${modulePath}`
|
|
2115
|
+
);
|
|
2116
|
+
}
|
|
2117
|
+
const input = await loadSnapshotExport({
|
|
2118
|
+
entryPath: snapshotRuntimePath,
|
|
2119
|
+
exportName
|
|
2120
|
+
});
|
|
1912
2121
|
const payload = await exportFinalizedLeaves(input, {
|
|
1913
2122
|
includeSource: true,
|
|
1914
2123
|
sourceModulePath: modulePath,
|
|
1915
2124
|
sourceExportName: exportName,
|
|
1916
|
-
tsconfigPath,
|
|
1917
|
-
|
|
2125
|
+
tsconfigPath: resolvedTsconfigPath ?? (tsconfigRel ? path4.resolve(worktreeDir, tsconfigRel) : void 0),
|
|
2126
|
+
handlers: exportOptions?.handlers
|
|
1918
2127
|
});
|
|
1919
2128
|
const routesByKey = toRouteSnapshots(payload);
|
|
1920
2129
|
const sourceObjectsById = toSourceObjectSnapshots(routesByKey);
|
|
@@ -2149,12 +2358,18 @@ async function exportFinalizedLeavesChangelog(options) {
|
|
|
2149
2358
|
log("[changelog] resolving commit window");
|
|
2150
2359
|
const window = await resolveCommitWindow(repoRoot, options.from, options.to);
|
|
2151
2360
|
log(`[changelog] window: ${window.from.slice(0, 12)}..${window.to.slice(0, 12)}`);
|
|
2361
|
+
const moduleCandidates = await buildModulePathCandidates(
|
|
2362
|
+
repoRoot,
|
|
2363
|
+
window.to,
|
|
2364
|
+
modulePathRelative
|
|
2365
|
+
);
|
|
2366
|
+
log(`[changelog] module candidates discovered: ${moduleCandidates.length}`);
|
|
2152
2367
|
const allCommits = await resolveCommitPath(repoRoot, window.from, window.to);
|
|
2153
2368
|
log(`[changelog] commits in ancestry path: ${allCommits.length}`);
|
|
2154
2369
|
const selectedCommitShas = await filterCommits(
|
|
2155
2370
|
repoRoot,
|
|
2156
2371
|
allCommits,
|
|
2157
|
-
|
|
2372
|
+
moduleCandidates,
|
|
2158
2373
|
tsconfigRelative
|
|
2159
2374
|
);
|
|
2160
2375
|
log(`[changelog] commits after path filter: ${selectedCommitShas.length}`);
|
|
@@ -2171,6 +2386,7 @@ async function exportFinalizedLeavesChangelog(options) {
|
|
|
2171
2386
|
log(`[changelog] temp workspace: ${tempRoot}`);
|
|
2172
2387
|
try {
|
|
2173
2388
|
const snapshots = [];
|
|
2389
|
+
const unresolvedModuleCommits = [];
|
|
2174
2390
|
for (let index = 0; index < commits.length; index += 1) {
|
|
2175
2391
|
const commit = commits[index];
|
|
2176
2392
|
log(
|
|
@@ -2179,7 +2395,7 @@ async function exportFinalizedLeavesChangelog(options) {
|
|
|
2179
2395
|
snapshots.push(
|
|
2180
2396
|
await createSnapshot(
|
|
2181
2397
|
repoRoot,
|
|
2182
|
-
|
|
2398
|
+
moduleCandidates,
|
|
2183
2399
|
exportName,
|
|
2184
2400
|
commit,
|
|
2185
2401
|
tempRoot,
|
|
@@ -2188,6 +2404,9 @@ async function exportFinalizedLeavesChangelog(options) {
|
|
|
2188
2404
|
log
|
|
2189
2405
|
)
|
|
2190
2406
|
);
|
|
2407
|
+
if (snapshots[snapshots.length - 1]?.unresolvedModule) {
|
|
2408
|
+
unresolvedModuleCommits.push(commit.sha);
|
|
2409
|
+
}
|
|
2191
2410
|
}
|
|
2192
2411
|
const routeEvents = [];
|
|
2193
2412
|
const sourceEvents = [];
|
|
@@ -2212,7 +2431,8 @@ async function exportFinalizedLeavesChangelog(options) {
|
|
|
2212
2431
|
exportName,
|
|
2213
2432
|
from: window.from,
|
|
2214
2433
|
to: window.to,
|
|
2215
|
-
selectedCommitCount: commits.length
|
|
2434
|
+
selectedCommitCount: commits.length,
|
|
2435
|
+
unresolvedModuleCommits: unresolvedModuleCommits.length > 0 ? unresolvedModuleCommits : void 0
|
|
2216
2436
|
},
|
|
2217
2437
|
commits,
|
|
2218
2438
|
byRoute: routeRecordByKey(routeEvents),
|
|
@@ -2239,6 +2459,13 @@ var __private = {
|
|
|
2239
2459
|
resolveCommitWindow,
|
|
2240
2460
|
resolveCommitPath,
|
|
2241
2461
|
filterCommits,
|
|
2462
|
+
buildModulePathCandidates,
|
|
2463
|
+
resolveModulePathForCommit,
|
|
2464
|
+
resolveSnapshotTsconfig,
|
|
2465
|
+
toEmittedModulePath,
|
|
2466
|
+
buildCompileCacheKey,
|
|
2467
|
+
compileSnapshotEntry,
|
|
2468
|
+
loadSnapshotExport,
|
|
2242
2469
|
toRouteSnapshots,
|
|
2243
2470
|
toSourceObjectSnapshots,
|
|
2244
2471
|
diffSnapshots,
|
|
@@ -2249,6 +2476,7 @@ var __private = {
|
|
|
2249
2476
|
import path5 from "path";
|
|
2250
2477
|
function parseFinalizedLeavesChangelogCliArgs(argv) {
|
|
2251
2478
|
const args = /* @__PURE__ */ new Map();
|
|
2479
|
+
let noCache = false;
|
|
2252
2480
|
for (let i = 0; i < argv.length; i += 1) {
|
|
2253
2481
|
const key = argv[i];
|
|
2254
2482
|
if (key === "--") continue;
|
|
@@ -2256,6 +2484,10 @@ function parseFinalizedLeavesChangelogCliArgs(argv) {
|
|
|
2256
2484
|
if (key === "--with-source") {
|
|
2257
2485
|
continue;
|
|
2258
2486
|
}
|
|
2487
|
+
if (key === "--no-cache") {
|
|
2488
|
+
noCache = true;
|
|
2489
|
+
continue;
|
|
2490
|
+
}
|
|
2259
2491
|
const value = argv[i + 1];
|
|
2260
2492
|
if (!value || value.startsWith("--")) {
|
|
2261
2493
|
throw new Error(`Missing value for ${key}`);
|
|
@@ -2274,7 +2506,9 @@ function parseFinalizedLeavesChangelogCliArgs(argv) {
|
|
|
2274
2506
|
htmlFile: args.get("--html") ?? void 0,
|
|
2275
2507
|
tsconfigPath: args.get("--tsconfig") ?? void 0,
|
|
2276
2508
|
from: args.get("--from") ?? void 0,
|
|
2277
|
-
to: args.get("--to") ?? void 0
|
|
2509
|
+
to: args.get("--to") ?? void 0,
|
|
2510
|
+
cacheDir: args.get("--cache-dir") ?? void 0,
|
|
2511
|
+
noCache
|
|
2278
2512
|
};
|
|
2279
2513
|
}
|
|
2280
2514
|
async function runExportFinalizedLeavesChangelogCli(argv) {
|
|
@@ -2292,6 +2526,8 @@ async function runExportFinalizedLeavesChangelogCli(argv) {
|
|
|
2292
2526
|
from: args.from,
|
|
2293
2527
|
to: args.to,
|
|
2294
2528
|
includeSource: true,
|
|
2529
|
+
cacheDir: args.cacheDir,
|
|
2530
|
+
noCache: args.noCache,
|
|
2295
2531
|
log
|
|
2296
2532
|
};
|
|
2297
2533
|
log("[changelog-cli] starting changelog export");
|