Skip to content

Commit

Permalink
Add the package std module
Browse files Browse the repository at this point in the history
  • Loading branch information
jneem committed Nov 22, 2024
1 parent c678b0f commit 3801ac3
Showing 1 changed file with 244 additions and 0 deletions.
244 changes: 244 additions & 0 deletions core/stdlib/std.ncl
Original file line number Diff line number Diff line change
Expand Up @@ -2800,6 +2800,250 @@
= 2.7182818284590452354,
},

package =
let rec
# https://semver.org is kind enough to supply this "official" semver regex.
semver_re = m%"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$"%,
# Just the major.minor.patch part, with minor and patch being optional.
partial_semver_re = m%"^(0|[1-9]\d*)(\.(0|[1-9]\d*))?(\.(0|[1-9]\d*))?$"%,
# An exact version constraint. This one is required to have minor and patch versions, and it's allowed to have a prerelease.
semver_equals_req_re = m%"^=(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?$"%,
semver_req_re = "(%{partial_semver_re})|(%{semver_equals_req_re})",
in {
is_semver_req
: String -> Bool
| doc m%"
Returns true if a string is a valid version requirement in Nickel.

See the `SemverReq` contract for more details.
"%
= std.string.is_match semver_req_re,
is_semver
: String -> Bool
| doc m%"
Returns true if a string is a valid semantic version.

# Examples

```nickel multiline
std.package.is_semver "1.2.0-pre1"
# => true

std.package.is_semver "1.foo"
# => false
```
"%
= std.string.is_match semver_re,
is_semver_prefix
: String -> Bool
| doc m%"
Returns true if a string is a valid semantic version prefix,
containing a major version and then optional minor and patch versions.

# Examples

```nickel multiline
std.package.is_semver_prefix "1.2"
# => true

std.package.is_semver_prefix "1.foo"
# => false
```
"%
= std.string.is_match partial_semver_re,
Semver
| doc m%"
A contract for semantic version ("semver") identifiers.

# Examples

```nickel multiline
"1.2.0-pre1" | std.package.Semver
# => "1.2.0-pre1"

"1.foo" | std.package.Semver
# => error: contract broken by a value
```
"%
= std.contract.from_predicate is_semver,
SemverPrefix
| doc m%"
A contract for semantic version ("semver") prefixes,
containing a major version and then optional minor and patch versions.

# Examples

```nickel multiline
"1.2" | std.package.SemverPrefix
# => "1.2"

"1.foo" | std.package.SemverPrefix
# => error: contract broken by a value
```
"%
= std.contract.from_predicate is_semver_prefix,
SemverReq
| doc m%"
A contract for semantic version ("semver") requirements.

Nickel supports two kinds of requirements: semver-compatible
requirements and exact version requirements. Semver-compatible
requirements take the form "major.minor.patch", where minor and patch
are optional. Their semantics are:

- "1.2.3" will match all versions having major version 1, minor version 2,
and patch version at least 3.
- "1.2" will match all versions having major version 1 and minor version
at least 2.
- "1" will match all versions having major version 1.
- a semver-compatible requirement will never match a prerelease version.

Exact version requirements take the form "=major.minor.patch-pre", where
the prerelease tag is optional, but major, minor, and patch are all required.

# Examples

```nickel multiline
"1.2" | SemverReq
# => "1.2"

"=1.2" | SemverReq
# => error: contract broken by a value

"1.2.0" | SemverReq
# => "1.2.0"

"=1.2.0" | SemverReq
# => "=1.2.0"

"1.2.0-pre1" | SemverReq
# => error: contract broken by a value

"=1.2.0-pre1" | SemverReq
# => "=1.2.0-pre1"
```
"%
= std.contract.from_predicate is_semver_req,
# TODO: bikeshedding opportunity: which fields should be optional?
Manifest = {
name
| String
| doc m%"
The name of this package.
"%,

version
| String
| Semver
| doc m%"
The version of this package.

Any semantic version is accepted, but the build metadata field has no effect when matching versions.
"%,

nickel_version
| String
| SemverPrefix
| doc m%"
The minimal nickel version required for this package.
"%,

authors
| Array String
| doc m%"
The authors of this package.
"%,

description
| String
| doc m%"
A description of this package.
"%,

keywords
| Array String
| optional
| doc m%"
A list of keywords to help people find this package.
"%,

# TODO: maybe restrict this to be a valid SPDX 2.3 license expression?
# Cargo allows anything here, but applies restrictions when trying to
# publish to crates.io.
license
| String
| optional
| doc m%"
The name of the license that this package is available under.
"%,

dependencies
| {
_ : [|
'Path String,
'Git {
url
| String
| doc m%"
The url of a git repository.

This supports local file paths, https urls like `https://example.com/example-repo`,
and ssh urls like `[email protected]:repo`.
"%,
ref
| [| 'Head, 'Branch String, 'Tag String, 'Commit String |]
| optional
| doc m%"
The git ref to fetch from the repository.

If not provided, defaults to 'Head.
"%,
path
| String
| optional
| doc m%"
The path of the nickel package within the git repository. If omitted, the nickel package
is at the root of the git repository.
"%,
},
'Index {
package
| String
| doc m%"
The dependency's identifier within the nickel index, in the format "github/<organization>/<repository>"
"%,
version
| String
| SemverReq
| doc m%"
The required version of the package.

Nickel supports two kinds of requirements: semver-compatible
requirements and exact version requirements. Semver-compatible
requirements take the form "major.minor.patch", where minor and patch
are optional. Their semantics are:

- "1.2.3" will match all versions having major version 1, minor version 2,
and patch version at least 3.
- "1.2" will match all versions having major version 1 and minor version
at least 2.
- "1" will match all versions having major version 1.
- a semver-compatible requirement will never match a prerelease version.

Exact version requirements take the form "=major.minor.patch-pre", where
the prerelease tag is optional, but major, minor, and patch are all required.
"%,
},
|]
}
| doc m%"
A dictionary of package dependencies, keyed by the name that this package uses to refer to them locally.
"%
| default
= {},
},
},

record = {
map
: forall a b. (String -> a -> b) -> { _ : a } -> { _ : b }
Expand Down

0 comments on commit 3801ac3

Please sign in to comment.