🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@kaiord/core

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@kaiord/core

Core library for the Kaiord health & fitness data framework

Source
npmnpm
Version
4.9.0
Version published
Weekly downloads
245
469.77%
Maintainers
1
Weekly downloads
 
Created
Source

@kaiord/core

npm version License: MIT Build Status

Core library for the Kaiord health & fitness data framework. Contains domain types, schemas, ports, use cases, and the plugin architecture for format adapters.

Note: As of v2.0, format adapters (FIT, TCX, ZWO) are in separate packages. Install only the adapters you need for optimal bundle size.

Features

  • KRD canonical format with Zod schema validation
  • Hexagonal architecture with ports and adapters pattern
  • Plugin architecture for format adapters
  • Full TypeScript support with type inference
  • Custom logger injection
  • Tree-shakeable ESM bundle

Installation

npm install @kaiord/core

or with pnpm:

pnpm add @kaiord/core

or with yarn:

yarn add @kaiord/core

Quick Start

Single Format

import { createDefaultProviders } from "@kaiord/core";
import { createFitProviders } from "@kaiord/fit";
import type { KRD } from "@kaiord/core";
import { readFile } from "fs/promises";

// Wire FIT adapter into core
const providers = createDefaultProviders({
  fit: createFitProviders(),
});

// Convert FIT to KRD
const fitBuffer = await readFile("workout.fit");
const krd: KRD = await providers.convertFitToKrd!({ fitBuffer });

// Convert KRD to FIT
const output = await providers.convertKrdToFit!({ krd });

Multiple Formats

import { createDefaultProviders } from "@kaiord/core";
import { createFitProviders } from "@kaiord/fit";
import { createTcxProviders } from "@kaiord/tcx";
import { createZwoProviders } from "@kaiord/zwo";

// Wire all adapters you need
const providers = createDefaultProviders({
  fit: createFitProviders(),
  tcx: createTcxProviders(),
  zwo: createZwoProviders(),
});

// Convert between formats
const krd = await providers.convertFitToKrd!({ fitBuffer });
const tcx = await providers.convertKrdToTcx!({ krd });
const zwo = await providers.convertKrdToZwift!({ krd });

Schema Validation

import { krdSchema } from "@kaiord/core";

// Validate KRD data
const result = krdSchema.safeParse(data);

if (result.success) {
  console.log("Valid KRD:", result.data);
} else {
  console.error("Validation errors:", result.error.errors);
}

API Overview

Main Functions

createDefaultProviders(adapters?, logger?)

Creates a provider container with optional format adapters wired in.

import { createDefaultProviders } from "@kaiord/core";
import { createFitProviders } from "@kaiord/fit";
import { createTcxProviders } from "@kaiord/tcx";

const providers = createDefaultProviders({
  fit: createFitProviders(),
  tcx: createTcxProviders(),
});
// Returns: { schemaValidator, toleranceChecker, logger, convertFitToKrd, ... }

convertFitToKrd({ fitBuffer })

Converts a FIT workout file to KRD format.

const krd = await providers.convertFitToKrd({ fitBuffer });

Parameters:

  • fitBuffer: Uint8Array - Binary FIT file data

Returns: Promise<KRD> - Validated KRD object

Throws:

  • FitParsingError - When FIT file is corrupted or invalid
  • KrdValidationError - When converted data fails schema validation

convertKrdToFit({ krd })

Converts a KRD object to FIT workout file format.

const fitBuffer = await providers.convertKrdToFit({ krd });

Parameters:

  • krd: KRD - Valid KRD object

Returns: Promise<Uint8Array> - Binary FIT file data

Throws:

  • KrdValidationError - When KRD data is invalid
  • FitParsingError - When FIT encoding fails

validateRoundTrip({ fitBuffer })

Validates that FIT → KRD → FIT conversion preserves data within tolerances.

import { validateRoundTrip, createToleranceChecker } from "@kaiord/core";

const checker = createToleranceChecker();
await validateRoundTrip(
  fitReader,
  fitWriter,
  validator,
  checker,
  logger
)({
  fitBuffer,
});

Throws:

  • ToleranceExceededError - When round-trip conversion exceeds tolerances

Schema Exports

All domain schemas are exported for validation and type inference:

import {
  krdSchema,
  workoutSchema,
  durationSchema,
  targetSchema,
  sportSchema,
  subSportSchema,
  intensitySchema,
} from "@kaiord/core";

// Validate data
const result = krdSchema.safeParse(data);

// Access enum values
const sport = sportSchema.enum.cycling;
const intensity = intensitySchema.enum.warmup;

Type Exports

All TypeScript types are inferred from Zod schemas:

import type {
  KRD,
  Workout,
  WorkoutStep,
  Duration,
  Target,
  Sport,
  SubSport,
  Intensity,
} from "@kaiord/core";

Error Types

import {
  FitParsingError,
  KrdValidationError,
  ToleranceExceededError,
} from "@kaiord/core";

For detailed API examples, see docs/api-examples.md (coming soon).

TypeScript Support

@kaiord/core is written in TypeScript and provides complete type definitions.

Type Imports

Import types separately from values for optimal tree-shaking:

import { createDefaultProviders, krdSchema } from "@kaiord/core";
import type { KRD, Workout, Duration } from "@kaiord/core";

Discriminated Unions

Duration and Target types use discriminated unions for type safety:

import type { Duration } from "@kaiord/core";

const duration: Duration =
  | { type: "time"; seconds: number }
  | { type: "distance"; meters: number }
  | { type: "open" };

// TypeScript narrows the type based on discriminator
if (duration.type === "time") {
  console.log(duration.seconds); // ✓ TypeScript knows this exists
}
import type { Target } from "@kaiord/core";

const target: Target =
  | { type: "power"; value: { unit: "watts"; value: number } }
  | { type: "heart_rate"; value: { unit: "bpm"; value: number } }
  | { type: "open" };

// Type narrowing works automatically
if (target.type === "power") {
  console.log(target.value.unit); // ✓ "watts" | "percent_ftp" | "zone" | "range"
}

Schema Validation with Type Inference

Zod schemas provide both runtime validation and TypeScript types:

import { krdSchema, workoutSchema } from "@kaiord/core";
import type { KRD, Workout } from "@kaiord/core";

// Parse with automatic type inference
const krd = krdSchema.parse(data); // Type: KRD

// Safe parse with error handling
const result = krdSchema.safeParse(data);
if (result.success) {
  const krd: KRD = result.data; // Type: KRD
} else {
  console.error(result.error.errors);
}

// Validate nested objects
const workout = workoutSchema.parse(data); // Type: Workout

Enum Values

Access enum values via schema .enum property:

import { sportSchema, intensitySchema } from "@kaiord/core";

// Access enum values
const sport = sportSchema.enum.cycling; // "cycling"
const intensity = intensitySchema.enum.warmup; // "warmup"

// Use in comparisons
if (workout.sport === sportSchema.enum.running) {
  console.log("Running workout");
}

Error Handling

@kaiord/core uses custom error classes for different failure scenarios.

Error Types

FitParsingError

Thrown when FIT file parsing fails due to corrupted or invalid data.

import { FitParsingError } from "@kaiord/core";

try {
  const krd = await providers.convertFitToKrd({ fitBuffer });
} catch (error) {
  if (error instanceof FitParsingError) {
    console.error("Failed to parse FIT file:", error.message);
    console.error("Original error:", error.cause);
  }
}

Properties:

  • message: string - Error description
  • cause?: unknown - Original error from FIT SDK

KrdValidationError

Thrown when KRD data fails schema validation.

import { KrdValidationError } from "@kaiord/core";

try {
  const krd = await providers.convertFitToKrd({ fitBuffer });
} catch (error) {
  if (error instanceof KrdValidationError) {
    console.error("KRD validation failed:");
    for (const err of error.errors) {
      console.error(`  - ${err.field}: ${err.message}`);
    }
  }
}

Properties:

  • message: string - Error description
  • errors: Array<{ field: string; message: string }> - Validation errors

ToleranceExceededError

Thrown when round-trip conversion exceeds defined tolerances.

import { ToleranceExceededError } from "@kaiord/core";

try {
  await validateRoundTrip(
    fitReader,
    fitWriter,
    validator,
    checker,
    logger
  )({
    fitBuffer,
  });
} catch (error) {
  if (error instanceof ToleranceExceededError) {
    console.error("Round-trip validation failed:");
    for (const violation of error.violations) {
      console.error(
        `  - ${violation.field}: expected ${violation.expected}, got ${violation.actual}`
      );
      console.error(
        `    Deviation: ${violation.deviation}, tolerance: ${violation.tolerance}`
      );
    }
  }
}

Properties:

  • message: string - Error description
  • violations: Array<{ field: string; expected: number; actual: number; deviation: number; tolerance: number }> - Tolerance violations

Complete Error Handling Example

import {
  createDefaultProviders,
  FitParsingError,
  KrdValidationError,
  ToleranceExceededError,
} from "@kaiord/core";

async function convertWorkout(fitBuffer: Uint8Array) {
  try {
    const providers = createDefaultProviders();
    const krd = await providers.convertFitToKrd({ fitBuffer });
    return krd;
  } catch (error) {
    if (error instanceof FitParsingError) {
      console.error("❌ FIT parsing failed:", error.message);
      if (error.cause) {
        console.error("   Cause:", error.cause);
      }
      throw new Error("Invalid FIT file");
    }

    if (error instanceof KrdValidationError) {
      console.error("❌ KRD validation failed:");
      for (const err of error.errors) {
        console.error(`   - ${err.field}: ${err.message}`);
      }
      throw new Error("Conversion produced invalid KRD");
    }

    // Unknown error - re-throw
    throw error;
  }
}

Documentation

Main Documentation

Package-Specific Documentation

Contributing

We welcome contributions! Please see:

Before contributing:

Scripts

pnpm build                  # Build the library
pnpm test                   # Run tests once
pnpm test:watch             # Run tests in watch mode
pnpm test:coverage          # Run tests with coverage report
pnpm generate:schema        # Generate JSON Schema from Zod schemas
pnpm generate:krd-fixtures  # Generate KRD test fixtures from FIT files
pnpm clean                  # Clean build artifacts

Tree-Shaking

@kaiord/core is fully optimized for tree-shaking. Import only what you need:

// ✅ Good: Import specific items (smaller bundle)
import { krdSchema, sportSchema } from "@kaiord/core";
import type { KRD, Sport } from "@kaiord/core";

// Test utilities (separate export, not included in main bundle)
import { loadKrdFixture } from "@kaiord/core/test-utils";

// ❌ Avoid: Import everything (larger bundle)
import * as Kaiord from "@kaiord/core";

Bundle sizes (minified + gzipped):

  • Types only: 0 KB (compile-time)
  • Schema validation: ~15 KB
  • Full conversion: ~80 KB
  • Test utilities: Not included in production bundles

See docs/tree-shaking.md for detailed guide and best practices.

Test Utilities

The package exports test utilities for other packages to use:

import {
  loadFitFixture,
  loadKrdFixture,
  loadFixturePair,
  FIXTURE_NAMES,
} from "@kaiord/core/test-utils";

// Load fixtures for testing
const fitBuffer = loadFitFixture("WorkoutIndividualSteps.fit");
const krd = loadKrdFixture("WorkoutIndividualSteps.krd");

// Load both for round-trip tests
const { fit, krd } = loadFixturePair(FIXTURE_NAMES.INDIVIDUAL_STEPS);

See docs/krd-fixtures-generation.md for details on fixture generation.

Keywords

kaiord

FAQs

Package last updated on 06 Mar 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts