@spyglassmc/core 0.4.34 → 0.4.35
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/lib/common/externals/BrowserExternals.js +4 -19
- package/lib/common/externals/NodeJsExternals.d.ts +115 -2
- package/lib/common/externals/NodeJsExternals.js +154 -96
- package/lib/common/externals/index.d.ts +4 -3
- package/lib/common/externals/index.js +1 -1
- package/lib/service/Dependency.d.ts +10 -1
- package/lib/service/FileService.js +21 -14
- package/lib/service/Project.d.ts +3 -6
- package/lib/service/Project.js +23 -20
- package/lib/service/fetcher.d.ts +3 -0
- package/lib/service/fetcher.js +48 -0
- package/lib/service/index.d.ts +1 -1
- package/lib/service/index.js +1 -1
- package/lib/symbol/Symbol.d.ts +8 -8
- package/lib/symbol/Symbol.js +4 -0
- package/package.json +2 -2
- package/lib/common/externals/downloader.d.ts +0 -31
- package/lib/common/externals/downloader.js +0 -36
- package/lib/service/Downloader.d.ts +0 -40
- package/lib/service/Downloader.js +0 -127
|
@@ -35,24 +35,6 @@ export class BrowserEventEmitter {
|
|
|
35
35
|
return this;
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
-
class BrowserExternalDownloader {
|
|
39
|
-
async get(uri, options = {}) {
|
|
40
|
-
const headers = new Headers();
|
|
41
|
-
for (const [name, value] of Object.entries(options?.headers ?? {})) {
|
|
42
|
-
const values = typeof value === 'string' ? [value] : value;
|
|
43
|
-
for (const v of values) {
|
|
44
|
-
headers.append(name, v);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
const res = await fetch(uri, { headers, redirect: 'follow' });
|
|
48
|
-
if (!res.ok) {
|
|
49
|
-
throw new Error(`Status code ${res.status}: ${res.ok}`);
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
return new Uint8Array(await res.arrayBuffer());
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
38
|
class BrowserFsWatcher {
|
|
57
39
|
on(event, listener) {
|
|
58
40
|
if (event === 'ready') {
|
|
@@ -157,7 +139,6 @@ export const BrowserExternals = {
|
|
|
157
139
|
return uint8ArrayToHex(new Uint8Array(hash));
|
|
158
140
|
},
|
|
159
141
|
},
|
|
160
|
-
downloader: new BrowserExternalDownloader(),
|
|
161
142
|
error: {
|
|
162
143
|
createKind(kind, message) {
|
|
163
144
|
return new Error(`${kind}: ${message}`);
|
|
@@ -168,6 +149,10 @@ export const BrowserExternals = {
|
|
|
168
149
|
},
|
|
169
150
|
event: { EventEmitter: BrowserEventEmitter },
|
|
170
151
|
fs: new BrowserFileSystem(),
|
|
152
|
+
web: {
|
|
153
|
+
fetch,
|
|
154
|
+
getCache: () => window.caches.open('spyglassmc'),
|
|
155
|
+
},
|
|
171
156
|
};
|
|
172
157
|
function uint8ArrayToHex(array) {
|
|
173
158
|
let ans = '';
|
|
@@ -1,3 +1,116 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
/// <reference types="node" />
|
|
4
|
+
import chokidar from 'chokidar';
|
|
5
|
+
import decompress from 'decompress';
|
|
6
|
+
import { Buffer } from 'node:buffer';
|
|
7
|
+
import { EventEmitter } from 'node:events';
|
|
8
|
+
import fs from 'node:fs';
|
|
9
|
+
import type { RootUriString } from '../../index.js';
|
|
10
|
+
import type { FsLocation, FsWatcher } from './index.js';
|
|
11
|
+
export declare function getNodeJsExternals({ cacheRoot }?: {
|
|
12
|
+
cacheRoot?: RootUriString;
|
|
13
|
+
}): Readonly<{
|
|
14
|
+
archive: {
|
|
15
|
+
decompressBall(buffer: Uint8Array, options: {
|
|
16
|
+
stripLevel?: number | undefined;
|
|
17
|
+
} | undefined): Promise<decompress.File[]>;
|
|
18
|
+
gunzip(buffer: Uint8Array): Promise<Buffer>;
|
|
19
|
+
gzip(buffer: Uint8Array): Promise<Buffer>;
|
|
20
|
+
};
|
|
21
|
+
crypto: {
|
|
22
|
+
getSha1(data: string | Uint8Array): Promise<string>;
|
|
23
|
+
};
|
|
24
|
+
error: {
|
|
25
|
+
createKind(kind: import("./index.js").ExternalErrorKind, message: string): Error;
|
|
26
|
+
isKind(e: unknown, kind: import("./index.js").ExternalErrorKind): boolean;
|
|
27
|
+
};
|
|
28
|
+
event: {
|
|
29
|
+
EventEmitter: typeof EventEmitter;
|
|
30
|
+
};
|
|
31
|
+
fs: {
|
|
32
|
+
chmod(location: FsLocation, mode: number): Promise<void>;
|
|
33
|
+
mkdir(location: FsLocation, options: {
|
|
34
|
+
mode?: number | undefined;
|
|
35
|
+
recursive?: boolean | undefined;
|
|
36
|
+
} | undefined): Promise<undefined>;
|
|
37
|
+
readdir(location: FsLocation): Promise<fs.Dirent[]>;
|
|
38
|
+
readFile(location: FsLocation): Promise<Buffer>;
|
|
39
|
+
showFile(location: FsLocation): Promise<void>;
|
|
40
|
+
stat(location: FsLocation): Promise<fs.Stats>;
|
|
41
|
+
unlink(location: FsLocation): Promise<void>;
|
|
42
|
+
watch(locations: FsLocation[], { usePolling }?: {
|
|
43
|
+
usePolling?: boolean | undefined;
|
|
44
|
+
}): ChokidarWatcherWrapper;
|
|
45
|
+
writeFile(location: FsLocation, data: string | Uint8Array, options: {
|
|
46
|
+
mode: number;
|
|
47
|
+
} | undefined): Promise<void>;
|
|
48
|
+
};
|
|
49
|
+
web: {
|
|
50
|
+
fetch: typeof fetch;
|
|
51
|
+
getCache: () => Promise<HttpCache>;
|
|
52
|
+
};
|
|
53
|
+
}>;
|
|
54
|
+
export declare const NodeJsExternals: Readonly<{
|
|
55
|
+
archive: {
|
|
56
|
+
decompressBall(buffer: Uint8Array, options: {
|
|
57
|
+
stripLevel?: number | undefined;
|
|
58
|
+
} | undefined): Promise<decompress.File[]>;
|
|
59
|
+
gunzip(buffer: Uint8Array): Promise<Buffer>;
|
|
60
|
+
gzip(buffer: Uint8Array): Promise<Buffer>;
|
|
61
|
+
};
|
|
62
|
+
crypto: {
|
|
63
|
+
getSha1(data: string | Uint8Array): Promise<string>;
|
|
64
|
+
};
|
|
65
|
+
error: {
|
|
66
|
+
createKind(kind: import("./index.js").ExternalErrorKind, message: string): Error;
|
|
67
|
+
isKind(e: unknown, kind: import("./index.js").ExternalErrorKind): boolean;
|
|
68
|
+
};
|
|
69
|
+
event: {
|
|
70
|
+
EventEmitter: typeof EventEmitter;
|
|
71
|
+
};
|
|
72
|
+
fs: {
|
|
73
|
+
chmod(location: FsLocation, mode: number): Promise<void>;
|
|
74
|
+
mkdir(location: FsLocation, options: {
|
|
75
|
+
mode?: number | undefined;
|
|
76
|
+
recursive?: boolean | undefined;
|
|
77
|
+
} | undefined): Promise<undefined>;
|
|
78
|
+
readdir(location: FsLocation): Promise<fs.Dirent[]>;
|
|
79
|
+
readFile(location: FsLocation): Promise<Buffer>;
|
|
80
|
+
showFile(location: FsLocation): Promise<void>;
|
|
81
|
+
stat(location: FsLocation): Promise<fs.Stats>;
|
|
82
|
+
unlink(location: FsLocation): Promise<void>;
|
|
83
|
+
watch(locations: FsLocation[], { usePolling }?: {
|
|
84
|
+
usePolling?: boolean | undefined;
|
|
85
|
+
}): ChokidarWatcherWrapper;
|
|
86
|
+
writeFile(location: FsLocation, data: string | Uint8Array, options: {
|
|
87
|
+
mode: number;
|
|
88
|
+
} | undefined): Promise<void>;
|
|
89
|
+
};
|
|
90
|
+
web: {
|
|
91
|
+
fetch: typeof fetch;
|
|
92
|
+
getCache: () => Promise<HttpCache>;
|
|
93
|
+
};
|
|
94
|
+
}>;
|
|
95
|
+
declare class ChokidarWatcherWrapper extends EventEmitter implements FsWatcher {
|
|
96
|
+
#private;
|
|
97
|
+
constructor(watcher: chokidar.FSWatcher);
|
|
98
|
+
close(): Promise<void>;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* A non-spec-compliant, non-complete implementation of the Cache Web API for use in Spyglass.
|
|
102
|
+
* This class stores the cached response on the file system under the cache root.
|
|
103
|
+
*/
|
|
104
|
+
declare class HttpCache implements Cache {
|
|
105
|
+
#private;
|
|
106
|
+
constructor(cacheRoot: RootUriString | undefined);
|
|
107
|
+
match(request: RequestInfo | URL, _options?: CacheQueryOptions | undefined): Promise<Response | undefined>;
|
|
108
|
+
put(request: RequestInfo | URL, response: Response): Promise<void>;
|
|
109
|
+
add(): Promise<void>;
|
|
110
|
+
addAll(): Promise<void>;
|
|
111
|
+
delete(): Promise<boolean>;
|
|
112
|
+
keys(): Promise<readonly Request[]>;
|
|
113
|
+
matchAll(): Promise<readonly Response[]>;
|
|
114
|
+
}
|
|
115
|
+
export {};
|
|
3
116
|
//# sourceMappingURL=NodeJsExternals.d.ts.map
|
|
@@ -1,119 +1,111 @@
|
|
|
1
1
|
// https://github.com/DefinitelyTyped/DefinitelyTyped/discussions/60592
|
|
2
2
|
import chokidar from 'chokidar';
|
|
3
3
|
import decompress from 'decompress';
|
|
4
|
-
import followRedirects from 'follow-redirects';
|
|
5
4
|
import { Buffer } from 'node:buffer';
|
|
6
5
|
import cp from 'node:child_process';
|
|
7
6
|
import crypto from 'node:crypto';
|
|
8
7
|
import { EventEmitter } from 'node:events';
|
|
9
|
-
import { promises as fsp } from 'node:fs';
|
|
8
|
+
import fs, { promises as fsp } from 'node:fs';
|
|
9
|
+
import os from 'node:os';
|
|
10
10
|
import process from 'node:process';
|
|
11
|
+
import stream from 'node:stream';
|
|
11
12
|
import url from 'node:url';
|
|
12
13
|
import { promisify } from 'node:util';
|
|
13
14
|
import zlib from 'node:zlib';
|
|
14
|
-
import {
|
|
15
|
-
const { http, https } = followRedirects;
|
|
15
|
+
import { Uri } from '../util.js';
|
|
16
16
|
const gunzip = promisify(zlib.gunzip);
|
|
17
17
|
const gzip = promisify(zlib.gzip);
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (res.statusCode !== 200) {
|
|
25
|
-
reject(new Error(`Status code ${res.statusCode}: ${res.statusMessage}`));
|
|
18
|
+
export function getNodeJsExternals({ cacheRoot } = {}) {
|
|
19
|
+
return Object.freeze({
|
|
20
|
+
archive: {
|
|
21
|
+
decompressBall(buffer, options) {
|
|
22
|
+
if (!(buffer instanceof Buffer)) {
|
|
23
|
+
buffer = Buffer.from(buffer);
|
|
26
24
|
}
|
|
27
|
-
else {
|
|
28
|
-
resolve(promisifyAsyncIterable(res, (chunks) => Buffer.concat(chunks)));
|
|
29
|
-
}
|
|
30
|
-
}).on('error', (e) => {
|
|
31
|
-
reject(e);
|
|
32
|
-
});
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
export const NodeJsExternals = {
|
|
37
|
-
archive: {
|
|
38
|
-
decompressBall(buffer, options) {
|
|
39
|
-
if (buffer instanceof Buffer) {
|
|
40
25
|
return decompress(buffer, { strip: options?.stripLevel });
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return gzip(buffer);
|
|
49
|
-
},
|
|
50
|
-
},
|
|
51
|
-
crypto: {
|
|
52
|
-
async getSha1(data) {
|
|
53
|
-
const hash = crypto.createHash('sha1');
|
|
54
|
-
hash.update(data);
|
|
55
|
-
return hash.digest('hex');
|
|
56
|
-
},
|
|
57
|
-
},
|
|
58
|
-
downloader: new NodeJsExternalDownloader(),
|
|
59
|
-
error: {
|
|
60
|
-
createKind(kind, message) {
|
|
61
|
-
const error = new Error(message);
|
|
62
|
-
error.code = kind;
|
|
63
|
-
return error;
|
|
64
|
-
},
|
|
65
|
-
isKind(e, kind) {
|
|
66
|
-
return e instanceof Error && e.code === kind;
|
|
67
|
-
},
|
|
68
|
-
},
|
|
69
|
-
event: { EventEmitter },
|
|
70
|
-
fs: {
|
|
71
|
-
chmod(location, mode) {
|
|
72
|
-
return fsp.chmod(toFsPathLike(location), mode);
|
|
73
|
-
},
|
|
74
|
-
async mkdir(location, options) {
|
|
75
|
-
return void (await fsp.mkdir(toFsPathLike(location), options));
|
|
76
|
-
},
|
|
77
|
-
readdir(location) {
|
|
78
|
-
return fsp.readdir(toFsPathLike(location), { encoding: 'utf-8', withFileTypes: true });
|
|
79
|
-
},
|
|
80
|
-
readFile(location) {
|
|
81
|
-
return fsp.readFile(toFsPathLike(location));
|
|
82
|
-
},
|
|
83
|
-
async showFile(location) {
|
|
84
|
-
const execFile = promisify(cp.execFile);
|
|
85
|
-
let command;
|
|
86
|
-
switch (process.platform) {
|
|
87
|
-
case 'darwin':
|
|
88
|
-
command = 'open';
|
|
89
|
-
break;
|
|
90
|
-
case 'win32':
|
|
91
|
-
command = 'explorer';
|
|
92
|
-
break;
|
|
93
|
-
default:
|
|
94
|
-
command = 'xdg-open';
|
|
95
|
-
break;
|
|
96
|
-
}
|
|
97
|
-
return void (await execFile(command, [toPath(location)]));
|
|
26
|
+
},
|
|
27
|
+
gunzip(buffer) {
|
|
28
|
+
return gunzip(buffer);
|
|
29
|
+
},
|
|
30
|
+
gzip(buffer) {
|
|
31
|
+
return gzip(buffer);
|
|
32
|
+
},
|
|
98
33
|
},
|
|
99
|
-
|
|
100
|
-
|
|
34
|
+
crypto: {
|
|
35
|
+
async getSha1(data) {
|
|
36
|
+
const hash = crypto.createHash('sha1');
|
|
37
|
+
hash.update(data);
|
|
38
|
+
return hash.digest('hex');
|
|
39
|
+
},
|
|
101
40
|
},
|
|
102
|
-
|
|
103
|
-
|
|
41
|
+
error: {
|
|
42
|
+
createKind(kind, message) {
|
|
43
|
+
const error = new Error(message);
|
|
44
|
+
error.code = kind;
|
|
45
|
+
return error;
|
|
46
|
+
},
|
|
47
|
+
isKind(e, kind) {
|
|
48
|
+
return e instanceof Error && e.code === kind;
|
|
49
|
+
},
|
|
104
50
|
},
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
51
|
+
event: { EventEmitter },
|
|
52
|
+
fs: {
|
|
53
|
+
chmod(location, mode) {
|
|
54
|
+
return fsp.chmod(toFsPathLike(location), mode);
|
|
55
|
+
},
|
|
56
|
+
async mkdir(location, options) {
|
|
57
|
+
return void (await fsp.mkdir(toFsPathLike(location), options));
|
|
58
|
+
},
|
|
59
|
+
readdir(location) {
|
|
60
|
+
return fsp.readdir(toFsPathLike(location), {
|
|
61
|
+
encoding: 'utf-8',
|
|
62
|
+
withFileTypes: true,
|
|
63
|
+
});
|
|
64
|
+
},
|
|
65
|
+
readFile(location) {
|
|
66
|
+
return fsp.readFile(toFsPathLike(location));
|
|
67
|
+
},
|
|
68
|
+
async showFile(location) {
|
|
69
|
+
const execFile = promisify(cp.execFile);
|
|
70
|
+
let command;
|
|
71
|
+
switch (process.platform) {
|
|
72
|
+
case 'darwin':
|
|
73
|
+
command = 'open';
|
|
74
|
+
break;
|
|
75
|
+
case 'win32':
|
|
76
|
+
command = 'explorer';
|
|
77
|
+
break;
|
|
78
|
+
default:
|
|
79
|
+
command = 'xdg-open';
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
return void (await execFile(command, [toPath(location)]));
|
|
83
|
+
},
|
|
84
|
+
stat(location) {
|
|
85
|
+
return fsp.stat(toFsPathLike(location));
|
|
86
|
+
},
|
|
87
|
+
unlink(location) {
|
|
88
|
+
return fsp.unlink(toFsPathLike(location));
|
|
89
|
+
},
|
|
90
|
+
watch(locations, { usePolling = false } = {}) {
|
|
91
|
+
return new ChokidarWatcherWrapper(chokidar.watch(locations.map(toPath), {
|
|
92
|
+
usePolling,
|
|
93
|
+
disableGlobbing: true,
|
|
94
|
+
}));
|
|
95
|
+
},
|
|
96
|
+
writeFile(location, data, options) {
|
|
97
|
+
return fsp.writeFile(toFsPathLike(location), data, options);
|
|
98
|
+
},
|
|
110
99
|
},
|
|
111
|
-
|
|
112
|
-
|
|
100
|
+
web: {
|
|
101
|
+
fetch,
|
|
102
|
+
getCache: async () => {
|
|
103
|
+
return new HttpCache(cacheRoot);
|
|
104
|
+
},
|
|
113
105
|
},
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
export const NodeJsExternals = getNodeJsExternals();
|
|
117
109
|
/**
|
|
118
110
|
* @returns A {@link fs.PathLike}.
|
|
119
111
|
*/
|
|
@@ -151,4 +143,70 @@ class ChokidarWatcherWrapper extends EventEmitter {
|
|
|
151
143
|
return this.#watcher.close();
|
|
152
144
|
}
|
|
153
145
|
}
|
|
146
|
+
/**
|
|
147
|
+
* A non-spec-compliant, non-complete implementation of the Cache Web API for use in Spyglass.
|
|
148
|
+
* This class stores the cached response on the file system under the cache root.
|
|
149
|
+
*/
|
|
150
|
+
class HttpCache {
|
|
151
|
+
#cacheRoot;
|
|
152
|
+
constructor(cacheRoot) {
|
|
153
|
+
if (cacheRoot) {
|
|
154
|
+
this.#cacheRoot = `${cacheRoot}http/`;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
async match(request, _options) {
|
|
158
|
+
if (!this.#cacheRoot) {
|
|
159
|
+
return undefined;
|
|
160
|
+
}
|
|
161
|
+
const fileName = this.#getFileName(request);
|
|
162
|
+
try {
|
|
163
|
+
const etag = (await fsp.readFile(new URL(`${fileName}.etag`, this.#cacheRoot), 'utf8'))
|
|
164
|
+
.trim();
|
|
165
|
+
const bodyStream = fs.createReadStream(new URL(`${fileName}.bin`, this.#cacheRoot));
|
|
166
|
+
return new Response(stream.Readable.toWeb(bodyStream),
|
|
167
|
+
// \___/
|
|
168
|
+
// stream Readable -> stream/web ReadableStream
|
|
169
|
+
// \_______________/
|
|
170
|
+
// stream/web ReadableStream -> DOM ReadableStream
|
|
171
|
+
{ headers: { etag } });
|
|
172
|
+
}
|
|
173
|
+
catch (e) {
|
|
174
|
+
if (e?.code === 'ENOENT') {
|
|
175
|
+
return undefined;
|
|
176
|
+
}
|
|
177
|
+
throw e;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
async put(request, response) {
|
|
181
|
+
const etag = response.headers.get('etag');
|
|
182
|
+
if (!(this.#cacheRoot && response.body && etag)) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const fileName = this.#getFileName(request);
|
|
186
|
+
await fsp.mkdir(new URL(this.#cacheRoot), { recursive: true });
|
|
187
|
+
await Promise.all([
|
|
188
|
+
fsp.writeFile(new URL(`${fileName}.bin`, this.#cacheRoot), stream.Readable.fromWeb(response.body)),
|
|
189
|
+
fsp.writeFile(new URL(`${fileName}.etag`, this.#cacheRoot), `${etag}${os.EOL}`),
|
|
190
|
+
]);
|
|
191
|
+
}
|
|
192
|
+
#getFileName(request) {
|
|
193
|
+
const uriString = request instanceof Request ? request.url : request.toString();
|
|
194
|
+
return Buffer.from(uriString, 'utf8').toString('base64url');
|
|
195
|
+
}
|
|
196
|
+
async add() {
|
|
197
|
+
throw new Error('Method not implemented.');
|
|
198
|
+
}
|
|
199
|
+
async addAll() {
|
|
200
|
+
throw new Error('Method not implemented.');
|
|
201
|
+
}
|
|
202
|
+
async delete() {
|
|
203
|
+
throw new Error('Method not implemented.');
|
|
204
|
+
}
|
|
205
|
+
async keys() {
|
|
206
|
+
throw new Error('Method not implemented.');
|
|
207
|
+
}
|
|
208
|
+
async matchAll() {
|
|
209
|
+
throw new Error('Method not implemented.');
|
|
210
|
+
}
|
|
211
|
+
}
|
|
154
212
|
//# sourceMappingURL=NodeJsExternals.js.map
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import type { Uri } from '../util.js';
|
|
2
|
-
import type { ExternalDownloader } from './downloader.js';
|
|
3
|
-
export * from './downloader.js';
|
|
4
2
|
export interface Externals {
|
|
5
3
|
archive: {
|
|
6
4
|
decompressBall: (buffer: Uint8Array, options?: {
|
|
@@ -15,7 +13,6 @@ export interface Externals {
|
|
|
15
13
|
*/
|
|
16
14
|
getSha1: (data: string | Uint8Array) => Promise<string>;
|
|
17
15
|
};
|
|
18
|
-
downloader: ExternalDownloader;
|
|
19
16
|
error: {
|
|
20
17
|
/**
|
|
21
18
|
* @returns an error of the specified kind
|
|
@@ -30,6 +27,10 @@ export interface Externals {
|
|
|
30
27
|
EventEmitter: new () => ExternalEventEmitter;
|
|
31
28
|
};
|
|
32
29
|
fs: ExternalFileSystem;
|
|
30
|
+
web: {
|
|
31
|
+
fetch: typeof fetch;
|
|
32
|
+
getCache: () => Promise<Cache>;
|
|
33
|
+
};
|
|
33
34
|
}
|
|
34
35
|
export interface DecompressedFile {
|
|
35
36
|
data: Uint8Array;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export
|
|
1
|
+
export {};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
export type Dependency = {
|
|
2
|
+
type: 'directory';
|
|
2
3
|
uri: string;
|
|
3
|
-
|
|
4
|
+
} | {
|
|
5
|
+
type: 'tarball-file';
|
|
6
|
+
uri: string;
|
|
7
|
+
stripLevel?: number;
|
|
8
|
+
} | {
|
|
9
|
+
type: 'tarball-ram';
|
|
10
|
+
name: string;
|
|
11
|
+
data: Uint8Array;
|
|
12
|
+
stripLevel?: number;
|
|
4
13
|
};
|
|
5
14
|
export type DependencyKey = `@${string}`;
|
|
6
15
|
export declare namespace DependencyKey {
|
|
@@ -137,7 +137,11 @@ export class FileUriSupporter {
|
|
|
137
137
|
static async create(dependencies, externals, logger) {
|
|
138
138
|
const roots = [];
|
|
139
139
|
const files = new Map();
|
|
140
|
-
for (
|
|
140
|
+
for (const dependency of dependencies) {
|
|
141
|
+
if (dependency.type !== 'directory') {
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
let { uri } = dependency;
|
|
141
145
|
try {
|
|
142
146
|
if (fileUtil.isFileUri(uri) && (await externals.fs.stat(uri)).isDirectory()) {
|
|
143
147
|
uri = fileUtil.ensureEndingSlash(uri);
|
|
@@ -232,23 +236,26 @@ export class ArchiveUriSupporter {
|
|
|
232
236
|
}
|
|
233
237
|
static async create(dependencies, externals, logger) {
|
|
234
238
|
const entries = new Map();
|
|
235
|
-
for (const
|
|
239
|
+
for (const dependency of dependencies) {
|
|
240
|
+
if (dependency.type === 'directory') {
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
const archiveName = dependency.type === 'tarball-file'
|
|
244
|
+
? fileUtil.basename(dependency.uri)
|
|
245
|
+
: dependency.name;
|
|
236
246
|
try {
|
|
237
|
-
if (
|
|
238
|
-
|
|
239
|
-
&& (await externals.fs.stat(uri)).isFile()) {
|
|
240
|
-
const archiveName = fileUtil.basename(uri);
|
|
241
|
-
if (entries.has(archiveName)) {
|
|
242
|
-
throw new Error(`A different URI with ${archiveName} already exists`);
|
|
243
|
-
}
|
|
244
|
-
const files = await externals.archive.decompressBall(await externals.fs.readFile(uri), { stripLevel: typeof info?.startDepth === 'number' ? info.startDepth : 0 });
|
|
245
|
-
/// Debug message for #1609
|
|
246
|
-
logger.info(`[ArchiveUriSupporter#create] Extracted ${files.length} files from ${archiveName}`);
|
|
247
|
-
entries.set(archiveName, new Map(files.map((f) => [f.path.replace(/\\/g, '/'), f])));
|
|
247
|
+
if (entries.has(archiveName)) {
|
|
248
|
+
throw new Error(`A different archive with ${archiveName} already exists`);
|
|
248
249
|
}
|
|
250
|
+
const files = await externals.archive.decompressBall(dependency.type === 'tarball-file'
|
|
251
|
+
? await externals.fs.readFile(dependency.uri)
|
|
252
|
+
: dependency.data, { stripLevel: dependency.stripLevel ?? 0 });
|
|
253
|
+
/// Debug message for #1609
|
|
254
|
+
logger.info(`[ArchiveUriSupporter#create] Extracted ${files.length} files from ${archiveName}`);
|
|
255
|
+
entries.set(archiveName, new Map(files.map((f) => [f.path.replace(/\\/g, '/'), f])));
|
|
249
256
|
}
|
|
250
257
|
catch (e) {
|
|
251
|
-
logger.error(`[ArchiveUriSupporter#create] Bad dependency ${
|
|
258
|
+
logger.error(`[ArchiveUriSupporter#create] Bad dependency ${archiveName}`, e);
|
|
252
259
|
}
|
|
253
260
|
}
|
|
254
261
|
return new ArchiveUriSupporter(externals, logger, entries);
|
package/lib/service/Project.d.ts
CHANGED
|
@@ -8,19 +8,17 @@ import type { PosRangeLanguageError } from '../source/index.js';
|
|
|
8
8
|
import { SymbolUtil } from '../symbol/index.js';
|
|
9
9
|
import { CacheService } from './CacheService.js';
|
|
10
10
|
import type { Config } from './Config.js';
|
|
11
|
-
import { Downloader } from './Downloader.js';
|
|
12
11
|
import { FileService } from './FileService.js';
|
|
13
12
|
import type { RootUriString } from './fileUtil.js';
|
|
14
13
|
import { MetaRegistry } from './MetaRegistry.js';
|
|
15
14
|
import { ProfilerFactory } from './Profiler.js';
|
|
16
|
-
export type ProjectInitializerContext = Pick<Project, 'cacheRoot' | 'config' | '
|
|
15
|
+
export type ProjectInitializerContext = Pick<Project, 'cacheRoot' | 'config' | 'externals' | 'isDebugging' | 'logger' | 'meta' | 'projectRoots'>;
|
|
17
16
|
export type SyncProjectInitializer = (this: void, ctx: ProjectInitializerContext) => Record<string, string> | void;
|
|
18
17
|
export type AsyncProjectInitializer = (this: void, ctx: ProjectInitializerContext) => PromiseLike<Record<string, string> | void>;
|
|
19
18
|
export type ProjectInitializer = SyncProjectInitializer | AsyncProjectInitializer;
|
|
20
19
|
export interface ProjectOptions {
|
|
21
20
|
cacheRoot: RootUriString;
|
|
22
21
|
defaultConfig?: Config;
|
|
23
|
-
downloader?: Downloader;
|
|
24
22
|
externals: Externals;
|
|
25
23
|
fs?: FileService;
|
|
26
24
|
initializers?: readonly ProjectInitializer[];
|
|
@@ -56,7 +54,7 @@ interface SymbolRegistrarEvent {
|
|
|
56
54
|
id: string;
|
|
57
55
|
checksum: string | undefined;
|
|
58
56
|
}
|
|
59
|
-
export type ProjectData = Pick<Project, 'cacheRoot' | 'config' | '
|
|
57
|
+
export type ProjectData = Pick<Project, 'cacheRoot' | 'config' | 'ensureBindingStarted' | 'externals' | 'fs' | 'isDebugging' | 'logger' | 'meta' | 'profilers' | 'projectRoots' | 'roots' | 'symbols' | 'ctx'>;
|
|
60
58
|
/**
|
|
61
59
|
* Manage all tracked documents and errors.
|
|
62
60
|
*
|
|
@@ -100,7 +98,6 @@ export declare class Project implements ExternalEventEmitter {
|
|
|
100
98
|
readonly cacheService: CacheService;
|
|
101
99
|
get isReady(): boolean;
|
|
102
100
|
config: Config;
|
|
103
|
-
readonly downloader: Downloader;
|
|
104
101
|
readonly externals: Externals;
|
|
105
102
|
readonly fs: FileService;
|
|
106
103
|
readonly isDebugging: boolean;
|
|
@@ -156,7 +153,7 @@ export declare class Project implements ExternalEventEmitter {
|
|
|
156
153
|
* are not loaded into the memory.
|
|
157
154
|
*/
|
|
158
155
|
getTrackedFiles(): string[];
|
|
159
|
-
constructor({ cacheRoot, defaultConfig,
|
|
156
|
+
constructor({ cacheRoot, defaultConfig, externals, fs, initializers, isDebugging, logger, profilers, projectRoots, }: ProjectOptions);
|
|
160
157
|
private setInitPromise;
|
|
161
158
|
private setReadyPromise;
|
|
162
159
|
/**
|