Skip to content
muthaniiPublic

About

Scaffold data-driven apps from declarative YAML DocTypes - Frappe-inspired, MySQL-backed, with a cute TUI.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

qalib

قالب — Arabic for "mold / template"

qalib scaffolds data-driven applications from declarative YAML files.

You describe your entities — DocTypes, in the Frappe Framework sense — as plain YAML files in your project. qalib turns them into typed SQLAlchemy models, Pydantic schemas, Alembic migrations and a live MySQL schema. The YAML is the single source of truth; everything else is a derived artifact you never hand-edit.

Type qalib and a web desk opens in your browser — Streamlit-style. It ships inside the Python package (no Node, no npm, no build step): a calm, Frappe-Desk-inspired UI with list views, filters, metadata-driven forms, inline child tables and English/Arabic switching, all rendered live from your YAML. Edit a YAML file, refresh the browser, and the desk follows.

The terminal side stays minimal on purpose — like the best modern CLIs: qalib serve prints a quiet status banner (project, URL, what it's watching) and gets out of your way, with a small ASCII cat that celebrates clean syncs ([cli] mascot = false turns it off). VS Code is a first-class citizen: qalib init wires JSON-Schema autocomplete and inline validation for every DocType YAML file.

The core loop

  desk / CLI ──creates/edits──▶  modules/*/doctypes/*.yaml ──edited in VS Code──┐
       ▲                              │                                   │
       │                              ▼                                   │
       └────────reads back───  qalib sync  ──▶  generated Python models    │
                                     │      ──▶  Alembic migration         │
                                     │      ──▶  MySQL schema              │
                                     └───────────────watch mode ◀──────────┘

qalib sync is idempotent: running it twice on an unchanged tree produces zero diffs and zero migrations.

Install

uv add qalib-cli                # as a project dependency
uvx --from qalib-cli qalib      # run without installing
pip install qalib-cli           # classic

The package installs as qalib-cli (the bare qalib name is squatted on PyPI), but the command and the import are plain qalib.

Requires Python 3.11+ and a MySQL 8 server for syncing (validation and codegen work offline).

60-second quickstart

qalib init myapp && cd myapp
# .env, git, pre-commit and VS Code wiring are ready; modules are folders:

code modules/crm/doctypes/customer.yaml   # schema autocomplete included

qalib check        # validate the YAML: every error with file, line, and a suggested fix
qalib sync         # generate models + migration, apply to MySQL
qalib              # opens the web desk in your browser (list views, forms, child tables)
qalib watch        # re-sync automatically whenever a YAML file changes

No npm install, ever: the web desk is part of the qalib package itself. While the server runs, YAML edits show up on the next browser refresh.

What a DocType looks like

One DocType per file, one folder per module (Frappe-app style): modules/<module>/doctypes/<doctype>.yaml — the module: key is optional and derived from the folder. Labels are {en, ar} maps — qalib is Arabic-first and every table is utf8mb4.

# modules/crm/doctypes/customer.yaml
doctype: Customer
module: CRM
label:
  en: Customer
  ar: زبون

naming:
  strategy: series
  series: "CUST-.YYYY.-.#####"

title_field: customer_name

fields:
  - fieldname: customer_name
    label: {en: Customer Name, ar: اسم الزبون}
    fieldtype: Data
    reqd: true
    in_list_view: true

  - fieldname: customer_type
    fieldtype: Select
    options: [Individual, Company]
    default: Company

  - fieldname: territory
    label: {en: Territory, ar: المنطقة}
    fieldtype: Link
    options: Territory        # foreign key to tabTerritory.name
    on_delete: restrict

  - fieldname: credit_limit
    fieldtype: Currency
    default: 0

  - fieldname: addresses
    fieldtype: Table
    options: Customer Address # child table rows, edited inline

permissions:
  - role: Sales User
    read: true
    write: true
    create: true

From this, qalib sync derives:

  • a tabCustomer MySQL table with standard fields (name primary key, creation, modified, owner, …) plus your columns, indexes and foreign keys,
  • a typed SQLAlchemy 2.0 model and Pydantic schemas under generated/ (banner-marked, never hand-edited — escape hatches live in hooks/ and overrides/),
  • a reviewed Alembic migration. Destructive changes (dropped columns or tables) are refused unless you pass --allow-destructive.

See examples/crm for a complete committed project: a territory tree, a customer with an embedded address child table, and a submittable sales order with line items.

CLI reference

qalib new [app|module|doctype]          create anything — guided, commented files
qalib init <name> [--db-url URL]        scaffold a new project (= qalib new app)
qalib doctype new [NAME]                interactive or flag-driven (= qalib new doctype)
qalib doctype list [--module M]
qalib doctype show <NAME>               rendered field table
qalib doctype rename <OLD> <NEW>
qalib doctype delete <NAME> --allow-destructive
qalib check [--strict]                  validate YAML only, exit 1 on error
qalib sync [--plan-only] [--yes] [--allow-destructive]
qalib migrate [--revision REV]          alembic passthrough
qalib watch                             re-sync on YAML change (debounce 400ms)
qalib db shell | reset | import-db      (import-db lands in Milestone 5)
qalib fixtures load|dump
qalib serve [--host H] [--port P]       web desk + REST API (also: bare `qalib`)

Global flags: --project PATH, --verbose, --no-color, and --json for machine-readable output from check, sync --plan-only and doctype list.

The web desk

Bare qalib (or qalib serve) starts a local server and opens the desk: a sidebar of your DocTypes grouped by module, list views with the columns you marked in_list_view, filters from in_standard_filter, and create/edit forms generated from the field metadata — sections and columns from your layout fields, inline grids for child tables, Submit/Cancel for submittable DocTypes, and an EN/AR toggle with real RTL. It talks to a REST API (/api/...) you can also use directly; DocType permissions are enforced per role, and each module's hooks/<doctype>.py functions (validate, before_insert, …) run on every write. Password fields are write-only and never returned.

The look is modern Frappe: white surfaces, quiet gray borders, and a single near-black accent — dark mode inverts it. The desk is three static files inside the wheel — hand-written JS/CSS, no framework, no build step, no external requests, no npm install.

CLI charm

The terminal stays calm and friendly — gentle wording, no noise, and a small ASCII cat that keeps you company:

$ qalib sync
Loaded 5 DocType(s).
Generated code: 0 written, 12 unchanged.
✓ Everything is in sync
  /\_/\
 ( ^.^ )  ~ nice!
  > ^ <

Not a cat person? [cli] mascot = false in qalib.toml.

Dev container

The repository ships a dev container with Python, uv and a MySQL 8 service (utf8mb4) preconfigured:

  1. Open the folder in VS Code and choose Reopen in Container.
  2. uv sync runs automatically on create; QALIB_TEST_DB_URL already points at the bundled MySQL service.

Contributing / dev setup

uv sync                                        # install everything
uv run ruff format --check src tests           # formatting
uv run ruff check src tests                    # lint
uv run mypy --strict src/qalib                 # types
uv run pytest -q                               # unit + snapshot tests

docker compose -f docker-compose.test.yml up -d   # MySQL 8 on port 3307
uv run pytest -q -m db                            # integration tests

Commits follow Conventional Commits (feat:, fix:, refactor:, test:, docs:).

Roadmap

Milestone Scope Status
M1 Schema & YAML core: DocType/Field models, loader, round-trip writer, qalib check shipping
M2 Codegen & MySQL: DDL mapping, SQLAlchemy models, idempotent qalib sync, naming series shipping
M3 Developer UX: VS Code round-trip, watch mode, CLI charm (superseded the TUI) shipping
M4 App runtime: web desk + REST API (qalib serve), hooks, docstatus, permissions shipping
M5 Polish: qalib import-db reverse engineering, fixtures, end-to-end CRM example in CI next

Prefer a custom frontend? qalib init --frontend also drops in a minimal React + Vite template wired to the same REST API — entirely optional; the built-in desk needs nothing.

Arabic-first

qalib assumes bilingual applications from day one: MySQL charset is utf8mb4 with utf8mb4_unicode_ci collation, every label is an {en, ar} map, and the desk is tested under LANG=ar_IQ.UTF-8. Latin-only and LTR-only assumptions are treated as bugs.

License

MIT

About

Scaffold data-driven apps from declarative YAML DocTypes - Frappe-inspired, MySQL-backed, with a cute TUI.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages