npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@deep-document-search/api-client-typescript-v2

v1.0.15

Published

TypeScript client generated from Swagger/OpenAPI specification

Readme

API Client Typescript V2

A TypeScript client library generated from the OpenAPI/Swagger specification for the backend API. This client provides type-safe access to all API endpoints with comprehensive TypeScript support.

Table of Contents

Installation

npm install
npm run build

Setup

// 完整导入所有方法和类型
import { 
  // 方法
  postAuthLogin,
  getOrganizations,
  // 类型 
  type Options,
  type Document,
  type UserResponse
} from '@deep-document-search/api-client-typescript-v2';

// 或者只导入需要的模块
import { postAuthLogin, type LoginRequest } from '@deep-document-search/api-client-typescript-v2';

// 默认客户端已经预配置,所有API函数都使用这个客户端实例
// 默认基础URL: localhost:8080/api/v1

Authentication

Authentication Token Configuration

有三种方式可以设置认证令牌,推荐使用方式3(直接设置请求头):

方式1:全局客户端配置(持久性配置)

import { client, getOrganizations } from '@deep-document-search/api-client-typescript-v2';

// 配置全局认证设置
client.setConfig({
  security: [{ name: 'Authorization', type: 'apiKey' }],
  auth: async () => {
    // 返回认证令牌(从localStorage或其他存储获取)
    return localStorage.getItem('authToken');
  }
});

// 现在所有API调用都会自动添加认证头
await getOrganizations(); // ✅ 自动包含认证

方式2:请求级认证配置(按需配置)

import { getOrganizations } from '@deep-document-search/api-client-typescript-v2';

// 在特定请求中配置认证
await getOrganizations({
  security: [{ name: 'Authorization', type: 'apiKey' }],
  auth: localStorage.getItem('authToken') // 直接传递令牌
});

方式3:直接设置请求头(推荐,最简单直接)

import { getOrganizations } from '@deep-document-search/api-client-typescript-v2';

await getOrganizations({
  headers: {
    'Authorization': `Bearer ${localStorage.getItem('authToken')}`
  }
});

推荐使用方式3的原因:

  • 简单直观:无需理解复杂的security配置
  • 灵活控制:每个请求独立管理认证
  • 调试友好:明确可见认证头内容
  • 兼容性好:适用于所有HTTP客户端

Login & Token Storage

import { postAuthLogin, getUsersById, type LoginRequest, type LoginResponse, type UserResponse } from '@deep-document-search/api-client-typescript-v2';

// 1. Login and get token with typed request const loginRequest: LoginRequest = { username: 'your-username', password: 'your-password' };

const loginResult = await postAuthLogin({ body: loginRequest });

// 2. Store token in localStorage (for web applications) if (loginResult.data && 'token' in loginResult.data) { const loginResponse = loginResult.data as LoginResponse; localStorage.setItem('authToken', loginResponse.token!); }

// 3. Retrieve token for subsequent requests const getAuthHeaders = () => ({ 'Authorization': Bearer ${localStorage.getItem('authToken')} });

// 4. Use in API calls with typed response const userProfile = await getUsersById({ path: { id: 'current-user-id' }, headers: getAuthHeaders() });

const userData: UserResponse = userProfile.data!;

const userProfile: UserResponse = userProfileResponse.data!;


### Token Refresh Strategy
```typescript
import { 
  postAuthRefresh,
  type RefreshTokenRequest,
  type LoginResponse
} from '@deep-document-search/api-client-typescript-v2';

// Check token expiration and refresh if needed
async function refreshTokenIfExpired(): Promise<string> {
  const token = localStorage.getItem('authToken');
  if (token && isTokenExpired(token)) {
    const refreshRequest: RefreshTokenRequest = {
      refreshToken: localStorage.getItem('refreshToken') || ''
    };
    
    const refreshResponse = await postAuthRefresh({
      body: refreshRequest
    });
    
    if (refreshResponse.data && 'token' in refreshResponse.data) {
      const loginResponse = refreshResponse.data as LoginResponse;
      localStorage.setItem('authToken', loginResponse.token);
      return loginResponse.token;
    }
  }
  return token || '';
}

// Wrap API calls with token refresh
async function safeApiCall<T>(apiFunction: (token: string) => Promise<T>): Promise<T> {
  const token = await refreshTokenIfExpired();
  return apiFunction(token);
}

Using Authentication in Requests

Most API endpoints require authentication. Include the JWT token in the Authorization header:

import { 
  getOrganizations,
  type ListOrganizationsResponse
} from '@deep-document-search/api-client-typescript-v2';

const organizationsResponse: ListOrganizationsResponse = await getOrganizations({
  headers: {
    'Authorization': `Bearer ${token}`
  }
});

const organizations = organizationsResponse.data?.organizations || []);

API Modules

Authentication API

Authentication endpoints for user login, logout, token refresh, and email verification.

| Method | Endpoint | Description | |--------|----------|-------------| | postAuthLogin | /auth/login | Authenticate user and return JWT token | | postAuthLogout | /auth/logout | Revoke current user session | | postAuthRefresh | /auth/refresh | Refresh JWT token using refresh token | | postAuthResendVerification | /auth/resend-verification | Resend email verification | | postAuthVerifyEmail | /auth/verify-email | Verify user email address | | getAuthVerificationStatusByEmail | /auth/verification-status/{email} | Check email verification status |

Search API

Search and search index management for configuring search clusters and indices.

Search Indices

| Method | Endpoint | Description | |--------|----------|-------------| | getApiV1SearchIndices | /api/v1/search-indices | List search indices with pagination | | postApiV1SearchIndices | /api/v1/search-indices | Create new search index | | deleteApiV1SearchIndicesById | /api/v1/search-indices/{id} | Delete search index | | getApiV1SearchIndicesById | /api/v1/search-indices/{id} | Get search index by ID | | putApiV1SearchIndicesById | /api/v1/search-indices/{id} | Update search index | | postApiV1SearchIndicesByIdAssociate | /api/v1/search-indices/{id}/associate | Associate index with search | | postApiV1SearchIndicesByIdSync | /api/v1/search-indices/{id}/sync | Sync index with Elasticsearch |

Searches

| Method | Endpoint | Description | |--------|----------|-------------| | getApiV1Searches | /api/v1/searches | List searches with pagination | | postApiV1Searches | /api/v1/searches | Create new search | | deleteApiV1SearchesById | /api/v1/searches/{id} | Delete search | | getApiV1SearchesById | /api/v1/searches/{id} | Get search by ID | | putApiV1SearchesById | /api/v1/searches/{id} | Update search | | getApiV1SearchesByIdIndices | /api/v1/searches/{id}/indices | List search indices by search ID |

Document Management API

Comprehensive document handling including upload, download, and batch operations with S3 integration.

Single Document Operations

| Method | Endpoint | Description | |--------|----------|-------------| | getWorkspaceDocuments | /workspace/documents | List documents with filtering | | postWorkspaceDocuments | /workspace/documents | Upload document (multipart/form-data) | | deleteWorkspaceDocumentsById | /workspace/documents/{id} | Delete document | | getWorkspaceDocumentsById | /workspace/documents/{id} | Get document details | | putWorkspaceDocumentsById | /workspace/documents/{id} | Update document metadata | | postWorkspaceDocumentsByIdAssociate | /workspace/documents/{id}/associate | Associate document with item | | deleteWorkspaceDocumentsByIdDisassociateByItemId | /workspace/documents/{id}/disassociate/{itemId} | Disassociate document from item | | getWorkspaceDocumentsByIdDownload | /workspace/documents/{id}/download | Download document file |

Batch Document Operations

| Method | Endpoint | Description | |--------|----------|-------------| | deleteWorkspaceDocumentsBatch | /workspace/documents/batch | Batch delete documents | | postWorkspaceDocumentsBatch | /workspace/documents/batch | Batch create documents | | putWorkspaceDocumentsBatch | /workspace/documents/batch | Batch update documents | | postWorkspaceDocumentsBatchConfirmUpload | /workspace/documents/batch-confirm-upload | Confirm batch uploads | | postWorkspaceDocumentsBatchDownloadUrls | /workspace/documents/batch-download-urls | Generate batch download URLs | | postApiV1DocumentsBatchUploadUrls | /api/v1/documents/batch-upload-urls | Generate batch upload URLs | | postWorkspaceDocumentsBatchUploadUrls | /workspace/documents/batch-upload-urls | Generate batch upload URLs | | postWorkspaceDocumentsBatchUploads | /workspace/documents/batch-uploads | Batch upload documents |

Workspace API

Workspace management for organizing projects and resources.

| Method | Endpoint | Description | |--------|----------|-------------| | getWorkspaceWorkspaces | /workspace/workspaces | List workspaces with filtering | | postWorkspaceWorkspaces | /workspace/workspaces | Create new workspace | | deleteWorkspaceWorkspacesById | /workspace/workspaces/{id} | Delete workspace | | getWorkspaceWorkspacesById | /workspace/workspaces/{id} | Get workspace by ID | | putWorkspaceWorkspacesById | /workspace/workspaces/{id} | Update workspace |

Item Management API

Item management within projects, supporting associations with documents.

Single Item Operations

| Method | Endpoint | Description | |--------|----------|-------------| | getWorkspaceItems | /workspace/items | List items with filtering | | postWorkspaceItems | /workspace/items | Create new item | | deleteWorkspaceItemsById | /workspace/items/{id} | Delete item | | getWorkspaceItemsById | /workspace/items/{id} | Get item by ID | | putWorkspaceItemsById | /workspace/items/{id} | Update item | | postWorkspaceItemsByIdAssociate | /workspace/items/{id}/associate | Associate item with document | | deleteWorkspaceItemsByIdDisassociateByDocId | /workspace/items/{id}/disassociate/{docId} | Disassociate item from document |

Batch Item Operations

| Method | Endpoint | Description | |--------|----------|-------------| | deleteWorkspaceItemsBatch | /workspace/items/batch | Batch delete items | | postWorkspaceItemsBatch | /workspace/items/batch | Batch create items | | putWorkspaceItemsBatch | /workspace/items/batch | Batch update items |

Project Management API

Project management within workspaces.

| Method | Endpoint | Description | |--------|----------|-------------| | getWorkspaceProjects | /workspace/projects | List projects with filtering | | postWorkspaceProjects | /workspace/projects | Create new project | | deleteWorkspaceProjectsById | /workspace/projects/{id} | Delete project | | getWorkspaceProjectsById | /workspace/projects/{id} | Get project by ID | | putWorkspaceProjectsById | /workspace/projects/{id} | Update project |

Organization Management API

Organization-level resource management.

| Method | Endpoint | Description | |--------|----------|-------------| | getOrganizations | /organizations | List organizations with filtering | | postOrganizations | /organizations | Create new organization | | deleteOrganizationsById | /organizations/{id} | Delete organization | | getOrganizationsById | /organizations/{id} | Get organization by ID | | putOrganizationsById | /organizations/{id} | Update organization |

User Management API

User administration and audit logging.

| Method | Endpoint | Description | |--------|----------|-------------| | getUsers | /users | List users with pagination | | postUsers | /users | Create new user | | deleteUsersById | /users/{id} | Delete user | | getUsersById | /users/{id} | Get user by ID | | putUsersById | /users/{id} | Update user | | getUsersByIdAuditLogs | /users/{id}/audit-logs | Get user audit logs | | postUsersOrganization | /users/organization | Create user within organization |

Complete Import Guide

Authentication API

postAuthLogin        // 用户登录
postAuthLogout       // 用户登出  
postAuthRefresh      // 刷新令牌
postAuthResendVerification  // 重发验证邮件
postAuthVerifyEmail  // 验证邮箱
getAuthVerificationStatusByEmail // 检查验证状态

Organization Management API

getOrganizations      // 获取组织列表
postOrganizations     // 创建组织
deleteOrganizationsById // 删除组织
getOrganizationsById  // 获取组织详情  
putOrganizationsById  // 更新组织

User Management API

getUsers              // 获取用户列表
postUsers             // 创建用户
deleteUsersById       // 删除用户
getUsersById          // 获取用户详情
putUsersById          // 更新用户
getUsersByIdAuditLogs // 获取用户审计日志
postUsersOrganization // 在组织内创建用户

Workspace Management API

getWorkspaceWorkspaces     // 获取工作区列表
postWorkspaceWorkspaces    // 创建工作区
deleteWorkspaceWorkspacesById // 删除工作区  
getWorkspaceWorkspacesById // 获取工作区详情
putWorkspaceWorkspacesById // 更新工作区

Project Management API

getWorkspaceProjects      // 获取项目列表
postWorkspaceProjects     // 创建项目
deleteWorkspaceProjectsById // 删除项目
getWorkspaceProjectsById  // 获取项目详情
putWorkspaceProjectsById  // 更新项目

Item Management API

getWorkspaceItems         // 获取项目项列表
postWorkspaceItems        // 创建项目项
deleteWorkspaceItemsById  // 删除项目项
getWorkspaceItemsById     // 获取项目项详情
putWorkspaceItemsById     // 更新项目项
postWorkspaceItemsByIdAssociate        // 关联文档
deleteWorkspaceItemsByIdDisassociateByDocId // 解除关联

Document Management API

getWorkspaceDocuments     // 获取文档列表
postWorkspaceDocuments    // 上传文档
deleteWorkspaceDocumentsById // 删除文档
getWorkspaceDocumentsById // 获取文档详情
putWorkspaceDocumentsById // 更新文档元数据
postWorkspaceDocumentsByIdAssociate    // 关联文档到项目项
deleteWorkspaceDocumentsByIdDisassociateByItemId // 解除关联
getWorkspaceDocumentsByIdDownload // 下载文档

Search API

getApiV1SearchIndices     // 获取搜索索引
postApiV1SearchIndices    // 创建搜索索引
deleteApiV1SearchIndicesById // 删除索引
getApiV1SearchIndicesById // 获取索引详情
putApiV1SearchIndicesById // 更新索引
postApiV1SearchIndicesByIdAssociate // 关联索引到搜索
postApiV1SearchIndicesByIdSync    // 同步索引

getApiV1Searches          // 获取搜索配置
postApiV1Searches         // 创建搜索配置  
deleteApiV1SearchesById   // 删除搜索配置
getApiV1SearchesById      // 获取搜索详情
putApiV1SearchesById      // 更新搜索配置
getApiV1SearchesByIdIndices // 按搜索ID获取索引

Domain Types

Core Types

Options                 // 请求选项
ClientOptions           // 客户端配置
ErrorResponse           // 错误响应
SuccessResponse         // 成功响应

Authentication Types

LoginRequest            // 登录请求
LoginResponse           // 登录响应
RefreshTokenRequest     // 刷新令牌请求

User & Organization Types

UserResponse            // 用户响应
CreateUserRequest       // 创建用户请求  
UpdateUserRequest       // 更新用户请求
Organization            // 组织
OrganizationResponse    // 组织响应
CreateOrganizationRequest // 创建组织请求
UpdateOrganizationRequest // 更新组织请求

Document Types

Document                // 文档对象
DocumentStatus          // 文档状态
CreateDocumentRequest   // 创建文档请求
UpdateDocumentRequest   // 更新文档请求
FileUploadRequest       // 文件上传请求
UploadUrlResponse       // 上传URL响应  
DownloadUrlResponse     // 下载URL响应

Project & Item Types

Project                 // 项目
Item                    // 项目项
CreateProjectRequest    // 创建项目请求
UpdateProjectRequest    // 更新项目请求
CreateItemRequest       // 创建项请求
UpdateItemRequest       // 更新项请求

Workspace Types

Workspace               // 工作区
CreateWorkspaceRequest  // 创建工作区请求
UpdateWorkspaceRequest  // 更新工作区请求

Search Types

Search                  // 搜索配置
SearchIndex             // 搜索索引  
SearchCluster           // 搜索集群
CreateSearchRequest     // 创建搜索请求
UpdateSearchRequest     // 更新搜索请求
CreateSearchIndexRequest // 创建索引请求
UpdateSearchIndexRequest // 更新索引请求

Error Handling

The client includes comprehensive error handling with typed error responses:

import { 
  getOrganizations,
  type ListOrganizationsResponse,
  type ErrorResponse
} from '@deep-document-search/api-client-typescript-v2';

try {
  const result: ListOrganizationsResponse = await getOrganizations({
    headers: { 'Authorization': 'Bearer your-token' }
  });
} catch (error: any) {
  if (error.status === 401) {
    console.error('Authentication required');
  } else if (error.status === 404) {
    console.error('Resource not found');
  } else if (error.data) {
    const errorResponse = error.data as ErrorResponse;
    console.error('API Error:', errorResponse.message);
  }
}

Advanced Configuration

Custom Client Configuration

默认客户端已经预配置,但如果需要自定义配置,可以通过以下方式:

import { client } from '@deep-document-search/api-client-typescript-v2';

// 方式1:修改默认客户端配置
client.setConfig({
  baseUrl: 'https://your-api-server.com/api/v1',
  // 其他配置选项...
});

// 使用自定义客户端
import { 
  getOrganizations,
  type ListOrganizationsResponse 
} from '@deep-document-search/api-client-typescript-v2';

const organizationsResponse: ListOrganizationsResponse = await getOrganizations({
  client: client, // 传递自定义客户端
  headers: {
    'Authorization': `Bearer ${token}`
  }
});

Options Parameter

所有API方法都接受一个可选的Options参数,具有以下属性:

interface Options {
  headers?: Record<string, string>;
  client?: Client; // 自定义客户端实例(可选)
  meta?: Record<string, unknown>; // 任意元数据
  // 错误处理
  throwOnError?: boolean;
  // 请求特定配置
  baseUrl?: string; // 基础URL(可选覆盖,优先级高于客户端配置)
  timeout?: number; // 超时时间
}

Examples

Complete Workflow Example

import {
  postAuthLogin,
  getOrganizations,
  postWorkspaceWorkspaces,
  postWorkspaceProjects,
  postWorkspaceDocuments,
  getWorkspaceDocuments,
  // Import request and response types
  type LoginRequest,
  type LoginResponse,
  type ListOrganizationsResponse,
  type Organization,
  type CreateWorkspaceRequest,
  type WorkspaceSuccessResponse,
  type Workspace,
  type CreateProjectRequest,
  type ProjectSuccessResponse,
  type Project,
  type CreateDocumentRequest,
  type DocumentSuccessResponse,
  type Document,
  type ListDocumentsResponse
} from '@deep-document-search/api-client-typescript-v2';

// 1. Authenticate with typed request
const loginRequest: LoginRequest = {
  username: 'admin',
  password: 'password123'
};

const loginResponse = await postAuthLogin({
  body: loginRequest
});

let token: string;
if (loginResponse.data && 'token' in loginResponse.data) {
  const loginData = loginResponse.data as LoginResponse;
  token = loginData.token;
} else {
  throw new Error('Login failed: No token received');
}

const headers = { 'Authorization': `Bearer ${token}` };

// 2. Get organizations with typed response
const organizationsResponse: ListOrganizationsResponse = await getOrganizations({ headers });
const organizations: Organization[] = organizationsResponse.data?.organizations || [];

// 3. Create workspace with typed request and response
const workspaceRequest: CreateWorkspaceRequest = {
  name: 'My Workspace',
  description: 'Test workspace for development'
};

const workspaceResponse: WorkspaceSuccessResponse = await postWorkspaceWorkspaces({
  body: workspaceRequest,
  headers
});
const workspace: Workspace = workspaceResponse;

// 4. Create project with typed request and response
const projectRequest: CreateProjectRequest = {
  name: 'My Project',
  description: 'Test project for API integration',
  workspace_id: workspace.id!,
  owner_id: 'user-id-from-auth'
};

const projectResponse: ProjectSuccessResponse = await postWorkspaceProjects({
  body: projectRequest,
  headers
});
const project: Project = projectResponse;

// 5. Upload document with typed request and response
const documentRequest: CreateDocumentRequest = {
  name: 'api-integration-test-document'
};

const formData = new FormData();
formData.append('name', documentRequest.name);
formData.append('file', fileBlob); // Assume fileBlob is defined

const documentResponse: DocumentSuccessResponse = await postWorkspaceDocuments({
  body: formData,
  headers: {
    ...headers,
    'Content-Type': null
  }
});
const document: Document = documentResponse;

// 6. List documents with typed response
const documentsResponse: ListDocumentsResponse = await getWorkspaceDocuments({ headers });
const documents: Document[] = documentsResponse.documents || [];

Batch Operations Example

import { 
  postApiV1DocumentsBatchUploadUrls,
  type BatchGenerateUploadUrlRequest,
  type BatchGenerateUploadUrlResponse,
  type UploadUrlResponse
} from '@deep-document-search/api-client-typescript-v2';

// Generate batch upload URLs with typed request
const uploadRequest: BatchGenerateUploadUrlRequest = {
  files: [
    {
      file_name: 'document1.pdf',
      file_size: 1024000,
      mime_type: 'application/pdf'
    },
    {
      file_name: 'image.jpg',
      file_size: 2048000,
      mime_type: 'image/jpeg'
    }
  ],
  expiry_minutes: 60
};

const uploadUrlsResponse: BatchGenerateUploadUrlResponse = await postApiV1DocumentsBatchUploadUrls({
  body: uploadRequest,
  headers
});

// Use the presigned URLs to upload files
uploadUrlsResponse.uploads?.forEach(async (urlInfo: UploadUrlResponse) => {
  await fetch(urlInfo.presigned_url!, {
    method: 'PUT',
    body: fileData
  });
});

Best Practices & Advanced Usage

Architecture Overview

This library is built on a modern function-first architecture with the following key characteristics:

  1. Function-Only API: Each API endpoint is exposed as a standalone function
  2. Default Client Pattern: All functions use a pre-configured client instance
  3. Type Safety: Full TypeScript support with comprehensive type definitions
  4. Flexible Configuration: Support for request-level and client-level customization

Pinia Store Integration Best Practices

1. Service Layer Pattern (Recommended)

Create a service layer that encapsulates API calls and provides clean interfaces for your stores:

// services/organizationService.ts
import { 
  getOrganizations, 
  postOrganizations, 
  putOrganizationsById,
  deleteOrganizationsById,
  type Organization,
  type CreateOrganizationRequest,
  type UpdateOrganizationRequest
} from '@deep-document-search/api-client-typescript-v2';

export class OrganizationService {
  static async listOrganizations(headers?: Record<string, string>): Promise<ListOrganizationsResponse> {
    return getOrganizations({ headers });
  }

  static async createOrganization(data: CreateOrganizationRequest, headers?: Record<string, string>): Promise<OrganizationSuccessResponse> {
    return postOrganizations({ body: data, headers });
  }

  static async updateOrganization(id: string, data: UpdateOrganizationRequest, headers?: Record<string, string>): Promise<OrganizationSuccessResponse> {
    return putOrganizationsById({ 
      path: { id }, 
      body: data, 
      headers 
    });
  }

  static async deleteOrganization(id: string, headers?: Record<string, string>): Promise<void> {
    await deleteOrganizationsById({ 
      path: { id }, 
      headers 
    });
  }
}

2. Pinia Store Implementation

// stores/organizationStore.ts
import { defineStore } from 'pinia';
import { OrganizationService } from '../services/organizationService';
import type { Organization, CreateOrganizationRequest, UpdateOrganizationRequest } from '@deep-document-search/api-client-typescript-v2';

export const useOrganizationStore = defineStore('organizations', {
  state: () => ({
    organizations: [] as Organization[],
    currentOrganization: null as Organization | null,
    isLoading: false,
    error: null as string | null
  }),

  getters: {
    organizationById: (state) => (id: string) => {
      return state.organizations.find(org => org.id === id);
    },
    activeOrganizations: (state) => {
      return state.organizations.filter(org => org.isActive);
    }
  },

  actions: {
    async loadOrganizations(authToken: string) {
      this.isLoading = true;
      this.error = null;
      
      try {
      const response: ListOrganizationsResponse = await OrganizationService.listOrganizations({
        'Authorization': `Bearer ${authToken}`
      });
      
      if (response.data && response.data.organizations) {
        this.organizations = response.data.organizations;
      }
      } catch (error) {
        this.error = error.message || 'Failed to load organizations';
        throw error;
      } finally {
        this.isLoading = false;
      }
    },

    async createOrganization(data: CreateOrganizationRequest, authToken: string) {
      this.isLoading = true;
      this.error = null;
      
      try {
        const response: OrganizationSuccessResponse = await OrganizationService.createOrganization(data, {
          'Authorization': `Bearer ${authToken}`
        });
        
        if (response) {
          this.organizations.push(response);
          return response;
        }
      } catch (error) {
        this.error = error.message || 'Failed to create organization';
        throw error;
      } finally {
        this.isLoading = false;
      }
    },

    async updateOrganization(id: string, data: UpdateOrganizationRequest, authToken: string) {
      this.isLoading = true;
      this.error = null;
      
      try {
        const response: OrganizationSuccessResponse = await OrganizationService.updateOrganization(id, data, {
          'Authorization': `Bearer ${authToken}`
        });
        
        if (response) {
          const index = this.organizations.findIndex(org => org.id === id);
          if (index !== -1) {
            this.organizations[index] = response;
          }
          return response;
        }
      } catch (error) {
        this.error = error.message || 'Failed to update organization';
        throw error;
      } finally {
        this.isLoading = false;
      }
    }
  }
});

3. Component Usage with Pinia

<!-- components/OrganizationList.vue -->
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { useOrganizationStore } from '../stores/organizationStore';
import { useAuthStore } from '../stores/authStore';

const organizationStore = useOrganizationStore();
const authStore = useAuthStore();

onMounted(async () => {
  if (authStore.isAuthenticated) {
    await organizationStore.loadOrganizations(authStore.token);
  }
});

const newOrganizationName = ref('');

async function handleCreateOrganization() {
  if (!newOrganizationName.value.trim()) return;
  
  try {
    await organizationStore.createOrganization(
      { name: newOrganizationName.value },
      authStore.token
    );
    newOrganizationName.value = '';
  } catch (error) {
    console.error('Failed to create organization:', error);
  }
}
</script>

<template>
  <div class="organization-list">
    <div v-if="organizationStore.isLoading">Loading organizations...</div>
    <div v-else-if="organizationStore.error" class="error">
      {{ organizationStore.error }}
    </div>
    <div v-else>
      <h3>Organizations</h3>
      <ul>
        <li v-for="org in organizationStore.organizations" :key="org.id">
          {{ org.name }} - {{ org.description }}
        </li>
      </ul>
      
      <div class="create-form">
        <input v-model="newOrganizationName" placeholder="New organization name">
        <button @click="handleCreateOrganization" :disabled="!newOrganizationName.trim()">
          Create Organization
        </button>
      </div>
    </div>
  </div>
</template>

Advanced Pinia Colada Integration

Plugin Registration and Global Configuration

First, register Pinia Colada in your main application file:

// main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import { PiniaColada } from '@pinia/colada'
import App from './App.vue'

const app = createApp(App)
const pinia = createPinia()

// Register Pinia Colada plugin with global configuration
app.use(pinia)
app.use(PiniaColada, {
  // Global request interceptor
  onRequest: (request) => {
    const token = localStorage.getItem('authToken')
    if (token) {
      request.headers = {
        ...request.headers,
        Authorization: `Bearer ${token}`
      }
    }
    return request
  },
  // Token refresh handler for 401 errors
  onResponseError: async (error) => {
    if (error.status === 401) {
      // Handle token refresh logic here
      const newToken = await refreshToken()
      localStorage.setItem('authToken', newToken)
      // The original request will be retried automatically
    }
    throw error
  }
})

app.mount('#app')

Component Usage with Pinia Colada

<script setup>
import { useQuery, useMutation } from '@pinia/colada'
import { 
  getOrganizations, 
  postOrganizations,
  type CreateOrganizationRequest
} from '@deep-document-search/api-client-typescript-v2'
import { useAuthStore } from '../stores/authStore'

const authStore = useAuthStore()

// Query for organizations with automatic caching and typed response
const { 
  data: organizationsResponse,
  isLoading, 
  error,
  refetch 
} = useQuery({
  key: () => ['organizations', authStore.token], // Cache key includes token for different users
  query: () => getOrganizations({
    headers: { 'Authorization': `Bearer ${authStore.token}` }
  }),
  // Cache settings
  staleTime: 5 * 60 * 1000, // 5 minutes
  cacheTime: 10 * 60 * 1000, // 10 minutes
})

// Extract organizations from response for cleaner usage
const organizations = organizationsResponse?.data?.organizations || [];

// Mutation for creating organizations
const createOrgMutation = useMutation({
  mutation: (data: CreateOrganizationRequest) => 
    postOrganizations({
      body: data,
      headers: { 'Authorization': `Bearer ${authStore.token}` }
    }),
  // Auto-invalidate related queries after mutation
  onSuccess: () => {
    // This will trigger a refetch of the organizations query
    refetch()
  }
})

async function handleCreate(name: string) {
  await createOrgMutation.mutate({ name })
  // organizations query will automatically refetch due to onSuccess
}
</script>

<template>
  <div>
    <div v-if="isLoading">Loading organizations...</div>
    <div v-else-if="error" class="error">{{ error.message }}</div>
    <div v-else>
      <ul>
        <li v-for="org in organizations" :key="org.id">
          {{ org.name }}
        </li>
      </ul>
    </div>
  </div>
</template>

Error Handling Best Practices

Centralized Error Handling

// utils/errorHandler.ts
export class ApiErrorHandler {
  static handleApiError(error: any, context: string): string {
    let userMessage = 'An unexpected error occurred';
    
    if (error.status === 401) {
      userMessage = 'Authentication required. Please log in again.';
      // Trigger logout flow
      this.handleUnauthorized();
    } else if (error.status === 403) {
      userMessage = 'You do not have permission to perform this action.';
    } else if (error.status === 404) {
      userMessage = 'The requested resource was not found.';
    } else if (error.data?.message) {
      userMessage = error.data.message;
    }
    
    console.error(`API Error in ${context}:`, error);
    return userMessage;
  }
  
  static handleUnauthorized() {
    // Clear auth state and redirect to login
    localStorage.removeItem('authToken');
    window.location.href = '/login';
  }
}

// Usage in store
async function loadOrganizations(authToken: string) {
  try {
    const response = await OrganizationService.listOrganizations({
      'Authorization': `Bearer ${authToken}`
    });
    return response.data?.organizations || [];
  } catch (error) {
    const message = ApiErrorHandler.handleApiError(error, 'loading organizations');
    throw new Error(message);
  }
}

Performance Optimization

Request Batching

// Batch multiple related requests
async function loadDashboardData(authToken: string) {
  const headers = { 'Authorization': `Bearer ${authToken}` };
  
  const [organizations, projects, documents] = await Promise.all([
    getOrganizations({ headers }),
    getWorkspaceProjects({ headers }),
    getWorkspaceDocuments({ headers })
  ]);
  
  return {
    organizations: organizations.data?.organizations || [],
    projects: projects.data?.projects || [],
    documents: documents.data?.documents || []
  };
}

Optimistic Updates

// Store with optimistic updates
async updateOrganization(id: string, data: UpdateOrganizationRequest, authToken: string) {
  // Optimistically update UI
  const original = this.organizations.find(org => org.id === id);
  if (original) {
    const optimistic = { ...original, ...data };
    this.organizations = this.organizations.map(org => 
      org.id === id ? optimistic : org
    );
  }
  
  try {
    const response = await OrganizationService.updateOrganization(id, data, {
      'Authorization': `Bearer ${authToken}`
    });
    // Update with server response
    if (response.data) {
      this.organizations = this.organizations.map(org => 
        org.id === id ? response.data! : org
      );
    }
  } catch (error) {
    // Revert optimistic update on error
    if (original) {
      this.organizations = this.organizations.map(org => 
        org.id === id ? original : org
      );
    }
    throw error;
  }
}

This architecture provides excellent separation of concerns, type safety, and maintainability for Vue/Pinia applications.

Pinia Colada Deep Dive

How Pinia Colada Actually Works

Pinia Colada is not a standalone object but a Pinia plugin that provides intelligent data fetching capabilities. Here's the actual architecture:

Architecture Flow

Your Components → useQuery/useMutation hooks → Internal Pinia Colada Cache → API Calls
                            ↓
              Pinia DevTools (for debugging)

Key Concepts Explained

  1. Plugin Registration: Pinia Colada registers itself as a Pinia plugin
  2. Internal Cache: Creates a query cache inside Pinia's store system
  3. Hook Access: Components use useQuery/useMutation to access the cache
  4. Automatic Integration: All query states are visible in Pinia DevTools

Real Usage Pattern (Corrected)

// ✅ Correct: Register once, use hooks everywhere
// main.ts
app.use(PiniaColada)

// Component.vue
import { useQuery } from '@pinia/colada'

const { data, isLoading } = useQuery({
  key: ['data'],
  query: fetchData // Uses the registered Pinia Colada instance
})

Common Misconceptions Clarified

Myth: "I need to create a colada object" Truth: Pinia Colada is a singleton plugin - you register it once and use hooks

Myth: "The colada object is used directly"
Truth: You interact through useQuery/useMutation hooks

Myth: "I need to manage cache manually" Truth: Cache management is automatic through query keys and invalidation

Advanced Pinia Colada Patterns

Store Integration Pattern

// stores/organizationStore.ts
import { defineStore } from 'pinia'
import { defineQuery, defineMutation } from '@pinia/colada'

export const useOrganizationStore = defineStore('organizations', () => {
  // Define reusable queries that automatically use Pinia Colada cache
  const fetchOrganizations = defineQuery({
    key: () => ['organizations'],
    query: () => getOrganizations({ headers })
  })
  
  const createOrganization = defineMutation({
    mutation: (data) => postOrganizations({ body: data, headers }),
    onSuccess: () => {
      // Auto-invalidate organizations query
    }
  })
  
  return { fetchOrganizations, createOrganization }
})

// Usage in component
const orgStore = useOrganizationStore()
const { data, isLoading } = orgStore.fetchOrganizations()

Dynamic Query Patterns

// Dynamic queries based on route parameters
const route = useRoute()
const { data: user } = useQuery({
  key: () => ['user', route.params.id],
  query: () => getUserById(route.params.id)
})

// Paginated queries
const { data: paginatedData } = useQuery({
  key: () => ['items', currentPage.value],
  query: () => getItems({ page: currentPage.value })
})

This architecture provides a seamless data fetching experience without manual cache management.

Publishing the Package

When publishing this package to npm, only the compiled code is included, not the source code. The package is configured to publish only the dist directory and README.md.

Publishing Configuration

The package.json is configured with:

{
  "files": [
    "dist",
    "README.md"
  ],
  "main": "dist/index.js",
  "module": "dist/index.js", 
  "types": "dist/index.d.ts"
}

This ensures that:

  • Only compiled JavaScript files are published (from dist/ directory)
  • TypeScript definitions are included for type safety
  • Source code (src/) is excluded from the published package

Publishing Steps

  1. Build the package:
npm run build
  1. Update version (if needed):
npm version patch  # or minor, major
  1. Publish to npm:
npm publish --access public

File Structure in Published Package

The published package will contain:

dist/
├── client/
│   ├── index.js          # Main entry point
│   ├── index.d.ts        # Type definitions
│   ├── sdk.gen.js        # API methods
│   ├── sdk.gen.d.ts      # API method types
│   ├── types.gen.js      # Type implementations
│   ├── types.gen.d.ts    # Type definitions
│   └── ...other files
README.md

Created Files

scripts/generate-llm-txt.ts - LLM-friendly documentation generator that:

  • Parses the OpenAPI spec from swagger.yaml
  • Generates structured text optimized for LLM consumption
  • Includes API endpoints, type definitions, authentication info, and usage examples
  • Outputs to llm.txt in the project root

typedoc.json - TypeDoc configuration for API documentation

Updated Files

package.json - Added new scripts:

  • npm run docs:generate - Generate llm.txt
  • npm run docs:api - Generate TypeDoc HTML documentation
  • npm run docs:all - Generate both

Added dependencies:

  • tsx - TypeScript execution
  • typedoc - API documentation
  • yaml - YAML parsing

Benefits of Publishing Only Compiled Code

  • Smaller package size: No source code, tests, or development files
  • Better security: Source code remains private
  • Faster downloads: Users download only what they need
  • TypeScript support: Full type definitions included

Development

Regenerating the Client

npm run generate

This will regenerate the client from the OpenAPI specification file (swagger.yaml).

Building

npm run build

Development Mode (Watch)

npm run dev

License

MIT