@enfyra/sdk-nuxt 0.1.12 → 0.2.0
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.md +348 -12
- package/dist/auth.d.ts +40 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +1 -0
- package/dist/composables/useEnfyraApi.d.ts +2 -0
- package/dist/composables/useEnfyraApi.mjs +37 -2
- package/dist/composables/useEnfyraAuth.d.ts +9 -0
- package/dist/composables.d.ts +11 -0
- package/dist/composables.d.ts.map +1 -0
- package/dist/composables.js +1 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/module.cjs +4 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +4 -0
- package/package.json +5 -5
- package/src/composables/useEnfyraApi.ts +52 -3
- package/src/module.ts +6 -0
- package/src/types/composables.ts +15 -0
- package/src/types/index.ts +11 -1
package/README.md
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
# @enfyra/sdk-nuxt
|
|
2
2
|
|
|
3
|
-
Nuxt SDK for Enfyra CMS
|
|
3
|
+
Nuxt SDK for Enfyra CMS - A powerful composable-based API client with full SSR support and TypeScript integration.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
✅ **SSR & Client-Side Support** - Automatic server-side rendering with `useFetch` or client-side with `$fetch`
|
|
8
|
+
✅ **Authentication Integration** - Built-in auth composables with automatic header forwarding
|
|
9
|
+
✅ **TypeScript Support** - Full type safety with auto-generated declarations
|
|
10
|
+
✅ **Batch Operations** - Efficient bulk operations for CRUD actions (client-side)
|
|
11
|
+
✅ **Error Handling** - Automatic error management with console logging
|
|
12
|
+
✅ **Reactive State** - Built-in loading, error, and data states
|
|
13
|
+
✅ **Caching Support** - Optional cache keys for SSR mode optimization
|
|
4
14
|
|
|
5
15
|
## Installation
|
|
6
16
|
|
|
@@ -8,9 +18,9 @@ Nuxt SDK for Enfyra CMS
|
|
|
8
18
|
npm install @enfyra/sdk-nuxt
|
|
9
19
|
```
|
|
10
20
|
|
|
11
|
-
##
|
|
21
|
+
## Setup
|
|
12
22
|
|
|
13
|
-
Add to your `nuxt.config.ts`:
|
|
23
|
+
Add the module to your `nuxt.config.ts`:
|
|
14
24
|
|
|
15
25
|
```typescript
|
|
16
26
|
export default defineNuxtConfig({
|
|
@@ -20,25 +30,351 @@ export default defineNuxtConfig({
|
|
|
20
30
|
runtimeConfig: {
|
|
21
31
|
public: {
|
|
22
32
|
enfyraSDK: {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
33
|
+
apiUrl: process.env.ENFYRA_API_URL || 'https://api.enfyra.com',
|
|
34
|
+
apiPrefix: '/api/v1', // Optional: API prefix
|
|
35
|
+
appUrl: process.env.ENFYRA_APP_URL || 'https://app.enfyra.com'
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
})
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Quick Start
|
|
43
|
+
|
|
44
|
+
### SSR Mode - Perfect for Page Data
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
// pages/users.vue
|
|
48
|
+
<script setup>
|
|
49
|
+
// ✅ Automatic server-side rendering with caching
|
|
50
|
+
const { data: users, pending, error, refresh } = useEnfyraApi('/users', {
|
|
51
|
+
ssr: true,
|
|
52
|
+
key: 'users-list'
|
|
53
|
+
});
|
|
54
|
+
</script>
|
|
55
|
+
|
|
56
|
+
<template>
|
|
57
|
+
<div>
|
|
58
|
+
<div v-if="pending">Loading users...</div>
|
|
59
|
+
<div v-else-if="error">Error: {{ error }}</div>
|
|
60
|
+
<div v-else>
|
|
61
|
+
<h1>Users ({{ users?.meta?.totalCount }})</h1>
|
|
62
|
+
<UserCard v-for="user in users?.data" :key="user.id" :user="user" />
|
|
63
|
+
<button @click="refresh">Refresh</button>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
</template>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Client Mode - Perfect for User Interactions
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
// components/CreateUserForm.vue
|
|
73
|
+
<script setup>
|
|
74
|
+
// ✅ Manual execution control for form submissions
|
|
75
|
+
const { execute: createUser, pending, error } = useEnfyraApi('/users', {
|
|
76
|
+
method: 'post',
|
|
77
|
+
errorContext: 'Create User'
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const formData = reactive({
|
|
81
|
+
name: '',
|
|
82
|
+
email: ''
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
async function handleSubmit() {
|
|
86
|
+
await createUser({ body: formData });
|
|
87
|
+
|
|
88
|
+
if (!error.value) {
|
|
89
|
+
toast.success('User created successfully!');
|
|
90
|
+
await navigateTo('/users');
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
</script>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Authentication
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
<script setup>
|
|
100
|
+
const { me, login, logout, isLoggedIn } = useEnfyraAuth();
|
|
101
|
+
|
|
102
|
+
// Login
|
|
103
|
+
await login({
|
|
104
|
+
email: 'user@example.com',
|
|
105
|
+
password: 'password123'
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Check auth status
|
|
109
|
+
console.log('Logged in:', isLoggedIn.value);
|
|
110
|
+
console.log('Current user:', me.value);
|
|
111
|
+
|
|
112
|
+
// Logout
|
|
113
|
+
await logout();
|
|
114
|
+
</script>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Core Composables
|
|
118
|
+
|
|
119
|
+
### `useEnfyraApi<T>(path, options)`
|
|
120
|
+
|
|
121
|
+
Main composable for API requests with both SSR and client-side support.
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
// SSR Mode - Automatic execution
|
|
125
|
+
const { data, pending, error, refresh } = useEnfyraApi('/endpoint', {
|
|
126
|
+
ssr: true,
|
|
127
|
+
key: 'cache-key',
|
|
128
|
+
method: 'get',
|
|
129
|
+
query: { page: 1 }
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// Client Mode - Manual execution
|
|
133
|
+
const { data, pending, error, execute } = useEnfyraApi('/endpoint', {
|
|
134
|
+
method: 'post',
|
|
135
|
+
errorContext: 'Create Resource'
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
await execute({
|
|
139
|
+
body: { name: 'New Item' },
|
|
140
|
+
id: '123' // For /endpoint/123
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Options:**
|
|
145
|
+
- `ssr?: boolean` - Enable server-side rendering mode
|
|
146
|
+
- `method?: 'get' | 'post' | 'patch' | 'delete'` - HTTP method
|
|
147
|
+
- `body?: any` - Request body (POST/PATCH)
|
|
148
|
+
- `query?: Record<string, any>` - URL query parameters
|
|
149
|
+
- `headers?: Record<string, string>` - Custom headers
|
|
150
|
+
- `errorContext?: string` - Error context for logging
|
|
151
|
+
- `key?: string` - Cache key (SSR mode only)
|
|
152
|
+
- `default?: () => T` - Default value (SSR mode only)
|
|
153
|
+
|
|
154
|
+
**Execute Options (Client mode only):**
|
|
155
|
+
- `id?: string | number` - Single resource ID
|
|
156
|
+
- `ids?: (string | number)[]` - Batch operation IDs (PATCH/DELETE)
|
|
157
|
+
- `files?: FormData[]` - Batch file upload (POST)
|
|
158
|
+
- `body?: any` - Override request body
|
|
159
|
+
|
|
160
|
+
### `useEnfyraAuth()`
|
|
161
|
+
|
|
162
|
+
Authentication composable with reactive state management.
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
const { me, login, logout, fetchUser, isLoggedIn } = useEnfyraAuth();
|
|
166
|
+
|
|
167
|
+
// Properties
|
|
168
|
+
me.value // Current user data (reactive)
|
|
169
|
+
isLoggedIn.value // Auth status (computed)
|
|
170
|
+
|
|
171
|
+
// Methods
|
|
172
|
+
await login({ email, password }) // Login user
|
|
173
|
+
await logout() // Logout user
|
|
174
|
+
await fetchUser() // Refresh user data
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Advanced Usage
|
|
178
|
+
|
|
179
|
+
### Batch Operations
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
// Batch delete multiple items
|
|
183
|
+
const { execute: deleteItems } = useEnfyraApi('/items', {
|
|
184
|
+
method: 'delete',
|
|
185
|
+
errorContext: 'Delete Items'
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
await deleteItems({ ids: ['1', '2', '3'] });
|
|
189
|
+
|
|
190
|
+
// Batch file upload
|
|
191
|
+
const { execute: uploadFiles } = useEnfyraApi('/files', {
|
|
192
|
+
method: 'post',
|
|
193
|
+
errorContext: 'Upload Files'
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
await uploadFiles({
|
|
197
|
+
files: [formData1, formData2, formData3]
|
|
198
|
+
});
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### TypeScript Integration
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
// Define your API response types
|
|
205
|
+
interface User {
|
|
206
|
+
id: string;
|
|
207
|
+
name: string;
|
|
208
|
+
email: string;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
interface ApiResponse<T> {
|
|
212
|
+
data: T[];
|
|
213
|
+
meta: { totalCount: number };
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Use with full type safety
|
|
217
|
+
const { data } = useEnfyraApi<ApiResponse<User>>('/users', {
|
|
218
|
+
ssr: true
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
// TypeScript knows data.value is ApiResponse<User> | null
|
|
222
|
+
const users = computed(() => data.value?.data || []);
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Reactive Parameters
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
const searchQuery = ref('');
|
|
229
|
+
const page = ref(1);
|
|
230
|
+
|
|
231
|
+
// SSR mode with reactive query
|
|
232
|
+
const { data, refresh } = useEnfyraApi('/users', {
|
|
233
|
+
ssr: true,
|
|
234
|
+
key: () => `users-${page.value}-${searchQuery.value}`,
|
|
235
|
+
query: computed(() => ({
|
|
236
|
+
search: searchQuery.value,
|
|
237
|
+
page: page.value,
|
|
238
|
+
limit: 10
|
|
239
|
+
}))
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
// Watch for changes and refresh
|
|
243
|
+
watch([searchQuery, page], () => refresh());
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## Documentation
|
|
247
|
+
|
|
248
|
+
For comprehensive guides and examples:
|
|
249
|
+
|
|
250
|
+
📚 **[useEnfyraApi Complete Guide](./docs/useEnfyraApi.md)** - Detailed documentation with examples, best practices, and troubleshooting
|
|
251
|
+
|
|
252
|
+
Key topics covered:
|
|
253
|
+
- SSR vs Client Mode comparison
|
|
254
|
+
- Authentication and headers forwarding
|
|
255
|
+
- Batch operations and CRUD patterns
|
|
256
|
+
- Error handling best practices
|
|
257
|
+
- TypeScript integration
|
|
258
|
+
- Performance optimization
|
|
259
|
+
- Migration guides
|
|
260
|
+
|
|
261
|
+
## Configuration
|
|
262
|
+
|
|
263
|
+
### Runtime Config Options
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
// nuxt.config.ts
|
|
267
|
+
export default defineNuxtConfig({
|
|
268
|
+
runtimeConfig: {
|
|
269
|
+
public: {
|
|
270
|
+
enfyraSDK: {
|
|
271
|
+
// Required: Main API URL
|
|
272
|
+
apiUrl: process.env.ENFYRA_API_URL,
|
|
273
|
+
|
|
274
|
+
// Optional: API path prefix (default: '')
|
|
275
|
+
apiPrefix: '/api/v1',
|
|
276
|
+
|
|
277
|
+
// Required: App URL for SSR requests
|
|
278
|
+
appUrl: process.env.ENFYRA_APP_URL,
|
|
279
|
+
|
|
280
|
+
// Optional: Default headers for all requests
|
|
281
|
+
defaultHeaders: {
|
|
282
|
+
'Accept': 'application/json',
|
|
283
|
+
'Content-Type': 'application/json'
|
|
284
|
+
}
|
|
26
285
|
},
|
|
27
286
|
},
|
|
28
287
|
},
|
|
29
288
|
})
|
|
30
289
|
```
|
|
31
290
|
|
|
32
|
-
|
|
291
|
+
### Environment Variables
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
# .env
|
|
295
|
+
ENFYRA_API_URL=https://api.enfyra.com
|
|
296
|
+
ENFYRA_APP_URL=https://app.enfyra.com
|
|
297
|
+
```
|
|
33
298
|
|
|
34
|
-
|
|
299
|
+
## Best Practices
|
|
300
|
+
|
|
301
|
+
### 1. Choose the Right Mode
|
|
35
302
|
|
|
36
303
|
```typescript
|
|
37
|
-
|
|
304
|
+
// ✅ Use SSR for initial page data
|
|
305
|
+
const { data } = useEnfyraApi('/dashboard', {
|
|
306
|
+
ssr: true,
|
|
307
|
+
key: 'dashboard'
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
// ✅ Use Client mode for user interactions
|
|
311
|
+
const { execute: saveData } = useEnfyraApi('/settings', {
|
|
312
|
+
method: 'patch',
|
|
313
|
+
errorContext: 'Save Settings'
|
|
314
|
+
});
|
|
38
315
|
```
|
|
39
316
|
|
|
40
|
-
###
|
|
317
|
+
### 2. Proper Error Handling
|
|
41
318
|
|
|
42
319
|
```typescript
|
|
43
|
-
|
|
44
|
-
|
|
320
|
+
// ✅ Check error state (don't use try-catch)
|
|
321
|
+
async function handleSubmit() {
|
|
322
|
+
await execute({ body: formData });
|
|
323
|
+
|
|
324
|
+
if (error.value) {
|
|
325
|
+
return; // Error already logged
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Success handling
|
|
329
|
+
toast.success('Saved successfully');
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### 3. Type Safety
|
|
334
|
+
|
|
335
|
+
```typescript
|
|
336
|
+
// ✅ Define interfaces for API responses
|
|
337
|
+
interface CreateUserResponse {
|
|
338
|
+
data: User;
|
|
339
|
+
message: string;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const { execute } = useEnfyraApi<CreateUserResponse>('/users', {
|
|
343
|
+
method: 'post'
|
|
344
|
+
});
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
## Troubleshooting
|
|
348
|
+
|
|
349
|
+
### Common Issues
|
|
350
|
+
|
|
351
|
+
1. **Headers not forwarded in SSR** - Ensure `ssr: true` is set
|
|
352
|
+
2. **Batch operations not working** - Only available in Client mode
|
|
353
|
+
3. **Data not reactive** - Use computed refs for reactive parameters
|
|
354
|
+
4. **TypeScript errors** - Check return type differences between modes
|
|
355
|
+
|
|
356
|
+
### Performance Tips
|
|
357
|
+
|
|
358
|
+
- Use SSR for initial data loading (better SEO, faster page loads)
|
|
359
|
+
- Use Client mode for user interactions (better UX)
|
|
360
|
+
- Implement proper cache keys to avoid over-caching
|
|
361
|
+
- Group related operations with batch APIs
|
|
362
|
+
|
|
363
|
+
## License
|
|
364
|
+
|
|
365
|
+
MIT
|
|
366
|
+
|
|
367
|
+
## Contributing
|
|
368
|
+
|
|
369
|
+
Pull requests are welcome! Please read our contributing guidelines and ensure tests pass.
|
|
370
|
+
|
|
371
|
+
## Changelog
|
|
372
|
+
|
|
373
|
+
See [CHANGELOG.md](./CHANGELOG.md) for a detailed history of changes and migration guides.
|
|
374
|
+
|
|
375
|
+
## Support
|
|
376
|
+
|
|
377
|
+
For issues and questions:
|
|
378
|
+
- 📖 Check the [detailed documentation](./docs/useEnfyraApi.md)
|
|
379
|
+
- 🐛 [Report bugs](https://github.com/enfyra/sdk-nuxt/issues)
|
|
380
|
+
- 💬 [Join our community](https://discord.gg/enfyra)
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Ref } from 'vue';
|
|
2
|
+
export interface User {
|
|
3
|
+
id: string;
|
|
4
|
+
email: string;
|
|
5
|
+
isRootAdmin: boolean;
|
|
6
|
+
isSystem: boolean;
|
|
7
|
+
role?: {
|
|
8
|
+
id: string;
|
|
9
|
+
name: string;
|
|
10
|
+
routePermissions: RoutePermission[];
|
|
11
|
+
};
|
|
12
|
+
allowedRoutePermissions?: RoutePermission[];
|
|
13
|
+
}
|
|
14
|
+
export interface RoutePermission {
|
|
15
|
+
id: string;
|
|
16
|
+
isEnabled: boolean;
|
|
17
|
+
allowedUsers?: {
|
|
18
|
+
id: string;
|
|
19
|
+
}[];
|
|
20
|
+
methods: {
|
|
21
|
+
id: string;
|
|
22
|
+
method: string;
|
|
23
|
+
}[];
|
|
24
|
+
route: {
|
|
25
|
+
id: string;
|
|
26
|
+
path: string;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export interface LoginPayload {
|
|
30
|
+
email: string;
|
|
31
|
+
password: string;
|
|
32
|
+
remember?: boolean;
|
|
33
|
+
}
|
|
34
|
+
export interface UseEnfyraAuthReturn {
|
|
35
|
+
me: Ref<User | null>;
|
|
36
|
+
login: (payload: LoginPayload) => Promise<any>;
|
|
37
|
+
logout: () => Promise<void>;
|
|
38
|
+
fetchUser: () => Promise<void>;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/types/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAE9B,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,OAAO,CAAA;IACpB,QAAQ,EAAE,OAAO,CAAA;IACjB,IAAI,CAAC,EAAE;QACL,EAAE,EAAE,MAAM,CAAA;QACV,IAAI,EAAE,MAAM,CAAA;QACZ,gBAAgB,EAAE,eAAe,EAAE,CAAA;KACpC,CAAA;IACD,uBAAuB,CAAC,EAAE,eAAe,EAAE,CAAA;CAC5C;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,OAAO,CAAA;IAClB,YAAY,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAC/B,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACzC,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CACpC;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAA;IACpB,KAAK,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;IAC9C,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3B,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC/B"}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ref, unref, toRaw } from "vue";
|
|
2
2
|
import { $fetch } from "../utils/http";
|
|
3
|
-
import { useRuntimeConfig } from "#imports";
|
|
3
|
+
import { useRuntimeConfig, useFetch, useRequestHeaders } from "#imports";
|
|
4
4
|
function handleApiError(error, context) {
|
|
5
5
|
let message = "Request failed";
|
|
6
6
|
let errorCode = "UNKNOWN_ERROR";
|
|
@@ -33,7 +33,42 @@ function handleApiError(error, context) {
|
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
35
|
export function useEnfyraApi(path, opts = {}) {
|
|
36
|
-
const { method = "get", body, query, errorContext } = opts;
|
|
36
|
+
const { method = "get", body, query, errorContext, ssr, key } = opts;
|
|
37
|
+
if (ssr) {
|
|
38
|
+
const config = useRuntimeConfig().public.enfyraSDK;
|
|
39
|
+
const basePath = (typeof path === "function" ? path() : path).replace(/^\/?api\/?/, "").replace(/^\/+/, "");
|
|
40
|
+
const finalUrl = (config?.appUrl || "") + (config?.apiPrefix || "") + "/" + basePath;
|
|
41
|
+
const clientHeaders = process.client ? {} : useRequestHeaders([
|
|
42
|
+
"authorization",
|
|
43
|
+
"cookie",
|
|
44
|
+
"user-agent",
|
|
45
|
+
"accept",
|
|
46
|
+
"accept-language",
|
|
47
|
+
"referer"
|
|
48
|
+
]);
|
|
49
|
+
const serverHeaders = { ...clientHeaders };
|
|
50
|
+
delete serverHeaders.connection;
|
|
51
|
+
delete serverHeaders["keep-alive"];
|
|
52
|
+
delete serverHeaders.host;
|
|
53
|
+
delete serverHeaders["content-length"];
|
|
54
|
+
const fetchOptions = {
|
|
55
|
+
method,
|
|
56
|
+
body,
|
|
57
|
+
query,
|
|
58
|
+
headers: {
|
|
59
|
+
...serverHeaders,
|
|
60
|
+
...opts.headers
|
|
61
|
+
// Custom headers override client headers
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
if (key) {
|
|
65
|
+
fetchOptions.key = key;
|
|
66
|
+
}
|
|
67
|
+
if (opts.default) {
|
|
68
|
+
fetchOptions.default = opts.default;
|
|
69
|
+
}
|
|
70
|
+
return useFetch(finalUrl, fetchOptions);
|
|
71
|
+
}
|
|
37
72
|
const data = ref(null);
|
|
38
73
|
const error = ref(null);
|
|
39
74
|
const pending = ref(false);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { LoginPayload, User } from "../types/auth";
|
|
2
|
+
import type { Ref, ComputedRef } from 'vue';
|
|
3
|
+
export declare function useEnfyraAuth(): {
|
|
4
|
+
me: Ref<User | null>;
|
|
5
|
+
login: (payload: LoginPayload) => Promise<any>;
|
|
6
|
+
logout: () => Promise<void>;
|
|
7
|
+
fetchUser: () => Promise<void>;
|
|
8
|
+
isLoggedIn: ComputedRef<boolean>;
|
|
9
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Ref, ComputedRef } from 'vue';
|
|
2
|
+
import type { LoginPayload, User, ApiOptions, UseEnfyraApiReturn } from './index';
|
|
3
|
+
export declare function useEnfyraAuth(): {
|
|
4
|
+
me: Ref<User | null>;
|
|
5
|
+
login: (payload: LoginPayload) => Promise<any>;
|
|
6
|
+
logout: () => Promise<void>;
|
|
7
|
+
fetchUser: () => Promise<void>;
|
|
8
|
+
isLoggedIn: ComputedRef<boolean>;
|
|
9
|
+
};
|
|
10
|
+
export declare function useEnfyraApi<T = any>(path: (() => string) | string, opts?: ApiOptions<T>): UseEnfyraApiReturn<T>;
|
|
11
|
+
//# sourceMappingURL=composables.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composables.d.ts","sourceRoot":"","sources":["../src/types/composables.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAEjF,MAAM,CAAC,OAAO,UAAU,aAAa,IAAI;IACvC,EAAE,EAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAA;IACpB,KAAK,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;IAC9C,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3B,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9B,UAAU,EAAE,WAAW,CAAC,OAAO,CAAC,CAAA;CACjC,CAAA;AAED,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,CAAC,GAAG,GAAG,EAC1C,IAAI,EAAE,CAAC,MAAM,MAAM,CAAC,GAAG,MAAM,EAC7B,IAAI,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,GACnB,kBAAkB,CAAC,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export interface EnfyraConfig {
|
|
2
|
+
apiUrl: string;
|
|
3
|
+
apiPrefix?: string;
|
|
4
|
+
defaultHeaders?: Record<string, string>;
|
|
5
|
+
}
|
|
6
|
+
export interface ApiOptions<T> {
|
|
7
|
+
method?: 'get' | 'post' | 'put' | 'patch' | 'delete' | 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
8
|
+
body?: any;
|
|
9
|
+
query?: Record<string, any>;
|
|
10
|
+
headers?: Record<string, string>;
|
|
11
|
+
errorContext?: string;
|
|
12
|
+
disableBatch?: boolean;
|
|
13
|
+
default?: () => T;
|
|
14
|
+
/** Enable SSR with useFetch instead of $fetch */
|
|
15
|
+
ssr?: boolean;
|
|
16
|
+
/** Unique key for useFetch caching */
|
|
17
|
+
key?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface BackendError {
|
|
20
|
+
success: false;
|
|
21
|
+
message: string;
|
|
22
|
+
}
|
|
23
|
+
export interface BackendErrorExtended extends BackendError {
|
|
24
|
+
error: {
|
|
25
|
+
code: string;
|
|
26
|
+
message: string;
|
|
27
|
+
details?: any;
|
|
28
|
+
timestamp: string;
|
|
29
|
+
path: string;
|
|
30
|
+
method: string;
|
|
31
|
+
correlationId?: string;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
import type { Ref } from 'vue';
|
|
35
|
+
export interface UseEnfyraApiReturn<T> {
|
|
36
|
+
data: Ref<T | null>;
|
|
37
|
+
error: Ref<any>;
|
|
38
|
+
pending: Ref<boolean>;
|
|
39
|
+
execute: (executeOpts?: {
|
|
40
|
+
body?: any;
|
|
41
|
+
id?: string | number;
|
|
42
|
+
ids?: (string | number)[];
|
|
43
|
+
files?: any[];
|
|
44
|
+
}) => Promise<T | T[] | null>;
|
|
45
|
+
}
|
|
46
|
+
export * from './auth';
|
|
47
|
+
export * from './composables';
|
|
48
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/types/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;IACnG,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC;IAClB,iDAAiD;IACjD,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,sCAAsC;IACtC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,KAAK,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,oBAAqB,SAAQ,YAAY;IACxD,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,GAAG,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;CACH;AAED,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE/B,MAAM,WAAW,kBAAkB,CAAC,CAAC;IACnC,IAAI,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACpB,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;IAChB,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACtB,OAAO,EAAE,CAAC,WAAW,CAAC,EAAE;QACtB,IAAI,CAAC,EAAE,GAAG,CAAC;QACX,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QACrB,GAAG,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;QAC1B,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC;KACf,KAAK,OAAO,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;CAC/B;AAGD,cAAc,QAAQ,CAAC;AAGvB,cAAc,eAAe,CAAC"}
|
package/dist/index.js
ADDED
package/dist/module.cjs
CHANGED
|
@@ -15,6 +15,10 @@ const module$1 = kit.defineNuxtModule({
|
|
|
15
15
|
},
|
|
16
16
|
setup(options, nuxt) {
|
|
17
17
|
const { resolve } = kit.createResolver((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('module.cjs', document.baseURI).href)));
|
|
18
|
+
nuxt.options.runtimeConfig.public.enfyraSDK = {
|
|
19
|
+
...nuxt.options.runtimeConfig.public.enfyraSDK,
|
|
20
|
+
...options
|
|
21
|
+
};
|
|
18
22
|
kit.addImportsDir(resolve("./composables"));
|
|
19
23
|
kit.addServerHandler({
|
|
20
24
|
handler: resolve("./runtime/server/middleware/auth"),
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -12,6 +12,10 @@ const module = defineNuxtModule({
|
|
|
12
12
|
},
|
|
13
13
|
setup(options, nuxt) {
|
|
14
14
|
const { resolve } = createResolver(import.meta.url);
|
|
15
|
+
nuxt.options.runtimeConfig.public.enfyraSDK = {
|
|
16
|
+
...nuxt.options.runtimeConfig.public.enfyraSDK,
|
|
17
|
+
...options
|
|
18
|
+
};
|
|
15
19
|
addImportsDir(resolve("./composables"));
|
|
16
20
|
addServerHandler({
|
|
17
21
|
handler: resolve("./runtime/server/middleware/auth"),
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@enfyra/sdk-nuxt",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Nuxt SDK for Enfyra CMS",
|
|
5
5
|
"main": "./dist/module.mjs",
|
|
6
|
-
"types": "./dist/
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": {
|
|
9
9
|
"import": "./dist/module.mjs",
|
|
10
10
|
"require": "./dist/module.cjs",
|
|
11
|
-
"types": "./dist/
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"files": [
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
},
|
|
29
29
|
"scripts": {
|
|
30
30
|
"dev": "nuxi dev playground",
|
|
31
|
-
"build": "nuxt-module-build build",
|
|
32
|
-
"prepack": "nuxt-module-build build"
|
|
31
|
+
"build": "nuxt-module-build build && npx tsc -p tsconfig.build.json && node scripts/copy-composables-types.js",
|
|
32
|
+
"prepack": "nuxt-module-build build && npx tsc -p tsconfig.build.json && node scripts/copy-composables-types.js"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"@nuxt/kit": "^3.18.1",
|
|
@@ -5,7 +5,7 @@ import type {
|
|
|
5
5
|
UseEnfyraApiReturn,
|
|
6
6
|
} from "../types";
|
|
7
7
|
import { $fetch } from "../utils/http";
|
|
8
|
-
import { useRuntimeConfig } from "#imports";
|
|
8
|
+
import { useRuntimeConfig, useFetch, useRequestHeaders } from "#imports";
|
|
9
9
|
|
|
10
10
|
function handleApiError(error: any, context?: string) {
|
|
11
11
|
let message = "Request failed";
|
|
@@ -50,7 +50,57 @@ export function useEnfyraApi<T = any>(
|
|
|
50
50
|
path: (() => string) | string,
|
|
51
51
|
opts: ApiOptions<T> = {}
|
|
52
52
|
): UseEnfyraApiReturn<T> {
|
|
53
|
-
const { method = "get", body, query, errorContext } = opts;
|
|
53
|
+
const { method = "get", body, query, errorContext, ssr, key } = opts;
|
|
54
|
+
|
|
55
|
+
// SSR mode - use useFetch
|
|
56
|
+
if (ssr) {
|
|
57
|
+
const config = useRuntimeConfig().public.enfyraSDK;
|
|
58
|
+
const basePath = (typeof path === "function" ? path() : path)
|
|
59
|
+
.replace(/^\/?api\/?/, "")
|
|
60
|
+
.replace(/^\/+/, ""); // Remove leading slashes
|
|
61
|
+
|
|
62
|
+
const finalUrl =
|
|
63
|
+
(config?.appUrl || "") + (config?.apiPrefix || "") + "/" + basePath;
|
|
64
|
+
|
|
65
|
+
// Get headers from client request and filter out connection-specific headers
|
|
66
|
+
const clientHeaders = process.client
|
|
67
|
+
? {}
|
|
68
|
+
: useRequestHeaders([
|
|
69
|
+
"authorization",
|
|
70
|
+
"cookie",
|
|
71
|
+
"user-agent",
|
|
72
|
+
"accept",
|
|
73
|
+
"accept-language",
|
|
74
|
+
"referer",
|
|
75
|
+
]);
|
|
76
|
+
|
|
77
|
+
// Remove connection-specific headers that shouldn't be forwarded
|
|
78
|
+
const serverHeaders = { ...clientHeaders };
|
|
79
|
+
delete serverHeaders.connection;
|
|
80
|
+
delete serverHeaders["keep-alive"];
|
|
81
|
+
delete serverHeaders.host;
|
|
82
|
+
delete serverHeaders["content-length"];
|
|
83
|
+
|
|
84
|
+
const fetchOptions: any = {
|
|
85
|
+
method: method as any,
|
|
86
|
+
body: body,
|
|
87
|
+
query: query,
|
|
88
|
+
headers: {
|
|
89
|
+
...serverHeaders,
|
|
90
|
+
...opts.headers, // Custom headers override client headers
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// Only add useFetch-specific options if provided
|
|
95
|
+
if (key) {
|
|
96
|
+
fetchOptions.key = key;
|
|
97
|
+
}
|
|
98
|
+
if (opts.default) {
|
|
99
|
+
fetchOptions.default = opts.default;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return useFetch<T>(finalUrl, fetchOptions) as any;
|
|
103
|
+
}
|
|
54
104
|
const data = ref<T | null>(null);
|
|
55
105
|
const error = ref<any>(null);
|
|
56
106
|
const pending = ref(false);
|
|
@@ -69,7 +119,6 @@ export function useEnfyraApi<T = any>(
|
|
|
69
119
|
const config: any = useRuntimeConfig().public.enfyraSDK;
|
|
70
120
|
const apiUrl = config?.appUrl;
|
|
71
121
|
const apiPrefix = config?.apiPrefix;
|
|
72
|
-
|
|
73
122
|
const basePath = (typeof path === "function" ? path() : path)
|
|
74
123
|
.replace(/^\/?api\/?/, "")
|
|
75
124
|
.replace(/^\/+/, ""); // Remove leading slashes
|
package/src/module.ts
CHANGED
|
@@ -18,6 +18,12 @@ export default defineNuxtModule({
|
|
|
18
18
|
setup(options, nuxt) {
|
|
19
19
|
const { resolve } = createResolver(import.meta.url);
|
|
20
20
|
|
|
21
|
+
// Make module options available at runtime
|
|
22
|
+
nuxt.options.runtimeConfig.public.enfyraSDK = {
|
|
23
|
+
...nuxt.options.runtimeConfig.public.enfyraSDK,
|
|
24
|
+
...options,
|
|
25
|
+
};
|
|
26
|
+
|
|
21
27
|
// Auto-import composables
|
|
22
28
|
addImportsDir(resolve("./composables"));
|
|
23
29
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Ref, ComputedRef } from 'vue'
|
|
2
|
+
import type { LoginPayload, User, ApiOptions, UseEnfyraApiReturn } from './index'
|
|
3
|
+
|
|
4
|
+
export declare function useEnfyraAuth(): {
|
|
5
|
+
me: Ref<User | null>
|
|
6
|
+
login: (payload: LoginPayload) => Promise<any>
|
|
7
|
+
logout: () => Promise<void>
|
|
8
|
+
fetchUser: () => Promise<void>
|
|
9
|
+
isLoggedIn: ComputedRef<boolean>
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export declare function useEnfyraApi<T = any>(
|
|
13
|
+
path: (() => string) | string,
|
|
14
|
+
opts?: ApiOptions<T>
|
|
15
|
+
): UseEnfyraApiReturn<T>
|
package/src/types/index.ts
CHANGED
|
@@ -12,6 +12,10 @@ export interface ApiOptions<T> {
|
|
|
12
12
|
errorContext?: string;
|
|
13
13
|
disableBatch?: boolean;
|
|
14
14
|
default?: () => T;
|
|
15
|
+
/** Enable SSR with useFetch instead of $fetch */
|
|
16
|
+
ssr?: boolean;
|
|
17
|
+
/** Unique key for useFetch caching */
|
|
18
|
+
key?: string;
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
export interface BackendError {
|
|
@@ -43,4 +47,10 @@ export interface UseEnfyraApiReturn<T> {
|
|
|
43
47
|
ids?: (string | number)[];
|
|
44
48
|
files?: any[];
|
|
45
49
|
}) => Promise<T | T[] | null>;
|
|
46
|
-
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Re-export auth types
|
|
53
|
+
export * from './auth';
|
|
54
|
+
|
|
55
|
+
// Re-export composables types
|
|
56
|
+
export * from './composables';
|