@orsetra/shared-ui 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,5 @@
1
+ "use client"
2
+
1
3
  import * as React from "react"
2
4
 
3
5
  const MOBILE_BREAKPOINT = 768
@@ -1,3 +1,5 @@
1
+ "use client"
2
+
1
3
  import { useEffect, useRef, useState } from 'react'
2
4
 
3
5
  interface UseWebSocketReturn<T> {
package/index.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  // Utilities
2
2
  export * from './lib/utils'
3
3
  export * from './lib/menu-utils'
4
+ export { BaseService } from './lib/base-service'
5
+ export { default as HttpClient, useHttpClient } from './lib/http-client'
4
6
 
5
7
  // UI Components
6
8
  export * from './components/ui'
@@ -0,0 +1,18 @@
1
+ import HttpClient from './http-client';
2
+
3
+ /**
4
+ * Classe de base pour tous les services qui utilisent HttpClient
5
+ * L'organization ID est automatiquement ajouté aux headers via les custom attributes AWS Amplify
6
+ */
7
+ export abstract class BaseService {
8
+ protected httpClient: HttpClient;
9
+
10
+ constructor(baseUrl: string) {
11
+ this.httpClient = HttpClient.getInstance(baseUrl);
12
+ }
13
+
14
+ protected handleServiceError(error: any): Error {
15
+ console.error('Service error:', error)
16
+ return error
17
+ }
18
+ }
@@ -0,0 +1,149 @@
1
+ // Simplified HTTP client without AWS Amplify dependencies
2
+
3
+ class HttpClient {
4
+ private static instance: HttpClient;
5
+ private baseUrl: string;
6
+
7
+ private constructor(baseUrl: string) {
8
+ this.baseUrl = baseUrl || process.env.NEXT_PUBLIC_API_URL || '';
9
+ }
10
+
11
+ public static getInstance(baseUrl: string): HttpClient {
12
+ if (!HttpClient.instance) {
13
+ HttpClient.instance = new HttpClient(baseUrl);
14
+ }
15
+ return HttpClient.instance;
16
+ }
17
+
18
+ private getFullUrl(path: string): string {
19
+ const cleanPath = path.startsWith('/') ? path.slice(1) : path;
20
+ return `${this.baseUrl}/${cleanPath}`;
21
+ }
22
+
23
+ private async getAuthHeaders(): Promise<Headers> {
24
+ const headers = new Headers();
25
+ headers.set('Content-Type', 'application/json');
26
+
27
+ try {
28
+ // TODO: Add authentication token and account context if needed
29
+ // For now, just return basic headers
30
+ } catch (error) {
31
+ console.warn('Failed to get auth headers:', error);
32
+ }
33
+
34
+ if (!headers.has('Content-Type')) {
35
+ headers.set('Content-Type', 'application/json');
36
+ }
37
+
38
+ return headers;
39
+ }
40
+
41
+ async request<T>(url: string, options: RequestInit = {}): Promise<T | null> {
42
+ const headers = await this.getAuthHeaders();
43
+
44
+ // Fusionner avec les headers existants
45
+ if (options.headers) {
46
+ Object.entries(options.headers).forEach(([key, value]) => {
47
+ headers.set(key, value as string);
48
+ });
49
+ }
50
+
51
+ const fullUrl = this.getFullUrl(url);
52
+
53
+ const response = await fetch(fullUrl, {
54
+ ...options,
55
+ headers,
56
+ });
57
+
58
+ if (!response.ok) {
59
+ throw new Error(`Request failed: ${response.status}`);
60
+ }
61
+
62
+ if (response.status === 204) {
63
+ return null;
64
+ }
65
+
66
+ return response.json();
67
+ }
68
+
69
+ async get<T>(url: string, options: RequestInit = {}): Promise<T | null> {
70
+ return this.request<T>(url, {
71
+ ...options,
72
+ method: 'GET'
73
+ });
74
+ }
75
+
76
+ async post<T>(url: string, body?: any, options: RequestInit = {}): Promise<T | null> {
77
+ return this.request<T>(url, {
78
+ ...options,
79
+ method: 'POST',
80
+ body: body ? JSON.stringify(body) : undefined
81
+ });
82
+ }
83
+
84
+ async put<T>(url: string, body?: any, options: RequestInit = {}): Promise<T | null> {
85
+ return this.request<T>(url, {
86
+ ...options,
87
+ method: 'PUT',
88
+ body: body ? JSON.stringify(body) : undefined
89
+ });
90
+ }
91
+
92
+ async delete<T>(url: string, options: RequestInit = {}): Promise<T | null> {
93
+ return this.request<T>(url, {
94
+ ...options,
95
+ method: 'DELETE'
96
+ });
97
+ }
98
+
99
+ async upload<T>(url: string, formData: FormData, options: RequestInit = {}): Promise<T> {
100
+ const headers = await this.getAuthHeaders();
101
+
102
+ if (headers.has('Content-Type')) {
103
+ headers.delete('Content-Type');
104
+ }
105
+
106
+ const fullUrl = this.getFullUrl(url);
107
+
108
+ const response = await fetch(fullUrl, {
109
+ ...options,
110
+ method: 'POST',
111
+ body: formData,
112
+ headers
113
+ });
114
+
115
+ if (!response.ok) {
116
+ const errorText = await response.text();
117
+ throw new Error(`Upload failed: ${response.status} ${response.statusText} - ${errorText}`);
118
+ }
119
+
120
+ if (response.status === 204) {
121
+ return null as unknown as T;
122
+ }
123
+
124
+ return response.json();
125
+ }
126
+
127
+ async download(url: string): Promise<Blob> {
128
+ const headers = await this.getAuthHeaders();
129
+ const fullUrl = this.getFullUrl(url);
130
+
131
+ const response = await fetch(fullUrl, {
132
+ method: 'GET',
133
+ headers,
134
+ credentials: 'include'
135
+ });
136
+
137
+ if (!response.ok) {
138
+ throw new Error(`Download failed: ${response.status} ${response.statusText}`);
139
+ }
140
+
141
+ return await response.blob();
142
+ }
143
+ }
144
+
145
+ export function useHttpClient(baseUrl: string) {
146
+ return HttpClient.getInstance(baseUrl);
147
+ }
148
+
149
+ export default HttpClient;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orsetra/shared-ui",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "Shared UI components for Orsetra platform",
5
5
  "main": "./index.ts",
6
6
  "types": "./index.ts",