-
Notifications
You must be signed in to change notification settings - Fork 5.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: deno vendor
#13346
Comments
I just want to point out that this is a good and important characteristic of this design. It means I can do this:
(Where The cumulative nature of |
Thank you, this suggestion is perfect! I'm working on a quite large Deno App with my team that has a few Deno dependencies (Like Oak), but our security model won't allow us to pull in code from external links, this proposal will solve this issue once and for all. |
@tmikaeld I'm working on a project that's probably relatively small, but where vendoring would allow me to "harden" the app against scenarios where there's no network after app distribution. This proposal is a perfect fit; and it's inspiration to do vendor my modules like this by hand for my project in anticipation of the CLI command. |
When you call |
|
How do you intend to use them other than to just load them as cached files?
You shouldn't edit vendor files either, no? This would constitute a license violation most of the time and if you want to edit 3rd party code you should fork it and release as an independent package and just cache it as any other library. What kind of use or modification are you thinking about here? It honestly sounds like |
From the use cases:
Specifically, users of Deno have come across several scenarios where this is a common pattern. Like for example you include a remote dependency and are getting some sort of type error and you want to investigate, or you are consuming a 3rd party library and something isn't working and you would like to be able to drop into that code in the editor and do a console log statement or insert a
Really? I am not a lawyer, but I am pretty sure you aren't either.
The good thing, is if you don't like it, you won't have to use it. 😄 |
How would it do that? You're allowed to make changes to most open source license, the legality of it applies to distribution. |
Ok got it, that does make sense. I thought you mean actually altering it permanently and then checking it in which is probably unadvisable. |
Context
Deno aspires to provide a full featured set of development tools baked into the single
deno
CLI. At the same time, Deno provides an open platform where code can be imported just as easily as a browser can fetch a web page. Deno stores remote dependencies in a cache commonly referred to as theDENO_DIR
. While Deno allows you "relocate" this directory at runtime, and the files in the cache are editable, it does not solve all the use cases in a well supported way.Use cases
All of these use cases also are constrained by:
Proposed Solution
Add a subcommand to the Deno CLI named
deno vendor
. The subcommand would work similar to thedeno run
subcommand, in that it would take a target script. For example:Would analyse
main.ts
and all of its dependencies. For those dependencies that are remote dependencies, it would write their source out locally to the_vendor
path, along with_vendor/import_map.json
, which would remap all the remote dependencies to local ones.The concept would then be then that changes could be made to the local "vendored" code and be reflected in the application by simply using the output import map:
(Note: having to be explicit about this import map isn't the ideal design, and suggestions below in other complimentary features would be able to make this just so then all the user would need to do is
deno run main.ts
)This would also allow specific dependencies to be vendored, without having to vendor everything. For example if someone wanted to just vendor oak and all of it dependencies, but leave everything else to continue to be remote:
Other flags that should be supported:
--output
- specify the output path, which defaults to_vendor
of cwd.--import-map
- specifies an upstream import map that should be used as the base when calculating the vendored import map--config
- specifies a configuration file, which will be considered when vendoring.--info
- output human readable information about the current state of the_vendor
directory.Other flags/features that might be supported, or might be added after the "MVP" feature:
--ignore
- a glob pattern of dependencies to exclude/ignore_vendor
(which can be accomplished from editing the_vendor/import_map.json
directly, but might be unapproachable for some devs)Semantics
Once the remote dependencies are identified, they would be written out in a way to minimise the need of remapping the paths. For example
https://example.com/pkg/mod.ts
would get written out to./_vendor/https/example.com/pkg/mod.ts
. In cases where the remote dependency cannot be written to disk following the simple algorithm, it will be written out in as close to a human readable way as possible.Once the "manifest" of the
_vendor
is calculated, the import map will be generated with the smallest set of entries possible. For example a remote import ofhttps://example.com/pkg/mod.ts
would get an entry like the following:But if there was something like
https://example.com/pkg/mod.ts
andhttps://example.com/pkg/lib?dev
something like the following would be written out:If a
_vendor
or output path already exists, the_vendor/import_map.json
and output dependencies would be updated.A design limitation would be that some dynamic imports that cannot be statically analysable would be missed. A consideration might be to warn on such dependencies being present.
It is assumed that at this point in time, other state/meta data does not need to be stored, but might need to be. If this is the case, then the state should be stored in the
_vendor/import-map.json
under additional private keys (e.g."__deno_vendor": {}
). The import map specification specifically allows additional keys without invalidating the file, and this would help ensure that the output ofdeno vendor
is contained, repeatable and portable.When an existing
_vendor
is updated, and for some reason a remote dependency has changed, import map"scopes"
can be used to allow two different versions of the same dependency to exist in the vendor directory.Other features which improve/compliment this feature
deno.json
/deno.jsonc
- This is already in progress.deno.json
/deno.jsonc
. This would allow the feature a) identify an existing import map that should be amended with the vendor mappings as well as "point" the configuration at the vendor import map.Specific advantages to this proposal
Other options considered
DENO_DIR
easier - currently, users can edit files in theDENO_DIR
. There are significant risks to this, like depending on the dependency type and the state of the cache, files may or may not be invalidated in a way that causes the program to emit properly. Also, it is a reasonable expectation that we should considerDENO_DIR
and its schema "private" and while accessible, the layout and format may need to change as Deno evolves, and if people are tightly coupled to this, it becomes problematic and could easily hold back the development of Deno for fear of breaking integrations to non-public behaviours. Another risk is that it would not be (ever) compatible with Deno Deploy.The text was updated successfully, but these errors were encountered: