← All @molecule/* packages · App templates

@molecule/api-import-export

Core interface · import-export · API (Node) · v1.0.1 · Apache-2.0

Data import/export core interface for molecule.dev

npm install @molecule/api-import-export

npm · Source on GitHub

How it works

@molecule/api-import-export is the import-export core interface on the API (Node) side: the API your app calls, with no vendor inside.

Choose the implementation by bonding one of its 1 provider: @molecule/api-import-export-csv.

import { setProvider, importCSV, exportJSON, getJobStatus } from '@molecule/api-import-export'
import { provider } from '@molecule/api-import-export-csv'

// Wire the provider at startup
setProvider(provider)

// Import CSV data
const result = await importCSV('users', csvBuffer, {
  mapping: { 'Full Name': 'name', 'Email Address': 'email' },
  skipDuplicates: true,
})

// Export data as JSON
const rows = await exportJSON('users', {
  filters: [{ field: 'active', operator: 'eq', value: true }],
  columns: ['name', 'email'],
})

// Check import job status
const status = await getJobStatus(result.jobId)

Providers (1): @molecule/api-import-export-csv

Works with: @molecule/api-bond, @molecule/api-i18n

Reference

Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit src/index.ts JSDoc, not this file.

Data import/export core interface for molecule.dev.

Defines the abstract {@link ImportExportProvider} contract and convenience functions for importing CSV/JSON data, exporting to CSV/JSON/Excel, and tracking asynchronous import job status.

Quick Start

import { setProvider, importCSV, exportJSON, getJobStatus } from '@molecule/api-import-export'
import { provider } from '@molecule/api-import-export-csv'

// Wire the provider at startup
setProvider(provider)

// Import CSV data
const result = await importCSV('users', csvBuffer, {
  mapping: { 'Full Name': 'name', 'Email Address': 'email' },
  skipDuplicates: true,
})

// Export data as JSON
const rows = await exportJSON('users', {
  filters: [{ field: 'active', operator: 'eq', value: true }],
  columns: ['name', 'email'],
})

// Check import job status
const status = await getJobStatus(result.jobId)

Type

core

Installation

npm install @molecule/api-import-export @molecule/api-bond @molecule/api-i18n

API

Interfaces

ExportQuery

Query options for export operations.

interface ExportQuery {
  /** Filters to apply to the exported data. */
  filters?: Filter[]

  /** Columns to include in the export (defaults to all). */
  columns?: string[]

  /** Sort order for the exported rows. */
  orderBy?: OrderBy[]

  /** Maximum number of rows to export. */
  limit?: number
}

Filter

A single filter condition for export queries.

interface Filter {
  /** The field name to filter on. */
  field: string

  /** The comparison operator. */
  operator: FilterOperator

  /** The value to compare against. */
  value: unknown
}

ImportError

Describes an error that occurred while importing a specific row.

interface ImportError {
  /** The 1-based row number where the error occurred. */
  row: number

  /** The field name that caused the error, if applicable. */
  field?: string

  /** A human-readable description of the error. */
  message: string
}

ImportExportProvider

Import/export provider interface.

All import/export providers must implement this interface.

interface ImportExportProvider {
  /**
   * Imports CSV data into the specified table.
   *
   * @param table - Target table name.
   * @param data - CSV data as a Buffer or ReadableStream.
   * @param options - Import options (mapping, dedup, batching, validation).
   * @returns The import result with row counts and any errors.
   */
  importCSV(
    table: string,
    data: Buffer | ReadableStream,
    options?: ImportOptions,
  ): Promise<ImportResult>

  /**
   * Imports JSON data into the specified table.
   *
   * @param table - Target table name.
   * @param data - Array of objects to import.
   * @param options - Import options (mapping, dedup, batching, validation).
   * @returns The import result with row counts and any errors.
   */
  importJSON(table: string, data: unknown[], options?: ImportOptions): Promise<ImportResult>

  /**
   * Exports table data as CSV.
   *
   * @param table - Source table name.
   * @param query - Optional filters, column selection, ordering, and limit.
   * @returns A Buffer containing the CSV data.
   */
  exportCSV(table: string, query?: ExportQuery): Promise<Buffer>

  /**
   * Exports table data as JSON.
   *
   * @param table - Source table name.
   * @param query - Optional filters, column selection, ordering, and limit.
   * @returns An array of row objects.
   */
  exportJSON(table: string, query?: ExportQuery): Promise<unknown[]>

  /**
   * Exports table data as an Excel file.
   *
   * @param table - Source table name.
   * @param query - Optional filters, column selection, ordering, and limit.
   * @returns A Buffer containing the Excel file data.
   */
  exportExcel(table: string, query?: ExportQuery): Promise<Buffer>

  /**
   * Retrieves the status of an import job.
   *
   * @param jobId - The unique identifier of the import job.
   * @returns The current status of the job.
   */
  getJobStatus(jobId: string): Promise<ImportJobStatus>
}

ImportOptions

Options for import operations.

interface ImportOptions {
  /** Column name mapping from source to destination (`{ sourceCol: destCol }`). */
  mapping?: Record<string, string>

  /** Whether to skip rows that would cause duplicate key violations. */
  skipDuplicates?: boolean

  /** Number of rows to process per batch. */
  batchSize?: number

  /**
   * Optional row validation function. Return `true` to accept the row,
   * `false` to skip it.
   *
   * @param row - The parsed row data.
   * @returns Whether the row should be imported.
   */
  validateRow?: (row: Record<string, unknown>) => boolean

  /**
   * Progress callback invoked after each batch is processed.
   *
   * @param progress - Current import progress.
   */
  onProgress?: (progress: ImportProgress) => void
}

ImportProgress

Progress information for an in-flight import operation.

interface ImportProgress {
  /** Number of rows processed so far. */
  processed: number

  /** Total number of rows to process. */
  total: number

  /** Completion percentage (0-100). */
  percentage: number
}

ImportResult

Result of a completed import operation.

interface ImportResult {
  /** Unique identifier for the import job. */
  jobId: string

  /** Total number of rows in the source data. */
  totalRows: number

  /** Number of rows successfully imported. */
  importedRows: number

  /** Number of rows skipped (duplicates, validation failures, etc.). */
  skippedRows: number

  /** Errors encountered during import. */
  errors: ImportError[]
}

OrderBy

Sort direction for export queries.

interface OrderBy {
  /** The field name to sort by. */
  field: string

  /** The sort direction. */
  direction: 'asc' | 'desc'
}

Types

FilterOperator

Filter operators for export queries.

type FilterOperator =
  'eq' | 'neq' | 'gt' | 'gte' | 'lt' | 'lte' | 'in' | 'notIn' | 'between' | 'like'

ImportJobStatus

Status of an import job.

type ImportJobStatus = {
  /** Unique identifier for the import job. */
  jobId: string

  /** Current status of the job. */
  status: 'pending' | 'processing' | 'completed' | 'failed'

  /** Current progress, if the job is in progress. */
  progress?: ImportProgress

  /** Final result, if the job has completed. */
  result?: ImportResult

  /** Error message, if the job has failed. */
  error?: string
}

Functions

exportCSV(table, query)

Exports table data as CSV.

function exportCSV(table: string, query?: ExportQuery): Promise<Buffer<ArrayBufferLike>>
  • table — Source table name.
  • query — Optional filters, column selection, ordering, and limit.

Returns: A Buffer containing the CSV data.

exportExcel(table, query)

Exports table data as an Excel file.

function exportExcel(table: string, query?: ExportQuery): Promise<Buffer<ArrayBufferLike>>
  • table — Source table name.
  • query — Optional filters, column selection, ordering, and limit.

Returns: A Buffer containing the Excel file data.

exportJSON(table, query)

Exports table data as JSON.

function exportJSON(table: string, query?: ExportQuery): Promise<unknown[]>
  • table — Source table name.
  • query — Optional filters, column selection, ordering, and limit.

Returns: An array of row objects.

getJobStatus(jobId)

Retrieves the status of an import job.

function getJobStatus(jobId: string): Promise<ImportJobStatus>
  • jobId — The unique identifier of the import job.

Returns: The current status of the job.

getProvider()

Retrieves the bonded import/export provider, throwing if none is configured.

function getProvider(): ImportExportProvider

Returns: The bonded import/export provider.

hasProvider()

Checks whether an import/export provider is currently bonded.

function hasProvider(): boolean

Returns: true if an import/export provider is bonded.

importCSV(table, data, options)

Imports CSV data into the specified table.

function importCSV(
  table: string,
  data: Buffer<ArrayBufferLike> | ReadableStream<any>,
  options?: ImportOptions,
): Promise<ImportResult>
  • table — Target table name.
  • data — CSV data as a Buffer or ReadableStream.
  • options — Import options (mapping, dedup, batching, validation).

Returns: The import result with row counts and any errors.

importJSON(table, data, options)

Imports JSON data into the specified table.

function importJSON(table: string, data: unknown[], options?: ImportOptions): Promise<ImportResult>
  • table — Target table name.
  • data — Array of objects to import.
  • options — Import options (mapping, dedup, batching, validation).

Returns: The import result with row counts and any errors.

setProvider(provider)

Registers an import/export provider as the active singleton. Called by bond packages during application startup.

function setProvider(provider: ImportExportProvider): void
  • provider — The import/export provider implementation to bond.

Available Providers

ProviderPackage
Import Export@molecule/api-import-export-csv

Injection Notes

Requirements

Peer dependencies:

  • @molecule/api-bond ^1.0.1
  • @molecule/api-i18n ^1.0.1

Runtime Dependencies

  • @molecule/api-bond

  • @molecule/api-i18n

  • Wire the database first — and migrate the target table. Providers persist through the bonded @molecule/api-database DataStore: bond it before setProvider(...), and the table (with its columns) must already exist via your app's migrations. Imports do NOT create tables.

  • Never pass a client-supplied table (or raw filter fields) through. exportCSV(req.query.table) is a full-database exfiltration hole. Whitelist the table server-side per endpoint, and ALWAYS add server-side owner scoping to the query (e.g. a { field: 'user_id', operator: 'eq', value: authenticatedUserId } filter) so users can only export their own rows.

  • Exports return the file CONTENT (Buffer for CSV/Excel, rows for JSON) — the endpoint must set Content-Type / Content-Disposition itself for a download.

  • Import failures are per-row (result.errors, 1-based row numbers) with skippedRows counted separately — surface them; don't report success when importedRows < totalRows.

E2E Tests

Integration checklist — drive the real UI (live preview, no mocks), adapt each item to this app's actual screens/flows, and check every box off one by one. A box you can't check is an integration bug to fix — not a skip:

  • Exporting from the UI downloads a file whose rows and columns match the data on screen (spot-check at least one row's values).
  • Importing a valid file adds the records: they appear in the UI and survive a full reload.
  • If the app surfaces column mapping, a file whose headers differ from the field names imports into the RIGHT fields via the mapping.
  • A malformed file (wrong columns, broken rows) is rejected with a readable error — no silent partial import; per-row errors (if reported) are truthful.
  • Re-importing the same file honors the app's duplicate policy (e.g. skip-duplicates does not double the rows).
  • Round-trip integrity: export, then re-import the same file — values, encodings, and special characters come back unchanged.