Skip to content
The book

Modules and packages#

Modules#

Every .vlt file is a module, with ES module syntax and named exports only:

ts
// 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
ts
// 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 ns binds a namespace; import type imports names for type positions only.
  • export default and default imports don't exist: the compiler's error suggests the named form.
  • A module-level let is 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> or velt/<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:

ts
paths: { "@app/*": "src/*" },
ts
import { execute } from "@app/commands";        // src/commands.vlt or src/commands/index.vlt

Packages#

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.

package.vlt
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.",
};
Terminal
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.vlt

The 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:

ts
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:

Terminal
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 directory
ts
import { slugify } from "textkit";             // the package's src/lib.vlt
import { wrap } from "textkit/format";         // its src/format.vlt

A 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":

velt.workspace.vlt
import type { Workspace } from "velt/package";

export const workspace: Workspace = {
  members: ["packages/*", "apps/*"],
  velt: "0.5",
};
apps/server/package.vlt
import type { Package } from "velt/package";

export const pkg: Package = {
  name: "server",
  version: "0.1.0",
  dependencies: { core: "workspace" },   // the member named `core`
};
Terminal
velt test                       # at the root: every member
velt run -p server              # one member's program

A 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.

ts
/**
 * 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.

Edit this page on GitHub