@jigx/mdk
Version:
Jigx Mobile Development Kit - SDK for building Jigx applications
448 lines (358 loc) • 12.9 kB
Markdown
[](https://github.com/jigx-com/jigx-mdk/actions/workflows/release.yml)
[](https://github.com/jigx-com/jigx-mdk/actions/workflows/code-quality.yml)
A comprehensive TypeScript MDK (Mobile Development Kit) for building mobile-first applications with the Jigx platform. This SDK provides a fluent API for creating offline-capable, data-driven mobile applications using Jigx's unique document-based architecture.
The style of the MDK follows that of a CDK, i.e., a declarative SDK. It compiles to Jigx's YAML configuration format.
[Guide](./dist/docs/DOCS.md)
## Overview
Jigx is a mobile-first application platform that enables developers to build offline-capable, enterprise-grade mobile applications. This SDK provides a TypeScript-based fluent API that compiles to Jigx's YAML configuration format.
### Key Concepts
- **Mobile-First Architecture**: All UI patterns optimized for mobile devices with bottom-action buttons and touch-friendly interfaces
- **Document-Based Storage**: SQLite + JSON architecture for flexible, offline-capable data management
- **Expression System**: Powerful JSONata-based expressions for dynamic data binding and transformations
- **Builder Pattern API**: Intuitive fluent API with full TypeScript type safety and IntelliSense support
## Features
### Application Building
- **ApplicationBuilder**: Main entry point for creating Jigx applications
- **Screen Types**: List, Default, Calendar, Table, Grid, and Tab screens
- **Component Library**: 50+ mobile-optimized UI components
- **Action System**: Navigation, data operations, and user interactions
- **Data Management**: Datasources, entities, and functions for data operations
### Core SDK Modules
- **Screen SDK**: All screen types with mobile-first layouts
- **Component SDK**: UI components (forms, lists, charts, media, etc.)
- **Action SDK**: User interactions, navigation, and data operations
- **Datasource SDK**: Data providers (dynamic, local, REST, SQL)
- **Function SDK**: Business logic (REST API, SQL queries, SOAP)
- **Widget SDK**: Home screen widgets for quick access
- **Database SDK**: Database connection configurations
### Development Experience
- **Type Safety**: Full TypeScript support with comprehensive type definitions
- **Fluent API**: Intuitive method chaining for rapid development
- **IntelliSense**: Rich IDE support with documentation and examples
- **Expression Helpers**: CTX utilities for accessing runtime data
- **Validation**: Built-in schema validation and error reporting
## Installation
```bash
# Using npm
npm install @jigx/mdk
# Using yarn
yarn add @jigx/mdk
# Using bun
bun add @jigx/mdk
```
## Quick Start
```typescript
import { application } from '@jigx/mdk'
const app = application('my-app', 'My Mobile App')
// Create a customer list screen
const listScreen = app.addScreen.list('customer-list', 'Customers')
.data('=@ctx.datasources.customers')
// Add list items
listScreen.addControl.listItem('customer-item')
.title('=@ctx.current.item.name')
.subtitle('=@ctx.current.item.email')
.onPress.goto('customer-detail')
.parameter('customerId', '=@ctx.current.item.id')
// Add bottom action button (mobile-first pattern)
listScreen.bottomPanel.buttons(1)
.add.goto('Add Customer', 'customer-form')
.style({ isPrimary: true })
// Build the application
const application = app.build()
```
All UI patterns are optimized for mobile devices:
- Action buttons ALWAYS at screen bottom (max 3 visible)
- Touch-optimized controls and layouts
- Offline-first data synchronization
### 2. Document-Based Data Model
```typescript
// All data stored as JSON documents
const datasource = app.addDatasource.sqlite('customers', 'dynamic')
.entity('default/customers')
.query(`
SELECT
id,
json_extract(data, '$.name') as name,
json_extract(data, '$.email') as email
FROM [default/customers]
WHERE json_extract(data, '$.active') = true
`)
```
```typescript
// Dynamic values with JSONata expressions
import { CTX } from '@jigx/mdk'
// Access datasources
CTX.datasources.expr('users') // '=@ctx.datasources.users'
// Access component state
CTX.components.expr('email', 'value') // '=@ctx.components.email.state.value'
// Access navigation parameters
CTX.screen.inputs.expr('customerId') // '=@ctx.jig.inputs.customerId'
```
```typescript
const listScreen = app.addScreen.list('products', 'Product Catalog')
.data('=@ctx.datasources.products')
.onRefresh.syncEntities()
.entity('products')
```
```typescript
const formScreen = app.addScreen.default('user-form', 'User Registration')
// Add form fields
formScreen.addControl.textField('name')
.label('Full Name')
.required(true)
formScreen.addControl.emailField('email')
.label('Email Address')
.required(true)
// Bottom action buttons
const buttons = formScreen.bottomPanel.buttons(2)
buttons.add.goto('Cancel', 'home')
buttons.add.executeEntity('Save')
.style({ isPrimary: true })
.dynamicData('users', 'create')
.data({
name: '=@ctx.components.name.state.value',
email: '=@ctx.components.email.state.value'
})
```
```typescript
const calendarScreen = app.addScreen.calendar('events', 'Event Calendar')
.data('=@ctx.datasources.events')
.dateField('=@ctx.current.item.date')
.titleField('=@ctx.current.item.title')
```
```typescript
const tableScreen = app.addScreen.table('inventory', 'Inventory')
.data('=@ctx.datasources.inventory')
tableScreen.addColumn('product', 'Product').width(200)
tableScreen.addColumn('quantity', 'Qty').width(80)
tableScreen.addColumn('price', 'Price').format('currency')
```
```typescript
app.addDatasource.sqlite('shared-data', 'dynamic')
.entity('default/customers')
.query(`SELECT * FROM [default/customers]`)
```
```typescript
app.addDatasource.sqlite('preferences', 'local')
.entity('user-preferences')
.query(`SELECT * FROM [user-preferences]`)
```
```typescript
const apiFunction = app.addFunction.rest('get-users', 'GET', 'https://api.example.com/users')
apiFunction.params.header('Authorization', 'Bearer =@ctx.solution.state.token')
```
```typescript
const sqlFunction = app.addFunction.sql('get-customer', 'customer-db')
.sql('SELECT * FROM customers WHERE id = @customerId')
sqlFunction.params.input('customerId', 'string')
```
```typescript
// WRONG - No inline buttons!
screen.addControl.button('save')
// WRONG - Direct column access
.query('SELECT name FROM users')
// WRONG - Too many visible buttons
screen.bottomPanel.buttons(4)
```
```typescript
// CORRECT - Buttons at screen bottom
screen.bottomPanel.buttons(2)
.add.executeEntity('Save')
// CORRECT - Use json_extract
.query(`SELECT json_extract(data, '$.name') as name FROM users`)
// CORRECT - Max 3 visible buttons
screen.bottomPanel.buttons(3)
```
## Component Examples
### Form Components
```typescript
// Text input
screen.addControl.textField('name')
.label('Name')
.placeholder('Enter your name')
.required(true)
// Dropdown
screen.addControl.dropdown('category')
.label('Category')
.datasource('=@ctx.datasources.categories')
.title('=@ctx.current.item.name')
.value('=@ctx.current.item.id')
// Date picker
screen.addControl.datePicker('startDate')
.label('Start Date')
.minimumDate('=@now()')
```
### List Components
```typescript
// List item with swipe actions
const listItem = screen.addControl.listItem('product-item')
.title('=@ctx.current.item.name')
.subtitle('=$currency(@ctx.current.item.price)')
.image('=@ctx.current.item.imageUrl')
// Swipe actions
listItem.swipeable.leftActions
.addAction.goto('Edit', 'edit-product')
.parameter('productId', '=@ctx.current.item.id')
listItem.swipeable.rightActions
.addAction.executeEntity('Delete')
.dynamicData('products', 'delete')
.data({ id: '=@ctx.current.item.id' })
```
```typescript
// Line chart
screen.addControl.lineChart('sales-chart')
.data('=@ctx.datasources.sales')
.xAxis('date')
.yAxis('revenue')
.height(300)
// Pie chart
screen.addControl.pieChart('category-distribution')
.data('=@ctx.datasources.categories')
.labelField('name')
.valueField('count')
```
```typescript
// Set state
action.setState('currentUser')
.value({ id: '123', name: 'John' })
// Access state
CTX.application.state.expr('currentUser.name')
```
```typescript
// Set screen state
action.setScreenState('selectedTab')
.value('products')
// Access screen state
'=@ctx.jig.state.selectedTab'
```
```typescript
// Access component value
'=@ctx.components.email.state.value'
// Check if valid
'=@ctx.components.email.state.isValid'
```
```typescript
// Master list
const list = app.addScreen.list('orders', 'Orders')
.data('=@ctx.datasources.orders')
list.addControl.listItem('order-item')
.title('=@ctx.current.item.orderNumber')
.subtitle('=$currency(@ctx.current.item.total)')
.onPress.goto('order-detail')
.parameter('orderId', '=@ctx.current.item.id')
.parameter('returnScreen', 'orders')
// Detail screen
const detail = app.addScreen.default('order-detail', 'Order Details')
// Add datasource for single order
detail.addDatasource.sqlite('order', 'dynamic')
.entity('default/orders')
.query(`
SELECT * FROM [default/orders]
WHERE id = @orderId
`)
.parameter('orderId', '=@ctx.jig.inputs.orderId')
// Back navigation
detail.bottomPanel.buttons(1)
.add.goto('Back', '=@ctx.jig.inputs.returnScreen')
```
```typescript
// Initial sync on app load
app.onLoad.actionList('sequential')
.actions.syncEntities()
.dynamic()
.entity('users')
.entity('products')
.entity('orders')
// Pull-to-refresh on screen
screen.onRefresh.syncEntities()
.dynamic()
.entity('orders')
.onSuccess.notification('Success', 'Orders refreshed')
.onError.notification('Error', 'Sync failed')
```
```typescript
const form = app.addScreen.default('product-form', 'New Product')
// Form fields with validation
form.addControl.textField('name')
.label('Product Name')
.required(true)
.minLength(3)
.maxLength(50)
form.addControl.numberField('price')
.label('Price')
.required(true)
.minimum(0)
.format('currency')
form.addControl.dropdown('category')
.label('Category')
.required(true)
.datasource('=@ctx.datasources.categories')
.title('=@ctx.current.item.name')
.value('=@ctx.current.item.id')
// Conditional visibility
form.addControl.textField('discount')
.label('Discount Code')
.isVisible('=@ctx.components.price.state.value > 100')
// Form submission with validation
const buttons = form.bottomPanel.buttons(2)
buttons.add.goto('Cancel', 'products')
buttons.add.actionList('Save', 'sequential')
.style({ isPrimary: true })
.actions.executeEntity()
.dynamicData('products', 'create')
.data({
name: '=@ctx.components.name.state.value',
price: '=@ctx.components.price.state.value',
category: '=@ctx.components.category.state.selected.value',
discount: '=@ctx.components.discount.state.value'
})
.actions.syncEntities()
.entity('products')
.actions.goto('products')
```
The SDK is organized into modular components:
- **Application SDK**: Main application builder and configuration
- **Screen SDK**: All screen types and layouts
- **Component SDK**: UI components and controls
- **Action SDK**: User interactions and navigation
- **Datasource SDK**: Data management and queries
- **Function SDK**: Business logic and integrations
- **Database SDK**: Database connection configurations
- **Widget SDK**: Home screen widgets
- [Official Jigx Documentation](https://docs.jigx.com)
- [Jigx SDK Guide](./dist/docs/DOCS.md) - Comprehensive guide with examples and patterns
- [SDK API Reference](./docs/API.md)
- [Migration Guide](./docs/MIGRATION.md)
- [Best Practices](./docs/BEST_PRACTICES.md)
Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests.
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.