@yassidev/nuxt-directus 0.0.10 → 0.0.12

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/README.fr.md ADDED
@@ -0,0 +1,501 @@
1
+ # @yassidev/nuxt-directus
2
+
3
+ [![npm version][npm-version-src]][npm-version-href]
4
+ [![npm downloads][npm-downloads-src]][npm-downloads-href]
5
+ [![License][license-src]][license-href]
6
+ [![Nuxt][nuxt-src]][nuxt-href]
7
+
8
+ Un module Nuxt pour une meilleure intégration avec Directus CMS, offrant une gestion avancée de l'i18n, des composables TypeScript, des types générés automatiquement et bien plus encore.
9
+
10
+ - [✨  Release Notes](/CHANGELOG.md)
11
+
12
+ ## ✨ Fonctionnalités
13
+
14
+ - 🔧 **Composables pré-configurés** : Accès facile à l'API Directus (REST/GraphQL)
15
+ - 🌍 **Intégration i18n** : Synchronisation bidirectionnelle avec @nuxtjs/i18n
16
+ - 📝 **Types TypeScript** : Génération automatique des types Directus
17
+ - 🖼️ **Intégration @nuxt/image** : Support optimisé pour les assets Directus
18
+ - 🔄 **Proxy transparent** : Contournement des problèmes CORS
19
+ - ⚡ **Configuration simplifiée** : Variables d'environnement et configuration par défaut
20
+ - 🔥 **Mode développement avancé** : Synchronisation en temps réel des traductions
21
+
22
+ ## 📦 Installation
23
+
24
+ ```bash
25
+ # npm
26
+ npm install @yassidev/nuxt-directus
27
+
28
+ # yarn
29
+ yarn add @yassidev/nuxt-directus
30
+
31
+ # pnpm
32
+ pnpm install @yassidev/nuxt-directus
33
+ ```
34
+
35
+ ## ⚙️ Configuration
36
+
37
+ ### Configuration de base
38
+
39
+ Ajoutez le module à votre configuration Nuxt :
40
+
41
+ ```typescript
42
+ // nuxt.config.ts
43
+ export default defineNuxtConfig({
44
+ modules: ['@yassidev/nuxt-directus'],
45
+
46
+ // Configuration optionnelle
47
+ directus: {
48
+ url: 'https://votre-instance.directus.app',
49
+ accessToken: 'votre-token-dacces',
50
+ },
51
+ })
52
+ ```
53
+
54
+ ### Variables d'environnement
55
+
56
+ Vous pouvez également utiliser les variables d'environnement :
57
+
58
+ ```bash
59
+ # .env
60
+ DIRECTUS_URL=https://votre-instance.directus.app
61
+ DIRECTUS_ACCESS_TOKEN=votre-token-dacces
62
+ ```
63
+
64
+ ### Configuration complète
65
+
66
+ ```typescript
67
+ // nuxt.config.ts
68
+ export default defineNuxtConfig({
69
+ modules: ['@yassidev/nuxt-directus'],
70
+
71
+ directus: {
72
+ // URL de votre instance Directus
73
+ url: 'https://votre-instance.directus.app',
74
+
75
+ // Token d'accès Directus
76
+ accessToken: 'votre-token-dacces',
77
+
78
+ // Configuration des composables
79
+ composables: {
80
+ enabled: true, // Active les composables
81
+ mode: 'rest', // 'rest' ou 'graphql'
82
+ client: true, // Disponible côté client
83
+ server: true, // Disponible côté serveur
84
+ },
85
+
86
+ // Configuration i18n
87
+ i18n: {
88
+ enabled: true, // Active l'intégration i18n
89
+ sync: true, // Synchronisation bidirectionnelle
90
+ prefix: 'app.', // Préfixe pour les clés de traduction
91
+ },
92
+
93
+ // Génération des types TypeScript
94
+ types: {
95
+ enabled: true, // Génère les types automatiquement
96
+ },
97
+
98
+ // Configuration du proxy
99
+ proxy: {
100
+ enabled: true, // Active le proxy
101
+ path: '/api', // Chemin du proxy
102
+ options: {}, // Options h3 ProxyOptions
103
+ },
104
+
105
+ // Intégration avec @nuxt/image
106
+ image: {
107
+ enabled: true, // Active l'intégration image
108
+ alias: 'directus', // Alias pour les images
109
+ },
110
+ },
111
+ })
112
+ ```
113
+
114
+ ## 🚀 Utilisation
115
+
116
+ ### Composables Directus
117
+
118
+ Le module fournit un composable `useDirectus()` configuré automatiquement :
119
+
120
+ ```vue
121
+ <script setup>
122
+ // Mode REST (par défaut)
123
+ const directus = useDirectus()
124
+
125
+ // Récupérer des données
126
+ const { data: articles } = await directus.request(readItems('articles'))
127
+
128
+ // Créer un nouvel élément
129
+ await directus.request(createItem('articles', {
130
+ title: 'Mon article',
131
+ content: 'Contenu de l\'article'
132
+ }))
133
+ </script>
134
+ ```
135
+
136
+ #### Mode GraphQL
137
+
138
+ ```typescript
139
+ // nuxt.config.ts
140
+ export default defineNuxtConfig({
141
+ directus: {
142
+ composables: {
143
+ mode: 'graphql'
144
+ }
145
+ }
146
+ })
147
+ ```
148
+
149
+ ```vue
150
+ <script setup>
151
+ const directus = useDirectus()
152
+
153
+ // Requête GraphQL
154
+ const result = await directus.query(`
155
+ query {
156
+ articles {
157
+ id
158
+ title
159
+ content
160
+ }
161
+ }
162
+ `)
163
+ </script>
164
+ ```
165
+
166
+ ### Types TypeScript
167
+
168
+ Le module génère automatiquement les types TypeScript de votre schéma Directus :
169
+
170
+ ```typescript
171
+ // Toutes les collections sont disponibles dans #directus/types
172
+ import type { Schema } from '#directus/types'
173
+
174
+ // Utilisation dans votre code - les types sont automatiquement détectés
175
+ const directus = useDirectus()
176
+ const articles = await directus.request(readItems('articles')) // Le type est automatiquement inféré
177
+ ```
178
+
179
+ ### Intégration i18n
180
+
181
+ #### Configuration préalable
182
+
183
+ Installez et configurez `@nuxtjs/i18n` :
184
+
185
+ ```bash
186
+ npm install @nuxtjs/i18n
187
+ ```
188
+
189
+ ```typescript
190
+ // nuxt.config.ts
191
+ export default defineNuxtConfig({
192
+ modules: ['@nuxtjs/i18n', '@yassidev/nuxt-directus'],
193
+
194
+ i18n: {
195
+ locales: [
196
+ { code: 'fr', name: 'Français' },
197
+ { code: 'en', name: 'English' }
198
+ ],
199
+ defaultLocale: 'fr'
200
+ }
201
+ })
202
+ ```
203
+
204
+ #### Synchronisation automatique
205
+
206
+ Les traductions sont automatiquement synchronisées entre Directus et votre application Nuxt :
207
+
208
+ ```vue
209
+ <template>
210
+ <div>
211
+ <!-- Les traductions sont chargées depuis Directus -->
212
+ <h1>{{ $t('welcome.title') }}</h1>
213
+ <p>{{ $t('welcome.description') }}</p>
214
+ </div>
215
+ </template>
216
+ ```
217
+
218
+ #### Gestion des traductions avec préfixe
219
+
220
+ ```typescript
221
+ // nuxt.config.ts
222
+ export default defineNuxtConfig({
223
+ directus: {
224
+ i18n: {
225
+ prefix: 'frontend.' // Seules les clés commençant par 'frontend.' seront synchronisées
226
+ }
227
+ }
228
+ })
229
+ ```
230
+
231
+ #### Synchronisation en temps réel (développement)
232
+
233
+ En mode développement, les modifications des fichiers de traduction sont automatiquement synchronisées avec Directus :
234
+
235
+ 1. Modifiez un fichier de traduction local
236
+ 2. Les changements sont automatiquement envoyés à Directus
237
+ 3. Les autres développeurs voient les mises à jour en temps réel
238
+
239
+ ### Intégration avec @nuxt/image
240
+
241
+ Le module configure automatiquement `@nuxt/image` avec un alias pour les assets Directus :
242
+
243
+ ```vue
244
+ <template>
245
+ <div>
246
+ <!-- Utilisation directe avec l'alias configuré -->
247
+ <NuxtImg
248
+ src="directus/votre-asset-id"
249
+ width="400"
250
+ height="300"
251
+ />
252
+
253
+ <!-- Avec transformations Directus -->
254
+ <NuxtImg
255
+ src="directus/votre-asset-id?fit=cover&width=800&height=600"
256
+ width="400"
257
+ height="300"
258
+ />
259
+ </div>
260
+ </template>
261
+ ```
262
+
263
+ ### Proxy API
264
+
265
+ Le proxy permet d'éviter les problèmes CORS en développement :
266
+
267
+ ```typescript
268
+ // Au lieu de https://votre-directus.com/items/articles
269
+ // Utilisez /api/items/articles
270
+
271
+ const { data } = await $fetch('/api/items/articles')
272
+ ```
273
+
274
+ ## 🛠️ Développement
275
+
276
+ ### Configuration du projet de développement
277
+
278
+ ```bash
279
+ # Cloner le repository
280
+ git clone https://github.com/yassilah/nuxt-directus.git
281
+
282
+ # Installer les dépendances
283
+ pnpm install
284
+
285
+ # Configurer l'environnement
286
+ cp .env.example .env
287
+ # Éditer .env avec vos paramètres Directus
288
+
289
+ # Lancer le playground
290
+ pnpm dev
291
+ ```
292
+
293
+ ### Scripts disponibles
294
+
295
+ ```bash
296
+ # Développement
297
+ pnpm dev
298
+
299
+ # Build
300
+ pnpm build
301
+
302
+ # Tests
303
+ pnpm test
304
+ pnpm test:watch
305
+
306
+ # Linting
307
+ pnpm lint
308
+
309
+ # Release
310
+ pnpm release
311
+ ```
312
+
313
+ ## 📚 Exemples avancés
314
+
315
+ ### Récupération de données avec relations
316
+
317
+ ```vue
318
+ <script setup>
319
+ const directus = useDirectus()
320
+
321
+ const { data: articles } = await directus.request(readItems('articles', {
322
+ fields: [
323
+ 'id',
324
+ 'title',
325
+ 'content',
326
+ 'author.first_name',
327
+ 'author.last_name',
328
+ 'category.name'
329
+ ],
330
+ filter: {
331
+ status: { _eq: 'published' }
332
+ },
333
+ sort: ['-date_created'],
334
+ limit: 10
335
+ }))
336
+ </script>
337
+ ```
338
+
339
+ ### Upload de fichiers
340
+
341
+ ```vue
342
+ <script setup>
343
+ const directus = useDirectus()
344
+
345
+ async function uploadFile(file: File) {
346
+ const formData = new FormData()
347
+ formData.append('file', file)
348
+
349
+ const result = await directus.request(uploadFiles(formData))
350
+ return result
351
+ }
352
+ </script>
353
+ ```
354
+
355
+ ### Authentification utilisateur
356
+
357
+ ```vue
358
+ <script setup>
359
+ const directus = useDirectus()
360
+
361
+ async function login(email: string, password: string) {
362
+ try {
363
+ const result = await directus.request(login(email, password))
364
+ // Gérer la connexion réussie
365
+ return result
366
+ } catch (error) {
367
+ // Gérer l'erreur de connexion
368
+ console.error('Erreur de connexion:', error)
369
+ }
370
+ }
371
+ </script>
372
+ ```
373
+
374
+ ## 🔧 Configuration avancée
375
+
376
+ ### Désactiver des fonctionnalités
377
+
378
+ ```typescript
379
+ // nuxt.config.ts
380
+ export default defineNuxtConfig({
381
+ directus: {
382
+ // Désactiver l'i18n
383
+ i18n: false,
384
+
385
+ // Désactiver les types
386
+ types: false,
387
+
388
+ // Désactiver le proxy
389
+ proxy: false,
390
+
391
+ // Désactiver les composables
392
+ composables: false,
393
+
394
+ // Désactiver l'intégration image
395
+ image: false,
396
+ }
397
+ })
398
+ ```
399
+
400
+ ### Configuration personnalisée du proxy
401
+
402
+ ```typescript
403
+ // nuxt.config.ts
404
+ export default defineNuxtConfig({
405
+ directus: {
406
+ proxy: {
407
+ enabled: true,
408
+ path: '/directus-api',
409
+ options: {
410
+ headers: {
411
+ 'Custom-Header': 'valeur'
412
+ },
413
+ timeout: 30000
414
+ }
415
+ }
416
+ }
417
+ })
418
+ ```
419
+
420
+ ## ⚠️ Prérequis
421
+
422
+ - Nuxt 3.x
423
+ - Node.js 18+
424
+ - Une instance Directus 10+
425
+
426
+ ### Modules optionnels
427
+
428
+ - `@nuxtjs/i18n` : Pour les fonctionnalités d'internationalisation
429
+ - `@nuxt/image` : Pour l'optimisation des images
430
+
431
+ ## 🤝 Contribution
432
+
433
+ <details>
434
+ <summary>Développement local</summary>
435
+
436
+ ```bash
437
+ # Installer les dépendances
438
+ pnpm install
439
+
440
+ # Générer les type stubs
441
+ pnpm dev:prepare
442
+
443
+ # Développer avec le playground
444
+ pnpm dev
445
+
446
+ # Build le playground
447
+ pnpm dev:build
448
+
449
+ # Lancer ESLint
450
+ pnpm lint
451
+
452
+ # Lancer Vitest
453
+ pnpm test
454
+ pnpm test:watch
455
+
456
+ # Release une nouvelle version
457
+ pnpm release
458
+ ```
459
+
460
+ </details>
461
+
462
+ ### Étapes pour contribuer
463
+
464
+ 1. Forkez le projet
465
+ 2. Créez votre branche de fonctionnalité (`git checkout -b feature/AmazingFeature`)
466
+ 3. Commitez vos changements (`git commit -m 'Add some AmazingFeature'`)
467
+ 4. Poussez vers la branche (`git push origin feature/AmazingFeature`)
468
+ 5. Ouvrez une Pull Request
469
+
470
+ ## 📄 Licence
471
+
472
+ Ce projet est sous licence [MIT](LICENSE).
473
+
474
+ ## 🙏 Remerciements
475
+
476
+ - L'équipe [Directus](https://directus.io) pour leur fantastique CMS headless
477
+ - L'équipe [Nuxt](https://nuxt.com) pour le framework
478
+ - La communauté open source pour les retours et contributions
479
+
480
+ ## 📞 Support
481
+
482
+ - 🐛 [Signaler un bug](https://github.com/yassilah/nuxt-directus/issues)
483
+ - 💡 [Demander une fonctionnalité](https://github.com/yassilah/nuxt-directus/issues)
484
+ - 💬 [Discussions](https://github.com/yassilah/nuxt-directus/discussions)
485
+
486
+ ---
487
+
488
+ Fait avec ❤️ par [Yasser Lahbibi](https://github.com/yassilah)
489
+
490
+ <!-- Badges -->
491
+ [npm-version-src]: https://img.shields.io/npm/v/@yassidev/nuxt-directus/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
492
+ [npm-version-href]: https://npmjs.com/package/@yassidev/nuxt-directus
493
+
494
+ [npm-downloads-src]: https://img.shields.io/npm/dm/@yassidev/nuxt-directus.svg?style=flat&colorA=18181B&colorB=28CF8D
495
+ [npm-downloads-href]: https://npmjs.com/package/@yassidev/nuxt-directus
496
+
497
+ [license-src]: https://img.shields.io/npm/l/@yassidev/nuxt-directus.svg?style=flat&colorA=18181B&colorB=28CF8D
498
+ [license-href]: https://npmjs.com/package/@yassidev/nuxt-directus
499
+
500
+ [nuxt-src]: https://img.shields.io/badge/Nuxt-18181B?logo=nuxt.js
501
+ [nuxt-href]: https://nuxt.com
package/README.md CHANGED
@@ -1,84 +1,501 @@
1
- <!--
2
- Get your module up and running quickly.
3
-
4
- Find and replace all on all files (CMD+SHIFT+F):
5
- - Name: My Module
6
- - Package name: my-module
7
- - Description: My new Nuxt module
8
- -->
9
-
10
- # My Module
1
+ # @yassidev/nuxt-directus
11
2
 
12
3
  [![npm version][npm-version-src]][npm-version-href]
13
4
  [![npm downloads][npm-downloads-src]][npm-downloads-href]
14
5
  [![License][license-src]][license-href]
15
6
  [![Nuxt][nuxt-src]][nuxt-href]
16
7
 
17
- My new Nuxt module for doing amazing things.
8
+ A Nuxt module for better integration with Directus CMS, featuring advanced i18n management, TypeScript composables, auto-generated types, and much more.
18
9
 
19
10
  - [✨ &nbsp;Release Notes](/CHANGELOG.md)
20
- <!-- - [🏀 Online playground](https://stackblitz.com/github/your-org/my-module?file=playground%2Fapp.vue) -->
21
- <!-- - [📖 &nbsp;Documentation](https://example.com) -->
22
11
 
23
- ## Features
12
+ ## Features
13
+
14
+ - 🔧 **Pre-configured Composables**: Easy access to Directus API (REST/GraphQL)
15
+ - 🌍 **i18n Integration**: Bidirectional synchronization with @nuxtjs/i18n
16
+ - 📝 **TypeScript Types**: Automatic generation of Directus types
17
+ - 🖼️ **@nuxt/image Integration**: Optimized support for Directus assets
18
+ - 🔄 **Transparent Proxy**: CORS issues bypass
19
+ - ⚡ **Simplified Configuration**: Environment variables and default configuration
20
+ - 🔥 **Advanced Development Mode**: Real-time translation synchronization
21
+
22
+ ## 📦 Installation
23
+
24
+ ```bash
25
+ # npm
26
+ npm install @yassidev/nuxt-directus
27
+
28
+ # yarn
29
+ yarn add @yassidev/nuxt-directus
30
+
31
+ # pnpm
32
+ pnpm install @yassidev/nuxt-directus
33
+ ```
34
+
35
+ ## ⚙️ Configuration
36
+
37
+ ### Basic Configuration
38
+
39
+ Add the module to your Nuxt configuration:
40
+
41
+ ```typescript
42
+ // nuxt.config.ts
43
+ export default defineNuxtConfig({
44
+ modules: ['@yassidev/nuxt-directus'],
45
+
46
+ // Optional configuration
47
+ directus: {
48
+ url: 'https://your-instance.directus.app',
49
+ accessToken: 'your-access-token',
50
+ },
51
+ })
52
+ ```
53
+
54
+ ### Environment Variables
55
+
56
+ You can also use environment variables:
57
+
58
+ ```bash
59
+ # .env
60
+ DIRECTUS_URL=https://your-instance.directus.app
61
+ DIRECTUS_ACCESS_TOKEN=your-access-token
62
+ ```
63
+
64
+ ### Complete Configuration
65
+
66
+ ```typescript
67
+ // nuxt.config.ts
68
+ export default defineNuxtConfig({
69
+ modules: ['@yassidev/nuxt-directus'],
70
+
71
+ directus: {
72
+ // URL of your Directus instance
73
+ url: 'https://your-instance.directus.app',
74
+
75
+ // Directus access token
76
+ accessToken: 'your-access-token',
77
+
78
+ // Composables configuration
79
+ composables: {
80
+ enabled: true, // Enable composables
81
+ mode: 'rest', // 'rest' or 'graphql'
82
+ client: true, // Available on client-side
83
+ server: true, // Available on server-side
84
+ },
85
+
86
+ // i18n configuration
87
+ i18n: {
88
+ enabled: true, // Enable i18n integration
89
+ sync: true, // Bidirectional synchronization
90
+ prefix: 'app.', // Prefix for translation keys
91
+ },
92
+
93
+ // TypeScript types generation
94
+ types: {
95
+ enabled: true, // Generate types automatically
96
+ },
97
+
98
+ // Proxy configuration
99
+ proxy: {
100
+ enabled: true, // Enable proxy
101
+ path: '/api', // Proxy path
102
+ options: {}, // h3 ProxyOptions
103
+ },
104
+
105
+ // @nuxt/image integration
106
+ image: {
107
+ enabled: true, // Enable image integration
108
+ alias: 'directus', // Alias for images
109
+ },
110
+ },
111
+ })
112
+ ```
113
+
114
+ ## 🚀 Usage
115
+
116
+ ### Directus Composables
117
+
118
+ The module provides a pre-configured `useDirectus()` composable:
119
+
120
+ ```vue
121
+ <script setup>
122
+ // REST mode (default)
123
+ const directus = useDirectus()
124
+
125
+ // Fetch data
126
+ const { data: articles } = await directus.request(readItems('articles'))
127
+
128
+ // Create a new item
129
+ await directus.request(createItem('articles', {
130
+ title: 'My article',
131
+ content: 'Article content'
132
+ }))
133
+ </script>
134
+ ```
135
+
136
+ #### GraphQL Mode
137
+
138
+ ```typescript
139
+ // nuxt.config.ts
140
+ export default defineNuxtConfig({
141
+ directus: {
142
+ composables: {
143
+ mode: 'graphql'
144
+ }
145
+ }
146
+ })
147
+ ```
148
+
149
+ ```vue
150
+ <script setup>
151
+ const directus = useDirectus()
152
+
153
+ // GraphQL query
154
+ const result = await directus.query(`
155
+ query {
156
+ articles {
157
+ id
158
+ title
159
+ content
160
+ }
161
+ }
162
+ `)
163
+ </script>
164
+ ```
165
+
166
+ ### TypeScript Types
167
+
168
+ The module automatically generates TypeScript types from your Directus schema:
169
+
170
+ ```typescript
171
+ // All collections are available in #directus/types
172
+ import type { Schema } from '#directus/types'
173
+
174
+ // Usage in your code - types are automatically inferred
175
+ const directus = useDirectus()
176
+ const articles = await directus.request(readItems('articles')) // Type is automatically inferred
177
+ ```
178
+
179
+ ### i18n Integration
180
+
181
+ #### Prerequisites
182
+
183
+ Install and configure `@nuxtjs/i18n`:
184
+
185
+ ```bash
186
+ npm install @nuxtjs/i18n
187
+ ```
188
+
189
+ ```typescript
190
+ // nuxt.config.ts
191
+ export default defineNuxtConfig({
192
+ modules: ['@nuxtjs/i18n', '@yassidev/nuxt-directus'],
193
+
194
+ i18n: {
195
+ locales: [
196
+ { code: 'fr', name: 'Français' },
197
+ { code: 'en', name: 'English' }
198
+ ],
199
+ defaultLocale: 'en'
200
+ }
201
+ })
202
+ ```
203
+
204
+ #### Automatic Synchronization
205
+
206
+ Translations are automatically synchronized between Directus and your Nuxt application:
207
+
208
+ ```vue
209
+ <template>
210
+ <div>
211
+ <!-- Translations are loaded from Directus -->
212
+ <h1>{{ $t('welcome.title') }}</h1>
213
+ <p>{{ $t('welcome.description') }}</p>
214
+ </div>
215
+ </template>
216
+ ```
217
+
218
+ #### Translation Management with Prefix
24
219
 
25
- <!-- Highlight some of the features your module provide here -->
26
- - ⛰ &nbsp;Foo
27
- - 🚠 &nbsp;Bar
28
- - 🌲 &nbsp;Baz
220
+ ```typescript
221
+ // nuxt.config.ts
222
+ export default defineNuxtConfig({
223
+ directus: {
224
+ i18n: {
225
+ prefix: 'frontend.' // Only keys starting with 'frontend.' will be synchronized
226
+ }
227
+ }
228
+ })
229
+ ```
230
+
231
+ #### Real-time Synchronization (Development)
232
+
233
+ In development mode, local translation file changes are automatically synchronized with Directus:
234
+
235
+ 1. Modify a local translation file
236
+ 2. Changes are automatically sent to Directus
237
+ 3. Other developers see updates in real-time
238
+
239
+ ### @nuxt/image Integration
240
+
241
+ The module automatically configures `@nuxt/image` with an alias for Directus assets. Please make sure to place `@yassidev/nuxt-directus` **before** `@nuxt/image` in your modules array.
242
+
243
+ ```vue
244
+ <template>
245
+ <div>
246
+ <!-- Direct usage with the configured alias -->
247
+ <NuxtImg
248
+ src="directus/your-asset-id"
249
+ width="400"
250
+ height="300"
251
+ />
252
+
253
+ <!-- With Directus transformations -->
254
+ <NuxtImg
255
+ src="directus/your-asset-id?fit=cover&width=800&height=600"
256
+ width="400"
257
+ height="300"
258
+ />
259
+ </div>
260
+ </template>
261
+ ```
262
+
263
+ ### API Proxy
264
+
265
+ The proxy allows bypassing CORS issues in development:
266
+
267
+ ```typescript
268
+ // Instead of https://your-directus.com/items/articles
269
+ // Use /api/items/articles
270
+
271
+ const { data } = await $fetch('/api/items/articles')
272
+ ```
273
+
274
+ ## 🛠️ Development
29
275
 
30
- ## Quick Setup
276
+ ### Development Project Setup
31
277
 
32
- Install the module to your Nuxt application with one command:
278
+ ```bash
279
+ # Clone the repository
280
+ git clone https://github.com/yassilah/nuxt-directus.git
281
+
282
+ # Install dependencies
283
+ pnpm install
284
+
285
+ # Configure environment
286
+ cp .env.example .env
287
+ # Edit .env with your Directus settings
288
+
289
+ # Start the playground
290
+ pnpm dev
291
+ ```
292
+
293
+ ### Available Scripts
33
294
 
34
295
  ```bash
35
- npx nuxi module add my-module
296
+ # Development
297
+ pnpm dev
298
+
299
+ # Build
300
+ pnpm build
301
+
302
+ # Tests
303
+ pnpm test
304
+ pnpm test:watch
305
+
306
+ # Linting
307
+ pnpm lint
308
+
309
+ # Release
310
+ pnpm release
311
+ ```
312
+
313
+ ## 📚 Advanced Examples
314
+
315
+ ### Data Fetching with Relations
316
+
317
+ ```vue
318
+ <script setup>
319
+ const directus = useDirectus()
320
+
321
+ const { data: articles } = await directus.request(readItems('articles', {
322
+ fields: [
323
+ 'id',
324
+ 'title',
325
+ 'content',
326
+ 'author.first_name',
327
+ 'author.last_name',
328
+ 'category.name'
329
+ ],
330
+ filter: {
331
+ status: { _eq: 'published' }
332
+ },
333
+ sort: ['-date_created'],
334
+ limit: 10
335
+ }))
336
+ </script>
337
+ ```
338
+
339
+ ### File Upload
340
+
341
+ ```vue
342
+ <script setup>
343
+ const directus = useDirectus()
344
+
345
+ async function uploadFile(file: File) {
346
+ const formData = new FormData()
347
+ formData.append('file', file)
348
+
349
+ const result = await directus.request(uploadFiles(formData))
350
+ return result
351
+ }
352
+ </script>
353
+ ```
354
+
355
+ ### User Authentication
356
+
357
+ ```vue
358
+ <script setup>
359
+ const directus = useDirectus()
360
+
361
+ async function login(email: string, password: string) {
362
+ try {
363
+ const result = await directus.request(login(email, password))
364
+ // Handle successful login
365
+ return result
366
+ } catch (error) {
367
+ // Handle login error
368
+ console.error('Login error:', error)
369
+ }
370
+ }
371
+ </script>
372
+ ```
373
+
374
+ ## 🔧 Advanced Configuration
375
+
376
+ ### Disabling Features
377
+
378
+ ```typescript
379
+ // nuxt.config.ts
380
+ export default defineNuxtConfig({
381
+ directus: {
382
+ // Disable i18n
383
+ i18n: false,
384
+
385
+ // Disable types
386
+ types: false,
387
+
388
+ // Disable proxy
389
+ proxy: false,
390
+
391
+ // Disable composables
392
+ composables: false,
393
+
394
+ // Disable image integration
395
+ image: false,
396
+ }
397
+ })
36
398
  ```
37
399
 
38
- That's it! You can now use My Module in your Nuxt app ✨
400
+ ### Custom Proxy Configuration
39
401
 
402
+ ```typescript
403
+ // nuxt.config.ts
404
+ export default defineNuxtConfig({
405
+ directus: {
406
+ proxy: {
407
+ enabled: true,
408
+ path: '/directus-api',
409
+ options: {
410
+ headers: {
411
+ 'Custom-Header': 'value'
412
+ },
413
+ timeout: 30000
414
+ }
415
+ }
416
+ }
417
+ })
418
+ ```
419
+
420
+ ## ⚠️ Requirements
421
+
422
+ - Nuxt 3.x
423
+ - Node.js 18+
424
+ - Directus 10+ instance
425
+
426
+ ### Optional Modules
40
427
 
41
- ## Contribution
428
+ - `@nuxtjs/i18n`: For internationalization features
429
+ - `@nuxt/image`: For image optimization
430
+
431
+ ## 🤝 Contributing
42
432
 
43
433
  <details>
44
434
  <summary>Local development</summary>
45
435
 
46
436
  ```bash
47
437
  # Install dependencies
48
- npm install
438
+ pnpm install
49
439
 
50
440
  # Generate type stubs
51
- npm run dev:prepare
441
+ pnpm dev:prepare
52
442
 
53
443
  # Develop with the playground
54
- npm run dev
444
+ pnpm dev
55
445
 
56
446
  # Build the playground
57
- npm run dev:build
447
+ pnpm dev:build
58
448
 
59
449
  # Run ESLint
60
- npm run lint
450
+ pnpm lint
61
451
 
62
452
  # Run Vitest
63
- npm run test
64
- npm run test:watch
453
+ pnpm test
454
+ pnpm test:watch
65
455
 
66
456
  # Release new version
67
- npm run release
457
+ pnpm release
68
458
  ```
69
459
 
70
460
  </details>
71
461
 
462
+ ### Steps to Contribute
463
+
464
+ 1. Fork the project
465
+ 2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
466
+ 3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
467
+ 4. Push to the branch (`git push origin feature/AmazingFeature`)
468
+ 5. Open a Pull Request
469
+
470
+ ## 📄 License
471
+
472
+ This project is licensed under the [MIT](LICENSE) License.
473
+
474
+ ## 🙏 Acknowledgments
475
+
476
+ - The [Directus](https://directus.io) team for their fantastic headless CMS
477
+ - The [Nuxt](https://nuxt.com) team for the framework
478
+ - The open source community for feedback and contributions
479
+
480
+ ## 📞 Support
481
+
482
+ - 🐛 [Report a bug](https://github.com/yassilah/nuxt-directus/issues)
483
+ - 💡 [Request a feature](https://github.com/yassilah/nuxt-directus/issues)
484
+ - 💬 [Discussions](https://github.com/yassilah/nuxt-directus/discussions)
485
+
486
+ ---
487
+
488
+ Made with ❤️ by [Yasser Lahbibi](https://github.com/yassilah)
72
489
 
73
490
  <!-- Badges -->
74
- [npm-version-src]: https://img.shields.io/npm/v/my-module/latest.svg?style=flat&colorA=020420&colorB=00DC82
75
- [npm-version-href]: https://npmjs.com/package/my-module
491
+ [npm-version-src]: https://img.shields.io/npm/v/@yassidev/nuxt-directus/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
492
+ [npm-version-href]: https://npmjs.com/package/@yassidev/nuxt-directus
76
493
 
77
- [npm-downloads-src]: https://img.shields.io/npm/dm/my-module.svg?style=flat&colorA=020420&colorB=00DC82
78
- [npm-downloads-href]: https://npm.chart.dev/my-module
494
+ [npm-downloads-src]: https://img.shields.io/npm/dm/@yassidev/nuxt-directus.svg?style=flat&colorA=18181B&colorB=28CF8D
495
+ [npm-downloads-href]: https://npmjs.com/package/@yassidev/nuxt-directus
79
496
 
80
- [license-src]: https://img.shields.io/npm/l/my-module.svg?style=flat&colorA=020420&colorB=00DC82
81
- [license-href]: https://npmjs.com/package/my-module
497
+ [license-src]: https://img.shields.io/npm/l/@yassidev/nuxt-directus.svg?style=flat&colorA=18181B&colorB=28CF8D
498
+ [license-href]: https://npmjs.com/package/@yassidev/nuxt-directus
82
499
 
83
- [nuxt-src]: https://img.shields.io/badge/Nuxt-020420?logo=nuxt.js
84
- [nuxt-href]: https://nuxt.com
500
+ [nuxt-src]: https://img.shields.io/badge/Nuxt-18181B?logo=nuxt.js
501
+ [nuxt-href]: https://nuxt.com
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "directus",
3
3
  "configKey": "directus",
4
- "version": "0.0.10",
4
+ "version": "0.0.12",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -1,7 +1,7 @@
1
- import { defineNuxtModule, useLogger, updateRuntimeConfig, hasNuxtModule, createResolver, addImports, addServerImports, addTemplate, addTypeTemplate } from 'nuxt/kit';
1
+ import { defineNuxtModule, useLogger, updateRuntimeConfig, hasNuxtModule, createResolver, addImportsDir, addImports, addServerImportsDir, addServerImports, addTemplate, addTypeTemplate } from 'nuxt/kit';
2
2
  import { generateDirectusTypes } from 'directus-sdk-typegen';
3
3
  import { fetchTranslations, syncTranslations } from '../dist/runtime/server.js';
4
- import { readFileSync } from 'node:fs';
4
+ import { readFileSync, existsSync } from 'node:fs';
5
5
  import { NAME } from '../dist/runtime/constants.js';
6
6
  import { resolve, join, relative, sep } from 'node:path';
7
7
  import { unwatchFile, watchFile, watch as watch$1, stat as stat$2 } from 'fs';
@@ -1820,21 +1820,20 @@ function normalizeConfig(options) {
1820
1820
  }
1821
1821
  function setupComposables(config, nuxt, logger) {
1822
1822
  const { resolve } = createResolver(import.meta.url);
1823
- const path = resolve(`./runtime/composables/${config.composables.mode}`);
1824
- nuxt.options.alias = defu(nuxt.options.alias, {
1825
- "#directus": path
1826
- });
1823
+ const path = resolve(`./runtime/composables`);
1824
+ const name = config.composables.mode === "graphql" ? "useDirectusGraphql" : "useDirectusRest";
1825
+ const mainImport = {
1826
+ name,
1827
+ as: "useDirectus",
1828
+ from: join(path, "useDirectus")
1829
+ };
1827
1830
  if (config.composables.client) {
1828
- addImports({
1829
- from: path,
1830
- name: "useDirectus"
1831
- });
1831
+ addImportsDir(path);
1832
+ addImports(mainImport);
1832
1833
  }
1833
1834
  if (config.composables.server) {
1834
- addServerImports({
1835
- from: path,
1836
- name: "useDirectus"
1837
- });
1835
+ addServerImportsDir(path);
1836
+ addServerImports(mainImport);
1838
1837
  }
1839
1838
  logger.info(`Composables have been registered (mode: ${config.composables.mode}).`);
1840
1839
  }
@@ -1850,21 +1849,21 @@ function setupI18n(config, nuxt, logger) {
1850
1849
  };
1851
1850
  const path = "directus/locales";
1852
1851
  const result = codes.map((code) => {
1853
- const { dst } = addTemplate({
1852
+ const { filename } = addTemplate({
1854
1853
  write: true,
1855
1854
  filename: join(path, `${code}.json`),
1856
1855
  getContents: () => fetchTranslations(code, runtimeConfig).then((translations) => {
1857
1856
  return JSON.stringify(Object.fromEntries(translations.map((translation) => [translation.key, translation.value])), null, 2);
1858
1857
  })
1859
1858
  });
1860
- return { code, dst };
1859
+ return { code, filename };
1861
1860
  });
1862
1861
  if (nuxt.options.dev && !nuxt.options._prepare) {
1863
- const watcher = chokidar.watch(resolve(nuxt.options.buildDir, path, "*.json"), { ignoreInitial: true });
1862
+ const watcher = chokidar.watch(path, { cwd: nuxt.options.buildDir, ignoreInitial: true });
1864
1863
  watcher.on("change", async (filePath) => {
1865
- const code = result.find((i) => i.dst === filePath)?.code;
1864
+ const code = result.find((i) => i.filename === filePath)?.code;
1866
1865
  if (!code) return;
1867
- const translations = JSON.parse(readFileSync(filePath, "utf-8"));
1866
+ const translations = JSON.parse(readFileSync(resolve(nuxt.options.buildDir, filePath), "utf-8"));
1868
1867
  const done = await syncTranslations(code, translations, runtimeConfig);
1869
1868
  if (!done) return;
1870
1869
  logger.info(`Synced translations for locale: ${code}`);
@@ -1872,11 +1871,12 @@ function setupI18n(config, nuxt, logger) {
1872
1871
  }
1873
1872
  }
1874
1873
  nuxt.hook("i18n:registerModule", (register) => {
1874
+ const isStubbing = existsSync(resolve("./runtime/lang/index.ts"));
1875
1875
  const locales = codes.map((code) => ({
1876
1876
  code,
1877
- file: resolve("./runtime/lang/index")
1877
+ file: isStubbing ? "index.ts" : "index.js"
1878
1878
  }));
1879
- register({ langDir: "", locales });
1879
+ register({ langDir: resolve("./runtime/lang"), locales });
1880
1880
  logger.success("Locales have been registered: " + codes.join(", "));
1881
1881
  });
1882
1882
  }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Use directus (rest)
3
+ */
4
+ export declare function useDirectusRest(): import("@directus/sdk").DirectusClient<Schema> & import("@directus/sdk").RestClient<Schema>;
5
+ /**
6
+ * Use directus (rest)
7
+ */
8
+ export declare function useDirectusGraphql(): import("@directus/sdk").DirectusClient<Schema> & import("@directus/sdk").GraphqlClient<Schema>;
@@ -0,0 +1,8 @@
1
+ import { rest, graphql } from "@directus/sdk";
2
+ import { createBaseDirectus } from "./../client.js";
3
+ export function useDirectusRest() {
4
+ return createBaseDirectus().with(rest());
5
+ }
6
+ export function useDirectusGraphql() {
7
+ return createBaseDirectus().with(graphql());
8
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yassidev/nuxt-directus",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "description": "A Nuxt module for better integration with Directus CMS.",
5
5
  "repository": "yassilah/nuxt-directus",
6
6
  "license": "MIT",
@@ -51,10 +51,13 @@
51
51
  "@nuxt/schema": "^4.1.3",
52
52
  "@nuxt/test-utils": "^3.19.2",
53
53
  "@nuxtjs/i18n": "^10.1.0",
54
+ "@playwright/test": "^1.56.0",
54
55
  "@types/node": "latest",
55
56
  "changelogen": "^0.6.2",
57
+ "directus": "^11.12.0",
56
58
  "eslint": "^9.37.0",
57
59
  "nuxt": "^4.1.3",
60
+ "playwright-core": "^1.56.0",
58
61
  "typescript": "~5.9.3",
59
62
  "vitest": "^3.2.4",
60
63
  "vue-tsc": "^3.1.0"
@@ -1,4 +0,0 @@
1
- /**
2
- * Use directus (rest)
3
- */
4
- export declare function useDirectus(): import("@directus/sdk").DirectusClient<Schema> & import("@directus/sdk").GraphqlClient<Schema>;
@@ -1,5 +0,0 @@
1
- import { graphql } from "@directus/sdk";
2
- import { createBaseDirectus } from "./../client.js";
3
- export function useDirectus() {
4
- return createBaseDirectus().with(graphql());
5
- }
@@ -1,4 +0,0 @@
1
- /**
2
- * Use directus (rest)
3
- */
4
- export declare function useDirectus(): import("@directus/sdk").DirectusClient<Schema> & import("@directus/sdk").RestClient<Schema>;
@@ -1,5 +0,0 @@
1
- import { rest } from "@directus/sdk";
2
- import { createBaseDirectus } from "./../client.js";
3
- export function useDirectus() {
4
- return createBaseDirectus().with(rest());
5
- }