A TypeScript/JavaScript client library for the Kadi4Mat REST API. Provides type-safe access to Kadi4Mat resources including records, collections, templates, files, and metadata.
- ✅ 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
npm install kadi4mat-clientimport { 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`);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:connectionThen 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.
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)
}- Log in to your Kadi4Mat instance
- Go to your user settings
- Navigate to "Personal Access Tokens"
- Click "Create new token"
- Give it a descriptive name and select the required permissions
- Copy the token (you won't be able to see it again!)
// 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// 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);// 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 });// 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 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,
});// 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 });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);
}
}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
});The library works with Node.js 16.0.0 and higher:
const { KadiClient } = require('kadi4mat-client');
// or
import { KadiClient } from 'kadi4mat-client';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>See the examples/ directory for more complete examples:
- basic-usage.ts - Basic CRUD operations
- file-operations.ts - File upload/download
- batch-operations.ts - Batch processing
- error-handling.ts - Error handling patterns
# 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 formatContributions are welcome! Please see CONTRIBUTING.md for guidelines.
Apache-2.0 License - see LICENSE for details.
- obsidian-kadi4mat-sync - Obsidian plugin for syncing notes to Kadi4Mat
- kadi-apy - Official Python client for Kadi4Mat