@pygmalionjs/pygmalion 0.2.23 → 0.2.24
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/dist-lib/{App-CkJW2APT.js → App-DaaT22K5.js} +1503 -1489
- package/dist-lib/pygmalion.js +200 -200
- package/dist-lib/testing.js +1 -1
- package/node/storyboard-environment.mjs +27 -2
- package/package.json +1 -1
package/dist-lib/testing.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
1
2
|
import fs from 'node:fs/promises';
|
|
2
3
|
import path from 'node:path';
|
|
3
4
|
import ts from 'typescript';
|
|
@@ -1040,7 +1041,22 @@ function resolveSourceSpecifier(importer, specifier, files) {
|
|
|
1040
1041
|
return candidates.find((candidate) => files.has(candidate)) ?? null;
|
|
1041
1042
|
}
|
|
1042
1043
|
|
|
1043
|
-
|
|
1044
|
+
/**
|
|
1045
|
+
* Content digest of everything a route renders from.
|
|
1046
|
+
*
|
|
1047
|
+
* A frame captured from these files stays valid until one of them changes, which
|
|
1048
|
+
* is what makes an unrelated commit stop invalidating it.
|
|
1049
|
+
*/
|
|
1050
|
+
function closureDigest(reachable, fileDigests) {
|
|
1051
|
+
const parts = [...reachable]
|
|
1052
|
+
.filter((file) => fileDigests.has(file))
|
|
1053
|
+
.sort()
|
|
1054
|
+
.map((file) => `${file}:${fileDigests.get(file)}`);
|
|
1055
|
+
if (!parts.length) return null;
|
|
1056
|
+
return createHash('sha256').update(parts.join('\n')).digest('hex').slice(0, 32);
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
function associateRouteCandidates(manifest, graph, fileDigests = new Map()) {
|
|
1044
1060
|
const dependencies = {};
|
|
1045
1061
|
for (const [file, values] of Object.entries(graph.dependencies)) {
|
|
1046
1062
|
dependencies[stripSourceDirectory(file, graph.sourceDirectory)] = values.map(
|
|
@@ -1125,11 +1141,13 @@ function associateRouteCandidates(manifest, graph) {
|
|
|
1125
1141
|
},
|
|
1126
1142
|
});
|
|
1127
1143
|
}
|
|
1144
|
+
const dependencyDigest = closureDigest(reachable, fileDigests);
|
|
1128
1145
|
return {
|
|
1129
1146
|
...route,
|
|
1130
1147
|
resolvedRoots: [...new Set(resolvedRoots)].sort(),
|
|
1131
1148
|
evidenceIds,
|
|
1132
1149
|
scenarioIds: [...scenarioIds].sort(),
|
|
1150
|
+
...(dependencyDigest == null ? {} : { dependencyDigest }),
|
|
1133
1151
|
};
|
|
1134
1152
|
});
|
|
1135
1153
|
|
|
@@ -1174,6 +1192,7 @@ export async function scanStoryboardEnvironment(root, options = {}) {
|
|
|
1174
1192
|
};
|
|
1175
1193
|
const sources = [];
|
|
1176
1194
|
|
|
1195
|
+
const fileDigests = new Map();
|
|
1177
1196
|
for (const file of files) {
|
|
1178
1197
|
let stat;
|
|
1179
1198
|
try {
|
|
@@ -1192,6 +1211,12 @@ export async function scanStoryboardEnvironment(root, options = {}) {
|
|
|
1192
1211
|
source,
|
|
1193
1212
|
sourcePath: normalizedRelativePath(sourceRoot, file),
|
|
1194
1213
|
});
|
|
1214
|
+
// The scan already holds every file, so a content digest costs nothing extra
|
|
1215
|
+
// here and is what lets a frame survive a revision it does not depend on.
|
|
1216
|
+
fileDigests.set(
|
|
1217
|
+
normalizedRelativePath(sourceRoot, file),
|
|
1218
|
+
createHash('sha256').update(source).digest('hex').slice(0, 32),
|
|
1219
|
+
);
|
|
1195
1220
|
}
|
|
1196
1221
|
|
|
1197
1222
|
const sourceFiles = new Set(sources.map((entry) => entry.sourcePath));
|
|
@@ -1212,7 +1237,7 @@ export async function scanStoryboardEnvironment(root, options = {}) {
|
|
|
1212
1237
|
const graph = await buildSourceGraph(path.resolve(root), {
|
|
1213
1238
|
sourceDirectory: options.sourceDirectory ?? '.',
|
|
1214
1239
|
});
|
|
1215
|
-
return associateRouteCandidates(manifest, graph);
|
|
1240
|
+
return associateRouteCandidates(manifest, graph, fileDigests);
|
|
1216
1241
|
}
|
|
1217
1242
|
|
|
1218
1243
|
export function storyboardEnvironmentBootstrapSource() {
|