@quvel-kit/core 1.3.8 → 1.3.10

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.
@@ -16,4 +16,5 @@ export { useQueryMessageHandler, normalizeKey, mapStatusToType } from './useQuer
16
16
  export type { MessageHandlerOptions } from './useQueryMessageHandler.js';
17
17
  export { useUrlQueryHandler } from './useUrlQueryHandler.js';
18
18
  export type { UrlQueryHandlerOptions } from './useUrlQueryHandler.js';
19
+ export { useSSRData } from './useSSRData.js';
19
20
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/composables/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,sBAAsB,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AACpG,YAAY,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,YAAY,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/composables/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,sBAAsB,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AACpG,YAAY,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,YAAY,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}
@@ -14,3 +14,4 @@ export { useRecaptcha } from './useRecaptcha.js';
14
14
  export { useXsrf } from './useXsrf.js';
15
15
  export { useQueryMessageHandler, normalizeKey, mapStatusToType } from './useQueryMessageHandler.js';
16
16
  export { useUrlQueryHandler } from './useUrlQueryHandler.js';
17
+ export { useSSRData } from './useSSRData.js';
@@ -0,0 +1,28 @@
1
+ /**
2
+ * SSR Data Composable
3
+ *
4
+ * Fetches data during SSR, serializes to client, and hydrates on mount.
5
+ * Eliminates the need for a Pinia store per page for SSR data loading.
6
+ */
7
+ import { type Ref } from 'vue';
8
+ /**
9
+ * SSR data loading composable
10
+ *
11
+ * @param key - Unique key for this data (used for serialization)
12
+ * @param fetcher - Async function that fetches the data
13
+ * @returns Reactive data ref, loading state, and error state
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const { data: household, isLoading, error } = useSSRData(
18
+ * `household-${route.params.id}`,
19
+ * () => householdService.get(route.params.id)
20
+ * );
21
+ * ```
22
+ */
23
+ export declare function useSSRData<T>(key: string, fetcher: () => Promise<T>): {
24
+ data: Ref<T | null>;
25
+ isLoading: Ref<boolean>;
26
+ error: Ref<Error | null>;
27
+ };
28
+ //# sourceMappingURL=useSSRData.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSSRData.d.ts","sourceRoot":"","sources":["../../src/composables/useSSRData.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAoC,KAAK,GAAG,EAAE,MAAM,KAAK,CAAC;AAejE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAC1B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACxB;IACD,IAAI,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACpB,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACxB,KAAK,EAAE,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;CAC1B,CAsDA"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * SSR Data Composable
3
+ *
4
+ * Fetches data during SSR, serializes to client, and hydrates on mount.
5
+ * Eliminates the need for a Pinia store per page for SSR data loading.
6
+ */
7
+ import { ref, onMounted, onServerPrefetch } from 'vue';
8
+ import { useQuvel } from './useQuvel.js';
9
+ const SSR_DATA_PREFIX = '__SSR_DATA_';
10
+ const SSR_ERROR_PREFIX = '__SSR_ERROR_';
11
+ /**
12
+ * Check if SSR data exists in window (for initial state)
13
+ */
14
+ function hasSSRData(key) {
15
+ if (typeof window === 'undefined')
16
+ return false;
17
+ const win = window;
18
+ return win[`${SSR_DATA_PREFIX}${key}`] !== undefined;
19
+ }
20
+ /**
21
+ * SSR data loading composable
22
+ *
23
+ * @param key - Unique key for this data (used for serialization)
24
+ * @param fetcher - Async function that fetches the data
25
+ * @returns Reactive data ref, loading state, and error state
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * const { data: household, isLoading, error } = useSSRData(
30
+ * `household-${route.params.id}`,
31
+ * () => householdService.get(route.params.id)
32
+ * );
33
+ * ```
34
+ */
35
+ export function useSSRData(key, fetcher) {
36
+ const isSSR = typeof window === 'undefined';
37
+ const container = useQuvel();
38
+ const dataKey = `${SSR_DATA_PREFIX}${key}`;
39
+ const errorKey = `${SSR_ERROR_PREFIX}${key}`;
40
+ const data = ref(null);
41
+ const error = ref(null);
42
+ const isLoading = ref(isSSR || !hasSSRData(key));
43
+ if (isSSR) {
44
+ onServerPrefetch(async () => {
45
+ try {
46
+ const result = await fetcher();
47
+ data.value = result;
48
+ container.windowBag?.set(dataKey, result);
49
+ }
50
+ catch (e) {
51
+ const err = e instanceof Error ? e : new Error(String(e));
52
+ error.value = err;
53
+ container.windowBag?.set(errorKey, { message: err.message, name: err.name });
54
+ }
55
+ finally {
56
+ isLoading.value = false;
57
+ }
58
+ });
59
+ }
60
+ else {
61
+ onMounted(async () => {
62
+ const win = window;
63
+ const ssrData = win[dataKey];
64
+ const ssrError = win[errorKey];
65
+ delete win[dataKey];
66
+ delete win[errorKey];
67
+ if (ssrError) {
68
+ const err = new Error(ssrError.message);
69
+ err.name = ssrError.name;
70
+ error.value = err;
71
+ isLoading.value = false;
72
+ }
73
+ else if (ssrData !== undefined) {
74
+ data.value = ssrData;
75
+ isLoading.value = false;
76
+ }
77
+ else {
78
+ try {
79
+ data.value = await fetcher();
80
+ }
81
+ catch (e) {
82
+ error.value = e instanceof Error ? e : new Error(String(e));
83
+ }
84
+ finally {
85
+ isLoading.value = false;
86
+ }
87
+ }
88
+ });
89
+ }
90
+ return { data, isLoading, error };
91
+ }
@@ -1,6 +1,7 @@
1
1
  import type { Service, ServiceClass } from './types.js';
2
2
  import type { QSsrContext } from '@quasar/app-vite';
3
3
  import type { AppConfig } from '../types/app.types.js';
4
+ import type { SSRDataBag } from '../types/ssr.js';
4
5
  import { LogService } from "../services/LogService.js";
5
6
  import { ApiService } from "../services/ApiService.js";
6
7
  import { I18nService } from "../services/I18nService.js";
@@ -29,6 +30,11 @@ export declare class ServiceContainer {
29
30
  * Get the SSR context
30
31
  */
31
32
  get ssrContext(): QSsrContext | null | undefined;
33
+ /**
34
+ * Get the WindowBag for SSR data serialization
35
+ * Only available during SSR
36
+ */
37
+ get windowBag(): SSRDataBag | undefined;
32
38
  /**
33
39
  * Initialize services from their classes with config and SSR context
34
40
  */
@@ -1 +1 @@
1
- {"version":3,"file":"ServiceContainer.d.ts","sourceRoot":"","sources":["../../src/container/ServiceContainer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,OAAO,EACP,YAAY,EAGb,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAC,UAAU,EAAC,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAC,UAAU,EAAC,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAC,WAAW,EAAC,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAC,iBAAiB,EAAC,MAAM,kCAAkC,CAAC;AAEnE,OAAO,EAAC,gBAAgB,EAAC,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAC,YAAY,EAAC,MAAM,6BAA6B,CAAC;AAGzD;;;;;;;GAOG;AACH,qBAAa,gBAAgB;IAMzB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;IAL/B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2C;IACpE,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAwC;IAC1E,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAY;gBAGjB,WAAW,CAAC,GAAE,WAAW,GAAG,IAAI,aAAA,EACjD,cAAc,GAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAa;IAQvD;;OAEG;IACH,IAAI,MAAM,IAAI,SAAS,CAEtB;IAED;;OAEG;IACH,IAAI,UAAU,IAAI,WAAW,GAAG,IAAI,GAAG,SAAS,CAE/C;IAED;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAS1B;;OAEG;IACH,OAAO,CAAC,YAAY;IAMpB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAMxB;;OAEG;IACH,GAAG,GAAI,CAAC,SAAS,OAAO,EAAE,cAAc,YAAY,CAAC,CAAC,CAAC,KAAG,CAAC,CAkBzD;IAEF;;OAEG;IACH,SAAS,CAAC,CAAC,SAAS,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAIzD;;OAEG;IACH,UAAU,CAAC,CAAC,SAAS,OAAO,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,SAAS,UAAQ,GAAG,OAAO;IAgBxF;;OAEG;IACH,UAAU,CAAC,CAAC,SAAS,OAAO,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO;IAIrE;;OAEG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAUpC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAO1B;;OAEG;IACH,OAAO,CAAC,WAAW;IAUnB;;OAEG;IACH,OAAO,CAAC,eAAe;IAUvB;;OAEG;IACH,OAAO,CAAC,OAAO;IASf;;OAEG;IACH,OAAO,CAAC,cAAc;IAItB;;OAEG;IACH,OAAO,CAAC,cAAc;IAItB;;OAEG;IAEH,IAAI,GAAG,IAAI,UAAU,CAEpB;IAED,IAAI,GAAG,IAAI,UAAU,CAEpB;IAED,IAAI,IAAI,IAAI,WAAW,CAEtB;IAED,IAAI,UAAU,IAAI,iBAAiB,CAElC;IAED,IAAI,IAAI;;;;;;;MAIP;IAED,IAAI,EAAE,IAAI,gBAAgB,CAEzB;IAED,IAAI,KAAK,IAAI,YAAY,CAExB;CACF"}
1
+ {"version":3,"file":"ServiceContainer.d.ts","sourceRoot":"","sources":["../../src/container/ServiceContainer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,OAAO,EACP,YAAY,EAGb,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAC,UAAU,EAAC,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAC,UAAU,EAAC,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAC,WAAW,EAAC,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAC,iBAAiB,EAAC,MAAM,kCAAkC,CAAC;AAEnE,OAAO,EAAC,gBAAgB,EAAC,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAC,YAAY,EAAC,MAAM,6BAA6B,CAAC;AAGzD;;;;;;;GAOG;AACH,qBAAa,gBAAgB;IAMzB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;IAL/B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2C;IACpE,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAwC;IAC1E,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAY;gBAGjB,WAAW,CAAC,GAAE,WAAW,GAAG,IAAI,aAAA,EACjD,cAAc,GAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAa;IAQvD;;OAEG;IACH,IAAI,MAAM,IAAI,SAAS,CAEtB;IAED;;OAEG;IACH,IAAI,UAAU,IAAI,WAAW,GAAG,IAAI,GAAG,SAAS,CAE/C;IAED;;;OAGG;IACH,IAAI,SAAS,IAAI,UAAU,GAAG,SAAS,CAGtC;IAED;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAS1B;;OAEG;IACH,OAAO,CAAC,YAAY;IAMpB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAMxB;;OAEG;IACH,GAAG,GAAI,CAAC,SAAS,OAAO,EAAE,cAAc,YAAY,CAAC,CAAC,CAAC,KAAG,CAAC,CAkBzD;IAEF;;OAEG;IACH,SAAS,CAAC,CAAC,SAAS,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAIzD;;OAEG;IACH,UAAU,CAAC,CAAC,SAAS,OAAO,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,SAAS,UAAQ,GAAG,OAAO;IAgBxF;;OAEG;IACH,UAAU,CAAC,CAAC,SAAS,OAAO,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO;IAIrE;;OAEG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAUpC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAO1B;;OAEG;IACH,OAAO,CAAC,WAAW;IAUnB;;OAEG;IACH,OAAO,CAAC,eAAe;IAUvB;;OAEG;IACH,OAAO,CAAC,OAAO;IASf;;OAEG;IACH,OAAO,CAAC,cAAc;IAItB;;OAEG;IACH,OAAO,CAAC,cAAc;IAItB;;OAEG;IAEH,IAAI,GAAG,IAAI,UAAU,CAEpB;IAED,IAAI,GAAG,IAAI,UAAU,CAEpB;IAED,IAAI,IAAI,IAAI,WAAW,CAEtB;IAED,IAAI,UAAU,IAAI,iBAAiB,CAElC;IAED,IAAI,IAAI;;;;;;;MAIP;IAED,IAAI,EAAE,IAAI,gBAAgB,CAEzB;IAED,IAAI,KAAK,IAAI,YAAY,CAExB;CACF"}
@@ -38,6 +38,14 @@ export class ServiceContainer {
38
38
  get ssrContext() {
39
39
  return this._ssrContext;
40
40
  }
41
+ /**
42
+ * Get the WindowBag for SSR data serialization
43
+ * Only available during SSR
44
+ */
45
+ get windowBag() {
46
+ const req = this._ssrContext?.req;
47
+ return req?.quvelContext?.windowBag;
48
+ }
41
49
  /**
42
50
  * Initialize services from their classes with config and SSR context
43
51
  */
@@ -9,3 +9,13 @@ declare module '@quasar/app-vite' {
9
9
  $quvel?: ServiceContainer;
10
10
  }
11
11
  }
12
+
13
+ /**
14
+ * SSR Data Bag interface for component data serialization
15
+ * Minimal interface matching WindowBag from @quvel-kit/ssr
16
+ */
17
+ export interface SSRDataBag {
18
+ set(key: string, value: unknown): void;
19
+ get<T = unknown>(key: string): T | undefined;
20
+ has(key: string): boolean;
21
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"axios.d.ts","sourceRoot":"","sources":["../../src/utils/axios.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAC,aAAa,EAAqB,MAAM,OAAO,CAAC;AAE7D,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AAsCrD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CASnE;AAoBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,CAAC,EAAE,WAAW,EAAE,SAAS,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,GAAG,aAAa,CAmD1G"}
1
+ {"version":3,"file":"axios.d.ts","sourceRoot":"","sources":["../../src/utils/axios.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAC,aAAa,EAAqB,MAAM,OAAO,CAAC;AAE7D,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AAsCrD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CASnE;AAoBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,CAAC,EAAE,WAAW,EAAE,SAAS,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,GAAG,aAAa,CA0D1G"}
@@ -87,10 +87,8 @@ export function createApiInstance(ssrContext, appConfig) {
87
87
  },
88
88
  };
89
89
  const instance = axios.create(axiosConfig);
90
- // Detect session cookie presence from AppConfig
91
90
  let hasSessionCookie = false;
92
91
  if (ssrContext) {
93
- // SSR: Set up SSR-specific headers and session detection
94
92
  if (appConfig?.api?.ssrKey) {
95
93
  const ssrKeyHeaderName = getSsrKeyHeader(appConfig);
96
94
  instance.defaults.headers.common[ssrKeyHeaderName] = appConfig.api.ssrKey;
@@ -103,10 +101,18 @@ export function createApiInstance(ssrContext, appConfig) {
103
101
  instance.defaults.maxRedirects = getEnv('SSR_AXIOS_MAX_REDIRECTS', 0, Number);
104
102
  instance.defaults.timeout = getEnv('SSR_AXIOS_TIMEOUT', 5000, Number);
105
103
  if (isValidSessionToken(sessionToken)) {
106
- instance.defaults.headers.Cookie = `${sessionCookie}=${sessionToken}`;
104
+ let cookieHeader = `${sessionCookie}=${sessionToken}`;
107
105
  if (xsrfToken) {
106
+ cookieHeader += `; ${xsrfCookieName}=${xsrfToken}`;
107
+ try {
108
+ instance.defaults.headers.common['X-XSRF-TOKEN'] = decodeURIComponent(xsrfToken);
109
+ }
110
+ catch {
111
+ instance.defaults.headers.common['X-XSRF-TOKEN'] = xsrfToken;
112
+ }
108
113
  hasSessionCookie = true;
109
114
  }
115
+ instance.defaults.headers.Cookie = cookieHeader;
110
116
  }
111
117
  }
112
118
  instance.defaults.hasSessionCookie = hasSessionCookie;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quvel-kit/core",
3
- "version": "1.3.8",
3
+ "version": "1.3.10",
4
4
  "description": "Core utilities for Quvel UI",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",