Skip to main content

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

Project description

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

qalib_cli-0.1.0.tar.gz (190.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

qalib_cli-0.1.0-py3-none-any.whl (127.6 kB view details)

Uploaded Python 3

File details

Details for the file qalib_cli-0.1.0.tar.gz.

File metadata

  • Download URL: qalib_cli-0.1.0.tar.gz
  • Upload date:
  • Size: 190.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.31 {"installer":{"name":"uv","version":"0.11.31","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for qalib_cli-0.1.0.tar.gz
Algorithm Hash digest
SHA256 39a7a392159867b26fd54af853db80a26b862d4d73bb359708345e1e0ff5f48d
MD5 ea1c3bdfacdf4b02326160d0654918f9
BLAKE2b-256 8f34e10857eb0e8eaa99b81113fdcce2a94c46d6c4a1302b8eae650df6a20212

See more details on using hashes here.

File details

Details for the file qalib_cli-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: qalib_cli-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 127.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.31 {"installer":{"name":"uv","version":"0.11.31","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for qalib_cli-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2a90a1cf41b2ceed36b43718608a2f055440c0a57e0f99bfff2d4f51428e0ffb
MD5 dc6626d73500e64bfe6c0370f80813ad
BLAKE2b-256 b4aa3e5b84a893df6a678be9d1517f524c5d127cec68811931eeb3650e599828

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page