npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@molecule/api-import-export

v1.0.1

Published

Data import/export core interface for molecule.dev

Readme

@molecule/api-import-export

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

| Provider | Package | | ------------- | --------------------------------- | | 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.