@bookinglab/booking-journey-api 1.0.0
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.
- package/LICENSE +21 -0
- package/README.md +178 -0
- package/dist/index.d.mts +404 -0
- package/dist/index.d.ts +404 -0
- package/dist/index.js +254 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +244 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +67 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { createContext, useMemo, useContext } from 'react';
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { useMutation } from '@tanstack/react-query';
|
|
4
|
+
|
|
5
|
+
// src/core.ts
|
|
6
|
+
var ApiClient = class {
|
|
7
|
+
constructor(config) {
|
|
8
|
+
this.baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
9
|
+
this.headers = config.headers || {};
|
|
10
|
+
this.timeout = config.timeout || 3e4;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Update client configuration
|
|
14
|
+
*/
|
|
15
|
+
setConfig(config) {
|
|
16
|
+
if (config.baseUrl) this.baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
17
|
+
if (config.headers) this.headers = { ...this.headers, ...config.headers };
|
|
18
|
+
if (config.timeout) this.timeout = config.timeout;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Set authorization token
|
|
22
|
+
*/
|
|
23
|
+
setAuthToken(token) {
|
|
24
|
+
this.headers["Authorization"] = `Bearer ${token}`;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Make an HTTP request
|
|
28
|
+
*/
|
|
29
|
+
async request(endpoint, options = {}) {
|
|
30
|
+
const { params, ...fetchOptions } = options;
|
|
31
|
+
let url = `${this.baseUrl}${endpoint}`;
|
|
32
|
+
if (params) {
|
|
33
|
+
const searchParams = new URLSearchParams();
|
|
34
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
35
|
+
if (value !== void 0) {
|
|
36
|
+
searchParams.append(key, String(value));
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
const queryString = searchParams.toString();
|
|
40
|
+
if (queryString) {
|
|
41
|
+
url += `?${queryString}`;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const headers = {
|
|
45
|
+
"Content-Type": "application/json",
|
|
46
|
+
...this.headers,
|
|
47
|
+
...fetchOptions.headers || {}
|
|
48
|
+
};
|
|
49
|
+
const controller = new AbortController();
|
|
50
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
51
|
+
try {
|
|
52
|
+
const response = await fetch(url, {
|
|
53
|
+
...fetchOptions,
|
|
54
|
+
headers,
|
|
55
|
+
signal: controller.signal
|
|
56
|
+
});
|
|
57
|
+
clearTimeout(timeoutId);
|
|
58
|
+
if (!response.ok) {
|
|
59
|
+
throw await this.handleError(response);
|
|
60
|
+
}
|
|
61
|
+
const data = await response.json();
|
|
62
|
+
return {
|
|
63
|
+
data,
|
|
64
|
+
status: response.status,
|
|
65
|
+
headers: response.headers
|
|
66
|
+
};
|
|
67
|
+
} catch (error) {
|
|
68
|
+
clearTimeout(timeoutId);
|
|
69
|
+
throw this.normalizeError(error);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* GET request
|
|
74
|
+
*/
|
|
75
|
+
async get(endpoint, options) {
|
|
76
|
+
return this.request(endpoint, { ...options, method: "GET" });
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* POST request
|
|
80
|
+
*/
|
|
81
|
+
async post(endpoint, body, options) {
|
|
82
|
+
return this.request(endpoint, {
|
|
83
|
+
...options,
|
|
84
|
+
method: "POST",
|
|
85
|
+
body: body ? JSON.stringify(body) : void 0
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* PUT request
|
|
90
|
+
*/
|
|
91
|
+
async put(endpoint, body, options) {
|
|
92
|
+
return this.request(endpoint, {
|
|
93
|
+
...options,
|
|
94
|
+
method: "PUT",
|
|
95
|
+
body: body ? JSON.stringify(body) : void 0
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* DELETE request
|
|
100
|
+
*/
|
|
101
|
+
async delete(endpoint, options) {
|
|
102
|
+
return this.request(endpoint, { ...options, method: "DELETE" });
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Handle error responses
|
|
106
|
+
*/
|
|
107
|
+
async handleError(response) {
|
|
108
|
+
let message = `HTTP ${response.status}: ${response.statusText}`;
|
|
109
|
+
let details;
|
|
110
|
+
try {
|
|
111
|
+
details = await response.json();
|
|
112
|
+
if (details.message) {
|
|
113
|
+
message = details.message;
|
|
114
|
+
} else if (details.error) {
|
|
115
|
+
message = details.error;
|
|
116
|
+
}
|
|
117
|
+
} catch {
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
message,
|
|
121
|
+
status: response.status,
|
|
122
|
+
details
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Normalize errors to consistent format
|
|
127
|
+
*/
|
|
128
|
+
normalizeError(error) {
|
|
129
|
+
if (error.name === "AbortError") {
|
|
130
|
+
return {
|
|
131
|
+
message: "Request timeout",
|
|
132
|
+
code: "TIMEOUT"
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
if ("status" in error) {
|
|
136
|
+
return error;
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
message: error.message || "Unknown error",
|
|
140
|
+
code: "UNKNOWN"
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
// src/jrni.ts
|
|
146
|
+
var JrniClient = class extends ApiClient {
|
|
147
|
+
constructor(baseUrl, config) {
|
|
148
|
+
super({ baseUrl });
|
|
149
|
+
this.appId = config.appId;
|
|
150
|
+
this.appKey = config.appKey;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Login to JRNI
|
|
154
|
+
*/
|
|
155
|
+
async login(credentials) {
|
|
156
|
+
return this.post("/login", credentials, {
|
|
157
|
+
headers: {
|
|
158
|
+
"Content-Type": "application/json",
|
|
159
|
+
"App-Id": this.appId,
|
|
160
|
+
"App-Key": this.appKey
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Update JRNI configuration
|
|
166
|
+
*/
|
|
167
|
+
setJrniConfig(config) {
|
|
168
|
+
if (config.appId) this.appId = config.appId;
|
|
169
|
+
if (config.appKey) this.appKey = config.appKey;
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
function createJrniClient(baseUrl, config) {
|
|
173
|
+
return new JrniClient(baseUrl, config);
|
|
174
|
+
}
|
|
175
|
+
var ApiClientContext = createContext(void 0);
|
|
176
|
+
function ApiClientProvider({
|
|
177
|
+
children,
|
|
178
|
+
jrniBaseUrl,
|
|
179
|
+
jrniConfig
|
|
180
|
+
}) {
|
|
181
|
+
const jrniClient = useMemo(() => {
|
|
182
|
+
if (jrniBaseUrl && jrniConfig) {
|
|
183
|
+
return new JrniClient(jrniBaseUrl, jrniConfig);
|
|
184
|
+
}
|
|
185
|
+
return null;
|
|
186
|
+
}, [jrniBaseUrl, jrniConfig?.appId, jrniConfig?.appKey]);
|
|
187
|
+
const value = useMemo(
|
|
188
|
+
() => ({
|
|
189
|
+
jrniClient
|
|
190
|
+
}),
|
|
191
|
+
[jrniClient]
|
|
192
|
+
);
|
|
193
|
+
return /* @__PURE__ */ jsx(ApiClientContext.Provider, { value, children });
|
|
194
|
+
}
|
|
195
|
+
function useApiClientContext() {
|
|
196
|
+
const context = useContext(ApiClientContext);
|
|
197
|
+
if (context === void 0) {
|
|
198
|
+
throw new Error("useApiClientContext must be used within an ApiClientProvider");
|
|
199
|
+
}
|
|
200
|
+
return context;
|
|
201
|
+
}
|
|
202
|
+
var JrniContext = createContext(void 0);
|
|
203
|
+
function JrniProvider({ children, baseUrl, config }) {
|
|
204
|
+
const client = useMemo(() => {
|
|
205
|
+
return new JrniClient(baseUrl, config);
|
|
206
|
+
}, [baseUrl, config.appId, config.appKey]);
|
|
207
|
+
const value = useMemo(() => ({ client }), [client]);
|
|
208
|
+
return /* @__PURE__ */ jsx(JrniContext.Provider, { value, children });
|
|
209
|
+
}
|
|
210
|
+
function useJrniContext() {
|
|
211
|
+
const context = useContext(JrniContext);
|
|
212
|
+
if (context === void 0) {
|
|
213
|
+
throw new Error("useJrniContext must be used within a JrniProvider");
|
|
214
|
+
}
|
|
215
|
+
return context.client;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// src/hooks/useApiClient.ts
|
|
219
|
+
function useJrniClient() {
|
|
220
|
+
try {
|
|
221
|
+
return useJrniContext();
|
|
222
|
+
} catch {
|
|
223
|
+
const context = useApiClientContext();
|
|
224
|
+
if (!context.jrniClient) {
|
|
225
|
+
throw new Error(
|
|
226
|
+
"JRNI client not configured. Wrap your app with ApiClientProvider or JrniProvider."
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
return context.jrniClient;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
function useLogin() {
|
|
233
|
+
const client = useJrniClient();
|
|
234
|
+
return useMutation({
|
|
235
|
+
mutationFn: async (credentials) => {
|
|
236
|
+
const response = await client.login(credentials);
|
|
237
|
+
return response.data;
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export { ApiClient, ApiClientProvider, JrniClient, JrniProvider, createJrniClient, useApiClientContext, useJrniClient, useJrniContext, useLogin };
|
|
243
|
+
//# sourceMappingURL=index.mjs.map
|
|
244
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core.ts","../src/jrni.ts","../src/providers/ApiClientProvider.tsx","../src/providers/JrniProvider.tsx","../src/hooks/useApiClient.ts","../src/hooks/useJrni.ts"],"names":["createContext","useMemo","jsx","useContext"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Core API Client\n * Base class for making HTTP requests\n */\n\nimport { ApiClientConfig, RequestOptions, ApiResponse, ApiError } from './types';\n\nexport class ApiClient {\n protected baseUrl: string;\n protected headers: Record<string, string>;\n protected timeout: number;\n\n constructor(config: ApiClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.headers = config.headers || {};\n this.timeout = config.timeout || 30000;\n }\n\n /**\n * Update client configuration\n */\n setConfig(config: Partial<ApiClientConfig>) {\n if (config.baseUrl) this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n if (config.headers) this.headers = { ...this.headers, ...config.headers };\n if (config.timeout) this.timeout = config.timeout;\n }\n\n /**\n * Set authorization token\n */\n setAuthToken(token: string) {\n this.headers['Authorization'] = `Bearer ${token}`;\n }\n\n /**\n * Make an HTTP request\n */\n protected async request<T>(\n endpoint: string,\n options: RequestOptions = {}\n ): Promise<ApiResponse<T>> {\n const { params, ...fetchOptions } = options;\n\n // Build URL with query parameters\n let url = `${this.baseUrl}${endpoint}`;\n if (params) {\n const searchParams = new URLSearchParams();\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined) {\n searchParams.append(key, String(value));\n }\n });\n const queryString = searchParams.toString();\n if (queryString) {\n url += `?${queryString}`;\n }\n }\n\n // Merge headers\n const headers = {\n 'Content-Type': 'application/json',\n ...this.headers,\n ...((fetchOptions.headers as Record<string, string>) || {}),\n };\n\n // Create abort controller for timeout\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n ...fetchOptions,\n headers,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n throw await this.handleError(response);\n }\n\n const data = await response.json();\n\n return {\n data,\n status: response.status,\n headers: response.headers,\n };\n } catch (error) {\n clearTimeout(timeoutId);\n throw this.normalizeError(error as Error);\n }\n }\n\n /**\n * GET request\n */\n protected async get<T>(endpoint: string, options?: RequestOptions): Promise<ApiResponse<T>> {\n return this.request<T>(endpoint, { ...options, method: 'GET' });\n }\n\n /**\n * POST request\n */\n protected async post<T>(\n endpoint: string,\n body?: any,\n options?: RequestOptions\n ): Promise<ApiResponse<T>> {\n return this.request<T>(endpoint, {\n ...options,\n method: 'POST',\n body: body ? JSON.stringify(body) : undefined,\n });\n }\n\n /**\n * PUT request\n */\n protected async put<T>(\n endpoint: string,\n body?: any,\n options?: RequestOptions\n ): Promise<ApiResponse<T>> {\n return this.request<T>(endpoint, {\n ...options,\n method: 'PUT',\n body: body ? JSON.stringify(body) : undefined,\n });\n }\n\n /**\n * DELETE request\n */\n protected async delete<T>(endpoint: string, options?: RequestOptions): Promise<ApiResponse<T>> {\n return this.request<T>(endpoint, { ...options, method: 'DELETE' });\n }\n\n /**\n * Handle error responses\n */\n private async handleError(response: Response): Promise<ApiError> {\n let message = `HTTP ${response.status}: ${response.statusText}`;\n let details: any;\n\n try {\n details = await response.json();\n if (details.message) {\n message = details.message;\n } else if (details.error) {\n message = details.error;\n }\n } catch {\n // Response body is not JSON\n }\n\n return {\n message,\n status: response.status,\n details,\n };\n }\n\n /**\n * Normalize errors to consistent format\n */\n private normalizeError(error: Error): ApiError {\n if (error.name === 'AbortError') {\n return {\n message: 'Request timeout',\n code: 'TIMEOUT',\n };\n }\n\n if ('status' in error) {\n return error as ApiError;\n }\n\n return {\n message: error.message || 'Unknown error',\n code: 'UNKNOWN',\n };\n }\n}\n","/**\n * JRNI API Client\n * Provides methods for interacting with the JRNI API\n */\n\nimport { ApiClient } from './core';\nimport { LoginRequest, LoginResponse, ApiResponse, JrniConfig } from './types';\n\nexport class JrniClient extends ApiClient {\n private appId: string;\n private appKey: string;\n\n constructor(baseUrl: string, config: JrniConfig) {\n super({ baseUrl });\n this.appId = config.appId;\n this.appKey = config.appKey;\n }\n\n /**\n * Login to JRNI\n */\n async login(credentials: LoginRequest): Promise<ApiResponse<LoginResponse>> {\n return this.post<LoginResponse>('/login', credentials, {\n headers: {\n 'Content-Type': 'application/json',\n 'App-Id': this.appId,\n 'App-Key': this.appKey,\n },\n });\n }\n\n /**\n * Update JRNI configuration\n */\n setJrniConfig(config: Partial<JrniConfig>) {\n if (config.appId) this.appId = config.appId;\n if (config.appKey) this.appKey = config.appKey;\n }\n}\n\n/**\n * Create a new JRNI client instance\n */\nexport function createJrniClient(baseUrl: string, config: JrniConfig) {\n return new JrniClient(baseUrl, config);\n}\n","/**\n * React Context Provider for API Clients\n * Combined provider for applications using multiple API clients\n */\n\nimport React, { createContext, useContext, useMemo, ReactNode } from 'react';\nimport { JrniClient } from '../jrni';\nimport { JrniConfig } from '../types';\n\ninterface ApiClientContextValue {\n jrniClient: JrniClient | null;\n}\n\ninterface ApiClientProviderProps {\n children: ReactNode;\n jrniBaseUrl?: string;\n jrniConfig?: JrniConfig;\n}\n\nconst ApiClientContext = createContext<ApiClientContextValue | undefined>(undefined);\n\n/**\n * Combined provider for multiple API clients\n */\nexport function ApiClientProvider({\n children,\n jrniBaseUrl,\n jrniConfig,\n}: ApiClientProviderProps) {\n const jrniClient = useMemo(() => {\n if (jrniBaseUrl && jrniConfig) {\n return new JrniClient(jrniBaseUrl, jrniConfig);\n }\n return null;\n }, [jrniBaseUrl, jrniConfig?.appId, jrniConfig?.appKey]);\n\n const value = useMemo(\n () => ({\n jrniClient,\n }),\n [jrniClient]\n );\n\n return <ApiClientContext.Provider value={value}>{children}</ApiClientContext.Provider>;\n}\n\n/**\n * Hook to access API client context\n */\nexport function useApiClientContext() {\n const context = useContext(ApiClientContext);\n if (context === undefined) {\n throw new Error('useApiClientContext must be used within an ApiClientProvider');\n }\n return context;\n}\n","/**\n * React Context Provider for JRNI API Client\n * Standalone provider for apps that only use JRNI\n */\n\nimport React, { createContext, useContext, useMemo, ReactNode } from 'react';\nimport { JrniClient } from '../jrni';\nimport { JrniConfig } from '../types';\n\ninterface JrniContextValue {\n client: JrniClient;\n}\n\ninterface JrniProviderProps {\n children: ReactNode;\n baseUrl: string;\n config: JrniConfig;\n}\n\nconst JrniContext = createContext<JrniContextValue | undefined>(undefined);\n\n/**\n * Provider component for JRNI client\n */\nexport function JrniProvider({ children, baseUrl, config }: JrniProviderProps) {\n const client = useMemo(() => {\n return new JrniClient(baseUrl, config);\n }, [baseUrl, config.appId, config.appKey]);\n\n const value = useMemo(() => ({ client }), [client]);\n\n return <JrniContext.Provider value={value}>{children}</JrniContext.Provider>;\n}\n\n/**\n * Hook to access JRNI client from context\n */\nexport function useJrniContext() {\n const context = useContext(JrniContext);\n if (context === undefined) {\n throw new Error('useJrniContext must be used within a JrniProvider');\n }\n return context.client;\n}\n","/**\n * Hook to access API clients from context\n */\n\nimport { useApiClientContext } from '../providers/ApiClientProvider';\nimport { useJrniContext } from '../providers/JrniProvider';\n\n/**\n * Hook to get JRNI client from either ApiClientProvider or JrniProvider\n */\nexport function useJrniClient() {\n // Try to get from standalone provider first\n try {\n return useJrniContext();\n } catch {\n // Fall back to combined provider\n const context = useApiClientContext();\n if (!context.jrniClient) {\n throw new Error(\n 'JRNI client not configured. Wrap your app with ApiClientProvider or JrniProvider.'\n );\n }\n return context.jrniClient;\n }\n}\n","/**\n * React hooks for JRNI API\n */\n\nimport { useMutation } from '@tanstack/react-query';\nimport { useJrniClient } from './useApiClient';\nimport { LoginRequest, LoginResponse } from '../types';\n\n/**\n * Hook for JRNI login\n */\nexport function useLogin() {\n const client = useJrniClient();\n\n return useMutation({\n mutationFn: async (credentials: LoginRequest) => {\n const response = await client.login(credentials);\n return response.data;\n },\n });\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bookinglab/booking-journey-api",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "TypeScript library for BookingLab and JRNI APIs with React hooks support",
|
|
5
|
+
"main": "./dist/index.cjs",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"require": {
|
|
15
|
+
"types": "./dist/index.d.cts",
|
|
16
|
+
"default": "./dist/index.cjs"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"README.md",
|
|
23
|
+
"LICENSE"
|
|
24
|
+
],
|
|
25
|
+
"keywords": [
|
|
26
|
+
"jrni",
|
|
27
|
+
"bookinglab",
|
|
28
|
+
"api-client",
|
|
29
|
+
"react",
|
|
30
|
+
"typescript",
|
|
31
|
+
"booking",
|
|
32
|
+
"scheduling"
|
|
33
|
+
],
|
|
34
|
+
"author": "BookingLab",
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "https://github.com/bookinglab/booking-journey-api"
|
|
39
|
+
},
|
|
40
|
+
"bugs": {
|
|
41
|
+
"url": "https://github.com/bookinglab/booking-journey-api/issues"
|
|
42
|
+
},
|
|
43
|
+
"homepage": "https://github.com/bookinglab/booking-journey-api#readme",
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "tsup",
|
|
46
|
+
"dev": "tsup --watch",
|
|
47
|
+
"typecheck": "tsc --noEmit",
|
|
48
|
+
"prepublishOnly": "npm run build"
|
|
49
|
+
},
|
|
50
|
+
"peerDependencies": {
|
|
51
|
+
"@tanstack/react-query": ">=5.0.0",
|
|
52
|
+
"react": ">=17.0.0"
|
|
53
|
+
},
|
|
54
|
+
"peerDependenciesMeta": {
|
|
55
|
+
"@tanstack/react-query": {
|
|
56
|
+
"optional": true
|
|
57
|
+
},
|
|
58
|
+
"react": {
|
|
59
|
+
"optional": true
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"devDependencies": {
|
|
63
|
+
"@types/react": "^18.3.0",
|
|
64
|
+
"tsup": "^8.0.0",
|
|
65
|
+
"typescript": "^5.8.0"
|
|
66
|
+
}
|
|
67
|
+
}
|