juxscript 1.1.2 → 1.1.4
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/machinery/build3.js +7 -91
- package/machinery/compiler3.js +3 -209
- package/machinery/config.js +93 -6
- package/machinery/serve.js +255 -0
- package/machinery/watcher.js +49 -161
- package/package.json +19 -5
- package/lib/components/alert.ts +0 -200
- package/lib/components/app.ts +0 -247
- package/lib/components/badge.ts +0 -101
- package/lib/components/base/BaseComponent.ts +0 -421
- package/lib/components/base/FormInput.ts +0 -227
- package/lib/components/button.ts +0 -178
- package/lib/components/card.ts +0 -173
- package/lib/components/chart.ts +0 -231
- package/lib/components/checkbox.ts +0 -242
- package/lib/components/code.ts +0 -123
- package/lib/components/container.ts +0 -140
- package/lib/components/data.ts +0 -135
- package/lib/components/datepicker.ts +0 -234
- package/lib/components/dialog.ts +0 -172
- package/lib/components/divider.ts +0 -100
- package/lib/components/dropdown.ts +0 -186
- package/lib/components/element.ts +0 -267
- package/lib/components/fileupload.ts +0 -309
- package/lib/components/grid.ts +0 -291
- package/lib/components/guard.ts +0 -92
- package/lib/components/heading.ts +0 -96
- package/lib/components/helpers.ts +0 -41
- package/lib/components/hero.ts +0 -224
- package/lib/components/icon.ts +0 -178
- package/lib/components/icons.ts +0 -464
- package/lib/components/include.ts +0 -410
- package/lib/components/input.ts +0 -457
- package/lib/components/list.ts +0 -419
- package/lib/components/loading.ts +0 -100
- package/lib/components/menu.ts +0 -275
- package/lib/components/modal.ts +0 -284
- package/lib/components/nav.ts +0 -257
- package/lib/components/paragraph.ts +0 -97
- package/lib/components/progress.ts +0 -159
- package/lib/components/radio.ts +0 -278
- package/lib/components/req.ts +0 -303
- package/lib/components/script.ts +0 -41
- package/lib/components/select.ts +0 -252
- package/lib/components/sidebar.ts +0 -275
- package/lib/components/style.ts +0 -41
- package/lib/components/switch.ts +0 -246
- package/lib/components/table.ts +0 -1249
- package/lib/components/tabs.ts +0 -250
- package/lib/components/theme-toggle.ts +0 -293
- package/lib/components/tooltip.ts +0 -144
- package/lib/components/view.ts +0 -190
- package/lib/components/write.ts +0 -272
- package/lib/layouts/default.css +0 -260
- package/lib/layouts/figma.css +0 -334
- package/lib/reactivity/state.ts +0 -78
- package/lib/utils/fetch.ts +0 -553
- package/machinery/ast.js +0 -347
- package/machinery/build.js +0 -466
- package/machinery/bundleAssets.js +0 -0
- package/machinery/bundleJux.js +0 -0
- package/machinery/bundleVendors.js +0 -0
- package/machinery/doc-generator.js +0 -136
- package/machinery/imports.js +0 -155
- package/machinery/server.js +0 -166
- package/machinery/ts-shim.js +0 -46
- package/machinery/validators/file-validator.js +0 -123
package/lib/utils/fetch.ts
DELETED
|
@@ -1,553 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Jux Fetch Utility
|
|
3
|
-
*
|
|
4
|
-
* A lightweight fetch wrapper with sensible defaults, error handling, and method chaining.
|
|
5
|
-
* Includes configuration helpers for juxconfig.js integration.
|
|
6
|
-
*
|
|
7
|
-
* Usage:
|
|
8
|
-
* // Configure once (optional)
|
|
9
|
-
* jux.fetch.config({
|
|
10
|
-
* baseUrl: 'https://api.example.com',
|
|
11
|
-
* credentials: 'include',
|
|
12
|
-
* timeout: 10000,
|
|
13
|
-
* log: 'errors',
|
|
14
|
-
* onUnauthorized: () => window.location.href = '/login'
|
|
15
|
-
* });
|
|
16
|
-
*
|
|
17
|
-
* // Simple GET
|
|
18
|
-
* const { data, error } = await jux.fetch('/users').send();
|
|
19
|
-
*
|
|
20
|
-
* // Method chaining
|
|
21
|
-
* const { data, error } = await jux.fetch('/users')
|
|
22
|
-
* .method('POST')
|
|
23
|
-
* .body({ name: 'John' })
|
|
24
|
-
* .params({ limit: 10 })
|
|
25
|
-
* .timeout(5000)
|
|
26
|
-
* .log(true)
|
|
27
|
-
* .send();
|
|
28
|
-
*
|
|
29
|
-
* // With juxconfig services
|
|
30
|
-
* const { data } = await jux.fetch('/users')
|
|
31
|
-
* .baseUrl(jux.fetch.getServiceUrl('database'))
|
|
32
|
-
* .send();
|
|
33
|
-
*
|
|
34
|
-
* // Service client helper
|
|
35
|
-
* const db = jux.fetch.serviceClient('database');
|
|
36
|
-
* const { data } = await db.fetch('/users').send();
|
|
37
|
-
*/
|
|
38
|
-
|
|
39
|
-
export type LogLevel = boolean | 'errors';
|
|
40
|
-
|
|
41
|
-
export interface FetchConfig {
|
|
42
|
-
baseUrl?: string;
|
|
43
|
-
credentials?: RequestCredentials;
|
|
44
|
-
headers?: Record<string, string>;
|
|
45
|
-
timeout?: number;
|
|
46
|
-
log?: LogLevel;
|
|
47
|
-
onUnauthorized?: () => void;
|
|
48
|
-
onError?: (error: FetchError) => void;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export interface FetchOptions extends Omit<RequestInit, 'body'> {
|
|
52
|
-
params?: Record<string, any>;
|
|
53
|
-
body?: any;
|
|
54
|
-
timeout?: number;
|
|
55
|
-
log?: LogLevel;
|
|
56
|
-
onUnauthorized?: () => void;
|
|
57
|
-
onError?: (error: FetchError) => void;
|
|
58
|
-
parseResponse?: boolean;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export interface FetchError {
|
|
62
|
-
message: string;
|
|
63
|
-
status?: number;
|
|
64
|
-
statusText?: string;
|
|
65
|
-
data?: any;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export interface FetchResult<T = any> {
|
|
69
|
-
data: T | null;
|
|
70
|
-
error: FetchError | null;
|
|
71
|
-
status: number;
|
|
72
|
-
response: Response;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Global configuration
|
|
76
|
-
let globalConfig: FetchConfig = {
|
|
77
|
-
credentials: 'same-origin',
|
|
78
|
-
headers: {
|
|
79
|
-
'Content-Type': 'application/json'
|
|
80
|
-
},
|
|
81
|
-
timeout: 30000,
|
|
82
|
-
log: false
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Configure global fetch defaults
|
|
87
|
-
*/
|
|
88
|
-
export function configureFetch(config: FetchConfig): void {
|
|
89
|
-
globalConfig = {
|
|
90
|
-
...globalConfig,
|
|
91
|
-
...config,
|
|
92
|
-
headers: {
|
|
93
|
-
...globalConfig.headers,
|
|
94
|
-
...config.headers
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Build URL with query parameters
|
|
101
|
-
*/
|
|
102
|
-
function buildUrl(url: string, params?: Record<string, any>): string {
|
|
103
|
-
if (!params || Object.keys(params).length === 0) {
|
|
104
|
-
return url;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const searchParams = new URLSearchParams();
|
|
108
|
-
Object.entries(params).forEach(([key, value]) => {
|
|
109
|
-
if (value !== undefined && value !== null) {
|
|
110
|
-
searchParams.append(key, String(value));
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
const queryString = searchParams.toString();
|
|
115
|
-
if (!queryString) return url;
|
|
116
|
-
|
|
117
|
-
return url.includes('?')
|
|
118
|
-
? `${url}&${queryString}`
|
|
119
|
-
: `${url}?${queryString}`;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Main fetch function
|
|
124
|
-
*/
|
|
125
|
-
async function executeFetch<T = any>(
|
|
126
|
-
url: string,
|
|
127
|
-
options: FetchOptions = {}
|
|
128
|
-
): Promise<FetchResult<T>> {
|
|
129
|
-
const {
|
|
130
|
-
params,
|
|
131
|
-
body,
|
|
132
|
-
timeout = globalConfig.timeout,
|
|
133
|
-
log = globalConfig.log,
|
|
134
|
-
onUnauthorized = globalConfig.onUnauthorized,
|
|
135
|
-
onError = globalConfig.onError,
|
|
136
|
-
parseResponse = true,
|
|
137
|
-
headers = {},
|
|
138
|
-
...fetchOptions
|
|
139
|
-
} = options;
|
|
140
|
-
|
|
141
|
-
// Build full URL
|
|
142
|
-
let fullUrl = url;
|
|
143
|
-
|
|
144
|
-
// Add base URL if configured and URL is relative
|
|
145
|
-
if (globalConfig.baseUrl && !url.startsWith('http://') && !url.startsWith('https://')) {
|
|
146
|
-
fullUrl = `${globalConfig.baseUrl}${url.startsWith('/') ? url : `/${url}`}`;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Add query params
|
|
150
|
-
fullUrl = buildUrl(fullUrl, params);
|
|
151
|
-
|
|
152
|
-
// Merge headers
|
|
153
|
-
const mergedHeaders = {
|
|
154
|
-
...globalConfig.headers,
|
|
155
|
-
...headers
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
// Prepare request init
|
|
159
|
-
const requestInit: RequestInit = {
|
|
160
|
-
...fetchOptions,
|
|
161
|
-
headers: mergedHeaders,
|
|
162
|
-
credentials: options.credentials ?? globalConfig.credentials
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
// Stringify body if it's an object
|
|
166
|
-
if (body !== undefined) {
|
|
167
|
-
if (body instanceof FormData) {
|
|
168
|
-
requestInit.body = body;
|
|
169
|
-
// Remove Content-Type header for FormData (browser sets it with boundary)
|
|
170
|
-
delete (requestInit.headers as Record<string, string>)['Content-Type'];
|
|
171
|
-
} else if (typeof body === 'object') {
|
|
172
|
-
requestInit.body = JSON.stringify(body);
|
|
173
|
-
} else {
|
|
174
|
-
requestInit.body = body;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// Log request
|
|
179
|
-
if (log === true) {
|
|
180
|
-
console.log(`[JUX Fetch] ${requestInit.method || 'GET'} ${fullUrl}`, {
|
|
181
|
-
headers: requestInit.headers,
|
|
182
|
-
body: requestInit.body,
|
|
183
|
-
params
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// Setup timeout
|
|
188
|
-
const controller = new AbortController();
|
|
189
|
-
const timeoutId = timeout ? setTimeout(() => controller.abort(), timeout) : null;
|
|
190
|
-
|
|
191
|
-
if (!requestInit.signal) {
|
|
192
|
-
requestInit.signal = controller.signal;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
try {
|
|
196
|
-
const response = await fetch(fullUrl, requestInit);
|
|
197
|
-
|
|
198
|
-
if (timeoutId) clearTimeout(timeoutId);
|
|
199
|
-
|
|
200
|
-
// Handle unauthorized
|
|
201
|
-
if (response.status === 401 || response.status === 403) {
|
|
202
|
-
if (onUnauthorized) {
|
|
203
|
-
onUnauthorized();
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// Parse response
|
|
208
|
-
let data: T | null = null;
|
|
209
|
-
let errorData: any = null;
|
|
210
|
-
|
|
211
|
-
if (parseResponse) {
|
|
212
|
-
const contentType = response.headers.get('content-type');
|
|
213
|
-
|
|
214
|
-
if (contentType?.includes('application/json')) {
|
|
215
|
-
try {
|
|
216
|
-
const json = await response.json();
|
|
217
|
-
if (response.ok) {
|
|
218
|
-
data = json;
|
|
219
|
-
} else {
|
|
220
|
-
errorData = json;
|
|
221
|
-
}
|
|
222
|
-
} catch (e) {
|
|
223
|
-
// JSON parse error
|
|
224
|
-
}
|
|
225
|
-
} else if (response.ok) {
|
|
226
|
-
// Non-JSON response, try to get text
|
|
227
|
-
try {
|
|
228
|
-
data = (await response.text()) as any;
|
|
229
|
-
} catch (e) {
|
|
230
|
-
// Ignore text parse errors
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// Check if request was successful
|
|
236
|
-
if (!response.ok) {
|
|
237
|
-
const error: FetchError = {
|
|
238
|
-
message: errorData?.message || errorData?.error || response.statusText || 'Request failed',
|
|
239
|
-
status: response.status,
|
|
240
|
-
statusText: response.statusText,
|
|
241
|
-
data: errorData
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
// Log error
|
|
245
|
-
if (log === true || log === 'errors') {
|
|
246
|
-
console.error(`[JUX Fetch Error] ${requestInit.method || 'GET'} ${fullUrl}`, error);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
if (onError) {
|
|
250
|
-
onError(error);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
return {
|
|
254
|
-
data: null,
|
|
255
|
-
error,
|
|
256
|
-
status: response.status,
|
|
257
|
-
response
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// Log success
|
|
262
|
-
if (log === true) {
|
|
263
|
-
console.log(`[JUX Fetch Success] ${requestInit.method || 'GET'} ${fullUrl}`, {
|
|
264
|
-
status: response.status,
|
|
265
|
-
data
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
return {
|
|
270
|
-
data,
|
|
271
|
-
error: null,
|
|
272
|
-
status: response.status,
|
|
273
|
-
response
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
} catch (err: any) {
|
|
277
|
-
if (timeoutId) clearTimeout(timeoutId);
|
|
278
|
-
|
|
279
|
-
const error: FetchError = {
|
|
280
|
-
message: err.name === 'AbortError'
|
|
281
|
-
? 'Request timeout'
|
|
282
|
-
: err.message || 'Network error',
|
|
283
|
-
status: 0
|
|
284
|
-
};
|
|
285
|
-
|
|
286
|
-
// Log error
|
|
287
|
-
if (log === true || log === 'errors') {
|
|
288
|
-
console.error(`[JUX Fetch Error] ${requestInit.method || 'GET'} ${fullUrl}`, error);
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
if (onError) {
|
|
292
|
-
onError(error);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
return {
|
|
296
|
-
data: null,
|
|
297
|
-
error,
|
|
298
|
-
status: 0,
|
|
299
|
-
response: null as any
|
|
300
|
-
};
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* FetchBuilder class for method chaining
|
|
306
|
-
*/
|
|
307
|
-
class FetchBuilder<T = any> {
|
|
308
|
-
public url: string;
|
|
309
|
-
public options: FetchOptions = {};
|
|
310
|
-
|
|
311
|
-
constructor(url: string, options: FetchOptions = {}) {
|
|
312
|
-
this.url = url;
|
|
313
|
-
this.options = options;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
method(value: string): this {
|
|
317
|
-
this.options.method = value;
|
|
318
|
-
return this;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
body(value: any): this {
|
|
322
|
-
this.options.body = value;
|
|
323
|
-
return this;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
params(value: Record<string, any>): this {
|
|
327
|
-
this.options.params = value;
|
|
328
|
-
return this;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
headers(value: Record<string, string>): this {
|
|
332
|
-
this.options.headers = { ...this.options.headers, ...value };
|
|
333
|
-
return this;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
header(key: string, value: string): this {
|
|
337
|
-
this.options.headers = { ...this.options.headers, [key]: value };
|
|
338
|
-
return this;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
timeout(value: number): this {
|
|
342
|
-
this.options.timeout = value;
|
|
343
|
-
return this;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
credentials(value: RequestCredentials): this {
|
|
347
|
-
this.options.credentials = value;
|
|
348
|
-
return this;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
log(value: LogLevel): this {
|
|
352
|
-
this.options.log = value;
|
|
353
|
-
return this;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
parseResponse(value: boolean): this {
|
|
357
|
-
this.options.parseResponse = value;
|
|
358
|
-
return this;
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
onUnauthorized(callback: () => void): this {
|
|
362
|
-
this.options.onUnauthorized = callback;
|
|
363
|
-
return this;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
onError(callback: (error: FetchError) => void): this {
|
|
367
|
-
this.options.onError = callback;
|
|
368
|
-
return this;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
/**
|
|
372
|
-
* Execute the fetch request
|
|
373
|
-
*/
|
|
374
|
-
send(): Promise<FetchResult<T>> {
|
|
375
|
-
return executeFetch<T>(this.url, this.options);
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
/**
|
|
379
|
-
* Alias for send()
|
|
380
|
-
*/
|
|
381
|
-
fetch(): Promise<FetchResult<T>> {
|
|
382
|
-
return this.send();
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
/**
|
|
386
|
-
* Make the builder thenable (Promise-like) so it can be awaited directly
|
|
387
|
-
* This allows: await jux.fetch('/users') without needing .send()
|
|
388
|
-
*/
|
|
389
|
-
then<TResult1 = FetchResult<T>, TResult2 = never>(
|
|
390
|
-
onfulfilled?: ((value: FetchResult<T>) => TResult1 | PromiseLike<TResult1>) | null,
|
|
391
|
-
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
|
|
392
|
-
): Promise<TResult1 | TResult2> {
|
|
393
|
-
return this.send().then(onfulfilled, onrejected);
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
/**
|
|
397
|
-
* Make the builder catchable for Promise.catch()
|
|
398
|
-
*/
|
|
399
|
-
catch<TResult = never>(
|
|
400
|
-
onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null
|
|
401
|
-
): Promise<FetchResult<T> | TResult> {
|
|
402
|
-
return this.send().catch(onrejected);
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
/**
|
|
406
|
-
* Make the builder finally-able for Promise.finally()
|
|
407
|
-
*/
|
|
408
|
-
finally(onfinally?: (() => void) | null): Promise<FetchResult<T>> {
|
|
409
|
-
return this.send().finally(onfinally);
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
/**
|
|
414
|
-
* Create a fetch builder
|
|
415
|
-
*/
|
|
416
|
-
export function juxFetch<T = any>(url: string, options: FetchOptions = {}): FetchBuilder<T> {
|
|
417
|
-
return new FetchBuilder<T>(url, options);
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
/**
|
|
421
|
-
* Convenience methods for common HTTP verbs
|
|
422
|
-
*/
|
|
423
|
-
export const fetchHelpers = {
|
|
424
|
-
get: <T = any>(url: string, options?: Omit<FetchOptions, 'method'>) =>
|
|
425
|
-
new FetchBuilder<T>(url, { ...options, method: 'GET' }),
|
|
426
|
-
|
|
427
|
-
post: <T = any>(url: string, body?: any, options?: Omit<FetchOptions, 'method' | 'body'>) =>
|
|
428
|
-
new FetchBuilder<T>(url, { ...options, method: 'POST', body }),
|
|
429
|
-
|
|
430
|
-
put: <T = any>(url: string, body?: any, options?: Omit<FetchOptions, 'method' | 'body'>) =>
|
|
431
|
-
new FetchBuilder<T>(url, { ...options, method: 'PUT', body }),
|
|
432
|
-
|
|
433
|
-
patch: <T = any>(url: string, body?: any, options?: Omit<FetchOptions, 'method' | 'body'>) =>
|
|
434
|
-
new FetchBuilder<T>(url, { ...options, method: 'PATCH', body }),
|
|
435
|
-
|
|
436
|
-
delete: <T = any>(url: string, options?: Omit<FetchOptions, 'method'>) =>
|
|
437
|
-
new FetchBuilder<T>(url, { ...options, method: 'DELETE' })
|
|
438
|
-
};
|
|
439
|
-
|
|
440
|
-
/**
|
|
441
|
-
* Fetch multiple URLs in parallel
|
|
442
|
-
*/
|
|
443
|
-
export async function fetchAll<T = any>(
|
|
444
|
-
urls: string[],
|
|
445
|
-
options?: FetchOptions
|
|
446
|
-
): Promise<FetchResult<T>[]> {
|
|
447
|
-
return Promise.all(urls.map(url => executeFetch<T>(url, options)));
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
/**
|
|
451
|
-
* Get a service URL from window.juxConfig
|
|
452
|
-
*/
|
|
453
|
-
export function getServiceUrl(serviceName: string): string | null {
|
|
454
|
-
if (typeof window === 'undefined') return null;
|
|
455
|
-
|
|
456
|
-
const juxConfig = (window as any).juxConfig;
|
|
457
|
-
if (!juxConfig?.services) return null;
|
|
458
|
-
|
|
459
|
-
return juxConfig.services[serviceName] || null;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
/**
|
|
463
|
-
* Create a fetch instance preconfigured for a specific service
|
|
464
|
-
*
|
|
465
|
-
* Usage:
|
|
466
|
-
* const api = jux.fetch.serviceClient('database');
|
|
467
|
-
* const { data } = await api.fetch('/users').send();
|
|
468
|
-
*/
|
|
469
|
-
export function serviceClient(serviceName: string) {
|
|
470
|
-
const baseUrl = getServiceUrl(serviceName);
|
|
471
|
-
|
|
472
|
-
if (!baseUrl) {
|
|
473
|
-
console.warn(`[JUX Fetch] Service '${serviceName}' not found in juxConfig.services`);
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
return {
|
|
477
|
-
fetch: (url: string, options?: any) => {
|
|
478
|
-
return juxFetch(url, {
|
|
479
|
-
...options,
|
|
480
|
-
baseUrl: baseUrl || undefined
|
|
481
|
-
});
|
|
482
|
-
},
|
|
483
|
-
baseUrl
|
|
484
|
-
};
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
/**
|
|
488
|
-
* Setup fetch from juxconfig
|
|
489
|
-
* Call this in your bootstrap function
|
|
490
|
-
*
|
|
491
|
-
* Usage:
|
|
492
|
-
* export default {
|
|
493
|
-
* bootstrap: [
|
|
494
|
-
* async function initFetch() {
|
|
495
|
-
* await jux.fetch.setupConfig();
|
|
496
|
-
* }
|
|
497
|
-
* ]
|
|
498
|
-
* };
|
|
499
|
-
*/
|
|
500
|
-
export async function setupConfig() {
|
|
501
|
-
if (typeof window === 'undefined') {
|
|
502
|
-
console.warn('[JUX Fetch] setupConfig() called outside browser environment');
|
|
503
|
-
return;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
const juxConfig = (window as any).juxConfig;
|
|
507
|
-
|
|
508
|
-
if (!juxConfig) {
|
|
509
|
-
console.warn('[JUX Fetch] No juxConfig found on window. Make sure your juxconfig.js is loaded.');
|
|
510
|
-
return;
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
const services = juxConfig.services || {};
|
|
514
|
-
|
|
515
|
-
if (Object.keys(services).length === 0) {
|
|
516
|
-
console.log('[JUX Fetch] No services configured in juxConfig');
|
|
517
|
-
return;
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
// Configure fetch with common defaults
|
|
521
|
-
const fetchConfig: FetchConfig = {
|
|
522
|
-
timeout: juxConfig.fetchTimeout || 30000,
|
|
523
|
-
log: juxConfig.fetchLog || false,
|
|
524
|
-
credentials: 'include'
|
|
525
|
-
};
|
|
526
|
-
|
|
527
|
-
// Add service-specific handlers
|
|
528
|
-
if (services.auth) {
|
|
529
|
-
fetchConfig.onUnauthorized = () => {
|
|
530
|
-
console.warn('[JUX Fetch] Unauthorized - consider redirecting to login');
|
|
531
|
-
};
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
configureFetch(fetchConfig);
|
|
535
|
-
|
|
536
|
-
// Log configured services
|
|
537
|
-
console.log('[JUX Fetch] Configured with services:', Object.keys(services));
|
|
538
|
-
|
|
539
|
-
return {
|
|
540
|
-
services,
|
|
541
|
-
getServiceUrl
|
|
542
|
-
};
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
// Export combined API
|
|
546
|
-
export const fetchAPI = Object.assign(juxFetch, {
|
|
547
|
-
config: configureFetch,
|
|
548
|
-
setupConfig,
|
|
549
|
-
getServiceUrl,
|
|
550
|
-
serviceClient,
|
|
551
|
-
...fetchHelpers,
|
|
552
|
-
all: fetchAll
|
|
553
|
-
});
|