@inspectapi-io/sdk
v1.0.0
Published
Offline-first mobile inspection/survey SDK for PWA and Node.js applications
Maintainers
Readme
@inspectapi-io/sdk
Offline-first mobile inspection/survey SDK for PWA and Node.js applications.
Website: https://www.inspectapi.io
Features
- 🔌 Framework Agnostic - Works with React, Vue, Next.js, Svelte, vanilla JS
- 📴 Offline-First - Full offline support with IndexedDB
- 🔄 Sync Queue - Automatic sync when online, queue when offline
- 🖼️ Image Compression - Built-in image processing (SD/HD/Full HD)
- 📝 Row Elements - Generic system for comments, findings, attachments
- 🔧 Extensible - Register custom element types
- 📦 Universal - ESM, CommonJS, and UMD builds
Installation
npm install @inspectapi-io/sdkQuick Start
ESM (Next.js, Vite, etc.)
import { InspectorSDK } from '@inspectapi-io/sdk';
const sdk = new InspectorSDK({ mode: 'headless' });
await sdk.init();
// Load survey
await sdk.loadSurvey(surveyData);
// Navigate
const rows = sdk.getRows();
await sdk.navigateToRow(rows[0].rowId);
// Add comment
await sdk.addComment(rows[0].rowId, {
title: 'Issue Found',
description: 'Details here',
images: [compressedImage]
});CommonJS (Node.js)
const { InspectorSDK } = require('@inspectapi-io/sdk');
const sdk = new InspectorSDK();
await sdk.init();Browser (UMD)
<script src="https://cdn.jsdelivr.net/npm/@inspectapi-io/sdk/dist/inspector-sdk.min.js"></script>
<script>
const sdk = InspectorSDK.create({ mode: 'headless' });
sdk.init().then(() => {
console.log('SDK Ready!');
});
</script>Usage Examples
With Next.js
'use client';
import { InspectorSDK } from '@inspectapi-io/sdk';
import { useEffect, useState } from 'react';
export default function SurveyPage() {
const [sdk, setSDK] = useState(null);
const [rows, setRows] = useState([]);
useEffect(() => {
const init = async () => {
const instance = new InspectorSDK({ mode: 'headless' });
await instance.init();
instance.on('rowChanged', () => {
// React to row changes
});
setSDK(instance);
};
init();
}, []);
return (
<div>
{rows.map(row => (
<div key={row.rowId}>{row.rowText}</div>
))}
</div>
);
}With Your MQTT Library
import { InspectorSDK, createMQTTAdapter } from '@inspectapi-io/sdk';
import { YourMQTTClient } from 'your-mqtt-library';
// Create your MQTT client
const mqttClient = new YourMQTTClient({
broker: 'wss://your-broker.com:8884/mqtt'
});
// Wrap it with the adapter
const mqtt = createMQTTAdapter(mqttClient);
// Pass to SDK
const sdk = new InspectorSDK({
mode: 'headless',
mqtt: mqtt
});
await sdk.init();Image Compression
// Compress single image
const result = await sdk.compressImage(file);
console.log(`Compressed: ${result.savings}% smaller`);
// Compress multiple with progress
const results = await sdk.compressImages(files, (current, total) => {
console.log(`Processing ${current}/${total}`);
});
// Change quality preset
sdk.setImageSettings({ preset: 'hd' }); // 'sd', 'hd', or 'fhd'Custom Element Types
// Register a custom element type
sdk.registerElementType('finding', {
fields: ['type', 'severity', 'notes', 'images'],
validation: {
type: { required: true },
severity: { required: true, enum: ['low', 'medium', 'high'] }
},
mqttTopic: 'meabaseapp/uploadfindings'
});
// Use it
await sdk.addElement(rowId, 'finding', {
type: 'safety_hazard',
severity: 'high',
notes: 'Wet floor without warning sign'
});Event Handling
sdk.on('surveyLoaded', (data) => {
console.log(`Loaded ${data.rowCount} rows`);
});
sdk.on('syncStatusChanged', (stats) => {
console.log(`Pending: ${stats.pending}, Synced: ${stats.synced}`);
});
sdk.on('elementAdded', (element) => {
console.log(`Added ${element.type} to ${element.rowId}`);
});API Reference
InspectorSDK
Constructor Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| mode | 'headless' \| 'ui' | 'headless' | SDK mode |
| mqtt | MQTTAdapter | null | MQTT adapter |
| dbName | string | 'InspectorDB' | IndexedDB name |
| imagePreset | 'sd' \| 'hd' \| 'fhd' | 'hd' | Image preset |
Core Methods
// Initialization
await sdk.init();
// Survey
await sdk.loadSurvey(jsonData);
sdk.getRows();
sdk.getRow(rowId);
sdk.getCurrentRow();
await sdk.moveForward();
await sdk.moveBackward();
await sdk.navigateToRow(rowId);
await sdk.updateRow(rowId, updates);
await sdk.selectRating(1, 'תקין');
// Elements
await sdk.addElement(rowId, type, data);
await sdk.updateElement(elementId, data);
await sdk.deleteElement(elementId);
await sdk.getElements(rowId, type?);
sdk.registerElementType(type, config);
// Images
await sdk.compressImage(file);
await sdk.compressImages(files, onProgress);
sdk.setImageSettings({ preset: 'hd' });
// Sync
sdk.getSyncQueue();
sdk.getSyncStats();
await sdk.retrySync();
await sdk.deleteSyncItem(uuid);
await sdk.clearSyncedItems();
// Events
sdk.on(event, handler);
sdk.off(event, handler);Module Imports
For advanced usage, you can import individual modules:
import {
createStorage,
createSyncQueue,
createImageProcessor,
createRowElementsManager,
createStateManager,
createMQTTAdapter
} from '@inspectapi-io/sdk';TypeScript
Full TypeScript definitions are included:
import { InspectorSDK, SurveyRow, RowElement, SyncStats } from '@inspectapi-io/sdk';
const sdk = new InspectorSDK();
const rows: SurveyRow[] = await sdk.loadSurvey(data);Browser Support
- Chrome 80+
- Firefox 75+
- Safari 13.1+
- Edge 80+
Requires IndexedDB support.
License
MIT
