@develia/commons 0.4.2 → 0.4.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.
Files changed (61) hide show
  1. package/dist/cjs/browser/index.js +129 -0
  2. package/dist/cjs/browser/index.js.map +1 -0
  3. package/dist/cjs/index.js +4 -3
  4. package/dist/cjs/index.js.map +1 -1
  5. package/dist/cjs/type-code.js +18 -0
  6. package/dist/cjs/type-code.js.map +1 -0
  7. package/dist/cjs/type.js +212 -12
  8. package/dist/cjs/type.js.map +1 -1
  9. package/dist/cjs/utilities.js +34 -127
  10. package/dist/cjs/utilities.js.map +1 -1
  11. package/dist/esm/browser/index.js +122 -0
  12. package/dist/esm/browser/index.js.map +1 -0
  13. package/dist/esm/index.js +2 -1
  14. package/dist/esm/index.js.map +1 -1
  15. package/dist/esm/type-code.js +16 -0
  16. package/dist/esm/type-code.js.map +1 -0
  17. package/dist/esm/type.js +209 -12
  18. package/dist/esm/type.js.map +1 -1
  19. package/dist/esm/utilities.js +33 -122
  20. package/dist/esm/utilities.js.map +1 -1
  21. package/dist/types/browser/index.d.ts +7 -0
  22. package/dist/types/browser/index.d.ts.map +1 -0
  23. package/dist/types/index.d.ts +2 -1
  24. package/dist/types/index.d.ts.map +1 -1
  25. package/dist/types/patch.d.ts +3 -3
  26. package/dist/types/patch.d.ts.map +1 -1
  27. package/dist/types/type-code.d.ts +15 -0
  28. package/dist/types/type-code.d.ts.map +1 -0
  29. package/dist/types/type.d.ts +45 -11
  30. package/dist/types/type.d.ts.map +1 -1
  31. package/dist/types/types.d.ts +1 -2
  32. package/dist/types/types.d.ts.map +1 -1
  33. package/dist/types/utilities.d.ts +2 -6
  34. package/dist/types/utilities.d.ts.map +1 -1
  35. package/dist/web/browser/index.js +123 -0
  36. package/dist/web/browser/index.js.map +1 -0
  37. package/dist/web/index.js +2 -1
  38. package/dist/web/index.js.map +1 -1
  39. package/dist/web/type-code.js +16 -0
  40. package/dist/web/type-code.js.map +1 -0
  41. package/dist/web/type.js +210 -12
  42. package/dist/web/type.js.map +1 -1
  43. package/dist/web/utilities.js +33 -122
  44. package/dist/web/utilities.js.map +1 -1
  45. package/package.json +1 -1
  46. package/src/browser/index.ts +172 -0
  47. package/src/index.ts +15 -13
  48. package/src/patch.ts +3 -3
  49. package/src/type-code.ts +16 -0
  50. package/src/type.ts +370 -17
  51. package/src/types.ts +1 -5
  52. package/src/utilities.ts +38 -169
  53. package/dist/cjs/remote-data.js +0 -115
  54. package/dist/cjs/remote-data.js.map +0 -1
  55. package/dist/esm/remote-data.js +0 -112
  56. package/dist/esm/remote-data.js.map +0 -1
  57. package/dist/types/remote-data.d.ts +0 -32
  58. package/dist/types/remote-data.d.ts.map +0 -1
  59. package/dist/web/remote-data.js +0 -112
  60. package/dist/web/remote-data.js.map +0 -1
  61. package/src/remote-data.ts +0 -149
package/src/utilities.ts CHANGED
@@ -2,9 +2,44 @@
2
2
 
3
3
 
4
4
  import KeyValuePair from "./key-value-pair.js";
5
- import type {Optional, Resolvable, Supplier} from "./types.js";
5
+ import type {Resolvable} from "./types.js";
6
6
  import Type from "./type.js";
7
7
 
8
+ export function lazy<T extends object>(factory: () => T): T {
9
+ let instance: T | null = null;
10
+
11
+ const getInstance = (): T => {
12
+ if (!instance) {
13
+ instance = factory();
14
+ }
15
+ return instance;
16
+ };
17
+
18
+ return new Proxy({} as T, {
19
+ get(_, prop, receiver) {
20
+ return Reflect.get(getInstance(), prop, receiver);
21
+ },
22
+ set(_, prop, value, receiver) {
23
+ return Reflect.set(getInstance(), prop, value, receiver);
24
+ },
25
+ has(_, prop) {
26
+ return Reflect.has(getInstance(), prop);
27
+ },
28
+ deleteProperty(_, prop) {
29
+ return Reflect.deleteProperty(getInstance(), prop);
30
+ },
31
+ ownKeys() {
32
+ return Reflect.ownKeys(getInstance());
33
+ },
34
+ getOwnPropertyDescriptor(_, prop) {
35
+ return Reflect.getOwnPropertyDescriptor(getInstance(), prop);
36
+ },
37
+ getPrototypeOf() {
38
+ return Reflect.getPrototypeOf(getInstance());
39
+ },
40
+ });
41
+ }
42
+
8
43
  /**
9
44
  * Checks if an object is iterable.
10
45
  *
@@ -134,56 +169,7 @@ export function deepEqual(a: any, b: any): boolean {
134
169
  * @param method - HTTP method to use: 'POST' or 'GET' (default: 'POST').
135
170
  * @param target - Optional parameter specifying the target for the form submission (e.g., '_blank', '_self', '_parent', '_top').
136
171
  */
137
- export function submitForm(
138
- url: string,
139
- data: Record<string, any>,
140
- method: 'POST' | 'GET' = 'POST',
141
- target?: '_blank' | '_self' | '_parent' | '_top'
142
- ): void {
143
-
144
- const form = document.createElement('form');
145
- form.method = method.toUpperCase();
146
- form.action = url;
147
- form.style.display = 'none';
148
-
149
- if (target) {
150
- form.target = target;
151
- }
152
172
 
153
- /**
154
- * Recursively appends inputs to the form, supporting nested keys and arrays.
155
- * @param keyPrefix - Key path, e.g., 'user[name]' or 'tags[]'
156
- * @param value - The value to append (can be nested)
157
- */
158
- const appendInputs = (keyPrefix: string, value: any) => {
159
- if (Array.isArray(value)) {
160
- value.forEach(val => {
161
- appendInputs(`${keyPrefix}[]`, val);
162
- });
163
- } else if (typeof value === 'object' && value !== null) {
164
- for (const subKey in value) {
165
- if (value.hasOwnProperty(subKey)) {
166
- appendInputs(`${keyPrefix}[${subKey}]`, value[subKey]);
167
- }
168
- }
169
- } else {
170
- const input = document.createElement('input');
171
- input.type = 'hidden';
172
- input.name = keyPrefix;
173
- input.value = String(value);
174
- form.appendChild(input);
175
- }
176
- };
177
-
178
- for (const key in data) {
179
- if (data.hasOwnProperty(key)) {
180
- appendInputs(key, data[key]);
181
- }
182
- }
183
-
184
- document.body.appendChild(form);
185
- form.submit();
186
- }
187
173
 
188
174
  /**
189
175
  * Compares two objects or arrays to check if they have the same immediate fields and values,
@@ -319,30 +305,6 @@ export function isEmptyOrWhitespace(value: any): boolean {
319
305
  }
320
306
 
321
307
 
322
- /**
323
- * Submits a form via AJAX and returns a Promise that resolves to the Response object.
324
- *
325
- * @param {HTMLFormElement | string} selectorOrElement - The form element or selector.
326
- * @return {Promise<Response>} A Promise that resolves to the Response object.
327
- * @throws {Error} If the element is invalid.
328
- */
329
- export async function ajaxSubmit(selectorOrElement: HTMLFormElement | string): Promise<Response> {
330
-
331
- const form = typeof selectorOrElement === 'string'
332
- ? document.querySelector(selectorOrElement)
333
- : selectorOrElement;
334
-
335
- if (!(form instanceof HTMLFormElement)) {
336
- throw new Error("Invalid element.");
337
- }
338
-
339
- // Crear un objeto FormData a partir del formulario
340
- return await fetch(form.action, {
341
- method: form.method,
342
- body: new FormData(form),
343
- });
344
- }
345
-
346
308
  /**
347
309
  * Converts an object into an array of key-value pairs.
348
310
  *
@@ -386,34 +348,6 @@ export function promisify<T>(thing: Resolvable<T>): Promise<T> {
386
348
  }
387
349
 
388
350
 
389
- export function ajaxSubmission(selectorOrElement: HTMLFormElement | string,
390
- onSuccess: Optional<Supplier<any>> = undefined,
391
- onFailure: Optional<Supplier<any>> = undefined): void {
392
-
393
- const form = typeof selectorOrElement === 'string'
394
- ? document.querySelector(selectorOrElement)
395
- : selectorOrElement;
396
-
397
- if (!(form instanceof HTMLFormElement)) {
398
- return;
399
- }
400
-
401
- form.addEventListener('submit', async (event) => {
402
- event.preventDefault();
403
- let promise = ajaxSubmit(form);
404
- if (promise) {
405
- if (onSuccess)
406
- promise = promise.then(onSuccess);
407
- if (onFailure)
408
- promise.catch(onFailure);
409
- }
410
-
411
- });
412
-
413
-
414
- }
415
-
416
-
417
351
  /**
418
352
  * Creates a deep clone of the given object.
419
353
  * @template T
@@ -447,77 +381,12 @@ export function deepClone<T>(obj: T): T {
447
381
  *
448
382
  * @param {any} value - The value to determine the type of.
449
383
  * @return {Type} - The type of the given value.
384
+ * @deprecated use Type.of(...)
450
385
  */
451
386
  export function getType(value: any): Type {
452
387
 
453
- return value === null ? Type.Null : Type[typeof value as keyof typeof Type];
388
+ return Type.of(value);
454
389
  }
455
390
 
456
- export function formToObject(form: HTMLFormElement): Record<string, FormDataEntryValue | FormDataEntryValue[]> {
457
- const fd = new FormData(form);
458
- const out: Record<string, FormDataEntryValue | FormDataEntryValue[]> = {};
459
-
460
- for (const [key, value] of fd.entries()) {
461
- if (key in out) {
462
- const current = out[key];
463
- if (Array.isArray(current)) {
464
- current.push(value);
465
- } else {
466
- out[key] = [current, value];
467
- }
468
- } else {
469
- out[key] = value;
470
- }
471
- }
472
391
 
473
- return out;
474
- }
475
392
 
476
- /**
477
- * Converts an object to `FormData` format recursively.
478
- *
479
- * @param {Record<string, any>} data - The object data to convert.
480
- * @param {FormData} formData - The `FormData` instance to append data to.
481
- * @param {string} parentKey - The parent key to append to child keys in the `FormData`.
482
- * @returns {FormData} - The `FormData` instance with the converted data.
483
- */
484
- function _objectToFormData(data: Record<string, any>, formData: FormData, parentKey: string = ''): FormData {
485
-
486
- for (const key in data) {
487
- if (data.hasOwnProperty(key)) {
488
- const value = data[key];
489
-
490
- if (value instanceof Date) {
491
- formData.append(parentKey ? `${parentKey}[${key}]` : key, value.toISOString());
492
- } else if (value instanceof File) {
493
- formData.append(parentKey ? `${parentKey}[${key}]` : key, value);
494
- } else if (typeof value === 'object' && !Array.isArray(value)) {
495
- _objectToFormData(value, formData, parentKey ? `${parentKey}[${key}]` : key);
496
- } else if (Array.isArray(value)) {
497
- value.forEach((item, index) => {
498
- const arrayKey = `${parentKey ? `${parentKey}[${key}]` : key}[${index}]`;
499
- if (typeof item === 'object' && !Array.isArray(item)) {
500
- _objectToFormData(item, formData, arrayKey);
501
- } else {
502
- formData.append(arrayKey, item);
503
- }
504
- });
505
- } else {
506
- formData.append(parentKey ? `${parentKey}[${key}]` : key, value);
507
- }
508
- }
509
- }
510
-
511
- return formData;
512
- }
513
-
514
- /**
515
- * Converts an object into FormData.
516
- *
517
- * @param {Record<string, any>} data - The object to be converted into FormData.
518
- * @return {FormData} - The FormData object representing the converted data.
519
- */
520
- export function objectToFormData(data: Record<string, any>): FormData {
521
- let formData = new FormData();
522
- return _objectToFormData(data, formData);
523
- }
@@ -1,115 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- class RemoteData {
4
- constructor(url, options = {}) {
5
- this._loaded = false;
6
- this._loading = false;
7
- this._data = null;
8
- this._error = null;
9
- this._promise = null;
10
- this._url = url;
11
- this._options = options;
12
- if (options.initialData !== undefined) {
13
- this._data = options.initialData;
14
- this._loaded = true;
15
- }
16
- }
17
- get url() {
18
- return this._url;
19
- }
20
- set url(value) {
21
- if (this._url !== value) {
22
- this._url = value;
23
- this._loaded = false;
24
- }
25
- }
26
- get loaded() {
27
- return this._loaded;
28
- }
29
- get loading() {
30
- return this._loading;
31
- }
32
- get error() {
33
- return this._error;
34
- }
35
- get succeeded() {
36
- return this._loaded && !this._error;
37
- }
38
- get data() {
39
- return this._data;
40
- }
41
- async getData() {
42
- if (!this._loaded) {
43
- await this.load();
44
- }
45
- return this._data;
46
- }
47
- async load() {
48
- if (this._loading && this._promise) {
49
- return this._promise;
50
- }
51
- this._promise = this._fetchWithRetries();
52
- return this._promise;
53
- }
54
- reset() {
55
- this._loaded = false;
56
- this._loading = false;
57
- this._data = null;
58
- this._error = null;
59
- this._promise = null;
60
- }
61
- async _fetchWithRetries() {
62
- const maxAttempts = (this._options.retries ?? 0) + 1;
63
- const retryDelay = this._options.retryDelay ?? 1000;
64
- for (let attempt = 1; attempt <= maxAttempts; attempt++) {
65
- try {
66
- return await this._doFetch();
67
- }
68
- catch (error) {
69
- if (attempt === maxAttempts)
70
- throw this._error;
71
- await new Promise((r) => setTimeout(r, retryDelay));
72
- }
73
- }
74
- return null;
75
- }
76
- async _doFetch() {
77
- try {
78
- this._error = null;
79
- this._loading = true;
80
- const fetchOptions = this._buildFetchOptions();
81
- const response = await fetch(this._url, fetchOptions);
82
- if (!response.ok) {
83
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
84
- }
85
- const raw = await response.json();
86
- this._data = this._options.transform
87
- ? this._options.transform(raw)
88
- : raw;
89
- this._loaded = true;
90
- return this._data;
91
- }
92
- catch (error) {
93
- this._error = error instanceof Error
94
- ? error
95
- : new Error(String(error));
96
- this._loaded = false;
97
- throw this._error;
98
- }
99
- finally {
100
- this._loading = false;
101
- this._promise = null;
102
- }
103
- }
104
- _buildFetchOptions() {
105
- const options = { ...this._options.fetchOptions };
106
- if (this._options.timeout && this._options.timeout > 0) {
107
- const controller = new AbortController();
108
- setTimeout(() => controller.abort(), this._options.timeout);
109
- options.signal = controller.signal;
110
- }
111
- return options;
112
- }
113
- }
114
- exports.default = RemoteData;
115
- //# sourceMappingURL=remote-data.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"remote-data.js","sourceRoot":"","sources":["../../src/remote-data.ts"],"names":[],"mappings":"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"}
@@ -1,112 +0,0 @@
1
- export default class RemoteData {
2
- constructor(url, options = {}) {
3
- this._loaded = false;
4
- this._loading = false;
5
- this._data = null;
6
- this._error = null;
7
- this._promise = null;
8
- this._url = url;
9
- this._options = options;
10
- if (options.initialData !== undefined) {
11
- this._data = options.initialData;
12
- this._loaded = true;
13
- }
14
- }
15
- get url() {
16
- return this._url;
17
- }
18
- set url(value) {
19
- if (this._url !== value) {
20
- this._url = value;
21
- this._loaded = false;
22
- }
23
- }
24
- get loaded() {
25
- return this._loaded;
26
- }
27
- get loading() {
28
- return this._loading;
29
- }
30
- get error() {
31
- return this._error;
32
- }
33
- get succeeded() {
34
- return this._loaded && !this._error;
35
- }
36
- get data() {
37
- return this._data;
38
- }
39
- async getData() {
40
- if (!this._loaded) {
41
- await this.load();
42
- }
43
- return this._data;
44
- }
45
- async load() {
46
- if (this._loading && this._promise) {
47
- return this._promise;
48
- }
49
- this._promise = this._fetchWithRetries();
50
- return this._promise;
51
- }
52
- reset() {
53
- this._loaded = false;
54
- this._loading = false;
55
- this._data = null;
56
- this._error = null;
57
- this._promise = null;
58
- }
59
- async _fetchWithRetries() {
60
- const maxAttempts = (this._options.retries ?? 0) + 1;
61
- const retryDelay = this._options.retryDelay ?? 1000;
62
- for (let attempt = 1; attempt <= maxAttempts; attempt++) {
63
- try {
64
- return await this._doFetch();
65
- }
66
- catch (error) {
67
- if (attempt === maxAttempts)
68
- throw this._error;
69
- await new Promise((r) => setTimeout(r, retryDelay));
70
- }
71
- }
72
- return null;
73
- }
74
- async _doFetch() {
75
- try {
76
- this._error = null;
77
- this._loading = true;
78
- const fetchOptions = this._buildFetchOptions();
79
- const response = await fetch(this._url, fetchOptions);
80
- if (!response.ok) {
81
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
82
- }
83
- const raw = await response.json();
84
- this._data = this._options.transform
85
- ? this._options.transform(raw)
86
- : raw;
87
- this._loaded = true;
88
- return this._data;
89
- }
90
- catch (error) {
91
- this._error = error instanceof Error
92
- ? error
93
- : new Error(String(error));
94
- this._loaded = false;
95
- throw this._error;
96
- }
97
- finally {
98
- this._loading = false;
99
- this._promise = null;
100
- }
101
- }
102
- _buildFetchOptions() {
103
- const options = { ...this._options.fetchOptions };
104
- if (this._options.timeout && this._options.timeout > 0) {
105
- const controller = new AbortController();
106
- setTimeout(() => controller.abort(), this._options.timeout);
107
- options.signal = controller.signal;
108
- }
109
- return options;
110
- }
111
- }
112
- //# sourceMappingURL=remote-data.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"remote-data.js","sourceRoot":"","sources":["../../src/remote-data.ts"],"names":[],"mappings":"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"}
@@ -1,32 +0,0 @@
1
- export interface RemoteDataOptions<T = unknown> {
2
- fetchOptions?: RequestInit;
3
- transform?: (raw: unknown) => T;
4
- timeout?: number;
5
- retries?: number;
6
- retryDelay?: number;
7
- initialData?: T;
8
- }
9
- export default class RemoteData<T = unknown> {
10
- _loaded: boolean;
11
- _loading: boolean;
12
- _data: T | null;
13
- _url: string;
14
- _error: Error | null;
15
- _promise: Promise<T | null> | null;
16
- _options: RemoteDataOptions<T>;
17
- constructor(url: string, options?: RemoteDataOptions<T>);
18
- get url(): string;
19
- set url(value: string);
20
- get loaded(): boolean;
21
- get loading(): boolean;
22
- get error(): Error | null;
23
- get succeeded(): boolean;
24
- get data(): T | null;
25
- getData(): Promise<T | null>;
26
- load(): Promise<T | null>;
27
- reset(): void;
28
- _fetchWithRetries(): Promise<T | null>;
29
- _doFetch(): Promise<T | null>;
30
- _buildFetchOptions(): RequestInit;
31
- }
32
- //# sourceMappingURL=remote-data.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"remote-data.d.ts","sourceRoot":"","sources":["../../src/remote-data.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB,CAAC,CAAC,GAAG,OAAO;IAE1C,YAAY,CAAC,EAAE,WAAW,CAAC;IAE3B,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,CAAC,CAAC;IAEhC,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,WAAW,CAAC,EAAE,CAAC,CAAC;CACnB;AAED,MAAM,CAAC,OAAO,OAAO,UAAU,CAAC,CAAC,GAAG,OAAO;IACvC,OAAO,EAAE,OAAO,CAAS;IACzB,QAAQ,EAAE,OAAO,CAAS;IAC1B,KAAK,EAAE,CAAC,GAAG,IAAI,CAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,KAAK,GAAG,IAAI,CAAQ;IAC5B,QAAQ,EAAE,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAQ;IAC1C,QAAQ,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;gBAEnB,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAiB,CAAC,CAAC,CAAM;IAU3D,IAAI,GAAG,IAAI,MAAM,CAEhB;IAED,IAAI,GAAG,CAAC,KAAK,EAAE,MAAM,EAKpB;IAED,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAI,KAAK,IAAI,KAAK,GAAG,IAAI,CAExB;IAED,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,IAAI,IAAI,IAAI,CAAC,GAAG,IAAI,CAEnB;IAEK,OAAO,IAAI,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAO5B,IAAI,IAAI,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAQ/B,KAAK,IAAI,IAAI;IAUP,iBAAiB,IAAI,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAgBtC,QAAQ,IAAI,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IA+BnC,kBAAkB,IAAI,WAAW;CAWpC"}
@@ -1,112 +0,0 @@
1
- export default class RemoteData {
2
- constructor(url, options = {}) {
3
- this._loaded = false;
4
- this._loading = false;
5
- this._data = null;
6
- this._error = null;
7
- this._promise = null;
8
- this._url = url;
9
- this._options = options;
10
- if (options.initialData !== undefined) {
11
- this._data = options.initialData;
12
- this._loaded = true;
13
- }
14
- }
15
- get url() {
16
- return this._url;
17
- }
18
- set url(value) {
19
- if (this._url !== value) {
20
- this._url = value;
21
- this._loaded = false;
22
- }
23
- }
24
- get loaded() {
25
- return this._loaded;
26
- }
27
- get loading() {
28
- return this._loading;
29
- }
30
- get error() {
31
- return this._error;
32
- }
33
- get succeeded() {
34
- return this._loaded && !this._error;
35
- }
36
- get data() {
37
- return this._data;
38
- }
39
- async getData() {
40
- if (!this._loaded) {
41
- await this.load();
42
- }
43
- return this._data;
44
- }
45
- async load() {
46
- if (this._loading && this._promise) {
47
- return this._promise;
48
- }
49
- this._promise = this._fetchWithRetries();
50
- return this._promise;
51
- }
52
- reset() {
53
- this._loaded = false;
54
- this._loading = false;
55
- this._data = null;
56
- this._error = null;
57
- this._promise = null;
58
- }
59
- async _fetchWithRetries() {
60
- const maxAttempts = (this._options.retries ?? 0) + 1;
61
- const retryDelay = this._options.retryDelay ?? 1000;
62
- for (let attempt = 1; attempt <= maxAttempts; attempt++) {
63
- try {
64
- return await this._doFetch();
65
- }
66
- catch (error) {
67
- if (attempt === maxAttempts)
68
- throw this._error;
69
- await new Promise((r) => setTimeout(r, retryDelay));
70
- }
71
- }
72
- return null;
73
- }
74
- async _doFetch() {
75
- try {
76
- this._error = null;
77
- this._loading = true;
78
- const fetchOptions = this._buildFetchOptions();
79
- const response = await fetch(this._url, fetchOptions);
80
- if (!response.ok) {
81
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
82
- }
83
- const raw = await response.json();
84
- this._data = this._options.transform
85
- ? this._options.transform(raw)
86
- : raw;
87
- this._loaded = true;
88
- return this._data;
89
- }
90
- catch (error) {
91
- this._error = error instanceof Error
92
- ? error
93
- : new Error(String(error));
94
- this._loaded = false;
95
- throw this._error;
96
- }
97
- finally {
98
- this._loading = false;
99
- this._promise = null;
100
- }
101
- }
102
- _buildFetchOptions() {
103
- const options = { ...this._options.fetchOptions };
104
- if (this._options.timeout && this._options.timeout > 0) {
105
- const controller = new AbortController();
106
- setTimeout(() => controller.abort(), this._options.timeout);
107
- options.signal = controller.signal;
108
- }
109
- return options;
110
- }
111
- }
112
- //# sourceMappingURL=remote-data.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"remote-data.js","sourceRoot":"","sources":["../../src/remote-data.ts"],"names":[],"mappings":"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"}