@ubean/runtime 0.1.1 → 0.1.3

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/index.js ADDED
@@ -0,0 +1,364 @@
1
+ import { $ as setI18nConfig, A as initCachedViewsFromRoutes, B as defineLocale, C as disablePageCache, D as getCachedViewNames, E as getCacheEnabled, F as resetRouteCache, G as getI18nConfig, H as detectLocale, I as useCacheViews, J as getLocaleName, K as getLocale, L as createUbeanRouter, M as isCacheEnabled, N as isPageCached, O as getExcludedViewNames, P as isPageExcluded, Q as onLocaleChange, R as addLocale, S as useReloadSignal, T as excludePageCache, U as extractLocaleFromPath, V as detectBrowserLocale, W as getDefaultLocale, X as localizePath, Y as getRegisteredLocales, Z as mergeLocale, _ as getReloadCounter, a as createUbeanSSRApp, at as useSwitchLocalePath, b as setPageTransition, c as useSeoMeta, d as getNavigationType, et as setLocale, f as supportsViewTransitions, g as getPageTransitionName, h as clearPageTransition, i as createUbeanApp, it as useLocalePath, j as invalidatePageCache, k as includePageCache, l as useUnheadHead, m as withViewTransition, n as Link, nt as t, o as usePage, p as useViewTransitionState, q as getLocaleDir, r as PageView, rt as useI18n, s as useRouter, t as Head, tt as switchLocalePath, u as useViewTransition, v as isReloading, w as enablePageCache, x as usePageTransition, y as reloadPage, z as clearLocales } from "./app-dx92OPRP.js";
2
+ import { applyAppConfig, createDefaultAppConfig, defineApp } from "./define-app.js";
3
+ import { injectHead, injectHead as injectHead$1 } from "@unhead/vue";
4
+ import { createHead as createClientHead } from "@unhead/vue/client";
5
+ import { createHead as createServerHead } from "@unhead/vue/server";
6
+ import { defineDataKey as defineDataKey$1 } from "@ubean/pages";
7
+ import { createApp, defineComponent, h } from "vue";
8
+ //#region src/client.ts
9
+ const _global$2 = globalThis;
10
+ function getInitialPageData() {
11
+ if (typeof _global$2.document === "undefined") return null;
12
+ const el = _global$2.document.getElementById("__UBEAN_PAGE_DATA__");
13
+ if (!el) return _global$2.__UBEAN_PAGE_DATA__ ?? null;
14
+ try {
15
+ return JSON.parse(el.textContent || "null");
16
+ } catch {
17
+ return null;
18
+ }
19
+ }
20
+ //#endregion
21
+ //#region src/head.ts
22
+ function useHeadInstance() {
23
+ return injectHead$1();
24
+ }
25
+ //#endregion
26
+ //#region src/composables.ts
27
+ const _global$1 = globalThis;
28
+ function createDataCacheStore() {
29
+ const cache = /* @__PURE__ */ new Map();
30
+ const tagIndex = /* @__PURE__ */ new Map();
31
+ const listeners = /* @__PURE__ */ new Set();
32
+ function notify() {
33
+ for (const fn of listeners) fn();
34
+ }
35
+ return {
36
+ get(key) {
37
+ return cache.get(key)?.data;
38
+ },
39
+ set(key, value, tags) {
40
+ cache.set(key, {
41
+ data: value,
42
+ timestamp: Date.now(),
43
+ tags
44
+ });
45
+ if (tags) for (const tag of tags) {
46
+ let set = tagIndex.get(tag);
47
+ if (!set) {
48
+ set = /* @__PURE__ */ new Set();
49
+ tagIndex.set(tag, set);
50
+ }
51
+ set.add(key);
52
+ }
53
+ notify();
54
+ },
55
+ has(key) {
56
+ return cache.has(key);
57
+ },
58
+ invalidate(keyOrTag) {
59
+ let count = 0;
60
+ if (typeof keyOrTag === "string") {
61
+ if (cache.has(keyOrTag)) {
62
+ const entry = cache.get(keyOrTag);
63
+ if (entry.tags) for (const t of entry.tags) {
64
+ const ts = tagIndex.get(t);
65
+ if (ts) ts.delete(keyOrTag);
66
+ }
67
+ cache.delete(keyOrTag);
68
+ count = 1;
69
+ }
70
+ const keys = tagIndex.get(keyOrTag);
71
+ if (keys) {
72
+ for (const k of keys) {
73
+ const entry = cache.get(k);
74
+ if (entry) {
75
+ if (entry.tags) for (const t of entry.tags) {
76
+ const ts = tagIndex.get(t);
77
+ if (ts) ts.delete(k);
78
+ }
79
+ cache.delete(k);
80
+ count++;
81
+ }
82
+ }
83
+ tagIndex.delete(keyOrTag);
84
+ }
85
+ } else {
86
+ const entry = cache.get(keyOrTag);
87
+ if (entry) {
88
+ if (entry.tags) for (const t of entry.tags) {
89
+ const ts = tagIndex.get(t);
90
+ if (ts) ts.delete(keyOrTag);
91
+ }
92
+ cache.delete(keyOrTag);
93
+ count = 1;
94
+ }
95
+ }
96
+ if (count > 0) notify();
97
+ return count;
98
+ },
99
+ clear() {
100
+ cache.clear();
101
+ tagIndex.clear();
102
+ notify();
103
+ },
104
+ subscribe(fn) {
105
+ listeners.add(fn);
106
+ return () => listeners.delete(fn);
107
+ },
108
+ getTimestamp(key) {
109
+ return cache.get(key)?.timestamp;
110
+ }
111
+ };
112
+ }
113
+ function createUseAsyncData(store) {
114
+ return function useAsyncData(keyOrFetcher, fetcherOrOptions, options) {
115
+ let key;
116
+ let fetcher;
117
+ let opts = {};
118
+ if (typeof keyOrFetcher === "string") {
119
+ key = keyOrFetcher;
120
+ fetcher = fetcherOrOptions;
121
+ opts = options || {};
122
+ } else {
123
+ fetcher = keyOrFetcher;
124
+ key = fetcherOrOptions?.key || Math.random().toString(36).slice(2);
125
+ opts = fetcherOrOptions || {};
126
+ }
127
+ const state = {
128
+ data: { value: store.get(key) ?? (opts.default ? opts.default() : void 0) },
129
+ error: { value: null },
130
+ loading: { value: false }
131
+ };
132
+ async function execute() {
133
+ state.loading.value = true;
134
+ state.error.value = null;
135
+ try {
136
+ const raw = await fetcher();
137
+ const value = opts.transform ? opts.transform(raw) : raw;
138
+ store.set(key, value, opts.tags);
139
+ state.data.value = value;
140
+ } catch (err) {
141
+ state.error.value = err instanceof Error ? err : new Error(String(err));
142
+ } finally {
143
+ state.loading.value = false;
144
+ }
145
+ }
146
+ function invalidate() {
147
+ store.invalidate(key);
148
+ }
149
+ if (!opts.lazy) {
150
+ if (!store.has(key)) execute();
151
+ }
152
+ store.subscribe(() => {
153
+ state.data.value = store.get(key) ?? (opts.default ? opts.default() : void 0);
154
+ });
155
+ return {
156
+ data: state.data,
157
+ error: state.error,
158
+ loading: state.loading,
159
+ refresh: execute,
160
+ invalidate
161
+ };
162
+ };
163
+ }
164
+ function invalidateCache(store, keyOrTag) {
165
+ return store.invalidate(keyOrTag);
166
+ }
167
+ function clearCache(store) {
168
+ store.clear();
169
+ }
170
+ function defineDataKey(key) {
171
+ return defineDataKey$1(key);
172
+ }
173
+ function createLinkHandler(ctx) {
174
+ return {
175
+ getProps: () => ({}),
176
+ async navigate(href, opts = {}) {
177
+ if (!ctx.__ubean_router) {
178
+ const loc = _global$1.location;
179
+ if (opts.replace) loc.replace(href);
180
+ else loc.href = href;
181
+ return;
182
+ }
183
+ if (opts.replace) await ctx.__ubean_router.replace(href);
184
+ else await ctx.__ubean_router.push(href);
185
+ },
186
+ async prefetch(_href) {}
187
+ };
188
+ }
189
+ function extractPageData() {
190
+ if (typeof _global$1.document === "undefined") return null;
191
+ const el = _global$1.document.getElementById("__UBEAN_PAGE_DATA__");
192
+ if (!el) return null;
193
+ try {
194
+ return JSON.parse(el.textContent || "null");
195
+ } catch {
196
+ return null;
197
+ }
198
+ }
199
+ async function useServerData(fetcher) {
200
+ return fetcher();
201
+ }
202
+ function getInvalidatedKeysForAction(actionName, invalidationMap, store) {
203
+ const toInvalidate = invalidationMap[actionName];
204
+ if (!toInvalidate) return 0;
205
+ let count = 0;
206
+ for (const key of toInvalidate) count += store.invalidate(key);
207
+ return count;
208
+ }
209
+ //#endregion
210
+ //#region src/page-macro.ts
211
+ function definePage(_meta) {}
212
+ function defineMeta(_meta) {}
213
+ function defineMiddleware(_handler) {}
214
+ //#endregion
215
+ //#region src/router-location.ts
216
+ function resolveRoute(to, routeMap) {
217
+ if (typeof to === "string") {
218
+ if (to.startsWith("/") || to.startsWith("http") || to.startsWith("#")) return to;
219
+ return `/${to.replace(/^\//, "")}`;
220
+ }
221
+ let path = to.path || "/";
222
+ if (to.name && routeMap) {
223
+ const route = routeMap[to.name];
224
+ if (route) path = route.route;
225
+ }
226
+ if (to.params) for (const [key, value] of Object.entries(to.params)) path = path.replace(`:${key}`, String(value));
227
+ if (to.query) {
228
+ const qs = Object.entries(to.query).filter(([, v]) => v !== void 0 && v !== null).map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`).join("&");
229
+ if (qs) path += (path.includes("?") ? "&" : "?") + qs;
230
+ }
231
+ if (to.hash) path += to.hash.startsWith("#") ? to.hash : `#${to.hash}`;
232
+ return path;
233
+ }
234
+ function isActiveRoute(currentPath, targetHref, exact = false) {
235
+ if (targetHref === "/" || targetHref === "") return currentPath === "/";
236
+ if (exact) return currentPath === targetHref || currentPath === `${targetHref}/`;
237
+ return currentPath === targetHref || currentPath.startsWith(`${targetHref}/`) || currentPath.startsWith(`${targetHref}?`);
238
+ }
239
+ //#endregion
240
+ //#region src/islands.ts
241
+ const _global = globalThis;
242
+ function decodeProps(raw) {
243
+ if (!raw) return {};
244
+ try {
245
+ return JSON.parse(raw.replace(/&quot;/g, "\"").replace(/&amp;/g, "&").replace(/&lt;/g, "<"));
246
+ } catch {
247
+ return {};
248
+ }
249
+ }
250
+ function collectIslands(root) {
251
+ const doc = root ?? _global.document;
252
+ if (!doc) return [];
253
+ const nodes = doc.querySelectorAll("ubean-island[data-island-id]");
254
+ const records = [];
255
+ nodes.forEach((el) => {
256
+ const domEl = el;
257
+ const id = domEl.getAttribute("data-island-id") || "";
258
+ const componentName = domEl.getAttribute("data-component") || "";
259
+ const directive = domEl.getAttribute("data-directive") || "client:load";
260
+ const mediaQuery = domEl.getAttribute("data-media") || void 0;
261
+ const props = decodeProps(domEl.getAttribute("data-props"));
262
+ records.push({
263
+ el: domEl,
264
+ id,
265
+ componentName,
266
+ directive,
267
+ mediaQuery,
268
+ props
269
+ });
270
+ });
271
+ return records;
272
+ }
273
+ function hydrateIsland(record, component, options = {}) {
274
+ if (record.el.hasAttribute("data-hydrated")) return;
275
+ record.el.setAttribute("data-hydrated", "true");
276
+ const app = createApp(defineComponent({
277
+ name: `Island-${record.componentName}`,
278
+ setup() {
279
+ return () => h(component, record.props);
280
+ }
281
+ }));
282
+ if (options.appContext) {
283
+ if (options.appContext.config?.globalProperties) Object.assign(app.config.globalProperties, options.appContext.config.globalProperties);
284
+ const appContextInternal = options.appContext;
285
+ if (appContextInternal._context?.provides) for (const [key, value] of Object.entries(appContextInternal._context.provides)) app.provide(key, value);
286
+ }
287
+ app.mount(record.el);
288
+ options.onHydrated?.(record.el, component);
289
+ }
290
+ function hydrateIslands(options = {}) {
291
+ const { root, components = {}, getComponent, ...rest } = options;
292
+ const islands = collectIslands(root);
293
+ if (islands.length === 0) return;
294
+ for (const record of islands) {
295
+ if (record.directive === "client:only") {
296
+ const comp = resolveComponent(record.componentName, components, getComponent);
297
+ if (comp) Promise.resolve(comp).then((c) => hydrateIsland(record, c, rest));
298
+ continue;
299
+ }
300
+ const doHydrate = () => {
301
+ const comp = resolveComponent(record.componentName, components, getComponent);
302
+ if (comp) Promise.resolve(comp).then((c) => hydrateIsland(record, c, rest));
303
+ };
304
+ if (record.el.getAttribute("data-hydrating") === "true" && !record.el.hasAttribute("data-hydrated")) {
305
+ doHydrate();
306
+ continue;
307
+ }
308
+ const MutationObserverCtor = _global.MutationObserver ?? null;
309
+ if (MutationObserverCtor) {
310
+ const observer = new MutationObserverCtor(() => {
311
+ if (record.el.getAttribute("data-hydrating") === "true" && !record.el.hasAttribute("data-hydrated")) {
312
+ observer.disconnect();
313
+ doHydrate();
314
+ }
315
+ });
316
+ observer.observe(record.el, {
317
+ attributes: true,
318
+ attributeFilter: ["data-hydrating"]
319
+ });
320
+ }
321
+ const directive = record.directive;
322
+ if (directive === "client:load") doHydrate();
323
+ else if (directive === "client:idle") {
324
+ const ric = _global.requestIdleCallback;
325
+ if (typeof ric === "function") ric(() => doHydrate(), { timeout: 2e3 });
326
+ else setTimeout(doHydrate, 200);
327
+ } else if (directive === "client:visible") {
328
+ const IOCtor = _global.IntersectionObserver;
329
+ if (typeof IOCtor === "function") {
330
+ const io = new IOCtor((entries) => {
331
+ entries.forEach((entry) => {
332
+ if (entry.isIntersecting) {
333
+ io.disconnect();
334
+ doHydrate();
335
+ }
336
+ });
337
+ }, { rootMargin: "200px" });
338
+ io.observe(record.el);
339
+ } else doHydrate();
340
+ } else if (directive === "client:media" && record.mediaQuery) {
341
+ const mql = _global.window?.matchMedia?.(record.mediaQuery);
342
+ if (mql) if (mql.matches) doHydrate();
343
+ else {
344
+ const fn = (e) => {
345
+ if (e.matches) {
346
+ doHydrate();
347
+ if (mql.removeEventListener) mql.removeEventListener("change", fn);
348
+ else if (mql.removeListener) mql.removeListener(fn);
349
+ }
350
+ };
351
+ if (mql.addEventListener) mql.addEventListener("change", fn);
352
+ else if (mql.addListener) mql.addListener(fn);
353
+ }
354
+ else doHydrate();
355
+ } else doHydrate();
356
+ }
357
+ }
358
+ function resolveComponent(name, components, getComponent) {
359
+ if (components[name]) return components[name];
360
+ if (getComponent) return getComponent(name);
361
+ return null;
362
+ }
363
+ //#endregion
364
+ export { Head, Link, PageView, addLocale, applyAppConfig, clearCache, clearLocales, clearPageTransition, collectIslands, createClientHead, createDataCacheStore, createDefaultAppConfig, createLinkHandler, createServerHead, createUbeanApp, createUbeanRouter, createUbeanSSRApp, createUseAsyncData, defineApp, defineDataKey, defineLocale, defineMeta, defineMiddleware, definePage, detectBrowserLocale, detectLocale, disablePageCache, enablePageCache, excludePageCache, extractLocaleFromPath, extractPageData, getCacheEnabled, getCachedViewNames, getDefaultLocale, getExcludedViewNames, getI18nConfig, getInitialPageData, getInvalidatedKeysForAction, getLocale, getLocaleDir, getLocaleName, getNavigationType, getPageTransitionName, getRegisteredLocales, getReloadCounter, hydrateIsland, hydrateIslands, includePageCache, initCachedViewsFromRoutes, injectHead, invalidateCache, invalidatePageCache, isActiveRoute, isCacheEnabled, isPageCached, isPageExcluded, isReloading, localizePath, mergeLocale, onLocaleChange, reloadPage, resetRouteCache, resolveRoute, setI18nConfig, setLocale, setPageTransition, supportsViewTransitions, switchLocalePath, t, useCacheViews, useUnheadHead as useHead, useHeadInstance, useI18n, useLocalePath, usePage, usePageTransition, useReloadSignal, useRouter, useSeoMeta, useServerData, useSwitchLocalePath, useViewTransition, useViewTransitionState, withViewTransition };
@@ -0,0 +1,12 @@
1
+ //#region src/view-transitions.d.ts
2
+ interface ViewTransitionOptions {
3
+ enabled?: boolean;
4
+ fallback?: 'none' | 'crossfade';
5
+ types?: string[];
6
+ }
7
+ declare function supportsViewTransitions(): boolean;
8
+ declare function withViewTransition<T>(callback: () => Promise<T> | T, options?: ViewTransitionOptions): Promise<T>;
9
+ declare function getNavigationType(): 'traverse' | 'push' | 'replace' | 'reload';
10
+ declare function useViewTransitionState(name: string): Record<string, string>;
11
+ //#endregion
12
+ export { withViewTransition as a, useViewTransitionState as i, getNavigationType as n, supportsViewTransitions as r, ViewTransitionOptions as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ubean/runtime",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Vue client runtime for ubean (createUbeanApp, useRouter, useHead, Link, Head, PageView, composables, view-transitions, cache-views, islands hydrate)",
5
5
  "files": [
6
6
  "dist"
@@ -27,9 +27,9 @@
27
27
  "@unhead/vue": "^3.2.3",
28
28
  "vue": "^3.5.40",
29
29
  "vue-router": "^5.2.0",
30
- "@ubean/i18n": "0.1.1",
31
- "@ubean/types": "0.1.1",
32
- "@ubean/pages": "0.1.1"
30
+ "@ubean/pages": "0.1.3",
31
+ "@ubean/i18n": "0.1.3",
32
+ "@ubean/types": "0.1.3"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@types/node": "^26.1.1",
@@ -37,8 +37,8 @@
37
37
  "vite-plus": "0.2.6"
38
38
  },
39
39
  "peerDependencies": {
40
- "@ubean/routing": "0.1.1",
41
- "@ubean/seo": "0.1.1"
40
+ "@ubean/routing": "0.1.3",
41
+ "@ubean/seo": "0.1.3"
42
42
  },
43
43
  "peerDependenciesMeta": {
44
44
  "@ubean/seo": {