vitecache 0.1.1 → 0.1.2

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/dist/storage.js CHANGED
@@ -1,10 +1,13 @@
1
+ import { createHash } from 'node:crypto';
1
2
  import { realpath } from 'node:fs/promises';
2
3
  import { isAbsolute, join, relative, resolve, sep } from 'node:path';
3
4
  import { fileURLToPath } from 'node:url';
4
5
  import * as disk from './disk.js';
5
6
  import { equalHashes, hashes, resolvedDependencies } from './dependencies.js';
6
7
  import { packageVersion } from './packages.js';
7
- import { digest } from './key.js';
8
+ function digest(bytes) {
9
+ return createHash('sha256').update(bytes).digest('hex');
10
+ }
8
11
  export class ChangedDependenciesError extends Error {
9
12
  constructor() {
10
13
  super('vitecache dependencies changed during computation.');
@@ -1 +1 @@
1
- {"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAQlC,MAAM,OAAO,wBAAyB,SAAQ,KAAK;IACjD;QACE,KAAK,CAAC,oDAAoD,CAAC,CAAC;IAC9D,CAAC;CACF;AAED,SAAS,QAAQ,CAAC,KAAiB;IACjC,MAAM,KAAK,GAAY,IAAI,CAAC,KAAK,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACnE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,CAAC,aAAa,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,cAAc,IAAI,KAAK,CAAC,EAAE,CAAC;QAC3G,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IACD,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,KAAK,CAAC;IAC5C,IAAI,OAAO,WAAW,KAAK,QAAQ,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QAC3E,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;AAC7D,CAAC;AAED,SAAS,OAAO,CAAC,OAAsB,EAAE,QAAgB;IACvD,OAAO,OAAO,KAAK,IAAI,IAAI,WAAW,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAqD;IACjF,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAEnD,KAAK,UAAU,QAAQ,CAAC,YAAkC;QACxD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,EAAE;YACnJ,IAAI,CAAC;gBACH,IAAI,UAAU,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;oBACrC,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;oBAC/D,OAAO,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAA4B,CAAC;gBACrH,CAAC;gBACD,IAAI,UAAU,CAAC,IAAI,KAAK,SAAS;oBAAE,MAAM,IAAI,SAAS,CAAC,iCAAiC,CAAC,CAAC;gBAC1F,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC9D,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAA4B,CAAC;YACvF,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC;oBAAE,MAAM,KAAK,CAAC;gBAChD,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC,CAAC,CAAC,CAAC;QACJ,MAAM,OAAO,GAAuB,EAAE,CAAC;QACvC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,KAAK,KAAK,IAAI;gBAAE,OAAO,IAAI,CAAC;YAChC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;QACD,OAAO,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;IAED,OAAO;QACL,KAAK,CAAC,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC,CAAC;QAChC,KAAK,CAAC,OAAO,CAAC,KAAmB;YAC/B,OAAO,oBAAoB,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,EAAE;gBACtH,IAAI,UAAU,CAAC,GAAG,KAAK,SAAS;oBAAE,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;gBAC5D,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;gBACpC,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;oBAC7B,MAAM,IAAI,KAAK,CAAC,mGAAmG,CAAC,CAAC;gBACvH,CAAC;gBACD,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;gBAChC,IAAI,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBAChC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;oBACrE,IAAI,GAAG,QAAQ,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC9D,CAAC;gBACD,OAAO,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACrD,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACR,CAAC;QACD,QAAQ;QACR,KAAK,CAAC,IAAI,CAAC,GAAG;YACZ,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC;YAC/D,IAAI,MAAM,KAAK,SAAS;gBAAE,OAAO,SAAS,CAAC;YAC3C,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;YACvD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC;YAC7D,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,WAAW;gBAAE,OAAO,SAAS,CAAC;YAC3E,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;QACzC,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ;YACpC,IAAI,CAAC,OAAO,CAAC,MAAM,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC;gBAAE,MAAM,IAAI,wBAAwB,EAAE,CAAC;YACpF,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YACnC,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,GAAG,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,IAAI,EAAE;gBAC/D,IAAI,CAAC,OAAO,CAAC,MAAM,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC;oBAAE,MAAM,IAAI,wBAAwB,EAAE,CAAC;YACtF,CAAC,CAAC,CAAC;YACH,MAAM,MAAM,GAAa,EAAE,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC;YAChF,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,CAAC,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACpG,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { realpath } from 'node:fs/promises';\nimport { isAbsolute, join, relative, resolve, sep } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport * as disk from './disk.js';\nimport { equalHashes, hashes, resolvedDependencies } from './dependencies.js';\nimport { packageVersion } from './packages.js';\nimport { digest } from './key.js';\nimport type { Backend, CacheEntryOptions, Dependencies, Hashes, ResolvedDependencies } from './types.js';\n\ninterface Metadata {\n contentHash: string;\n dependencies: Hashes;\n}\n\nexport class ChangedDependenciesError extends Error {\n constructor() {\n super('vitecache dependencies changed during computation.');\n }\n}\n\nfunction metadata(bytes: Uint8Array): Metadata {\n const value: unknown = JSON.parse(new TextDecoder().decode(bytes));\n if (typeof value !== 'object' || value === null || !('contentHash' in value) || !('dependencies' in value)) {\n throw new Error('Invalid vitecache metadata.');\n }\n const { contentHash, dependencies } = value;\n if (typeof contentHash !== 'string' || !/^[a-f0-9]{64}$/.test(contentHash)) {\n throw new Error('Invalid vitecache metadata.');\n }\n return { contentHash, dependencies: hashes(dependencies) };\n}\n\nfunction matches(current: Hashes | null, expected: Hashes): boolean {\n return current !== null && equalHashes(current, expected);\n}\n\nexport function createStorage(options: Pick<CacheEntryOptions, 'root' | 'basePath'>): Backend {\n const { root, directory } = disk.location(options);\n\n async function snapshot(dependencies: ResolvedDependencies): Promise<Hashes | null> {\n const entries = await Promise.all(Object.entries(dependencies).filter(([, dependency]) => !('value' in dependency)).map(async ([name, dependency]) => {\n try {\n if (dependency.package !== undefined) {\n const version = await packageVersion(root, dependency.package);\n return version === undefined ? null : [name, digest(new TextEncoder().encode(version))] satisfies [string, string];\n }\n if (dependency.path === undefined) throw new TypeError('Expected a resolved dependency.');\n const bytes = await disk.load(resolve(root, dependency.path));\n return bytes === undefined ? null : [name, digest(bytes)] satisfies [string, string];\n } catch (error) {\n if (!disk.missingDependency(error)) throw error;\n return null;\n }\n }));\n const present: [string, string][] = [];\n for (const entry of entries) {\n if (entry === null) return null;\n present.push(entry);\n }\n return Object.fromEntries(present);\n }\n\n return {\n async canSave() { return true; },\n async resolve(files: Dependencies) {\n return resolvedDependencies(Object.fromEntries(await Promise.all(Object.entries(files).map(async ([name, dependency]) => {\n if (dependency.url === undefined) return [name, dependency];\n const url = new URL(dependency.url);\n if (url.protocol !== 'file:') {\n throw new Error('Node file dependency URLs must use file:. Use a project-root-relative path for Vite-served files.');\n }\n const file = fileURLToPath(url);\n let path = relative(root, file);\n if (path === '..' || path.startsWith(`..${sep}`) || isAbsolute(path)) {\n path = relative(await realpath(root), await realpath(file));\n }\n return [name, { path: path.split(sep).join('/') }];\n }))));\n },\n snapshot,\n async load(key) {\n const record = await disk.load(join(directory, `${key}.json`));\n if (record === undefined) return undefined;\n const { contentHash, dependencies } = metadata(record);\n const bytes = await disk.load(join(directory, `${key}.bin`));\n if (bytes === undefined || digest(bytes) !== contentHash) return undefined;\n return { bytes, hashes: dependencies };\n },\n async save(key, value, files, expected) {\n if (!matches(await snapshot(files), expected)) throw new ChangedDependenciesError();\n await disk.ignore(root, directory);\n await disk.save(join(directory, `${key}.bin`), value, async () => {\n if (!matches(await snapshot(files), expected)) throw new ChangedDependenciesError();\n });\n const record: Metadata = { contentHash: digest(value), dependencies: expected };\n await disk.save(join(directory, `${key}.json`), new TextEncoder().encode(JSON.stringify(record)));\n },\n };\n}\n"]}
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from 'node:crypto';\nimport { realpath } from 'node:fs/promises';\nimport { isAbsolute, join, relative, resolve, sep } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport * as disk from './disk.js';\nimport { equalHashes, hashes, resolvedDependencies } from './dependencies.js';\nimport { packageVersion } from './packages.js';\nimport type { Backend, CacheEntryOptions, Dependencies, Hashes, ResolvedDependencies } from './types.js';\n\nfunction digest(bytes: Uint8Array): string {\n return createHash('sha256').update(bytes).digest('hex');\n}\n\ninterface Metadata {\n contentHash: string;\n dependencies: Hashes;\n}\n\nexport class ChangedDependenciesError extends Error {\n constructor() {\n super('vitecache dependencies changed during computation.');\n }\n}\n\nfunction metadata(bytes: Uint8Array): Metadata {\n const value: unknown = JSON.parse(new TextDecoder().decode(bytes));\n if (typeof value !== 'object' || value === null || !('contentHash' in value) || !('dependencies' in value)) {\n throw new Error('Invalid vitecache metadata.');\n }\n const { contentHash, dependencies } = value;\n if (typeof contentHash !== 'string' || !/^[a-f0-9]{64}$/.test(contentHash)) {\n throw new Error('Invalid vitecache metadata.');\n }\n return { contentHash, dependencies: hashes(dependencies) };\n}\n\nfunction matches(current: Hashes | null, expected: Hashes): boolean {\n return current !== null && equalHashes(current, expected);\n}\n\nexport function createStorage(options: Pick<CacheEntryOptions, 'root' | 'basePath'>): Backend {\n const { root, directory } = disk.location(options);\n\n async function snapshot(dependencies: ResolvedDependencies): Promise<Hashes | null> {\n const entries = await Promise.all(Object.entries(dependencies).filter(([, dependency]) => !('value' in dependency)).map(async ([name, dependency]) => {\n try {\n if (dependency.package !== undefined) {\n const version = await packageVersion(root, dependency.package);\n return version === undefined ? null : [name, digest(new TextEncoder().encode(version))] satisfies [string, string];\n }\n if (dependency.path === undefined) throw new TypeError('Expected a resolved dependency.');\n const bytes = await disk.load(resolve(root, dependency.path));\n return bytes === undefined ? null : [name, digest(bytes)] satisfies [string, string];\n } catch (error) {\n if (!disk.missingDependency(error)) throw error;\n return null;\n }\n }));\n const present: [string, string][] = [];\n for (const entry of entries) {\n if (entry === null) return null;\n present.push(entry);\n }\n return Object.fromEntries(present);\n }\n\n return {\n async canSave() { return true; },\n async resolve(files: Dependencies) {\n return resolvedDependencies(Object.fromEntries(await Promise.all(Object.entries(files).map(async ([name, dependency]) => {\n if (dependency.url === undefined) return [name, dependency];\n const url = new URL(dependency.url);\n if (url.protocol !== 'file:') {\n throw new Error('Node file dependency URLs must use file:. Use a project-root-relative path for Vite-served files.');\n }\n const file = fileURLToPath(url);\n let path = relative(root, file);\n if (path === '..' || path.startsWith(`..${sep}`) || isAbsolute(path)) {\n path = relative(await realpath(root), await realpath(file));\n }\n return [name, { path: path.split(sep).join('/') }];\n }))));\n },\n snapshot,\n async load(key) {\n const record = await disk.load(join(directory, `${key}.json`));\n if (record === undefined) return undefined;\n const { contentHash, dependencies } = metadata(record);\n const bytes = await disk.load(join(directory, `${key}.bin`));\n if (bytes === undefined || digest(bytes) !== contentHash) return undefined;\n return { bytes, hashes: dependencies };\n },\n async save(key, value, files, expected) {\n if (!matches(await snapshot(files), expected)) throw new ChangedDependenciesError();\n await disk.ignore(root, directory);\n await disk.save(join(directory, `${key}.bin`), value, async () => {\n if (!matches(await snapshot(files), expected)) throw new ChangedDependenciesError();\n });\n const record: Metadata = { contentHash: digest(value), dependencies: expected };\n await disk.save(join(directory, `${key}.json`), new TextEncoder().encode(JSON.stringify(record)));\n },\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vitecache",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Persistent binary caching for expensive computation in browsers and Node.",
5
5
  "type": "module",
6
6
  "license": "MIT",