vitecache 0.2.0 → 0.3.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 +2 -6
- package/dist/browser.d.ts +2 -1
- package/dist/browser.js +105 -58
- package/dist/browser.js.map +1 -1
- package/dist/dependencies.d.ts +17 -3
- package/dist/dependencies.js +40 -11
- package/dist/dependencies.js.map +1 -1
- package/dist/disk.d.ts +18 -1
- package/dist/disk.js +51 -6
- package/dist/disk.js.map +1 -1
- package/dist/entry.d.ts +13 -4
- package/dist/entry.js +56 -21
- package/dist/entry.js.map +1 -1
- package/dist/hash.d.ts +4 -0
- package/dist/hash.js +41 -0
- package/dist/hash.js.map +1 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/key.d.ts +2 -2
- package/dist/key.js.map +1 -1
- package/dist/node.d.ts +2 -1
- package/dist/node.js +1 -0
- package/dist/node.js.map +1 -1
- package/dist/packages.d.ts +5 -0
- package/dist/packages.js +40 -15
- package/dist/packages.js.map +1 -1
- package/dist/prune.d.ts +11 -0
- package/dist/prune.js +71 -0
- package/dist/prune.js.map +1 -0
- package/dist/storage.d.ts +11 -4
- package/dist/storage.js +60 -65
- package/dist/storage.js.map +1 -1
- package/dist/types.d.ts +44 -9
- package/dist/types.js.map +1 -1
- package/dist/vite/index.js +80 -70
- package/dist/vite/index.js.map +1 -1
- package/dist/vite/manifest.js +3 -3
- package/dist/vite/manifest.js.map +1 -1
- package/dist/vite/resolve.d.ts +7 -6
- package/dist/vite/resolve.js +35 -26
- package/dist/vite/resolve.js.map +1 -1
- package/package.json +5 -1
- package/skills/vitecache/SKILL.md +31 -5
package/README.md
CHANGED
|
@@ -29,11 +29,7 @@ if (bytes === undefined) {
|
|
|
29
29
|
useMeshBytes(bytes)
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
Entries identify computations by version and named dependencies: JSON `{ value }`, file `{ path }` or `{ url }`, and installed library `{ package: "
|
|
33
|
-
|
|
34
|
-
Paths are always relative to the project root: `root` in Node (the working directory by default), or the Vite project root in browsers. The Vite plugin resolves served URLs to their source paths and preserves mappings for public files and emitted assets in production builds; Node accepts local file URLs.
|
|
35
|
-
|
|
36
|
-
Package installation paths are excluded from identity; transitive packages need their own declarations. Load before computing so saving can detect dependencies that changed during computation.
|
|
32
|
+
Entries identify computations by version and named dependencies: JSON `{ value }`, file `{ path }` or `{ url }`, and installed library `{ package: "layout-engine" }`. Node and the Vite development plugin validate file contents and package versions without changing entry keys.
|
|
37
33
|
|
|
38
34
|
Node reads and writes `<project_root>/public/_vitecache/`. Add the plugin to save browser results into the same directory during development:
|
|
39
35
|
|
|
@@ -44,6 +40,6 @@ import { vitecache } from "vitecache/vite"
|
|
|
44
40
|
export default defineConfig({ plugins: [vitecache()] })
|
|
45
41
|
```
|
|
46
42
|
|
|
47
|
-
Node saves and the plugin add the cache directory to `.gitignore`. Generate caches before building and include them in your deployment. Browsers without the plugin read public cache files, assume dependencies unchanged, and warn and skip writes when `save()` is called.
|
|
43
|
+
Node saves and the plugin add the cache directory to `.gitignore`. Generate caches before building and include them in your deployment; `prune` from `vitecache/prune` removes entries no load or save has used since a given time. Browsers without the plugin read public cache files, assume dependencies unchanged, and warn and skip writes when `save()` is called.
|
|
48
44
|
|
|
49
45
|
For usage patterns, see the [vitecache skill](skills/vitecache/SKILL.md), also shipped in this package.
|
package/dist/browser.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Entry } from './entry.js';
|
|
2
2
|
import type { CacheEntryOptions } from './types.js';
|
|
3
|
-
export
|
|
3
|
+
export { ChangedDependenciesError, MissingDependencyError } from './dependencies.js';
|
|
4
|
+
export type { CacheEntryOptions, Dependency, Dependencies, JsonValue, SavedDependencies, SavedDependency, SaveOptions } from './types.js';
|
|
4
5
|
/** A persistent binary computation result. Pass a browser basePath matching the public cache URL, including any Vite base. */
|
|
5
6
|
export declare class CacheEntry extends Entry {
|
|
6
7
|
constructor(options: CacheEntryOptions);
|
package/dist/browser.js
CHANGED
|
@@ -1,31 +1,72 @@
|
|
|
1
|
-
import { hashes,
|
|
1
|
+
import { ChangedDependenciesError, hashes, MissingDependencyError, paths, resolvedDependencies } from './dependencies.js';
|
|
2
2
|
import { Entry } from './entry.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
3
|
+
export { ChangedDependenciesError, MissingDependencyError } from './dependencies.js';
|
|
4
|
+
/** Shares one request per URL across the page, and retries after a failure. */
|
|
5
|
+
function memoize(cache, url, request) {
|
|
6
|
+
const existing = cache.get(url.href);
|
|
7
|
+
if (existing)
|
|
8
|
+
return existing;
|
|
9
|
+
const pending = request(url).catch((error) => {
|
|
10
|
+
cache.delete(url.href);
|
|
11
|
+
throw error;
|
|
12
|
+
});
|
|
13
|
+
cache.set(url.href, pending);
|
|
14
|
+
return pending;
|
|
15
|
+
}
|
|
16
|
+
const discoveries = new Map();
|
|
17
|
+
async function discover(url) {
|
|
18
|
+
const response = await fetch(url, { cache: 'no-store' });
|
|
19
|
+
if (response.status === 404)
|
|
20
|
+
return false;
|
|
21
|
+
if (!response.ok)
|
|
22
|
+
throw new Error(`vitecache discovery failed: HTTP ${response.status}`);
|
|
23
|
+
// Static SPA servers may return index.html for unknown paths.
|
|
24
|
+
if (!response.headers.get('content-type')?.includes('application/json'))
|
|
25
|
+
return false;
|
|
26
|
+
const data = await response.json();
|
|
27
|
+
return typeof data === 'object' && data !== null && 'vitecache' in data && data.vitecache === 1;
|
|
28
|
+
}
|
|
29
|
+
const mappings = new Map();
|
|
30
|
+
/** The production build's served pathnames mapped to project-root-relative source paths. */
|
|
31
|
+
async function mapping(url) {
|
|
32
|
+
const response = await fetch(url, { cache: 'no-cache' });
|
|
33
|
+
if (!response.ok || !response.headers.get('content-type')?.includes('application/json')) {
|
|
34
|
+
throw new Error('URL dependencies require the vitecache Vite plugin during development and build. Missing production URL mapping.');
|
|
17
35
|
}
|
|
36
|
+
const data = await response.json();
|
|
37
|
+
const manifest = responseObject(data);
|
|
38
|
+
const mapped = paths(manifest.paths);
|
|
39
|
+
if (typeof manifest.root !== 'string' || !/^(?:\.\.\/)+$/.test(manifest.root))
|
|
40
|
+
throw new Error('Invalid vitecache production mapping root.');
|
|
41
|
+
const projectRoot = new URL(manifest.root, url);
|
|
42
|
+
return Object.fromEntries(Object.entries(mapped).map(([served, path]) => [new URL(served, projectRoot).pathname, path]));
|
|
43
|
+
}
|
|
44
|
+
/** A JSON object that the plugin or a build answered with. */
|
|
45
|
+
function responseObject(data) {
|
|
46
|
+
if (typeof data !== 'object' || data === null || Array.isArray(data))
|
|
47
|
+
throw new TypeError('Invalid vitecache response.');
|
|
48
|
+
return Object.fromEntries(Object.entries(data));
|
|
49
|
+
}
|
|
50
|
+
/** The plugin answers a missing file or package dependency with `{ status: 'missing', message }` on every route. */
|
|
51
|
+
function missingMessage(data) {
|
|
52
|
+
if (data.status !== 'missing')
|
|
53
|
+
return undefined;
|
|
54
|
+
if (typeof data.message !== 'string')
|
|
55
|
+
throw new TypeError('Invalid vitecache missing dependency response.');
|
|
56
|
+
return data.message;
|
|
57
|
+
}
|
|
58
|
+
function createBackend(options) {
|
|
59
|
+
const base = new URL(options.basePath ?? '/_vitecache/', globalThis.location.href);
|
|
60
|
+
base.pathname = `${base.pathname.replace(/\/+$/, '')}/`;
|
|
61
|
+
base.search = '';
|
|
62
|
+
base.hash = '';
|
|
18
63
|
function plugin() {
|
|
19
|
-
|
|
20
|
-
discovery = undefined;
|
|
21
|
-
throw error;
|
|
22
|
-
});
|
|
23
|
-
return discovery;
|
|
64
|
+
return memoize(discoveries, new URL('__vitecache', base), discover);
|
|
24
65
|
}
|
|
25
66
|
return {
|
|
26
67
|
canSave: plugin,
|
|
27
|
-
async resolve(
|
|
28
|
-
const locators = Object.entries(
|
|
68
|
+
async resolve(declared) {
|
|
69
|
+
const locators = Object.entries(declared).map(([name, locator]) => {
|
|
29
70
|
if (locator.url === undefined)
|
|
30
71
|
return [name, locator];
|
|
31
72
|
const url = new URL(locator.url, globalThis.location.href);
|
|
@@ -44,40 +85,33 @@ function createBackend(options) {
|
|
|
44
85
|
cache: 'no-store',
|
|
45
86
|
});
|
|
46
87
|
if (!response.ok)
|
|
47
|
-
throw new Error(`vitecache URL resolution failed: HTTP ${response.status}`);
|
|
48
|
-
const data = await response.json();
|
|
49
|
-
const
|
|
88
|
+
throw new Error(`vitecache URL resolution failed: HTTP ${response.status}: ${await response.text()}`);
|
|
89
|
+
const data = responseObject(await response.json());
|
|
90
|
+
const missing = missingMessage(data);
|
|
91
|
+
if (missing !== undefined)
|
|
92
|
+
throw new MissingDependencyError(missing);
|
|
93
|
+
const resolved = resolvedDependencies(data.dependencies);
|
|
50
94
|
if (Object.keys(resolved).length !== locators.length || !locators.every(([name]) => Object.hasOwn(resolved, name))) {
|
|
51
95
|
throw new Error('Invalid vitecache resolved dependencies.');
|
|
52
96
|
}
|
|
53
97
|
return resolved;
|
|
54
98
|
}
|
|
55
|
-
const
|
|
56
|
-
const response = await fetch(manifestUrl, { cache: 'no-store' });
|
|
57
|
-
if (!response.ok || !response.headers.get('content-type')?.includes('application/json')) {
|
|
58
|
-
throw new Error('URL dependencies require the vitecache Vite plugin during development and build. Missing production URL mapping.');
|
|
59
|
-
}
|
|
60
|
-
const data = await response.json();
|
|
61
|
-
const manifest = record(data);
|
|
62
|
-
const mapping = paths(manifest.paths);
|
|
63
|
-
if (typeof manifest.root !== 'string' || !/^(?:\.\.\/)+$/.test(manifest.root))
|
|
64
|
-
throw new Error('Invalid vitecache production mapping root.');
|
|
65
|
-
const projectRoot = new URL(manifest.root, manifestUrl);
|
|
66
|
-
const mapped = Object.fromEntries(Object.entries(mapping).map(([url, path]) => [new URL(url, projectRoot).pathname, path]));
|
|
99
|
+
const mapped = await memoize(mappings, new URL('__vitecache/paths.json', base), mapping);
|
|
67
100
|
const resolved = locators.map(([name, locator]) => {
|
|
68
101
|
if (locator.url === undefined)
|
|
69
102
|
return [name, locator];
|
|
70
103
|
const pathname = new URL(locator.url).pathname;
|
|
71
104
|
const path = mapped[pathname];
|
|
105
|
+
// The build maps every file it deployed, so an unmapped URL has no backing file, as the plugin reports in development.
|
|
72
106
|
if (path === undefined)
|
|
73
|
-
throw new
|
|
107
|
+
throw new MissingDependencyError(`No vitecache source file mapping for URL: ${pathname}`);
|
|
74
108
|
return [name, { path }];
|
|
75
109
|
});
|
|
76
110
|
return resolvedDependencies(Object.fromEntries(resolved));
|
|
77
111
|
},
|
|
78
112
|
async snapshot(dependencies) {
|
|
79
113
|
if (!await plugin())
|
|
80
|
-
return
|
|
114
|
+
return { status: 'unchecked' };
|
|
81
115
|
const response = await fetch(new URL('__vitecache/snapshot', base), {
|
|
82
116
|
method: 'POST',
|
|
83
117
|
headers: { 'Content-Type': 'application/json' },
|
|
@@ -85,16 +119,20 @@ function createBackend(options) {
|
|
|
85
119
|
cache: 'no-store',
|
|
86
120
|
});
|
|
87
121
|
if (!response.ok)
|
|
88
|
-
throw new Error(`vitecache dependency validation failed: HTTP ${response.status}`);
|
|
89
|
-
const data = await response.json();
|
|
90
|
-
|
|
122
|
+
throw new Error(`vitecache dependency validation failed: HTTP ${response.status}: ${await response.text()}`);
|
|
123
|
+
const data = responseObject(await response.json());
|
|
124
|
+
const missing = missingMessage(data);
|
|
125
|
+
if (missing !== undefined)
|
|
126
|
+
return { status: 'missing', message: missing };
|
|
127
|
+
if (data.status !== 'current')
|
|
91
128
|
throw new TypeError('Invalid vitecache dependency response.');
|
|
92
|
-
}
|
|
93
|
-
return data.hashes === null ? null : hashes(data.hashes);
|
|
129
|
+
return { status: 'current', hashes: hashes(data.hashes) };
|
|
94
130
|
},
|
|
95
|
-
async load(key
|
|
96
|
-
|
|
97
|
-
|
|
131
|
+
async load(key) {
|
|
132
|
+
// Entry names do not change with their contents, so cached bytes are revalidated before each use.
|
|
133
|
+
const response = await fetch(new URL(`${key}.bin`, base), { cache: 'no-cache' });
|
|
134
|
+
// The plugin answers misses with 204 so they stay out of the console; static hosts answer 404.
|
|
135
|
+
if (response.status === 204 || response.status === 404)
|
|
98
136
|
return undefined;
|
|
99
137
|
if (!response.ok)
|
|
100
138
|
throw new Error(`vitecache load failed: HTTP ${response.status}`);
|
|
@@ -104,26 +142,35 @@ function createBackend(options) {
|
|
|
104
142
|
if (contentType !== 'application/octet-stream')
|
|
105
143
|
throw new Error(`Unexpected vitecache content type: ${contentType ?? 'missing'}`);
|
|
106
144
|
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
107
|
-
|
|
108
|
-
return { bytes };
|
|
145
|
+
// Only the plugin sends hashes.
|
|
109
146
|
const header = response.headers.get('X-Vitecache-Dependencies');
|
|
110
147
|
if (header === null)
|
|
111
|
-
|
|
148
|
+
return { bytes };
|
|
112
149
|
const value = JSON.parse(decodeURIComponent(header));
|
|
113
150
|
return { bytes, hashes: hashes(value) };
|
|
114
151
|
},
|
|
115
|
-
async save(key, value,
|
|
152
|
+
async save(key, value, { checked, expected, saved }) {
|
|
153
|
+
// Metadata travels in the body: headers are capped near 16 KiB, and saved dependencies can be many.
|
|
154
|
+
const metadata = new TextEncoder().encode(JSON.stringify({ checked, expected, saved }));
|
|
155
|
+
const body = new Uint8Array(4 + metadata.byteLength + value.byteLength);
|
|
156
|
+
new DataView(body.buffer).setUint32(0, metadata.byteLength);
|
|
157
|
+
body.set(metadata, 4);
|
|
158
|
+
body.set(value, 4 + metadata.byteLength);
|
|
116
159
|
const response = await fetch(new URL(`${key}.bin`, base), {
|
|
117
160
|
method: 'PUT',
|
|
118
|
-
headers: {
|
|
119
|
-
|
|
120
|
-
'X-Vitecache-Dependencies': encodeURIComponent(JSON.stringify(dependencies)),
|
|
121
|
-
'X-Vitecache-Hashes': encodeURIComponent(JSON.stringify(expected)),
|
|
122
|
-
},
|
|
123
|
-
body: new Uint8Array(value),
|
|
161
|
+
headers: { 'Content-Type': 'application/octet-stream' },
|
|
162
|
+
body,
|
|
124
163
|
});
|
|
164
|
+
if (response.status === 409)
|
|
165
|
+
throw new ChangedDependenciesError();
|
|
125
166
|
if (!response.ok)
|
|
126
|
-
throw new Error(`vitecache save failed: HTTP ${response.status}`);
|
|
167
|
+
throw new Error(`vitecache save failed: HTTP ${response.status}: ${await response.text()}`);
|
|
168
|
+
if (response.status === 204)
|
|
169
|
+
return;
|
|
170
|
+
const missing = missingMessage(responseObject(await response.json()));
|
|
171
|
+
if (missing === undefined)
|
|
172
|
+
throw new TypeError('Invalid vitecache save response.');
|
|
173
|
+
throw new MissingDependencyError(missing);
|
|
127
174
|
},
|
|
128
175
|
};
|
|
129
176
|
}
|
package/dist/browser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"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","sourcesContent":["import { hashes, paths, record, resolvedDependencies } from './dependencies.js';\nimport { Entry } from './entry.js';\nimport type { Backend, CacheEntryOptions, Dependency, ResolvedDependency } from './types.js';\nexport type { CacheEntryOptions, Dependency, Dependencies, JsonValue } from './types.js';\n\nfunction createBackend(options: CacheEntryOptions): Backend {\n const base = new URL(`${(options.basePath ?? '/_vitecache/').replace(/\\/+$/, '')}/`, globalThis.location.href);\n let discovery: Promise<boolean> | undefined;\n\n async function discover(): Promise<boolean> {\n const response = await fetch(new URL('__vitecache', base), { cache: 'no-store' });\n if (response.status === 404) return false;\n if (!response.ok) throw new Error(`vitecache discovery failed: HTTP ${response.status}`);\n // Static SPA servers may return index.html for unknown paths.\n if (!response.headers.get('content-type')?.includes('application/json')) return false;\n const data: unknown = await response.json();\n return typeof data === 'object' && data !== null && 'vitecache' in data && data.vitecache === 1;\n }\n\n function plugin(): Promise<boolean> {\n discovery ??= discover().catch((error: unknown) => {\n discovery = undefined;\n throw error;\n });\n return discovery;\n }\n\n return {\n canSave: plugin,\n async resolve(dependencies) {\n const locators = Object.entries(dependencies).map(([name, locator]): [string, Dependency] => {\n if (locator.url === undefined) return [name, locator];\n const url = new URL(locator.url, globalThis.location.href);\n if (url.origin !== new URL(globalThis.location.href).origin) throw new Error('URL dependencies must be served by the same Vite project origin.');\n return [name, { url: url.href }];\n });\n if (locators.every(([, locator]) => locator.url === undefined)) {\n return resolvedDependencies(Object.fromEntries(locators));\n }\n if (await plugin()) {\n const response = await fetch(new URL('__vitecache/resolve', base), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ dependencies: Object.fromEntries(locators) }),\n cache: 'no-store',\n });\n if (!response.ok) throw new Error(`vitecache URL resolution failed: HTTP ${response.status}`);\n const data: unknown = await response.json();\n const resolved = resolvedDependencies(record(data).dependencies);\n if (Object.keys(resolved).length !== locators.length || !locators.every(([name]) => Object.hasOwn(resolved, name))) {\n throw new Error('Invalid vitecache resolved dependencies.');\n }\n return resolved;\n }\n const manifestUrl = new URL('__vitecache/paths.json', base);\n const response = await fetch(manifestUrl, { cache: 'no-store' });\n if (!response.ok || !response.headers.get('content-type')?.includes('application/json')) {\n throw new Error('URL dependencies require the vitecache Vite plugin during development and build. Missing production URL mapping.');\n }\n const data: unknown = await response.json();\n const manifest = record(data);\n const mapping = paths(manifest.paths);\n if (typeof manifest.root !== 'string' || !/^(?:\\.\\.\\/)+$/.test(manifest.root)) throw new Error('Invalid vitecache production mapping root.');\n const projectRoot = new URL(manifest.root, manifestUrl);\n const mapped = Object.fromEntries(Object.entries(mapping).map(([url, path]) => [new URL(url, projectRoot).pathname, path]));\n const resolved = locators.map(([name, locator]): [string, ResolvedDependency] => {\n if (locator.url === undefined) return [name, locator];\n const pathname = new URL(locator.url).pathname;\n const path = mapped[pathname];\n if (path === undefined) throw new Error(`No vitecache source file mapping for URL: ${pathname}`);\n return [name, { path }];\n });\n return resolvedDependencies(Object.fromEntries(resolved));\n },\n async snapshot(dependencies) {\n if (!await plugin()) return undefined;\n const response = await fetch(new URL('__vitecache/snapshot', base), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ dependencies }),\n cache: 'no-store',\n });\n if (!response.ok) throw new Error(`vitecache dependency validation failed: HTTP ${response.status}`);\n const data: unknown = await response.json();\n if (typeof data !== 'object' || data === null || !('hashes' in data)) {\n throw new TypeError('Invalid vitecache dependency response.');\n }\n return data.hashes === null ? null : hashes(data.hashes);\n },\n async load(key, validate) {\n const response = await fetch(new URL(`${key}.bin`, base), { cache: 'no-store' });\n if (response.status === 404) return undefined;\n if (!response.ok) throw new Error(`vitecache load failed: HTTP ${response.status}`);\n const contentType = response.headers.get('content-type')?.split(';')[0]?.trim();\n if (contentType === 'text/html') return undefined;\n if (contentType !== 'application/octet-stream') throw new Error(`Unexpected vitecache content type: ${contentType ?? 'missing'}`);\n const bytes = new Uint8Array(await response.arrayBuffer());\n if (!validate) return { bytes };\n const header = response.headers.get('X-Vitecache-Dependencies');\n if (header === null) throw new Error('Missing vitecache dependency metadata.');\n const value: unknown = JSON.parse(decodeURIComponent(header));\n return { bytes, hashes: hashes(value) };\n },\n async save(key, value, dependencies, expected) {\n const response = await fetch(new URL(`${key}.bin`, base), {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/octet-stream',\n 'X-Vitecache-Dependencies': encodeURIComponent(JSON.stringify(dependencies)),\n 'X-Vitecache-Hashes': encodeURIComponent(JSON.stringify(expected)),\n },\n body: new Uint8Array(value),\n });\n if (!response.ok) throw new Error(`vitecache save failed: HTTP ${response.status}`);\n },\n };\n}\n\n/** A persistent binary computation result. Pass a browser basePath matching the public cache URL, including any Vite base. */\nexport class CacheEntry extends Entry {\n constructor(options: CacheEntryOptions) {\n super(options, createBackend(options));\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChangedDependenciesError, hashes, MissingDependencyError, paths, resolvedDependencies } from './dependencies.js';\nimport { Entry } from './entry.js';\nimport type { Backend, CacheEntryOptions, Dependency, Paths, Resolved } from './types.js';\nexport { ChangedDependenciesError, MissingDependencyError } from './dependencies.js';\nexport type { CacheEntryOptions, Dependency, Dependencies, JsonValue, SavedDependencies, SavedDependency, SaveOptions } from './types.js';\n\n/** Shares one request per URL across the page, and retries after a failure. */\nfunction memoize<T>(cache: Map<string, Promise<T>>, url: URL, request: (url: URL) => Promise<T>): Promise<T> {\n const existing = cache.get(url.href);\n if (existing) return existing;\n const pending = request(url).catch((error: unknown) => {\n cache.delete(url.href);\n throw error;\n });\n cache.set(url.href, pending);\n return pending;\n}\n\nconst discoveries = new Map<string, Promise<boolean>>();\n\nasync function discover(url: URL): Promise<boolean> {\n const response = await fetch(url, { cache: 'no-store' });\n if (response.status === 404) return false;\n if (!response.ok) throw new Error(`vitecache discovery failed: HTTP ${response.status}`);\n // Static SPA servers may return index.html for unknown paths.\n if (!response.headers.get('content-type')?.includes('application/json')) return false;\n const data: unknown = await response.json();\n return typeof data === 'object' && data !== null && 'vitecache' in data && data.vitecache === 1;\n}\n\nconst mappings = new Map<string, Promise<Paths>>();\n\n/** The production build's served pathnames mapped to project-root-relative source paths. */\nasync function mapping(url: URL): Promise<Paths> {\n const response = await fetch(url, { cache: 'no-cache' });\n if (!response.ok || !response.headers.get('content-type')?.includes('application/json')) {\n throw new Error('URL dependencies require the vitecache Vite plugin during development and build. Missing production URL mapping.');\n }\n const data: unknown = await response.json();\n const manifest = responseObject(data);\n const mapped = paths(manifest.paths);\n if (typeof manifest.root !== 'string' || !/^(?:\\.\\.\\/)+$/.test(manifest.root)) throw new Error('Invalid vitecache production mapping root.');\n const projectRoot = new URL(manifest.root, url);\n return Object.fromEntries(Object.entries(mapped).map(([served, path]) => [new URL(served, projectRoot).pathname, path]));\n}\n\n/** A JSON object that the plugin or a build answered with. */\nfunction responseObject(data: unknown): Record<string, unknown> {\n if (typeof data !== 'object' || data === null || Array.isArray(data)) throw new TypeError('Invalid vitecache response.');\n return Object.fromEntries(Object.entries(data));\n}\n\n/** The plugin answers a missing file or package dependency with `{ status: 'missing', message }` on every route. */\nfunction missingMessage(data: Record<string, unknown>): string | undefined {\n if (data.status !== 'missing') return undefined;\n if (typeof data.message !== 'string') throw new TypeError('Invalid vitecache missing dependency response.');\n return data.message;\n}\n\nfunction createBackend(options: CacheEntryOptions): Backend {\n const base = new URL(options.basePath ?? '/_vitecache/', globalThis.location.href);\n base.pathname = `${base.pathname.replace(/\\/+$/, '')}/`;\n base.search = '';\n base.hash = '';\n\n function plugin(): Promise<boolean> {\n return memoize(discoveries, new URL('__vitecache', base), discover);\n }\n\n return {\n canSave: plugin,\n async resolve(declared) {\n const locators = Object.entries(declared).map(([name, locator]): [string, Dependency] => {\n if (locator.url === undefined) return [name, locator];\n const url = new URL(locator.url, globalThis.location.href);\n if (url.origin !== new URL(globalThis.location.href).origin) throw new Error('URL dependencies must be served by the same Vite project origin.');\n return [name, { url: url.href }];\n });\n if (locators.every(([, locator]) => locator.url === undefined)) {\n return resolvedDependencies(Object.fromEntries(locators));\n }\n if (await plugin()) {\n const response = await fetch(new URL('__vitecache/resolve', base), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ dependencies: Object.fromEntries(locators) }),\n cache: 'no-store',\n });\n if (!response.ok) throw new Error(`vitecache URL resolution failed: HTTP ${response.status}: ${await response.text()}`);\n const data = responseObject(await response.json());\n const missing = missingMessage(data);\n if (missing !== undefined) throw new MissingDependencyError(missing);\n const resolved = resolvedDependencies(data.dependencies);\n if (Object.keys(resolved).length !== locators.length || !locators.every(([name]) => Object.hasOwn(resolved, name))) {\n throw new Error('Invalid vitecache resolved dependencies.');\n }\n return resolved;\n }\n const mapped = await memoize(mappings, new URL('__vitecache/paths.json', base), mapping);\n const resolved = locators.map(([name, locator]): [string, Resolved] => {\n if (locator.url === undefined) return [name, locator];\n const pathname = new URL(locator.url).pathname;\n const path = mapped[pathname];\n // The build maps every file it deployed, so an unmapped URL has no backing file, as the plugin reports in development.\n if (path === undefined) throw new MissingDependencyError(`No vitecache source file mapping for URL: ${pathname}`);\n return [name, { path }];\n });\n return resolvedDependencies(Object.fromEntries(resolved));\n },\n async snapshot(dependencies) {\n if (!await plugin()) return { status: 'unchecked' };\n const response = await fetch(new URL('__vitecache/snapshot', base), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ dependencies }),\n cache: 'no-store',\n });\n if (!response.ok) throw new Error(`vitecache dependency validation failed: HTTP ${response.status}: ${await response.text()}`);\n const data = responseObject(await response.json());\n const missing = missingMessage(data);\n if (missing !== undefined) return { status: 'missing', message: missing };\n if (data.status !== 'current') throw new TypeError('Invalid vitecache dependency response.');\n return { status: 'current', hashes: hashes(data.hashes) };\n },\n async load(key) {\n // Entry names do not change with their contents, so cached bytes are revalidated before each use.\n const response = await fetch(new URL(`${key}.bin`, base), { cache: 'no-cache' });\n // The plugin answers misses with 204 so they stay out of the console; static hosts answer 404.\n if (response.status === 204 || response.status === 404) return undefined;\n if (!response.ok) throw new Error(`vitecache load failed: HTTP ${response.status}`);\n const contentType = response.headers.get('content-type')?.split(';')[0]?.trim();\n if (contentType === 'text/html') return undefined;\n if (contentType !== 'application/octet-stream') throw new Error(`Unexpected vitecache content type: ${contentType ?? 'missing'}`);\n const bytes = new Uint8Array(await response.arrayBuffer());\n // Only the plugin sends hashes.\n const header = response.headers.get('X-Vitecache-Dependencies');\n if (header === null) return { bytes };\n const value: unknown = JSON.parse(decodeURIComponent(header));\n return { bytes, hashes: hashes(value) };\n },\n async save(key, value, { checked, expected, saved }) {\n // Metadata travels in the body: headers are capped near 16 KiB, and saved dependencies can be many.\n const metadata = new TextEncoder().encode(JSON.stringify({ checked, expected, saved }));\n const body = new Uint8Array(4 + metadata.byteLength + value.byteLength);\n new DataView(body.buffer).setUint32(0, metadata.byteLength);\n body.set(metadata, 4);\n body.set(value, 4 + metadata.byteLength);\n const response = await fetch(new URL(`${key}.bin`, base), {\n method: 'PUT',\n headers: { 'Content-Type': 'application/octet-stream' },\n body,\n });\n if (response.status === 409) throw new ChangedDependenciesError();\n if (!response.ok) throw new Error(`vitecache save failed: HTTP ${response.status}: ${await response.text()}`);\n if (response.status === 204) return;\n const missing = missingMessage(responseObject(await response.json()));\n if (missing === undefined) throw new TypeError('Invalid vitecache save response.');\n throw new MissingDependencyError(missing);\n },\n };\n}\n\n/** A persistent binary computation result. Pass a browser basePath matching the public cache URL, including any Vite base. */\nexport class CacheEntry extends Entry {\n constructor(options: CacheEntryOptions) {\n super(options, createBackend(options));\n }\n}\n"]}
|
package/dist/dependencies.d.ts
CHANGED
|
@@ -1,9 +1,23 @@
|
|
|
1
|
-
import type { Dependencies, Hashes, JsonValue, Paths,
|
|
2
|
-
|
|
1
|
+
import type { Checked, Dependencies, Dependency, Hashable, Hashes, JsonValue, Paths, Resolved, SavedDependencies } from './types.js';
|
|
2
|
+
/** A file or package dependency has no backing file or installation, so its state cannot be checked. */
|
|
3
|
+
export declare class MissingDependencyError extends Error {
|
|
4
|
+
name: string;
|
|
5
|
+
}
|
|
6
|
+
/** A file or package dependency changed between load() and save(), so the result may be built from stale inputs. */
|
|
7
|
+
export declare class ChangedDependenciesError extends Error {
|
|
8
|
+
name: string;
|
|
9
|
+
constructor();
|
|
10
|
+
}
|
|
3
11
|
export declare function paths(value: unknown): Paths;
|
|
4
12
|
/** Validate and snapshot JSON before asynchronous dependency resolution starts. */
|
|
5
13
|
export declare function json(value: unknown, ancestors?: Set<object>): JsonValue;
|
|
6
14
|
export declare function dependencies(value: unknown): Dependencies;
|
|
7
|
-
export declare function
|
|
15
|
+
export declare function isChecked<D extends Dependency>(dependency: D): dependency is Checked<D>;
|
|
16
|
+
/** Dependencies after resolution, which turns URLs into paths. */
|
|
17
|
+
export declare function resolvedDependencies(value: unknown): Dependencies<Resolved>;
|
|
18
|
+
/** Saved dependencies are rechecked later, so they cannot be values: values select the result and belong to the key. */
|
|
19
|
+
export declare function savedDependencies(value: unknown): SavedDependencies;
|
|
20
|
+
/** Resolved file and package dependencies: the ones whose current state can be hashed. */
|
|
21
|
+
export declare function hashableDependencies(value: unknown): Dependencies<Hashable>;
|
|
8
22
|
export declare function hashes(value: unknown): Hashes;
|
|
9
23
|
export declare function equalHashes(first: Hashes, second: Hashes): boolean;
|
package/dist/dependencies.js
CHANGED
|
@@ -1,16 +1,28 @@
|
|
|
1
|
-
|
|
1
|
+
/** A file or package dependency has no backing file or installation, so its state cannot be checked. */
|
|
2
|
+
export class MissingDependencyError extends Error {
|
|
3
|
+
name = 'MissingDependencyError';
|
|
4
|
+
}
|
|
5
|
+
/** A file or package dependency changed between load() and save(), so the result may be built from stale inputs. */
|
|
6
|
+
export class ChangedDependenciesError extends Error {
|
|
7
|
+
name = 'ChangedDependenciesError';
|
|
8
|
+
constructor() {
|
|
9
|
+
super('vitecache dependencies changed during computation.');
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/** A plain object of named entries, sorted by name: dependencies, their values, paths or hashes. */
|
|
13
|
+
function record(value) {
|
|
2
14
|
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
3
|
-
throw new TypeError('Expected
|
|
15
|
+
throw new TypeError('Expected an object of named entries.');
|
|
4
16
|
}
|
|
5
17
|
const prototype = Object.getPrototypeOf(value);
|
|
6
18
|
if (prototype !== Object.prototype && prototype !== null)
|
|
7
|
-
throw new TypeError('Expected a plain
|
|
19
|
+
throw new TypeError('Expected a plain object of named entries.');
|
|
8
20
|
if (Object.getOwnPropertySymbols(value).length)
|
|
9
|
-
throw new TypeError('
|
|
21
|
+
throw new TypeError('Entry names must be strings.');
|
|
10
22
|
return Object.fromEntries(Object.keys(value).sort().map((name) => {
|
|
11
23
|
const property = Object.getOwnPropertyDescriptor(value, name);
|
|
12
24
|
if (!property || !('value' in property))
|
|
13
|
-
throw new TypeError('
|
|
25
|
+
throw new TypeError('Getters are not supported.');
|
|
14
26
|
const item = property.value;
|
|
15
27
|
return [name, item];
|
|
16
28
|
}));
|
|
@@ -95,13 +107,30 @@ export function dependencies(value) {
|
|
|
95
107
|
});
|
|
96
108
|
return Object.freeze(Object.fromEntries(entries));
|
|
97
109
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if (dependency
|
|
101
|
-
throw new TypeError(
|
|
110
|
+
function only(value, keep, message) {
|
|
111
|
+
return Object.freeze(Object.fromEntries(Object.entries(value).map(([name, dependency]) => {
|
|
112
|
+
if (!keep(dependency))
|
|
113
|
+
throw new TypeError(message);
|
|
102
114
|
return [name, dependency];
|
|
103
|
-
});
|
|
104
|
-
|
|
115
|
+
})));
|
|
116
|
+
}
|
|
117
|
+
function isResolved(dependency) {
|
|
118
|
+
return dependency.url === undefined;
|
|
119
|
+
}
|
|
120
|
+
export function isChecked(dependency) {
|
|
121
|
+
return dependency.value === undefined;
|
|
122
|
+
}
|
|
123
|
+
/** Dependencies after resolution, which turns URLs into paths. */
|
|
124
|
+
export function resolvedDependencies(value) {
|
|
125
|
+
return only(dependencies(value), isResolved, 'Expected resolved dependencies, not URLs.');
|
|
126
|
+
}
|
|
127
|
+
/** Saved dependencies are rechecked later, so they cannot be values: values select the result and belong to the key. */
|
|
128
|
+
export function savedDependencies(value) {
|
|
129
|
+
return only(dependencies(value), isChecked, 'Saved dependencies cannot be values: values select the result; pass them to the constructor.');
|
|
130
|
+
}
|
|
131
|
+
/** Resolved file and package dependencies: the ones whose current state can be hashed. */
|
|
132
|
+
export function hashableDependencies(value) {
|
|
133
|
+
return only(dependencies(value), (dependency) => isChecked(dependency) && isResolved(dependency), 'Expected file paths and packages, not values or URLs.');
|
|
105
134
|
}
|
|
106
135
|
export function hashes(value) {
|
|
107
136
|
return Object.freeze(Object.fromEntries(Object.entries(record(value)).map(([name, hash]) => {
|
package/dist/dependencies.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dependencies.js","sourceRoot":"","sources":["../src/dependencies.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,MAAM,CAAC,KAAc;IACnC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxE,MAAM,IAAI,SAAS,CAAC,qCAAqC,CAAC,CAAC;IAC7D,CAAC;IACD,MAAM,SAAS,GAAY,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IACxD,IAAI,SAAS,KAAK,MAAM,CAAC,SAAS,IAAI,SAAS,KAAK,IAAI;QAAE,MAAM,IAAI,SAAS,CAAC,qCAAqC,CAAC,CAAC;IACrH,IAAI,MAAM,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,MAAM;QAAE,MAAM,IAAI,SAAS,CAAC,mCAAmC,CAAC,CAAC;IACzG,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAC/D,MAAM,QAAQ,GAAG,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAC9D,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,OAAO,IAAI,QAAQ,CAAC;YAAE,MAAM,IAAI,SAAS,CAAC,uCAAuC,CAAC,CAAC;QACtG,MAAM,IAAI,GAAY,QAAQ,CAAC,KAAK,CAAC;QACrC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACtB,CAAC,CAAC,CAAC,CAAC;AACN,CAAC;AAED,SAAS,IAAI,CAAC,KAAc;IAC1B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,2CAA2C,CAAC,CAAC;IAClI,IAAI,0CAA0C,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3D,MAAM,IAAI,SAAS,CAAC,6DAA6D,CAAC,CAAC;IACrF,CAAC;IACD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACxD,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,GAAG;YAAE,SAAS;QACpC,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjB,SAAS;QACX,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,MAAM;YAAE,MAAM,IAAI,SAAS,CAAC,0DAA0D,CAAC,CAAC;QACnG,KAAK,CAAC,GAAG,EAAE,CAAC;IACd,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,MAAM,IAAI,SAAS,CAAC,8DAA8D,CAAC,CAAC;IACvG,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,KAAc;IAClC,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE;QAC1F,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,SAAS,CAAC,2CAA2C,CAAC,CAAC;QAC5E,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC,CAAC,CAAC;AACP,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,IAAI,CAAC,KAAc,EAAE,YAAY,IAAI,GAAG,EAAU;IAChE,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAC5F,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACtE,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,MAAM,IAAI,SAAS,CAAC,kDAAkD,CAAC,CAAC;IACvG,IAAI,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,4CAA4C,CAAC,CAAC;IAC5F,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACrB,IAAI,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAAE,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxJ,IAAI,MAAM,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,MAAM;YAAE,MAAM,IAAI,SAAS,CAAC,uDAAuD,CAAC,CAAC;QAC7H,MAAM,KAAK,GAAgB,EAAE,CAAC;QAC9B,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;YAClD,MAAM,QAAQ,GAAG,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YAC/D,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,OAAO,IAAI,QAAQ,CAAC;gBAAE,MAAM,IAAI,SAAS,CAAC,8DAA8D,CAAC,CAAC;YAC7H,MAAM,IAAI,GAAY,QAAQ,CAAC,KAAK,CAAC;YACrC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;QACpC,CAAC;QACD,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;YAAS,CAAC;QACT,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAwB,EAAE;QACxF,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,SAAS,CAAC,sCAAsC,CAAC,CAAC;QACvE,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAC7B,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,SAAS,CAAC,qEAAqE,CAAC,CAAC;QACjI,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;YAAE,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;QAChG,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;YAAE,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7F,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/G,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,IAAI,qDAAqD,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YACzJ,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC5D,CAAC;QACD,MAAM,IAAI,SAAS,CAAC,8GAA8G,CAAC,CAAC;IACtI,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAc;IACjD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,UAAU,CAAC,EAAgC,EAAE;QAC3G,IAAI,UAAU,CAAC,GAAG,KAAK,SAAS;YAAE,MAAM,IAAI,SAAS,CAAC,2CAA2C,CAAC,CAAC;QACnG,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,KAAc;IACnC,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;QACzF,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACtE,MAAM,IAAI,SAAS,CAAC,+BAA+B,CAAC,CAAC;QACvD,CAAC;QACD,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACtB,CAAC,CAAC,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,MAAc;IACvD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjC,OAAO,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AAC5G,CAAC","sourcesContent":["import type { Dependencies, Dependency, Hashes, JsonValue, Paths, ResolvedDependencies, ResolvedDependency } from './types.js';\n\nexport function record(value: unknown): Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new TypeError('Expected a named dependency record.');\n }\n const prototype: unknown = Object.getPrototypeOf(value);\n if (prototype !== Object.prototype && prototype !== null) throw new TypeError('Expected a plain dependency record.');\n if (Object.getOwnPropertySymbols(value).length) throw new TypeError('Dependency names must be strings.');\n return Object.fromEntries(Object.keys(value).sort().map((name) => {\n const property = Object.getOwnPropertyDescriptor(value, name);\n if (!property || !('value' in property)) throw new TypeError('Dependency getters are not supported.');\n const item: unknown = property.value;\n return [name, item];\n }));\n}\n\nfunction path(value: unknown): string {\n if (typeof value !== 'string' || !value || value.includes('\\0')) throw new TypeError('File dependencies require nonempty paths.');\n if (/^(?:[\\\\/]|[a-z]:|[a-z][a-z\\d+.-]*:\\/\\/)/i.test(value)) {\n throw new TypeError('File dependency paths must be relative to the project root.');\n }\n const parts: string[] = [];\n for (const part of value.replace(/\\\\/g, '/').split('/')) {\n if (!part || part === '.') continue;\n if (part !== '..') {\n parts.push(part);\n continue;\n }\n if (!parts.length) throw new TypeError('File dependency paths must stay inside the project root.');\n parts.pop();\n }\n if (!parts.length) throw new TypeError('File dependencies must identify files, not the project root.');\n return parts.join('/');\n}\n\nexport function paths(value: unknown): Paths {\n return Object.freeze(Object.fromEntries(Object.entries(record(value)).map(([name, value]) => {\n if (!name) throw new TypeError('File dependencies require nonempty names.');\n return [name, path(value)];\n })));\n}\n\n/** Validate and snapshot JSON before asynchronous dependency resolution starts. */\nexport function json(value: unknown, ancestors = new Set<object>()): JsonValue {\n if (value === null || typeof value === 'string' || typeof value === 'boolean') return value;\n if (typeof value === 'number' && Number.isFinite(value)) return value;\n if (typeof value !== 'object') throw new TypeError('Dependency values must contain only JSON values.');\n if (ancestors.has(value)) throw new TypeError('Dependency values must not contain cycles.');\n ancestors.add(value);\n try {\n if (!Array.isArray(value)) return Object.freeze(Object.fromEntries(Object.entries(record(value)).map(([name, item]) => [name, json(item, ancestors)])));\n if (Object.getOwnPropertySymbols(value).length) throw new TypeError('Dependency values must not contain symbol properties.');\n const items: JsonValue[] = [];\n for (let index = 0; index < value.length; index++) {\n const property = Object.getOwnPropertyDescriptor(value, index);\n if (!property || !('value' in property)) throw new TypeError('Dependency values must not contain sparse arrays or getters.');\n const item: unknown = property.value;\n items.push(json(item, ancestors));\n }\n return Object.freeze(items);\n } finally {\n ancestors.delete(value);\n }\n}\n\nexport function dependencies(value: unknown): Dependencies {\n const entries = Object.entries(record(value)).map(([name, value]): [string, Dependency] => {\n if (!name) throw new TypeError('Dependencies require nonempty names.');\n const source = record(value);\n if (Object.keys(source).length !== 1) throw new TypeError('Each dependency must have exactly one value, path, url, or package.');\n if (Object.hasOwn(source, 'value')) return [name, Object.freeze({ value: json(source.value) })];\n if (Object.hasOwn(source, 'path')) return [name, Object.freeze({ path: path(source.path) })];\n if (Object.hasOwn(source, 'url') && typeof source.url === 'string' && source.url && !source.url.includes('\\0')) {\n return [name, Object.freeze({ url: source.url })];\n }\n if (Object.hasOwn(source, 'package') && typeof source.package === 'string' && /^(?:@[a-z0-9][a-z0-9._-]*\\/)?[a-z0-9][a-z0-9._-]*$/i.test(source.package)) {\n return [name, Object.freeze({ package: source.package })];\n }\n throw new TypeError('Each dependency must have a JSON value, root-relative path, nonempty URL, or package name without a subpath.');\n });\n return Object.freeze(Object.fromEntries(entries));\n}\n\nexport function resolvedDependencies(value: unknown): ResolvedDependencies {\n const entries = Object.entries(dependencies(value)).map(([name, dependency]): [string, ResolvedDependency] => {\n if (dependency.url !== undefined) throw new TypeError('Expected resolved dependencies, not URLs.');\n return [name, dependency];\n });\n return Object.freeze(Object.fromEntries(entries));\n}\n\nexport function hashes(value: unknown): Hashes {\n return Object.freeze(Object.fromEntries(Object.entries(record(value)).map(([name, hash]) => {\n if (!name || typeof hash !== 'string' || !/^[a-f0-9]{64}$/.test(hash)) {\n throw new TypeError('Invalid file dependency hash.');\n }\n return [name, hash];\n })));\n}\n\nexport function equalHashes(first: Hashes, second: Hashes): boolean {\n const names = Object.keys(first);\n return names.length === Object.keys(second).length && names.every((name) => first[name] === second[name]);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"dependencies.js","sourceRoot":"","sources":["../src/dependencies.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Checked, Dependencies, Dependency, Hashable, Hashes, JsonValue, Paths, Resolved, SavedDependencies } from './types.js';\n\n/** A file or package dependency has no backing file or installation, so its state cannot be checked. */\nexport class MissingDependencyError extends Error {\n override name = 'MissingDependencyError';\n}\n\n/** A file or package dependency changed between load() and save(), so the result may be built from stale inputs. */\nexport class ChangedDependenciesError extends Error {\n override name = 'ChangedDependenciesError';\n constructor() {\n super('vitecache dependencies changed during computation.');\n }\n}\n\n/** A plain object of named entries, sorted by name: dependencies, their values, paths or hashes. */\nfunction record(value: unknown): Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new TypeError('Expected an object of named entries.');\n }\n const prototype: unknown = Object.getPrototypeOf(value);\n if (prototype !== Object.prototype && prototype !== null) throw new TypeError('Expected a plain object of named entries.');\n if (Object.getOwnPropertySymbols(value).length) throw new TypeError('Entry names must be strings.');\n return Object.fromEntries(Object.keys(value).sort().map((name) => {\n const property = Object.getOwnPropertyDescriptor(value, name);\n if (!property || !('value' in property)) throw new TypeError('Getters are not supported.');\n const item: unknown = property.value;\n return [name, item];\n }));\n}\n\nfunction path(value: unknown): string {\n if (typeof value !== 'string' || !value || value.includes('\\0')) throw new TypeError('File dependencies require nonempty paths.');\n if (/^(?:[\\\\/]|[a-z]:|[a-z][a-z\\d+.-]*:\\/\\/)/i.test(value)) {\n throw new TypeError('File dependency paths must be relative to the project root.');\n }\n const parts: string[] = [];\n for (const part of value.replace(/\\\\/g, '/').split('/')) {\n if (!part || part === '.') continue;\n if (part !== '..') {\n parts.push(part);\n continue;\n }\n if (!parts.length) throw new TypeError('File dependency paths must stay inside the project root.');\n parts.pop();\n }\n if (!parts.length) throw new TypeError('File dependencies must identify files, not the project root.');\n return parts.join('/');\n}\n\nexport function paths(value: unknown): Paths {\n return Object.freeze(Object.fromEntries(Object.entries(record(value)).map(([name, value]) => {\n if (!name) throw new TypeError('File dependencies require nonempty names.');\n return [name, path(value)];\n })));\n}\n\n/** Validate and snapshot JSON before asynchronous dependency resolution starts. */\nexport function json(value: unknown, ancestors = new Set<object>()): JsonValue {\n if (value === null || typeof value === 'string' || typeof value === 'boolean') return value;\n if (typeof value === 'number' && Number.isFinite(value)) return value;\n if (typeof value !== 'object') throw new TypeError('Dependency values must contain only JSON values.');\n if (ancestors.has(value)) throw new TypeError('Dependency values must not contain cycles.');\n ancestors.add(value);\n try {\n if (!Array.isArray(value)) return Object.freeze(Object.fromEntries(Object.entries(record(value)).map(([name, item]) => [name, json(item, ancestors)])));\n if (Object.getOwnPropertySymbols(value).length) throw new TypeError('Dependency values must not contain symbol properties.');\n const items: JsonValue[] = [];\n for (let index = 0; index < value.length; index++) {\n const property = Object.getOwnPropertyDescriptor(value, index);\n if (!property || !('value' in property)) throw new TypeError('Dependency values must not contain sparse arrays or getters.');\n const item: unknown = property.value;\n items.push(json(item, ancestors));\n }\n return Object.freeze(items);\n } finally {\n ancestors.delete(value);\n }\n}\n\nexport function dependencies(value: unknown): Dependencies {\n const entries = Object.entries(record(value)).map(([name, value]): [string, Dependency] => {\n if (!name) throw new TypeError('Dependencies require nonempty names.');\n const source = record(value);\n if (Object.keys(source).length !== 1) throw new TypeError('Each dependency must have exactly one value, path, url, or package.');\n if (Object.hasOwn(source, 'value')) return [name, Object.freeze({ value: json(source.value) })];\n if (Object.hasOwn(source, 'path')) return [name, Object.freeze({ path: path(source.path) })];\n if (Object.hasOwn(source, 'url') && typeof source.url === 'string' && source.url && !source.url.includes('\\0')) {\n return [name, Object.freeze({ url: source.url })];\n }\n if (Object.hasOwn(source, 'package') && typeof source.package === 'string' && /^(?:@[a-z0-9][a-z0-9._-]*\\/)?[a-z0-9][a-z0-9._-]*$/i.test(source.package)) {\n return [name, Object.freeze({ package: source.package })];\n }\n throw new TypeError('Each dependency must have a JSON value, root-relative path, nonempty URL, or package name without a subpath.');\n });\n return Object.freeze(Object.fromEntries(entries));\n}\n\nfunction only<D extends Dependency, K extends D>(value: Dependencies<D>, keep: (dependency: D) => dependency is K, message: string): Dependencies<K> {\n return Object.freeze(Object.fromEntries(Object.entries(value).map(([name, dependency]) => {\n if (!keep(dependency)) throw new TypeError(message);\n return [name, dependency] as const;\n })));\n}\n\nfunction isResolved<D extends Dependency>(dependency: D): dependency is Resolved<D> {\n return dependency.url === undefined;\n}\n\nexport function isChecked<D extends Dependency>(dependency: D): dependency is Checked<D> {\n return dependency.value === undefined;\n}\n\n/** Dependencies after resolution, which turns URLs into paths. */\nexport function resolvedDependencies(value: unknown): Dependencies<Resolved> {\n return only(dependencies(value), isResolved, 'Expected resolved dependencies, not URLs.');\n}\n\n/** Saved dependencies are rechecked later, so they cannot be values: values select the result and belong to the key. */\nexport function savedDependencies(value: unknown): SavedDependencies {\n return only(dependencies(value), isChecked, 'Saved dependencies cannot be values: values select the result; pass them to the constructor.');\n}\n\n/** Resolved file and package dependencies: the ones whose current state can be hashed. */\nexport function hashableDependencies(value: unknown): Dependencies<Hashable> {\n return only(dependencies(value), (dependency): dependency is Hashable => isChecked(dependency) && isResolved(dependency), 'Expected file paths and packages, not values or URLs.');\n}\n\nexport function hashes(value: unknown): Hashes {\n return Object.freeze(Object.fromEntries(Object.entries(record(value)).map(([name, hash]) => {\n if (!name || typeof hash !== 'string' || !/^[a-f0-9]{64}$/.test(hash)) {\n throw new TypeError('Invalid file dependency hash.');\n }\n return [name, hash];\n })));\n}\n\nexport function equalHashes(first: Hashes, second: Hashes): boolean {\n const names = Object.keys(first);\n return names.length === Object.keys(second).length && names.every((name) => first[name] === second[name]);\n}\n"]}
|
package/dist/disk.d.ts
CHANGED
|
@@ -1,10 +1,27 @@
|
|
|
1
1
|
import type { CacheEntryOptions } from './types.js';
|
|
2
2
|
export declare function missing(error: unknown): boolean;
|
|
3
|
-
|
|
3
|
+
/** A filesystem error for a path that does not exist, also below a path component that is a file. */
|
|
4
|
+
export declare function notFound(error: unknown): boolean;
|
|
5
|
+
/** Whether `path` is `root` or below it, compared lexically. */
|
|
6
|
+
export declare function inside(root: string, path: string): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* `file` relative to `root`, with `/` separators. A file that lies outside `root` only lexically, as through a symlinked
|
|
9
|
+
* root, is related by real paths instead.
|
|
10
|
+
*/
|
|
11
|
+
export declare function rootRelative(root: string, file: string): Promise<string>;
|
|
4
12
|
export declare function location(options: Pick<CacheEntryOptions, 'root' | 'basePath'>): {
|
|
5
13
|
root: string;
|
|
6
14
|
directory: string;
|
|
7
15
|
};
|
|
8
16
|
export declare function ignore(root: string, directory: string): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* A file's bytes as a plain Uint8Array that owns its whole ArrayBuffer, as a browser's response gives them. A Buffer's
|
|
19
|
+
* slice() shares its memory, so a slice whose buffer is transferred to a worker would detach the bytes it came from.
|
|
20
|
+
*/
|
|
9
21
|
export declare function load(path: string): Promise<Uint8Array | undefined>;
|
|
10
22
|
export declare function save(path: string, value: Uint8Array, beforeCommit?: () => Promise<void>): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Sets a file's modification time to now; a file that no longer exists is left alone. Where this process may not change
|
|
25
|
+
* it, as on a read-only deployment, it warns once per directory instead of failing the read that called it.
|
|
26
|
+
*/
|
|
27
|
+
export declare function touch(path: string): Promise<void>;
|
package/dist/disk.js
CHANGED
|
@@ -1,11 +1,28 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import { appendFile, mkdir, readFile, rename, unlink, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { appendFile, mkdir, readFile, realpath, rename, unlink, utimes, writeFile } from 'node:fs/promises';
|
|
3
3
|
import { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
4
|
+
function code(error) {
|
|
5
|
+
return error instanceof Error && 'code' in error ? error.code : undefined;
|
|
6
|
+
}
|
|
4
7
|
export function missing(error) {
|
|
5
|
-
return
|
|
8
|
+
return code(error) === 'ENOENT';
|
|
9
|
+
}
|
|
10
|
+
/** A filesystem error for a path that does not exist, also below a path component that is a file. */
|
|
11
|
+
export function notFound(error) {
|
|
12
|
+
return missing(error) || code(error) === 'ENOTDIR';
|
|
13
|
+
}
|
|
14
|
+
/** Whether `path` is `root` or below it, compared lexically. */
|
|
15
|
+
export function inside(root, path) {
|
|
16
|
+
const name = relative(root, path);
|
|
17
|
+
return name !== '..' && !name.startsWith(`..${sep}`) && !isAbsolute(name);
|
|
6
18
|
}
|
|
7
|
-
|
|
8
|
-
|
|
19
|
+
/**
|
|
20
|
+
* `file` relative to `root`, with `/` separators. A file that lies outside `root` only lexically, as through a symlinked
|
|
21
|
+
* root, is related by real paths instead.
|
|
22
|
+
*/
|
|
23
|
+
export async function rootRelative(root, file) {
|
|
24
|
+
const path = inside(root, file) ? relative(root, file) : relative(await realpath(root), await realpath(file));
|
|
25
|
+
return path.split(sep).join('/');
|
|
9
26
|
}
|
|
10
27
|
export function location(options) {
|
|
11
28
|
const root = resolve(options.root ?? process.cwd());
|
|
@@ -23,7 +40,7 @@ export function ignore(root, directory) {
|
|
|
23
40
|
}
|
|
24
41
|
async function updateIgnore(root, directory) {
|
|
25
42
|
const path = relative(root, directory);
|
|
26
|
-
if (!path ||
|
|
43
|
+
if (!path || !inside(root, directory))
|
|
27
44
|
return;
|
|
28
45
|
const entry = `${path.split(sep).join('/').replace(/[!*?[\]# ]/g, '\\$&')}/*`;
|
|
29
46
|
const file = join(root, '.gitignore');
|
|
@@ -40,9 +57,15 @@ async function updateIgnore(root, directory) {
|
|
|
40
57
|
return;
|
|
41
58
|
await appendFile(file, `${contents && !contents.endsWith('\n') ? '\n' : ''}${entry}\n`);
|
|
42
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* A file's bytes as a plain Uint8Array that owns its whole ArrayBuffer, as a browser's response gives them. A Buffer's
|
|
62
|
+
* slice() shares its memory, so a slice whose buffer is transferred to a worker would detach the bytes it came from.
|
|
63
|
+
*/
|
|
43
64
|
export async function load(path) {
|
|
44
65
|
try {
|
|
45
|
-
|
|
66
|
+
const bytes = await readFile(path);
|
|
67
|
+
const owned = bytes.byteOffset === 0 && bytes.byteLength === bytes.buffer.byteLength;
|
|
68
|
+
return owned ? new Uint8Array(bytes.buffer) : new Uint8Array(bytes);
|
|
46
69
|
}
|
|
47
70
|
catch (error) {
|
|
48
71
|
if (!missing(error))
|
|
@@ -68,4 +91,26 @@ export async function save(path, value, beforeCommit) {
|
|
|
68
91
|
}
|
|
69
92
|
}
|
|
70
93
|
}
|
|
94
|
+
const unrecorded = new Set();
|
|
95
|
+
/**
|
|
96
|
+
* Sets a file's modification time to now; a file that no longer exists is left alone. Where this process may not change
|
|
97
|
+
* it, as on a read-only deployment, it warns once per directory instead of failing the read that called it.
|
|
98
|
+
*/
|
|
99
|
+
export async function touch(path) {
|
|
100
|
+
try {
|
|
101
|
+
const now = new Date();
|
|
102
|
+
await utimes(path, now, now);
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
if (missing(error))
|
|
106
|
+
return;
|
|
107
|
+
const reason = code(error);
|
|
108
|
+
if (reason !== 'EROFS' && reason !== 'EACCES' && reason !== 'EPERM')
|
|
109
|
+
throw error;
|
|
110
|
+
const directory = dirname(path);
|
|
111
|
+
if (!unrecorded.has(directory))
|
|
112
|
+
console.warn(`vitecache: cannot record use of entries in ${directory} (${reason}), so prune() treats them as unused.`);
|
|
113
|
+
unrecorded.add(directory);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
71
116
|
//# sourceMappingURL=disk.js.map
|