juxscript 1.1.244 → 1.1.246
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/dist/lib/components/dataframe.d.ts +1 -0
- package/dist/lib/components/dataframe.d.ts.map +1 -0
- package/dist/lib/components/dataframe.js +1 -0
- package/dist/lib/components/include.d.ts +86 -0
- package/dist/lib/components/include.d.ts.map +1 -0
- package/{lib/components/include.ts → dist/lib/components/include.js} +57 -100
- package/dist/lib/components/tag.d.ts +27 -0
- package/dist/lib/components/tag.d.ts.map +1 -0
- package/{lib/components/tag.ts → dist/lib/components/tag.js} +14 -25
- package/dist/lib/index.d.ts +17 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/{index.js → dist/lib/index.js} +4 -2
- package/dist/lib/utils/codeparser.d.ts +29 -0
- package/dist/lib/utils/codeparser.d.ts.map +1 -0
- package/{lib/utils/codeparser.ts → dist/lib/utils/codeparser.js} +64 -91
- package/dist/lib/utils/fetch.d.ts +176 -0
- package/dist/lib/utils/fetch.d.ts.map +1 -0
- package/{lib/utils/fetch.ts → dist/lib/utils/fetch.js} +80 -206
- package/dist/lib/utils/formatId.d.ts +16 -0
- package/dist/lib/utils/formatId.d.ts.map +1 -0
- package/{lib/utils/formatId.ts → dist/lib/utils/formatId.js} +7 -8
- package/dist/lib/utils/idgen.d.ts +2 -0
- package/dist/lib/utils/idgen.d.ts.map +1 -0
- package/{lib/utils/idgen.ts → dist/lib/utils/idgen.js} +2 -4
- package/package.json +2 -7
- package/lib/components/dataframe.ts +0 -0
- package/lib/styles/animations.css +0 -218
- package/lib/styles/foundation.css +0 -542
- package/lib/styles/gradients.css +0 -326
- package/lib/styles/link.css +0 -158
- package/lib/styles/modal.css +0 -402
- package/lib/styles/modifiers.css +0 -103
- package/lib/styles/nav.css +0 -322
- package/lib/styles/shadcn.css +0 -960
- package/lib/styles/stacks.css +0 -132
- package/lib/styles/themes.css +0 -486
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Jux Fetch Utility
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* A lightweight fetch wrapper with sensible defaults, error handling, and method chaining.
|
|
5
5
|
* Includes configuration helpers for juxconfig.js integration.
|
|
6
|
-
*
|
|
6
|
+
*
|
|
7
7
|
* Usage:
|
|
8
8
|
* // Configure once (optional)
|
|
9
9
|
* jux.fetch.config({
|
|
@@ -13,10 +13,10 @@
|
|
|
13
13
|
* log: 'errors',
|
|
14
14
|
* onUnauthorized: () => window.location.href = '/login'
|
|
15
15
|
* });
|
|
16
|
-
*
|
|
16
|
+
*
|
|
17
17
|
* // Simple GET
|
|
18
18
|
* const { data, error } = await jux.fetch('/users').send();
|
|
19
|
-
*
|
|
19
|
+
*
|
|
20
20
|
* // Method chaining
|
|
21
21
|
* const { data, error } = await jux.fetch('/users')
|
|
22
22
|
* .method('POST')
|
|
@@ -25,55 +25,18 @@
|
|
|
25
25
|
* .timeout(5000)
|
|
26
26
|
* .log(true)
|
|
27
27
|
* .send();
|
|
28
|
-
*
|
|
28
|
+
*
|
|
29
29
|
* // With juxconfig services
|
|
30
30
|
* const { data } = await jux.fetch('/users')
|
|
31
31
|
* .baseUrl(jux.fetch.getServiceUrl('database'))
|
|
32
32
|
* .send();
|
|
33
|
-
*
|
|
33
|
+
*
|
|
34
34
|
* // Service client helper
|
|
35
35
|
* const db = jux.fetch.serviceClient('database');
|
|
36
36
|
* const { data } = await db.fetch('/users').send();
|
|
37
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
38
|
// Global configuration
|
|
76
|
-
let globalConfig
|
|
39
|
+
let globalConfig = {
|
|
77
40
|
credentials: 'same-origin',
|
|
78
41
|
headers: {
|
|
79
42
|
'Content-Type': 'application/json'
|
|
@@ -81,11 +44,10 @@ let globalConfig: FetchConfig = {
|
|
|
81
44
|
timeout: 30000,
|
|
82
45
|
log: false
|
|
83
46
|
};
|
|
84
|
-
|
|
85
47
|
/**
|
|
86
48
|
* Configure global fetch defaults
|
|
87
49
|
*/
|
|
88
|
-
export function configureFetch(config
|
|
50
|
+
export function configureFetch(config) {
|
|
89
51
|
globalConfig = {
|
|
90
52
|
...globalConfig,
|
|
91
53
|
...config,
|
|
@@ -95,86 +57,64 @@ export function configureFetch(config: FetchConfig): void {
|
|
|
95
57
|
}
|
|
96
58
|
};
|
|
97
59
|
}
|
|
98
|
-
|
|
99
60
|
/**
|
|
100
61
|
* Build URL with query parameters
|
|
101
62
|
*/
|
|
102
|
-
function buildUrl(url
|
|
63
|
+
function buildUrl(url, params) {
|
|
103
64
|
if (!params || Object.keys(params).length === 0) {
|
|
104
65
|
return url;
|
|
105
66
|
}
|
|
106
|
-
|
|
107
67
|
const searchParams = new URLSearchParams();
|
|
108
68
|
Object.entries(params).forEach(([key, value]) => {
|
|
109
69
|
if (value !== undefined && value !== null) {
|
|
110
70
|
searchParams.append(key, String(value));
|
|
111
71
|
}
|
|
112
72
|
});
|
|
113
|
-
|
|
114
73
|
const queryString = searchParams.toString();
|
|
115
|
-
if (!queryString)
|
|
116
|
-
|
|
74
|
+
if (!queryString)
|
|
75
|
+
return url;
|
|
117
76
|
return url.includes('?')
|
|
118
77
|
? `${url}&${queryString}`
|
|
119
78
|
: `${url}?${queryString}`;
|
|
120
79
|
}
|
|
121
|
-
|
|
122
80
|
/**
|
|
123
81
|
* Main fetch function
|
|
124
82
|
*/
|
|
125
|
-
async function executeFetch
|
|
126
|
-
|
|
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
|
-
|
|
83
|
+
async function executeFetch(url, options = {}) {
|
|
84
|
+
const { params, body, timeout = globalConfig.timeout, log = globalConfig.log, onUnauthorized = globalConfig.onUnauthorized, onError = globalConfig.onError, parseResponse = true, headers = {}, ...fetchOptions } = options;
|
|
141
85
|
// Build full URL
|
|
142
86
|
let fullUrl = url;
|
|
143
|
-
|
|
144
87
|
// Add base URL if configured and URL is relative
|
|
145
88
|
if (globalConfig.baseUrl && !url.startsWith('http://') && !url.startsWith('https://')) {
|
|
146
89
|
fullUrl = `${globalConfig.baseUrl}${url.startsWith('/') ? url : `/${url}`}`;
|
|
147
90
|
}
|
|
148
|
-
|
|
149
91
|
// Add query params
|
|
150
92
|
fullUrl = buildUrl(fullUrl, params);
|
|
151
|
-
|
|
152
93
|
// Merge headers
|
|
153
94
|
const mergedHeaders = {
|
|
154
95
|
...globalConfig.headers,
|
|
155
96
|
...headers
|
|
156
97
|
};
|
|
157
|
-
|
|
158
98
|
// Prepare request init
|
|
159
|
-
const requestInit
|
|
99
|
+
const requestInit = {
|
|
160
100
|
...fetchOptions,
|
|
161
101
|
headers: mergedHeaders,
|
|
162
102
|
credentials: options.credentials ?? globalConfig.credentials
|
|
163
103
|
};
|
|
164
|
-
|
|
165
104
|
// Stringify body if it's an object
|
|
166
105
|
if (body !== undefined) {
|
|
167
106
|
if (body instanceof FormData) {
|
|
168
107
|
requestInit.body = body;
|
|
169
108
|
// Remove Content-Type header for FormData (browser sets it with boundary)
|
|
170
|
-
delete
|
|
171
|
-
}
|
|
109
|
+
delete requestInit.headers['Content-Type'];
|
|
110
|
+
}
|
|
111
|
+
else if (typeof body === 'object') {
|
|
172
112
|
requestInit.body = JSON.stringify(body);
|
|
173
|
-
}
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
174
115
|
requestInit.body = body;
|
|
175
116
|
}
|
|
176
117
|
}
|
|
177
|
-
|
|
178
118
|
// Log request
|
|
179
119
|
if (log === true) {
|
|
180
120
|
console.log(`[JUX Fetch] ${requestInit.method || 'GET'} ${fullUrl}`, {
|
|
@@ -183,73 +123,66 @@ async function executeFetch<T = any>(
|
|
|
183
123
|
params
|
|
184
124
|
});
|
|
185
125
|
}
|
|
186
|
-
|
|
187
126
|
// Setup timeout
|
|
188
127
|
const controller = new AbortController();
|
|
189
128
|
const timeoutId = timeout ? setTimeout(() => controller.abort(), timeout) : null;
|
|
190
|
-
|
|
191
129
|
if (!requestInit.signal) {
|
|
192
130
|
requestInit.signal = controller.signal;
|
|
193
131
|
}
|
|
194
|
-
|
|
195
132
|
try {
|
|
196
133
|
const response = await fetch(fullUrl, requestInit);
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
134
|
+
if (timeoutId)
|
|
135
|
+
clearTimeout(timeoutId);
|
|
200
136
|
// Handle unauthorized
|
|
201
137
|
if (response.status === 401 || response.status === 403) {
|
|
202
138
|
if (onUnauthorized) {
|
|
203
139
|
onUnauthorized();
|
|
204
140
|
}
|
|
205
141
|
}
|
|
206
|
-
|
|
207
142
|
// Parse response
|
|
208
|
-
let data
|
|
209
|
-
let errorData
|
|
210
|
-
|
|
143
|
+
let data = null;
|
|
144
|
+
let errorData = null;
|
|
211
145
|
if (parseResponse) {
|
|
212
146
|
const contentType = response.headers.get('content-type');
|
|
213
|
-
|
|
214
147
|
if (contentType?.includes('application/json')) {
|
|
215
148
|
try {
|
|
216
149
|
const json = await response.json();
|
|
217
150
|
if (response.ok) {
|
|
218
151
|
data = json;
|
|
219
|
-
}
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
220
154
|
errorData = json;
|
|
221
155
|
}
|
|
222
|
-
}
|
|
156
|
+
}
|
|
157
|
+
catch (e) {
|
|
223
158
|
// JSON parse error
|
|
224
159
|
}
|
|
225
|
-
}
|
|
160
|
+
}
|
|
161
|
+
else if (response.ok) {
|
|
226
162
|
// Non-JSON response, try to get text
|
|
227
163
|
try {
|
|
228
|
-
data = (await response.text())
|
|
229
|
-
}
|
|
164
|
+
data = (await response.text());
|
|
165
|
+
}
|
|
166
|
+
catch (e) {
|
|
230
167
|
// Ignore text parse errors
|
|
231
168
|
}
|
|
232
169
|
}
|
|
233
170
|
}
|
|
234
|
-
|
|
235
171
|
// Check if request was successful
|
|
236
172
|
if (!response.ok) {
|
|
237
|
-
const error
|
|
173
|
+
const error = {
|
|
238
174
|
message: errorData?.message || errorData?.error || response.statusText || 'Request failed',
|
|
239
175
|
status: response.status,
|
|
240
176
|
statusText: response.statusText,
|
|
241
177
|
data: errorData
|
|
242
178
|
};
|
|
243
|
-
|
|
244
179
|
// Log error
|
|
245
180
|
if (log === true || log === 'errors') {
|
|
246
181
|
console.error(`[JUX Fetch Error] ${requestInit.method || 'GET'} ${fullUrl}`, error);
|
|
247
182
|
}
|
|
248
|
-
|
|
249
183
|
if (onError) {
|
|
250
184
|
onError(error);
|
|
251
185
|
}
|
|
252
|
-
|
|
253
186
|
return {
|
|
254
187
|
data: null,
|
|
255
188
|
error,
|
|
@@ -257,7 +190,6 @@ async function executeFetch<T = any>(
|
|
|
257
190
|
response
|
|
258
191
|
};
|
|
259
192
|
}
|
|
260
|
-
|
|
261
193
|
// Log success
|
|
262
194
|
if (log === true) {
|
|
263
195
|
console.log(`[JUX Fetch Success] ${requestInit.method || 'GET'} ${fullUrl}`, {
|
|
@@ -265,216 +197,169 @@ async function executeFetch<T = any>(
|
|
|
265
197
|
data
|
|
266
198
|
});
|
|
267
199
|
}
|
|
268
|
-
|
|
269
200
|
return {
|
|
270
201
|
data,
|
|
271
202
|
error: null,
|
|
272
203
|
status: response.status,
|
|
273
204
|
response
|
|
274
205
|
};
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
if (timeoutId)
|
|
278
|
-
|
|
279
|
-
const error
|
|
206
|
+
}
|
|
207
|
+
catch (err) {
|
|
208
|
+
if (timeoutId)
|
|
209
|
+
clearTimeout(timeoutId);
|
|
210
|
+
const error = {
|
|
280
211
|
message: err.name === 'AbortError'
|
|
281
212
|
? 'Request timeout'
|
|
282
213
|
: err.message || 'Network error',
|
|
283
214
|
status: 0
|
|
284
215
|
};
|
|
285
|
-
|
|
286
216
|
// Log error
|
|
287
217
|
if (log === true || log === 'errors') {
|
|
288
218
|
console.error(`[JUX Fetch Error] ${requestInit.method || 'GET'} ${fullUrl}`, error);
|
|
289
219
|
}
|
|
290
|
-
|
|
291
220
|
if (onError) {
|
|
292
221
|
onError(error);
|
|
293
222
|
}
|
|
294
|
-
|
|
295
223
|
return {
|
|
296
224
|
data: null,
|
|
297
225
|
error,
|
|
298
226
|
status: 0,
|
|
299
|
-
response: null
|
|
227
|
+
response: null
|
|
300
228
|
};
|
|
301
229
|
}
|
|
302
230
|
}
|
|
303
|
-
|
|
304
231
|
/**
|
|
305
232
|
* FetchBuilder class for method chaining
|
|
306
233
|
*/
|
|
307
|
-
class FetchBuilder
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
constructor(url: string, options: FetchOptions = {}) {
|
|
234
|
+
class FetchBuilder {
|
|
235
|
+
constructor(url, options = {}) {
|
|
236
|
+
this.options = {};
|
|
312
237
|
this.url = url;
|
|
313
238
|
this.options = options;
|
|
314
239
|
}
|
|
315
|
-
|
|
316
|
-
method(value: string): this {
|
|
240
|
+
method(value) {
|
|
317
241
|
this.options.method = value;
|
|
318
242
|
return this;
|
|
319
243
|
}
|
|
320
|
-
|
|
321
|
-
body(value: any): this {
|
|
244
|
+
body(value) {
|
|
322
245
|
this.options.body = value;
|
|
323
246
|
return this;
|
|
324
247
|
}
|
|
325
|
-
|
|
326
|
-
params(value: Record<string, any>): this {
|
|
248
|
+
params(value) {
|
|
327
249
|
this.options.params = value;
|
|
328
250
|
return this;
|
|
329
251
|
}
|
|
330
|
-
|
|
331
|
-
headers(value: Record<string, string>): this {
|
|
252
|
+
headers(value) {
|
|
332
253
|
this.options.headers = { ...this.options.headers, ...value };
|
|
333
254
|
return this;
|
|
334
255
|
}
|
|
335
|
-
|
|
336
|
-
header(key: string, value: string): this {
|
|
256
|
+
header(key, value) {
|
|
337
257
|
this.options.headers = { ...this.options.headers, [key]: value };
|
|
338
258
|
return this;
|
|
339
259
|
}
|
|
340
|
-
|
|
341
|
-
timeout(value: number): this {
|
|
260
|
+
timeout(value) {
|
|
342
261
|
this.options.timeout = value;
|
|
343
262
|
return this;
|
|
344
263
|
}
|
|
345
|
-
|
|
346
|
-
credentials(value: RequestCredentials): this {
|
|
264
|
+
credentials(value) {
|
|
347
265
|
this.options.credentials = value;
|
|
348
266
|
return this;
|
|
349
267
|
}
|
|
350
|
-
|
|
351
|
-
log(value: LogLevel): this {
|
|
268
|
+
log(value) {
|
|
352
269
|
this.options.log = value;
|
|
353
270
|
return this;
|
|
354
271
|
}
|
|
355
|
-
|
|
356
|
-
parseResponse(value: boolean): this {
|
|
272
|
+
parseResponse(value) {
|
|
357
273
|
this.options.parseResponse = value;
|
|
358
274
|
return this;
|
|
359
275
|
}
|
|
360
|
-
|
|
361
|
-
onUnauthorized(callback: () => void): this {
|
|
276
|
+
onUnauthorized(callback) {
|
|
362
277
|
this.options.onUnauthorized = callback;
|
|
363
278
|
return this;
|
|
364
279
|
}
|
|
365
|
-
|
|
366
|
-
onError(callback: (error: FetchError) => void): this {
|
|
280
|
+
onError(callback) {
|
|
367
281
|
this.options.onError = callback;
|
|
368
282
|
return this;
|
|
369
283
|
}
|
|
370
|
-
|
|
371
284
|
/**
|
|
372
285
|
* Execute the fetch request
|
|
373
286
|
*/
|
|
374
|
-
send()
|
|
375
|
-
return executeFetch
|
|
287
|
+
send() {
|
|
288
|
+
return executeFetch(this.url, this.options);
|
|
376
289
|
}
|
|
377
|
-
|
|
378
290
|
/**
|
|
379
291
|
* Alias for send()
|
|
380
292
|
*/
|
|
381
|
-
fetch()
|
|
293
|
+
fetch() {
|
|
382
294
|
return this.send();
|
|
383
295
|
}
|
|
384
|
-
|
|
385
296
|
/**
|
|
386
297
|
* Make the builder thenable (Promise-like) so it can be awaited directly
|
|
387
298
|
* This allows: await jux.fetch('/users') without needing .send()
|
|
388
299
|
*/
|
|
389
|
-
then
|
|
390
|
-
onfulfilled?: ((value: FetchResult<T>) => TResult1 | PromiseLike<TResult1>) | null,
|
|
391
|
-
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
|
|
392
|
-
): Promise<TResult1 | TResult2> {
|
|
300
|
+
then(onfulfilled, onrejected) {
|
|
393
301
|
return this.send().then(onfulfilled, onrejected);
|
|
394
302
|
}
|
|
395
|
-
|
|
396
303
|
/**
|
|
397
304
|
* Make the builder catchable for Promise.catch()
|
|
398
305
|
*/
|
|
399
|
-
catch
|
|
400
|
-
onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null
|
|
401
|
-
): Promise<FetchResult<T> | TResult> {
|
|
306
|
+
catch(onrejected) {
|
|
402
307
|
return this.send().catch(onrejected);
|
|
403
308
|
}
|
|
404
|
-
|
|
405
309
|
/**
|
|
406
310
|
* Make the builder finally-able for Promise.finally()
|
|
407
311
|
*/
|
|
408
|
-
finally(onfinally
|
|
312
|
+
finally(onfinally) {
|
|
409
313
|
return this.send().finally(onfinally);
|
|
410
314
|
}
|
|
411
315
|
}
|
|
412
|
-
|
|
413
316
|
/**
|
|
414
317
|
* Create a fetch builder
|
|
415
318
|
*/
|
|
416
|
-
export function juxFetch
|
|
417
|
-
return new FetchBuilder
|
|
319
|
+
export function juxFetch(url, options = {}) {
|
|
320
|
+
return new FetchBuilder(url, options);
|
|
418
321
|
}
|
|
419
|
-
|
|
420
322
|
/**
|
|
421
323
|
* Convenience methods for common HTTP verbs
|
|
422
324
|
*/
|
|
423
325
|
export const fetchHelpers = {
|
|
424
|
-
get:
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
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' })
|
|
326
|
+
get: (url, options) => new FetchBuilder(url, { ...options, method: 'GET' }),
|
|
327
|
+
post: (url, body, options) => new FetchBuilder(url, { ...options, method: 'POST', body }),
|
|
328
|
+
put: (url, body, options) => new FetchBuilder(url, { ...options, method: 'PUT', body }),
|
|
329
|
+
patch: (url, body, options) => new FetchBuilder(url, { ...options, method: 'PATCH', body }),
|
|
330
|
+
delete: (url, options) => new FetchBuilder(url, { ...options, method: 'DELETE' })
|
|
438
331
|
};
|
|
439
|
-
|
|
440
332
|
/**
|
|
441
333
|
* Fetch multiple URLs in parallel
|
|
442
334
|
*/
|
|
443
|
-
export async function fetchAll
|
|
444
|
-
urls
|
|
445
|
-
options?: FetchOptions
|
|
446
|
-
): Promise<FetchResult<T>[]> {
|
|
447
|
-
return Promise.all(urls.map(url => executeFetch<T>(url, options)));
|
|
335
|
+
export async function fetchAll(urls, options) {
|
|
336
|
+
return Promise.all(urls.map(url => executeFetch(url, options)));
|
|
448
337
|
}
|
|
449
|
-
|
|
450
338
|
/**
|
|
451
339
|
* Get a service URL from window.juxConfig
|
|
452
340
|
*/
|
|
453
|
-
export function getServiceUrl(serviceName
|
|
454
|
-
if (typeof window === 'undefined')
|
|
455
|
-
|
|
456
|
-
const juxConfig =
|
|
457
|
-
if (!juxConfig?.services)
|
|
458
|
-
|
|
341
|
+
export function getServiceUrl(serviceName) {
|
|
342
|
+
if (typeof window === 'undefined')
|
|
343
|
+
return null;
|
|
344
|
+
const juxConfig = window.juxConfig;
|
|
345
|
+
if (!juxConfig?.services)
|
|
346
|
+
return null;
|
|
459
347
|
return juxConfig.services[serviceName] || null;
|
|
460
348
|
}
|
|
461
|
-
|
|
462
349
|
/**
|
|
463
350
|
* Create a fetch instance preconfigured for a specific service
|
|
464
|
-
*
|
|
351
|
+
*
|
|
465
352
|
* Usage:
|
|
466
353
|
* const api = jux.fetch.serviceClient('database');
|
|
467
354
|
* const { data } = await api.fetch('/users').send();
|
|
468
355
|
*/
|
|
469
|
-
export function serviceClient(serviceName
|
|
356
|
+
export function serviceClient(serviceName) {
|
|
470
357
|
const baseUrl = getServiceUrl(serviceName);
|
|
471
|
-
|
|
472
358
|
if (!baseUrl) {
|
|
473
359
|
console.warn(`[JUX Fetch] Service '${serviceName}' not found in juxConfig.services`);
|
|
474
360
|
}
|
|
475
|
-
|
|
476
361
|
return {
|
|
477
|
-
fetch: (url
|
|
362
|
+
fetch: (url, options) => {
|
|
478
363
|
return juxFetch(url, {
|
|
479
364
|
...options,
|
|
480
365
|
baseUrl: baseUrl || undefined
|
|
@@ -483,11 +368,10 @@ export function serviceClient(serviceName: string) {
|
|
|
483
368
|
baseUrl
|
|
484
369
|
};
|
|
485
370
|
}
|
|
486
|
-
|
|
487
371
|
/**
|
|
488
372
|
* Setup fetch from juxconfig
|
|
489
373
|
* Call this in your bootstrap function
|
|
490
|
-
*
|
|
374
|
+
*
|
|
491
375
|
* Usage:
|
|
492
376
|
* export default {
|
|
493
377
|
* bootstrap: [
|
|
@@ -502,46 +386,36 @@ export async function setupConfig() {
|
|
|
502
386
|
console.warn('[JUX Fetch] setupConfig() called outside browser environment');
|
|
503
387
|
return;
|
|
504
388
|
}
|
|
505
|
-
|
|
506
|
-
const juxConfig = (window as any).juxConfig;
|
|
507
|
-
|
|
389
|
+
const juxConfig = window.juxConfig;
|
|
508
390
|
if (!juxConfig) {
|
|
509
391
|
console.warn('[JUX Fetch] No juxConfig found on window. Make sure your juxconfig.js is loaded.');
|
|
510
392
|
return;
|
|
511
393
|
}
|
|
512
|
-
|
|
513
394
|
const services = juxConfig.services || {};
|
|
514
|
-
|
|
515
395
|
if (Object.keys(services).length === 0) {
|
|
516
396
|
console.log('[JUX Fetch] No services configured in juxConfig');
|
|
517
397
|
return;
|
|
518
398
|
}
|
|
519
|
-
|
|
520
399
|
// Configure fetch with common defaults
|
|
521
|
-
const fetchConfig
|
|
400
|
+
const fetchConfig = {
|
|
522
401
|
timeout: juxConfig.fetchTimeout || 30000,
|
|
523
402
|
log: juxConfig.fetchLog || false,
|
|
524
403
|
credentials: 'include'
|
|
525
404
|
};
|
|
526
|
-
|
|
527
405
|
// Add service-specific handlers
|
|
528
406
|
if (services.auth) {
|
|
529
407
|
fetchConfig.onUnauthorized = () => {
|
|
530
408
|
console.warn('[JUX Fetch] Unauthorized - consider redirecting to login');
|
|
531
409
|
};
|
|
532
410
|
}
|
|
533
|
-
|
|
534
411
|
configureFetch(fetchConfig);
|
|
535
|
-
|
|
536
412
|
// Log configured services
|
|
537
413
|
console.log('[JUX Fetch] Configured with services:', Object.keys(services));
|
|
538
|
-
|
|
539
414
|
return {
|
|
540
415
|
services,
|
|
541
416
|
getServiceUrl
|
|
542
417
|
};
|
|
543
418
|
}
|
|
544
|
-
|
|
545
419
|
// Export combined API
|
|
546
420
|
export const fetchAPI = Object.assign(juxFetch, {
|
|
547
421
|
config: configureFetch,
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a component ID to a human-readable label
|
|
3
|
+
*
|
|
4
|
+
* Examples:
|
|
5
|
+
* 'btn-1' → 'Btn 1'
|
|
6
|
+
* 'btn1' → 'Btn1'
|
|
7
|
+
* 'btn-primary-1' → 'Btn Primary 1'
|
|
8
|
+
* 'user-email-input' → 'User Email Input'
|
|
9
|
+
* 'firstName' → 'First Name'
|
|
10
|
+
* 'first_name' → 'First Name'
|
|
11
|
+
*
|
|
12
|
+
* @param id - Component ID (kebab-case, snake_case, or camelCase)
|
|
13
|
+
* @returns Human-readable label with proper capitalization
|
|
14
|
+
*/
|
|
15
|
+
export declare function formatIdAsLabel(id: string): string;
|
|
16
|
+
//# sourceMappingURL=formatId.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatId.d.ts","sourceRoot":"","sources":["../../../lib/utils/formatId.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAalD"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Convert a component ID to a human-readable label
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* Examples:
|
|
5
5
|
* 'btn-1' → 'Btn 1'
|
|
6
6
|
* 'btn1' → 'Btn1'
|
|
@@ -8,19 +8,18 @@
|
|
|
8
8
|
* 'user-email-input' → 'User Email Input'
|
|
9
9
|
* 'firstName' → 'First Name'
|
|
10
10
|
* 'first_name' → 'First Name'
|
|
11
|
-
*
|
|
11
|
+
*
|
|
12
12
|
* @param id - Component ID (kebab-case, snake_case, or camelCase)
|
|
13
13
|
* @returns Human-readable label with proper capitalization
|
|
14
14
|
*/
|
|
15
|
-
export function formatIdAsLabel(id
|
|
16
|
-
if (!id)
|
|
17
|
-
|
|
15
|
+
export function formatIdAsLabel(id) {
|
|
16
|
+
if (!id)
|
|
17
|
+
return '';
|
|
18
18
|
// Split by common delimiters: hyphens, underscores, or camelCase boundaries
|
|
19
19
|
const words = id
|
|
20
|
-
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
21
|
-
.split(/[-_\s]+/)
|
|
20
|
+
.replace(/([a-z])([A-Z])/g, '$1 $2') // camelCase → separate words
|
|
21
|
+
.split(/[-_\s]+/) // Split by hyphens, underscores, spaces
|
|
22
22
|
.filter(word => word.length > 0);
|
|
23
|
-
|
|
24
23
|
// Capitalize first letter of each word
|
|
25
24
|
return words
|
|
26
25
|
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idgen.d.ts","sourceRoot":"","sources":["../../../lib/utils/idgen.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,MAAM,GAAE,MAAc,EAAE,MAAM,GAAE,MAAU,GAAG,MAAM,CAGrF"}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export default function generateId(prefix: string = 'jux', length: number = 9): string {
|
|
1
|
+
export default function generateId(prefix = 'jux', length = 9) {
|
|
4
2
|
const randomPart = Math.random().toString(36).substr(2, length); // Generate a random string
|
|
5
3
|
return `${prefix}-${randomPart}`;
|
|
6
|
-
}
|
|
4
|
+
}
|