vitecache 0.3.0 → 0.4.0
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 +17 -22
- package/dist/browser.d.ts +9 -6
- package/dist/browser.js +28 -178
- package/dist/browser.js.map +1 -1
- package/dist/discover.d.ts +15 -0
- package/dist/discover.js +131 -0
- package/dist/discover.js.map +1 -0
- package/dist/disk.d.ts +2 -26
- package/dist/disk.js +8 -107
- package/dist/disk.js.map +1 -1
- package/dist/entry.d.ts +29 -17
- package/dist/entry.js +11 -114
- package/dist/entry.js.map +1 -1
- package/dist/node.d.ts +9 -6
- package/dist/node.js +101 -6
- package/dist/node.js.map +1 -1
- package/dist/shared.d.ts +17 -0
- package/dist/shared.js +5 -0
- package/dist/shared.js.map +1 -0
- package/dist/vite.d.ts +12 -0
- package/dist/vite.js +253 -0
- package/dist/vite.js.map +1 -0
- package/package.json +17 -13
- package/skills/vitecache/SKILL.md +41 -46
- package/dist/dependencies.d.ts +0 -23
- package/dist/dependencies.js +0 -147
- package/dist/dependencies.js.map +0 -1
- package/dist/hash.d.ts +0 -4
- package/dist/hash.js +0 -41
- package/dist/hash.js.map +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +0 -1
- package/dist/key.d.ts +0 -3
- package/dist/key.js +0 -10
- package/dist/key.js.map +0 -1
- package/dist/packages.d.ts +0 -6
- package/dist/packages.js +0 -52
- package/dist/packages.js.map +0 -1
- package/dist/prune.d.ts +0 -11
- package/dist/prune.js +0 -71
- package/dist/prune.js.map +0 -1
- package/dist/storage.d.ts +0 -12
- package/dist/storage.js +0 -95
- package/dist/storage.js.map +0 -1
- package/dist/types.d.ts +0 -89
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/dist/vite/index.d.ts +0 -8
- package/dist/vite/index.js +0 -220
- package/dist/vite/index.js.map +0 -1
- package/dist/vite/manifest.d.ts +0 -3
- package/dist/vite/manifest.js +0 -34
- package/dist/vite/manifest.js.map +0 -1
- package/dist/vite/resolve.d.ts +0 -9
- package/dist/vite/resolve.js +0 -90
- package/dist/vite/resolve.js.map +0 -1
package/dist/types.d.ts
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
export type JsonValue = null | boolean | number | string | readonly JsonValue[] | {
|
|
2
|
-
readonly [key: string]: JsonValue;
|
|
3
|
-
};
|
|
4
|
-
/** Exactly one source per dependency. Names and descriptors participate in cache identity. */
|
|
5
|
-
export type Dependency = {
|
|
6
|
-
readonly value: JsonValue;
|
|
7
|
-
readonly path?: never;
|
|
8
|
-
readonly url?: never;
|
|
9
|
-
readonly package?: never;
|
|
10
|
-
} | {
|
|
11
|
-
readonly path: string;
|
|
12
|
-
readonly value?: never;
|
|
13
|
-
readonly url?: never;
|
|
14
|
-
readonly package?: never;
|
|
15
|
-
} | {
|
|
16
|
-
readonly url: string;
|
|
17
|
-
readonly value?: never;
|
|
18
|
-
readonly path?: never;
|
|
19
|
-
readonly package?: never;
|
|
20
|
-
} | {
|
|
21
|
-
readonly package: string;
|
|
22
|
-
readonly value?: never;
|
|
23
|
-
readonly path?: never;
|
|
24
|
-
readonly url?: never;
|
|
25
|
-
};
|
|
26
|
-
export type Dependencies<D extends Dependency = Dependency> = Readonly<Record<string, D>>;
|
|
27
|
-
/** A dependency whose URL, if it had one, was resolved to a path. */
|
|
28
|
-
export type Resolved<D extends Dependency = Dependency> = Exclude<D, {
|
|
29
|
-
readonly url: string;
|
|
30
|
-
}>;
|
|
31
|
-
/** A file, URL, or package dependency: unlike a value, one whose current state can be checked again later. */
|
|
32
|
-
export type Checked<D extends Dependency = Dependency> = Exclude<D, {
|
|
33
|
-
readonly value: JsonValue;
|
|
34
|
-
}>;
|
|
35
|
-
/** A dependency passed to save(): only checked kinds, since values select the result. */
|
|
36
|
-
export type SavedDependency = Checked;
|
|
37
|
-
export type SavedDependencies = Dependencies<SavedDependency>;
|
|
38
|
-
/** A resolved checked dependency, a file path or a package: one whose current state can be hashed. */
|
|
39
|
-
export type Hashable = Resolved<Checked>;
|
|
40
|
-
export type Paths = Readonly<Record<string, string>>;
|
|
41
|
-
/** Dependency names mapped to file-content or installed-package-version hashes. */
|
|
42
|
-
export type Hashes = Readonly<Record<string, string>>;
|
|
43
|
-
/** Current dependency hashes, a missing dependency, or dependencies a browser without the plugin cannot check. */
|
|
44
|
-
export type Snapshot = {
|
|
45
|
-
readonly status: 'current';
|
|
46
|
-
readonly hashes: Hashes;
|
|
47
|
-
} | {
|
|
48
|
-
readonly status: 'missing';
|
|
49
|
-
readonly message: string;
|
|
50
|
-
} | {
|
|
51
|
-
readonly status: 'unchecked';
|
|
52
|
-
};
|
|
53
|
-
export interface CacheEntryOptions {
|
|
54
|
-
/** Identifies the computation and its implementation version, for example "simplify@2". */
|
|
55
|
-
version: string;
|
|
56
|
-
/** Named dependencies. JSON values affect the key; file contents and installed package versions are validated in Node or through the Vite plugin. Paths are always project-root-relative. URLs resolve to those paths through Vite, or from local file: URLs in Node. Packages track only the declared package's installed version, without importing it. */
|
|
57
|
-
dependencies?: Dependencies;
|
|
58
|
-
/** Disk directory in Node (default public/_vitecache); URL prefix in browsers (default /_vitecache/). Excluded from the key. */
|
|
59
|
-
basePath?: string;
|
|
60
|
-
/** Node project root, default process.cwd(). Browser dependencies resolve against the Vite root. Excluded from the key. */
|
|
61
|
-
root?: string;
|
|
62
|
-
}
|
|
63
|
-
export interface SaveOptions {
|
|
64
|
-
/**
|
|
65
|
-
* What the result was built from, when known only after computing it. They do not affect the key, so a save with
|
|
66
|
-
* different saved dependencies replaces the same entry. Rechecked by every load() where file contents are validated;
|
|
67
|
-
* a changed or missing one is a miss. Hashed when save() runs, so one that changed after the computation read it goes
|
|
68
|
-
* unnoticed until it changes again. One without a backing file makes save() throw MissingDependencyError. Values select
|
|
69
|
-
* the result, so they belong in the constructor.
|
|
70
|
-
*/
|
|
71
|
-
dependencies?: SavedDependencies;
|
|
72
|
-
}
|
|
73
|
-
export interface Stored {
|
|
74
|
-
bytes: Uint8Array;
|
|
75
|
-
hashes?: Hashes;
|
|
76
|
-
}
|
|
77
|
-
export interface Backend {
|
|
78
|
-
canSave(): Promise<boolean>;
|
|
79
|
-
resolve(dependencies: Dependencies): Promise<Dependencies<Resolved>>;
|
|
80
|
-
snapshot(dependencies: Dependencies<Hashable>): Promise<Snapshot>;
|
|
81
|
-
load(key: string): Promise<Stored | undefined>;
|
|
82
|
-
save(key: string, value: Uint8Array, check: {
|
|
83
|
-
/** Must still match `expected`. */
|
|
84
|
-
checked: Dependencies<Hashable>;
|
|
85
|
-
expected: Hashes;
|
|
86
|
-
/** Hashed now and rechecked on load. */
|
|
87
|
-
saved: Dependencies<Hashable>;
|
|
88
|
-
}): Promise<void>;
|
|
89
|
-
}
|
package/dist/types.js
DELETED
package/dist/types.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["export type JsonValue = null | boolean | number | string | readonly JsonValue[] | { readonly [key: string]: JsonValue };\n\n/** Exactly one source per dependency. Names and descriptors participate in cache identity. */\nexport type Dependency =\n | { readonly value: JsonValue; readonly path?: never; readonly url?: never; readonly package?: never }\n | { readonly path: string; readonly value?: never; readonly url?: never; readonly package?: never }\n | { readonly url: string; readonly value?: never; readonly path?: never; readonly package?: never }\n | { readonly package: string; readonly value?: never; readonly path?: never; readonly url?: never };\nexport type Dependencies<D extends Dependency = Dependency> = Readonly<Record<string, D>>;\n/** A dependency whose URL, if it had one, was resolved to a path. */\nexport type Resolved<D extends Dependency = Dependency> = Exclude<D, { readonly url: string }>;\n/** A file, URL, or package dependency: unlike a value, one whose current state can be checked again later. */\nexport type Checked<D extends Dependency = Dependency> = Exclude<D, { readonly value: JsonValue }>;\n/** A dependency passed to save(): only checked kinds, since values select the result. */\nexport type SavedDependency = Checked;\nexport type SavedDependencies = Dependencies<SavedDependency>;\n/** A resolved checked dependency, a file path or a package: one whose current state can be hashed. */\nexport type Hashable = Resolved<Checked>;\nexport type Paths = Readonly<Record<string, string>>;\n/** Dependency names mapped to file-content or installed-package-version hashes. */\nexport type Hashes = Readonly<Record<string, string>>;\n/** Current dependency hashes, a missing dependency, or dependencies a browser without the plugin cannot check. */\nexport type Snapshot =\n | { readonly status: 'current'; readonly hashes: Hashes }\n | { readonly status: 'missing'; readonly message: string }\n | { readonly status: 'unchecked' };\n\nexport interface CacheEntryOptions {\n /** Identifies the computation and its implementation version, for example \"simplify@2\". */\n version: string;\n /** Named dependencies. JSON values affect the key; file contents and installed package versions are validated in Node or through the Vite plugin. Paths are always project-root-relative. URLs resolve to those paths through Vite, or from local file: URLs in Node. Packages track only the declared package's installed version, without importing it. */\n dependencies?: Dependencies;\n /** Disk directory in Node (default public/_vitecache); URL prefix in browsers (default /_vitecache/). Excluded from the key. */\n basePath?: string;\n /** Node project root, default process.cwd(). Browser dependencies resolve against the Vite root. Excluded from the key. */\n root?: string;\n}\n\nexport interface SaveOptions {\n /**\n * What the result was built from, when known only after computing it. They do not affect the key, so a save with\n * different saved dependencies replaces the same entry. Rechecked by every load() where file contents are validated;\n * a changed or missing one is a miss. Hashed when save() runs, so one that changed after the computation read it goes\n * unnoticed until it changes again. One without a backing file makes save() throw MissingDependencyError. Values select\n * the result, so they belong in the constructor.\n */\n dependencies?: SavedDependencies;\n}\n\nexport interface Stored {\n bytes: Uint8Array;\n hashes?: Hashes;\n}\n\nexport interface Backend {\n canSave(): Promise<boolean>;\n resolve(dependencies: Dependencies): Promise<Dependencies<Resolved>>;\n snapshot(dependencies: Dependencies<Hashable>): Promise<Snapshot>;\n load(key: string): Promise<Stored | undefined>;\n save(key: string, value: Uint8Array, check: {\n /** Must still match `expected`. */\n checked: Dependencies<Hashable>;\n expected: Hashes;\n /** Hashed now and rechecked on load. */\n saved: Dependencies<Hashable>;\n }): Promise<void>;\n}\n"]}
|
package/dist/vite/index.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { Plugin } from 'vite';
|
|
2
|
-
export interface VitecacheOptions {
|
|
3
|
-
/** Cache directory relative to the Vite project root; must be inside publicDir. */
|
|
4
|
-
basePath?: string;
|
|
5
|
-
}
|
|
6
|
-
/** Persist and validate entries in development; preserve asset URL mappings in production builds. */
|
|
7
|
-
export declare function vitecache(options?: VitecacheOptions): Plugin;
|
|
8
|
-
export default vitecache;
|
package/dist/vite/index.js
DELETED
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
import { relative, resolve, sep } from 'node:path';
|
|
2
|
-
import * as disk from '../disk.js';
|
|
3
|
-
import { createStorage } from '../storage.js';
|
|
4
|
-
import { ChangedDependenciesError, dependencies, hashableDependencies, hashes, MissingDependencyError } from '../dependencies.js';
|
|
5
|
-
import { confine, RequestError, resolveDependencies } from './resolve.js';
|
|
6
|
-
import { assetUrl, publicPaths } from './manifest.js';
|
|
7
|
-
function status(error) {
|
|
8
|
-
if (error instanceof RequestError)
|
|
9
|
-
return error.status;
|
|
10
|
-
if (error instanceof ChangedDependenciesError)
|
|
11
|
-
return 409;
|
|
12
|
-
return 500;
|
|
13
|
-
}
|
|
14
|
-
function allowed(request) {
|
|
15
|
-
if (request.headers['sec-fetch-site'] === 'cross-site')
|
|
16
|
-
return false;
|
|
17
|
-
const origin = request.headers.origin;
|
|
18
|
-
if (!origin)
|
|
19
|
-
return true;
|
|
20
|
-
try {
|
|
21
|
-
const url = new URL(origin);
|
|
22
|
-
return (url.protocol === 'http:' || url.protocol === 'https:') && url.host === request.headers.host;
|
|
23
|
-
}
|
|
24
|
-
catch {
|
|
25
|
-
return false;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
async function body(request) {
|
|
29
|
-
const chunks = [];
|
|
30
|
-
for await (const value of request) {
|
|
31
|
-
const chunk = value;
|
|
32
|
-
if (!Buffer.isBuffer(chunk))
|
|
33
|
-
throw new RequestError(400, 'Expected a binary request body');
|
|
34
|
-
chunks.push(chunk);
|
|
35
|
-
}
|
|
36
|
-
return Buffer.concat(chunks);
|
|
37
|
-
}
|
|
38
|
-
function parse(value) {
|
|
39
|
-
try {
|
|
40
|
-
return JSON.parse(value);
|
|
41
|
-
}
|
|
42
|
-
catch {
|
|
43
|
-
throw new RequestError(400, 'Expected valid JSON');
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
function parseRequest(value, parser) {
|
|
47
|
-
try {
|
|
48
|
-
return parser(value);
|
|
49
|
-
}
|
|
50
|
-
catch (error) {
|
|
51
|
-
if (!(error instanceof TypeError))
|
|
52
|
-
throw error;
|
|
53
|
-
throw new RequestError(400, error.message);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
/** A save body: a 4-byte big-endian metadata length, that much JSON metadata, then the cached bytes. */
|
|
57
|
-
function upload(bytes) {
|
|
58
|
-
if (bytes.byteLength < 4)
|
|
59
|
-
throw new RequestError(400, 'Expected a metadata length');
|
|
60
|
-
const end = 4 + new DataView(bytes.buffer, bytes.byteOffset, 4).getUint32(0);
|
|
61
|
-
if (end > bytes.byteLength)
|
|
62
|
-
throw new RequestError(400, 'Truncated save metadata');
|
|
63
|
-
const metadata = parse(new TextDecoder().decode(bytes.subarray(4, end)));
|
|
64
|
-
if (typeof metadata !== 'object' || metadata === null || !('checked' in metadata) || !('expected' in metadata) || !('saved' in metadata)) {
|
|
65
|
-
throw new RequestError(400, 'Expected checked, expected, and saved');
|
|
66
|
-
}
|
|
67
|
-
return { metadata, value: bytes.subarray(end) };
|
|
68
|
-
}
|
|
69
|
-
/** The `dependencies` of a same-origin POST's JSON body. */
|
|
70
|
-
async function posted(request) {
|
|
71
|
-
if (!allowed(request))
|
|
72
|
-
throw new RequestError(403, 'Cross-origin requests are forbidden');
|
|
73
|
-
const value = parse(new TextDecoder().decode(await body(request)));
|
|
74
|
-
if (typeof value !== 'object' || value === null || !('dependencies' in value))
|
|
75
|
-
throw new RequestError(400, 'Expected dependencies');
|
|
76
|
-
return value.dependencies;
|
|
77
|
-
}
|
|
78
|
-
function sendJson(response, value) {
|
|
79
|
-
response.setHeader('Content-Type', 'application/json');
|
|
80
|
-
response.end(JSON.stringify(value));
|
|
81
|
-
}
|
|
82
|
-
async function respond(request, response, name, storage, server) {
|
|
83
|
-
const root = server.config.root;
|
|
84
|
-
response.setHeader('Cache-Control', 'no-store');
|
|
85
|
-
if (name === '__vitecache' && request.method === 'GET') {
|
|
86
|
-
sendJson(response, { vitecache: 1 });
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
if (name === '__vitecache/resolve' && request.method === 'POST') {
|
|
90
|
-
const deps = parseRequest(await posted(request), dependencies);
|
|
91
|
-
const origin = `${server.config.server.https ? 'https' : 'http'}://${request.headers.host}`;
|
|
92
|
-
sendJson(response, { dependencies: await resolveDependencies(server, deps, origin) });
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
if (name === '__vitecache/snapshot' && request.method === 'POST') {
|
|
96
|
-
const deps = parseRequest(await posted(request), hashableDependencies);
|
|
97
|
-
await confine(root, deps);
|
|
98
|
-
sendJson(response, await storage.snapshot(deps));
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
if (!/^[a-f0-9]{64}\.bin$/.test(name)) {
|
|
102
|
-
response.statusCode = 404;
|
|
103
|
-
response.end();
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
const key = name.slice(0, -4);
|
|
107
|
-
if (request.method === 'PUT') {
|
|
108
|
-
if (!allowed(request))
|
|
109
|
-
throw new RequestError(403, 'Cross-origin requests are forbidden');
|
|
110
|
-
const { metadata, value } = upload(await body(request));
|
|
111
|
-
const checked = parseRequest(metadata.checked, hashableDependencies);
|
|
112
|
-
const expected = parseRequest(metadata.expected, hashes);
|
|
113
|
-
const saved = parseRequest(metadata.saved, hashableDependencies);
|
|
114
|
-
await confine(root, checked);
|
|
115
|
-
await confine(root, saved);
|
|
116
|
-
await storage.save(key, value, { checked, expected, saved });
|
|
117
|
-
response.statusCode = 204;
|
|
118
|
-
response.end();
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
if (request.method !== 'GET') {
|
|
122
|
-
response.statusCode = 405;
|
|
123
|
-
response.setHeader('Allow', 'GET, PUT');
|
|
124
|
-
response.end();
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
const stored = await storage.load(key);
|
|
128
|
-
if (stored === undefined) {
|
|
129
|
-
// Browsers log every 404 fetch as an error, and a miss is an expected answer.
|
|
130
|
-
response.statusCode = 204;
|
|
131
|
-
response.end();
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
// Browsers keep the bytes and revalidate them on every load, so an unchanged entry costs a 304 rather than a download.
|
|
135
|
-
response.setHeader('Cache-Control', 'no-cache');
|
|
136
|
-
const tag = `"${stored.tag}"`;
|
|
137
|
-
response.setHeader('ETag', tag);
|
|
138
|
-
response.setHeader('X-Vitecache-Dependencies', encodeURIComponent(JSON.stringify(stored.hashes)));
|
|
139
|
-
if (request.headers['if-none-match'] === tag) {
|
|
140
|
-
response.statusCode = 304;
|
|
141
|
-
response.end();
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
response.setHeader('Content-Type', 'application/octet-stream');
|
|
145
|
-
response.setHeader('Content-Length', stored.bytes.byteLength);
|
|
146
|
-
response.end(stored.bytes);
|
|
147
|
-
}
|
|
148
|
-
/** Persist and validate entries in development; preserve asset URL mappings in production builds. */
|
|
149
|
-
export function vitecache(options = {}) {
|
|
150
|
-
let state;
|
|
151
|
-
return {
|
|
152
|
-
name: 'vitecache',
|
|
153
|
-
enforce: 'post',
|
|
154
|
-
async configResolved(config) {
|
|
155
|
-
if (!config.publicDir)
|
|
156
|
-
throw new Error('vitecache requires Vite publicDir');
|
|
157
|
-
const { root, directory } = disk.location({ root: config.root, ...options });
|
|
158
|
-
const path = relative(config.publicDir, directory);
|
|
159
|
-
if (!path || !disk.inside(config.publicDir, directory)) {
|
|
160
|
-
throw new Error('vitecache basePath must be a directory inside Vite publicDir');
|
|
161
|
-
}
|
|
162
|
-
const base = new URL(config.base, 'http://vitecache').pathname.replace(/\/$/, '');
|
|
163
|
-
state = {
|
|
164
|
-
storage: createStorage({ root, ...options }),
|
|
165
|
-
root,
|
|
166
|
-
directory,
|
|
167
|
-
config,
|
|
168
|
-
cachePath: path.split(sep).join('/'),
|
|
169
|
-
prefix: `${base}/${path.split(sep).map(encodeURIComponent).join('/')}/`,
|
|
170
|
-
};
|
|
171
|
-
await disk.ignore(root, directory);
|
|
172
|
-
},
|
|
173
|
-
async generateBundle(_options, bundle) {
|
|
174
|
-
const resolved = state;
|
|
175
|
-
if (!resolved)
|
|
176
|
-
throw new Error('vitecache configuration was not resolved');
|
|
177
|
-
const paths = new Map(Object.entries(await publicPaths(resolved.config, resolved.directory)));
|
|
178
|
-
for (const asset of Object.values(bundle)) {
|
|
179
|
-
if (asset.type !== 'asset')
|
|
180
|
-
continue;
|
|
181
|
-
const originals = [...new Set(asset.originalFileNames)];
|
|
182
|
-
if (originals.length !== 1)
|
|
183
|
-
continue;
|
|
184
|
-
const original = originals[0];
|
|
185
|
-
if (!original)
|
|
186
|
-
continue;
|
|
187
|
-
const file = resolve(resolved.root, original);
|
|
188
|
-
if (!disk.inside(resolved.root, file))
|
|
189
|
-
continue;
|
|
190
|
-
paths.set(assetUrl(asset.fileName), relative(resolved.root, file).split(sep).join('/'));
|
|
191
|
-
}
|
|
192
|
-
const manifest = { paths: Object.fromEntries(paths), root: '../'.repeat(resolved.cachePath.split('/').length + 1) };
|
|
193
|
-
this.emitFile({ type: 'asset', fileName: `${resolved.cachePath}/__vitecache/paths.json`, source: JSON.stringify(manifest) });
|
|
194
|
-
},
|
|
195
|
-
configureServer(server) {
|
|
196
|
-
const resolved = state;
|
|
197
|
-
if (!resolved)
|
|
198
|
-
throw new Error('vitecache configuration was not resolved');
|
|
199
|
-
server.middlewares.use((request, response, next) => {
|
|
200
|
-
const path = new URL(request.url ?? '/', 'http://vitecache').pathname;
|
|
201
|
-
if (!path.startsWith(resolved.prefix)) {
|
|
202
|
-
next();
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
void respond(request, response, path.slice(resolved.prefix.length), resolved.storage, server).catch((error) => {
|
|
206
|
-
// A missing dependency is an expected answer, as in a snapshot: a body, and no error status for browsers to log.
|
|
207
|
-
if (error instanceof MissingDependencyError) {
|
|
208
|
-
sendJson(response, { status: 'missing', message: error.message });
|
|
209
|
-
return;
|
|
210
|
-
}
|
|
211
|
-
response.statusCode = status(error);
|
|
212
|
-
response.setHeader('Content-Type', 'text/plain');
|
|
213
|
-
response.end(error instanceof Error ? error.message : 'vitecache request failed');
|
|
214
|
-
});
|
|
215
|
-
});
|
|
216
|
-
},
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
export default vitecache;
|
|
220
|
-
//# sourceMappingURL=index.js.map
|
package/dist/vite/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/vite/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { relative, resolve, sep } from 'node:path';\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport type { Plugin, ResolvedConfig, ViteDevServer } from 'vite';\nimport * as disk from '../disk.js';\nimport { createStorage } from '../storage.js';\nimport type { Storage } from '../storage.js';\nimport { ChangedDependenciesError, dependencies, hashableDependencies, hashes, MissingDependencyError } from '../dependencies.js';\nimport { confine, RequestError, resolveDependencies } from './resolve.js';\nimport { assetUrl, publicPaths } from './manifest.js';\n\nexport interface VitecacheOptions {\n /** Cache directory relative to the Vite project root; must be inside publicDir. */\n basePath?: string;\n}\n\nfunction status(error: unknown): number {\n if (error instanceof RequestError) return error.status;\n if (error instanceof ChangedDependenciesError) return 409;\n return 500;\n}\n\nfunction allowed(request: IncomingMessage): boolean {\n if (request.headers['sec-fetch-site'] === 'cross-site') return false;\n const origin = request.headers.origin;\n if (!origin) return true;\n try {\n const url = new URL(origin);\n return (url.protocol === 'http:' || url.protocol === 'https:') && url.host === request.headers.host;\n } catch {\n return false;\n }\n}\n\nasync function body(request: IncomingMessage): Promise<Uint8Array> {\n const chunks: Uint8Array[] = [];\n for await (const value of request) {\n const chunk: unknown = value;\n if (!Buffer.isBuffer(chunk)) throw new RequestError(400, 'Expected a binary request body');\n chunks.push(chunk);\n }\n return Buffer.concat(chunks);\n}\n\nfunction parse(value: string): unknown {\n try {\n return JSON.parse(value);\n } catch {\n throw new RequestError(400, 'Expected valid JSON');\n }\n}\n\nfunction parseRequest<T>(value: unknown, parser: (value: unknown) => T): T {\n try {\n return parser(value);\n } catch (error) {\n if (!(error instanceof TypeError)) throw error;\n throw new RequestError(400, error.message);\n }\n}\n\n/** A save body: a 4-byte big-endian metadata length, that much JSON metadata, then the cached bytes. */\nfunction upload(bytes: Uint8Array): { metadata: Record<string, unknown>; value: Uint8Array } {\n if (bytes.byteLength < 4) throw new RequestError(400, 'Expected a metadata length');\n const end = 4 + new DataView(bytes.buffer, bytes.byteOffset, 4).getUint32(0);\n if (end > bytes.byteLength) throw new RequestError(400, 'Truncated save metadata');\n const metadata = parse(new TextDecoder().decode(bytes.subarray(4, end)));\n if (typeof metadata !== 'object' || metadata === null || !('checked' in metadata) || !('expected' in metadata) || !('saved' in metadata)) {\n throw new RequestError(400, 'Expected checked, expected, and saved');\n }\n return { metadata, value: bytes.subarray(end) };\n}\n\n/** The `dependencies` of a same-origin POST's JSON body. */\nasync function posted(request: IncomingMessage): Promise<unknown> {\n if (!allowed(request)) throw new RequestError(403, 'Cross-origin requests are forbidden');\n const value = parse(new TextDecoder().decode(await body(request)));\n if (typeof value !== 'object' || value === null || !('dependencies' in value)) throw new RequestError(400, 'Expected dependencies');\n return value.dependencies;\n}\n\nfunction sendJson(response: ServerResponse, value: unknown): void {\n response.setHeader('Content-Type', 'application/json');\n response.end(JSON.stringify(value));\n}\n\nasync function respond(\n request: IncomingMessage,\n response: ServerResponse,\n name: string,\n storage: Storage,\n server: ViteDevServer,\n): Promise<void> {\n const root = server.config.root;\n response.setHeader('Cache-Control', 'no-store');\n if (name === '__vitecache' && request.method === 'GET') {\n sendJson(response, { vitecache: 1 });\n return;\n }\n if (name === '__vitecache/resolve' && request.method === 'POST') {\n const deps = parseRequest(await posted(request), dependencies);\n const origin = `${server.config.server.https ? 'https' : 'http'}://${request.headers.host}`;\n sendJson(response, { dependencies: await resolveDependencies(server, deps, origin) });\n return;\n }\n if (name === '__vitecache/snapshot' && request.method === 'POST') {\n const deps = parseRequest(await posted(request), hashableDependencies);\n await confine(root, deps);\n sendJson(response, await storage.snapshot(deps));\n return;\n }\n if (!/^[a-f0-9]{64}\\.bin$/.test(name)) {\n response.statusCode = 404;\n response.end();\n return;\n }\n const key = name.slice(0, -4);\n if (request.method === 'PUT') {\n if (!allowed(request)) throw new RequestError(403, 'Cross-origin requests are forbidden');\n const { metadata, value } = upload(await body(request));\n const checked = parseRequest(metadata.checked, hashableDependencies);\n const expected = parseRequest(metadata.expected, hashes);\n const saved = parseRequest(metadata.saved, hashableDependencies);\n await confine(root, checked);\n await confine(root, saved);\n await storage.save(key, value, { checked, expected, saved });\n response.statusCode = 204;\n response.end();\n return;\n }\n if (request.method !== 'GET') {\n response.statusCode = 405;\n response.setHeader('Allow', 'GET, PUT');\n response.end();\n return;\n }\n const stored = await storage.load(key);\n if (stored === undefined) {\n // Browsers log every 404 fetch as an error, and a miss is an expected answer.\n response.statusCode = 204;\n response.end();\n return;\n }\n // Browsers keep the bytes and revalidate them on every load, so an unchanged entry costs a 304 rather than a download.\n response.setHeader('Cache-Control', 'no-cache');\n const tag = `\"${stored.tag}\"`;\n response.setHeader('ETag', tag);\n response.setHeader('X-Vitecache-Dependencies', encodeURIComponent(JSON.stringify(stored.hashes)));\n if (request.headers['if-none-match'] === tag) {\n response.statusCode = 304;\n response.end();\n return;\n }\n response.setHeader('Content-Type', 'application/octet-stream');\n response.setHeader('Content-Length', stored.bytes.byteLength);\n response.end(stored.bytes);\n}\n\n/** Persist and validate entries in development; preserve asset URL mappings in production builds. */\nexport function vitecache(options: VitecacheOptions = {}): Plugin {\n let state: { storage: Storage; root: string; prefix: string; directory: string; config: ResolvedConfig; cachePath: string } | undefined;\n return {\n name: 'vitecache',\n enforce: 'post',\n async configResolved(config) {\n if (!config.publicDir) throw new Error('vitecache requires Vite publicDir');\n const { root, directory } = disk.location({ root: config.root, ...options });\n const path = relative(config.publicDir, directory);\n if (!path || !disk.inside(config.publicDir, directory)) {\n throw new Error('vitecache basePath must be a directory inside Vite publicDir');\n }\n const base = new URL(config.base, 'http://vitecache').pathname.replace(/\\/$/, '');\n state = {\n storage: createStorage({ root, ...options }),\n root,\n directory,\n config,\n cachePath: path.split(sep).join('/'),\n prefix: `${base}/${path.split(sep).map(encodeURIComponent).join('/')}/`,\n };\n await disk.ignore(root, directory);\n },\n async generateBundle(_options, bundle) {\n const resolved = state;\n if (!resolved) throw new Error('vitecache configuration was not resolved');\n const paths = new Map(Object.entries(await publicPaths(resolved.config, resolved.directory)));\n for (const asset of Object.values(bundle)) {\n if (asset.type !== 'asset') continue;\n const originals = [...new Set(asset.originalFileNames)];\n if (originals.length !== 1) continue;\n const original = originals[0];\n if (!original) continue;\n const file = resolve(resolved.root, original);\n if (!disk.inside(resolved.root, file)) continue;\n paths.set(assetUrl(asset.fileName), relative(resolved.root, file).split(sep).join('/'));\n }\n const manifest = { paths: Object.fromEntries(paths), root: '../'.repeat(resolved.cachePath.split('/').length + 1) };\n this.emitFile({ type: 'asset', fileName: `${resolved.cachePath}/__vitecache/paths.json`, source: JSON.stringify(manifest) });\n },\n configureServer(server) {\n const resolved = state;\n if (!resolved) throw new Error('vitecache configuration was not resolved');\n server.middlewares.use((request, response, next) => {\n const path = new URL(request.url ?? '/', 'http://vitecache').pathname;\n if (!path.startsWith(resolved.prefix)) {\n next();\n return;\n }\n void respond(request, response, path.slice(resolved.prefix.length), resolved.storage, server).catch((error: unknown) => {\n // A missing dependency is an expected answer, as in a snapshot: a body, and no error status for browsers to log.\n if (error instanceof MissingDependencyError) {\n sendJson(response, { status: 'missing', message: error.message });\n return;\n }\n response.statusCode = status(error);\n response.setHeader('Content-Type', 'text/plain');\n response.end(error instanceof Error ? error.message : 'vitecache request failed');\n });\n });\n },\n };\n}\n\nexport default vitecache;\n"]}
|
package/dist/vite/manifest.d.ts
DELETED
package/dist/vite/manifest.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { readdir } from 'node:fs/promises';
|
|
2
|
-
import { relative, resolve, sep } from 'node:path';
|
|
3
|
-
import * as disk from '../disk.js';
|
|
4
|
-
export function assetUrl(file) {
|
|
5
|
-
return file.split('/').map(encodeURIComponent).join('/');
|
|
6
|
-
}
|
|
7
|
-
export async function publicPaths(config, cacheDirectory) {
|
|
8
|
-
const paths = [];
|
|
9
|
-
async function visit(directory) {
|
|
10
|
-
let entries;
|
|
11
|
-
try {
|
|
12
|
-
entries = await readdir(directory, { withFileTypes: true });
|
|
13
|
-
}
|
|
14
|
-
catch (error) {
|
|
15
|
-
if (disk.notFound(error))
|
|
16
|
-
return;
|
|
17
|
-
throw error;
|
|
18
|
-
}
|
|
19
|
-
for (const entry of entries) {
|
|
20
|
-
const file = resolve(directory, entry.name);
|
|
21
|
-
if (disk.inside(cacheDirectory, file))
|
|
22
|
-
continue;
|
|
23
|
-
if (entry.isDirectory())
|
|
24
|
-
await visit(file);
|
|
25
|
-
else if (entry.isFile()) {
|
|
26
|
-
const publicPath = relative(config.publicDir, file).split(sep).join('/');
|
|
27
|
-
paths.push([assetUrl(publicPath), relative(config.root, file).split(sep).join('/')]);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
await visit(config.publicDir);
|
|
32
|
-
return Object.fromEntries(paths);
|
|
33
|
-
}
|
|
34
|
-
//# sourceMappingURL=manifest.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/vite/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAEnD,OAAO,KAAK,IAAI,MAAM,YAAY,CAAC;AAEnC,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAsB,EAAE,cAAsB;IAC9E,MAAM,KAAK,GAAuB,EAAE,CAAC;IACrC,KAAK,UAAU,KAAK,CAAC,SAAiB;QACpC,IAAI,OAAO,CAAC;QACZ,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,OAAO,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,OAAO;YACjC,MAAM,KAAK,CAAC;QACd,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAC5C,IAAI,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,IAAI,CAAC;gBAAE,SAAS;YAChD,IAAI,KAAK,CAAC,WAAW,EAAE;gBAAE,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;iBACtC,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;gBACxB,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACzE,KAAK,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACvF,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC9B,OAAO,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC","sourcesContent":["import { readdir } from 'node:fs/promises';\nimport { relative, resolve, sep } from 'node:path';\nimport type { ResolvedConfig } from 'vite';\nimport * as disk from '../disk.js';\n\nexport function assetUrl(file: string): string {\n return file.split('/').map(encodeURIComponent).join('/');\n}\n\nexport async function publicPaths(config: ResolvedConfig, cacheDirectory: string): Promise<Record<string, string>> {\n const paths: [string, string][] = [];\n async function visit(directory: string): Promise<void> {\n let entries;\n try {\n entries = await readdir(directory, { withFileTypes: true });\n } catch (error) {\n if (disk.notFound(error)) return;\n throw error;\n }\n for (const entry of entries) {\n const file = resolve(directory, entry.name);\n if (disk.inside(cacheDirectory, file)) continue;\n if (entry.isDirectory()) await visit(file);\n else if (entry.isFile()) {\n const publicPath = relative(config.publicDir, file).split(sep).join('/');\n paths.push([assetUrl(publicPath), relative(config.root, file).split(sep).join('/')]);\n }\n }\n }\n await visit(config.publicDir);\n return Object.fromEntries(paths);\n}\n"]}
|
package/dist/vite/resolve.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { ViteDevServer } from 'vite';
|
|
2
|
-
import type { Dependencies, Resolved } from '../types.js';
|
|
3
|
-
/** A request the plugin refuses, answered with `status` and the message. */
|
|
4
|
-
export declare class RequestError extends Error {
|
|
5
|
-
readonly status: number;
|
|
6
|
-
constructor(status: number, message: string);
|
|
7
|
-
}
|
|
8
|
-
export declare function confine(root: string, dependencies: Dependencies<Resolved>): Promise<void>;
|
|
9
|
-
export declare function resolveDependencies(server: ViteDevServer, dependencies: Dependencies, origin: string): Promise<Dependencies<Resolved>>;
|
package/dist/vite/resolve.js
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { realpath, stat } from 'node:fs/promises';
|
|
2
|
-
import { isAbsolute, resolve } from 'node:path';
|
|
3
|
-
import * as disk from '../disk.js';
|
|
4
|
-
import { MissingDependencyError } from '../dependencies.js';
|
|
5
|
-
/** A request the plugin refuses, answered with `status` and the message. */
|
|
6
|
-
export class RequestError extends Error {
|
|
7
|
-
status;
|
|
8
|
-
constructor(status, message) {
|
|
9
|
-
super(message);
|
|
10
|
-
this.status = status;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
function outsideRoot() {
|
|
14
|
-
return new RequestError(403, 'File dependencies must be inside the project root');
|
|
15
|
-
}
|
|
16
|
-
export async function confine(root, dependencies) {
|
|
17
|
-
const canonicalRoot = await realpath(root);
|
|
18
|
-
for (const dependency of Object.values(dependencies)) {
|
|
19
|
-
if (!('path' in dependency))
|
|
20
|
-
continue;
|
|
21
|
-
const path = resolve(root, dependency.path);
|
|
22
|
-
if (!disk.inside(root, path))
|
|
23
|
-
throw outsideRoot();
|
|
24
|
-
try {
|
|
25
|
-
if (!disk.inside(canonicalRoot, await realpath(path)))
|
|
26
|
-
throw outsideRoot();
|
|
27
|
-
}
|
|
28
|
-
catch (error) {
|
|
29
|
-
if (!disk.notFound(error))
|
|
30
|
-
throw error;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
async function isFile(path) {
|
|
35
|
-
try {
|
|
36
|
-
return (await stat(path)).isFile();
|
|
37
|
-
}
|
|
38
|
-
catch (error) {
|
|
39
|
-
if (!disk.notFound(error))
|
|
40
|
-
throw error;
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
function decoded(pathname) {
|
|
45
|
-
try {
|
|
46
|
-
return decodeURIComponent(pathname);
|
|
47
|
-
}
|
|
48
|
-
catch {
|
|
49
|
-
throw new RequestError(400, `Malformed file dependency URL: ${pathname}`);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
export async function resolveDependencies(server, dependencies, origin) {
|
|
53
|
-
const entries = [];
|
|
54
|
-
const base = new URL(server.config.base, origin).pathname;
|
|
55
|
-
for (const [name, dependency] of Object.entries(dependencies)) {
|
|
56
|
-
if (!('url' in dependency)) {
|
|
57
|
-
entries.push([name, dependency]);
|
|
58
|
-
continue;
|
|
59
|
-
}
|
|
60
|
-
const url = new URL(dependency.url, origin);
|
|
61
|
-
if (url.origin !== origin)
|
|
62
|
-
throw new RequestError(400, 'File dependency URLs must have the Vite server origin');
|
|
63
|
-
if (!url.pathname.startsWith(base))
|
|
64
|
-
throw new RequestError(400, 'File dependency URL is outside the Vite base');
|
|
65
|
-
const pathname = decoded(`/${url.pathname.slice(base.length)}`);
|
|
66
|
-
const publicFile = resolve(server.config.publicDir, `.${pathname}`);
|
|
67
|
-
const rootFile = resolve(server.config.root, `.${pathname}`);
|
|
68
|
-
let file;
|
|
69
|
-
if (await isFile(publicFile))
|
|
70
|
-
file = publicFile;
|
|
71
|
-
else if (pathname.startsWith('/@fs/'))
|
|
72
|
-
file = pathname.slice('/@fs'.length).replace(/^\/([A-Za-z]:\/)/, '$1');
|
|
73
|
-
else if (await isFile(rootFile))
|
|
74
|
-
file = rootFile;
|
|
75
|
-
else {
|
|
76
|
-
const module = await server.pluginContainer.resolveId(pathname);
|
|
77
|
-
// A virtual module is served without a file whose contents could be hashed.
|
|
78
|
-
if (!module || !isAbsolute(module.id))
|
|
79
|
-
throw new MissingDependencyError(`File dependency URL has no backing file: ${dependency.url}`);
|
|
80
|
-
file = module.id.split('?')[0] ?? module.id;
|
|
81
|
-
}
|
|
82
|
-
if (!await isFile(file))
|
|
83
|
-
throw new MissingDependencyError(`File dependency URL has no backing file: ${dependency.url}`);
|
|
84
|
-
entries.push([name, { path: await disk.rootRelative(server.config.root, file) }]);
|
|
85
|
-
}
|
|
86
|
-
const resolved = Object.fromEntries(entries);
|
|
87
|
-
await confine(server.config.root, resolved);
|
|
88
|
-
return resolved;
|
|
89
|
-
}
|
|
90
|
-
//# sourceMappingURL=resolve.js.map
|
package/dist/vite/resolve.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/vite/resolve.ts"],"names":[],"mappings":"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","sourcesContent":["import { realpath, stat } from 'node:fs/promises';\nimport { isAbsolute, resolve } from 'node:path';\nimport type { ViteDevServer } from 'vite';\nimport type { Dependencies, Resolved } from '../types.js';\nimport * as disk from '../disk.js';\nimport { MissingDependencyError } from '../dependencies.js';\n\n/** A request the plugin refuses, answered with `status` and the message. */\nexport class RequestError extends Error {\n constructor(readonly status: number, message: string) {\n super(message);\n }\n}\n\nfunction outsideRoot(): RequestError {\n return new RequestError(403, 'File dependencies must be inside the project root');\n}\n\nexport async function confine(root: string, dependencies: Dependencies<Resolved>): Promise<void> {\n const canonicalRoot = await realpath(root);\n for (const dependency of Object.values(dependencies)) {\n if (!('path' in dependency)) continue;\n const path = resolve(root, dependency.path);\n if (!disk.inside(root, path)) throw outsideRoot();\n try {\n if (!disk.inside(canonicalRoot, await realpath(path))) throw outsideRoot();\n } catch (error) {\n if (!disk.notFound(error)) throw error;\n }\n }\n}\n\nasync function isFile(path: string): Promise<boolean> {\n try {\n return (await stat(path)).isFile();\n } catch (error) {\n if (!disk.notFound(error)) throw error;\n return false;\n }\n}\n\nfunction decoded(pathname: string): string {\n try {\n return decodeURIComponent(pathname);\n } catch {\n throw new RequestError(400, `Malformed file dependency URL: ${pathname}`);\n }\n}\n\nexport async function resolveDependencies(server: ViteDevServer, dependencies: Dependencies, origin: string): Promise<Dependencies<Resolved>> {\n const entries: [string, Resolved][] = [];\n const base = new URL(server.config.base, origin).pathname;\n for (const [name, dependency] of Object.entries(dependencies)) {\n if (!('url' in dependency)) {\n entries.push([name, dependency]);\n continue;\n }\n const url = new URL(dependency.url, origin);\n if (url.origin !== origin) throw new RequestError(400, 'File dependency URLs must have the Vite server origin');\n if (!url.pathname.startsWith(base)) throw new RequestError(400, 'File dependency URL is outside the Vite base');\n const pathname = decoded(`/${url.pathname.slice(base.length)}`);\n const publicFile = resolve(server.config.publicDir, `.${pathname}`);\n const rootFile = resolve(server.config.root, `.${pathname}`);\n let file: string;\n if (await isFile(publicFile)) file = publicFile;\n else if (pathname.startsWith('/@fs/')) file = pathname.slice('/@fs'.length).replace(/^\\/([A-Za-z]:\\/)/, '$1');\n else if (await isFile(rootFile)) file = rootFile;\n else {\n const module = await server.pluginContainer.resolveId(pathname);\n // A virtual module is served without a file whose contents could be hashed.\n if (!module || !isAbsolute(module.id)) throw new MissingDependencyError(`File dependency URL has no backing file: ${dependency.url}`);\n file = module.id.split('?')[0] ?? module.id;\n }\n if (!await isFile(file)) throw new MissingDependencyError(`File dependency URL has no backing file: ${dependency.url}`);\n entries.push([name, { path: await disk.rootRelative(server.config.root, file) }]);\n }\n const resolved = Object.fromEntries(entries);\n await confine(server.config.root, resolved);\n return resolved;\n}\n"]}
|