juxscript 1.0.132 → 1.1.2

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