Open dsherret opened 6 months ago
Without this, it sounds like currently people would need to have an import map entry for each submodule they use from the standard library, where they are repeatedly specifying the version for each one that they use. Then to update std, they would have to update the version in all those import map lines.
{
"imports": {
"@std/assert", "jsr:@std/assert@0.215",
"@std/fs", "jsr:@std/fs@0.215",
}
}
import { assertEquals } from "@std/assert";
import { exists } from "@std/fs";
I think since std is a package made by the deno organization and that all submodules within it share the same version, it would make the most sense for std to be a package in the @deno scope along with other packages like Fresh that are made and maintained by Deno. It would also make it more clear to users that std was created by deno.
{
"imports": {
"@deno/std", "jsr:@deno/std@0.215"
}
}
import { assertEquals } from "@deno/std/assert";
import { exists } from "@deno/std/fs";
With this single package approach, it is much easier to bump the version of the standard library that you are using and will reduce the odds of you ending up using a variety of different std versions due to not updating one of your import map lines.
I'm in favor having all-in-one @std/std
as convenient entrypoint for all modules.
I think we need some consideration about versioning of it.
@std/std
?I'm -1 for this. Having two sets of versions (std
as a whole and individual modules) makes navigating versions more complicated than it is worth for maintainers and users. It also muddies the idea that the Standard Library will be a collection of modules, which is what we're trying to do by enabling workspaces functionality and JSR.
It appears this is all to avoid having a few extra imports, which doesn't seem like a problem to me. We do it for all other dependencies. Why should the Standard Library be any different?
Here's one use case, or view on why this would be a nice feature.
I tend to update std versions as well as all other libraries for all of my (monorepo) code when new Deno version comes out. Here's my current ritual, which is weekly or biweekly along with deno releases:
deno upgrade
sudo setcap CAP_NET_BIND_SERVICE=+eip ~/.deno/bin/deno
(I really hope this could be handled by deno upgrade but it is what it is)Step 4 is the most tedious and relevant part here. I really always want to update everything to latest unless problems are detected on step 6. Along with std I only have four or so other dependencies, so manually checking everything isn't too bad.
But if std became 10+ separate libraries each with different version, the manual work for this already somewhat tedious update ritual would multiply three-fourfold. Higher amount of manual update work would possibly discourage the practice of regularly bumping dependencies to latest version.
I respect any decision you make on this. But hopefully this can clarify why an all-encompassing package might be useful.
My (unsolicited) opinion is std shouldn't have versions once it becomes stable. If you really want to create a standard library for JavaScript, it should be treated as if it were a web standard. In the same way that there's no versions for fetch
, URL
or GPU
, there shouldn't be versions for std functions.
For example, if path.dirname
becomes stable, the function signature and behavior should be frozen. Issues and detected bugs must be fixed (obviously) but without changing the behavior and always keeping backward compatibility.
This split the definition from implementation details. The same function can have different implementations for different runtimes (Deno, browser, Node, Bun, etc) but the behavior is the same everywhere.
To me, this is the difference between a standard library and any other dependency.
It all depends on whether std is supposed to be versioned as one package, or fully separated. If there will be separate versioning it makes most sense to publish separate packages and vice versa. If std will continue to be a "blob" i would prefer @deno/std to @std/xyz.
Packages within the Standard Library will have separate versions, so there's no manageable way to have this done.
To better clarify my point here, I think a std library should be imported like this:
import join from "std:path/join";
Instead of this:
import join from "jsr:@std/path@x.x.x/join";
Std library shouldn't have a versions because it's not like another dependency. It's a collection of functions provided by the runtime, similar to node:
modules, but with cross-runtime support.
- open import_map.json
- click every external url in import map to open them in browser tabs to manually see if any new versions are available (this includes the std url)
- manually change every updated dependency
- run test suite to verify everything works with all the updated stuffs
Turn these steps into a script and then simply run the script.
My (unsolicited) opinion is std shouldn't have versions once it becomes stable. If you really want to create a standard library for JavaScript, it should be treated as if it were a web standard. In the same way that there's no versions for fetch, URL or GPU, there shouldn't be versions for std functions.
For example, if path.dirname becomes stable, the function signature and behavior should be frozen. Issues and detected bugs must be fixed (obviously) but without changing the behavior and always keeping backward compatibility.
Without versions the std is required to gain bloat as it adds new features but can't get rid of old depreciated ones. With versions people can always use the older versions if they still want that functionality while not adding in extra stuff for others to sift through. Having versions doesn't prevent backwards compatibility. The parts that rely on older versions will pull those older versions.
Without versions the std is required to gain bloat as it adds new features but can't get rid of old depreciated ones.
Deprecated features could be deleted in a Deno's major version. The standard library for Deno 3 could get rid of old features deprecated for Deno 2. The same as Deno.*
namespace.
Deprecated features could be deleted in a Deno's major version. The standard library for Deno 3 could get rid of old features deprecated for Deno 2. The same as Deno.* namespace.
That would cause stagnation as many breaking changes couldn't be introduced until Deno is updated. Much of Deno's STD isn't just for Deno but other runtimes as well so it doesn't make sense for it to be linked to Deno's version. It makes much more sense for it to be its own thing that moves at its own pace.
Okay, but in this case it's not a standard library (at least how I interpret it), but a collection of 3rd party modules maintained by Deno.
I'm not familiarized with many programing languages, but the few that I know (Node, PHP, Python, etc) don't have semantic versions in their standard libraries. They are provided within the language.
a collection of 3rd party modules maintained by Deno.
Very correct.
Clarification: I don’t advocate for std:
. I just meant that if each module has a different version (the way it is now) then deno_std is effectively "a collection of 3rd party modules maintained by Deno."
Now that there's an announcement about some std packages being stabilized, I feel like Deno is confident in the new direction of having individual packages in the standard library, that should be thought of separately. Deno doesn't have to work like other platforms. Innovation is much needed.
It would be nice if there was a JSR package for depending on all of std. This would allow the following pattern that was previously allowed.
For example:
Then the "@std/std" package (or whatever name) would contain a deno.json like (this would probably be code generated):
The individual files would then contain something like:
The downside would be these extra files, but probably not that bad for a first start. In the future, we may want to consider allowing JSR specifiers directly in an export value.
This solution would still be about as efficient as using the package directly since JSR only downloads the exports you use.