nuxt-directus-sdk 3.1.0 → 4.0.1

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 (35) hide show
  1. package/README.md +18 -5
  2. package/dist/module.d.mts +48 -49
  3. package/dist/module.json +12 -0
  4. package/dist/module.mjs +105 -27
  5. package/dist/runtime/components/directus-visual-editor.d.vue.ts +21 -0
  6. package/dist/runtime/components/directus-visual-editor.vue +37 -33
  7. package/dist/runtime/components/directus-visual-editor.vue.d.ts +21 -0
  8. package/dist/runtime/composables/auth.d.ts +2 -8
  9. package/dist/runtime/composables/auth.js +15 -24
  10. package/dist/runtime/composables/directus.d.ts +1 -1
  11. package/dist/runtime/composables/directus.js +39 -25
  12. package/dist/runtime/composables/files.d.ts +2 -3
  13. package/dist/runtime/composables/files.js +0 -6
  14. package/dist/runtime/composables/storage.d.ts +6 -0
  15. package/dist/runtime/composables/storage.js +11 -0
  16. package/dist/runtime/middleware/guest.d.ts +2 -0
  17. package/dist/runtime/middleware/guest.js +3 -0
  18. package/dist/runtime/plugin.js +7 -36
  19. package/dist/runtime/server/routes/directus.d.ts +2 -0
  20. package/dist/runtime/server/routes/directus.js +10 -0
  21. package/dist/runtime/server/services/directus.d.ts +3 -3
  22. package/dist/runtime/server/services/directus.js +6 -6
  23. package/dist/runtime/server/services/index.d.ts +1 -1
  24. package/dist/runtime/server/services/index.js +1 -1
  25. package/dist/runtime/types/generate.d.ts +4 -0
  26. package/dist/runtime/types/generate.js +125 -43
  27. package/dist/runtime/types/index.d.ts +1 -0
  28. package/dist/runtime/types/index.js +1 -0
  29. package/dist/runtime/types/types.d.ts +1 -0
  30. package/dist/types.d.mts +3 -0
  31. package/package.json +22 -16
  32. package/dist/module.cjs +0 -5
  33. package/dist/module.d.ts +0 -140
  34. package/dist/runtime/composables/tokens.d.ts +0 -9
  35. package/dist/runtime/composables/tokens.js +0 -55
package/README.md CHANGED
@@ -5,13 +5,14 @@
5
5
  [![License][license-src]][license-href]
6
6
  [![Nuxt][nuxt-src]][nuxt-href]
7
7
 
8
- > A Nuxt 3 Directus module that uses the Directus SDK to enhance your Nuxt application
8
+ > A Nuxt 4 Directus module that uses the Directus SDK to enhance your Nuxt application
9
9
 
10
10
  - [✨  Release Notes](/CHANGELOG.md)
11
- - [🔗  Documentation - Coming soon!](http://nuxt-directus-sdk.vercel.app)
11
+ - [📚  Documentation](https://nuxt-directus-sdk.rolley.io)
12
12
 
13
13
  ## Features
14
14
 
15
+ - 🔒  **Session-based authentication** with cross-domain support
15
16
  - ⛰  Authentication out of the box
16
17
  - 🚠  Type generation based on Directus collections
17
18
  - 🔥  Typesafe Client Websockets enabled
@@ -44,17 +45,29 @@ export default defineNuxtConfig({
44
45
  'nuxt-directus-sdk'
45
46
  ],
46
47
  directus: {
47
- url: '',
48
+ // Optional: customize authentication (defaults shown)
49
+ auth: {
50
+ autoRefresh: true,
51
+ credentials: 'include', // Required for cross-domain
52
+ realtimeAuthMode: 'public',
53
+ }
48
54
  }
49
55
  })
50
56
  ```
51
57
 
52
- 3. OPTIONAL: Add an Directus admin token to .env file for additional goodies (Type generation, admin server directus)
58
+ 3. Create a `.env` file:
53
59
 
54
- DIRECTUS_ADMIN_TOKEN=""
60
+ ```env
61
+ DIRECTUS_URL=https://your-directus-url.com
62
+ DIRECTUS_ADMIN_TOKEN=your_admin_token # Optional: for type generation
63
+ ```
64
+
65
+ 4. **Configure your Directus backend** for cross-domain authentication (see [Authentication Guide](https://nuxt-directus-sdk.rolley.io/guide/authentication))
55
66
 
56
67
  That's it! You can now use Directus within your Nuxt app ✨
57
68
 
69
+ For cross-domain setups (e.g., `app.example.com` ↔ `api.example.com`), see the [Authentication Guide](https://nuxt-directus-sdk.rolley.io/guide/authentication).
70
+
58
71
  ## Development
59
72
 
60
73
  ```bash
package/dist/module.d.mts CHANGED
@@ -8,6 +8,25 @@ interface ModuleOptions {
8
8
  * @type string
9
9
  */
10
10
  url: string;
11
+ /**
12
+ * Development proxy configuration
13
+ * When enabled, creates a proxy at /directus that forwards to your Directus URL
14
+ * This solves CORS and cookie issues in development
15
+ * @default { enabled: true, path: '/directus' } in dev mode
16
+ * @type boolean | { enabled?: boolean, path?: string }
17
+ */
18
+ devProxy?: boolean | {
19
+ /**
20
+ * Enable the development proxy
21
+ * @default true in dev mode, false in production
22
+ */
23
+ enabled?: boolean;
24
+ /**
25
+ * Proxy path (where the proxy will be mounted)
26
+ * @default '/directus'
27
+ */
28
+ path?: string;
29
+ };
11
30
  /**
12
31
  * Admin Auth Token used for generating types and server functions
13
32
  * @default process.env.DIRECTUS_ADMIN_TOKEN
@@ -43,56 +62,31 @@ interface ModuleOptions {
43
62
  * @type boolean
44
63
  */
45
64
  enableGlobalAuthMiddleware?: boolean;
65
+ /**
66
+ * Auto refresh tokens
67
+ * @default true
68
+ * @type boolean
69
+ */
70
+ autoRefresh?: boolean;
71
+ /**
72
+ * Credentials mode for cross-domain requests
73
+ * Set to 'include' when your frontend and backend are on different domains
74
+ * @default 'include'
75
+ * @type RequestCredentials
76
+ */
77
+ credentials?: RequestCredentials;
78
+ /**
79
+ * Realtime/WebSocket authentication mode
80
+ * @default 'handshake'
81
+ * @type 'public' | 'handshake' | 'strict'
82
+ */
83
+ realtimeAuthMode?: 'public' | 'handshake' | 'strict';
46
84
  /**
47
85
  * ReadMe fields to fetch
48
86
  * @default []
49
- * @type Query<AllDirectusCollections, AllDirectusCollections['directus_users']>['fields']
87
+ * @type Query<DirectusSchema, DirectusSchema['directus_users']>['fields']
50
88
  */
51
- readMeFields?: Query<AllDirectusCollections, AllDirectusCollections['directus_users']>['fields'];
52
- cookies?: {
53
- /**
54
- * Session token cookie name
55
- * @default 'directus_access_token'
56
- */
57
- accessToken?: string;
58
- /**
59
- * Refresh token cookie name
60
- * @default 'directus_refresh_token'
61
- */
62
- refreshToken?: string;
63
- /**
64
- * Logged in token cookie name
65
- * @default 'directus_logged_in'
66
- */
67
- loggedInToken?: string;
68
- /**
69
- * Session token cookie max age
70
- * @default 900
71
- */
72
- maxAge?: number;
73
- /**
74
- * Refresh token cookie max age
75
- * @default 604800
76
- */
77
- maxAgeRefreshToken?: number;
78
- /**
79
- * SameSite cookie attribute
80
- * @default 'lax'
81
- */
82
- sameSite?: 'lax' | 'strict' | 'none';
83
- /**
84
- * Secure cookie attribute
85
- * @default false
86
- * @type boolean
87
- */
88
- secure?: boolean;
89
- /**
90
- * Domain cookie attribute
91
- * @default undefined
92
- * @type string | undefined
93
- */
94
- domain?: string | undefined;
95
- };
89
+ readMeFields?: Query<DirectusSchema, DirectusSchema['directus_users']>['fields'];
96
90
  redirect?: {
97
91
  /**
98
92
  * Redirect to home page after login
@@ -128,13 +122,18 @@ interface ModuleOptions {
128
122
  }
129
123
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
130
124
 
125
+ interface NuxtDirectusModuleOptions extends ModuleOptions {
126
+ directusUrl: string;
127
+ wsProxyUrl?: string;
128
+ }
131
129
  declare module '@nuxt/schema' {
132
130
  interface ConfigSchema {
133
- directus?: ModuleOptions;
131
+ directus?: NuxtDirectusModuleOptions;
134
132
  publicRuntimeConfig?: {
135
- directus?: Omit<ModuleOptions, 'adminToken'>;
133
+ directus?: Omit<NuxtDirectusModuleOptions, 'adminToken'>;
136
134
  };
137
135
  }
138
136
  }
139
137
 
140
- export { type ModuleOptions, _default as default };
138
+ export { _default as default };
139
+ export type { ModuleOptions };
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "nuxt-directus-sdk",
3
+ "version": "4.0.1",
4
+ "configKey": "directus",
5
+ "compatibility": {
6
+ "nuxt": "^4.0.0"
7
+ },
8
+ "builder": {
9
+ "@nuxt/module-builder": "1.0.2",
10
+ "unbuild": "3.6.1"
11
+ }
12
+ }
package/dist/module.mjs CHANGED
@@ -1,10 +1,11 @@
1
- import { useLogger, defineNuxtModule, createResolver, installModule, addPlugin, addRouteMiddleware, addImportsDir, addComponentsDir, addImportsSources, addTypeTemplate } from '@nuxt/kit';
1
+ import { useLogger, defineNuxtModule, createResolver, addServerHandler, installModule, addPlugin, addRouteMiddleware, addImportsDir, addComponentsDir, addImportsSources, addTypeTemplate } from '@nuxt/kit';
2
2
  import { defu } from 'defu';
3
+ import { joinURL } from 'ufo';
3
4
  import { generateTypes } from '../dist/runtime/types/index.js';
4
5
  import { useUrl } from '../dist/runtime/utils/index.js';
5
6
 
6
7
  const name = "nuxt-directus-sdk";
7
- const version = "3.1.0";
8
+ const version = "4.0.1";
8
9
 
9
10
  const configKey = "directus";
10
11
  const logger = useLogger("nuxt-directus-sdk");
@@ -14,12 +15,13 @@ const module = defineNuxtModule({
14
15
  version,
15
16
  configKey,
16
17
  compatibility: {
17
- nuxt: "^3.0.0",
18
- bridge: false
18
+ nuxt: "^4.0.0"
19
19
  }
20
20
  },
21
21
  defaults: {
22
22
  url: import.meta.env.DIRECTUS_URL ?? "",
23
+ devProxy: void 0,
24
+ // Will be set based on dev mode in setup
23
25
  adminToken: import.meta.env.DIRECTUS_ADMIN_TOKEN ?? "",
24
26
  devtools: true,
25
27
  visualEditor: true,
@@ -30,18 +32,10 @@ const module = defineNuxtModule({
30
32
  auth: {
31
33
  enabled: true,
32
34
  enableGlobalAuthMiddleware: false,
35
+ autoRefresh: true,
36
+ credentials: "include",
37
+ realtimeAuthMode: "public",
33
38
  readMeFields: [],
34
- cookies: {
35
- accessToken: "directus_access_token",
36
- refreshToken: "directus_refresh_token",
37
- loggedInToken: "directus_logged_in",
38
- maxAge: 900,
39
- maxAgeRefreshToken: 604800,
40
- // Nuxt Cookies Docs @ https://nuxt.com/docs/api/composables/use-cookie
41
- sameSite: "lax",
42
- secure: false,
43
- domain: void 0
44
- },
45
39
  redirect: {
46
40
  home: "/",
47
41
  login: "/account/login",
@@ -54,11 +48,88 @@ const module = defineNuxtModule({
54
48
  logger.error("nuxt-directus-sdk requires a url to your Directus instance, set it in the config options or .env file as DIRECTUS_URL");
55
49
  return;
56
50
  }
51
+ const resolver = createResolver(import.meta.url);
52
+ const devProxyConfig = typeof options.devProxy === "boolean" ? { enabled: options.devProxy } : { ...options.devProxy };
53
+ const devProxyEnabled = devProxyConfig.enabled ?? nuxtApp.options.dev;
54
+ const devProxyPath = devProxyConfig.path ?? "/directus";
55
+ const directusUrl = options.url;
56
+ if (devProxyEnabled && nuxtApp.options.dev) {
57
+ const devPort = nuxtApp.options.devServer?.port ?? 3e3;
58
+ const devHost = nuxtApp.options.devServer?.host ?? "localhost";
59
+ const baseUrl = `http://${devHost}:${devPort}`;
60
+ const proxyUrl = `${baseUrl}${devProxyPath}/`;
61
+ const wsProxyPath = `${devProxyPath}-ws`;
62
+ const wsTarget = joinURL(directusUrl, "websocket");
63
+ logger.info(`\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501`);
64
+ logger.info(`\u{1F504} Directus Development Proxy Enabled`);
65
+ logger.info(` Proxy path: ${devProxyPath}`);
66
+ logger.info(` Forwarding to: ${directusUrl}`);
67
+ logger.info(` Local URL: ${proxyUrl}`);
68
+ logger.info(` WebSocket proxy path: ${wsProxyPath}`);
69
+ logger.info(` WebSocket target: ${wsTarget}`);
70
+ logger.info(`\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501`);
71
+ nuxtApp.options.nitro = nuxtApp.options.nitro || {};
72
+ nuxtApp.options.nitro.devProxy = nuxtApp.options.nitro.devProxy || {};
73
+ nuxtApp.options.nitro.devProxy[wsProxyPath] = {
74
+ target: directusUrl,
75
+ changeOrigin: true,
76
+ ws: true
77
+ };
78
+ const httpProxy = await import('http-proxy');
79
+ const proxy = httpProxy.default.createProxyServer({
80
+ target: directusUrl,
81
+ changeOrigin: true,
82
+ ws: true,
83
+ secure: false
84
+ // Allow self-signed certificates
85
+ });
86
+ proxy.on("error", (err, _req, socket) => {
87
+ logger.error(`WebSocket proxy error:`, err.message);
88
+ if (socket && !socket.destroyed) {
89
+ socket.end();
90
+ }
91
+ });
92
+ proxy.on("proxyReqWs", (proxyReq, req, _socket) => {
93
+ proxyReq.path = "/websocket";
94
+ if (req.headers.cookie) {
95
+ proxyReq.setHeader("cookie", req.headers.cookie);
96
+ }
97
+ });
98
+ nuxtApp.hook("ready", () => {
99
+ const originalUpgrade = nuxtApp.server?.upgrade;
100
+ if (nuxtApp.server) {
101
+ nuxtApp.server.upgrade = (req, socket, head) => {
102
+ if (req.url?.startsWith(wsProxyPath)) {
103
+ try {
104
+ proxy.ws(req, socket, head);
105
+ } catch (err) {
106
+ logger.error("WebSocket proxy error:", err.message);
107
+ if (!socket.destroyed) {
108
+ socket.destroy();
109
+ }
110
+ }
111
+ } else if (originalUpgrade) {
112
+ return originalUpgrade(req, socket, head);
113
+ } else if (!socket.destroyed) {
114
+ socket.destroy();
115
+ }
116
+ };
117
+ }
118
+ });
119
+ addServerHandler({
120
+ route: `${devProxyPath}/**`,
121
+ handler: resolver.resolve("./runtime/server/routes/directus")
122
+ });
123
+ options.url = proxyUrl;
124
+ options.wsProxyUrl = joinURL(baseUrl, wsProxyPath);
125
+ } else if (!nuxtApp.options.dev) {
126
+ logger.info(`\u{1F310} Production mode: Connecting directly to ${directusUrl}`);
127
+ }
128
+ options.directusUrl = directusUrl;
57
129
  nuxtApp.options.runtimeConfig[configKey] = options;
58
130
  nuxtApp.options.runtimeConfig.public = nuxtApp.options.runtimeConfig.public || {};
59
131
  nuxtApp.options.runtimeConfig.public[configKey] = defu(nuxtApp.options.runtimeConfig.public[configKey], options);
60
132
  delete nuxtApp.options.runtimeConfig.public[configKey].adminToken;
61
- const resolver = createResolver(import.meta.url);
62
133
  await installModule("@nuxt/image", {
63
134
  directus: {
64
135
  baseURL: useUrl(options.url, "assets")
@@ -70,6 +141,10 @@ const module = defineNuxtModule({
70
141
  path: resolver.resolve("./runtime/middleware/auth"),
71
142
  global: options.auth?.enableGlobalAuthMiddleware
72
143
  });
144
+ addRouteMiddleware({
145
+ name: "guest",
146
+ path: resolver.resolve("./runtime/middleware/guest")
147
+ });
73
148
  addImportsDir(resolver.resolve("./runtime/composables"));
74
149
  addComponentsDir({
75
150
  path: resolver.resolve("./runtime/components"),
@@ -143,16 +218,16 @@ const module = defineNuxtModule({
143
218
  nitroConfig.imports.presets.push({
144
219
  from: resolver.resolve("./runtime/server/services"),
145
220
  imports: [
146
- "useDirectus",
147
- "useUserDirectus",
221
+ "getDirectusSessionToken",
148
222
  "useAdminDirectus",
223
+ "useServerDirectus",
149
224
  "useDirectusUrl",
150
- "useDirectusAccessToken"
225
+ "useTokenDirectus"
151
226
  ]
152
227
  });
153
228
  });
154
229
  if (options.devtools) {
155
- const adminUrl = useUrl(options.url, "admin");
230
+ const adminUrl = useUrl(directusUrl, "admin");
156
231
  logger.info(`Directus Admin URL: ${adminUrl}`);
157
232
  nuxtApp.hook("devtools:customTabs", (iframeTabs) => {
158
233
  iframeTabs.push({
@@ -172,16 +247,19 @@ const module = defineNuxtModule({
172
247
  if (!options.adminToken) {
173
248
  logger.warn("Directus types generation is disabled, set the admin token in the config or .env file as DIRECTUS_ADMIN_TOKEN");
174
249
  } else {
175
- logger.info("Generating Directus types");
176
250
  try {
251
+ let cachedTypes = null;
177
252
  const typesPath = addTypeTemplate({
178
253
  filename: `types/${configKey}.d.ts`,
179
- getContents() {
180
- return generateTypes({
181
- url: useUrl(options.url),
182
- token: options.adminToken,
183
- prefix: options.types?.prefix ?? ""
184
- });
254
+ async getContents() {
255
+ if (!cachedTypes) {
256
+ cachedTypes = await generateTypes({
257
+ url: useUrl(directusUrl),
258
+ token: options.adminToken,
259
+ prefix: options.types?.prefix ?? ""
260
+ });
261
+ }
262
+ return cachedTypes;
185
263
  }
186
264
  }, { nitro: true, nuxt: true }).dst;
187
265
  nuxtApp.hook("prepare:types", (options2) => {
@@ -0,0 +1,21 @@
1
+ import type { PrimaryKey } from '@directus/types';
2
+ declare const _default: <T extends keyof DirectusSchema>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
3
+ props: __VLS_PrettifyLocal<Pick<Partial<{}> & Omit<{} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, never>, never> & {
4
+ collection: T;
5
+ item: PrimaryKey;
6
+ fields?: (string | number | symbol) | (string | number | symbol)[];
7
+ mode?: "drawer" | "modal" | "popover";
8
+ } & {}> & import("vue").PublicProps;
9
+ expose(exposed: import("vue").ShallowUnwrapRef<{}>): void;
10
+ attrs: any;
11
+ slots: {
12
+ default?: (props: {}) => any;
13
+ };
14
+ emit: {};
15
+ }>) => import("vue").VNode & {
16
+ __ctx?: Awaited<typeof __VLS_setup>;
17
+ };
18
+ export default _default;
19
+ type __VLS_PrettifyLocal<T> = {
20
+ [K in keyof T as K]: T[K];
21
+ } & {};
@@ -1,47 +1,51 @@
1
- <script setup lang="ts" generic="T extends keyof DirectusSchema">
2
- import type { PrimaryKey } from '@directus/types'
3
- import { computed } from '#imports'
4
- import { setAttr } from '@directus/visual-editing'
5
- import { useDirectusPreview } from '../composables/directus'
6
- import { Slot } from '../utils'
7
-
8
- type SingleDirectusCollection = DirectusSchema[T] extends Array<any> ? DirectusSchema[T][0] : DirectusSchema[T]
9
- type FieldKey = keyof SingleDirectusCollection
10
-
11
- const props = defineProps<{
12
- collection: T
13
- item: PrimaryKey
14
- fields?: FieldKey | FieldKey[]
15
- mode?: 'drawer' | 'modal' | 'popover'
16
- }>()
17
-
18
- const directusPreview = useDirectusPreview()
19
-
1
+ <script setup>
2
+ import { computed, onBeforeUnmount, onMounted, ref, useRuntimeConfig } from "#imports";
3
+ import { apply, setAttr } from "@directus/visual-editing";
4
+ import { useDirectusPreview } from "../composables/directus";
5
+ import { Slot } from "../utils";
6
+ const props = defineProps({
7
+ collection: { type: null, required: true },
8
+ item: { type: [String, Number], required: true },
9
+ fields: { type: null, required: false },
10
+ mode: { type: String, required: false }
11
+ });
12
+ const config = useRuntimeConfig();
13
+ const directusPreview = useDirectusPreview();
14
+ const editorElement = ref(null);
20
15
  const directusAttr = computed(() => {
21
- const data: Record<any, any> = {}
22
-
16
+ const data = {};
23
17
  Object.entries(props).forEach(([key, value]) => {
24
- if (value !== undefined) {
25
- data[key] = value
18
+ if (value !== void 0) {
19
+ data[key] = value;
26
20
  }
27
- })
28
-
29
- return setAttr(data as any)
30
- })
31
-
21
+ });
22
+ return setAttr(data);
23
+ });
32
24
  const attributes = computed(() => {
33
25
  if (!directusPreview.value) {
34
- return null
26
+ return null;
35
27
  }
36
-
37
28
  return {
38
- 'data-directus': directusAttr.value,
29
+ "data-directus": directusAttr.value
30
+ };
31
+ });
32
+ onMounted(async () => {
33
+ if (!config.public.directus.visualEditor || !editorElement.value || import.meta.server) {
34
+ return;
35
+ }
36
+ const applied = await apply({ directusUrl: config.public.directus.url });
37
+ if (!applied) {
38
+ return;
39
39
  }
40
- })
40
+ applied.enable();
41
+ onBeforeUnmount(() => {
42
+ applied.remove();
43
+ });
44
+ });
41
45
  </script>
42
46
 
43
47
  <template>
44
- <Slot v-bind="attributes">
48
+ <Slot ref="editorElement" v-bind="attributes">
45
49
  <slot />
46
50
  </Slot>
47
51
  </template>
@@ -0,0 +1,21 @@
1
+ import type { PrimaryKey } from '@directus/types';
2
+ declare const _default: <T extends keyof DirectusSchema>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
3
+ props: __VLS_PrettifyLocal<Pick<Partial<{}> & Omit<{} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, never>, never> & {
4
+ collection: T;
5
+ item: PrimaryKey;
6
+ fields?: (string | number | symbol) | (string | number | symbol)[];
7
+ mode?: "drawer" | "modal" | "popover";
8
+ } & {}> & import("vue").PublicProps;
9
+ expose(exposed: import("vue").ShallowUnwrapRef<{}>): void;
10
+ attrs: any;
11
+ slots: {
12
+ default?: (props: {}) => any;
13
+ };
14
+ emit: {};
15
+ }>) => import("vue").VNode & {
16
+ __ctx?: Awaited<typeof __VLS_setup>;
17
+ };
18
+ export default _default;
19
+ type __VLS_PrettifyLocal<T> = {
20
+ [K in keyof T as K]: T[K];
21
+ } & {};
@@ -8,20 +8,14 @@ export interface DirectusAuth {
8
8
  updateMe: (data: Partial<DirectusUsers>) => Promise<DirectusUsers | null>;
9
9
  login: (email: string, password: string, options?: LoginOptions & {
10
10
  redirect?: boolean | RouteLocationRaw;
11
- }) => Promise<{
12
- user: DirectusUsers | null;
13
- accessToken: string;
14
- refreshToken: string | null;
15
- expires: number | null;
16
- expiresAt: number | null;
17
- }>;
11
+ }) => Promise<DirectusUsers | null>;
18
12
  loginWithProvider: (provider: string, redirectOnLogin?: string) => Promise<void>;
19
13
  logout: (redirect?: boolean | RouteLocationRaw) => Promise<void>;
20
14
  createUser: (data: Partial<DirectusUsers>) => Promise<DirectusUsers>;
21
15
  register: (data: Partial<DirectusUsers>) => Promise<DirectusUsers>;
22
16
  inviteUser: (email: string, role: string, inviteUrl?: string | undefined) => Promise<void>;
23
17
  acceptUserInvite: (token: string, password: string) => Promise<void>;
24
- passwordRequest: (email: string, resetUrl?: string | null | undefined) => Promise<void>;
18
+ passwordRequest: (email: string, resetUrl?: string | undefined) => Promise<void>;
25
19
  passwordReset: (token: string, password: string) => Promise<void>;
26
20
  }
27
21
  export declare function useDirectusUser(): Ref<DirectusUsers | null>;
@@ -1,29 +1,33 @@
1
1
  import { navigateTo, useNuxtApp, useRouter, useRuntimeConfig } from "#app";
2
2
  import { computed, useState } from "#imports";
3
3
  import { acceptUserInvite as directusAcceptUserInvite, createUser as directusCreateUser, inviteUser as directusInviteUser, passwordRequest as directusPasswordRequest, passwordReset as directusPasswordReset, readMe as directusReadMe, updateMe as directusUpdateMe } from "@directus/sdk";
4
- import { useDirectus } from "./directus.js";
5
- import { useDirectusTokens } from "./tokens.js";
4
+ import { useDirectus, useDirectusUrl } from "./directus.js";
6
5
  export function useDirectusUser() {
7
6
  return useState("directus.user", () => null);
8
7
  }
8
+ function useDirectusUserLoading() {
9
+ return useState("directus.user.loading", () => false);
10
+ }
9
11
  export function useDirectusAuth() {
10
12
  const config = useRuntimeConfig();
11
13
  const router = useRouter();
12
14
  const directus = useDirectus();
13
- const tokens = useDirectusTokens();
14
15
  const user = useDirectusUser();
16
+ const loading = useDirectusUserLoading();
15
17
  const nuxtApp = useNuxtApp();
16
18
  const loggedIn = computed(() => user.value !== null);
17
19
  async function readMe() {
20
+ if (loading.value) {
21
+ return user.value;
22
+ }
23
+ loading.value = true;
18
24
  try {
19
- if (!tokens.accessToken.value) {
20
- if (!tokens.refreshToken.value)
21
- throw new Error("No refresh token");
22
- await directus.refresh();
23
- }
24
25
  user.value = await directus.request(directusReadMe({ fields: config.public.directus.auth?.readMeFields ?? ["*"] }));
25
- } catch {
26
+ } catch (error) {
27
+ console.error("[Auth] Failed to fetch user:", error);
26
28
  user.value = null;
29
+ } finally {
30
+ loading.value = false;
27
31
  }
28
32
  await nuxtApp.callHook("directus:loggedIn", user.value);
29
33
  return user.value;
@@ -36,9 +40,7 @@ export function useDirectusAuth() {
36
40
  return user.value;
37
41
  }
38
42
  async function login(email, password, options) {
39
- const response = await directus.login(email, password, { ...options, mode: "json" });
40
- if (!response.access_token)
41
- throw new Error("Login failed, please check your credentials.");
43
+ await directus.login({ email, password }, { ...options, mode: "session" });
42
44
  await readMe();
43
45
  const redirect = options?.redirect ?? true;
44
46
  if (redirect !== false) {
@@ -51,16 +53,9 @@ export function useDirectusAuth() {
51
53
  navigateTo(config.public.directus.auth?.redirect?.home ?? "/");
52
54
  }
53
55
  }
54
- return {
55
- user: user.value,
56
- accessToken: response.access_token,
57
- refreshToken: response.refresh_token,
58
- expires: response.expires,
59
- expiresAt: response.expires_at
60
- };
56
+ return user.value;
61
57
  }
62
58
  async function loginWithProvider(provider, redirectOnLogin) {
63
- await logout();
64
59
  const redirect = `${window.location.origin}${redirectOnLogin ?? router.currentRoute.value.fullPath}`;
65
60
  await navigateTo(useDirectusUrl(`/auth/login/${provider}?redirect=${encodeURIComponent(redirect)}`), { external: true });
66
61
  }
@@ -87,10 +82,6 @@ export function useDirectusAuth() {
87
82
  await directus.logout();
88
83
  } finally {
89
84
  user.value = null;
90
- tokens.refreshToken.value = null;
91
- tokens.accessToken.value = null;
92
- tokens.expires.value = null;
93
- tokens.expiresAt.value = null;
94
85
  }
95
86
  if (redirect) {
96
87
  const defaultRedirect = config.public.directus.auth?.redirect?.logout ?? config.public.directus.auth?.redirect?.home ?? "/";
@@ -1,4 +1,4 @@
1
1
  import type { Ref } from '#imports';
2
2
  export declare function useDirectusPreview(): Ref<boolean>;
3
3
  export declare function useDirectusUrl(path?: string): string;
4
- export declare function useDirectus(token?: string): import("@directus/sdk").DirectusClient<DirectusSchema> & import("@directus/sdk").AuthenticationClient<DirectusSchema> & import("@directus/sdk").RestClient<DirectusSchema> & import("@directus/sdk").WebSocketClient<DirectusSchema>;
4
+ export declare function useDirectus(): import("@directus/sdk").DirectusClient<DirectusSchema> & import("@directus/sdk").AuthenticationClient<DirectusSchema> & import("@directus/sdk").RestClient<DirectusSchema> & import("@directus/sdk").WebSocketClient<DirectusSchema>;