nuxt-feathers-zod 6.4.73 → 6.4.98

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 (41) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +49 -4
  3. package/dist/module.json +1 -1
  4. package/dist/module.mjs +5 -1
  5. package/dist/runtime/client.d.ts +9 -0
  6. package/dist/runtime/client.js +3 -0
  7. package/dist/runtime/composables/useAuth.d.ts +7 -6
  8. package/dist/runtime/composables/useAuth.js +27 -135
  9. package/dist/runtime/composables/useAuthBoundFetch.d.ts +6 -0
  10. package/dist/runtime/composables/useAuthBoundFetch.js +86 -0
  11. package/dist/runtime/composables/useAuthDiagnostics.d.ts +24 -0
  12. package/dist/runtime/composables/useAuthDiagnostics.js +25 -0
  13. package/dist/runtime/composables/useAuthRuntime.d.ts +77 -0
  14. package/dist/runtime/composables/useAuthRuntime.js +371 -0
  15. package/dist/runtime/composables/useAuthenticatedRequest.d.ts +7 -0
  16. package/dist/runtime/composables/useAuthenticatedRequest.js +23 -0
  17. package/dist/runtime/composables/useKeycloakBridge.d.ts +9 -0
  18. package/dist/runtime/composables/useKeycloakBridge.js +44 -0
  19. package/dist/runtime/composables/useMongoManagementClient.d.ts +15 -0
  20. package/dist/runtime/composables/useMongoManagementClient.js +27 -0
  21. package/dist/runtime/composables/useProtectedService.d.ts +2 -0
  22. package/dist/runtime/composables/useProtectedService.js +49 -0
  23. package/dist/runtime/composables/useProtectedTool.d.ts +19 -0
  24. package/dist/runtime/composables/useProtectedTool.js +60 -0
  25. package/dist/runtime/options/index.d.ts +15 -0
  26. package/dist/runtime/options/index.js +17 -0
  27. package/dist/runtime/plugins/feathers-auth.d.ts +0 -12
  28. package/dist/runtime/plugins/feathers-auth.js +5 -15
  29. package/dist/runtime/plugins/keycloak-sso.js +35 -155
  30. package/dist/runtime/server.d.ts +25 -0
  31. package/dist/runtime/server.js +6 -0
  32. package/dist/runtime/stores/auth.d.ts +34 -16
  33. package/dist/runtime/stores/auth.js +17 -50
  34. package/dist/runtime/templates/client/connection.js +2 -5
  35. package/dist/runtime/templates/client/plugin.js +16 -27
  36. package/dist/runtime/templates/server/app.js +8 -2
  37. package/dist/runtime/templates/server/authentication.js +10 -0
  38. package/dist/runtime/templates/server/keycloak.js +28 -8
  39. package/dist/runtime/utils/config.d.ts +20 -0
  40. package/dist/runtime/utils/config.js +13 -0
  41. package/package.json +46 -10
package/CHANGELOG.md CHANGED
@@ -1,3 +1,22 @@
1
+ ## 6.4.98
2
+
3
+ - fix(dev/playground): create a self-link `playground/node_modules/nuxt-feathers-zod` so local `nuxi dev playground` resolves `nuxt-feathers-zod/*` bare imports correctly under the nested playground package scope.
4
+ - chore(scripts): run `playground:ensure-link` during `prepare`, `playground:dev`, and `playground:build`.
5
+
6
+ ## 6.4.95
7
+
8
+ - add phase 4 auth runtime refactor helpers: `useProtectedTool()` and `useMongoManagementClient()`
9
+ - expose safe public runtime metadata for Mongo management basePath and routes
10
+ - align docs FR/EN for protected runtime tools and embedded Mongo management
11
+
12
+
13
+ ## 6.4.93
14
+
15
+ - auth runtime phase 2: add `useAuthenticatedRequest()` and `useProtectedService()`
16
+ - auth diagnostics: add `useAuthDiagnostics()` and `getStateSnapshot()`
17
+ - generated client plugin now synchronizes remote auth results with the unified auth runtime
18
+ - documentation FR/EN aligned with unified auth runtime and Keycloak bridge behavior
19
+
1
20
  ## v6.4.57
2
21
 
3
22
  - positionnement produit clarifié face à `@nuxtjs/supabase` (README + docs)
@@ -246,3 +265,16 @@
246
265
  - devtools plume icon/theme-parent behavior preserved
247
266
 
248
267
  - 6.4.45: remote Keycloak Option B contract (`strategy: 'sso'`, `user: loginuser`, `authenticated: true`) is now first-class in the runtime and docs; generated route middleware no longer re-runs `auth.init()` or reuses callback hashes in redirect URIs.
268
+
269
+ ## 6.4.94
270
+
271
+ - auth runtime refactor phase 3: add `useAuthBoundFetch()` and auth-aware REST fetch implementation
272
+ - generated REST clients now use the auth-bound fetch implementation by default
273
+ - `useProtectedService()` retries once after `reAuthenticate()` on 401
274
+ - docs FR/EN updated for phase 3 runtime auth usage
275
+
276
+
277
+ ## 6.4.96
278
+ - auth runtime phase 5: official Keycloak bridge helper and richer diagnostics
279
+ - protected helpers now validate Keycloak bearer before protected calls
280
+ - docs FR/EN aligned on auth runtime phases 3/4/5
package/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # nuxt-feathers-zod
2
2
 
3
- > OSS reference snapshot: **v6.4.73** — optional Mongo management options aligned and release metadata synchronized.
3
+ > OSS reference snapshot: **v6.4.98** — optional Mongo management options aligned and release metadata synchronized.
4
4
 
5
5
  [Documentation](https://vevedh.github.io/nuxt-feathers-zod/)
6
6
 
7
7
  `nuxt-feathers-zod` is the official **Nuxt 4** module that embeds or connects to **FeathersJS v5 (Dove)** with a **CLI-first** workflow and optional **Zod-first** service generation.
8
8
 
9
- Current OSS release target: **6.4.73**.
9
+ Current OSS release target: **6.4.98**.
10
10
 
11
11
  It supports two main usage patterns:
12
12
 
@@ -157,7 +157,7 @@ bunx nuxt-feathers-zod middlewares list --target nitro
157
157
  bunx nuxt-feathers-zod middlewares add request-id --target nitro
158
158
  ```
159
159
 
160
- ## CLI command surface in 6.4.73
160
+ ## CLI command surface in 6.4.98
161
161
 
162
162
  | Area | Commands |
163
163
  |---|---|
@@ -498,7 +498,52 @@ Le dashboard de démonstration associé au module peut désormais être packagé
498
498
  The Docker Edition can expose a reusable `License Center` page and feature-gating components to manage future licensed options for the `nuxt-feathers-zod` product surface.
499
499
 
500
500
 
501
- ## 6.4.73 — License Center layout clarity
501
+ ## 6.4.87 — License Center layout clarity
502
502
  - La page /license-center côté dashboard de démonstration a été refondue pour une lecture plus claire et sans écrasement responsive.
503
503
  - Nouveau découpage : status + quick actions + runtime summary en haut, puis onglets Overview / Features / Plans.
504
504
  - Le breakpoint de colonnes latérales a été repoussé à 2xl pour éviter les défauts de mise en page sur desktop intermédiaire.
505
+
506
+
507
+ ## PATCH 6.4.93 auth runtime refactor (phase 2)
508
+
509
+ - Added official protected runtime helpers: `useAuthenticatedRequest()` and `useProtectedService()`.
510
+ - Added `useAuthDiagnostics()` and `getStateSnapshot()` for easier auth diagnostics.
511
+ - Generated remote client plugin now synchronizes remote authenticate / reAuthenticate results with the unified auth runtime instead of only syncing a Pinia store.
512
+ - Documentation FR/EN updated around the unified auth runtime, protected requests, protected services and Keycloak bridge behavior.
513
+ - Recommended rule: protected NFZ tools must stop rebuilding Bearer headers manually and should consume the runtime helpers.
514
+
515
+ ## PATCH 6.4.92 auth runtime refactor (phase 1)
516
+
517
+ - Unified client auth runtime added via `useAuthRuntime()`.
518
+ - Single source of truth for token/user/authenticated/ready/status.
519
+ - Keycloak SSO now syncs token and Keycloak user through a dedicated bridge flow before protected Feathers calls.
520
+ - Generated Keycloak bridge service now accepts token aliases and keycloak user hints, and returns `accessToken`/`authentication` in its result.
521
+ - Goal: eliminate auth drift between `$api`, raw Feathers client, Pinia auth store, storage, and runtime tools.
522
+
523
+
524
+
525
+ ## Unified auth runtime helpers
526
+
527
+ `6.4.94` adds a stronger phase-3 runtime auth layer for protected REST/service flows:
528
+
529
+ - `useAuthRuntime()` remains the single auth source of truth
530
+ - `useAuthBoundFetch()` provides an auth-aware fetch helper with automatic bearer injection and one-shot `reAuthenticate()` retry on 401
531
+ - `useAuthenticatedRequest()` now delegates to this helper
532
+ - `useProtectedService()` retries once after `reAuthenticate()` on 401
533
+ - generated REST Feathers clients now use the auth-bound fetch implementation by default
534
+
535
+ This is especially useful for embedded REST mode, remote JWT mode, and Keycloak SSO bridging where a single runtime token must be reused consistently across Feathers services and protected HTTP routes.
536
+
537
+
538
+ ## 6.4.95
539
+
540
+ - auth runtime refactor phase 4
541
+ - official protected tool helpers: `useProtectedTool()` and `useMongoManagementClient()`
542
+ - public runtime metadata for embedded Mongo management routes
543
+ - better alignment between protected Feathers services and protected runtime tool HTTP routes
544
+
545
+ ## 6.4.96
546
+
547
+ - auth runtime refactor phase 5: official Keycloak bridge helper `useKeycloakBridge()`
548
+ - richer runtime diagnostics (`lastBridgeAt`, `lastEnsureReason`, `bridgePath`, `clientSync`)
549
+ - `useAuthBoundFetch()` and `useProtectedService()` now explicitly validate the Keycloak bearer before protected calls
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": "^4.0.0"
6
6
  },
7
- "version": "6.4.73",
7
+ "version": "6.4.98",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -491,7 +491,11 @@ function setAliases(options, nuxt) {
491
491
  "nuxt-feathers-zod/zod$": resolver.resolve("runtime/zod/index"),
492
492
  "nuxt-feathers-zod/options$": resolver.resolve("runtime/options"),
493
493
  "nuxt-feathers-zod/auth-utils$": resolver.resolve("runtime/utils/auth"),
494
- "nuxt-feathers-zod/config-utils$": resolver.resolve("runtime/utils/config")
494
+ "nuxt-feathers-zod/config-utils$": resolver.resolve("runtime/utils/config"),
495
+ "nuxt-feathers-zod/auth-runtime$": resolver.resolve("runtime/composables/useAuthRuntime"),
496
+ "nuxt-feathers-zod/auth-bound-fetch$": resolver.resolve("runtime/composables/useAuthBoundFetch"),
497
+ "nuxt-feathers-zod/protected-tool$": resolver.resolve("runtime/composables/useProtectedTool"),
498
+ "nuxt-feathers-zod/mongo-management-client$": resolver.resolve("runtime/composables/useMongoManagementClient")
495
499
  };
496
500
  nuxt.options.alias = defu(nuxt.options.alias, aliases);
497
501
  if (options.client)
@@ -0,0 +1,9 @@
1
+ import type { Application as FeathersApplication, TransportConnection } from '@feathersjs/feathers';
2
+ export interface ServiceTypes {
3
+ }
4
+ export interface Configuration {
5
+ connection: TransportConnection<ServiceTypes>;
6
+ }
7
+ export type ClientApplication = FeathersApplication<ServiceTypes, Configuration>;
8
+ export type FeathersClientPlugin = Parameters<ClientApplication['configure']>['0'];
9
+ export declare function defineFeathersClientPlugin(def: FeathersClientPlugin): FeathersClientPlugin;
@@ -0,0 +1,3 @@
1
+ export function defineFeathersClientPlugin(def) {
2
+ return def;
3
+ }
@@ -1,19 +1,20 @@
1
- type AuthProvider = 'keycloak' | 'local' | 'remote' | 'none';
2
1
  export declare function useAuth(): {
3
- provider: import("vue").ComputedRef<AuthProvider>;
2
+ provider: import("vue").ComputedRef<"none" | "local" | "remote" | "keycloak">;
4
3
  ready: import("vue").Ref<boolean, boolean>;
4
+ status: import("vue").Ref<"error" | "idle" | "bootstrapping" | "authenticated" | "anonymous", "error" | "idle" | "bootstrapping" | "authenticated" | "anonymous">;
5
5
  isAuthenticated: import("vue").ComputedRef<boolean>;
6
6
  isSsoAuthenticated: import("vue").ComputedRef<boolean>;
7
7
  isFeathersAuthenticated: import("vue").ComputedRef<boolean>;
8
- user: import("vue").ComputedRef<any>;
8
+ user: import("vue").Ref<any, any>;
9
9
  ssoUser: import("vue").ComputedRef<any>;
10
10
  feathersUser: import("vue").ComputedRef<any>;
11
- permissions: import("vue").ComputedRef<any>;
12
- token: import("vue").ComputedRef<string | null>;
11
+ permissions: import("vue").Ref<any[], any[]>;
12
+ token: import("vue").Ref<string | null, string | null>;
13
13
  ssoToken: import("vue").ComputedRef<string | null>;
14
14
  feathersToken: import("vue").ComputedRef<string | null>;
15
15
  init: () => Promise<void>;
16
16
  login: (options?: any) => Promise<any>;
17
17
  logout: (options?: any) => Promise<any>;
18
+ ensureReady: (reason?: string) => Promise<void>;
19
+ getAuthorizationHeader: () => Promise<string | null>;
18
20
  };
19
- export {};
@@ -1,155 +1,47 @@
1
- import { useNuxtApp, useRuntimeConfig } from "#imports";
2
- import { computed, ref } from "vue";
3
- import { useAuthStore } from "../stores/auth.js";
4
- import { buildRemoteAuthPayload } from "../utils/auth.js";
5
- import { getForcedAuthProvider, getPublicClientMode, getPublicRemoteAuthConfig, hasPublicKeycloakConfig, isPublicRemoteAuthEnabled } from "../utils/config.js";
1
+ import { useNuxtApp } from "#imports";
2
+ import { computed } from "vue";
3
+ import { useAuthRuntime } from "./useAuthRuntime.js";
6
4
  export function useAuth() {
5
+ const runtime = useAuthRuntime();
7
6
  const nuxtApp = useNuxtApp();
8
- const rc = useRuntimeConfig();
9
- const pub = rc.public;
10
- const provider = computed(() => {
11
- const forced = getForcedAuthProvider(pub);
12
- if (forced === "keycloak")
13
- return "keycloak";
14
- if (forced === "remote")
15
- return "remote";
16
- if (forced === "local")
17
- return "local";
18
- const cm = getPublicClientMode(pub);
19
- const remoteAuth = getPublicRemoteAuthConfig(pub);
20
- if (hasPublicKeycloakConfig(pub) && cm === "remote" && remoteAuth?.enabled && remoteAuth?.payloadMode === "keycloak")
21
- return "keycloak";
22
- if (isPublicRemoteAuthEnabled(pub))
23
- return "remote";
24
- if (hasPublicKeycloakConfig(pub))
25
- return "keycloak";
26
- if (pub?._feathers?.auth)
27
- return "local";
28
- return "none";
29
- });
30
- const ready = ref(false);
31
- const keycloak = computed(() => nuxtApp.$keycloak);
32
- const authStore = computed(() => {
33
- try {
34
- return useAuthStore();
35
- } catch {
36
- return null;
37
- }
38
- });
39
- const ssoUser = computed(() => {
40
- const kc = keycloak.value;
41
- return kc?.user ?? (kc?.tokenParsed ? { ...kc.tokenParsed, userid: kc.userid ?? kc.tokenParsed?.preferred_username } : null);
42
- });
43
- const feathersUser = computed(() => authStore.value?.user ?? null);
44
- const ssoToken = computed(() => keycloak.value?.token?.() ?? null);
45
- const feathersToken = computed(() => authStore.value?.accessToken ?? null);
46
- const isSsoAuthenticated = computed(() => {
47
- if (provider.value !== "keycloak")
48
- return false;
49
- return Boolean(keycloak.value?.authenticated);
50
- });
51
- const isFeathersAuthenticated = computed(() => {
52
- if (provider.value === "keycloak")
53
- return Boolean(authStore.value?.authenticated || keycloak.value?.authenticated);
54
- if (provider.value === "local" || provider.value === "remote")
55
- return Boolean(authStore.value?.authenticated);
56
- return false;
57
- });
58
- const isAuthenticated = computed(() => {
59
- if (provider.value === "keycloak")
60
- return Boolean(isSsoAuthenticated.value || isFeathersAuthenticated.value);
61
- if (provider.value === "local" || provider.value === "remote")
62
- return Boolean(isFeathersAuthenticated.value);
63
- return false;
64
- });
65
- const user = computed(() => {
66
- if (provider.value === "keycloak")
67
- return feathersUser.value ?? ssoUser.value ?? null;
68
- if (provider.value === "local" || provider.value === "remote")
69
- return feathersUser.value ?? null;
70
- return null;
71
- });
72
- const permissions = computed(() => {
73
- if (provider.value === "keycloak")
74
- return keycloak.value?.permissions ?? [];
75
- return [];
76
- });
77
- const token = computed(() => {
78
- if (provider.value === "keycloak")
79
- return feathersToken.value ?? ssoToken.value ?? null;
80
- if (provider.value === "local" || provider.value === "remote")
81
- return feathersToken.value ?? null;
82
- return null;
83
- });
7
+ const isSsoAuthenticated = computed(() => runtime.provider.value === "keycloak" && runtime.authenticated.value);
8
+ const isFeathersAuthenticated = computed(() => runtime.authenticated.value);
9
+ const isAuthenticated = computed(() => runtime.authenticated.value);
10
+ const ssoUser = computed(() => runtime.provider.value === "keycloak" ? runtime.user.value : null);
11
+ const feathersUser = computed(() => runtime.user.value);
12
+ const ssoToken = computed(() => runtime.provider.value === "keycloak" ? runtime.accessToken.value : null);
13
+ const feathersToken = computed(() => runtime.accessToken.value);
84
14
  async function init() {
85
- if (import.meta.server)
86
- return;
87
- if (ready.value) {
88
- if (provider.value !== "keycloak")
89
- return;
90
- if (!isAuthenticated.value)
91
- return;
92
- if (user.value)
93
- return;
94
- }
95
- if (provider.value === "keycloak") {
96
- const kc = keycloak.value;
97
- if (kc?.authenticated && typeof kc.ensureFeathersAuth === "function")
98
- await kc.ensureFeathersAuth("useAuth.init").catch(() => false);
99
- if (kc?.authenticated && typeof kc.whoami === "function")
100
- await kc.whoami().catch(() => null);
101
- }
102
- if (provider.value === "local" || provider.value === "remote") {
103
- const s = authStore.value;
104
- if (s?.restore) {
105
- await s.restore().catch(() => {
106
- });
107
- } else {
108
- const api = nuxtApp.$api;
109
- await api?.reAuthenticate?.().catch(() => {
110
- });
111
- }
112
- }
113
- ready.value = true;
15
+ await runtime.ensureReady();
114
16
  }
115
17
  async function login(options) {
116
- if (provider.value === "keycloak")
117
- return keycloak.value?.login?.(options);
118
- if (provider.value === "local")
119
- return authStore.value?.authenticate?.(options);
120
- if (provider.value === "remote") {
121
- const pub2 = useRuntimeConfig().public;
122
- const ra = getPublicRemoteAuthConfig(pub2);
123
- const token2 = options?.token || options?.accessToken || options?.access_token;
124
- if (!token2)
125
- throw new Error("Remote login requires a token (options.token)");
126
- const payload = buildRemoteAuthPayload(token2, ra);
127
- return authStore.value?.authenticate?.(payload);
128
- }
18
+ if (runtime.provider.value === "keycloak")
19
+ return nuxtApp.$keycloak?.login?.(options);
20
+ return runtime.authenticate(options);
129
21
  }
130
22
  async function logout(options) {
131
- if (provider.value === "keycloak")
132
- return keycloak.value?.logout?.(options);
133
- if (provider.value === "local")
134
- return authStore.value?.logout?.();
135
- if (provider.value === "remote")
136
- return authStore.value?.logout?.();
23
+ if (runtime.provider.value === "keycloak")
24
+ return nuxtApp.$keycloak?.logout?.(options);
25
+ return runtime.logout();
137
26
  }
138
27
  return {
139
- provider,
140
- ready,
28
+ provider: runtime.provider,
29
+ ready: runtime.ready,
30
+ status: runtime.status,
141
31
  isAuthenticated,
142
32
  isSsoAuthenticated,
143
33
  isFeathersAuthenticated,
144
- user,
34
+ user: runtime.user,
145
35
  ssoUser,
146
36
  feathersUser,
147
- permissions,
148
- token,
37
+ permissions: runtime.permissions,
38
+ token: runtime.accessToken,
149
39
  ssoToken,
150
40
  feathersToken,
151
41
  init,
152
42
  login,
153
- logout
43
+ logout,
44
+ ensureReady: runtime.ensureReady,
45
+ getAuthorizationHeader: runtime.getAuthorizationHeader
154
46
  };
155
47
  }
@@ -0,0 +1,6 @@
1
+ export interface AuthBoundOptions extends RequestInit {
2
+ auth?: 'required' | 'optional' | 'none';
3
+ retryOn401?: boolean;
4
+ }
5
+ export declare function useAuthBoundFetchImplementation(defaults?: Partial<AuthBoundOptions>): (input: RequestInfo | URL, init?: AuthBoundOptions) => Promise<any>;
6
+ export declare function useAuthBoundFetch(defaults?: Partial<AuthBoundOptions>): <T = any>(input: RequestInfo | URL, init?: AuthBoundOptions) => Promise<T>;
@@ -0,0 +1,86 @@
1
+ import { useRequestFetch } from "#imports";
2
+ import { useAuthRuntime } from "./useAuthRuntime.js";
3
+ function mergeHeaders(input, authorization) {
4
+ const headers = new Headers(input || {});
5
+ if (authorization && !headers.has("authorization") && !headers.has("Authorization")) {
6
+ headers.set("Authorization", authorization);
7
+ }
8
+ return headers;
9
+ }
10
+ function toRequestInit(input, init, headers) {
11
+ const request = input instanceof Request ? input : null;
12
+ const base = request ? {
13
+ method: request.method,
14
+ body: request.body,
15
+ credentials: request.credentials,
16
+ cache: request.cache,
17
+ integrity: request.integrity,
18
+ keepalive: request.keepalive,
19
+ mode: request.mode,
20
+ redirect: request.redirect,
21
+ referrer: request.referrer,
22
+ referrerPolicy: request.referrerPolicy,
23
+ signal: request.signal
24
+ } : {};
25
+ const result = {
26
+ ...base,
27
+ ...init,
28
+ headers
29
+ };
30
+ delete result.auth;
31
+ delete result.retryOn401;
32
+ return result;
33
+ }
34
+ function resolveNativeFetch() {
35
+ if (import.meta.server)
36
+ return useRequestFetch();
37
+ if (typeof window !== "undefined" && typeof window.fetch === "function")
38
+ return window.fetch.bind(window);
39
+ if (typeof globalThis.fetch === "function")
40
+ return globalThis.fetch.bind(globalThis);
41
+ throw new Error("[nuxt-feathers-zod] No native fetch implementation available");
42
+ }
43
+ export function useAuthBoundFetchImplementation(defaults = {}) {
44
+ const auth = useAuthRuntime();
45
+ const nativeFetch = resolveNativeFetch();
46
+ return async function authBoundFetch(input, init = {}) {
47
+ const authMode = init.auth ?? defaults.auth ?? "required";
48
+ const retryOn401 = init.retryOn401 ?? defaults.retryOn401 ?? true;
49
+ if (authMode !== "none") {
50
+ await auth.ensureReady("auth-bound-fetch");
51
+ if (auth.provider.value === "keycloak")
52
+ await auth.ensureValidatedBearer("auth-bound-fetch");
53
+ }
54
+ async function execute() {
55
+ const authorization = authMode === "none" ? null : await auth.getAuthorizationHeader();
56
+ const headers = mergeHeaders(init.headers, authorization);
57
+ return await nativeFetch(input, toRequestInit(input, init, headers));
58
+ }
59
+ let response = await execute();
60
+ if (authMode !== "none" && retryOn401 && response.status === 401) {
61
+ await auth.reAuthenticate().catch(() => null);
62
+ response = await execute();
63
+ }
64
+ return response;
65
+ };
66
+ }
67
+ export function useAuthBoundFetch(defaults = {}) {
68
+ const request = useAuthBoundFetchImplementation(defaults);
69
+ return async function authBoundRequest(input, init = {}) {
70
+ const response = await request(input, init);
71
+ if (response.status === 204)
72
+ return null;
73
+ const contentType = response.headers.get("content-type") || "";
74
+ const payload = contentType.includes("application/json") ? await response.json() : await response.text();
75
+ if (!response.ok) {
76
+ throw {
77
+ name: "AuthBoundFetchError",
78
+ message: payload?.message || response.statusText || "Request failed",
79
+ status: response.status,
80
+ statusCode: response.status,
81
+ data: payload
82
+ };
83
+ }
84
+ return payload;
85
+ };
86
+ }
@@ -0,0 +1,24 @@
1
+ export declare function useAuthDiagnostics(): import("vue").ComputedRef<{
2
+ provider: "none" | "local" | "remote" | "keycloak";
3
+ status: "error" | "idle" | "bootstrapping" | "authenticated" | "anonymous";
4
+ ready: boolean;
5
+ bootstrapping: boolean;
6
+ authenticated: boolean;
7
+ hasAccessToken: boolean;
8
+ tokenSource: "none" | "storage" | "authenticate" | "reauth" | "keycloak-bridge" | "keycloak-fallback" | "runtime";
9
+ user: any;
10
+ permissions: any[];
11
+ error: any;
12
+ lastSyncAt: number;
13
+ lastReadyAt: number;
14
+ lastAuthenticateAt: number;
15
+ lastReAuthenticateAt: number;
16
+ lastBridgeAt: number;
17
+ lastEnsureReason: string;
18
+ bridgePath: string;
19
+ clientSync: {
20
+ api: "error" | "idle" | "ok" | "missing";
21
+ client: "error" | "idle" | "ok" | "missing";
22
+ feathersClient: "error" | "idle" | "ok" | "missing";
23
+ };
24
+ }>;
@@ -0,0 +1,25 @@
1
+ import { computed } from "vue";
2
+ import { useAuthRuntime } from "./useAuthRuntime.js";
3
+ export function useAuthDiagnostics() {
4
+ const auth = useAuthRuntime();
5
+ return computed(() => ({
6
+ provider: auth.provider.value,
7
+ status: auth.status.value,
8
+ ready: auth.ready.value,
9
+ bootstrapping: auth.bootstrapping.value,
10
+ authenticated: auth.authenticated.value,
11
+ hasAccessToken: Boolean(auth.accessToken.value),
12
+ tokenSource: auth.tokenSource.value,
13
+ user: auth.user.value,
14
+ permissions: auth.permissions.value,
15
+ error: auth.error.value,
16
+ lastSyncAt: auth.lastSyncAt.value,
17
+ lastReadyAt: auth.lastReadyAt.value,
18
+ lastAuthenticateAt: auth.lastAuthenticateAt.value,
19
+ lastReAuthenticateAt: auth.lastReAuthenticateAt.value,
20
+ lastBridgeAt: auth.lastBridgeAt.value,
21
+ lastEnsureReason: auth.lastEnsureReason.value,
22
+ bridgePath: auth.bridgePath.value,
23
+ clientSync: auth.clientSync.value
24
+ }));
25
+ }
@@ -0,0 +1,77 @@
1
+ type AuthProvider = 'keycloak' | 'local' | 'remote' | 'none';
2
+ type AuthStatus = 'idle' | 'bootstrapping' | 'authenticated' | 'anonymous' | 'error';
3
+ type TokenSource = 'none' | 'storage' | 'authenticate' | 'reauth' | 'keycloak-bridge' | 'keycloak-fallback' | 'runtime';
4
+ type AuthSyncState = 'idle' | 'ok' | 'missing' | 'error';
5
+ export declare function useAuthRuntime(): {
6
+ provider: import("vue").ComputedRef<AuthProvider>;
7
+ ensureReady: (reason?: string) => Promise<void>;
8
+ authenticate: (payload: any) => Promise<any>;
9
+ reAuthenticate: () => Promise<any>;
10
+ logout: () => Promise<void>;
11
+ setSession: (payload?: {
12
+ user?: any;
13
+ accessToken?: string | null;
14
+ authenticated?: boolean;
15
+ permissions?: any[];
16
+ error?: any;
17
+ }, source?: TokenSource) => Promise<void>;
18
+ synchronizeKeycloakSession: (reason?: string, hint?: {
19
+ token?: string | null;
20
+ user?: any;
21
+ tokenParsed?: any;
22
+ permissions?: any[];
23
+ loginuser?: string | null;
24
+ }) => Promise<boolean>;
25
+ ensureValidatedBearer: (reason?: string) => Promise<boolean>;
26
+ getAuthorizationHeader: () => Promise<string | null>;
27
+ getStateSnapshot: () => {
28
+ provider: AuthProvider;
29
+ status: AuthStatus;
30
+ ready: boolean;
31
+ bootstrapping: boolean;
32
+ authenticated: boolean;
33
+ accessToken: string | null;
34
+ user: any;
35
+ permissions: any[];
36
+ tokenSource: TokenSource;
37
+ error: any;
38
+ lastSyncAt: number;
39
+ lastReadyAt: number;
40
+ lastAuthenticateAt: number;
41
+ lastReAuthenticateAt: number;
42
+ lastBridgeAt: number;
43
+ lastEnsureReason: string;
44
+ bridgePath: string;
45
+ clientSync: {
46
+ api: AuthSyncState;
47
+ client: AuthSyncState;
48
+ feathersClient: AuthSyncState;
49
+ };
50
+ };
51
+ status: import("vue").Ref<AuthStatus, AuthStatus>;
52
+ ready: import("vue").Ref<boolean, boolean>;
53
+ bootstrapping: import("vue").Ref<boolean, boolean>;
54
+ authenticated: import("vue").Ref<boolean, boolean>;
55
+ accessToken: import("vue").Ref<string | null, string | null>;
56
+ user: import("vue").Ref<any, any>;
57
+ permissions: import("vue").Ref<any[], any[]>;
58
+ tokenSource: import("vue").Ref<TokenSource, TokenSource>;
59
+ error: import("vue").Ref<any, any>;
60
+ lastSyncAt: import("vue").Ref<number, number>;
61
+ lastReadyAt: import("vue").Ref<number, number>;
62
+ lastAuthenticateAt: import("vue").Ref<number, number>;
63
+ lastReAuthenticateAt: import("vue").Ref<number, number>;
64
+ lastBridgeAt: import("vue").Ref<number, number>;
65
+ lastEnsureReason: import("vue").Ref<string, string>;
66
+ bridgePath: import("vue").Ref<string, string>;
67
+ clientSync: import("vue").Ref<{
68
+ api: AuthSyncState;
69
+ client: AuthSyncState;
70
+ feathersClient: AuthSyncState;
71
+ }, {
72
+ api: AuthSyncState;
73
+ client: AuthSyncState;
74
+ feathersClient: AuthSyncState;
75
+ }>;
76
+ };
77
+ export {};