api-client/packages/hoppscotch-kernel
Shreyas 137e95e873
fix(relay): expand MIME type support (#5306)
This fixes file uploads incorrectly showing MIME type as "Other" instead
 of their actual content types by expanding the `MediaType` enum relay
 to include common audio, video, and image formats.

 Basically `MediaType` enum is used for both `ContentType` which would
 map to `ContentType` from `hoppscotch-data` (e.g. `multipart/form-data`)
 but also to `FormValue` in `interop`
 ```rust
 pub enum FormValue {
     ...
     File {
         filename: String,
         content_type: MediaType,
         data: Bytes,
     },
 }
 ```
 although the later should be much more pervasive.

 This is a follow up on #5244

 Closes FE-887
 Closes #3810
 Closes #5223
 Closes #5233

 The issue occurred because the `relay`'s `MediaType` couldn't deserialize
 beyond the basic types (text, JSON, XML, etc.), lacked support for
 other media file types. The TypeScript layer correctly detected MIME
 types (e.g., "audio/x-m4a"), but the deserialization process fell back
 to `MediaType::Other`. Main reason for servers performing strict MIME
 validation to reject uploads.
2025-08-08 13:51:46 +05:30
..
src feat(kernel): extensible content media types (#5244) 2025-07-24 16:29:50 +05:30
package.json fix(relay): expand MIME type support (#5306) 2025-08-08 13:51:46 +05:30
README.md feat(kernel): multi-instance support for store (#5083) 2025-05-21 19:08:55 +05:30
tsconfig.base.json feat: platform independent core and the new desktop app (#4684) 2025-02-28 00:01:25 +05:30
tsconfig.decl.json feat: platform independent core and the new desktop app (#4684) 2025-02-28 00:01:25 +05:30
tsconfig.json feat: platform independent core and the new desktop app (#4684) 2025-02-28 00:01:25 +05:30
vite.config.d.ts feat: platform independent core and the new desktop app (#4684) 2025-02-28 00:01:25 +05:30
vite.config.ts feat: platform independent core and the new desktop app (#4684) 2025-02-28 00:01:25 +05:30

Hoppscotch Kernel

Cross-platform abstraction kernel for Hoppscotch, a unified interface between application logic and platform-specific implementations.

Architecture

The kernel acts as a thin abstraction layer, mediating between high-level application logic and low-level platform implementations, similar to how operating system kernels abstract over hardware details. This helps the core Hoppscotch app be platform-agnostic while maintaining near native performance.

This codebase is minimal by design, providing just the building blocks for constructing features. If possible, always try composition before modifying the kernel directly.

Modules

IO Module

File system and external resource handling:

interface IoV1 {
  saveFileWithDialog(opts: SaveFileWithDialogOptions): Promise<SaveFileResponse>
  openExternalLink(opts: OpenExternalLinkOptions): Promise<OpenExternalLinkResponse>
  listen<T>(event: string, handler: EventCallback<T>): Promise<UnlistenFn>
}

Relay Module

Network operations with platform-specific optimizations:

interface RelayV1 {
  readonly capabilities: RelayCapabilities
  execute(request: RelayRequest): {
    cancel: () => Promise<void>
    emitter: RelayEventEmitter<RelayRequestEvents>
    response: Promise<Either<RelayError, RelayResponse>>
  }
}

Store Module

Cross-platform persistence with encryption support:

interface StoreV1 {
  readonly capabilities: Set<StoreCapability>
  set(namespace: string, key: string, value: unknown, options?: StorageOptions): Promise<Either<StoreError, void>>
  watch(namespace: string, key: string): Promise<StoreEventEmitter<StoreEvents>>
}

Usage

Kernel Initialization

import { initKernel } from '@hoppscotch/kernel'

// Platform-specific initialization
const kernel = initKernel('web' | 'desktop')

Network Operations

import { RelayRequest } from '@hoppscotch/kernel'

const request: RelayRequest = {
  id: 1,
  url: "https://api.example.com",
  method: "GET",
  version: "HTTP/1.1",
  headers: { 
    "Content-Type": "application/json" 
  }
}

// Execute with capability checks
const { response, cancel } = kernel.relay.execute(request)

Storage Operations

// Encrypted storage with compression
await kernel.store.set("collections", "team-a", data, {
  encrypt: true,
  compress: true
})

// Watch for changes
const watcher = await kernel.store.watch("collections", "team-a")
watcher.on("change", 
  (update) => console.log("Collection updated:", update)
)

File Operations

// Platform-agnostic file save
await kernel.io.saveFileWithDialog({
  data: new Uint8Array([...]),
  suggestedFilename: "export.json",
  contentType: "application/json"
})