Skip to content

Commit 840245b

Browse files
committedNov 2, 2022
docs(SPEC): add specification of modules
The implementation of this work is still in-progress see #4296
1 parent c1d3964 commit 840245b

File tree

1 file changed

+172
-1
lines changed

1 file changed

+172
-1
lines changed
 

‎docs/SPEC.md

+172-1
Original file line numberDiff line numberDiff line change
@@ -1051,9 +1051,10 @@ The _main_ package is special for a few reasons:
10511051

10521052
ImportDeclaration = [ Attributes ] "import" [identifier] string_lit
10531053

1054+
10541055
Associated with every package is a package name and an import path.
10551056
The import statement takes a package's import path and brings all of the identifiers defined in that package into the current scope under a namespace.
1056-
The import statment defines the namespace through which to access the imported identifiers.
1057+
The import statement defines the namespace through which to access the imported identifiers.
10571058
By default the identifier of this namespace is the package name unless otherwise specified.
10581059
For example, given a variable `x` declared in package `foo`, importing `foo` and referencing `x` would look like this:
10591060

@@ -1426,6 +1427,176 @@ A query specification defines what data and operations to perform.
14261427
The execution model reserves the right to perform those operations as efficiently as possible.
14271428
The execution model may rewrite the query in anyway it sees fit while maintaining correctness.
14281429

1430+
## Modules
1431+
1432+
>NOTE: Modules are not fully implemented yet, follow https://github.com/influxdata/flux/issues/4296 for details.
1433+
1434+
A module is a collection of packages that can be imported.
1435+
A module has a module path, version and a collection of packages with their source code.
1436+
1437+
### Module path
1438+
1439+
The module path is the import path of the top level package within the module.
1440+
Additionally major versions of a module of two or greater must add a final element to the path of the form `v#` where `#` is the major version number.
1441+
For modules at version zero or one the path must not contain the major version as it is not necessary.
1442+
A change from `v0` to `v1` may include a breaking change but once `v1` is published any future breaking changes will be a new major version.
1443+
1444+
Example
1445+
1446+
foo/bar // module path of foo/bar for version zero or one
1447+
foo/bar/v2 // module path of foo/bar for major version two
1448+
1449+
### Module versions
1450+
1451+
All modules are versioned using a [semantic version number](https://semver.org/) prefixed with a `v`, i.e. `vMAJOR.MINOR.PATCH`.
1452+
Once a module version has been published it cannot be modified.
1453+
A new version of the module must be published.
1454+
1455+
### Module registry
1456+
1457+
A modules is hosted and stored on a registry.
1458+
A module path is unique to the the registry that hosts the module.
1459+
Module paths need not be unique across different registries.
1460+
1461+
#### Registry attribute
1462+
1463+
The `registry` attribute defines the available registries.
1464+
The registry attribute expects two arguments, the first is the name of the registry and the second is the `$base` URL of the registry API endpoint.
1465+
See the [Registry API](#registry-api) for more details.
1466+
1467+
The runtime may define default registries, a registry attribute will override any default registry.
1468+
The standard library will never contain a top level package named `modules` or any name containing a `.`.
1469+
This makes it possible for the runtime to use `modules` or any name containing a `.` (i.e. a DNS name) as a default registry name.
1470+
1471+
Example:
1472+
1473+
@registry("modules", "http://localhost/modules")
1474+
@registry("example.com", "https://example.com/api/modules")
1475+
package main
1476+
1477+
### Importing modules
1478+
1479+
Flux modules are imported using an import declaration.
1480+
The import path may contain specifiers about which registry and which versions of a module should be imported.
1481+
1482+
An import path follows this grammar:
1483+
1484+
ImportPath = ModulePath [ "/" PackagePath ] [ Version ] .
1485+
ModulePath = PathElement [ "/" PathElement ] [ MajorVersion ] .
1486+
MajorVersion = "/v" int_lit .
1487+
PackagePath = PathElement { "/" PathElement } .
1488+
Version = PreVersion | MinVersion
1489+
PreVersion = "@pre"
1490+
MinVersion = "@v" int_lit "." int_lit "." int_lit "." .
1491+
PathElement = ascii_letter { ascii_letter } .
1492+
ascii_letter = /* alpha numeric and underscore ASCII characters */
1493+
1494+
Per the grammar a module path may have up to three path elements:
1495+
1496+
* Registry name
1497+
* Module name
1498+
* Module major version
1499+
1500+
A package path may have an arbitrary depth and must not begin with a major version.
1501+
1502+
When resolving an import path the first path element of the module path is compared against the defined registry names.
1503+
If a match is found the import path is understood to be relative to the registry.
1504+
If no match is found the import path is understood to be an import from the standard library.
1505+
It is an error to specify a version on imports from the standard library.
1506+
The standard library version is implicit to the runtime.
1507+
1508+
When no version information is provided the latest version of the module is used.
1509+
A _minimum_ version may be specified.
1510+
An import may also specify the version `pre` which is the most recent pre-release version of the module.
1511+
1512+
1513+
Examples
1514+
1515+
@registry("modules", "http://localhost/modules")
1516+
package main
1517+
1518+
import "foo" // imports package `foo` from the standard library
1519+
import "modules/foo" // imports the latest version 0.x or 1.x version of the `foo` module from the `modules` registry
1520+
import "modules/foo/a/b/c" // imports package a/b/c from the latest 0.x or 1.x version
1521+
import "modules/foo@v1.5.6" // imports at least version 1.5.6
1522+
import "modules/foo/v2" // imports the latest 2.x version
1523+
import "modules/foo/v2/a" // imports package `a` from the latest 2.x version
1524+
import "modules/foo/v2/a@v2.3.0" // imports package `a` from at least version 2.3.0 of the `foo` module
1525+
import "modules/foo/v2/a/b/c" // imports package `a/b/c` from the latest 2.x version
1526+
import "modules/foo/v2/a/b/c@v2.3.0" // imports package `a/b/c` from at least version 2.3.0
1527+
import "modules/foo/a/b/c@pre" // imports package `a/b/c` from the latest pre-release 0.x or 1.x version
1528+
import "modules/foo@pre" // imports the latest pre-release 0.x or 1.x version
1529+
import "modules/foo/v2@pre" // imports the latest pre-release 2.x version
1530+
1531+
### Version resolution
1532+
1533+
When multiple modules both depend on a specific version of another module the maximum version of the minimum versions is used.
1534+
Major versions of a module are considered different modules (they have different module paths), therefore multiple major versions of a module may be imported into the same Flux script.
1535+
1536+
When multiple import declarations exist for the same module at most one import declaration must specify version information.
1537+
1538+
Example
1539+
1540+
```
1541+
// a.flux
1542+
package a
1543+
1544+
import "foo@v1.1.0"
1545+
```
1546+
1547+
```
1548+
// b.flux
1549+
package b
1550+
1551+
import "foo@v1.2.0"
1552+
```
1553+
1554+
```
1555+
// main.flux
1556+
@registry("modules", "http://localhost/modules")
1557+
package main
1558+
1559+
import "modules/a"
1560+
import "modules/b"
1561+
```
1562+
1563+
Package `main` depends on module `foo` via both of the modules `a` and `b`.
1564+
However `a` and `b` specify different versions of `foo`.
1565+
The possible versions of `foo` include `1.1.0` and `1.2.0`.
1566+
Flux will pick the maximum version of these possible versions, so version `1.2.0` of `foo` is used.
1567+
This is sound because module `a` has specified that it needs at least version `1.1.0` of `foo` and that constraint is satisfied.
1568+
1569+
### Registry API
1570+
1571+
Modules can be published and downloaded over an HTTP API from a registry.
1572+
Modules are immutable, once a version is published it cannot be modified, a new version must be published instead.
1573+
1574+
The HTTP API will have the routes listed in the following table where `$base` is the anchor point of the API, `$module` is a module path without the registry name, and `$version` is a semantic version of the form `vMAJOR.MINOR.PATCH`.
1575+
1576+
| Method | Path | Description |
1577+
| ------ | ---- | ----------- |
1578+
| GET | $base/$module/@v/list | Returns a list of known versions of the given module in plain text, one per line. |
1579+
| GET | $base/$module/@v/$version.zip | Returns a zip file of the contents of the module at a specific version. |
1580+
| GET | $base/$module/@latest | Returns the highest released version, or if no released versions exist the highest pre-release version of the given module in plain text on a single line. |
1581+
| GET | $base/$module/@pre | Returns the highest pre-released version of the given module in plain text on a single line. |
1582+
| POST | $base/$module/@v/$version | Publish a new version of the module where the POST body contains multipart formdata for the contents of the module. |
1583+
1584+
As an example, to download the zip file for a module `foo` at version `v0.5.6`, for an API endpoint anchored at `https://example.com/flux/modules/` use this URL `https://example.com/flux/modules/foo/@v/v1.5.6.zip`.
1585+
Or for the module `foo/v2` at version `v2.3.4` the URL is `https://example.com/flux/modules/foo/v2/@v/v2.3.4.zip`.
1586+
1587+
Examples
1588+
1589+
The following examples use a $base of `/flux/modules/`
1590+
1591+
GET /flux/modules/foo/@v/list # Return a list of versions for the module foo
1592+
GET /flux/modules/bar/@v/v1.3.4.zip # Return a zip file of the bar module at version 1.3.4
1593+
GET /flux/modules/bar/v2/@v/v2.3.4.zip # Return a zip file of the bar module at version 2.3.4
1594+
GET /flux/modules/bar/@latest # Return the latest 0.x or 1.x version of bar
1595+
GET /flux/modules/bar/@pre # Return the latest 0.x or 1.x pre-release version of bar
1596+
GET /flux/modules/bar/v2/@latest # Return the latest 2.x release version of bar
1597+
GET /flux/modules/bar/v2/@pre # Return the latest 2.x pre-release version of bar
1598+
1599+
14291600
## Versions and editions
14301601

14311602
Flux follows a [semantic versioning scheme](https://semver.org/) such that breaking changes are clearly communicated as part of the version information.

0 commit comments

Comments
 (0)
Please sign in to comment.