Skip to main content

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)

Untyped JSON codec

Besides the typed to_tytx / from_tytx API, TYTX exposes a plain JSON codec for the untyped path — no type suffixes, just fast JSON (orjson when available, stdlib otherwise):

from genro_tytx import json_dumps, json_loads

json_dumps({"a": 1})        # -> b'{"a":1}'   (UTF-8 bytes)
json_loads('{"a": 1}')      # accepts str or bytes -> {"a": 1}

json_dumps returns UTF-8 bytes (ready for ASGI/WebSocket send), json_loads accepts str or bytes. Use these when you want plain JSON; use to_tytx / from_tytx when you want typed values to flow.

Custom types

register_type lets an external package teach TYTX a new type — a serialize hook (object → string) and a deserialize hook (string → object) under a custom suffix. The package registers at its own import time, so TYTX gains no dependency on it:

from genro_tytx import register_type, to_tytx, from_tytx

class Point:
    def __init__(self, x, y): self.x, self.y = x, y

register_type(Point, "PT", lambda p: f"{p.x},{p.y}",
              lambda s: Point(*map(int, s.split(","))))

to_tytx([1, Point(5, 6), "k"])   # '[1,"5,6::PT","k"]::JS'
from_tytx('5,6::PT')             # Point(5, 6)

The custom type flows like any built-in scalar, including nested inside dicts and lists. Matching is by exact type — subclasses must be registered explicitly. Re-registering the same class replaces its hooks; reusing a suffix owned by a different type raises an error. The same semantics apply to the JavaScript client (registerType / registerClass).

When the type owns its serialization, register_class reads the hooks from the class itself — usable as a decorator. It needs __tytx_suffix__, an instance to_tytx() and a from_tytx classmethod (from_tytx must be a classmethod: decoding starts from the suffix and rebuilds the instance from scratch):

from genro_tytx import register_class

@register_class
class Point:
    __tytx_suffix__ = "PT"
    def __init__(self, x, y): self.x, self.y = x, y
    def to_tytx(self): return f"{self.x},{self.y}"
    @classmethod
    def from_tytx(cls, s): return cls(*map(int, s.split(",")))

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

import { fetchTytx } from 'genro-tytx';

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

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' });

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 it over HTTP 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.

Metadata

Release files for genro-tytx 0.13.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for genro-tytx 0.13.0
File Size Uploaded
genro_tytx-0.13.0.tar.gz 392.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for genro-tytx 0.13.0
File Interpreter ABI Platform
genro_tytx-0.13.0-py3-none-any.whl Python 3 none any Details

Total release size: 411.5 kB

Release files / genro_tytx-0.13.0.tar.gz

Download URL genro_tytx-0.13.0.tar.gz
Size 392.6 kB
Tags Source
SHA-256 checksum
How to use checksums
cae552460de7162b892853cd4ce8fc7a1cffa0401322654a670789ddec6f3d8a
BLAKE2b-256 checksum
How to use checksums
c9cc679f8c95dd834194bebe8a193808d7fe09acbde6d6df75c7faea3b103408
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 2, 2026.

Transparency log

Release files / genro_tytx-0.13.0-py3-none-any.whl

Download URL genro_tytx-0.13.0-py3-none-any.whl
Size 18.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
96131e5be39c1721bac628b01022e3f90fe1d9640ac0602fbc35885896d651ec
BLAKE2b-256 checksum
How to use checksums
97a3996fb341b47a169aee1e6a886263af5e561876ea7099367e452706571ef5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 2, 2026.

Transparency log

Release history Release notifications | RSS feed

0.16.0

2 release files

This release

0.13.0 This release

2 release files

0.10.1

2 release files

0.10.0

2 release files

0.9.3

2 release files

0.9.2

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.4

2 release files

0.7.3

2 release files

0.7.2

2 release files

0.7.0

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.3.0

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page