npm package: @inspectapi-io/sdk
Description: Offline-first mobile inspection/survey SDK for PWA and Node.js applications
Author: NoCodeROI
Latest version: 1.0.0

# @inspectapi-io/sdk

Offline-first mobile inspection/survey SDK for PWA and Node.js applications.

**Website:** [https://www.inspectapi.io](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

```bash
npm install @inspectapi-io/sdk
```

## Quick Start

### ESM (Next.js, Vite, etc.)

```javascript
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)

```javascript
const { InspectorSDK } = require('@inspectapi-io/sdk');

const sdk = new InspectorSDK();
await sdk.init();
```

### Browser (UMD)

```html
<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

```jsx
'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

```javascript
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

```javascript
// 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

```javascript
// 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

```javascript
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

```javascript
// 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:

```javascript
import {
  createStorage,
  createSyncQueue,
  createImageProcessor,
  createRowElementsManager,
  createStateManager,
  createMQTTAdapter
} from '@inspectapi-io/sdk';
```

## TypeScript

Full TypeScript definitions are included:

```typescript
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