-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcacheIdentity.ts
More file actions
87 lines (76 loc) · 2.73 KB
/
Copy pathcacheIdentity.ts
File metadata and controls
87 lines (76 loc) · 2.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import { hash as createDigest } from 'node:crypto';
import { isAbsolute } from 'node:path';
import stableStringify from 'fast-json-stable-stringify';
import { fmtCacheVersion } from './cacheStore.ts';
import { createRelativePathResolver, toPosixPath } from './pathHelpers.ts';
import type { ResolvedFmtOptions } from './types.ts';
declare const PRETTIER_VERSION: string;
declare const RSTACK_VERSION: string;
type CacheKeyResolver = (filePath: string) => string | undefined;
type OptionsHasher = (options: ResolvedFmtOptions) => string | undefined;
type PluginFingerprints = ReadonlyMap<string, string>;
const cacheHashLength = 16;
const createCacheHash = (content: string | Uint8Array): string =>
createDigest('sha256', content, 'base64url').slice(0, cacheHashLength);
/** Identifies formatter behavior shared by all cache entries in this process. */
const cacheNamespace: string = JSON.stringify([
fmtCacheVersion,
RSTACK_VERSION,
PRETTIER_VERSION,
]);
/** Creates project-relative POSIX cache keys without repeating path setup. */
const createCacheKeyResolver = (rootPath: string): CacheKeyResolver => {
const resolveRelativePath = createRelativePathResolver(rootPath);
return (filePath) => {
const relativePath = resolveRelativePath(filePath);
return isAbsolute(relativePath) ? undefined : toPosixPath(relativePath);
};
};
/** Hashes final per-file options and memoizes option objects shared by many files. */
const createOptionsHasher = (
pluginFingerprints?: PluginFingerprints,
): OptionsHasher => {
const hashes = new WeakMap<ResolvedFmtOptions, string | null>();
return (options) => {
const cached = hashes.get(options);
if (cached !== undefined) {
return cached ?? undefined;
}
let hash: string | undefined;
try {
const { plugins } = options;
let value = options;
if (plugins?.length) {
const fingerprints: string[] = [];
for (const plugin of plugins) {
const key =
plugin instanceof URL
? plugin.href
: typeof plugin === 'string'
? plugin
: undefined;
const fingerprint =
key === undefined ? undefined : pluginFingerprints?.get(key);
if (fingerprint === undefined) {
hashes.set(options, null);
return undefined;
}
fingerprints.push(fingerprint);
}
value = { ...options, plugins: fingerprints };
}
hash = createCacheHash(stableStringify(value));
} catch {
// Circular or unreadable options cannot be cached.
}
hashes.set(options, hash ?? null);
return hash;
};
};
export {
cacheHashLength,
cacheNamespace,
createCacheHash,
createCacheKeyResolver,
createOptionsHasher,
};