{"_id":"@ecs-doculink/studio-sdk","_rev":"4-0c44f50dcde2d1edc62f6c251c82d6bf","name":"@ecs-doculink/studio-sdk","dist-tags":{"latest":"0.5.0"},"versions":{"0.2.0":{"name":"@ecs-doculink/studio-sdk","version":"0.2.0","keywords":["doculink","sdk","ocr","document-processing","customer-api"],"license":"MIT","_id":"@ecs-doculink/studio-sdk@0.2.0","maintainers":[{"name":"ecs.mobiledev","email":"ecs.mobiledev@gmail.com"}],"homepage":"https://gitlab.com/ecs7702831/doculink-studio/sdk/js#readme","bugs":{"url":"https://gitlab.com/ecs7702831/doculink-studio/sdk/js/-/issues"},"dist":{"shasum":"39836697fd32a046d5cfdf4a27d686ad1e994e6a","tarball":"https://registry.npmjs.org/@ecs-doculink/studio-sdk/-/studio-sdk-0.2.0.tgz","fileCount":9,"integrity":"sha512-bmlN6Go4hFfs/y4Z7fAhpmDxcybptpCYBjOQp88EJpOzwv8VuQel2nKhX/Hvanp3gzBh5bxI2DjND7mjKbDaNQ==","signatures":[{"sig":"MEUCIQDmx0IZATMVPZKwg3V3HnPHHT9c0ZttjUGox+QG3J+yugIgNBORJMgWhbqAa9f99mfJcB4XAoguW5jL+9zt3b74tgE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":192847},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"27d300366b8bdea46bb6fb687fe414cc3b896c75","scripts":{"test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"ecs.mobiledev","email":"ecs.mobiledev@gmail.com"},"repository":{"url":"git+https://gitlab.com/ecs7702831/doculink-studio/sdk/js.git","type":"git"},"_npmVersion":"10.8.1","description":"JavaScript/TypeScript SDK for the DocuLink Studio Customer API (REST + SSE + Socket.IO).","directories":{},"sideEffects":false,"_nodeVersion":"24.15.0","dependencies":{"socket.io-client":"^4.7.5"},"_hasShrinkwrap":false,"devDependencies":{"msw":"^2.3.1","tsup":"^8.1.0","vitest":"^1.6.0","typescript":"^5.5.3","@vitest/coverage-v8":"^1.6.1"},"_npmOperationalInternal":{"tmp":"tmp/studio-sdk_0.2.0_1784692237710_0.9500092355437426","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@ecs-doculink/studio-sdk","version":"0.3.0","keywords":["doculink","sdk","ocr","document-processing","customer-api"],"license":"MIT","_id":"@ecs-doculink/studio-sdk@0.3.0","maintainers":[{"name":"ecs.mobiledev","email":"ecs.mobiledev@gmail.com"}],"homepage":"https://gitlab.com/ecs7702831/doculink-studio/sdk/js#readme","bugs":{"url":"https://gitlab.com/ecs7702831/doculink-studio/sdk/js/-/issues"},"dist":{"shasum":"59fb174681afba1612d9b9f94cf8ff42cff82b35","tarball":"https://registry.npmjs.org/@ecs-doculink/studio-sdk/-/studio-sdk-0.3.0.tgz","fileCount":9,"integrity":"sha512-8HeTi7WElaDsh+Pp5G+kIR+5EftpjaiMBzTW+BTxPYOcFyOjuSFqkC7YO8+XVfcGiUItebmoPnAKIo5ir+K9bA==","signatures":[{"sig":"MEQCIEaGS0MG51Sy3/42Jo1ec4Y8kMQxkoFc4BtV25qNUuJ1AiBqAhicDnwKxErtacVnNB5GDGnwGZzXCgT4df4WY/k3Ag==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":193468},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"12a23718f3392fba286db27f8cf05517c5fe655a","scripts":{"test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"ecs.mobiledev","email":"ecs.mobiledev@gmail.com"},"repository":{"url":"git+https://gitlab.com/ecs7702831/doculink-studio/sdk/js.git","type":"git"},"_npmVersion":"10.8.1","description":"JavaScript/TypeScript SDK for the DocuLink Studio Customer API (REST + SSE + Socket.IO).","directories":{},"sideEffects":false,"_nodeVersion":"24.15.0","dependencies":{"socket.io-client":"^4.7.5"},"_hasShrinkwrap":false,"devDependencies":{"msw":"^2.3.1","tsup":"^8.1.0","vitest":"^1.6.0","typescript":"^5.5.3","@vitest/coverage-v8":"^1.6.1"},"_npmOperationalInternal":{"tmp":"tmp/studio-sdk_0.3.0_1784887049054_0.5246431789439177","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@ecs-doculink/studio-sdk","version":"0.4.0","keywords":["doculink","sdk","ocr","document-processing","customer-api"],"license":"MIT","_id":"@ecs-doculink/studio-sdk@0.4.0","maintainers":[{"name":"ecs.mobiledev","email":"ecs.mobiledev@gmail.com"}],"homepage":"https://gitlab.com/ecs7702831/doculink-studio/sdk/js#readme","bugs":{"url":"https://gitlab.com/ecs7702831/doculink-studio/sdk/js/-/issues"},"dist":{"shasum":"3aa5613a7221f3c1652bcd8b82759f54aa18ec84","tarball":"https://registry.npmjs.org/@ecs-doculink/studio-sdk/-/studio-sdk-0.4.0.tgz","fileCount":9,"integrity":"sha512-6yETsvPcHCk3m8VPGvAjofSWwVopXWj9GJ12ScAPtRFMzAZAq6d6NxSAv93Du20julhEMu7c5iIvK4IIR2Fzng==","signatures":[{"sig":"MEYCIQD6v55djtadW06Z82MUUxCAnuEYAmQJIvr5yntYtvg0EwIhAK9uUFQ3SbeFiZ+xaYazqCZSWyl1eDHlnlIHp60ohbCW","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":224110},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"71594b4e505104a9626f7889c2313af187460f0d","scripts":{"test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"ecs.mobiledev","email":"ecs.mobiledev@gmail.com"},"repository":{"url":"git+https://gitlab.com/ecs7702831/doculink-studio/sdk/js.git","type":"git"},"_npmVersion":"10.8.1","description":"JavaScript/TypeScript SDK for the DocuLink Studio Customer API (REST + SSE + Socket.IO).","directories":{},"sideEffects":false,"_nodeVersion":"24.15.0","dependencies":{"socket.io-client":"^4.7.5"},"_hasShrinkwrap":false,"devDependencies":{"msw":"^2.3.1","tsup":"^8.1.0","vitest":"^1.6.0","typescript":"^5.5.3","@vitest/coverage-v8":"^1.6.1"},"_npmOperationalInternal":{"tmp":"tmp/studio-sdk_0.4.0_1785979265608_0.35241228905337163","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@ecs-doculink/studio-sdk","version":"0.5.0","description":"JavaScript/TypeScript SDK for the DocuLink Studio Customer API (REST + SSE + Socket.IO).","license":"MIT","repository":{"type":"git","url":"git+https://gitlab.com/ecs7702831/doculink-studio/sdk/js.git"},"homepage":"https://gitlab.com/ecs7702831/doculink-studio/sdk/js#readme","bugs":{"url":"https://gitlab.com/ecs7702831/doculink-studio/sdk/js/-/issues"},"type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"sideEffects":false,"engines":{"node":">=18"},"scripts":{"build":"tsup","test":"vitest run","test:coverage":"vitest run --coverage","typecheck":"tsc --noEmit"},"dependencies":{"socket.io-client":"^4.7.5"},"devDependencies":{"@vitest/coverage-v8":"^1.6.1","msw":"^2.3.1","tsup":"^8.1.0","typescript":"^5.5.3","vitest":"^1.6.0"},"keywords":["doculink","sdk","ocr","document-processing","customer-api"],"_id":"@ecs-doculink/studio-sdk@0.5.0","gitHead":"71594b4e505104a9626f7889c2313af187460f0d","_nodeVersion":"24.15.0","_npmVersion":"10.8.1","dist":{"integrity":"sha512-7WZS+KsMhv7QEvVuRjAaHnlCTF5EaHnGWL0b/rKOVdkaMOKc4X8KRT5aKsnGn6Rb65/9n+aWaoHHm+3gFHTN/g==","shasum":"794c45ebf868e0b76c96d9b8003f34530db654a8","tarball":"https://registry.npmjs.org/@ecs-doculink/studio-sdk/-/studio-sdk-0.5.0.tgz","fileCount":9,"unpackedSize":330775,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQD/2iiVZqmEpwIi9DxVHzjjjwH8TUm9n+G4aPAaGl5vxAIgQNyWGuGo6aB48DmBJwW/CF6EigGFZth5TicxuxwGvfM="}]},"_npmUser":{"name":"ecs.mobiledev","email":"ecs.mobiledev@gmail.com"},"directories":{},"maintainers":[{"name":"ecs.mobiledev","email":"ecs.mobiledev@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/studio-sdk_0.5.0_1786250356798_0.9789483920830839"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-22T03:50:37.560Z","modified":"2026-08-09T04:39:17.096Z","0.2.0":"2026-07-22T03:50:37.866Z","0.3.0":"2026-07-24T09:57:29.200Z","0.4.0":"2026-08-06T01:21:05.757Z","0.5.0":"2026-08-09T04:39:16.946Z"},"bugs":{"url":"https://gitlab.com/ecs7702831/doculink-studio/sdk/js/-/issues"},"license":"MIT","homepage":"https://gitlab.com/ecs7702831/doculink-studio/sdk/js#readme","keywords":["doculink","sdk","ocr","document-processing","customer-api"],"repository":{"type":"git","url":"git+https://gitlab.com/ecs7702831/doculink-studio/sdk/js.git"},"description":"JavaScript/TypeScript SDK for the DocuLink Studio Customer API (REST + SSE + Socket.IO).","maintainers":[{"name":"ecs.mobiledev","email":"ecs.mobiledev@gmail.com"}],"readme":"# @ecs-doculink/studio-sdk\r\n\r\nJavaScript / TypeScript SDK for the **DocuLink Studio Customer API** — REST document\r\nprocessing, master data, and AI chat (SSE + Socket.IO). Works in Node 18+ (global\r\n`fetch`) and modern browsers. Ships ESM + CJS + `.d.ts`.\r\n\r\n> ### 🆕 What's new in 0.5.0\r\n>\r\n> **All-Process** — hand the whole pipeline to the server instead of driving it\r\n> yourself: pass `AutoProcess` to the upload, or call `allProcess` on an\r\n> uploaded scan (it also resumes one stuck at `\"3\"`/`\"5\"`). Then poll\r\n> `getScanStatus` until `Done`. **`scanDocument` now defaults to this path and\r\n> uses no Socket.IO at all**, so it works from serverless functions, batch jobs\r\n> and anything behind a firewall — pass `allProcess: false` for the 0.4.x\r\n> socket-driven behaviour.\r\n>\r\n> **Human-in-the-loop** — `editOutputRecord` / `deleteOutputRecord` change one\r\n> row instead of PUT-ing the whole document back; `getMappingCandidates` /\r\n> `getMappingMeta` / `pickMappingCandidate` let you inspect and change the\r\n> master-data row the engine matched; `exportScanOutput` and\r\n> `getScanSourceFile` download the result and the original file.\r\n> `listScans` finally lists scans **across every task**.\r\n>\r\n> ⚠️ `updateJsonOutput` saves a *full-output override* that `getJsonOutput`\r\n> returns in preference to the server's own output, so while one exists the\r\n> record editors answer **409** on purpose — call `clearOutputOverride` first.\r\n>\r\n> **Row-level master data** — read/add/update/delete individual rows plus\r\n> search, history and a validating import, instead of replacing the whole table.\r\n>\r\n> **Account self-service** — `getMe`, usage reports + export, invoices,\r\n> `rotateApiKey` and `getAuditLogs`. Rotating the key revokes every previously\r\n> issued token immediately; the SDK swaps in the new key and re-authenticates\r\n> for you, but the key is shown only once — persist it.\r\n\r\n> ⚠️ **Breaking change in v0.4.0 — document status constants.** `DocumentStatus`\r\n> now matches the server's full lifecycle: `\"1\"` Uploaded, `\"2\"`/`\"3\"` OCR\r\n> (processing/completed), `\"4\"`/`\"5\"` Schema, `\"6\"`/`\"7\"` Mapping, `\"9\"` Error —\r\n> **`DocumentStatus.Completed` changed value from `\"4\"` to `\"7\"`**, and\r\n> `OCR` / `Schema` / `Mapping` were replaced by `*Processing` / `*Completed`.\r\n> See [`../CHANGELOG.md`](../CHANGELOG.md).\r\n\r\n> ⚠️ **Also in v0.4.0:** the doc-scan `join` payload is now the object `{room}` the\r\n> server actually reads (bare-string joins were silently ignored — realtime never\r\n> worked through 0.2.0–0.3.1); `ReturnFormatType` takes `'1' | '2'` (the return\r\n> format's `Type`), not `'JSON'|'XML'|'CSV'`; new `scanDocument` pipeline helper +\r\n> `updateJsonOutput`.\r\n\r\n> ⚠️ **Breaking change in v0.3.0 — real-time subscription.** `subscribeDocumentScan(...)`\r\n> now takes the **TaskUUID** (the task id you use for upload), *not* the\r\n> DocumentScanUUID. The server broadcasts `doc-scan` events to room\r\n> `doc-scan-{TaskUUID}`; a `0.2.0` subscription that passed the scan UUID\r\n> received nothing. Each event's payload `UUID` is still the DocumentScanUUID.\r\n> See [`../CHANGELOG.md`](../CHANGELOG.md).\r\n\r\n> ℹ️ **v0.3.1** — `subscribeDocumentScan(...)` now sends the `auth: { token }`\r\n> Socket.IO handshake the document server requires. Authenticate (or pre-set an\r\n> access token) before subscribing; anonymous connects are rejected. The\r\n> standalone helper takes an optional trailing `accessToken` argument.\r\n\r\n## Install\r\n\r\n```bash\r\nnpm i @ecs-doculink/studio-sdk\r\n```\r\n\r\n## Quickstart\r\n\r\n```ts\r\nimport { DoculinkClient } from '@ecs-doculink/studio-sdk';\r\n\r\nconst client = new DoculinkClient({\r\n  providerApiKey: 'PROVIDER_API_KEY_35_CHARS_..........',\r\n  customerApiKey: 'CUSTOMER_API_KEY_35_CHARS_..........',\r\n  email: 'me@example.com', // optional\r\n  // baseURL / documentWsURL / chatWsURL default to the test environment.\r\n});\r\n\r\n// Authentication is automatic on the first authenticated call, but you can\r\n// force it (and inspect the tokens) up front:\r\nawait client.authenticate();\r\n\r\nconst usage = await client.getUsage();             // { planCode, quotaPages, ... }\r\n```\r\n\r\n## Authentication & auto-refresh\r\n\r\nThe client calls `POST /auth` with your API keys and stores the access + refresh\r\ntokens. Every authenticated request sends `Authorization: Bearer <AccessToken>`.\r\n\r\n- If there is no access token yet, the client authenticates first.\r\n- On HTTP `401`, it refreshes the token (`POST /refresh/token`) and retries once.\r\n  If refreshing fails, it re-authenticates with the API keys and retries once.\r\n\r\nYou may also pre-seed tokens to skip the initial login:\r\n\r\n```ts\r\nconst client = new DoculinkClient({\r\n  providerApiKey, customerApiKey,\r\n  accessToken: savedAccess,\r\n  refreshToken: savedRefresh,\r\n});\r\n```\r\n\r\n## Uploading a document\r\n\r\n```ts\r\nimport { readFile } from 'node:fs/promises';\r\n\r\nconst bytes = new Uint8Array(await readFile('./invoice.pdf'));\r\n\r\nconst result = await client.uploadFile('TASK_UUID', {\r\n  File: { data: bytes, filename: 'invoice.pdf' }, // or a browser File/Blob\r\n  SchemaUUID: 'SCHEMA_UUID',\r\n  ReturnFormatUUID: 'RETURN_FORMAT_UUID',\r\n  ReturnFormatType: '1', // '1' public / '2' customer — ค่า Type ของ return format ที่เลือก (ไม่ใช่ชื่อ file format)\r\n  ClientUUID: 'CLIENT_UUID', // optional\r\n});\r\n\r\n// Drive the pipeline (each returns a status string):\r\nawait client.ocrProcess('TASK_UUID', result.DocumentScanUUID);\r\nawait client.schemaProcess('TASK_UUID', result.DocumentScanUUID);\r\nawait client.mappingProcess('TASK_UUID', result.DocumentScanUUID);\r\n\r\nconst { JsonOutput } = await client.getJsonOutput('TASK_UUID', result.DocumentScanUUID);\r\n```\r\n\r\n## Real-time: document processing (Socket.IO)\r\n\r\n```ts\r\n// Subscribe with the TaskUUID (the `:taskid` used for upload). The task room\r\n// streams `doc-scan` events for every scan in the task; use `u.UUID`\r\n// (DocumentScanUUID) to tell them apart.\r\nconst sub = client.subscribeDocumentScan('TASK_UUID', {\r\n  onUpdate: (u) => console.log(u.UUID, u.Status, u.CurrentLog, u.Error),\r\n  onError: (e) => console.error(e),\r\n});\r\n// later\r\nsub.close();\r\n```\r\n\r\n`Status` values (even = stage running, odd = stage done — wait for the odd\r\nstatus of each stage before calling the next endpoint): `\"1\"` Uploaded,\r\n`\"2\"`/`\"3\"` OCR (processing/completed), `\"4\"`/`\"5\"` Schema, `\"6\"`/`\"7\"` Mapping\r\n(`\"7\"` = Completed), `\"9\"` Error (exported as `DocumentStatus`).\r\n\r\n## Real-time: chat\r\n\r\n**SSE (recommended)** — streams the assistant reply and resolves with the full message:\r\n\r\n```ts\r\nconst { session_uuid } = await client.createChatSession(); // optional model arg\r\nconst message = await client.sendChatMessageStream(session_uuid, 'Hello!', (evt) => {\r\n  if (evt.event === 'stream_chunk') process.stdout.write(evt.chunk);\r\n});\r\nconsole.log('\\nFinal:', message.Content);\r\n```\r\n\r\n**Sync** — returns the full assistant message in one call:\r\n\r\n```ts\r\nconst message = await client.sendChatMessageSync(session_uuid, 'Hello!');\r\n```\r\n\r\n**Socket.IO** — subscribe, then send asynchronously (HTTP 202) and receive events:\r\n\r\n```ts\r\nconst chatSub = client.subscribeChatSession(session_uuid, {\r\n  onChunk: (e) => process.stdout.write(e.chunk),\r\n  onEnd: (e) => console.log('\\nDone:', e.message.Content),\r\n  onError: (e) => console.error(e.error),\r\n});\r\nawait client.sendChatMessage(session_uuid, 'Hello!'); // 202, watch the socket\r\n// later: chatSub.close();\r\n```\r\n\r\n> Both subscriptions join with an object payload `{ room }` — the shape the\r\n> server's join handler actually reads (a bare string is silently ignored).\r\n\r\n## Errors\r\n\r\nEvery failed call throws an `ApiError`:\r\n\r\n```ts\r\nimport { ApiError } from '@ecs-doculink/studio-sdk';\r\n\r\ntry {\r\n  await client.getUsage();\r\n} catch (e) {\r\n  if (e instanceof ApiError) {\r\n    console.error(e.statusCode, e.status, e.message);\r\n  }\r\n}\r\n```\r\n\r\nAn `ApiError` is thrown when HTTP status is `>= 400` **or** when the response\r\nenvelope carries `status: false` (including billing rejections that return HTTP 200).\r\n\r\n## API surface\r\n\r\nAll 59 endpoints from the contract are implemented as camelCase async methods:\r\nauth (`authenticate`, `refreshAccessToken`), account (`getUsage`),\r\ncompany/client/schema/provider lookups, document processing\r\n(`uploadFile`, `ocrProcess`, `schemaProcess`, `mappingProcess`, `getJsonOutput`,\r\n`getListDocumentScans`, `getDocumentScanById`, `deleteDocumentScan`), master data\r\n(`getMyMasterDatas`, `updateMasterData`), and chat\r\n(`createChatSession`, `sendChatMessage`, `sendChatMessageStream`,\r\n`sendChatMessageSync`, `listChatSessions`, `getChatSession`, `getChatHistory`,\r\n`deleteChatSession`, `getAvailableModels`, `getChatGuides`).\r\n\r\n## Scripts\r\n\r\n```bash\r\nnpm run build      # tsup → dist (ESM + CJS + .d.ts)\r\nnpm test           # vitest run\r\nnpm run typecheck  # tsc --noEmit\r\n```\r\n\r\n## Reference\r\n\r\nFull REST reference: [`../docs/index.html`](../docs/index.html).\r\nContract (single source of truth for all four SDKs): `../CONTRACT.md`.\r\n\r\n## License\r\n\r\nMIT\r\n","readmeFilename":"README.md"}