{"version":3,"sources":["jsdelivr-header.js","/npm/@sthg-sdk/shared.client@1.2.7/src/auth/TokenAuthProvider.ts","/npm/@sthg-sdk/shared.client@1.2.7/src/auth/UsernamePasswordAuthProvider.ts","/npm/@sthg-sdk/shared.client@1.2.7/src/client/HttpClient.ts","/npm/@sthg-sdk/shared.client@1.2.7/src/client/ClientFactory.ts"],"names":[],"mappings":"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","file":"/npm/@sthg-sdk/shared.client@1.2.7/dist/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/@sthg-sdk/shared.client@1.2.7/dist/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","import { AuthProvider } from '@sthg-sdk/tiangong.core';\n\nexport class TokenAuthProvider implements AuthProvider {\n  private token: string;\n\n  constructor(token: string) {\n    this.token = token;\n  }\n\n  async getAuthHeaders(): Promise<Record<string, string>> {\n    return {\n      'Authorization': `Bearer ${this.token}`,\n      // 'satoken': `${this.token}`,\n      'Content-Type': 'application/json'\n    };\n  }\n\n  isAuthenticated(): boolean {\n    return !!this.token && this.token.length > 0;\n  }\n\n  async authenticate(): Promise<void> {\n    if (!this.isAuthenticated()) {\n      throw new Error('No valid token provided for authentication');\n    }\n  }\n\n  setToken(token: string): void {\n    this.token = token;\n  }\n\n  getToken(): string {\n    return this.token;\n  }\n}","import axios, { AxiosResponse } from 'axios';\n\nimport { AuthProvider, TokenResponse } from '@sthg-sdk/tiangong.core';\n\nexport class UsernamePasswordAuthProvider implements AuthProvider {\n  private authUrl: string;\n  private username: string;\n  private password: string;\n  private clientId: string | undefined;\n  private clientSecret: string | undefined;\n  private accessToken: string | undefined;\n  private refreshToken: string | undefined;\n  private tokenExpiresAt: Date | undefined;\n  private timeout: number;\n\n  constructor(\n    authUrl: string,\n    username: string,\n    password: string,\n    options: {\n      clientId?: string;\n      clientSecret?: string;\n      timeout?: number;\n    } = {}\n  ) {\n    this.authUrl = authUrl.endsWith('/') ? authUrl.slice(0, -1) : authUrl;\n    this.username = username;\n    this.password = password;\n    this.clientId = options.clientId;\n    this.clientSecret = options.clientSecret;\n    this.timeout = options.timeout || 30000;\n  }\n\n  async getAuthHeaders(): Promise<Record<string, string>> {\n    if (!this.isAuthenticated() || this.isTokenExpired()) {\n      await this.authenticate();\n    }\n\n    if (!this.accessToken) {\n      throw new Error('Failed to obtain access token');\n    }\n\n    return {\n      'Authorization': `Bearer ${this.accessToken}`,\n      'Content-Type': 'application/json'\n    };\n  }\n\n  isAuthenticated(): boolean {\n    return !!this.accessToken && !this.isTokenExpired();\n  }\n\n  private isTokenExpired(): boolean {\n    if (!this.tokenExpiresAt) return false;\n    // Add 5 minute buffer before expiry\n    const bufferTime = 5 * 60 * 1000;\n    return new Date().getTime() >= (this.tokenExpiresAt.getTime() - bufferTime);\n  }\n\n  async authenticate(): Promise<void> {\n    try {\n      // Try to refresh token first if available and not expired\n      if (this.refreshToken && this.accessToken && this.isTokenExpired()) {\n        try {\n          await this.refresh();\n          return;\n        } catch (error) {\n          // If refresh fails, continue with password authentication\n          console.warn('Token refresh failed, falling back to password authentication');\n        }\n      }\n\n      // Authenticate with username/password\n      await this.authenticateWithPassword();\n    } catch (error: any) {\n      throw new Error(`Authentication failed: ${error.message || 'Unknown error'}`);\n    }\n  }\n\n  async refresh(): Promise<void> {\n    if (!this.refreshToken) {\n      throw new Error('No refresh token available');\n    }\n\n    try {\n      const requestData = new URLSearchParams({\n        grant_type: 'refresh_token',\n        refresh_token: this.refreshToken,\n      });\n\n      if (this.clientId) {\n        requestData.append('client_id', this.clientId);\n      }\n\n      if (this.clientSecret) {\n        requestData.append('client_secret', this.clientSecret);\n      }\n\n      const response: AxiosResponse<TokenResponse> = await axios.post(\n        this.authUrl,\n        requestData,\n        {\n          headers: {\n            'Content-Type': 'application/x-www-form-urlencoded',\n          },\n          timeout: this.timeout,\n        }\n      );\n\n      this.handleTokenResponse(response.data);\n    } catch (error: any) {\n      this.clearTokens();\n      throw new Error(`Token refresh failed: ${error.message || 'Unknown error'}`);\n    }\n  }\n\n  private async authenticateWithPassword(): Promise<void> {\n    const requestData = new URLSearchParams({\n      grant_type: 'password',\n      username: this.username,\n      password: this.password,\n    });\n\n    if (this.clientId) {\n      requestData.append('client_id', this.clientId);\n    }\n\n    if (this.clientSecret) {\n      requestData.append('client_secret', this.clientSecret);\n    }\n\n    const response: AxiosResponse<TokenResponse> = await axios.post(\n      this.authUrl,\n      requestData,\n      {\n        headers: {\n          'Content-Type': 'application/x-www-form-urlencoded',\n        },\n        timeout: this.timeout,\n      }\n    );\n\n    this.handleTokenResponse(response.data);\n  }\n\n  private handleTokenResponse(tokenResponse: TokenResponse): void {\n    this.accessToken = tokenResponse.access_token;\n    this.refreshToken = tokenResponse.refresh_token;\n    \n    if (tokenResponse.expires_in) {\n      this.tokenExpiresAt = new Date(Date.now() + (tokenResponse.expires_in * 1000));\n    }\n  }\n\n  private clearTokens(): void {\n    this.accessToken = undefined;\n    this.refreshToken = undefined;\n    this.tokenExpiresAt = undefined;\n  }\n\n  getAccessToken(): string | undefined {\n    return this.accessToken;\n  }\n\n  setCredentials(username: string, password: string): void {\n    this.username = username;\n    this.password = password;\n    this.clearTokens();\n  }\n\n  setClientCredentials(clientId?: string, clientSecret?: string): void {\n    this.clientId = clientId;\n    this.clientSecret = clientSecret;\n  }\n\n  updateAuthUrl(authUrl: string): void {\n    this.authUrl = authUrl.endsWith('/') ? authUrl.slice(0, -1) : authUrl;\n    this.clearTokens();\n  }\n}","import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';\nimport { v4 as uuid } from 'uuid';\n\nimport { ApiError, ApiResponseUnion, ClientContext, RequestConfig, ServiceType } from '@sthg-sdk/tiangong.core';\n\nexport class HttpClient {\n  private axiosInstance: AxiosInstance;\n  private context: ClientContext;\n\n  constructor(context: ClientContext) {\n    this.context = context;\n\n    this.axiosInstance = axios.create({\n      baseURL: context.baseUrl,\n      timeout: context.timeout,\n    });\n\n    // Set default headers\n    if (context.headers) {\n      Object.assign(this.axiosInstance.defaults.headers.common, context.headers);\n    }\n\n    this.setupInterceptors();\n  }\n\n  private setupInterceptors(): void {\n    // Request interceptor for authentication\n    this.axiosInstance.interceptors.request.use(\n      async (config) => {\n        try {\n          const authHeaders = await this.context.authProvider.getAuthHeaders();\n          Object.assign(config.headers || {}, authHeaders);\n\n          // Add X-Request-Id header\n          config.headers['X-Request-Id'] = uuid() + '-' + new Date().getTime();\n\n          console.log('🚀 请求头信息:', config.headers);\n        } catch (error) {\n          console.error('Failed to get auth headers:', error);\n          throw error;\n        }\n        return config;\n      },\n      (error) => Promise.reject(error)\n    );\n\n    // Response interceptor for error handling\n    this.axiosInstance.interceptors.response.use(\n      (response: AxiosResponse<ApiResponseUnion>) => {\n        return response;\n      },\n      (error: AxiosError) => {\n        const apiError = this.createApiError(error);\n        console.log(apiError, 'apiError')\n        return Promise.reject(apiError);\n      }\n    );\n  }\n\n  private createApiError(axiosError: AxiosError): ApiError {\n    const apiError = new Error(axiosError.message || 'An error occurred') as ApiError;\n    apiError.name = 'ApiError';\n    apiError.status = axiosError.response?.status;\n    apiError.code = axiosError.code;\n    \n    if (axiosError.response) {\n      apiError.response = {\n        data: axiosError.response.data,\n        status: axiosError.response.status,\n        statusText: axiosError.response.statusText,\n      };\n\n      // Use error message from response if available\n      if (axiosError.response.data && typeof axiosError.response.data === 'object') {\n        const responseData = axiosError.response.data as any;\n        if (responseData.message) {\n          apiError.message = responseData.message;\n        } else if (responseData.error_description) {\n          apiError.message = responseData.error_description;\n        } else if (responseData.error) {\n          apiError.message = responseData.error;\n        }\n      }\n    }\n\n    return apiError;\n  }\n\n  async request<T = any>(config: RequestConfig): Promise<ApiResponseUnion<T>> {\n    const axiosConfig: AxiosRequestConfig = {\n      method: config.method,\n      url: config.url,\n      data: config.data,\n      params: config.params,\n      timeout: config.timeout || this.context.timeout,\n    };\n\n    // 根据服务类型动态设置 baseURL\n    if (config.serviceType && this.context.serviceUrls[config.serviceType]) {\n      axiosConfig.baseURL = this.context.serviceUrls[config.serviceType];\n    }\n\n    if (config.headers) {\n      axiosConfig.headers = config.headers;\n    }\n\n    if (config.responseType) {\n      axiosConfig.responseType = config.responseType;\n    }\n\n    const response = await this.axiosInstance.request<ApiResponseUnion<T>>(axiosConfig);\n    if (response.config.responseType === 'blob') {\n      return response as unknown as ApiResponseUnion<T>;\n    }\n    return this.transformResponse(response);\n  }\n\n  async get<T = any>(url: string, config?: Partial<RequestConfig>): Promise<ApiResponseUnion<T>> {\n    return this.request<T>({\n      method: 'GET',\n      url,\n      ...config,\n    });\n  }\n\n  async post<T = any>(url: string, data?: any, config?: Partial<RequestConfig>): Promise<ApiResponseUnion<T>> {\n    return this.request<T>({\n      method: 'POST',\n      url,\n      data,\n      ...config,\n    });\n  }\n\n  // 便捷方法：针对特定服务类型的请求\n  async getFromService<T>(serviceType: ServiceType, url: string, config?: Partial<RequestConfig>): Promise<ApiResponseUnion<T>> {\n    return this.get<T>(url, { ...config, serviceType });\n  }\n\n  async postToService<T = any>(serviceType: ServiceType, url: string, data?: any, config?: Partial<RequestConfig>): Promise<ApiResponseUnion<T>> {\n    return this.post<T>(url, data, { ...config, serviceType });\n  }\n\n  async putToService<T = any>(serviceType: ServiceType, url: string, data?: any, config?: Partial<RequestConfig>): Promise<ApiResponseUnion<T>> {\n    return this.put<T>(url, data, { ...config, serviceType });\n  }\n\n  async patchToService<T = any>(serviceType: ServiceType, url: string, data?: any, config?: Partial<RequestConfig>): Promise<ApiResponseUnion<T>> {\n    return this.patch<T>(url, data, { ...config, serviceType });\n  }\n\n  async deleteFromService<T = any>(serviceType: ServiceType, url: string, data?: any, config?: Partial<RequestConfig>): Promise<ApiResponseUnion<T>> {\n    return this.request<T>({\n      method: 'DELETE',\n      url,\n      data,\n      serviceType,\n      ...config,\n    });\n  }\n\n  async put<T = any>(url: string, data?: any, config?: Partial<RequestConfig>): Promise<ApiResponseUnion<T>> {\n    return this.request<T>({\n      method: 'PUT',\n      url,\n      data,\n      ...config,\n    });\n  }\n\n  async patch<T = any>(url: string, data?: any, config?: Partial<RequestConfig>): Promise<ApiResponseUnion<T>> {\n    return this.request<T>({\n      method: 'PATCH',\n      url,\n      data,\n      ...config,\n    });\n  }\n\n  async delete<T = any>(url: string, config?: Partial<RequestConfig>): Promise<ApiResponseUnion<T>> {\n    return this.request<T>({\n      method: 'DELETE',\n      url,\n      ...config,\n    });\n  }\n\n  private transformResponse<T>(response: AxiosResponse<ApiResponseUnion<T>>): ApiResponseUnion<T> {\n    \n    // 检查是否是标准 ApiResponse 格式 (包含 code 和 data 字段)\n    // console.log(this.isApiResponse<T>(response.data), 'this.isApiResponse<T>(response.data)')\n    // if (this.isApiResponse<T>(response.data)) {\n    //   // TypeScript 现在知道 response.data 是 ApiResponse<T>，所以 response.data.data 的类型是 T\n    //   return response.data.data;\n    // }\n    \n    return response.data;\n  }\n\n  // private isApiResponse<T>(data: any): data is ApiResponse<T> {\n  //   if (!data || typeof data !== 'object') {\n  //     return false;\n  //   }\n    \n  //   // 严格检查：必须同时具有 code/busiCode 和 data 字段才是标准 ApiResponse\n  //   const hasCodeField = 'code' in data || 'busiCode' in data;\n  //   const hasDataField = 'data' in data;\n  //   const hasCountField = 'count' in data;\n  //   const isSuccess = data.code === 200;\n  //   // 只有同时具备这两个字段才认为是标准 ApiResponse\n  //   return hasCodeField && hasDataField && !hasCountField && isSuccess;\n  // }\n\n  // Context management\n  updateContext(context: Partial<ClientContext>): void {\n    Object.assign(this.context, context);\n    \n    if (context.baseUrl !== undefined) {\n      this.axiosInstance.defaults.baseURL = context.baseUrl;\n    }\n    \n    if (context.timeout !== undefined) {\n      this.axiosInstance.defaults.timeout = context.timeout;\n    }\n    \n    if (context.headers) {\n      Object.assign(this.axiosInstance.defaults.headers.common, context.headers);\n    }\n\n    if (context.serviceUrls) {\n      Object.assign(this.context.serviceUrls, context.serviceUrls);\n    }\n  }\n\n  getContext(): ClientContext {\n    return { ...this.context };\n  }\n\n  // Helper method to construct API URLs\n  buildUrl(path: string, serviceType?: ServiceType): string {\n    const apiPath = path.startsWith('/') ? path : `/${path}`;\n    const baseUrl = serviceType && this.context.serviceUrls[serviceType] \n      ? this.context.serviceUrls[serviceType] \n      : this.context.baseUrl;\n    return `${baseUrl}/api${apiPath}`;\n  }\n\n  // 获取特定服务的 baseUrl\n  getServiceUrl(serviceType: ServiceType): string {\n    return this.context.serviceUrls[serviceType] || this.context.baseUrl;\n  }\n\n}","import { AuthConfig, AuthProvider, ClientContext, ServiceUrls, ServiceType } from '@sthg-sdk/tiangong.core';\nimport { TokenAuthProvider, UsernamePasswordAuthProvider } from '../auth';\nimport { HttpClient } from './HttpClient';\n\nexport class ClientFactory {\n  /**\n   * Create an HTTP client with the specified configuration\n   */\n  static createClient(config: AuthConfig): HttpClient {\n    const authProvider = ClientFactory.createAuthProvider(config);\n    const context = ClientFactory.createClientContext(config, authProvider);\n    return new HttpClient(context);\n  }\n\n  /**\n   * Create an authentication provider based on the configuration\n   */\n  static createAuthProvider(config: AuthConfig): AuthProvider {\n    if (config.token) {\n      return new TokenAuthProvider(config.token);\n    }\n\n    if (config.username && config.password) {\n      if (!config.baseUrl) {\n        throw new Error('baseUrl is required when using username/password authentication');\n      }\n      const authUrl = config.authUrl || `${config.baseUrl}/multipass/api/oauth2/token`;\n      const options: {\n        clientId?: string;\n        clientSecret?: string;\n        timeout?: number;\n      } = {};\n      \n      if (config.clientId !== undefined) options.clientId = config.clientId;\n      if (config.clientSecret !== undefined) options.clientSecret = config.clientSecret;\n      if (config.timeout !== undefined) options.timeout = config.timeout;\n      \n      return new UsernamePasswordAuthProvider(\n        authUrl,\n        config.username,\n        config.password,\n        options\n      );\n    }\n\n    throw new Error(\n      'Invalid authentication configuration. Either token or username/password must be provided.'\n    );\n  }\n\n  /**\n   * Create a client context from the configuration\n   */\n  static createClientContext(config: AuthConfig, authProvider: AuthProvider): ClientContext {\n    // Use a default base URL if none provided\n    const defaultBaseUrl = config.objectsBaseUrl || config.adminBaseUrl || config.approvalBaseUrl || config.dataeaseBaseUrl || config.difyChatBaseUrl || config.ontologyBaseUrl || config.ontologyV2BaseUrl || '';\n    const configBaseUrl = config.baseUrl || defaultBaseUrl;\n\n    if (!configBaseUrl) {\n      throw new Error('At least one baseUrl (baseUrl, objectsBaseUrl, adminBaseUrl, approvalBaseUrl, dataeaseBaseUrl, difyChatBaseUrl, ontologyBaseUrl, or ontologyV2BaseUrl) must be provided');\n    }\n\n    // Normalize base URL\n    const baseUrl = configBaseUrl.endsWith('/') \n      ? configBaseUrl.slice(0, -1) \n      : configBaseUrl;\n\n    // Set default auth URL if not provided\n    const authUrl = config.authUrl || `${baseUrl}/multipass/api/oauth2/token`;\n\n    // Create service URLs mapping\n    const serviceUrls: ServiceUrls = {\n      [ServiceType.OBJECTS]: config.objectsBaseUrl?.replace(/\\/$/, '') || baseUrl,\n      [ServiceType.ADMIN]: config.adminBaseUrl?.replace(/\\/$/, '') || baseUrl,\n      [ServiceType.CORE]: config.baseUrl?.replace(/\\/$/, '') || baseUrl,\n      [ServiceType.ONTOLOGY]: config.ontologyBaseUrl?.replace(/\\/$/, '') || baseUrl,\n      [ServiceType.ONTOLOGY_V2]: config.ontologyV2BaseUrl?.replace(/\\/$/, '') || baseUrl,\n      [ServiceType.APPROVAL]: config.approvalBaseUrl?.replace(/\\/$/, '') || baseUrl,\n      [ServiceType.DATAEASE]: config.dataeaseBaseUrl?.replace(/\\/$/, '') || baseUrl,\n      [ServiceType.DIFY_CHAT]: config.difyChatBaseUrl?.replace(/\\/$/, '') || baseUrl,\n      [ServiceType.FILESYSTEM]: config.filesystemBaseUrl?.replace(/\\/$/, '') || baseUrl,\n    };\n\n    return {\n      baseUrl,\n      authUrl,\n      timeout: config.timeout || 30000,\n      headers: {\n        'Accept': 'application/json',\n        ...config.headers,\n      },\n      authProvider,\n      useSatoken: config.useSatoken,\n      proid: config.proid,\n      serviceUrls,\n    };\n  }\n\n  /**\n   * Create a service-specific client with custom base URL\n   */\n  static createServiceClient(config: AuthConfig, serviceBaseUrl: string): HttpClient {\n    const serviceConfig = {\n      ...config,\n      baseUrl: serviceBaseUrl\n    };\n    const authProvider = ClientFactory.createAuthProvider(serviceConfig);\n    const context = ClientFactory.createClientContext(serviceConfig, authProvider);\n    return new HttpClient(context);\n  }\n\n  /**\n   * Create a token-based client\n   */\n  static createTokenClient(baseUrl: string, token: string, options: Partial<AuthConfig> = {}): HttpClient {\n    return ClientFactory.createClient({\n      baseUrl,\n      token,\n      ...options,\n    });\n  }\n\n  /**\n   * Create a username/password-based client\n   */\n  static createUsernamePasswordClient(\n    baseUrl: string,\n    username: string,\n    password: string,\n    options: Partial<AuthConfig> = {}\n  ): HttpClient {\n    return ClientFactory.createClient({\n      baseUrl,\n      username,\n      password,\n      ...options,\n    });\n  }\n\n  /**\n   * Create a client with custom authentication URL\n   */\n  static createClientWithCustomAuth(\n    baseUrl: string,\n    authUrl: string,\n    username: string,\n    password: string,\n    options: Partial<AuthConfig> = {}\n  ): HttpClient {\n    return ClientFactory.createClient({\n      baseUrl,\n      authUrl,\n      username,\n      password,\n      ...options,\n    });\n  }\n\n  /**\n   * Create a unified client with multiple service URLs (推荐使用)\n   * 支持根据请求类型动态切换不同的服务 baseUrl\n   */\n  static createUnifiedClient(config: AuthConfig): HttpClient {\n    // 确保至少有一个 baseUrl\n    if (!config.baseUrl && !config.objectsBaseUrl && !config.adminBaseUrl && !config.approvalBaseUrl && !config.dataeaseBaseUrl && !config.ontologyBaseUrl && !config.ontologyV2BaseUrl) {\n      throw new Error('At least one baseUrl must be provided');\n    }\n\n    return ClientFactory.createClient(config);\n  }\n\n}"]}