{"_id":"@bernierllc/csv-import-suite-client","_rev":"2-bca5f7856dbd6d208b8675f786db4835","name":"@bernierllc/csv-import-suite-client","dist-tags":{"latest":"0.2.1"},"versions":{"0.0.1":{"name":"@bernierllc/csv-import-suite-client","version":"0.0.1","keywords":["oidc","trusted-publishing","setup"],"_id":"@bernierllc/csv-import-suite-client@0.0.1","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"dist":{"shasum":"b0e43dfdaeafc62b6aeb3f9e6b15f2db6614018d","tarball":"https://registry.npmjs.org/@bernierllc/csv-import-suite-client/-/csv-import-suite-client-0.0.1.tgz","fileCount":2,"integrity":"sha512-poDK9OYIP/lr9l3fGtSSgz6uidnFgnmEUicMoHNVyKg08PY5BS2eUuNh/8Hgp+Bhb9pfPNX+zFStClrgR/TOVg==","signatures":[{"sig":"MEUCIQCTYwHdN5Kzm5stmrDpPWNI6F7xBC14TXApzN2FL+Hv1gIgBJQs64YlJTaLLQk57Y5sB9GEGWcXezqAB2DrjH5xzb8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2103},"_npmUser":{"name":"mkbernier","email":"mkbernier@gmail.com"},"_npmVersion":"11.12.1","description":"OIDC trusted publishing setup package for @bernierllc/csv-import-suite-client","directories":{},"_nodeVersion":"25.9.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/csv-import-suite-client_0.0.1_1781125297038_0.11904682626908536","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"_id":"@bernierllc/csv-import-suite-client@0.2.1","bugs":{"url":"https://github.com/bernierllc/tools/issues"},"dist":{"shasum":"ebb28c432bf9e28f9d061bd89b77cc03ef92960c","tarball":"https://registry.npmjs.org/@bernierllc/csv-import-suite-client/-/csv-import-suite-client-0.2.1.tgz","fileCount":23,"integrity":"sha512-DUTSlWGU75o+4ZaHOyWAdm+1/WKC+UvQ3lAidn2aDNJLR7bhq7fzilLd5+W/ZOp5MTGzhEOhjMJMG36TIHi8rA==","signatures":[{"sig":"MEYCIQDVaMwBSXioJbySCme0OQfzW8bJ17B7+OLrQf4Y3/J2CwIhAOwc55ilSDIRAV39M9TvB5G938fQI8L9EZrD/1Y4F1bD","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCNIYyVapWzVxJ/HG/nPf8DGxuX7Oqna5QPaXWWwy8S5wIhAIgO/xu1Q6W8ZWQQEIEo0pZel0eLYkTx9L7gLTLduh+M"}],"unpackedSize":100505},"main":"dist/index.js","name":"@bernierllc/csv-import-suite-client","_from":"file:bernierllc-csv-import-suite-client-0.2.1.tgz","types":"dist/index.d.ts","author":{"name":"Bernier LLC"},"browser":"dist/index.js","engines":{"node":">=18.0.0"},"license":"Bernier LLC","scripts":{"lint":"eslint src/**/*.ts","test":"jest","build":"tsc","clean":"rm -rf dist","prebuild":"npm run clean","test:watch":"jest --watch","test:coverage":"jest --coverage"},"version":"0.2.1","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"161b0ad9-5db7-420b-8d81-56e59eb07f6e"}},"homepage":"https://github.com/bernierllc/tools#readme","keywords":["csv","import","client","http","browser","bernierllc"],"_resolved":"/home/runner/work/tools/tools/packages/suite/csv-import-suite-client/bernierllc-csv-import-suite-client-0.2.1.tgz","_integrity":"sha512-DUTSlWGU75o+4ZaHOyWAdm+1/WKC+UvQ3lAidn2aDNJLR7bhq7fzilLd5+W/ZOp5MTGzhEOhjMJMG36TIHi8rA==","repository":{"url":"git+https://github.com/bernierllc/tools.git","type":"git","directory":"packages/suite/csv-import-suite-client"},"_npmVersion":"12.2.0","description":"Browser-safe HTTP client mirroring the csv-import-suite server API for driving CSV imports from a frontend","directories":{},"maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"_nodeVersion":"24.21.0","dependencies":{"zod":"^3.22.4"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.0.0","rimraf":"^5.0.0","ts-jest":"^29.1.2","typescript":"^5.3.3","@types/jest":"^29.5.12","@types/node":"^20.11.19"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/csv-import-suite-client_0.2.1_1790902455468_0.6933597589825025"}}},"time":{"created":"2026-06-10T21:01:36.832Z","modified":"2026-10-02T00:54:15.705Z","0.0.1":"2026-06-10T21:01:37.229Z","0.2.1":"2026-10-02T00:54:15.554Z"},"keywords":["csv","import","client","http","browser","bernierllc"],"description":"Browser-safe HTTP client mirroring the csv-import-suite server API for driving CSV imports from a frontend","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"readme":"# @bernierllc/csv-import-suite-client\n\nBrowser-safe isomorphic HTTP client for the\n[`@bernierllc/csv-import-suite`](../csv-import-suite/README.md) server API.\n\nDrives the full six-step CSV import pipeline from any browser, Node.js ≥ 18\nruntime, or integration test — without importing any Node.js-only code.\n\n**Pairs with:**\n- `@bernierllc/csv-import-suite` — the Node-only server backend that this client calls over HTTP\n- `@bernierllc/csv-ui` — React components and headless hooks that connect to these client methods\n\n---\n\n## Installation\n\n```bash\nnpm install @bernierllc/csv-import-suite-client\n```\n\n**Runtime requirements:** Node.js ≥ 18 (for native `fetch`) or any modern browser.\n\n---\n\n## Quick Start\n\n```typescript\nimport { CsvImportClient } from '@bernierllc/csv-import-suite-client';\n\nconst client = new CsvImportClient({\n  baseUrl: 'https://api.example.com',\n  apiKey: 'optional-bearer-token',\n  timeout: 30000,\n});\n```\n\n---\n\n## Constructor\n\n```typescript\nnew CsvImportClient(config: CsvImportClientConfig)\n```\n\n| Property  | Type                     | Default     | Description                                                     |\n|-----------|--------------------------|-------------|-----------------------------------------------------------------|\n| `baseUrl` | `string` (required)      | —           | Server API base URL. Trailing slashes are stripped.             |\n| `apiKey`  | `string` (optional)      | `undefined` | When set, sent as `Authorization: Bearer <apiKey>`.             |\n| `timeout` | `number` (optional)      | `30000`     | Request timeout in ms. Pass `0` to disable.                     |\n| `headers` | `Record<string, string>` | `{}`        | Additional headers merged onto every request.                   |\n\nThrows a `CsvImportClientError` (code `BAD_REQUEST`) synchronously if `baseUrl` is empty.\n\n---\n\n## All 7 Methods\n\n### Step 1 — createSession\n\n```typescript\nPOST /csv-imports\n\nconst session = await client.createSession({\n  csv: 'name,email\\nAlice,alice@example.com',\n  targetFields: ['name', 'email'],\n  autoMapThreshold: 0.8,        // optional\n});\n// session.sessionId, session.headers, session.suggestions\n```\n\n**Response** — `{ sessionId: string; headers: string[]; suggestions: MappingSuggestion[] }`\n\n`suggestions` are auto-mapping hints with `csvColumn`, `targetField`, `confidence`, and `reasoning`.\n\n---\n\n### Step 2 — setMapping\n\n```typescript\nPUT /csv-imports/{sessionId}/mapping\n\nconst result = await client.setMapping(session.sessionId, {\n  mapping: {\n    name: 'name',\n    email: 'emailAddress',\n  },\n});\n// result.ok === true\n```\n\n**Response** — `{ ok: true }`\n\n---\n\n### Step 3 — validate\n\n```typescript\nPOST /csv-imports/{sessionId}/validate\n\nconst validation = await client.validate(session.sessionId);\nif (!validation.valid) {\n  console.log('Errors:', validation.errors);\n  console.log('Warnings:', validation.warnings);\n}\n```\n\n**Response** — `{ valid: boolean; errors: ValidationIssue[]; warnings: ValidationIssue[] }`\n\n`ValidationIssue` — `{ row: number; field: string; message: string }`\n\n---\n\n### Step 4 — resolve\n\n```typescript\nPOST /csv-imports/{sessionId}/resolve\n\nconst resolved = await client.resolve(session.sessionId, {\n  autoAcceptAt: 0.9,   // optional: auto-accept matches above this score\n  reviewAt: 0.5,       // optional: flag matches in this score range for review\n});\n\nfor (const r of resolved.resolutions) {\n  console.log(r.rowIndex, r.tier);  // 'auto' | 'review' | 'none'\n}\n```\n\n**Response** — `{ resolutions: RowResolution[] }`\n\n`RowResolution` — `{ rowIndex, tier, best?, alternatives, conflicts }`\n\n---\n\n### Step 5 — buildPlan\n\n```typescript\nPOST /csv-imports/{sessionId}/plan\n\nconst plan = await client.buildPlan(session.sessionId, {\n  decisions: [\n    { rowIndex: 0, action: 'create', fieldDecisions: {} },\n    {\n      rowIndex: 1,\n      action: 'merge',\n      fieldDecisions: {\n        name: 'use-incoming',      // 'keep-existing' | 'use-incoming' | 'skip-field'\n        email: 'keep-existing',\n      },\n    },\n    { rowIndex: 2, action: 'skip', fieldDecisions: {} },\n  ],\n});\n// plan.creates, plan.merges, plan.skips\n```\n\n**Response** — `{ creates: number; merges: number; skips: number }`\n\n---\n\n### Step 6 — commit\n\n```typescript\nPOST /csv-imports/{sessionId}/commit\n\nconst result = await client.commit(session.sessionId);\nconst { applied, skipped, failed, total } = result.report;\n```\n\n**Response** — `{ report: { applied: number; skipped: number; failed: number; total: number } }`\n\nIdempotent: calling `commit` twice for the same session returns the existing report.\n\n---\n\n### Step 7 — progress\n\n```typescript\nGET /csv-imports/{sessionId}/progress\n\nconst poll = setInterval(async () => {\n  const p = await client.progress(session.sessionId);\n  console.log(`${(p.fraction * 100).toFixed(0)}% — ${p.applied}/${p.total}`);\n  if (p.fraction >= 1) clearInterval(poll);\n}, 500);\n```\n\n**Response** — `{ applied: number; skipped: number; failed: number; total: number; fraction: number }`\n\n---\n\n## Full Pipeline Example\n\n```typescript\nimport { CsvImportClient } from '@bernierllc/csv-import-suite-client';\n\nconst client = new CsvImportClient({ baseUrl: 'https://api.example.com' });\n\n// 1. Create session\nconst session = await client.createSession({\n  csv: 'name,email\\nAlice,alice@example.com\\nBob,bob@example.com',\n  targetFields: ['name', 'emailAddress'],\n});\nconsole.log('Suggested mapping:', session.suggestions);\n\n// 2. Submit mapping\nawait client.setMapping(session.sessionId, {\n  mapping: { name: 'name', email: 'emailAddress' },\n});\n\n// 3. Validate\nconst validation = await client.validate(session.sessionId);\nif (!validation.valid) throw new Error('Validation failed');\n\n// 4. Resolve entities\nconst resolved = await client.resolve(session.sessionId, { autoAcceptAt: 0.85 });\nconst decisions = resolved.resolutions.map(r => ({\n  rowIndex: r.rowIndex,\n  action: r.tier === 'none' ? 'create' : 'merge' as const,\n  fieldDecisions: {},\n}));\n\n// 5. Build plan\nconst plan = await client.buildPlan(session.sessionId, { decisions });\nconsole.log(`Plan: ${plan.creates} creates, ${plan.merges} merges, ${plan.skips} skips`);\n\n// 6. Commit\nconst result = await client.commit(session.sessionId);\nconsole.log(`Done: ${result.report.applied}/${result.report.total} applied`);\n```\n\n---\n\n## Error Handling\n\nAll errors extend `CsvImportClientError`.\n\n| Class                  | Code            | Status | Retryable | Description                                    |\n|------------------------|-----------------|--------|-----------|------------------------------------------------|\n| `CsvImportClientError` | `API_ERROR`     | 4xx    | false     | Base class; unexpected 4xx                     |\n| `CsvImportClientError` | `PARSE_ERROR`   | 2xx    | false     | Response failed zod schema validation          |\n| `BadRequestError`      | `BAD_REQUEST`   | 400    | false     | Invalid request parameters                     |\n| `UnauthorizedError`    | `UNAUTHORIZED`  | 401    | false     | Missing or invalid API key                     |\n| `ForbiddenError`       | `FORBIDDEN`     | 403    | false     | Insufficient permissions                       |\n| `NotFoundError`        | `NOT_FOUND`     | 404    | false     | Session not found                              |\n| `RateLimitError`       | `RATE_LIMITED`  | 429    | true      | Too many requests; check `err.retryAfter`      |\n| `ServerError`          | `SERVER_ERROR`  | 5xx    | true      | Server-side error                              |\n| `NetworkError`         | `NETWORK_ERROR` | —      | true      | Network failure before server responded        |\n| `TimeoutError`         | `TIMEOUT_ERROR` | —      | true      | Request exceeded `timeout` ms                  |\n\n```typescript\nimport {\n  CsvImportClientError,\n  RateLimitError,\n  NetworkError,\n} from '@bernierllc/csv-import-suite-client';\n\ntry {\n  await client.createSession({ csv: '...', targetFields: ['name'] });\n} catch (err) {\n  if (err instanceof RateLimitError) {\n    const waitSecs = err.retryAfter ?? 60;\n    console.log(`Rate limited. Retry in ${waitSecs}s`);\n  } else if (err instanceof NetworkError) {\n    console.log('Network failure — retryable:', err.retryable);\n  } else if (err instanceof CsvImportClientError) {\n    console.log('code:', err.code, 'statusCode:', err.statusCode);\n    // ES2022 cause chain\n    if (err.cause) console.log('caused by:', err.cause);\n  }\n}\n```\n\n---\n\n## TypeScript\n\nAll types are exported. Zod schemas are also exported for consumers that need\nthem directly (e.g. to validate webhook payloads on the server side).\n\n```typescript\nimport type {\n  CreateSessionRequest,\n  CreateSessionResponse,\n  SetMappingRequest,\n  ValidateResponse,\n  ResolveRequest,\n  ResolveResponse,\n  BuildPlanRequest,\n  BuildPlanResponse,\n  CommitResponse,\n  ProgressResponse,\n  RowResolution,\n  FieldDecision,\n} from '@bernierllc/csv-import-suite-client';\n```\n\n---\n\n## Backend Setup\n\nYou need a backend server that exposes the `csv-import-suite` API. Set `baseUrl`\nto the root of your backend's CSV import routes:\n\n```\nPOST   /csv-imports                             → createSession\nPUT    /csv-imports/:sessionId/mapping          → setMapping\nPOST   /csv-imports/:sessionId/validate         → validate\nPOST   /csv-imports/:sessionId/resolve          → resolve\nPOST   /csv-imports/:sessionId/plan             → buildPlan\nPOST   /csv-imports/:sessionId/commit           → commit\nGET    /csv-imports/:sessionId/progress         → progress\n```\n\nError envelope (non-2xx responses):\n```json\n{ \"error\": { \"code\": \"ERR_CODE\", \"message\": \"Human-readable message\", \"context\": {} } }\n```\n","readmeFilename":"README.md","homepage":"https://github.com/bernierllc/tools#readme","repository":{"url":"git+https://github.com/bernierllc/tools.git","type":"git","directory":"packages/suite/csv-import-suite-client"},"author":{"name":"Bernier LLC"},"bugs":{"url":"https://github.com/bernierllc/tools/issues"},"license":"Bernier LLC"}