@arc-lang/arc-import-export
v0.1.0
Published
One-line import/export for every arc-cms admin table — CSV, JSON, XLSX with preview, history, and upsert. Zero per-page code.
Maintainers
Readme
arc-import-export
One-line import/export for every arc-cms admin table.
Drop one <script> tag into your CmsLayout and every admin page with a table instantly gets CSV, JSON, and XLSX import/export — with a 3-step preview wizard, upsert support, and a full audit history. Zero per-page code required.
Inspired by django-import-export.
Features
- Auto-activates on every
<table>in the admin — no widget imports, no per-page code - ↓ Export to CSV, JSON, or XLSX in one click
- ↑ Import with a 3-step wizard: Upload → Preview (dry-run with error highlighting) → Confirm
- Upsert support — update existing records by a unique field, create new ones
- Batched commits — 500-row batches keep memory flat on large datasets
- Full history at
/admin/import-export— every import and export logged with row counts and errors - Lazy XLSX — SheetJS only loads when an XLSX request is actually made; CSV/JSON have zero runtime deps
- Dark mode native — uses your site's
--ui-*CSS variables automatically - Override-friendly — works on customized/overridden admin pages too
Install
bun add @arc-language/arc-import-exportSetup (3 steps)
1. Register the package in your Arc project
In arc.config.json, add the server routes and schema:
{
"serverRoutes": [
"node_modules/@arc-language/arc-import-export/src/server/import-export.arc"
],
"schemas": [
"node_modules/@arc-language/arc-import-export/src/server/schemas/import-log.arc"
]
}2. Add the script tag to CmsLayout
In site/cms/CmsLayout.arc, add one line after your existing scripts:
@raw '<script src="/arc-ie/bar.js" defer></script>'If you installed arc-cms via
arc cms init, this line is already there.
3. Create a config file
In your project root, create arc-import-export.config.js:
export default {
resources: {
users: { fields: ['name', 'email', 'role'], uniqueBy: 'email' },
pages: { fields: ['title', 'slug', 'published'], uniqueBy: 'slug' },
groups: { fields: ['name', 'slug', 'description'], uniqueBy: 'slug' },
}
}That's it. Open /admin/users — the Import/Export toolbar appears above the table.
How it works
/admin/users
┌─────────────────────────────────────────────────────┐
│ users ↓ Export ↑ Import History ↗ │ ← auto-injected toolbar
└─────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────┐
│ Name Email Role Joined │
│ ... ... ... ... │ ← your existing table
└──────────────────────────────────────────────────────┘Import wizard
Step 1 Upload → Step 2 Preview → Step 3 Confirm
──────────────── ───────────────────────── ────────────────
Drop file here ✓ 138 valid · ✗ 4 errors Import 138 records
CSV / JSON / XLSX [table of first 20 rows] Cancel
[error rows highlighted red]Resource auto-detection
The toolbar infers the resource from the URL path:
| URL | Resource |
|-----|---------|
| /admin/users | users |
| /admin/my-orders | my-orders |
| /admin/products | products |
To override (e.g. on a page with a custom URL), add a data-ie-resource attribute anywhere on the page:
@raw '<div data-ie-resource="products" data-ie-fields="name,sku,price"></div>'Or use the optional widget:
import ImportExportBar from "@arc-language/arc-import-export/src/widgets/ImportExportBar.arc"
ImportExportBar resource="products" fields="name,sku,price" uniqueBy="sku"Config reference
// arc-import-export.config.js
export default {
resources: {
[resourceName]: {
fields: string[], // fields allowed in import (required for import to be enabled)
uniqueBy: string, // optional: upsert key — update if exists, create if not
}
}
}| Option | Type | Required | Description |
|--------|------|----------|-------------|
| fields | string[] | Yes (for import) | Column names that can be imported. Export uses all columns by default. |
| uniqueBy | string | No | Field used for upsert on import. If omitted, always creates new records. |
If a resource is not in the config, Export still works (shows all columns) but the Import button is hidden.
API routes
All routes are mounted automatically when you add the server route to arc.config.json.
| Method | Path | Auth | Description |
|--------|------|------|-------------|
| GET | /arc-ie/bar.js | Public | The auto-detect script (~3 KB gzip) |
| GET | /admin/api/ie/config | editor+ | Field config for a resource |
| POST | /admin/api/ie/preview | editor+ | Parse file, return preview (no DB write) |
| POST | /admin/api/ie/commit | editor+ | Commit import to database |
| GET | /admin/api/ie/export | editor+ | Stream export file download |
| GET | /admin/api/ie/logs | editor+ | List import/export history |
| GET | /admin/api/ie/logs/:id | editor+ | Single log detail with errors |
Supported formats
| Format | Import | Export | Notes |
|--------|--------|--------|-------|
| CSV | ✓ | ✓ | RFC 4180, handles quoted fields and escaped commas |
| JSON | ✓ | ✓ | Array of objects; rows/data wrapper accepted on import |
| XLSX | ✓ | ✓ | SheetJS (lazy-loaded — zero cost if unused) |
History page
Every import and export is logged at /admin/import-export:
- Filter by action (import / export), status (success / partial / failed), or resource name
- Click any row to see full details including per-row error messages
- Counts: total rows, imported, skipped, errors
Performance
| Operation | Complexity | Notes | |-----------|------------|-------| | Preview parse | O(n) time, O(20) space | Only first 20 rows buffered for preview | | Import commit | O(n) time, O(500) space | 500-row batch loop | | Export (CSV/JSON) | O(n) time, O(1) space | Streaming response | | Export (XLSX) | O(n) time, O(n) space | SheetJS buffer — unavoidable | | Config fetch | O(1) | Cached 60 s per browser tab |
Contributing
Contributions welcome. See CONTRIBUTING.md for guidelines.
# Clone
git clone https://github.com/arc-language/arc-import-export.git
cd arc-import-export
# Install
bun install
# Run against an arc-cms project (set ARC_PROJECT_DIR)
ARC_PROJECT_DIR=../my-arc-project bun run devLicense
MIT © KCuppens
