Skip to main content

TYTX Base - Typed text protocol for scalar types (JSON/XML/MessagePack)

Project description

TYTX Logo

PyPI npm Python 3.10+ License Status
Tests Coverage Documentation

genro-tytx

A lightweight multi-transport typed data interchange system.

TYTX eliminates manual type conversions between Python and JavaScript, and makes switching to MessagePack for better performance as simple as changing a parameter.

You send a Decimal from Python, JavaScript receives a string. You convert it back. Every. Single. Time. TYTX fixes this—types flow automatically between Python and JavaScript, over JSON, XML, or MessagePack.

The Pain You Know

# Your Python API
return {"price": Decimal("99.99"), "due_date": date(2025, 1, 15)}
// Your JavaScript client
const data = await response.json();
// data.price is "99.99" (string) - need to convert
// data.due_date is "2025-01-15" (string) - need to convert

const price = new Decimal(data.price);      // Manual conversion
const dueDate = new Date(data.due_date);    // Manual conversion

This leads to:

  • Conversion code scattered everywhere
  • Bugs when someone forgets to convert
  • Financial calculations with floating-point errors
  • Different date formats causing off-by-one-day bugs

The TYTX Solution

# Server - just return native types
return {"price": Decimal("99.99"), "due_date": date(2025, 1, 15)}
// Client - types arrive ready to use
const data = await fetchTytx('/api/order');
data.price      // → Decimal (not string)
data.due_date   // → Date (not string)

Zero conversion code. Types just work.

30-Second Demo

Python:

pip install genro-tytx
from decimal import Decimal
from datetime import date
from genro_tytx import to_tytx, from_tytx

# Encode
data = {"price": Decimal("99.99"), "date": date(2025, 1, 15)}
encoded = to_tytx(data)
# '{"price": "99.99::N", "date": "2025-01-15::D"}::JS'

# Decode
decoded = from_tytx(encoded)
# {"price": Decimal("99.99"), "date": date(2025, 1, 15)}

JavaScript:

npm install genro-tytx big.js
import { fetchTytx } from 'genro-tytx';
import Big from 'big.js';

const result = await fetchTytx('/api/invoice', {
    body: { price: new Big('99.99'), date: new Date() }
});
// result.total → Big (ready to use)

Installation

# Python
pip install genro-tytx

# JavaScript/TypeScript
npm install genro-tytx

# Recommended: decimal library for JS
npm install big.js  # lightweight, good for most cases
# or: npm install decimal.js  # more features

Real-World Example: Order Processing

A typical business scenario: process an order with 8 typed fields, return 6 typed results.

1. The Data

JavaScript Client has order data with proper types:

import Big from 'big.js';

const orderData = {
    unit_price: new Big('149.99'),      // Decimal
    quantity: 3,
    discount: new Big('10.00'),         // Decimal
    order_date: new Date(2025, 0, 15),  // Date
    delivery_date: new Date(2025, 0, 20),
    express: true,
    customer_id: 12345,
    notes: 'Handle with care'
};

// Expects response: { subtotal, tax, shipping, total, ship_date, arrival_date }

Python Server has business logic expecting proper types:

async def process_order(unit_price, quantity, discount, order_date,
                        delivery_date, express, customer_id, notes):
    """Business logic - expects Decimal and date types."""
    subtotal = unit_price * quantity
    tax = subtotal * Decimal('0.22')
    shipping = Decimal('15.00') if express else Decimal('5.00')
    total = subtotal - discount + tax + shipping
    ship_date = order_date + timedelta(days=1 if express else 3)
    return {
        'subtotal': subtotal, 'tax': tax, 'shipping': shipping,
        'total': total, 'ship_date': ship_date, 'arrival_date': delivery_date
    }

2. ❌ WITHOUT TYTX: 20 Manual Conversions

JavaScript - must convert to/from strings:

// Send: convert types → strings
const response = await fetch('/api/process_order', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
        unit_price: orderData.unit_price.toString(),           // Decimal → string
        discount: orderData.discount.toString(),               // Decimal → string
        order_date: orderData.order_date.toISOString().slice(0, 10),  // Date → string
        delivery_date: orderData.delivery_date.toISOString().slice(0, 10),
        quantity: orderData.quantity, express: orderData.express,
        customer_id: orderData.customer_id, notes: orderData.notes
    })
});

// Receive: convert strings → types
const json = await response.json();
const result = {
    subtotal: new Big(json.subtotal),     tax: new Big(json.tax),
    shipping: new Big(json.shipping),     total: new Big(json.total),
    ship_date: new Date(json.ship_date),  arrival_date: new Date(json.arrival_date)
};

Python - must convert to/from strings:

@app.post("/api/process_order")
async def handle_order(request: Request):
    json_data = await request.json()

    # Receive: convert strings → types
    unit_price = Decimal(json_data['unit_price'])
    discount = Decimal(json_data['discount'])
    order_date = date.fromisoformat(json_data['order_date'])
    delivery_date = date.fromisoformat(json_data['delivery_date'])

    result = await process_order(unit_price, json_data['quantity'], discount,
        order_date, delivery_date, json_data['express'],
        json_data['customer_id'], json_data['notes'])

    # Send: convert types → strings
    return JSONResponse({
        'subtotal': str(result['subtotal']), 'tax': str(result['tax']),
        'shipping': str(result['shipping']), 'total': str(result['total']),
        'ship_date': result['ship_date'].isoformat(),
        'arrival_date': result['arrival_date'].isoformat()
    })

Total: 20 manual conversions (4 JS→string + 4 string→Python + 6 Python→string + 6 string→JS).


3. ✅ WITH TYTX: Zero Conversions

JavaScript:

import { fetchTytx } from 'genro-tytx';

const result = await fetchTytx('/api/process_order', { body: orderData });
console.log(result.total.toFixed(2));  // Big, ready to use

Python:

from genro_tytx import asgi_data, to_tytx

@app.post("/api/process_order")
async def handle_order(request: Request):
    data = await asgi_data(request.scope, request.receive)
    result = await process_order(**data['body'])
    return Response(content=to_tytx(result), media_type='application/vnd.tytx+json')

Total: 0 conversions. Types flow naturally.

Bonus: Switch to MessagePack in One Line

Need binary format for better performance? Just add transport: 'msgpack':

// JSON (default)
const result = await fetchTytx('/api/process_order', { body: orderData });

// MessagePack - same API, binary format
const result = await fetchTytx('/api/process_order', { body: orderData, transport: 'msgpack' });
# Server auto-detects transport from Content-Type header
# No code changes needed!

Supported Types

Python JavaScript Wire Format
Decimal Decimal (big.js) "99.99::N"
date Date (midnight UTC) "2025-01-15::D"
datetime Date "2025-01-15T10:30:00.000Z::DHZ"
time Date (epoch date) "10:30:00.000::H"

Native JSON types (string, number, boolean, null) pass through unchanged.

When to Use TYTX

Good fit:

  • Web apps with forms containing dates/decimals
  • Financial applications requiring decimal precision
  • APIs that send/receive typed data frequently
  • Excel-like grids with mixed types

Not needed:

  • APIs that only use strings and integers
  • Simple CRUD with no special types
  • Already using GraphQL/Protobuf with full type support

Documentation

I want to... Go to...
Try it in 5 minutes Quick Start
Use with FastAPI/Flask HTTP Integration
Understand the wire format How It Works
See API reference API Reference
Compare with alternatives Alternatives

License

Apache License 2.0 - Copyright 2025 Softwell S.r.l.

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

genro_tytx-0.8.0.tar.gz (373.7 kB view details)

Uploaded Source

Built Distribution

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

genro_tytx-0.8.0-py3-none-any.whl (17.6 kB view details)

Uploaded Python 3

File details

Details for the file genro_tytx-0.8.0.tar.gz.

File metadata

  • Download URL: genro_tytx-0.8.0.tar.gz
  • Upload date:
  • Size: 373.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for genro_tytx-0.8.0.tar.gz
Algorithm Hash digest
SHA256 a72211531ade57603317c364ab94f0be9c110a1f3e863adb0b25cdf905a40d47
MD5 e1d77942830c03bdf09fed9eb6ce33f1
BLAKE2b-256 a3efe2efaaf2b38c568ccfdd4d701e28194d334617402dd2462bb7e0f9dcd7af

See more details on using hashes here.

Provenance

The following attestation bundles were made for genro_tytx-0.8.0.tar.gz:

Publisher: publish.yml on genropy/genro-tytx

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file genro_tytx-0.8.0-py3-none-any.whl.

File metadata

  • Download URL: genro_tytx-0.8.0-py3-none-any.whl
  • Upload date:
  • Size: 17.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for genro_tytx-0.8.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b567540b58e72c73eea483f7df82196c0df8388b07accec44dd206d7a03dbc54
MD5 d6101c7a7a99dc6f476d5866b72099f8
BLAKE2b-256 f44602608068624abbe1f72d0493daf67a816e02066ba44ca9f949d77a403271

See more details on using hashes here.

Provenance

The following attestation bundles were made for genro_tytx-0.8.0-py3-none-any.whl:

Publisher: publish.yml on genropy/genro-tytx

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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