{"_id":"@blueflamingos/laravel-client","_rev":"2-133696a35db10b051bdc0e85117a2e61","name":"@blueflamingos/laravel-client","dist-tags":{"latest":"1.6.0"},"versions":{"1.5.0":{"name":"@blueflamingos/laravel-client","version":"1.5.0","keywords":["laravel","api"],"author":{"name":"Blue Flamingos"},"license":"MIT","_id":"@blueflamingos/laravel-client@1.5.0","maintainers":[{"name":"blueflamingos-dev","email":"development@blueflamingos.nl"},{"name":"rjvandoesburg","email":"rjvandoesburg@gmail.com"}],"homepage":"https://github.com/blueflamingos/laravel-client#readme","bugs":{"url":"https://github.com/blueflamingos/laravel-client/issues"},"dist":{"shasum":"ce802f1ac33888210b240d5a8f1e0527ca731ad2","tarball":"https://registry.npmjs.org/@blueflamingos/laravel-client/-/laravel-client-1.5.0.tgz","fileCount":6,"integrity":"sha512-U9r+JXM0M6ZxlKgl3AYnoiqm8bOKMBEvNn2IPiMCkBAjtsFp6y5Cl1rnU2HRNegriOqR/TDyvsNsLHwAxPZlCQ==","signatures":[{"sig":"MEQCIA4pMKiavPb26d6Kdx0nRK5HVTymSQVjnSvwjiNkqhNkAiBRwVh49KeMnpPIACsLZ5kaE1PmSvRgc4H8BzHB4QyGzA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":42514},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"237518c29287139cb91fba9d0632945b88ee3947","scripts":{"dev":"nodemon --watch src --ext ts,tsx --exec 'npm run build && yalc push'","test":"jest","build":"tsc","watch":"tsc --watch","yalc:push":"npm run build && yalc push","yalc:publish":"npm run build && yalc publish","prepublishOnly":"npm run build"},"_npmUser":{"name":"blueflamingos-dev","email":"development@blueflamingos.nl"},"repository":{"url":"git+https://github.com/blueflamingos/laravel-client.git","type":"git"},"_npmVersion":"10.2.4","description":"Laravel client for JavaScript/TypeScript","directories":{},"_nodeVersion":"20.11.1","_hasShrinkwrap":false,"devDependencies":{"nodemon":"^3.1.10","typescript":"^5.8.3","@types/node":"^22.15.1"},"_npmOperationalInternal":{"tmp":"tmp/laravel-client_1.5.0_1757313713048_0.7508512545631627","host":"s3://npm-registry-packages-npm-production"}},"1.6.0":{"name":"@blueflamingos/laravel-client","version":"1.6.0","description":"Laravel client for JavaScript/TypeScript","main":"dist/index.js","types":"dist/index.d.ts","scripts":{"build":"tsc","prepublishOnly":"npm run build","test":"jest","watch":"tsc --watch","dev":"nodemon --watch src --ext ts,tsx --exec 'npm run build && yalc push'","yalc:publish":"npm run build && yalc publish","yalc:push":"npm run build && yalc push"},"keywords":["laravel","api"],"author":{"name":"Blue Flamingos"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/blueflamingos/laravel-client.git"},"publishConfig":{"access":"public"},"devDependencies":{"@types/node":"^22.15.1","nodemon":"^3.1.10","typescript":"^5.8.3"},"_id":"@blueflamingos/laravel-client@1.6.0","gitHead":"a280c7de73b8b27c5419e5e401e7382485148fb9","bugs":{"url":"https://github.com/blueflamingos/laravel-client/issues"},"homepage":"https://github.com/blueflamingos/laravel-client#readme","_nodeVersion":"20.19.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-oP4FZaFY8kh3KNGFnrJAfyfrhh+hLVQzh3zETB1xzQNU+0Afstm16oZuR7q4XxdthgNMk0CnLWHtWNxxDMbbyA==","shasum":"40e8969c4335749f31bbdbb51ba1fb773048985c","tarball":"https://registry.npmjs.org/@blueflamingos/laravel-client/-/laravel-client-1.6.0.tgz","fileCount":6,"unpackedSize":43312,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCICDNnpTpkDGFcXqx2Ysy+4ROKFmt39OYZN9qZPmV9YkTAiA/bpnbNZxIC6LCOD6yJecYb62CJtcKdJXUoYuRbmULRg=="}]},"_npmUser":{"name":"blueflamingos-dev","email":"development@blueflamingos.nl"},"directories":{},"maintainers":[{"name":"blueflamingos-dev","email":"development@blueflamingos.nl"},{"name":"rjvandoesburg","email":"rjvandoesburg@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/laravel-client_1.6.0_1780988156614_0.6625038471396592"},"_hasShrinkwrap":false}},"time":{"created":"2025-09-08T06:41:52.899Z","modified":"2026-06-09T06:55:56.905Z","1.5.0":"2025-09-08T06:41:53.252Z","1.6.0":"2026-06-09T06:55:56.774Z"},"bugs":{"url":"https://github.com/blueflamingos/laravel-client/issues"},"author":{"name":"Blue Flamingos"},"license":"MIT","homepage":"https://github.com/blueflamingos/laravel-client#readme","keywords":["laravel","api"],"repository":{"type":"git","url":"git+https://github.com/blueflamingos/laravel-client.git"},"description":"Laravel client for JavaScript/TypeScript","maintainers":[{"name":"blueflamingos-dev","email":"development@blueflamingos.nl"},{"name":"rjvandoesburg","email":"rjvandoesburg@gmail.com"}],"readme":"<p align=\"center\"><img src=\"/blue-flamingos-logo.png\" alt=\"Blue Flamingos\"></p>\n\n# Laravel Client\n\nA lightweight TypeScript client for interacting with Laravel Sanctum-protected APIs in SPA mode. Designed to work smoothly with NextJS and other frontend frameworks.\n\n[![npm version](https://img.shields.io/npm/v/@blueflamingos/laravel-client.svg)](https://www.npmjs.com/package/@blueflamingos/laravel-client)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)\n\n## Features\n\n- 🔒 Seamless integration with Laravel Sanctum SPA authentication\n- 🔄 Support for all common HTTP methods (GET, POST, PUT, PATCH, DELETE)\n- 📦 Works with JSON, FormData, or plain text request bodies\n- 🍪 Automatic CSRF token handling and cookie management\n- 🔑 Flexible authentication with Bearer tokens and token resolvers\n- ⚡ NextJS cache tagging support for App Router\n- 🔗 Full TypeScript support with custom response types\n- 🛠️ Built-in Laravel authentication helpers\n\n## Installation\n\n```bash\nnpm install @blueflamingos/laravel-client\n```\n\nor\n\n```bash\nyarn add @blueflamingos/laravel-client\n```\n\n## Basic Usage\n\n```typescript\nimport Laravel from '@blueflamingos/laravel-client';\n\nconst laravel = new Laravel(process.env.NEXT_PUBLIC_LARAVEL_URL);\n\n// Make API requests\nconst users = await laravel.get('/api/users');\nconst user = await laravel.post('/api/users', { name: 'John Doe', email: 'john@example.com' });\n```\n\n## API Reference\n\n### Constructor\n\n```typescript\nconst api = new Laravel(url: string);\n```\n\nCreates a new Laravel client instance. The URL parameter is required and should point to your Laravel application's base URL.\n\n### Authentication Configuration\n\n#### Bearer Token Authentication\n\n```typescript\n// Set a static bearer token\nlaravel.withToken('your-bearer-token');\n\n// Set a token resolver for dynamic tokens\nlaravel.setTokenResolver(async () => {\n  const session = await getSession();\n  return session?.accessToken || null;\n});\n\n// Clear the token\nlaravel.withToken(null);\n```\n\n#### CSRF Token Handling\n\n```typescript\n// Get CSRF cookie from Laravel Sanctum\nawait laravel.csrf();\n\n// Manually set CSRF token\nlaravel.withCSRFToken('csrf-token-value');\n```\n\n#### Cookie Management\n\n```typescript\n// Set cookies manually (useful for SSR)\nlaravel.withCookies('session_cookie=value; other_cookie=value2');\n\n// Clear cookies\nlaravel.withCookies(null);\n```\n\n#### Custom Headers\n\n```typescript\n// Add one or more custom headers to the next request. Chainable, and applied\n// after the built-in headers so they can override them. Reset after each request.\nlaravel.withHeaders({ 'X-Cart-Token': token }).get('/api/carts');\n```\n\n### HTTP Methods\n\n#### GET Requests\n\n```typescript\n// Simple GET request\nconst response = await laravel.get('/api/users');\nconsole.log(response.data); // Array of users\nconsole.log(response.success); // true if 2xx status\n\n// GET with query parameters (object)\nconst response = await laravel.get('/api/users', {\n  params: { search: 'keyword', page: 1, per_page: 10 }\n});\n\n// GET with raw query string\nconst response = await laravel.get('/api/users', {\n  params: 'search=keyword&page=1&per_page=10'\n});\n\n// With NextJS cache options\nconst response = await laravel.get('/api/users', {\n  params: { active: true },\n  next: {\n    tags: ['users'],\n    revalidate: 60,\n    cache: 'force-cache'\n  }\n});\n```\n\n#### POST/PUT/PATCH/DELETE Requests\n\n```typescript\n// JSON body\nconst response = await laravel.post('/api/users', { \n  name: 'John', \n  email: 'john@example.com' \n});\n\n// FormData (automatically detected)\nconst formData = new FormData();\nformData.append('name', 'John');\nformData.append('avatar', fileInput.files[0]);\nconst response = await laravel.post('/api/users', formData);\n\n// Plain text body\nconst response = await laravel.post('/api/webhook', 'raw text data');\n\n// Blob or ArrayBuffer\nconst response = await laravel.post('/api/upload', blob);\n\n// With NextJS cache options\nconst response = await laravel.post('/api/users', data, {\n  tags: ['users'],\n  cache: 'no-store'\n});\n\n// Other HTTP methods work the same way\nawait laravel.put('/api/users/1', userData);\nawait laravel.patch('/api/users/1', { name: 'Jane' });\nawait laravel.delete('/api/users/1');\n```\n\n### Response Format\n\nAll methods return a `LaravelResponse<T>` object:\n\n```typescript\ninterface LaravelResponse<T = any> {\n  data: T;                    // Response data\n  status: number;             // HTTP status code\n  statusText: string;         // HTTP status text\n  headers: Record<string, string>; // Response headers\n  config: RequestInit;        // Request configuration\n  request?: any;              // Original Response object\n  success: boolean;           // true for 2xx status codes\n}\n```\n\n### Built-in Authentication Helpers\n\nThe client includes convenient methods for common Laravel authentication flows:\n\n```typescript\n// Login\nconst response = await laravel.login('user@example.com', 'password');\nif (response.success) {\n  console.log('Login successful', response.data);\n}\n\n// Register\nconst response = await laravel.register({\n  name: 'John Doe',\n  email: 'john@example.com',\n  password: 'secret',\n  password_confirmation: 'secret'\n});\n\n// Send email verification notification\nawait laravel.sendVerificationNotification('user@example.com');\n\n// Verify email\nawait laravel.verifyEmail(userId, hash, {\n  expires: '1234567890',\n  signature: 'signature-hash'\n});\n\n// Forgot password\nawait laravel.forgotPassword('user@example.com');\n\n// Reset password\nawait laravel.resetPassword({\n  token: 'reset-token',\n  email: 'user@example.com',\n  password: 'newpassword',\n  password_confirmation: 'newpassword'\n});\n\n// Update password (authenticated)\nawait laravel.withToken(token).updatePassword({\n  password: 'currentpassword',\n  new_password: 'newpassword',\n  new_password_confirmation: 'newpassword'\n});\n\n// Update account (authenticated)\nawait laravel.withToken(token).updateAccount({\n  name: 'New Name',\n  email: 'newemail@example.com'\n});\n```\n\n### Utility Methods\n\n```typescript\n// Get full URL for a path\nconst url = laravel.getUri('/api/users'); // \"https://api.example.com/api/users\"\nconst url = laravel.getUri(); // \"https://api.example.com/\"\n```\n\n## NextJS Integration\n\nThis client has special support for NextJS App Router's data fetching and caching mechanisms:\n\n### Client-side Component\n\n```typescript\n'use client';\n\nimport { useState, useEffect } from 'react';\nimport Laravel from '@blueflamingos/laravel-client';\n\nconst api = new Laravel(process.env.NEXT_PUBLIC_LARAVEL_URL!);\n\nexport default function UserProfile() {\n  const [user, setUser] = useState(null);\n  \n  useEffect(() => {\n    const fetchUser = async () => {\n      // Set up authentication\n      api.setTokenResolver(async () => {\n        const session = await getSession();\n        return session?.accessToken || null;\n      });\n      \n      const response = await api.get('/api/user');\n      if (response.success) {\n        setUser(response.data);\n      }\n    };\n    \n    fetchUser();\n  }, []);\n  \n  if (!user) return <div>Loading...</div>;\n  \n  return <div>Welcome, {user.name}!</div>;\n}\n```\n\n### Server Component with SSR\n\n```typescript\nimport Laravel from '@blueflamingos/laravel-client';\nimport { cookies } from 'next/headers';\n\nconst api = new Laravel(process.env.LARAVEL_API_URL!);\n\nexport default async function UsersPage() {\n  const response = await api\n    .withCookies(cookies().toString())\n    .get('/api/users', {\n      next: {\n        tags: ['users'],\n        revalidate: 60\n      }\n    });\n  \n  if (!response.success) {\n    return <div>Error loading users</div>;\n  }\n  \n  return (\n    <div>\n      {response.data.map(user => (\n        <div key={user.id}>{user.name}</div>\n      ))}\n    </div>\n  );\n}\n```\n\n### Server Actions with Revalidation\n\n```typescript\n'use server';\n\nimport { revalidateTag } from 'next/cache';\nimport Laravel from '@blueflamingos/laravel-client';\n\nconst api = new Laravel(process.env.LARAVEL_API_URL!);\n\nexport async function createUser(formData: FormData) {\n  const response = await api.post('/api/users', {\n    name: formData.get('name'),\n    email: formData.get('email')\n  });\n  \n  if (response.success) {\n    revalidateTag('users');\n  }\n  \n  return response;\n}\n```\n\n## TypeScript Support\n\nThe client includes full TypeScript support with generics:\n\n```typescript\n// Define your data types\ninterface User {\n  id: number;\n  name: string;\n  email: string;\n  created_at: string;\n}\n\ninterface ApiResponse<T> {\n  data: T[];\n  meta: {\n    current_page: number;\n    total: number;\n  };\n}\n\n// Use with typed responses\nconst response = await api.get<ApiResponse<User>>('/api/users');\nconsole.log(response.data.data); // User[]\nconsole.log(response.data.meta.total); // number\n\n// Authentication responses\ninterface LoginResponse {\n  user: User;\n  token: string;\n}\n\nconst loginResponse = await api.login<LoginResponse>('email', 'password');\nif (loginResponse.success) {\n  console.log(loginResponse.data.user.name);\n  console.log(loginResponse.data.token);\n}\n```\n\n## Error Handling\n\n```typescript\nconst response = await laravel.get('/api/users');\n\nif (!response.success) {\n  console.error('Request failed:', response.status, response.statusText);\n  console.error('Error data:', response.data);\n} else {\n  console.log('Users:', response.data);\n}\n\n// Or handle specific status codes\nswitch (response.status) {\n  case 401:\n    // Unauthorized - redirect to login\n    break;\n  case 403:\n    // Forbidden - show access denied\n    break;\n  case 422:\n    // Validation errors\n    console.log('Validation errors:', response.data.errors);\n    break;\n  default:\n    // Handle other errors\n}\n```\n\n## Common Patterns\n\n### Authentication Flow\n\n```typescript\n// 1. Get CSRF token (for SPA mode)\nawait laravel.csrf();\n\n// 2. Login\nconst loginResponse = await laravel.login(email, password);\n\nif (loginResponse.success) {\n  // 3. Set token for subsequent requests\n  laravel.withToken(loginResponse.data.token);\n  \n  // 4. Make authenticated requests\n  const userResponse = await laravel.get('/api/user');\n}\n```\n\n### File Upload with Progress\n\n```typescript\nconst formData = new FormData();\nformData.append('file', file);\nformData.append('title', 'My Upload');\n\nconst response = await laravel.post('/api/uploads', formData);\n\nif (response.success) {\n  console.log('Upload successful:', response.data);\n}\n```\n\n### Validation Error Handling\n\n```typescript\nconst response = await laravel.post('/api/users', userData);\n\nif (response.status === 422) {\n  // Laravel validation errors\n  const errors = response.data.errors;\n  Object.keys(errors).forEach(field => {\n    console.log(`${field}: ${errors[field].join(', ')}`);\n  });\n}\n```\n\n## License\n\nMIT Licensed. Copyright (c) Blue Flamingos.\n","readmeFilename":"README.md"}