soma.cell

Paginated product list: GET /products?page=N&size=M slices a stored list

Returns a Map with items + pagination metadata (total, page, pages).

A Soma program from the web part of the verified corpus: 57 lines, cells Catalog, CatalogTest. It passes soma check with soma 3.2.4.

How it is built

The cell Catalog declares 3 signals in its face: request(method: String, path: String, body: String) -> Map, seed(n: Int) -> Int and page(page: Int, size: Int) -> Map; keeps 1 memory slot: products (Map<String, Map>, persistent and consistent). Handlers: seed (line 16), page (line 24) and request (line 38).

The file also holds 1 test cell (CatalogTest) with 6 assertions, run by soma test.

Generated from soma describe on this file.

The source

soma.toml

[package]
name = "web-corpus"
version = "0.1.0"
entry = "todo_state.cell"

[verify]
cells = ["TodoService"]
deadlock_free = true
eventually = ["Done", "Cancelled"]

paginated_list.cell

// Paginated product list: GET /products?page=N&size=M slices a stored list.
// Returns a Map with items + pagination metadata (total, page, pages).

cell Catalog {
    face {
        signal request(method: String, path: String, body: String) -> Map
        signal seed(n: Int) -> Int
        signal page(page: Int, size: Int) -> Map
        promise all_persistent
    }

    memory {
        products: Map<String, Map> [persistent, consistent]
    }

    on seed(n: Int) {
        for i in range(1, n + 1) {
            let p = map("id", i, "name", "product-{i}", "price", i * 10)
            products.set(to_string(i), p)
        }
        return products.len()
    }

    on page(page: Int, size: Int) {
        let all = products.values
        let total = len(all)
        let pages = if total == 0 { 0 } else { floor((total + size - 1) / size) }
        let start = (page - 1) * size
        let items = list()
        let i = start
        while i < start + size && i < total {
            items = push(items, all[i])
            i = i + 1
        }
        return map("page", page, "size", size, "total", total, "pages", pages, "items", items)
    }

    on request(method: String, path: String, body: String) {
        let req = map("method", method, "path", path)
        match req {
            {method: "GET", path: "/products"} -> page(1, 10)
            _                                  -> response(404, map("error", "no route"))
        }
    }
}

cell test CatalogTest {
    rules {
        assert seed(25) == 25
        assert page(1, 10).total == 25
        assert page(1, 10).pages == 3
        assert len(page(1, 10).items) == 10
        assert len(page(3, 10).items) == 5
        assert page(2, 10).page == 2
    }
}

What the toolchain says

Run on a fresh copy of the program at build time; the outputs are pasted unedited.

$ soma check paginated_list.cell
✓ All checks passed.
$ soma test paginated_list.cell
test CatalogTest ...
  ✓ assert seed(25) == 25
  ✓ assert page(1, 10).total == 25
  ✓ assert page(1, 10).pages == 3
  ✓ assert len(page(1, 10).items) == 10
  ✓ assert len(page(3, 10).items) == 5
  ✓ assert page(2, 10).page == 2

6 tests: 6 passed, 0 failed
$ soma verify paginated_list.cell
Verifying paginated_list.cell...
note: soma.toml [verify] cells names 'TodoService', which this file does not define — its properties are not checked here

Catalog/termination:

  ⚠ handler `page`: while-loop without provable termination bound (write `while [loop_bound(N)] cond { … }`, or a for-loop over a bounded range)
  ⚠ `request` calls `Catalog.page`, which may not terminate

0 passed, 2 warnings, 0 failures
soma.toml: 1 user-defined properties loaded — NONE applies to this file ([verify] cells = ["TodoService"] names no cell of it)
Temporal: 0 passed, 0 failed
VERIFY OK

Builtins used

floor, len, list, map, push, range, response, to_string

Source file: /corpus/web/paginated_list.cell · examples/corpus/web/paginated_list.cell