Skip to content

fcskit/kadi4mat-client

Repository files navigation

kadi4mat-client

A TypeScript/JavaScript client library for the Kadi4Mat REST API. Provides type-safe access to Kadi4Mat resources including records, collections, templates, files, and metadata.

📖 Documentation

View Full Documentation

Features

  • Type-safe - Full TypeScript support with comprehensive type definitions
  • Platform-agnostic - Works in Node.js and modern browsers
  • Zero dependencies - No runtime dependencies
  • Dual module format - ESM and CommonJS exports
  • Async/await - Modern promise-based API
  • Comprehensive - Covers all major Kadi4Mat API endpoints

Installation

npm install kadi4mat-client

Quick Start

Basic Usage

import { KadiClient } from 'kadi4mat-client';

// Create a client instance
const client = new KadiClient({
  host: 'https://kadi4mat.postlithiumstorage.org',
  pat: 'your-personal-access-token',
});

// Get current user information
const user = await client.getCurrentUser();
console.log(`Hello, ${user.displayname}!`);
console.log(`Email: ${user.identity.email}`);

// Create a new record
const record = await client.createRecord({
  title: 'My Experiment',
  description: 'Results from experiment XYZ',
  state: 'draft',
  extras: [
    { key: 'temperature', type: 'float', value: 25.5, unit: '°C' },
    { key: 'experimenter', type: 'str', value: user.identity.username },
  ],
});

// Upload a file to the record
await client.uploadRecordFile(record.id, {
  file: fileBlob,
  fileName: 'data.csv',
  description: 'Experimental data',
});

// List all records
const records = await client.listRecords({ page: 1, per_page: 20 });
console.log(`Found ${records.total} records`);

Using Configuration File (Recommended)

For easier credential management and to avoid hardcoding secrets, use a .env file:

# 1. Copy the example configuration
cp .env.example .env

# 2. Edit .env and add your credentials:
#    KADI_HOST=https://kadi4mat.postlithiumstorage.org
#    KADI_PAT=your_personal_access_token

# 3. Test the connection
npm run test:connection

Then in your code:

import { KadiClient, loadConfig } from 'kadi4mat-client';

// Load configuration from .env file
const config = loadConfig();
const client = new KadiClient(config);

// Use the client normally
const user = await client.getCurrentUser();

Note: The .env file is automatically excluded from git to protect your credentials.

Configuration

The KadiClient constructor accepts a configuration object:

interface KadiClientConfig {
  host: string;      // Kadi4Mat instance URL (e.g., 'https://kadi4mat.postlithiumstorage.org')
  pat: string;       // Personal Access Token
  timeout?: number;  // Request timeout in milliseconds (default: 60000)
  verify?: boolean;  // SSL certificate verification (default: true)
}

Getting a Personal Access Token

  1. Log in to your Kadi4Mat instance
  2. Go to your user settings
  3. Navigate to "Personal Access Tokens"
  4. Click "Create new token"
  5. Give it a descriptive name and select the required permissions
  6. Copy the token (you won't be able to see it again!)

API Reference

Records

// Get a record by ID
const record = await client.getRecord(123);

// Create a new record
const record = await client.createRecord({
  title: 'My Record',
  description: 'Description',
  state: 'draft', // 'draft' | 'submitted' | 'published'
  visibility: 'private', // 'private' | 'internal' | 'public'
  extras: [
    { key: 'temperature', value: 25, unit: '°C' },
    { key: 'pressure', value: 1.013, unit: 'bar' },
  ],
});

// Update a record
const updated = await client.updateRecord(record.id, {
  title: 'Updated Title',
  state: 'published',
});

// Delete a record
await client.deleteRecord(record.id);

// List records with pagination
const response = await client.listRecords({ page: 1, per_page: 20 });
// response.results - array of records
// response.total - total number of records
// response.page - current page
// response.per_page - items per page
// response.total_pages - total number of pages

Files

// Get files for a record
const files = await client.getRecordFiles(recordId);

// Upload a file
const fileInfo = await client.uploadRecordFile(recordId, {
  file: blob, // Blob | ArrayBuffer | Uint8Array
  fileName: 'data.csv',
  description: 'Optional description',
  force: false, // Set to true to overwrite existing file
});

// Download a file
const blob = await client.downloadRecordFile(recordId, fileId);

// Delete a file
await client.deleteRecordFile(recordId, fileId);

Collections

// Get a collection
const collection = await client.getCollection(123);

// Create a new collection
const collection = await client.createCollection({
  title: 'My Collection',
  description: 'A collection of related records',
  visibility: 'internal',
  records: [1, 2, 3], // Optional: array of record IDs
});

// Update a collection
await client.updateCollection(collection.id, {
  title: 'Updated Collection',
});

// Add records to a collection
await client.addRecordsToCollection(collection.id, [4, 5, 6]);

// Remove records from a collection
await client.removeRecordsFromCollection(collection.id, [1]);

// Delete a collection
await client.deleteCollection(collection.id);

// List collections
const collections = await client.listCollections({ page: 1, per_page: 20 });

Templates

// Get a template
const template = await client.getTemplate(123);

// Create a new template
const template = await client.createTemplate({
  title: 'Experiment Template',
  type: 'record', // 'record' | 'collection'
  fields: [
    {
      key: 'temperature',
      label: 'Temperature',
      type: 'float',
      unit: '°C',
      required: true,
    },
    {
      key: 'method',
      label: 'Method',
      type: 'select',
      options: ['Method A', 'Method B', 'Method C'],
      required: true,
    },
  ],
});

// Update a template
await client.updateTemplate(template.id, {
  title: 'Updated Template',
});

// Delete a template
await client.deleteTemplate(template.id);

// List templates
const templates = await client.listTemplates({ page: 1, per_page: 20 });

Search

// Search for resources
const results = await client.search({
  query: 'experiment',
  type: 'record', // 'record' | 'collection' | 'template'
  state: 'published', // 'draft' | 'submitted' | 'published'
  visibility: 'public', // 'private' | 'internal' | 'public'
  page: 1,
  per_page: 20,
});

Users & Groups

// Get current user
const user = await client.getCurrentUser();

// Get a user by ID
const user = await client.getUser(123);

// Get a group
const group = await client.getGroup(456);

// List groups
const groups = await client.listGroups({ page: 1, per_page: 20 });

Error Handling

The client throws custom error classes for different types of errors:

import {
  KadiError,
  KadiAuthError,
  KadiNotFoundError,
  KadiValidationError,
  KadiRateLimitError,
  KadiServerError,
  KadiNetworkError,
} from 'kadi4mat-client';

try {
  const record = await client.getRecord(123);
} catch (error) {
  if (error instanceof KadiAuthError) {
    console.error('Authentication failed:', error.message);
  } else if (error instanceof KadiNotFoundError) {
    console.error('Record not found:', error.message);
  } else if (error instanceof KadiValidationError) {
    console.error('Validation error:', error.message);
    console.error('Details:', error.response);
  } else if (error instanceof KadiNetworkError) {
    console.error('Network error:', error.message);
  } else {
    console.error('Unknown error:', error);
  }
}

TypeScript Support

This library is written in TypeScript and provides comprehensive type definitions:

import {
  KadiClient,
  Record as KadiRecord,
  Collection,
  Template,
  FileInfo,
  CreateRecordParams,
  UpdateRecordParams,
  PaginatedResponse,
} from 'kadi4mat-client';

// All types are fully typed
const client = new KadiClient({ host: '...', pat: '...' });

// TypeScript knows the return types
const record: KadiRecord = await client.getRecord(123);
const records: PaginatedResponse<KadiRecord> = await client.listRecords();

// And validates parameters
await client.createRecord({
  title: 'My Record', // required
  state: 'draft', // autocomplete: 'draft' | 'submitted' | 'published'
  // TypeScript will error if you use invalid values
});

Platform Compatibility

Node.js

The library works with Node.js 16.0.0 and higher:

const { KadiClient } = require('kadi4mat-client');
// or
import { KadiClient } from 'kadi4mat-client';

Browser

The library works in modern browsers that support ES2020:

<script type="module">
  import { KadiClient } from 'kadi4mat-client';
  
  const client = new KadiClient({
    host: 'https://kadi.iam.kit.edu',
    pat: 'your-token',
  });
  
  const user = await client.getCurrentUser();
  console.log(user);
</script>

Examples

See the examples/ directory for more complete examples:

Development

# Clone the repository
git clone https://github.com/your-org/kadi4mat-client.git
cd kadi4mat-client

# Install dependencies
npm install

# Build the library
npm run build

# Run tests
npm test

# Run tests with coverage
npm run test:coverage

# Lint code
npm run lint

# Format code
npm run format

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

License

Apache-2.0 License - see LICENSE for details.

Resources

Related Projects

About

TypeScript client library for Kadi4Mat REST API

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published