@arex95/vue-core 5.0.0 → 5.1.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.
Files changed (2) hide show
  1. package/README.md +196 -55
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,97 +1,238 @@
1
1
  # @arex95/vue-core
2
2
 
3
- A comprehensive Vue.js core library designed to streamline the development of Vue applications. It provides a set of composables, utilities, and services for handling common tasks such as API communication, authentication, and data management.
3
+ **Stop rewriting the same API boilerplate in every Vue project.**
4
4
 
5
- ## Features
6
-
7
- - **RESTful Standard**: A standardized RESTful class (`RestStd`) that you can extend directly from your models for clean, semantic API calls (e.g., `User.getOne()`).
8
- - **Fetching Agnostic**: Works with any fetching system (Axios, ofetch, fetch API, or custom fetchers).
9
- - **Flexible Authentication**: JWT-based authentication system that works with any fetcher (not tied to Axios).
10
- - **Enhanced Error Handling**: Custom error classes (`NetworkError`, `AuthError`, `ValidationError`, etc.) with structured error information.
11
- - **Retry Logic**: Built-in retry mechanism with exponential backoff for failed requests.
12
- - **Secure Storage**: Support for localStorage, sessionStorage, and cookies with encryption and security options (Secure, SameSite).
13
- - **SSR/SSG Support**: Full support for server-side rendering with automatic cookie fallback.
14
- - **Type Safety**: Improved generic types for better TypeScript inference and autocompletion.
15
- - **Utility Functions**: A rich collection of utilities for dates, strings, validations, encryption, and more.
16
-
17
- ## Installation
5
+ `@arex95/vue-core` gives you a battle-tested foundation for REST communication, encrypted token auth, and session management — so you ship features instead of infrastructure.
18
6
 
19
7
  ```sh
20
8
  npm install @arex95/vue-core
9
+ # or
10
+ pnpm add @arex95/vue-core
21
11
  ```
22
12
 
23
- ## Quick Start
13
+ ---
14
+
15
+ ## Why this library?
16
+
17
+ Every Vue project ends up with the same problem: you need authentication, you need a clean way to talk to your REST API, and you need it to work the same way across every service file. The usual answer is copying patterns between projects and hoping nothing drifts.
18
+
19
+ `@arex95/vue-core` is the answer:
24
20
 
25
- To get started, you need to configure the library in your main `main.ts` file.
21
+ - **`RestStd`** one class to extend, and your entire API layer is consistent. No more hand-writing `axios.get('/users/'+id)` everywhere.
22
+ - **Fetcher-agnostic** — bring Axios, `ofetch`, the native Fetch API, or your own fetcher. The library doesn't care.
23
+ - **Encrypted token storage** — JWTs stored with AES-CBC-256 via the Web Crypto API. Not plain text in localStorage.
24
+ - **Automatic token refresh** — 401? The library refreshes silently and retries. Your components never see it.
25
+ - **Works in Nuxt SSR** — `setupAuthInterceptors: false` gives you full control for server-side environments.
26
+
27
+ ---
28
+
29
+ ## Setup
26
30
 
27
31
  ```typescript
28
- import { createApp } from 'vue';
29
- import App from './App.vue';
32
+ // main.ts
30
33
  import { ArexVueCore } from '@arex95/vue-core';
31
34
 
32
- const app = createApp(App);
33
-
34
35
  app.use(ArexVueCore, {
35
- appKey: 'your-secret-key',
36
+ appKey: import.meta.env.VITE_APP_KEY, // used to encrypt tokens at rest
37
+
36
38
  endpoints: {
37
- login: '/api/login',
38
- refresh: '/api/refresh',
39
- logout: '/api/logout',
39
+ login: 'auth/login',
40
+ refresh: 'auth/refresh',
41
+ logout: 'auth/logout',
40
42
  },
43
+
41
44
  tokenKeys: {
42
- accessToken: 'ACCESS_TOKEN',
43
- refreshToken: 'REFRESH_TOKEN',
45
+ accessToken: 'myapp_access', // storage key name
46
+ refreshToken: 'myapp_refresh',
44
47
  },
48
+
49
+ // dot-notation paths to find tokens in your API response
45
50
  tokenPaths: {
46
- accessToken: 'data.access_token',
47
- refreshToken: 'data.refresh_token',
51
+ accessToken: 'token', // response.token
52
+ refreshToken: 'refresh_token', // response.refresh_token
48
53
  },
49
54
  refreshTokenPaths: {
50
- accessToken: 'data.access_token',
51
- refreshToken: 'data.refresh_token',
55
+ accessToken: 'token',
56
+ refreshToken: 'refresh_token',
52
57
  },
58
+
53
59
  axios: {
54
- baseURL: 'https://api.example.com',
60
+ baseURL: import.meta.env.VITE_API_URL,
61
+ headers: { 'X-API-Key': import.meta.env.VITE_API_KEY },
62
+ setupAuthInterceptors: true, // false for Nuxt SSR
55
63
  },
56
- });
57
64
 
58
- app.mount('#app');
65
+ onRefreshFailed: () => router.push('/login'),
66
+ });
59
67
  ```
60
68
 
61
- **Create a model:**
69
+ ---
70
+
71
+ ## RestStd — the core pattern
72
+
73
+ Extend `RestStd` and get a full CRUD interface for free:
62
74
 
63
75
  ```typescript
64
76
  import { RestStd } from '@arex95/vue-core';
65
77
 
66
- export interface UserData {
67
- id: number;
68
- name: string;
69
- email: string;
78
+ export class ProductService extends RestStd {
79
+ static override resource = 'catalog/products';
70
80
  }
71
81
 
72
- export class User extends RestStd {
82
+ // Now use it anywhere — with TanStack Query, in composables, wherever.
83
+ const products = await ProductService.getAll({ params: { page: 1 } });
84
+ const product = await ProductService.getOne({ id: 42 });
85
+ const created = await ProductService.create({ data: { name: 'Widget' } });
86
+ await ProductService.patch({ id: 42, data: { price: 9.99 } });
87
+ await ProductService.delete({ id: 42 });
88
+ ```
89
+
90
+ Need a custom endpoint? `customRequest` has you covered:
91
+
92
+ ```typescript
93
+ export class CheckoutService extends RestStd {
94
+ static override resource = 'sales/checkouts';
95
+
96
+ static complete(data: PaymentData) {
97
+ return this.customRequest({
98
+ method: 'POST',
99
+ url: 'sales/checkout/complete',
100
+ data,
101
+ });
102
+ }
103
+ }
104
+ ```
105
+
106
+ All requests go through the same globally configured Axios instance — same base URL, same headers, same auth interceptors. Consistent by default.
107
+
108
+ ---
109
+
110
+ ## Authentication
111
+
112
+ ```typescript
113
+ import { useAuth, verifyAuth, cleanCredentials } from '@arex95/vue-core';
114
+
115
+ const { login, logout } = useAuth();
116
+
117
+ // 'local' → localStorage (persists across browser sessions)
118
+ // 'session' → sessionStorage (cleared on tab close)
119
+ // 'cookie' → document.cookie
120
+ await login({ email, password }, 'local');
121
+
122
+ // Check if the user has a valid, non-expired token
123
+ const isAuthed = await verifyAuth(); // → boolean
124
+
125
+ // Logout — clears ALL storage locations so no token survives
126
+ await cleanCredentials('any');
127
+ await logout();
128
+ ```
129
+
130
+ Tokens are encrypted with **AES-CBC-256** before hitting any storage. Even if someone reads your localStorage, they get ciphertext.
131
+
132
+ ### Automatic token refresh
133
+
134
+ When `setupAuthInterceptors: true`, every 401 response triggers a silent refresh:
135
+
136
+ ```
137
+ Request → 401
138
+ → POST /auth/refresh (with refresh_token in body)
139
+ → New tokens stored
140
+ → Original request retried
141
+ → Response returned to your code as if nothing happened
142
+ ```
143
+
144
+ If the refresh also fails, `onRefreshFailed` is called — typically a redirect to `/login`.
145
+
146
+ ---
147
+
148
+ ## Fetcher-agnostic
149
+
150
+ Don't want Axios? Swap it out:
151
+
152
+ ```typescript
153
+ import { createOfetchFetcher, configAuthFetcher } from '@arex95/vue-core';
154
+
155
+ // Use ofetch globally for auth requests
156
+ configAuthFetcher(createOfetchFetcher('https://api.example.com'));
157
+
158
+ // Or pass a custom fetcher to a specific RestStd subclass
159
+ export class UserService extends RestStd {
160
+ static fetchFn = createOfetchFetcher('https://users.example.com');
73
161
  static override resource = 'users';
74
- // fetchFn is optional if you configured Axios with configAxios()
75
162
  }
163
+ ```
164
+
165
+ ---
166
+
167
+ ## Token Storage
76
168
 
77
- // Use directly in components
78
- const { data: users } = useQuery({
79
- queryKey: ['users'],
80
- queryFn: () => User.getAll<UserData[]>(),
169
+ | location | Stores in | Persistence | `"any"` reads it? |
170
+ |----------|-----------|-------------|-------------------|
171
+ | `'local'` | localStorage | Until explicitly cleared | ✅ |
172
+ | `'session'` | sessionStorage | Until tab closes | ✅ |
173
+ | `'cookie'` | document.cookie | Configurable expiry | ✅ (last) |
174
+ | `'any'` | localStorage | Until explicitly cleared | — |
175
+
176
+ `'local'` is the recommended default for SPAs — persistent, simple, and always found by the automatic interceptors.
177
+
178
+ ---
179
+
180
+ ## Nuxt / SSR Integration
181
+
182
+ ```typescript
183
+ // plugins/arex-core.ts
184
+ export default defineNuxtPlugin({
185
+ enforce: 'pre',
186
+ setup() {
187
+ const config = useRuntimeConfig();
188
+ app.use(ArexVueCore, {
189
+ appKey: config.public.appKey,
190
+ // ...
191
+ axios: {
192
+ baseURL: config.public.apiUrl,
193
+ setupAuthInterceptors: false, // handle headers in your own plugin
194
+ },
195
+ onRefreshFailed: () => navigateTo('/auth/login'),
196
+ });
197
+ }
81
198
  });
82
199
  ```
83
200
 
84
- For more detailed usage examples, please refer to the [documentation](./docs/getting-started.md) and [EXAMPLES.md](./EXAMPLES.md) file.
201
+ With `setupAuthInterceptors: false` you control exactly how `Authorization` and other headers are attached — essential for SSR where `localStorage` doesn't exist.
202
+
203
+ ---
204
+
205
+ ## Error Handling
206
+
207
+ ```typescript
208
+ import { handleError, NetworkError, AuthError, ValidationError } from '@arex95/vue-core';
209
+
210
+ try {
211
+ await login(credentials, 'local');
212
+ } catch (error) {
213
+ if (error instanceof AuthError) showError('Invalid credentials');
214
+ if (error instanceof NetworkError) showError(`Connection error ${error.statusCode}`);
215
+ if (error instanceof ValidationError) error.issues.forEach(i => setFieldError(i.field, i.message));
216
+ }
217
+ ```
218
+
219
+ ---
220
+
221
+ ## Full API Reference
222
+
223
+ → [docs/authentication.md](./docs/authentication.md)
224
+ → [docs/configuration.md](./docs/configuration.md)
225
+ → [docs/api-reference.md](./docs/api-reference.md)
226
+ → [EXAMPLES.md](./EXAMPLES.md)
227
+
228
+ ---
229
+
230
+ ## Requirements
85
231
 
86
- ## Project Structure
232
+ - Vue 3
233
+ - Node.js 15+ (Web Crypto API required for token encryption)
234
+ - TypeScript recommended
87
235
 
88
- - **`src/composables`**: Reusable Vue composables for various functionalities.
89
- - **`src/config`**: Global configuration for Axios, API endpoints, and tokens.
90
- - **`src/enums`**: Enums for constants used throughout the library.
91
- - **`src/fetchers`**: Optional helpers for creating fetchers (Axios, ofetch).
92
- - **`src/rest`**: A standardized RESTful class (`RestStd`) for CRUD operations.
93
- - **`src/services`**: Services for authentication and token management.
94
- - **`src/types`**: TypeScript type definitions.
95
- - **`src/utils`**: A collection of utility functions.
236
+ ## License
96
237
 
97
- For a more in-depth explanation of the project's architecture, please see the [ARCHITECTURE.md](./ARCHITECTURE.md) file.
238
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arex95/vue-core",
3
- "version": "5.0.0",
3
+ "version": "5.1.0",
4
4
  "description": "Opinionated Vue Core",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",