@molecule/api-import-export
v1.0.1
Published
Data import/export core interface for molecule.dev
Maintainers
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.tsJSDoc, 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-i18nAPI
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(): ImportExportProviderReturns: The bonded import/export provider.
hasProvider()
Checks whether an import/export provider is currently bonded.
function hasProvider(): booleanReturns: 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): voidprovider— 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-i18nWire the database first — and migrate the target table. Providers persist through the bonded
@molecule/api-databaseDataStore: bond it beforesetProvider(...), and thetable(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 (
Bufferfor CSV/Excel, rows for JSON) — the endpoint must setContent-Type/Content-Dispositionitself for a download.Import failures are per-row (
result.errors, 1-based row numbers) withskippedRowscounted separately — surface them; don't report success whenimportedRows < 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.
