# Modules in Sesi

Modules let you split code across `.sesi` files and reuse it. Use `export` to expose values from a file and `import` or `allow` to bring them in.

---

## Exporting

Mark any `let` binding or `fn` declaration with `export` to make it available to other files:

```sesi
// math.sesi
export fn add(a, b) { return a + b }
export fn multiply(a, b) { return a * b }
export let PI = 3.14159
```

Only exported names are visible to importers. Everything else stays private to the file.

---

## Importing — `import`

Pull named exports directly into the current scope:

```sesi
import {
  add,
  multiply,
  PI
} from "math"

show add(10, 20)   // 30
show PI            // 3.14159
```

---

## Importing — `allow`

`allow` is Sesi's scoped import syntax. It has two forms:

### Named bindings

Import specific exports directly into scope:

```sesi
allow "math" in with {
  add, multiply
}

show add(3, 4)   // 7
```

### Namespace object

Import the entire module under a single identifier:

```sesi
allow "math" in as Math

show Math.add(3, 4)      // 7
show Math.multiply(2, 5) // 10
```

---

## Standard Library Modules

Sesi ships with built-in standard library modules:

| Module     | Namespace | Description         |
| ---------- | --------- | ------------------- |
| `std/math` | `Math`    | Math operations     |
| `std/time` | `Time`    | Time/date functions |
| `std/db`   | —         | Database access     |
| [`std/game`](GAME.md) | `Game` | Data-driven 2D Canvas games, HTML export, and local preview |
... and more!

```sesi
allow "std/math" in as Math
allow "std/time" in as Time
allow "std/game" in as Game

show Math.PI
show Time.now()
let game = Game.create({"width": 640, "height": 360})
```

---

## Module Resolution Order

When you import `"mymodule"`, Sesi searches for `mymodule.sesi` (or the folder `mymodule` for directory modules) in this order:

| Priority | Location                  | Description                                                           |
| -------- | ------------------------- | --------------------------------------------------------------------- |
| 1        | Script's own directory    | Same folder as the running `.sesi` file                               |
| 2        | Current working directory | Where you ran `sesi` from                                             |
| 3        | `sesi_modules/`           | Project third-party dependencies directory                            |
| 4        | `SESI_PATH`               | Colon-separated (Unix) or semicolon-separated (Windows) list of paths |
| 5        | `~/.sesi/lib`             | Global shared library, available system-wide                          |

---

## Third-Party Package Management

Sesi features a built-in, git-centric package manager to install and share reusable libraries. Packages are stored inside a local `sesi_modules` directory in your project.

### Project Manifest (`sesi.json`)

To track dependencies, Sesi uses a simple `sesi.json` file in the root of your project:

```json
{
  "name": "my-project",
  "version": "1.0.0",
  "dependencies": {
    "http-router": "example-repo/http-router#v1.0.0"
  }
}
```

### Installation Commands

- **Install a specific package**:

  ```bash
  sesi install owner/repo#ref
  ```

  This downloads the package from GitHub, extracts it to `sesi_modules/repo`, and registers it inside `sesi.json`. You can specify branch names, tag names, or commit hashes using `#ref`.

- **Restore all dependencies**:
  ```bash
  sesi install
  ```
  This reads your `sesi.json` and restores all dependencies into `sesi_modules/`.

### Directory Modules & Entry Points

When you import a third-party package folder (e.g. `allow "repo" in as Repo`), Sesi automatically resolves the module's entry point. It checks the directory for:

1. `sesi_modules/<package-name>/index.sesi`
2. `sesi_modules/<package-name>/main.sesi`

---

## Global Library (`~/.sesi/lib`)

Copy a module to the global library to make it importable from any project on your system:

```bash
# macOS / Unix
cp mymodule.sesi ~/.sesi/lib/
```

```powershell
# Windows
copy mymodule.sesi $env:USERPROFILE\.sesi\lib\
```

```sesi
// Now importable from anywhere
allow "mymodule" in with { helper, util }
```

---

## Custom Paths (`SESI_PATH`)

Point `SESI_PATH` to additional directories for team or monorepo setups:

```bash
# macOS / Unix
export SESI_PATH="/mylibs/shared:/projects/common"
```

```powershell
# Windows
$env:SESI_PATH = "C:\MyLibs\shared;C:\Projects\common"
```

---

## Quick Reference

```sesi
// Export
export fn greet(name) { show "Hello," name }
export let VERSION = "1.8.6"

// import (named)
import { greet, VERSION } from "mymodule"

// allow (named bindings)
allow "mymodule" in with { greet, VERSION }

// allow (namespace)
allow "mymodule" in with Mod
Mod.greet("Ada")

// Standard library
allow "std/math" in as Math
allow "std/time" in as Time
allow "std/game" in as Game
```

---
