denoland / deno

A modern runtime for JavaScript and TypeScript.
https://deno.com
MIT License
97.73k stars 5.38k forks source link

feat: Deno.cacheDir, Deno.cache, resolveCacheModulePath #6891

Closed timreichen closed 2 years ago

timreichen commented 4 years ago

Proposal

I propose these implementations:

Deno.cacheDir()

Implementation of rust's cache_dir

Deno.cache(path: string, options: CacheOptions)

access to deno cache as a method

resolveCacheModulePath(path: string)

Native way to resolve an url to the local cache file. Either returns the filepath if the file is cached or null if not. Example:

resolveCachedModulePath("https://deno.land/std/fmt/colors.ts") // output on macOS: /User/Name/Library/Caches/deno/deps/https/deno.land/0e481eaf33c7b5f679cc7af0c476a798458854f912fe489bb77131d47e0929db

Maybe Deno needs a dedicated std/cache module for functions like resolveCachedModulePath and other cache related stuff?

Use case

The Deno cache system is great. For dev tools written for Deno it is important to have access to the local files for a certain path when bundling or compiling, else it needs to be either re-downloaded or cached with a custom cache system.

What are your thoughts on this?

References: https://github.com/denoland/deno/issues/4069 https://denolib.gitbook.io/guide/advanced/deno_dir-code-fetch-and-cache https://doc.deno.land/https/github.com/denoland/deno/releases/latest/download/lib.deno.d.ts https://deno.land/manual/runtime/compiler_apis https://deno.land/x/cache

nayeemrmn commented 4 years ago

Deno.cacheDir()

This was removed in #6385. We can maybe bring some of these back without the dirs dependency, I believe that was the problem.

Deno.cache(path: string, options: CacheOptions)

Duplicate of #4752.

resolveCacheModulePath(path: string)

Duplicate of #2096 (tracking issue for programmatic deno info, which provides this).

ry commented 4 years ago

I wonder what your exact use case is? I'm researching vscode extensions now and the thought is that we might want to expose language service from Deno. If this is what you're after maybe this feature isn't needed.

timreichen commented 4 years ago

My specific use case is a tool that works natively with Deno and has no npm deps. The goal is to make Deno modules work in a browser without the need of bundling them. It transpiles ts modules to esm js files (no bundling like Deno.bundle). It resolves paths with .ts extensions and urls correctly (since tsc doesn't support that yet) and outputs all transpiled files in a dist dir that can be served to the web. Since it needs to actually parse the source code I need to read the cached files directly and transpile it to js, therefore the need of cache access. I actually got it to work and will publish a proof of concept rep soon.

The features proposed in this issue are implementable in ts, though it feels really hacky (static typed paths). Since Deno does so much right and would make web development really easy, I would love to see Deno expose these internals instead of each developer coming up with an own hacky solution.

Btw: The same use case is for this issue about import maps.

timreichen commented 4 years ago

Update: Bundler is the proof of concept project. I had to implement the functionality of deno cache and path resolution to cached files as a hacky functions here. Because Deno has implemented that functionality into the core, it would be better if one could access that instead of imitating it in my opinion. I hope that describes my use case a bit better?

bartlomieju commented 4 years ago

I'm not a big fan of making DENO_DIR accessible via APIs. It's doesn't have a public interface and we tend to change its structure as need/bugs arise. In general I think it should be considered implementation detail and messing with it might lead to very strange errors.

timreichen commented 4 years ago

Interesting, I would have thought exactly the opposite. I like the idea of denos caching system. That is why I think it should give access via API. Deno can change when needed and also adjust the API instead of having 3rd party modules that will break when changes happen. If it had an API, the functionality can be limited to be non-destructive.

In that sense the functionality boils down to two features:

What would you think of that?

wojpawlik commented 3 years ago

Reading from deps cache is useful for Deno build tools. It allows https://deno.land/x/deno2node to work without --allow-net.

Cache access can be exposed without leaking implementation details. This is what https://deno.land/x/fromdeno_cache does:

/**
 * @permissions `--allow-read --allow-env`
 * @returns cached `Response` on success.
 * @throws `Deno.errors.NotFound` when the URL isn't cached.
 */
export declare function readCache(url: string | URL): Promise<Response>;

/**
 * If `Response` isn't cached, performs the request and caches `Response`.
 * @permissions `--allow-net --allow-write --allow-read --allow-env`
 */
export declare function fetchCache(url: string | URL): Promise<Response>;

I think these two belong in core, where they can reuse Deno's caching logic.

After fetch cache is implemented (#3756) and used for remote caching dependencies, Deno.fetchCache should be deprecated in favor of fetch.

timreichen commented 2 years ago

Closing because of reasons given in #11829