char/avril

(wip) why'd you have to go and make things so complicaaaaated?

git clone https://git.t4t.associates/char/avril

Charlotte Somchore: use lowercase avril branding consistentlyb862289

main
6.2 KiB120 linesraw

HTTP(S) modules

Import modules directly or through a local import map:

import { value } from "https://example.com/lib/mod.ts";

URLs can also be entry points:

avril run https://example.com/app/main.ts
avril update https://example.com/app/main.ts

Static imports are acquired before execution. Computed dynamic imports acquire and prepare their static dependencies asynchronously. Relative and root-relative imports resolve against the final response URL after redirects. Remote modules do not inherit local package aliases or resolve filesystem imports; explicit jsr: and avril: imports remain available.

Module identity and import.meta.url use the requested URL, not the cache path or redirect destination. Queries and fragments distinguish module identities; fragments are not sent to the server. Consequently, constructing a URL relative to import.meta.url can differ from a relative import after a redirect. TypeScript is transpiled according to the final URL's .ts or .mts extension, ignoring its query and fragment. Content-Type does not select the source language. Registry URLs retain JSR's manifest verification and package confinement.

Cache and integrity

HTTP sources are reused until avril update. The cache defaults to $AVRIL_CACHE_DIR, $XDG_CACHE_HOME/avril, or $HOME/.cache/avril, with --cache-dir=PATH as an override. Source blobs are content-addressed; updating one project does not overwrite another project's pinned source.

The root avril.lock records the SHA-256 checksum and final response URL for each requested URL. Successful graph preparation saves new pins; update explicitly replaces encountered HTTP pins. If a pinned source is missing from the cache, an online download must match both its checksum and final URL. Corrupt cached sources fail integrity checks rather than silently being replaced.

--offline prohibits downloads. --frozen requires existing pins and does not modify the lockfile. cache, info, --include, pruning, vendoring, and editor support also work with HTTP sources. Vendor trees store sources beneath http/; the lockfile supplies their checksums and redirect bases for offline use.

Permissions and redirects

Acquisition uses host tooling authority, independently of guest net, read, and write permissions. Each requested module needs js-exec authority, even on cache hits. Like local entry files, a URL entry point receives an exact execution grant; explicit denials still override it.

Redirect chains check execution permission only for the initial requested URL, not the destinations. Granting a URL therefore trusts its server to redirect to any HTTP(S) destination, including other origins and local services. A denial for a destination does not block a redirect to it. Relative dependencies resolve to their own requested URLs and need their own execution grants.

The initial URL's execution permission is rechecked during asynchronous work and before linking cached modules, so revocation still takes effect. Redirects are limited to ten hops. Credentials and non-HTTP(S) destinations are rejected; responses are bounded to 32 MiB and downloads to 30 seconds. HTML responses are rejected as modules.

HTTP(S) packages

A directory URL ending with / in deps fetches avril.conf beneath that URL:

deps: [
  'https://example.com/math/',
  {from: 'https://example.com/format/', name: 'format'},
],

The first entry binds the package's declared name; the second overrides it. Import that binding or an exported subpath, just like a local package. The remote config uses the same schema, including exact exports, self-imports, imports, scopes, and private deps. Relative remote dependencies are directory URLs too: '../numeric/'. Remote configs cannot declare filesystem dependencies.

Exports and config-relative targets resolve against the config's final response URL after redirects. Export targets must stay within that URL's package directory; redirects follow the ordinary HTTP module rules. Dependencies do not grant execution permission to their exports or transitive dependencies.

The requested config URL requires js-exec permission, including when reading a dependency's declared name and on cache hits. A directory URL execution grant covers its config and modules. Configs and sources are pinned together in avril.lock; update, --offline, --frozen, pruning, and vendoring apply to both.

Package ownership follows the importing module's config, not a global registry. A package export starts in that package. Other URL imports match the importing package's declared HTTP dependencies or its own requested/final directory, choosing the most specific match. Nested package boundaries must be declared in the parent package's deps; their configs are loaded only when a module crosses that boundary. An unrelated package's private dependencies cannot change another module's maps.

Each requested module URL keeps its first owner, including plain modules. Reaching the same URL with a different owner is an explicit conflict, never a silent rebind. Redirected package aliases share ownership only when their final config URL, pinned contents, and module ownership region agree. Modules beneath the final package directory inherit only that canonical region, not an alias's requested directory. Other modules inherit their matching requested directory. All requested config URLs that have claimed a canonical package remain required execution authorities; revoking any of them blocks subsequent imports through every alias. Ordinary redirects still resolve relative imports and scopes against the module's final response URL.

avril does not probe remote ancestors for configs. Direct URL imports beneath a declared dependency require that dependency's config and its execution permission; imports from plain remote modules have no package context. Trailing-slash URLs are package syntax in deps, not a change to direct URL entry points. URLs beneath the configured JSR registry are reserved for registry packages, not HTTP configs.

An unused dependency whose name must be inferred still needs its config at package initialization. Network, cache, or permission failures are fatal for execution; the language server instead reports package errors and unresolved imports.

1# HTTP(S) modules
2
3Import modules directly or through a local import map:
4
5```ts
6import { value } from "https://example.com/lib/mod.ts";
7```
8
9URLs can also be entry points:
10
11```sh
12avril run https://example.com/app/main.ts
13avril update https://example.com/app/main.ts
14```
15
16Static imports are acquired before execution. Computed dynamic imports acquire
17and prepare their static dependencies asynchronously. Relative and root-relative
18imports resolve against the final response URL after redirects. Remote modules
19do not inherit local package aliases or resolve filesystem imports; explicit
20`jsr:` and `avril:` imports remain available.
21
22Module identity and `import.meta.url` use the requested URL, not the cache path
23or redirect destination. Queries and fragments distinguish module identities;
24fragments are not sent to the server. Consequently, constructing a URL relative
25to `import.meta.url` can differ from a relative import after a redirect.
26TypeScript is transpiled according to the final URL's `.ts` or `.mts` extension,
27ignoring its query and fragment. Content-Type does not select the source language.
28Registry URLs retain JSR's manifest verification and package confinement.
29
30## Cache and integrity
31
32HTTP sources are reused until `avril update`. The cache defaults to
33`$AVRIL_CACHE_DIR`, `$XDG_CACHE_HOME/avril`, or `$HOME/.cache/avril`, with
34`--cache-dir=PATH` as an override. Source blobs are content-addressed; updating one
35project does not overwrite another project's pinned source.
36
37The root `avril.lock` records the SHA-256 checksum and final response URL for each
38requested URL. Successful graph preparation saves new pins; `update` explicitly
39replaces encountered HTTP pins. If a pinned source is missing from the cache, an
40online download must match both its checksum and final URL. Corrupt cached sources
41fail integrity checks rather than silently being replaced.
42
43`--offline` prohibits downloads. `--frozen` requires existing pins and does not
44modify the lockfile. `cache`, `info`, `--include`, pruning, vendoring, and editor
45support also work with HTTP sources. Vendor trees store sources beneath `http/`;
46the lockfile supplies their checksums and redirect bases for offline use.
47
48## Permissions and redirects
49
50Acquisition uses host tooling authority, independently of guest `net`, `read`,
51and `write` permissions. Each requested module needs `js-exec` authority, even on
52cache hits. Like local entry files, a URL entry point receives an exact execution
53grant; explicit denials still override it.
54
55Redirect chains check execution permission only for the initial requested URL,
56not the destinations. Granting a URL therefore trusts its server to redirect to
57any HTTP(S) destination, including other origins and local services. A denial
58for a destination does not block a redirect to it. Relative dependencies resolve
59to their own requested URLs and need their own execution grants.
60
61The initial URL's execution permission is rechecked during asynchronous work and
62before linking cached modules, so revocation still takes effect. Redirects are
63limited to ten hops. Credentials and non-HTTP(S) destinations are rejected;
64responses are bounded to 32 MiB and downloads to 30 seconds. HTML responses are
65rejected as modules.
66
67## HTTP(S) packages
68
69A directory URL ending with `/` in `deps` fetches `avril.conf` beneath that URL:
70
71```text
72deps: [
73  'https://example.com/math/',
74  {from: 'https://example.com/format/', name: 'format'},
75],
76```
77
78The first entry binds the package's declared `name`; the second overrides it.
79Import that binding or an exported subpath, just like a local package.
80The remote config uses the same schema, including exact `exports`, self-imports,
81`imports`, `scopes`, and private `deps`. Relative remote dependencies are directory
82URLs too: `'../numeric/'`. Remote configs cannot declare filesystem dependencies.
83
84Exports and config-relative targets resolve against the config's final response
85URL after redirects. Export targets must stay within that URL's package directory;
86redirects follow the ordinary HTTP module rules. Dependencies do not grant execution
87permission to their exports or transitive dependencies.
88
89The requested config URL requires `js-exec` permission, including when reading a
90dependency's declared name and on cache hits. A directory URL execution grant
91covers its config and modules. Configs and sources are pinned together in
92`avril.lock`; `update`, `--offline`, `--frozen`, pruning, and vendoring apply to both.
93
94Package ownership follows the importing module's config, not a global registry.
95A package export starts in that package. Other URL imports match the importing
96package's declared HTTP dependencies or its own requested/final directory, choosing
97the most specific match. Nested package boundaries must be declared in the parent
98package's `deps`; their configs are loaded only when a module crosses that boundary.
99An unrelated package's private dependencies cannot change another module's maps.
100
101Each requested module URL keeps its first owner, including plain modules. Reaching
102the same URL with a different owner is an explicit conflict, never a silent rebind.
103Redirected package aliases share ownership only when their final config URL,
104pinned contents, and module ownership region agree. Modules beneath the final
105package directory inherit only that canonical region, not an alias's requested
106directory. Other modules inherit their matching requested directory. All requested
107config URLs that have claimed a canonical package remain required execution
108authorities; revoking any of them blocks subsequent imports through every alias.
109Ordinary redirects still resolve relative imports and scopes against the module's
110final response URL.
111
112avril does not probe remote ancestors for configs. Direct URL imports beneath a
113declared dependency require that dependency's config and its execution permission;
114imports from plain remote modules have no package context. Trailing-slash URLs are
115package syntax in `deps`, not a change to direct URL entry points. URLs beneath the
116configured JSR registry are reserved for registry packages, not HTTP configs.
117
118An unused dependency whose name must be inferred still needs its config at package
119initialization. Network, cache, or permission failures are fatal for execution;
120the language server instead reports package errors and unresolved imports.