Topazdocs
Создание приложений

Data Lens

Создайте, протестируйте, упакуйте и автономно запустите многомодульное local-first Web-приложение Topaz.

Data Lens показывает весь Web Application Loop в одном поддерживаемом приложении. Оно разбирает JSON и CSV в браузере, хранит строки и сводки в номинальных типах, нормализует многоязычные метки через зафиксированную пакетную зависимость и обрабатывает фильтрацию, сортировку, выбор, ошибки и клавиатуру, не отправляя набор данных на сервер. Текущий Topaz предоставляет этот workflow, включая выбор локального файла и экспорт текста.

Выбор Web-продукта

Используйте web-app, когда Topaz владеет состоянием приложения, событиями, обновлением и представлением. Компилятор проверяет единый lifecycle init/update/view и создаёт полный статический продукт с ограниченным безопасным DOM-host. Выбирайте raw web или web-worker, когда существующий JavaScript-host владеет UI либо worker-протоколом и вызывает отдельные типизированные exports Topaz. Playground — песочница компилятора, а не модель развёртывания.

Data Lens использует web-app, потому что модель и взаимодействия принадлежат Topaz.

Структура пакета

Начните с установленного scaffold, затем разделите parsing, transformation, model, view и lifecycle по модулям:

BASH
topaz init --target web-app --root data-lens
mkdir -p data-lens/src data-lens/tests registry/lens_labels/1.0.0/src

Manifest приложения задаёт эффективную цель сборки, управляемый stylesheet и одну локальную зависимость:

TOML
[package]
name = "data_lens"
version = "0.1.0"
language = "5.8"
entry = "src/main.tpz"

[build]
target = "web-app"
deterministic = true

[web]
title = "Topaz Data Lens"
styles = ["styles/app.css"]
assets = []
lifecycle = "v2"

[capabilities.web]
open_text = true
download_text = true
local_state = true

[dependencies]
std = "5.8"
lens_labels = "1.0.0"

Храните приложение в семи исходных модулях:

src/main.tpz       lifecycle и сообщения
src/model.tpz      номинальные строки, сводка, модель и enum сообщений
src/session.tpz    ограниченные JSON-настройки для долговременного состояния
src/parsing.tpz    декодирование JSON/CSV и детерминированные ошибки путей
src/transform.tpz  фильтрация, сортировка и агрегаты
src/exporting.tpz  детерминированный UTF-8 CSV/JSON
src/view.tpz       типизированное построение Html<Msg>

Модель делает переходы состояния явными:

TOPAZ
export record DataRow {
  name: string,
  category: string,
  value: int,
  active: bool,
}

export record Summary {
  totalRows: int,
  activeRows: int,
  totalValue: int,
}

export enum SortMode { ByName, ByValue }

export record Model {
  source: string,
  query: string,
  activeOnly: bool,
  sortMode: SortMode,
  rows: Array<DataRow>,
  summary: Summary,
  status: string,
  error: Option<string>,
}

Entry экспортирует lifecycle v2. Данные браузера и завершения локальных операций приходят как WebAppEvent, а сообщения приложения остаются номинальными значениями:

TOPAZ
export function init() -> WebAppStep<Model, Msg> {
  WebAppStep { model: initialModel(), commands: [loadState("data-lens-session-load", "session", Msg.LocalCompleted)] }
}

export function update(model: Model, message: Msg, event: WebAppEvent) -> WebAppStep<Model, Msg> {
  match message {
    case OpenDocument => step(model, [openText("data-lens-open", ".csv,.json,text/csv,application/json", Msg.LocalCompleted)])
    case SaveSession => saveSession(model)
    case ForgetSession => step(model, [deleteState("data-lens-session-delete", "session", Msg.LocalCompleted)])
    case LocalCompleted => {
      match event {
        case LocalData(local) => completeLocalData(model, local)
        case LocalState(local) => completeLocalState(model, local)
        case Browser(_) => step(model, [])
      }
    }
    case DownloadResults => downloadResults(model)
    case Apply | Submit => step(applyModel(model), [])
    case Clear => step(clearModel(), [dom(focus("#source"))])
    case _ => updateFromBrowser(model, message, event)
  }
}

export function view(model: Model) -> Html<Msg> {
  render(model)
}

Parsing возвращает Result со стабильным путём, например JSON $[0].category: missing field. Update сохраняет ошибку в модели, а view выводит её как текст. Не переносите обработку в JavaScript и не вставляйте исходные данные через innerHTML.

OpenText передаёт только ограниченные имя, media type, размер и UTF-8 текст документа после явного выбора пользователем. Путь и повторно используемый дескриптор не раскрываются. DownloadStarted от DownloadText сообщает о запуске загрузки браузером, а не о физическом сохранении файла.

Сохраняемая сессия намеренно уже модели. Save session записывает через saveState только запрос, фильтр активных строк и режим сортировки; после перезагрузки loadState восстанавливает лишь эти настройки. Исходный текст, разобранные строки, сводка, имя файла и ошибки не сохраняются. Forget session использует deleteState, а повреждение, запрет, исчерпание квоты и недоступность хранилища отображаются как типизированное состояние приложения, а не скрываются host-слоем.

Lock, проверки и тесты

Создайте локальный registry-пакет lens_labels, затем один раз скопируйте его в vendor. Все последующие команды используют lockfile и vendored bytes:

BASH
topaz vendor --root data-lens --from registry
rm -rf registry
topaz check --root data-lens --locked
topaz fmt --root data-lens --check
topaz test data-lens/tests/parsing.tpz --root data-lens --locked
topaz test data-lens/tests/transform.tpz --root data-lens --locked
topaz test data-lens/tests/application.tpz --root data-lens --locked
topaz test data-lens/tests/exporting.tpz --root data-lens --locked
topaz doc --root data-lens --locked --out-dir data-lens-docs

Выбранные тестовые файлы выполняются в контексте пакета, поэтому imports, идентичность зависимости, режим языка и корень модулей совпадают с приложением.

Разработка и упаковка

Во время разработки используйте loopback-сервер, затем соберите управляемый продукт:

BASH
topaz dev --root data-lens --port 8000
topaz build --root data-lens --locked --release --out-dir data-lens-product

Проверьте выбор реальных CSV/JSON-файлов, Unicode-метки, текстовый фильтр, checkbox активных строк, оба режима сортировки, сохранение, перезагрузку и удаление сессии, submit и Enter, отмену, неверный UTF-8, очистку, одну ошибку отсутствующего поля и содержимое загруженного CSV/JSON. После ошибочной правки сервер продолжает отдавать последний исправный продукт. Поддерживаемый установленный путь включает многоязычный CSV на 256 строк, JSON на 128 строк, Unicode-имена файлов, восемь последовательных файловых и state-операций, семантические сводки, восстановление focus и точные экспортированные данные.

Итоговый каталог содержит HTML, безопасный host приложения, проверенный raw Web facade, WASM, объявленные стили, лицензии, notices, topaz-web-capabilities.json и topaz-artifact.json. Скопируйте только data-lens-product/ в новый статический корень, удалите исходники пакета и build storage, отключите сеть и раздавайте этот каталог. Все сценарии выше должны продолжить работу: продукту не нужны установка Topaz, registry, исходные файлы, npm runtime, CDN или удалённый сервис данных.

Связанная документация