{"_id":"@cartat/connect-js","_rev":"4-9e6d6824c9d9f4b8246707ba82ff8c6d","name":"@cartat/connect-js","dist-tags":{"latest":"0.2.2"},"versions":{"0.1.0":{"name":"@cartat/connect-js","version":"0.1.0","keywords":["cartat","connect","oauth","partner","onboarding","sdk"],"license":"SEE LICENSE IN LICENSE","_id":"@cartat/connect-js@0.1.0","maintainers":[{"name":"cartat","email":"mahmoud@firstcube.co"}],"dist":{"shasum":"b9dd444c88130fa21a4a20ccee7af5e88298b773","tarball":"https://registry.npmjs.org/@cartat/connect-js/-/connect-js-0.1.0.tgz","fileCount":5,"integrity":"sha512-C/86xSd54QIna3wx3nSqerwpPI1uqB03Lx46pvKbUUlcJnkYKKDMjjIxAYqVE9Pd5WC5FqOQGNGIcfNjgkQqOA==","signatures":[{"sig":"MEYCIQDL8wXhRF/HPu9SisOZcB+jhdJn+6QsFokVr6zaTVR20AIhAPOK5CxvZc7CJzqoHhXDQGqBma53IOzBixK0dh8haZC/","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":42232},"main":"./src/index.js","type":"module","types":"./src/index.d.ts","module":"./src/index.js","exports":{".":{"types":"./src/index.d.ts","import":"./src/index.js"}},"gitHead":"db9333255a22aa580ed9eb4ab5a93001b82fe61b","_npmUser":{"name":"cartat","email":"mahmoud@firstcube.co"},"_npmVersion":"11.3.0","description":"Cartat Connect browser SDK for partner onboarding and popup lifecycle handling.","directories":{},"sideEffects":false,"_nodeVersion":"24.1.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/connect-js_0.1.0_1782418223061_0.3322247137263725","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@cartat/connect-js","version":"0.2.0","keywords":["cartat","connect","oauth","partner","onboarding","sdk"],"license":"SEE LICENSE IN LICENSE","_id":"@cartat/connect-js@0.2.0","maintainers":[{"name":"cartat","email":"mahmoud@firstcube.co"}],"dist":{"shasum":"0e13a8fb3251b1c1c3b5eace53dd30f9df4e6161","tarball":"https://registry.npmjs.org/@cartat/connect-js/-/connect-js-0.2.0.tgz","fileCount":5,"integrity":"sha512-B19WqUg/hAIEcjcFDKdtmXDKEZvs7IgUzJjpQRhZF1GivDG0quqkws0MYofmrcUPnlhbXFWhl71N2BB6ul38tg==","signatures":[{"sig":"MEUCIDgElFG3GxVm6mHvMBwnAwD2wF2HTHTjsTdN31st5NziAiEAjxTX4OeX7/kjSmofRUrYTzlY5ri5qHJg3fQb5o+iqSY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":43518},"main":"./src/index.js","type":"module","types":"./src/index.d.ts","module":"./src/index.js","exports":{".":{"types":"./src/index.d.ts","import":"./src/index.js"}},"gitHead":"79e583b9190e9ad1908aeffe5b1b7c13d4571092","_npmUser":{"name":"cartat","email":"mahmoud@firstcube.co"},"_npmVersion":"11.3.0","description":"Cartat Connect browser SDK for partner onboarding and popup lifecycle handling.","directories":{},"sideEffects":false,"_nodeVersion":"24.1.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/connect-js_0.2.0_1783960158611_0.620902106949307","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@cartat/connect-js","version":"0.2.1","keywords":["cartat","connect","oauth","partner","onboarding","sdk"],"license":"SEE LICENSE IN LICENSE","_id":"@cartat/connect-js@0.2.1","maintainers":[{"name":"cartat","email":"mahmoud@firstcube.co"}],"dist":{"shasum":"47ed9dd0164491eee16eeb82d3b37a1b90b7fdbe","tarball":"https://registry.npmjs.org/@cartat/connect-js/-/connect-js-0.2.1.tgz","fileCount":5,"integrity":"sha512-Z9pFuk2zajfd4fsehOvow7cPRnyP1fQPNLcUjgz08uMh0hGi0HcR2kIL0+iECvIqu1iYD7NV7UUBFvg+94+acA==","signatures":[{"sig":"MEUCICErKyEg/VybLgsuaOhHUB0FQ2f0qpLjUVMMttEQRRa8AiEA+OLi7XHMbt5tVQv4P3r9JlJdn/CjGimFYNVneFH7Gt4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":43149},"main":"./src/index.js","type":"module","types":"./src/index.d.ts","module":"./src/index.js","exports":{".":{"types":"./src/index.d.ts","import":"./src/index.js"}},"gitHead":"48efc21d3585220068269e403915ca4f12b74acb","_npmUser":{"name":"cartat","email":"mahmoud@firstcube.co"},"_npmVersion":"11.3.0","description":"Cartat Connect browser SDK for partner onboarding and popup lifecycle handling.","directories":{},"sideEffects":false,"_nodeVersion":"24.1.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/connect-js_0.2.1_1783961732026_0.11648037551956358","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"@cartat/connect-js","version":"0.2.2","description":"Cartat Connect browser SDK for partner onboarding and popup lifecycle handling.","type":"module","main":"./src/index.js","module":"./src/index.js","types":"./src/index.d.ts","exports":{".":{"types":"./src/index.d.ts","import":"./src/index.js"}},"publishConfig":{"access":"public"},"sideEffects":false,"keywords":["cartat","connect","oauth","partner","onboarding","sdk"],"license":"SEE LICENSE IN LICENSE","_id":"@cartat/connect-js@0.2.2","gitHead":"04153a34bfaec91929ac6f14f0c8473705e04144","_nodeVersion":"24.1.0","_npmVersion":"11.3.0","dist":{"integrity":"sha512-03sSPFQCyXPb9Nukb9Jlh5INM3sERXFmz/vDggQf6Zclepcv7/i/ZXVpOvzLQcEAm+M9baZYZGS0k7+l4HZqWQ==","shasum":"325fb34af11f2ece77baa6d9c3fb34c97bf25b20","tarball":"https://registry.npmjs.org/@cartat/connect-js/-/connect-js-0.2.2.tgz","fileCount":5,"unpackedSize":48216,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIEdKiDCh+8fl8ZPkvoky7EL3Sf6Z+0Adc3YyJI4ddPKxAiEAvv4+VPblk9zkk2/vwFWmjE5DxxPUlpNcJbp4hPLQGAc="}]},"_npmUser":{"name":"cartat","email":"mahmoud@firstcube.co"},"directories":{},"maintainers":[{"name":"cartat","email":"mahmoud@firstcube.co"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/connect-js_0.2.2_1783993051511_0.7231201537802534"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-25T20:10:22.874Z","modified":"2026-07-14T01:37:31.773Z","0.1.0":"2026-06-25T20:10:23.196Z","0.2.0":"2026-07-13T16:29:18.750Z","0.2.1":"2026-07-13T16:55:32.173Z","0.2.2":"2026-07-14T01:37:31.662Z"},"license":"SEE LICENSE IN LICENSE","keywords":["cartat","connect","oauth","partner","onboarding","sdk"],"description":"Cartat Connect browser SDK for partner onboarding and popup lifecycle handling.","maintainers":[{"name":"cartat","email":"mahmoud@firstcube.co"}],"readme":"# @cartat/connect-js\n\nCartat Connect browser SDK for partner onboarding.\n\nThe SDK is framework-agnostic. It does not own your UI. It owns the Cartat onboarding lifecycle:\n\n- Open Cartat onboarding in a centered external popup.\n- Start the managed Cartat onboarding flow.\n- Wait for Cartat onboarding events from the popup or managed flow.\n- Emit typed lifecycle events so product UI can show precise progress.\n\n## Install\n\n```bash\nnpm install @cartat/connect-js\n```\n\n## Production Base URL\n\nThe SDK defaults to the production Cartat Connect host:\n\n```text\nhttps://connect.cartat.net\n```\n\nPartners normally pass only `appId`. Do not hardcode the authorize URL or token URL in partner apps.\n\n```js\nimport { createCartatConnect } from '@cartat/connect-js';\n\nconst cartat = createCartatConnect({\n  appId: '9b5e2f2c-7c2f-45df-8c58-7674f92f6d9a',\n});\n```\n\n## Start Cartat Onboarding\n\nCartat supports two official onboarding paths:\n\n- SDK path: recommended for browser integrations. Call `startOnboarding()` with the public UUID `appId`; the SDK opens Cartat onboarding, creates PKCE, waits for completion events, exchanges the authorization code, and returns token fields directly.\n- Direct OAuth URL path: recommended for backend-owned OAuth flows. Redirect the customer to `/oauth/partner/authorize`; Cartat returns `code` and `state` to the registered callback; the partner backend exchanges the code with `client_id` and `client_secret`.\n\n```js\n// Install:\n// npm install @cartat/connect-js\n\nimport { createCartatConnect } from '@cartat/connect-js';\n\nconst cartat = createCartatConnect({\n  appId: '9b5e2f2c-7c2f-45df-8c58-7674f92f6d9a',\n  onEvent(event) {\n    console.log(event.type, event);\n  },\n});\n\nconst result = await cartat.startOnboarding({\n  // Use a CSRF value, or your internal USER_ID/session_id if you need to map the result.\n  // Cartat returns the same state in onboarding.completed so you can verify and match it.\n  state: crypto.randomUUID(), // or: 'user_12345'\n\n  // Optional: YOUR OWN workspace/tenant identifiers. Cartat records them on\n  // the resulting connection (external_workspace_id / external_workspace_name)\n  // so you can map your tenant to the Cartat workspace later.\n  externalWorkspaceId: 'shop_991', // defaults to the storeId option when set\n  externalWorkspaceName: 'Ahmed Store',\n});\n\nconsole.log(result.code, result.state);\nconsole.log(result.accessToken, result.refreshToken, result.expiresIn);\n```\n\n`appId` is the public UUID shown in Partner Hub under the app Integration tab. It is not the OAuth Client ID and it is not the internal dashboard route id.\nWhen `startOnboarding()` is used, the SDK automatically uses PKCE, exchanges the returned `code`, and includes `token`, `accessToken`, `refreshToken`, `tokenType`, and `expiresIn` in the resolved result and the `onboarding.completed` event. No `client_secret` is used in the browser.\nDirect OAuth URL usage does not return tokens to the browser event. It returns only `code` and `state` to the partner callback, and the partner backend must call `/oauth/partner/token`.\n`state` is partner-owned. Use it to prevent CSRF and to match the completed onboarding result to your local user, tenant, or session. Store/verify it on your side; Cartat only echoes it back.\n\n`externalWorkspaceId` / `externalWorkspaceName` are also partner-owned: they identify the workspace **in your system** and are stored on the Cartat connection record. Unlike `state` (echoed back once), they persist on the connection for later reconciliation. When you already pass `storeId`, it is used as the default `externalWorkspaceId`. Direct OAuth URL usage passes the same values as `external_workspace_id` / `external_workspace_name` query params on the authorize URL.\n\n## startOnboarding() options — complete reference\n\n| Option | Type | Default | Description |\n| --- | --- | --- | --- |\n| `state` | `string` | random UUID | Partner-owned correlation + CSRF value (min 8 chars). Echoed back in the completion result and every event. |\n| `appId` | `string` | constructor `appId` | The public app UUID from Partner Hub → Integration tab. |\n| `redirectUri` | `string` | app's configured URI | Must exactly match a redirect URI registered on the app. |\n| `scope` | `string \\| string[]` | all approved scopes | Subset of the app's approved scopes, e.g. `['workspace.read']`. |\n| `externalWorkspaceId` | `string \\| number` | `storeId` when set | YOUR workspace/tenant id — persisted on the Cartat connection (`external_workspace_id`). |\n| `externalWorkspaceName` | `string` | — | YOUR workspace/tenant name — persisted on the connection (`external_workspace_name`). |\n| `storeId` | `string \\| number` | — | Hint of your tenant id; also the default `externalWorkspaceId`. |\n| `sessionId` / `session` | `string` / `object` | — | Resume/track an existing onboarding session (advanced, custom flows). |\n| `generateAccessToken` | `boolean` | `true` | Auto-PKCE + code exchange; the result includes `accessToken`/`refreshToken`. Set `false` to receive only `code` + `state` and exchange server-side. |\n| `timeoutMs` | `number` | none with popup / 10 min without | Explicit absolute completion deadline; rejects with `onboarding_timeout`. |\n| `popupCloseCheckMs` | `number` | `500` | How often the SDK checks whether the customer closed the popup. |\n| `waitWhileStep` / `isComplete` | `string` / `fn` | — | Custom completion detection for `flow.open` integrations. |\n\n## createCartatConnect() constructor options\n\n| Option | Type | Default | Description |\n| --- | --- | --- | --- |\n| `appId` | `string` | — | Default public app UUID for all calls. |\n| `baseUrl` | `string` | `https://connect.cartat.net` | Cartat Connect API origin. |\n| `onEvent` | `fn(event)` | — | Receives every lifecycle event (see the events table). |\n| `autoGenerateAccessToken` | `boolean` | `true` | Global default for `generateAccessToken`. |\n| `completionTimeoutMs` | `number` | see `timeoutMs` | Global explicit completion deadline. |\n| `channel` | `string` | internal | BroadcastChannel name override (multi-frame setups). |\n| `api` | `{ fetchSession, submitResult }` | — | Adapters for custom session storage (advanced). |\n| `flow` | `{ open }` | — | Fully custom window flow instead of the SDK popup (advanced). |\n\n## Direct authorize URL — query parameters\n\nWhen building the URL yourself instead of using the SDK:\n\n| Param | Required | Description |\n| --- | --- | --- |\n| `app_id` or `client_id` | one of them | Public app UUID, or the OAuth client id. |\n| `state` | yes (min 8) | Partner CSRF/correlation value, echoed back to your callback. |\n| `redirect_uri` | no | Must match a registered redirect URI (defaults to the first one). |\n| `response_type` | no | Only `code` (default). |\n| `scope` | no | Space-separated approved scopes (defaults to all approved). |\n| `code_challenge` | no | PKCE S256 challenge (43–128 chars) for public clients. |\n| `code_challenge_method` | no | `S256` (default) or `plain`. |\n| `external_workspace_id` | no | Your workspace/tenant id, persisted on the connection. |\n| `external_workspace_name` | no | Your workspace/tenant name, persisted on the connection. |\n\n## Lifecycle Events\n\n| Event | Meaning |\n| --- | --- |\n| `onboarding.started` | Cartat onboarding started. |\n| `onboarding.window.waiting` | Cartat opened a managed step and is waiting for callback data. |\n| `partner.popup.opening` | SDK is about to open the Cartat popup. |\n| `partner.popup.opened` | SDK opened the popup successfully. |\n| `partner.popup.resolve_failed` | SDK could not resolve the final onboarding URL from the JSON authorize response and falls back to navigating the popup to the authorize URL. |\n| `onboarding.callback.received` | Cartat received the managed callback payload. |\n| `onboarding.callback.failed` | The managed step failed or was cancelled. |\n| `onboarding.syncing` | SDK is saving the result in Cartat. |\n| `onboarding.synced` | Cartat accepted the result. |\n| `onboarding.sync.failed` | Cartat could not save the onboarding result. |\n| `onboarding.event.waiting` | SDK is waiting for a Cartat onboarding event. |\n| `onboarding.event.received` | SDK received a Cartat onboarding event. |\n| `onboarding.event.fetch_failed` | SDK received an event but could not fetch the latest session through the optional adapter. |\n| `onboarding.event.timeout` | Completion event did not arrive before the deadline; the promise rejects with `code: \"onboarding_timeout\"`. Only possible when an explicit `timeoutMs`/`completionTimeoutMs` was set, or after the 10-minute safety net in flows without an SDK popup handle. SDK-managed popups never time out while the customer keeps the window open. |\n| `onboarding.completed` | The onboarding flow is complete. Direct-link completion includes `code` and `state`. SDK PKCE completion also includes `token`, `accessToken`, `refreshToken`, `tokenType`, and `expiresIn`. |\n| `access_token.generated` | SDK exchanged the authorization code through PKCE and received a token. |\n| `access_token.failed` | SDK could not exchange the authorization code through PKCE. |\n| `onboarding.cancelled` | Customer closed the popup before completion. |\n\nThese names are not illustrative; they are the current `CartatConnectEventType` values shipped in `src/index.d.ts`.\n\n## Publishing Completion From Cartat Popup\n\nWhen Cartat onboarding reaches completion, publish an event:\n\n```js\nimport { publishOnboardingEvent } from '@cartat/connect-js';\n\npublishOnboardingEvent('onboarding.completed', {\n  sessionId,\n  state,\n  code,\n  redirectUrl,\n  connectionId,\n  authorizationCodeId,\n  workspace,\n  scopes,\n  app,\n  partner,\n  whatsapp,\n});\n```\n\nThe SDK delivers events through `postMessage`, `BroadcastChannel`, `storage`, and same-window `CustomEvent`.\n\n## Generate Access Token\n\nNormal SDK usage does this automatically. For advanced flows, call `generateAccessToken()` with the PKCE verifier you created for the authorize URL:\n\n```js\nimport { createCartatConnect, createPkcePair } from '@cartat/connect-js';\n\nconst cartat = createCartatConnect({ appId: '9b5e2f2c-7c2f-45df-8c58-7674f92f6d9a' });\nconst pkce = await createPkcePair();\nconst authorizeUrl = cartat.createAuthorizeUrl({\n  state: 'partner_state',\n  codeChallenge: pkce.codeChallenge,\n  codeChallengeMethod: pkce.codeChallengeMethod,\n});\n\n// After Cartat returns a code:\nconst token = await cartat.generateAccessToken({\n  code: 'code_FROM_CARTAT',\n  codeVerifier: pkce.codeVerifier,\n});\n```\n\n## Popup Onboarding\n\n```js\nconst popup = cartat.openPartnerOnboarding(cartat.createAuthorizeUrl(), {\n  name: 'cartat_connect_onboarding',\n  width: 820,\n  height: 960,\n  resizable: false,\n  lockSize: true,\n});\n```\n\nThe popup is opened synchronously as `about:blank` from the user's click, using a unique popup name for each attempt so stale partner windows are not reused. The default window is `820x960`, centered, scrollable, requested as non-resizable, and actively size-locked by the opener while it remains open to match embedded signup style windows. Browser and operating-system policies may still expose resize handles, but the SDK restores the approved geometry. The onboarding UI must remain responsive for direct-link usage and browser policy differences. The SDK then calls the Cartat authorize endpoint with `Accept: application/json`, reads `data.onboarding_url`, and redirects the popup to that exact onboarding URL. The SDK never falls back to navigating the partner page. If the browser blocks the popup, `startOnboarding()` throws `CartatConnectError` with `code: \"popup_blocked\"`.\n\n## Error Shape\n\nAll SDK errors use `CartatConnectError`:\n\n```js\n{\n  name: 'CartatConnectError',\n  code: 'onboarding_step_failed',\n  message: 'Cartat onboarding step was not completed.',\n  details: {}\n}\n```\n\n## Product Rules\n\n- The SDK is the source of lifecycle behavior; UI should listen to events and render progress.\n- The SDK is event-first. Do not add interval polling to the package.\n- The SDK opens a real external popup and must never redirect the partner's current page.\n- The SDK default `baseUrl` is `https://connect.cartat.net`. Partner apps should not build Cartat URLs manually.\n- The SDK resolves the final Cartat onboarding URL from the JSON authorize response before navigating the popup.\n- If the customer closes the popup before completion, the SDK emits `onboarding.cancelled` and rejects `startOnboarding()` with `code: \"onboarding_cancelled\"`.\n- Completion payloads must include the returned authorization `code`. In normal SDK usage the SDK also exchanges that code through PKCE and adds `token` to the completed result.\n- Completion payloads must not include raw onboarding session internals such as `stores`, `qr`, provider responses, or `raw`.\n- The SDK does not store `client_secret` in the browser.\n- Browser token generation must use SDK PKCE. Direct authorize links still use the partner backend with `client_id` and `client_secret`.\n- Timeout is not a hard failure. It means the UI should keep the latest session and allow retry/refresh.\n\n## TypeScript\n\nThe package ships `src/index.d.ts` for autocomplete and typed lifecycle events:\n\n```ts\nimport { createCartatConnect, type CartatConnectEvent } from '@cartat/connect-js';\n\nfunction handleEvent(event: CartatConnectEvent) {\n  if (event.type === 'onboarding.completed') {\n    console.log(event.code, event.workspace?.id);\n  }\n}\n\nconst cartat = createCartatConnect({ onEvent: handleEvent });\nconst result = await cartat.startOnboarding();\n```\n","readmeFilename":"README.md"}