{"_id":"@auth-craft/frontend-sdk","_rev":"4-ae226b4a632dd13f77d3c20a942ceb5b","name":"@auth-craft/frontend-sdk","dist-tags":{"latest":"0.1.3"},"versions":{"0.1.0":{"name":"@auth-craft/frontend-sdk","version":"0.1.0","keywords":["auth-craft","fetchguard","authentication","sdk","typescript"],"author":{"name":"minhtaimc"},"license":"MIT","_id":"@auth-craft/frontend-sdk@0.1.0","maintainers":[{"name":"minhtaimc","email":"minhtaimc@gmail.com"}],"dist":{"shasum":"586f418d95672915504f474cdd5cac92fa1a3dc3","tarball":"https://registry.npmjs.org/@auth-craft/frontend-sdk/-/frontend-sdk-0.1.0.tgz","fileCount":90,"integrity":"sha512-9bpn4WjxEZWyVjMpyYzPp6Z4fE2mpOgMQzJf4aoERa+eo5xG48E1f7nhuOmmkldvZucva64/b/TwzKwfWl63Fg==","signatures":[{"sig":"MEUCIQDam1HaFggx7t8VsG0S9cvq0iH4lqkJ5O8MZadcARCd8gIgVJJvMHYMgHk/gxVcvP8z3Z8bGyDzhudO9M79+rmCglc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":127901},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./types":{"types":"./dist/types/index.d.ts","import":"./dist/types/index.js"}},"gitHead":"5d78c4628e42b983f7dcb095cca25b1b5740c124","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"minhtaimc","email":"minhtaimc@gmail.com"},"_npmVersion":"11.6.2","description":"Frontend SDK for Auth Craft — wraps FetchGuard with typed modules for authentication, user management, MFA, OAuth, and tenant operations","directories":{},"_nodeVersion":"24.11.1","dependencies":{"fetchguard":"^2.2.3","ts-micro-result":"^3.3.0"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.0","typescript":"^5.7.0"},"_npmOperationalInternal":{"tmp":"tmp/frontend-sdk_0.1.0_1773583329625_0.8991571723709784","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@auth-craft/frontend-sdk","version":"0.1.1","keywords":["auth-craft","fetchguard","authentication","sdk","typescript"],"author":{"name":"minhtaimc"},"license":"MIT","_id":"@auth-craft/frontend-sdk@0.1.1","maintainers":[{"name":"minhtaimc","email":"minhtaimc@gmail.com"}],"dist":{"shasum":"c13af5deeba561c6d571b29472f2e8b965298eb1","tarball":"https://registry.npmjs.org/@auth-craft/frontend-sdk/-/frontend-sdk-0.1.1.tgz","fileCount":90,"integrity":"sha512-hnL6m1oHIXgUUnGqllGSf9N2P6RrzdKbIxlpwcTGpAyzQPDDrvr4km8c1YSbOm2OXpzZ0gpNBsf+eU10Ss7r7w==","signatures":[{"sig":"MEQCIFoEvZXrQ7kb/KMUHNPAwcPAT655VMTdITSQL8zj1YZjAiBnV65LWjBgJPmWl1tApyf3Sp6BGuwyADcIT8lc+Rxexw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":128504},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./types":{"types":"./dist/types/index.d.ts","import":"./dist/types/index.js"}},"gitHead":"5d78c4628e42b983f7dcb095cca25b1b5740c124","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"minhtaimc","email":"minhtaimc@gmail.com"},"_npmVersion":"11.6.2","description":"Frontend SDK for Auth Craft — wraps FetchGuard with typed modules for authentication, user management, MFA, OAuth, and tenant operations","directories":{},"_nodeVersion":"24.11.1","dependencies":{"fetchguard":"^2.2.3","ts-micro-result":"^3.3.0"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.0","typescript":"^5.7.0"},"_npmOperationalInternal":{"tmp":"tmp/frontend-sdk_0.1.1_1773583938716_0.9282498990984862","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@auth-craft/frontend-sdk","version":"0.1.2","keywords":["auth-craft","fetchguard","authentication","sdk","typescript"],"author":{"name":"minhtaimc"},"license":"MIT","_id":"@auth-craft/frontend-sdk@0.1.2","maintainers":[{"name":"minhtaimc","email":"minhtaimc@gmail.com"}],"dist":{"shasum":"ead6f80fc603aab67c7b041cff8ad169db191386","tarball":"https://registry.npmjs.org/@auth-craft/frontend-sdk/-/frontend-sdk-0.1.2.tgz","fileCount":90,"integrity":"sha512-OV54LH66BG/iTjng5C5Fh15UGd0ktcd33suVyH6Bvl6XYSDodmqe/T1VHyHYdYK41ctS2/bBmfGtU8AXUx36yw==","signatures":[{"sig":"MEYCIQC+ETKN0j0I1nQBSTGJwa/veWnk3CJLNWJvhzKXF/Hm6wIhANptoAyy/WYs7cPpLf89gdg7S/+YtqiIFMqfEEUwSjYJ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":128450},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./types":{"types":"./dist/types/index.d.ts","import":"./dist/types/index.js"}},"gitHead":"c6cdb5c6e14b50c3fc2e68b51d36939075e8c30a","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"minhtaimc","email":"minhtaimc@gmail.com"},"_npmVersion":"11.6.2","description":"Frontend SDK for Auth Craft — wraps FetchGuard with typed modules for authentication, user management, MFA, OAuth, and tenant operations","directories":{},"_nodeVersion":"24.11.1","dependencies":{"fetchguard":"^2.2.3","ts-micro-result":"^3.3.0"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.0","typescript":"^5.7.0"},"_npmOperationalInternal":{"tmp":"tmp/frontend-sdk_0.1.2_1774232839994_0.26462857897662917","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@auth-craft/frontend-sdk","version":"0.1.3","description":"Frontend SDK for Auth Craft — wraps FetchGuard with typed modules for authentication, user management, MFA, OAuth, and tenant operations","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./types":{"types":"./dist/types/index.d.ts","import":"./dist/types/index.js"}},"scripts":{"build":"tsc","dev":"tsc --watch","clean":"rm -rf dist","typecheck":"tsc --noEmit","test":"vitest run","test:watch":"vitest"},"dependencies":{"fetchguard":"^2.2.3","ts-micro-result":"^3.3.0"},"devDependencies":{"typescript":"^5.7.0","vitest":"^4.1.0"},"keywords":["auth-craft","fetchguard","authentication","sdk","typescript"],"author":{"name":"minhtaimc"},"license":"MIT","gitHead":"79a55af1b93264d28702b402299a0747716f50a4","_id":"@auth-craft/frontend-sdk@0.1.3","_nodeVersion":"24.11.1","_npmVersion":"11.6.2","dist":{"integrity":"sha512-GzfT2E4XIaWD1+uGSSKB5DIMPBAeI2d+z7984Pw5Khd8ZSpF0GvNPF/9j54Rmx3p14LA3mQ+t4Le/0l0JnZn7w==","shasum":"ad8133bdc0f19ad37b8bb0f3c93401cb6a261ba7","tarball":"https://registry.npmjs.org/@auth-craft/frontend-sdk/-/frontend-sdk-0.1.3.tgz","fileCount":90,"unpackedSize":129375,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDlE727eAWszMgwRbNrkLfvWt5700YNGpF1o/RPQi4jQwIgC8L0bNP1z+J+lDmxd4Tm2z/3NgduphrRNY9vrU2cdIg="}]},"_npmUser":{"name":"minhtaimc","email":"minhtaimc@gmail.com"},"directories":{},"maintainers":[{"name":"minhtaimc","email":"minhtaimc@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/frontend-sdk_0.1.3_1774233822605_0.5473341593988341"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-15T14:02:09.516Z","modified":"2026-03-23T02:43:42.867Z","0.1.0":"2026-03-15T14:02:09.783Z","0.1.1":"2026-03-15T14:12:18.880Z","0.1.2":"2026-03-23T02:27:20.154Z","0.1.3":"2026-03-23T02:43:42.743Z"},"author":{"name":"minhtaimc"},"license":"MIT","keywords":["auth-craft","fetchguard","authentication","sdk","typescript"],"description":"Frontend SDK for Auth Craft — wraps FetchGuard with typed modules for authentication, user management, MFA, OAuth, and tenant operations","maintainers":[{"name":"minhtaimc","email":"minhtaimc@gmail.com"}],"readme":"# @auth-craft/frontend-sdk\r\n\r\nFrontend SDK cho Auth Craft — wrap [FetchGuard](https://github.com/nicepkg/fetchguard) v2 cung cấp typed modules cho authentication, user management, MFA, OAuth và tenant operations.\r\n\r\n## Architecture\r\n\r\n```\r\n┌─────────────────────────────────────────────────────────────────┐\r\n│  Your App (React / Vue / Svelte / Vanilla)                      │\r\n│                                                                 │\r\n│  import { createAuthCraft } from '@auth-craft/frontend-sdk'     │\r\n│  const ac = createAuthCraft(config)                             │\r\n│  await ac.init()                                                │\r\n│                                                                 │\r\n│  ┌───────────────────────────────────────────────────────────┐  │\r\n│  │                   AuthCraftClient                         │  │\r\n│  │                                                           │  │\r\n│  │  ┌─────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐  │  │\r\n│  │  │  auth   │ │ password │ │  oauth   │ │ verification │  │  │\r\n│  │  └────┬────┘ └────┬─────┘ └────┬─────┘ └──────┬───────┘  │  │\r\n│  │  ┌────┴────┐ ┌────┴─────┐ ┌────┴─────┐ ┌──────┴───────┐  │  │\r\n│  │  │  user   │ │ session  │ │   mfa    │ │   tenant     │  │  │\r\n│  │  └────┬────┘ └────┬─────┘ └────┬─────┘ └──────┬───────┘  │  │\r\n│  │       │           │            │               │          │  │\r\n│  │       └───────────┴────────────┴───────────────┘          │  │\r\n│  │                         │                                 │  │\r\n│  │              ┌──────────┴──────────┐                      │  │\r\n│  │              │  InternalClient     │                      │  │\r\n│  │              │  get/post/put/patch  │                      │  │\r\n│  │              │  delete/buildUrl     │                      │  │\r\n│  │              └──────────┬──────────┘                      │  │\r\n│  │                         │                                 │  │\r\n│  │              ┌──────────┴──────────┐                      │  │\r\n│  │              │  FetchGuard Client  │                      │  │\r\n│  │              │  (Web Worker)       │                      │  │\r\n│  │              └──────────┬──────────┘                      │  │\r\n│  └──────────────────────── │ ────────────────────────────────┘  │\r\n│                            │                                    │\r\n│                   ┌────────┴────────┐                           │\r\n│                   │  Worker Thread  │                           │\r\n│                   │  Token Storage  │                           │\r\n│                   │  Auto Refresh   │                           │\r\n│                   └────────┬────────┘                           │\r\n└──────────────────────────── │ ───────────────────────────────────┘\r\n                             │\r\n                    ┌────────┴────────┐\r\n                    │  Auth Craft API │\r\n                    │  /auth/...      │\r\n                    │  /users/...     │\r\n                    │  /sessions/...  │\r\n                    │  /mfa/...       │\r\n                    │  /tenant/...    │\r\n                    └─────────────────┘\r\n```\r\n\r\n## Authentication Flow\r\n\r\n```\r\n                           authenticate()\r\n                                │\r\n                    ┌───────────┼───────────┐\r\n                    ▼           ▼           ▼\r\n             TokenResponse  Challenge   MfaRequired\r\n             (success)     Response     Response\r\n                │               │           │\r\n                │     completeChallenge()   │\r\n                │               │           │\r\n                │       ┌───────┼───────┐   │\r\n                │       ▼               ▼   │\r\n                │  TokenResponse  MfaRequired\r\n                │       │          Response\r\n                │       │               │\r\n                │       │    ┌──────────┘\r\n                │       │    │\r\n                │       │    ▼  issueMfaChallenge() (optional, SMS/Email)\r\n                │       │    │\r\n                │       │    ▼  completeMfaChallenge()\r\n                │       │    │\r\n                │       │    ▼\r\n                │       │  TokenResponse\r\n                │       │    │\r\n                ▼       ▼    ▼\r\n            ┌─────────────────────┐\r\n            │  Authenticated!     │\r\n            │  Token in Worker    │\r\n            │  onAuthStateChanged │\r\n            └─────────────────────┘\r\n```\r\n\r\n## Install\r\n\r\n```bash\r\npnpm add @auth-craft/frontend-sdk\r\n# or\r\nnpm install @auth-craft/frontend-sdk\r\n```\r\n\r\n**Peer Dependencies:** `fetchguard@^2.2.3`, `ts-micro-result@^3.3.0`\r\n\r\n## Quick Start\r\n\r\n```typescript\r\nimport { createAuthCraft, isTokenResponse, isChallengeResponse } from '@auth-craft/frontend-sdk'\r\n\r\n// 1. Create client\r\nconst authCraft = createAuthCraft({\r\n  baseUrl: 'https://auth.example.com',\r\n  strategy: 'cookie-auth',            // or 'body-auth'\r\n  allowedDomains: ['api.example.com'],\r\n  onAuthStateChanged: (state) => {\r\n    console.log('Auth changed:', state.authenticated)\r\n  },\r\n})\r\n\r\n// 2. Initialize (loads Web Worker, restores session)\r\nawait authCraft.init()\r\n\r\n// 3. Login\r\nconst result = await authCraft.auth.authenticate({\r\n  identityType: 'email',\r\n  identityValue: 'user@example.com',\r\n  credentialType: 'password',\r\n  credentialValue: 's3cret',\r\n})\r\n\r\nif (result.ok) {\r\n  if (isTokenResponse(result.data)) {\r\n    console.log('Logged in!')\r\n  } else if (isChallengeResponse(result.data)) {\r\n    // Handle email verification challenge\r\n    const { challengeId } = result.data.challenge\r\n    // ... show OTP input, then:\r\n    await authCraft.auth.completeChallenge({ challengeId, code: '123456' })\r\n  }\r\n} else {\r\n  console.error(result.errors[0].message)\r\n}\r\n```\r\n\r\n## Configuration\r\n\r\n```typescript\r\ninterface AuthCraftConfig {\r\n  baseUrl: string                               // Auth Craft server URL\r\n  strategy: 'cookie-auth' | 'body-auth'         // Token refresh strategy\r\n  allowedDomains: string[]                       // Domains receiving auth tokens\r\n  refreshEarlyMs?: number                        // Refresh before expiry (default: 5 min)\r\n  defaultHeaders?: Record<string, string>        // Headers for all requests\r\n  onAuthStateChanged?: (state: AuthState) => void // Auth state callback\r\n  workerFactory?: () => Worker                   // Custom Worker factory (required when consuming compiled dist/)\r\n}\r\n```\r\n\r\n### Strategy\r\n\r\n| Strategy | Refresh Token Storage | Use Case |\r\n|---|---|---|\r\n| `cookie-auth` | httpOnly cookie (server-set) | Web apps with same-domain API |\r\n| `body-auth` | FetchGuard Web Worker (IndexedDB) | Cross-domain, Lambda/serverless |\r\n\r\n### `workerFactory`\r\n\r\nRequired when the SDK is consumed as compiled JS (e.g. from `dist/`) since bundlers cannot resolve the worker URL automatically:\r\n\r\n```typescript\r\nconst authCraft = createAuthCraft({\r\n  baseUrl: 'https://auth.example.com',\r\n  strategy: 'body-auth',\r\n  allowedDomains: ['api.example.com'],\r\n  workerFactory: () => new Worker(new URL('./fetchguard.worker.js', import.meta.url)),\r\n})\r\n```\r\n\r\n## Modules\r\n\r\n### `auth` — Authentication\r\n\r\n```typescript\r\n// Login\r\nac.auth.authenticate(req: AuthenticateRequest)       → Result<AuthenticateResult>\r\n\r\n// Register\r\nac.auth.register(req: RegisterRequest)                → Result<RegisterResponse>\r\n\r\n// Multi-step auth\r\nac.auth.completeChallenge(req: CompleteChallengeRequest)       → Result<AuthenticateResult>\r\nac.auth.completeMfaChallenge(req: CompleteMfaChallengeRequest) → Result<TokenResponse>\r\nac.auth.issueMfaChallenge(req: IssueMfaChallengeRequest)       → Result<IssueMfaChallengeResponse>\r\n\r\n// Session\r\nac.auth.logout()                                      → Result<void>\r\nac.auth.refresh()                                     → { authenticated: boolean }\r\nac.auth.me()                                          → Result<AuthUserProfile>\r\n\r\n// Tenant\r\nac.auth.selectTenant(tenantId: string)                → Result<TokenResponse>\r\n```\r\n\r\n### `password` — Password Management\r\n\r\n```typescript\r\nac.password.change(req: ChangePasswordRequest)        → Result<MessageResponse>\r\nac.password.forgot(req: ForgotPasswordRequest)        → Result<ForgotPasswordResponse>\r\nac.password.reset(req: ResetPasswordRequest)          → Result<MessageResponse>\r\n```\r\n\r\n### `verification` — Email / SMS Verification\r\n\r\n```typescript\r\nac.verification.send(req: SendVerificationRequest)    → Result<VerificationResponse>\r\nac.verification.verify(req: VerifyCodeRequest)        → Result<VerifyCodeResponse>\r\nac.verification.resend(req: ResendVerificationRequest)→ Result<VerificationResponse>\r\n```\r\n\r\n### `user` — User Profile\r\n\r\n```typescript\r\nac.user.sendWelcomeEmail(req: WelcomeEmailRequest)    → Result<MessageResponse>\r\nac.user.updateProfile(req: UpdateProfileRequest)      → Result<AuthUserProfile>\r\n```\r\n\r\n### `oauth` — Social Login\r\n\r\n```typescript\r\nac.oauth.callback(req: OAuthCallbackRequest)          → Result<TokenResponse>\r\nac.oauth.link(req: OAuthLinkRequest)                  → Result<MessageResponse>\r\nac.oauth.unlink(req: OAuthUnlinkRequest)              → Result<MessageResponse>\r\nac.oauth.listProviders()                              → Result<ListOAuthProvidersResponse>\r\n```\r\n\r\n### `session` — Session Management\r\n\r\n```typescript\r\nac.session.list(includeRevoked?: boolean)             → Result<ListSessionsResponse>\r\nac.session.delete(req: DeleteSessionRequest)          → Result<MessageResponse>\r\nac.session.revoke(req: RevokeSessionRequest)          → Result<MessageResponse>\r\n```\r\n\r\n### `mfa` — Multi-Factor Authentication\r\n\r\n```typescript\r\nac.mfa.setup(req: MfaSetupRequest)                    → Result<MfaSetupResponse>\r\nac.mfa.verify(req: MfaVerifyRequest)                  → Result<MfaVerifyResponse>\r\nac.mfa.list(options?: { method?: string; verifiedOnly?: boolean })\r\n                                                      → Result<ListMfaAuthenticatorsResponse>\r\nac.mfa.delete(req: DeleteMfaAuthenticatorRequest)     → Result<MessageResponse>\r\nac.mfa.updateSettings(req: UpdateMfaSettingsRequest)  → Result<MfaSettings>\r\n```\r\n\r\n### `tenant` — Tenant / Organization\r\n\r\n```typescript\r\n// Invites\r\nac.tenant.createInvite(req: CreateTenantInviteRequest)          → Result<CreateTenantInviteResponse>\r\nac.tenant.listInvites(status?: string)                          → Result<{ invites: TenantInvite[] }>\r\nac.tenant.acceptInvite(req: AcceptInviteRequest)                → Result<AcceptInviteResponse>\r\nac.tenant.declineInvite(req: DeclineInviteRequest)              → Result<MessageResponse>\r\nac.tenant.revokeInvite(req: RevokeInviteRequest)                → Result<MessageResponse>\r\nac.tenant.checkPendingInvites(req: CheckPendingInvitesRequest)  → Result<{ invites: PendingInvite[] }>\r\n\r\n// Members\r\nac.tenant.listMembers()                                         → Result<ListTenantMembersResponse>\r\nac.tenant.updateMember(req: UpdateTenantMemberRequest)          → Result<MessageResponse>\r\nac.tenant.removeMember(req: RemoveTenantMemberRequest)          → Result<MessageResponse>\r\n\r\n// Profile\r\nac.tenant.getProfile()                                          → Result<TenantProfile>\r\nac.tenant.updateProfile(req: UpdateTenantProfileRequest)        → Result<MessageResponse>\r\n```\r\n\r\n## Response Types\r\n\r\n### AuthenticateResult\r\n\r\nLogin/challenge methods return a union — use type guards to discriminate:\r\n\r\n```typescript\r\nimport {\r\n  isTokenResponse,\r\n  isChallengeResponse,\r\n  isMfaRequiredResponse,\r\n} from '@auth-craft/frontend-sdk'\r\n\r\nconst result = await ac.auth.authenticate(req)\r\n\r\nif (!result.ok) {\r\n  // result.errors: readonly ErrorDetail[]\r\n  return\r\n}\r\n\r\nif (isTokenResponse(result.data)) {\r\n  // { accessToken, expiresAt }\r\n}\r\n\r\nif (isChallengeResponse(result.data)) {\r\n  // { requiresChallenge: true, challenge: { challengeId, phase, expiresAt, data? } }\r\n}\r\n\r\nif (isMfaRequiredResponse(result.data)) {\r\n  // { requiresMfa: true, mfa: { phase, challengeId, methods, method?, expiresAt, userId } }\r\n}\r\n```\r\n\r\n### Result\\<T\\> Pattern\r\n\r\nAll methods return `Result<T>` from [ts-micro-result](https://github.com/nicepkg/ts-micro-result):\r\n\r\n```typescript\r\ntype Result<T> =\r\n  | { ok: true;  data: T;                      meta?: unknown }\r\n  | { ok: false; errors: readonly ErrorDetail[]; meta?: unknown }\r\n\r\ninterface ErrorDetail {\r\n  code: string\r\n  message: string\r\n  field?: string\r\n  params?: Record<string, unknown>\r\n}\r\n```\r\n\r\n## HTTP Client\r\n\r\n`AuthCraftClient` also exposes authenticated HTTP methods for custom API calls:\r\n\r\n```typescript\r\n// All return Result<T> — auto-handles token injection, refresh, error transform\r\nawait ac.get<User>(ac.buildUrl('/users/123'))\r\nawait ac.post<Order>(ac.buildUrl('/orders'), { items: [...] })\r\nawait ac.put<void>(url, body)\r\nawait ac.patch<void>(url, body)\r\nawait ac.delete<void>(url, body)\r\n```\r\n\r\n`ac.buildUrl(path)` constructs full URLs: `{baseUrl}{path}`. Pass absolute URLs for other APIs.\r\n\r\n## Lifecycle\r\n\r\n```typescript\r\n// Create + init\r\nconst ac = createAuthCraft(config)\r\nawait ac.init()    // creates Web Worker, restores session, triggers onAuthStateChanged\r\n\r\n// Use...\r\n\r\n// Cleanup (SPA unmount)\r\nac.destroy()       // terminates Web Worker, clears state\r\n```\r\n\r\n## Error Codes\r\n\r\nSDK-level errors (from `SdkErrors`):\r\n\r\n| Code | Description |\r\n|---|---|\r\n| `NOT_INITIALIZED` | `init()` not called |\r\n| `LOGIN_FAILED` | Authentication failed |\r\n| `NETWORK_ERROR` | Connection failed |\r\n| `SERVER_ERROR` | 5xx from server |\r\n| `GET_FAILED` / `POST_FAILED` / ... | HTTP method error |\r\n| `PARSE_ERROR` | Response JSON parse failed |\r\n\r\nBackend errors are passed through as-is in `result.errors`.\r\n\r\n## Project Structure\r\n\r\n```\r\nsrc/\r\n├── index.ts              # Public API exports\r\n├── client.ts             # AuthCraftClient (FetchGuard wrapper)\r\n├── config.ts             # AuthCraftConfig interface\r\n├── errors.ts             # SdkErrors factories\r\n├── utils.ts              # Response transform, error mapping\r\n├── types/\r\n│   ├── index.ts          # Type barrel\r\n│   ├── auth.ts           # Auth request/response types\r\n│   ├── user.ts           # User profile types\r\n│   ├── password.ts       # Password types\r\n│   ├── verification.ts   # Verification types\r\n│   ├── session.ts        # Session types\r\n│   ├── mfa.ts            # MFA types\r\n│   ├── oauth.ts          # OAuth types\r\n│   └── tenant.ts         # Tenant types\r\n└── modules/\r\n    ├── auth.ts           # AuthModule\r\n    ├── user.ts           # UserModule\r\n    ├── password.ts       # PasswordModule\r\n    ├── verification.ts   # VerificationModule\r\n    ├── session.ts        # SessionModule\r\n    ├── mfa.ts            # MfaModule\r\n    ├── oauth.ts          # OAuthModule\r\n    └── tenant.ts         # TenantModule\r\n```\r\n\r\n## Integration Example (merchant-web)\r\n\r\nKhi tích hợp vào FE app, dùng **ApiClient** pattern — 1 singleton quản lý lifecycle, expose 2 namespace:\r\n\r\n```typescript\r\n// ApiClient.ts — Composition Root\r\nimport { createAuthCraft, type AuthCraftClient } from '@auth-craft/frontend-sdk'\r\n\r\nclass ApiClientImpl {\r\n  private _sdk: AuthCraftClient | null = null\r\n\r\n  /** Auth operations (login, MFA, password, verification, OAuth, etc.) */\r\n  get auth(): AuthCraftClient {\r\n    if (!this._sdk) throw new Error('ApiClient not initialized')\r\n    return this._sdk\r\n  }\r\n\r\n  /** Authenticated API for feature services (orders, stores, wallet, etc.) */\r\n  readonly api = {\r\n    get:    <T>(url: string, opts?) => this.auth.get<T>(url, opts),\r\n    post:   <T>(url: string, body?, opts?) => this.auth.post<T>(url, body, opts),\r\n    put:    <T>(url: string, body?, opts?) => this.auth.put<T>(url, body, opts),\r\n    patch:  <T>(url: string, body?, opts?) => this.auth.patch<T>(url, body, opts),\r\n    delete: <T>(url: string, body?, opts?) => this.auth.delete<T>(url, body, opts),\r\n  }\r\n\r\n  async init() { /* createAuthCraft + init + wire auth state bridge */ }\r\n  destroy()    { /* cleanup */ }\r\n}\r\n\r\nexport const apiClient = new ApiClientImpl()\r\n```\r\n\r\nUsage:\r\n\r\n```typescript\r\n// Auth service (auth operations)\r\napiClient.auth.auth.authenticate({ ... })\r\napiClient.auth.password.forgot({ email })\r\napiClient.auth.oauth.callback({ provider: 'google', code })\r\n\r\n// Feature services (business API)\r\napiClient.api.get<Order[]>('/orders')\r\napiClient.api.post<Store>('/stores', data)\r\n\r\n// Lifecycle (AuthProvider)\r\nawait apiClient.init()\r\napiClient.destroy()\r\n```\r\n\r\n```\r\n┌───────────────────────────────────────────────────────────┐\r\n│  FE App                                                   │\r\n│                                                           │\r\n│  ┌─────────────────────────────────────────────────────┐  │\r\n│  │  apiClient (singleton)                              │  │\r\n│  │                                                     │  │\r\n│  │  .auth  → AuthCraftClient (SDK modules)             │  │\r\n│  │  .api   → authenticated HTTP (get/post/put/...)     │  │\r\n│  │  .init() / .destroy()                               │  │\r\n│  └────────┬──────────────┬─────────────────────────────┘  │\r\n│           │              │                                │\r\n│     .api (HTTP)    .auth (SDK)                            │\r\n│           │              │                                │\r\n│  ┌────────▼───────┐  ┌──▼──────────────────────┐         │\r\n│  │ feature svcs   │  │ authService              │         │\r\n│  │ orders, stores │  │ login, register, MFA     │         │\r\n│  │ items, wallet  │  │ password, verification   │         │\r\n│  │ ...            │  │ OAuth, tenant            │         │\r\n│  └────────────────┘  └──────────────────────────┘         │\r\n└───────────────────────────────────────────────────────────┘\r\n```\r\n\r\n## License\r\n\r\nMIT\r\n","readmeFilename":"README.md"}