dalila 1.8.2 → 1.8.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 (89) hide show
  1. package/dist/cli/routes-generator.js +1 -2
  2. package/dist/components/ui/dialog/index.d.ts +0 -8
  3. package/dist/components/ui/dialog/index.js +2 -41
  4. package/dist/components/ui/dialog/internal.d.ts +5 -0
  5. package/dist/{componentes/ui/dialog/index.js → components/ui/dialog/internal.js} +1 -23
  6. package/dist/components/ui/drawer/index.js +2 -2
  7. package/dist/components/ui/index.d.ts +1 -1
  8. package/dist/components/ui/index.js +1 -1
  9. package/dist/core/index.d.ts +1 -1
  10. package/dist/core/index.js +1 -1
  11. package/dist/core/query.js +9 -7
  12. package/dist/core/resource.d.ts +23 -171
  13. package/dist/core/resource.js +178 -15
  14. package/dist/form/index.d.ts +1 -1
  15. package/dist/form/index.js +1 -1
  16. package/dist/router/index.d.ts +1 -1
  17. package/dist/router/index.js +1 -1
  18. package/dist/runtime/bind.d.ts +10 -0
  19. package/dist/runtime/bind.js +382 -53
  20. package/package.json +1 -1
  21. package/dist/componentes/ui/accordion/index.d.ts +0 -2
  22. package/dist/componentes/ui/accordion/index.js +0 -114
  23. package/dist/componentes/ui/calendar/index.d.ts +0 -2
  24. package/dist/componentes/ui/calendar/index.js +0 -132
  25. package/dist/componentes/ui/combobox/index.d.ts +0 -2
  26. package/dist/componentes/ui/combobox/index.js +0 -161
  27. package/dist/componentes/ui/dialog/index.d.ts +0 -10
  28. package/dist/componentes/ui/drawer/index.d.ts +0 -2
  29. package/dist/componentes/ui/drawer/index.js +0 -41
  30. package/dist/componentes/ui/dropdown/index.d.ts +0 -2
  31. package/dist/componentes/ui/dropdown/index.js +0 -48
  32. package/dist/componentes/ui/dropzone/index.d.ts +0 -2
  33. package/dist/componentes/ui/dropzone/index.js +0 -92
  34. package/dist/componentes/ui/env.d.ts +0 -1
  35. package/dist/componentes/ui/env.js +0 -2
  36. package/dist/componentes/ui/index.d.ts +0 -13
  37. package/dist/componentes/ui/index.js +0 -12
  38. package/dist/componentes/ui/popover/index.d.ts +0 -2
  39. package/dist/componentes/ui/popover/index.js +0 -156
  40. package/dist/componentes/ui/runtime.d.ts +0 -20
  41. package/dist/componentes/ui/runtime.js +0 -421
  42. package/dist/componentes/ui/tabs/index.d.ts +0 -3
  43. package/dist/componentes/ui/tabs/index.js +0 -101
  44. package/dist/componentes/ui/toast/index.d.ts +0 -3
  45. package/dist/componentes/ui/toast/index.js +0 -115
  46. package/dist/componentes/ui/ui-types.d.ts +0 -175
  47. package/dist/componentes/ui/ui-types.js +0 -1
  48. package/dist/componentes/ui/validate.d.ts +0 -7
  49. package/dist/componentes/ui/validate.js +0 -71
  50. package/dist/core/store.d.ts +0 -130
  51. package/dist/core/store.js +0 -234
  52. package/dist/core/virtual.d.ts +0 -26
  53. package/dist/core/virtual.js +0 -277
  54. package/dist/core/watch-testing.d.ts +0 -13
  55. package/dist/core/watch-testing.js +0 -16
  56. package/dist/router/route.d.ts +0 -23
  57. package/dist/router/route.js +0 -48
  58. package/dist/simple.d.ts +0 -11
  59. package/dist/simple.js +0 -11
  60. package/dist/ui/accordion.d.ts +0 -2
  61. package/dist/ui/accordion.js +0 -114
  62. package/dist/ui/calendar.d.ts +0 -2
  63. package/dist/ui/calendar.js +0 -132
  64. package/dist/ui/combobox.d.ts +0 -2
  65. package/dist/ui/combobox.js +0 -161
  66. package/dist/ui/dialog.d.ts +0 -10
  67. package/dist/ui/dialog.js +0 -54
  68. package/dist/ui/drawer.d.ts +0 -2
  69. package/dist/ui/drawer.js +0 -41
  70. package/dist/ui/dropdown.d.ts +0 -2
  71. package/dist/ui/dropdown.js +0 -48
  72. package/dist/ui/dropzone.d.ts +0 -2
  73. package/dist/ui/dropzone.js +0 -92
  74. package/dist/ui/env.d.ts +0 -1
  75. package/dist/ui/env.js +0 -2
  76. package/dist/ui/index.d.ts +0 -13
  77. package/dist/ui/index.js +0 -12
  78. package/dist/ui/popover.d.ts +0 -2
  79. package/dist/ui/popover.js +0 -156
  80. package/dist/ui/runtime.d.ts +0 -20
  81. package/dist/ui/runtime.js +0 -421
  82. package/dist/ui/tabs.d.ts +0 -3
  83. package/dist/ui/tabs.js +0 -101
  84. package/dist/ui/toast.d.ts +0 -3
  85. package/dist/ui/toast.js +0 -115
  86. package/dist/ui/ui-types.d.ts +0 -175
  87. package/dist/ui/ui-types.js +0 -1
  88. package/dist/ui/validate.d.ts +0 -7
  89. package/dist/ui/validate.js +0 -71
@@ -1,4 +1,4 @@
1
- import { signal, effectAsync } from "./signal.js";
1
+ import { signal, effect, effectAsync } from "./signal.js";
2
2
  import { isInDevMode } from "./dev.js";
3
3
  import { getCurrentScope, createScope, isScopeDisposed, withScope } from "./scope.js";
4
4
  function createDeferred() {
@@ -33,7 +33,7 @@ function createDeferred() {
33
33
  * - dispose the driver
34
34
  * - resolve all pending waiters (avoid hanging Promises)
35
35
  */
36
- export function createResource(fetchFn, options = {}) {
36
+ function createResourceBase(fetchFn, options = {}) {
37
37
  const data = signal(options.initialValue ?? null);
38
38
  const loading = signal(false);
39
39
  const error = signal(null);
@@ -154,6 +154,152 @@ export function createResource(fetchFn, options = {}) {
154
154
  }
155
155
  return { data, loading, error, refresh };
156
156
  }
157
+ function normalizeResourceCachePolicy(cache) {
158
+ if (!cache)
159
+ return null;
160
+ if (typeof cache === "string")
161
+ return { key: cache };
162
+ return cache;
163
+ }
164
+ function attachResourceRefreshInterval(resource, refreshInterval) {
165
+ const scope = getCurrentScope();
166
+ if (!scope) {
167
+ if (isInDevMode()) {
168
+ console.warn(`[Dalila] createResource(..., { refreshInterval }) called outside a scope. ` +
169
+ `Auto-refresh will not work. Use within a scope or manage cleanup manually.`);
170
+ }
171
+ return;
172
+ }
173
+ const intervalId = setInterval(() => {
174
+ resource.refresh().catch(() => { });
175
+ }, refreshInterval);
176
+ scope.onCleanup(() => {
177
+ clearInterval(intervalId);
178
+ });
179
+ }
180
+ function enqueueForcedRefresh(resource) {
181
+ queueMicrotask(() => {
182
+ resource.refresh({ force: true }).catch(() => { });
183
+ });
184
+ }
185
+ function createDynamicCachedResource(fetchFn, cachePolicy, options) {
186
+ const ownerScope = getCurrentScope();
187
+ const rawKey = cachePolicy.key;
188
+ const keyGetter = typeof rawKey === "function"
189
+ ? rawKey
190
+ : () => rawKey;
191
+ const deps = options.deps;
192
+ const cachedOptions = {
193
+ initialValue: options.initialValue,
194
+ onError: options.onError,
195
+ onSuccess: options.onSuccess,
196
+ ttlMs: cachePolicy.ttlMs,
197
+ tags: cachePolicy.tags,
198
+ persist: cachePolicy.persist,
199
+ };
200
+ let activeKey = null;
201
+ let activeKeyScope = null;
202
+ let activeResource = null;
203
+ const activeResourceSignal = signal(null);
204
+ let first = true;
205
+ const activateKey = (key) => {
206
+ if (activeResource && activeKey === key) {
207
+ return activeResource;
208
+ }
209
+ if (ownerScope) {
210
+ activeKeyScope?.dispose();
211
+ const keyScope = createScope(ownerScope);
212
+ activeKeyScope = keyScope;
213
+ activeResource = withScope(keyScope, () => createCachedResource(key, fetchFn, cachedOptions));
214
+ }
215
+ else {
216
+ // Outside a scope, createCachedResource already applies safe-by-default semantics.
217
+ activeResource = createCachedResource(key, fetchFn, cachedOptions);
218
+ }
219
+ activeKey = key;
220
+ activeResourceSignal.set(activeResource);
221
+ return activeResource;
222
+ };
223
+ effect(() => {
224
+ if (deps)
225
+ deps();
226
+ const key = keyGetter();
227
+ const previousKey = activeKey;
228
+ const resource = activateKey(key);
229
+ // If deps changed but key stayed the same, revalidate current entry.
230
+ if (!first && deps && previousKey === key) {
231
+ enqueueForcedRefresh(resource);
232
+ }
233
+ if (first) {
234
+ first = false;
235
+ }
236
+ });
237
+ if (ownerScope) {
238
+ ownerScope.onCleanup(() => {
239
+ activeKeyScope?.dispose();
240
+ activeKeyScope = null;
241
+ });
242
+ }
243
+ return {
244
+ data: () => activeResourceSignal()?.data() ?? null,
245
+ loading: () => activeResourceSignal()?.loading() ?? false,
246
+ error: () => activeResourceSignal()?.error() ?? null,
247
+ refresh: (opts) => activeResourceSignal()?.refresh(opts) ?? Promise.resolve(),
248
+ };
249
+ }
250
+ export function createResource(fetchFn, options = {}) {
251
+ const { deps, refreshInterval } = options;
252
+ const cachePolicy = normalizeResourceCachePolicy(options.cache);
253
+ const fetchFnForCached = deps
254
+ ? async (signal) => {
255
+ // Keep deps ownership explicit (via options.deps) when cache is enabled.
256
+ // This avoids duplicate revalidations from sync reads inside fetchFn.
257
+ await Promise.resolve();
258
+ return fetchFn(signal);
259
+ }
260
+ : fetchFn;
261
+ const baseOptions = {
262
+ initialValue: options.initialValue,
263
+ onError: options.onError,
264
+ onSuccess: options.onSuccess,
265
+ };
266
+ let resource;
267
+ if (cachePolicy) {
268
+ const key = cachePolicy.key;
269
+ if (typeof key === "function") {
270
+ resource = createDynamicCachedResource(fetchFnForCached, cachePolicy, options);
271
+ }
272
+ else {
273
+ resource = createCachedResource(key, fetchFnForCached, {
274
+ ...baseOptions,
275
+ ttlMs: cachePolicy.ttlMs,
276
+ tags: cachePolicy.tags,
277
+ persist: cachePolicy.persist,
278
+ });
279
+ if (deps) {
280
+ let first = true;
281
+ effect(() => {
282
+ deps();
283
+ if (first) {
284
+ first = false;
285
+ return;
286
+ }
287
+ enqueueForcedRefresh(resource);
288
+ });
289
+ }
290
+ }
291
+ }
292
+ else if (deps) {
293
+ resource = createDependentResource((signal) => fetchFn(signal), deps, baseOptions);
294
+ }
295
+ else {
296
+ resource = createResourceBase(fetchFn, baseOptions);
297
+ }
298
+ if (refreshInterval != null && refreshInterval > 0) {
299
+ attachResourceRefreshInterval(resource, refreshInterval);
300
+ }
301
+ return resource;
302
+ }
157
303
  /**
158
304
  * Fetch helper built on top of createResource().
159
305
  *
@@ -162,18 +308,22 @@ export function createResource(fetchFn, options = {}) {
162
308
  * - Uses fetch() with AbortSignal.
163
309
  * - Non-2xx responses throw (surfaced via resource.error()).
164
310
  */
165
- export function createFetchResource(url, options = {}) {
311
+ function createFetchResource(url, options = {}) {
312
+ return resourceFromUrl(url, options);
313
+ }
314
+ export function resourceFromUrl(url, options = {}) {
315
+ const { fetchOptions, ...resourceOptions } = options;
166
316
  return createResource(async (signal) => {
167
317
  const fetchUrl = typeof url === "function" ? url() : url;
168
318
  const response = await fetch(fetchUrl, {
169
- ...options.fetchOptions,
319
+ ...fetchOptions,
170
320
  signal,
171
321
  });
172
322
  if (!response.ok) {
173
323
  throw new Error(`HTTP error! status: ${response.status}`);
174
324
  }
175
325
  return (await response.json());
176
- }, options);
326
+ }, resourceOptions);
177
327
  }
178
328
  /**
179
329
  * Resource that revalidates when dependencies change.
@@ -196,7 +346,7 @@ export function createFetchResource(url, options = {}) {
196
346
  * we must not resolve refresh waiters prematurely.
197
347
  * Guard: early-return resolves only if `!loading()`.
198
348
  */
199
- export function createDependentResource(fetchFn, deps, options = {}) {
349
+ function createDependentResource(fetchFn, deps, options = {}) {
200
350
  const data = signal(options.initialValue ?? null);
201
351
  const loading = signal(false);
202
352
  const error = signal(null);
@@ -440,7 +590,7 @@ function evictIfNeeded() {
440
590
  * - Each entry has a dedicated cacheScope, disposed when the entry is removed.
441
591
  * - Scopes referencing an entry increment refCount; on scope cleanup they release it.
442
592
  */
443
- export function createCachedResource(key, fetchFn, options = {}) {
593
+ function createCachedResource(key, fetchFn, options = {}) {
444
594
  const scope = getCurrentScope();
445
595
  const fetchScope = options.fetchScope && !isScopeDisposed(options.fetchScope) ? options.fetchScope : null;
446
596
  const wrappedFetch = fetchScope
@@ -462,7 +612,7 @@ export function createCachedResource(key, fetchFn, options = {}) {
462
612
  `No caching will happen. Use persist: true (or q.queryGlobal) for global cache.`);
463
613
  }
464
614
  }
465
- return createResource(wrappedFetch, options);
615
+ return createResourceBase(wrappedFetch, options);
466
616
  }
467
617
  const now = Date.now();
468
618
  const existing = resourceCache.get(key);
@@ -509,7 +659,7 @@ export function createCachedResource(key, fetchFn, options = {}) {
509
659
  * Create the resource inside cacheScope so its subscriptions, effects, and abort handling
510
660
  * belong to the cache entry itself.
511
661
  */
512
- const resource = withScope(cacheScope, () => createResource(wrappedFetch, options));
662
+ const resource = withScope(cacheScope, () => createResourceBase(wrappedFetch, options));
513
663
  const entry = {
514
664
  resource,
515
665
  createdAt: now,
@@ -533,7 +683,7 @@ export function createCachedResource(key, fetchFn, options = {}) {
533
683
  /**
534
684
  * Convenience wrapper: builds the cache key from an id.
535
685
  */
536
- export function createCachedResourceById(id, keyFn, fetchFn, options = {}) {
686
+ function createCachedResourceById(id, keyFn, fetchFn, options = {}) {
537
687
  const key = keyFn(id);
538
688
  return createCachedResource(key, (sig) => fetchFn(sig, id), options);
539
689
  }
@@ -698,9 +848,9 @@ function removeCacheKey(key) {
698
848
  * - Requires a scope so the interval can be cleaned up automatically.
699
849
  * - Outside a scope, it warns and returns a normal resource (no interval).
700
850
  */
701
- export function createAutoRefreshResource(fetchFn, refreshInterval, options = {}) {
851
+ function createAutoRefreshResource(fetchFn, refreshInterval, options = {}) {
702
852
  const scope = getCurrentScope();
703
- const resource = createResource(fetchFn, options);
853
+ const resource = createResourceBase(fetchFn, options);
704
854
  if (!scope) {
705
855
  if (isInDevMode()) {
706
856
  console.warn(`[Dalila] createAutoRefreshResource called outside a scope. ` +
@@ -716,7 +866,20 @@ export function createAutoRefreshResource(fetchFn, refreshInterval, options = {}
716
866
  });
717
867
  return resource;
718
868
  }
719
- export function createIsolatedCache() {
869
+ export function createResourceCache(config = {}) {
870
+ const isolated = createIsolatedCache();
871
+ isolated.configure(config);
872
+ return {
873
+ create: isolated.createCachedResource,
874
+ clear: isolated.clearCache,
875
+ invalidate: isolated.invalidateKey,
876
+ invalidateTag: isolated.invalidateTag,
877
+ invalidateTags: isolated.invalidateTags,
878
+ keys: () => Array.from(isolated.getCache().keys()),
879
+ configure: isolated.configure,
880
+ };
881
+ }
882
+ function createIsolatedCache() {
720
883
  // Isolated state
721
884
  const isolatedCache = new Map();
722
885
  const isolatedTagIndex = new Map();
@@ -828,7 +991,7 @@ export function createIsolatedCache() {
828
991
  console.warn(`[Dalila] createCachedResource("${key}") called outside a scope. ` +
829
992
  `No caching will happen. Use persist: true for global cache.`);
830
993
  }
831
- return createResource(wrappedFetch, options);
994
+ return createResourceBase(wrappedFetch, options);
832
995
  }
833
996
  const now = Date.now();
834
997
  const existing = isolatedCache.get(key);
@@ -860,7 +1023,7 @@ export function createIsolatedCache() {
860
1023
  }
861
1024
  }
862
1025
  const cacheScope = createScope(null);
863
- const resource = withScope(cacheScope, () => createResource(wrappedFetch, options));
1026
+ const resource = withScope(cacheScope, () => createResourceBase(wrappedFetch, options));
864
1027
  const entry = {
865
1028
  resource,
866
1029
  createdAt: now,
@@ -1,2 +1,2 @@
1
1
  export * from "./form-types.js";
2
- export { createForm, parseFormData, WRAPPED_HANDLER } from "./form.js";
2
+ export { createForm, parseFormData } from "./form.js";
@@ -1,2 +1,2 @@
1
1
  export * from "./form-types.js";
2
- export { createForm, parseFormData, WRAPPED_HANDLER } from "./form.js";
2
+ export { createForm, parseFormData } from "./form.js";
@@ -1,2 +1,2 @@
1
- export * from "./router.js";
1
+ export { createRouter, createTypedNavigate, type RouterStatus, type Router, type ScrollBehavior, type LifecycleHooks, type RouterConfig, type RouteTagContext, type RouterPreloadCacheEntry, type TypedNavigate, } from "./router.js";
2
2
  export * from "./route-tables.js";
@@ -1,2 +1,2 @@
1
- export * from "./router.js";
1
+ export { createRouter, createTypedNavigate, } from "./router.js";
2
2
  export * from "./route-tables.js";
@@ -15,6 +15,16 @@ export interface BindOptions {
15
15
  * Selectors for elements where text interpolation should be skipped
16
16
  */
17
17
  rawTextSelectors?: string;
18
+ /**
19
+ * Optional runtime cache policy for text interpolation template plans.
20
+ * Defaults are tuned for general SPA usage.
21
+ */
22
+ templatePlanCache?: {
23
+ /** Maximum number of cached template plans (0 disables cache). */
24
+ maxEntries?: number;
25
+ /** Time-to-live (ms) per plan, refreshed on hit (0 disables cache). */
26
+ ttlMs?: number;
27
+ };
18
28
  /**
19
29
  * Internal flag — set by fromHtml for router/template rendering.
20
30
  * Skips HMR context registration but KEEPS d-ready/d-loading lifecycle.