forked from redhat-developer/vscode-yaml
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjson-schema-cache.ts
More file actions
96 lines (82 loc) · 2.91 KB
/
json-schema-cache.ts
File metadata and controls
96 lines (82 loc) · 2.91 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
88
89
90
91
92
93
94
95
96
/*---------------------------------------------------------------------------------------------
* Copyright (c) Red Hat, Inc. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as fs from 'fs-extra';
import * as path from 'path';
import * as crypto from 'crypto';
import { Memento, OutputChannel } from 'vscode';
const CACHE_DIR = 'schemas_cache';
const CACHE_KEY = 'json-schema-key';
interface CacheEntry {
eTag: string;
schemaPath: string;
}
interface SchemaCache {
[uri: string]: CacheEntry;
}
export class JSONSchemaCache {
private readonly cachePath: string;
private readonly cache: SchemaCache;
private isInitialized = false;
constructor(globalStoragePath: string, private memento: Memento, private output: OutputChannel) {
this.cachePath = path.join(globalStoragePath, CACHE_DIR);
this.cache = memento.get(CACHE_KEY, {});
}
private async init(): Promise<void> {
await fs.ensureDir(this.cachePath);
const cachedFiles = await fs.readdir(this.cachePath);
// clean up memento if cached files was deleted from fs
const cachedValues = cachedFiles.map((it) => path.join(this.cachePath, it));
for (const key in this.cache) {
if (Object.prototype.hasOwnProperty.call(this.cache, key)) {
const cacheEntry = this.cache[key];
if (!cachedValues.includes(cacheEntry.schemaPath)) {
delete this.cache[key];
}
}
}
await this.memento.update(CACHE_KEY, this.cache);
this.isInitialized = true;
}
private getCacheFilePath(uri: string): string {
const hash = crypto.createHash('MD5');
hash.update(uri);
const hashedURI = hash.digest('hex');
return path.join(this.cachePath, hashedURI);
}
getETag(schemaUri: string): string | undefined {
if (!this.isInitialized) {
return undefined;
}
return this.cache[schemaUri]?.eTag;
}
async putSchema(schemaUri: string, eTag: string, schemaContent: string): Promise<void> {
if (!this.isInitialized) {
await this.init();
}
if (!this.cache[schemaUri]) {
this.cache[schemaUri] = { eTag, schemaPath: this.getCacheFilePath(schemaUri) };
} else {
this.cache[schemaUri].eTag = eTag;
}
try {
const cacheFile = this.cache[schemaUri].schemaPath;
await fs.writeFile(cacheFile, schemaContent);
await this.memento.update(CACHE_KEY, this.cache);
} catch (err) {
delete this.cache[schemaUri];
this.output.appendLine(err);
}
}
async getSchema(schemaUri: string): Promise<string | undefined> {
if (!this.isInitialized) {
await this.init();
}
const cacheFile = this.cache[schemaUri]?.schemaPath;
if (await fs.pathExists(cacheFile)) {
return await fs.readFile(cacheFile, { encoding: 'UTF8' });
}
return undefined;
}
}