Modules and packages
Modules
Every .vlt file is a module, with ES module syntax and named exports only:
// src/geometry.vlt
export type Point = { x: f64; y: f64 };
export function distance(a: Point, b: Point): f64 {
return Math.sqrt((a.x - b.x) ** 2.0 + (a.y - b.y) ** 2.0);
}
const EPSILON = 1e-9; // not exported: private to the file// src/main.vlt
import { distance, type Point } from "./geometry";
import * as path from "velt/path";
const a: Point = { x: 0.0, y: 0.0 };
console.log(distance(a, { x: 3.0, y: 4.0 }), path.basename("/srv/app.vlt")); // 5 app.vlt- Relative imports drop the extension. A folder is a module through its
index.vlt, which usually re-exports its parts:export { Circle } from "./circle";,export * from "./square";. import * as nsbinds a namespace;import typeimports names for type positions only.export defaultand default imports don't exist: the compiler's error suggests the named form.- A module-level
letis module state, one per process as in Node; importers see its current value (module state). - Importing a module runs its top-level statements once, before the importer's, as in Node.
- Standard library modules are imported as
velt/<area>orvelt/<area>/<module>:"velt/fs","velt/collections","velt/net/http"(the standard library).
All rules are in Modules and packages in the Reference.
Path aliases
In a package, paths in package.vlt replaces long ../../ chains, like TypeScript's
compilerOptions.paths:
paths: { "@app/*": "src/*" },import { execute } from "@app/commands"; // src/commands.vlt or src/commands/index.vltPackages
A package is a directory with a package.vlt (reference). An
application has src/main.vlt; a library has src/lib.vlt, whose exports are what other
packages import. package.vlt is written in Velt, as data only: building or installing a
package never runs code from it.
import type { Package } from "velt/package";
export const pkg: Package = {
name: "textkit",
version: "0.1.0",
velt: "0.5", // the velt versions that build it
description: "Text helpers: slugs, truncation and word frequencies.",
};velt new textkit --template lib # a library: src/lib.vlt, tests, doc comments
cd textkit
velt test
velt doc # HTML docs in target/doc from the doc comments
velt publish # to the local registry, or the one in package.vltThe names velt and std are reserved for the standard library, whose modules are velt/…:
a package named velt is an error (the package name `velt` is reserved for the standard library), so an import of velt/… always means the standard library.
Dependencies
A package's dependencies in package.vlt say where each one comes from:
dependencies: {
textkit: "0.1", // a registry, semver requirement
util: { path: "../util" }, // a local directory
"http-server": { // a git repository
git: "https://github.com/velt-lang/velt",
tag: "v0.5.0",
path: "packages/http-server", // the package's directory in it
},
},velt add writes the first two forms, and keeps your comments in package.vlt:
cd ../app
velt add textkit # the latest version, into package.vlt and velt.lock.json
velt add util --path ../util # or a package from a local directoryimport { slugify } from "textkit"; // the package's src/lib.vlt
import { wrap } from "textkit/format"; // its src/format.vltA git dependency names a branch, a tag or a rev (a commit); the first install resolves it
to a commit and locks it (git dependencies).
velt install resolves dependencies and writes velt.lock.json with exact versions and content
hashes; velt install --locked (also on build, run and test) fails instead of changing
the lockfile, for reproducible builds. Commit velt.lock.json for applications.
Official packages
The HTTP server and the database drivers are packages in the Velt repository's packages/
directory, not part of the standard library: http-server,
sqlite, postgres and
redis. Until there is a public registry, depend on one with a git
dependency as above, or with a path into a checkout of the repository. velt new --template api
starts a project that depends on http-server. The database drivers include native code, built
with cargo from a git or path dependency (native code).
Official packages has the details.
Workspaces
A repository with several packages (a server, a CLI and the library they share) is a workspace:
a velt.workspace.vlt at its root lists the members, which share one velt.lock.json and one
velt version, and depend on each other with "workspace":
import type { Workspace } from "velt/package";
export const workspace: Workspace = {
members: ["packages/*", "apps/*"],
velt: "0.5",
};import type { Package } from "velt/package";
export const pkg: Package = {
name: "server",
version: "0.1.0",
dependencies: { core: "workspace" }, // the member named `core`
};velt test # at the root: every member
velt run -p server # one member's programA member leaves out the velt field, which the workspace sets. See
Workspaces.
Documenting a library
velt doc documents exported items from the doc comments right above them: JSDoc /** … */
comments, as in TypeScript, or /// lines. The text is Markdown; tags describe the parameters,
the result, errors and examples. Plain // comments are not documentation.
/**
* A URL-friendly form of `text`: lower case, words joined by `-`.
*
* @param text - the text to turn into a slug
* @returns `""` when `text` has no words
* @example
* slugify("Hello World"); // "hello-world"
*/
export function slugify(text: string): string {
return text.toLowerCase().split(" ").filter((w) => w !== "").join("-");
}The comment block at the top of a file, followed by a blank line, documents the module. The
tags are @param, @returns, @throws, @example, @deprecated, @see and {@link name}
(velt doc).
Registries
Packages come from a registry: a local directory by default (~/.velt/registry), or an HTTP
registry you run with velt registry serve. A public registry doesn't exist yet. See
Packages and registries.