@aifabrix/miso-client 4.9.0 → 4.12.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 (268) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +164 -139
  3. package/dist/api/applications.api.d.ts +3 -3
  4. package/dist/api/applications.api.d.ts.map +1 -1
  5. package/dist/api/applications.api.js +21 -16
  6. package/dist/api/applications.api.js.map +1 -1
  7. package/dist/api/auth-cache.api.d.ts +3 -3
  8. package/dist/api/auth-cache.api.d.ts.map +1 -1
  9. package/dist/api/auth-cache.api.js +30 -30
  10. package/dist/api/auth-cache.api.js.map +1 -1
  11. package/dist/api/auth-login.api.d.ts +3 -3
  12. package/dist/api/auth-login.api.d.ts.map +1 -1
  13. package/dist/api/auth-login.api.js +25 -23
  14. package/dist/api/auth-login.api.js.map +1 -1
  15. package/dist/api/auth-token.api.d.ts +3 -3
  16. package/dist/api/auth-token.api.d.ts.map +1 -1
  17. package/dist/api/auth-token.api.js +53 -41
  18. package/dist/api/auth-token.api.js.map +1 -1
  19. package/dist/api/auth-user.api.d.ts +3 -3
  20. package/dist/api/auth-user.api.d.ts.map +1 -1
  21. package/dist/api/auth-user.api.js +18 -18
  22. package/dist/api/auth-user.api.js.map +1 -1
  23. package/dist/api/auth.api.d.ts +3 -3
  24. package/dist/api/auth.api.d.ts.map +1 -1
  25. package/dist/api/auth.api.js.map +1 -1
  26. package/dist/api/encryption.api.d.ts +2 -2
  27. package/dist/api/encryption.api.js +8 -8
  28. package/dist/api/index.d.ts +7 -7
  29. package/dist/api/logs-create.api.d.ts +3 -3
  30. package/dist/api/logs-create.api.d.ts.map +1 -1
  31. package/dist/api/logs-create.api.js +41 -19
  32. package/dist/api/logs-create.api.js.map +1 -1
  33. package/dist/api/logs-export.api.d.ts +3 -3
  34. package/dist/api/logs-export.api.d.ts.map +1 -1
  35. package/dist/api/logs-export.api.js +8 -6
  36. package/dist/api/logs-export.api.js.map +1 -1
  37. package/dist/api/logs-list.api.d.ts +3 -3
  38. package/dist/api/logs-list.api.d.ts.map +1 -1
  39. package/dist/api/logs-list.api.js +39 -33
  40. package/dist/api/logs-list.api.js.map +1 -1
  41. package/dist/api/logs-stats.api.d.ts +3 -3
  42. package/dist/api/logs-stats.api.d.ts.map +1 -1
  43. package/dist/api/logs-stats.api.js +24 -24
  44. package/dist/api/logs-stats.api.js.map +1 -1
  45. package/dist/api/logs.api.d.ts +3 -3
  46. package/dist/api/permissions.api.d.ts +3 -3
  47. package/dist/api/permissions.api.d.ts.map +1 -1
  48. package/dist/api/permissions.api.js +12 -12
  49. package/dist/api/permissions.api.js.map +1 -1
  50. package/dist/api/roles.api.d.ts +3 -3
  51. package/dist/api/roles.api.d.ts.map +1 -1
  52. package/dist/api/roles.api.js +12 -12
  53. package/dist/api/roles.api.js.map +1 -1
  54. package/dist/api/types/auth.types.d.ts +1 -1
  55. package/dist/api/types/encryption.types.d.ts +1 -1
  56. package/dist/api/types/logs.types.d.ts +10 -8
  57. package/dist/api/types/logs.types.d.ts.map +1 -1
  58. package/dist/express/client-token-endpoint.d.ts.map +1 -1
  59. package/dist/express/client-token-endpoint.js +29 -11
  60. package/dist/express/client-token-endpoint.js.map +1 -1
  61. package/dist/express/error-handler.d.ts.map +1 -1
  62. package/dist/express/error-handler.js +30 -8
  63. package/dist/express/error-handler.js.map +1 -1
  64. package/dist/express/error-types.d.ts.map +1 -1
  65. package/dist/express/error-types.js +26 -9
  66. package/dist/express/error-types.js.map +1 -1
  67. package/dist/express/index.d.ts +4 -4
  68. package/dist/express/index.d.ts.map +1 -1
  69. package/dist/express/index.js.map +1 -1
  70. package/dist/express/logger-context.middleware.d.ts.map +1 -1
  71. package/dist/express/logger-context.middleware.js +12 -5
  72. package/dist/express/logger-context.middleware.js.map +1 -1
  73. package/dist/express/response-helper.d.ts.map +1 -1
  74. package/dist/express/response-helper.js.map +1 -1
  75. package/dist/express/validation-helper.d.ts.map +1 -1
  76. package/dist/express/validation-helper.js +6 -2
  77. package/dist/express/validation-helper.js.map +1 -1
  78. package/dist/miso-client.d.ts.map +1 -1
  79. package/dist/miso-client.js +11 -4
  80. package/dist/miso-client.js.map +1 -1
  81. package/dist/sdk-exports.d.ts +6 -5
  82. package/dist/sdk-exports.d.ts.map +1 -1
  83. package/dist/sdk-exports.js +20 -1
  84. package/dist/sdk-exports.js.map +1 -1
  85. package/dist/services/application-context.service.d.ts.map +1 -1
  86. package/dist/services/application-context.service.js +3 -1
  87. package/dist/services/application-context.service.js.map +1 -1
  88. package/dist/services/auth-cache-helpers.d.ts.map +1 -1
  89. package/dist/services/auth-cache-helpers.js +9 -6
  90. package/dist/services/auth-cache-helpers.js.map +1 -1
  91. package/dist/services/auth-environment-token.d.ts.map +1 -1
  92. package/dist/services/auth-environment-token.js.map +1 -1
  93. package/dist/services/auth-error-handler.d.ts.map +1 -1
  94. package/dist/services/auth-error-handler.js.map +1 -1
  95. package/dist/services/auth.service.d.ts +0 -10
  96. package/dist/services/auth.service.d.ts.map +1 -1
  97. package/dist/services/auth.service.helpers.d.ts +22 -0
  98. package/dist/services/auth.service.helpers.d.ts.map +1 -0
  99. package/dist/services/auth.service.helpers.js +45 -0
  100. package/dist/services/auth.service.helpers.js.map +1 -0
  101. package/dist/services/auth.service.js +21 -57
  102. package/dist/services/auth.service.js.map +1 -1
  103. package/dist/services/browser-permission.service.d.ts.map +1 -1
  104. package/dist/services/browser-permission.service.js +10 -4
  105. package/dist/services/browser-permission.service.js.map +1 -1
  106. package/dist/services/browser-role.service.d.ts.map +1 -1
  107. package/dist/services/browser-role.service.js +6 -2
  108. package/dist/services/browser-role.service.js.map +1 -1
  109. package/dist/services/cache.service.d.ts.map +1 -1
  110. package/dist/services/cache.service.js +2 -1
  111. package/dist/services/cache.service.js.map +1 -1
  112. package/dist/services/encryption.service.d.ts +3 -3
  113. package/dist/services/encryption.service.d.ts.map +1 -1
  114. package/dist/services/encryption.service.js +12 -6
  115. package/dist/services/encryption.service.js.map +1 -1
  116. package/dist/services/logger/index.d.ts +1 -1
  117. package/dist/services/logger/index.d.ts.map +1 -1
  118. package/dist/services/logger/index.js.map +1 -1
  119. package/dist/services/logger/log-entry-builder.d.ts.map +1 -1
  120. package/dist/services/logger/log-entry-builder.js.map +1 -1
  121. package/dist/services/logger/logger-chain.d.ts.map +1 -1
  122. package/dist/services/logger/logger-chain.js.map +1 -1
  123. package/dist/services/logger/logger-context.d.ts.map +1 -1
  124. package/dist/services/logger/logger-context.js +5 -3
  125. package/dist/services/logger/logger-context.js.map +1 -1
  126. package/dist/services/logger/logger-http-utils.d.ts.map +1 -1
  127. package/dist/services/logger/logger-http-utils.js.map +1 -1
  128. package/dist/services/logger/logger.service.d.ts.map +1 -1
  129. package/dist/services/logger/logger.service.js +2 -1
  130. package/dist/services/logger/logger.service.js.map +1 -1
  131. package/dist/services/logger/trace-field-utils.d.ts.map +1 -1
  132. package/dist/services/logger/trace-field-utils.js.map +1 -1
  133. package/dist/services/logger/unified-logger.service.d.ts.map +1 -1
  134. package/dist/services/logger/unified-logger.service.js.map +1 -1
  135. package/dist/services/permission.service.d.ts.map +1 -1
  136. package/dist/services/permission.service.js +6 -2
  137. package/dist/services/permission.service.js.map +1 -1
  138. package/dist/services/role.service.d.ts.map +1 -1
  139. package/dist/services/role.service.js +6 -2
  140. package/dist/services/role.service.js.map +1 -1
  141. package/dist/services/token-validation.service.d.ts.map +1 -1
  142. package/dist/services/token-validation.service.js +4 -2
  143. package/dist/services/token-validation.service.js.map +1 -1
  144. package/dist/types/data-client.types.d.ts +25 -5
  145. package/dist/types/data-client.types.d.ts.map +1 -1
  146. package/dist/types/data-client.types.js.map +1 -1
  147. package/dist/types/errors.types.d.ts.map +1 -1
  148. package/dist/types/filter-schema.types.d.ts.map +1 -1
  149. package/dist/types/filter-schema.types.js.map +1 -1
  150. package/dist/utils/audit-log-queue.d.ts.map +1 -1
  151. package/dist/utils/audit-log-queue.js +3 -1
  152. package/dist/utils/audit-log-queue.js.map +1 -1
  153. package/dist/utils/browser-jwt-decoder.d.ts.map +1 -1
  154. package/dist/utils/browser-jwt-decoder.js +1 -4
  155. package/dist/utils/browser-jwt-decoder.js.map +1 -1
  156. package/dist/utils/client-token-manager.d.ts.map +1 -1
  157. package/dist/utils/client-token-manager.js +9 -3
  158. package/dist/utils/client-token-manager.js.map +1 -1
  159. package/dist/utils/config-loader.d.ts.map +1 -1
  160. package/dist/utils/config-loader.js +16 -9
  161. package/dist/utils/config-loader.js.map +1 -1
  162. package/dist/utils/controller-url-resolver.js +4 -4
  163. package/dist/utils/controller-url-resolver.js.map +1 -1
  164. package/dist/utils/data-client-audit.d.ts.map +1 -1
  165. package/dist/utils/data-client-audit.js +26 -6
  166. package/dist/utils/data-client-audit.js.map +1 -1
  167. package/dist/utils/data-client-auth.d.ts +7 -0
  168. package/dist/utils/data-client-auth.d.ts.map +1 -1
  169. package/dist/utils/data-client-auth.js +62 -3
  170. package/dist/utils/data-client-auth.js.map +1 -1
  171. package/dist/utils/data-client-auto-init.d.ts.map +1 -1
  172. package/dist/utils/data-client-auto-init.js +12 -5
  173. package/dist/utils/data-client-auto-init.js.map +1 -1
  174. package/dist/utils/data-client-cache.js +2 -2
  175. package/dist/utils/data-client-cache.js.map +1 -1
  176. package/dist/utils/data-client-core.d.ts +82 -0
  177. package/dist/utils/data-client-core.d.ts.map +1 -0
  178. package/dist/utils/data-client-core.js +303 -0
  179. package/dist/utils/data-client-core.js.map +1 -0
  180. package/dist/utils/data-client-init.d.ts.map +1 -1
  181. package/dist/utils/data-client-init.js +2 -1
  182. package/dist/utils/data-client-init.js.map +1 -1
  183. package/dist/utils/data-client-oauth.d.ts.map +1 -1
  184. package/dist/utils/data-client-oauth.js +5 -2
  185. package/dist/utils/data-client-oauth.js.map +1 -1
  186. package/dist/utils/data-client-redirect.d.ts.map +1 -1
  187. package/dist/utils/data-client-redirect.js +8 -8
  188. package/dist/utils/data-client-redirect.js.map +1 -1
  189. package/dist/utils/data-client-request.d.ts +4 -33
  190. package/dist/utils/data-client-request.d.ts.map +1 -1
  191. package/dist/utils/data-client-request.js +80 -43
  192. package/dist/utils/data-client-request.js.map +1 -1
  193. package/dist/utils/data-client-request.types.d.ts +68 -0
  194. package/dist/utils/data-client-request.types.d.ts.map +1 -0
  195. package/dist/utils/data-client-request.types.js +3 -0
  196. package/dist/utils/data-client-request.types.js.map +1 -0
  197. package/dist/utils/data-client-response.d.ts.map +1 -1
  198. package/dist/utils/data-client-response.js +23 -9
  199. package/dist/utils/data-client-response.js.map +1 -1
  200. package/dist/utils/data-client-utils.d.ts.map +1 -1
  201. package/dist/utils/data-client-utils.js +2 -1
  202. package/dist/utils/data-client-utils.js.map +1 -1
  203. package/dist/utils/data-client.d.ts +3 -40
  204. package/dist/utils/data-client.d.ts.map +1 -1
  205. package/dist/utils/data-client.js +21 -242
  206. package/dist/utils/data-client.js.map +1 -1
  207. package/dist/utils/data-masker.d.ts +28 -35
  208. package/dist/utils/data-masker.d.ts.map +1 -1
  209. package/dist/utils/data-masker.js +116 -80
  210. package/dist/utils/data-masker.js.map +1 -1
  211. package/dist/utils/encryption-error.d.ts +2 -2
  212. package/dist/utils/encryption-error.js +1 -1
  213. package/dist/utils/environment-token.d.ts.map +1 -1
  214. package/dist/utils/environment-token.js +6 -2
  215. package/dist/utils/environment-token.js.map +1 -1
  216. package/dist/utils/error-extractor.d.ts.map +1 -1
  217. package/dist/utils/error-extractor.js +4 -2
  218. package/dist/utils/error-extractor.js.map +1 -1
  219. package/dist/utils/errors.d.ts.map +1 -1
  220. package/dist/utils/errors.js +29 -7
  221. package/dist/utils/errors.js.map +1 -1
  222. package/dist/utils/filter-colon.utils.d.ts.map +1 -1
  223. package/dist/utils/filter-colon.utils.js.map +1 -1
  224. package/dist/utils/filter-schema-loader.d.ts.map +1 -1
  225. package/dist/utils/filter-schema-loader.js +3 -1
  226. package/dist/utils/filter-schema-loader.js.map +1 -1
  227. package/dist/utils/filter-schema.utils.d.ts.map +1 -1
  228. package/dist/utils/filter-schema.utils.js.map +1 -1
  229. package/dist/utils/filter.utils.d.ts.map +1 -1
  230. package/dist/utils/filter.utils.js +11 -4
  231. package/dist/utils/filter.utils.js.map +1 -1
  232. package/dist/utils/http-client-audit.d.ts.map +1 -1
  233. package/dist/utils/http-client-audit.js +51 -14
  234. package/dist/utils/http-client-audit.js.map +1 -1
  235. package/dist/utils/http-client-masking.d.ts.map +1 -1
  236. package/dist/utils/http-client-masking.js +6 -2
  237. package/dist/utils/http-client-masking.js.map +1 -1
  238. package/dist/utils/http-client-metadata.d.ts.map +1 -1
  239. package/dist/utils/http-client-metadata.js.map +1 -1
  240. package/dist/utils/http-client.d.ts +4 -0
  241. package/dist/utils/http-client.d.ts.map +1 -1
  242. package/dist/utils/http-client.js +135 -2
  243. package/dist/utils/http-client.js.map +1 -1
  244. package/dist/utils/http-error-handler.d.ts.map +1 -1
  245. package/dist/utils/http-error-handler.js +6 -3
  246. package/dist/utils/http-error-handler.js.map +1 -1
  247. package/dist/utils/http-response-validator.d.ts.map +1 -1
  248. package/dist/utils/http-response-validator.js +5 -2
  249. package/dist/utils/http-response-validator.js.map +1 -1
  250. package/dist/utils/internal-http-client.d.ts.map +1 -1
  251. package/dist/utils/internal-http-client.js +19 -6
  252. package/dist/utils/internal-http-client.js.map +1 -1
  253. package/dist/utils/logging-helpers.d.ts.map +1 -1
  254. package/dist/utils/logging-helpers.js +2 -1
  255. package/dist/utils/logging-helpers.js.map +1 -1
  256. package/dist/utils/sensitive-fields.config.json +27 -55
  257. package/dist/utils/sensitive-fields.loader.d.ts +27 -16
  258. package/dist/utils/sensitive-fields.loader.d.ts.map +1 -1
  259. package/dist/utils/sensitive-fields.loader.js +186 -139
  260. package/dist/utils/sensitive-fields.loader.js.map +1 -1
  261. package/dist/utils/token-utils.d.ts.map +1 -1
  262. package/dist/utils/token-utils.js +3 -3
  263. package/dist/utils/token-utils.js.map +1 -1
  264. package/dist/utils/user-token-refresh.d.ts +40 -0
  265. package/dist/utils/user-token-refresh.d.ts.map +1 -0
  266. package/dist/utils/user-token-refresh.js +258 -0
  267. package/dist/utils/user-token-refresh.js.map +1 -0
  268. package/package.json +18 -1
package/README.md CHANGED
@@ -138,7 +138,7 @@ REDIS_HOST=localhost
138
138
  ### Step 3: Use It
139
139
 
140
140
  ```typescript
141
- import { MisoClient, loadConfig } from '@aifabrix/miso-client';
141
+ import { MisoClient, loadConfig } from "@aifabrix/miso-client";
142
142
 
143
143
  const client = new MisoClient(loadConfig());
144
144
  await client.initialize();
@@ -157,7 +157,7 @@ For React, Vue, Angular, or other front-end applications, use **DataClient** - a
157
157
  **⚠️ Security Warning:** Never expose `clientSecret` in browser/client-side code. Use the Server-Provided Client Token Pattern instead.
158
158
 
159
159
  ```typescript
160
- import { DataClient } from '@aifabrix/miso-client';
160
+ import { DataClient } from "@aifabrix/miso-client";
161
161
 
162
162
  // Server provides client token (from initial page load or API endpoint)
163
163
  const initialClientToken = window.INITIAL_CLIENT_TOKEN; // From server
@@ -165,20 +165,20 @@ const tokenExpiresAt = window.INITIAL_CLIENT_TOKEN_EXPIRES_AT;
165
165
 
166
166
  // Browser-safe configuration WITHOUT clientSecret
167
167
  const dataClient = new DataClient({
168
- baseUrl: 'https://api.example.com',
168
+ baseUrl: "https://api.example.com",
169
169
  misoConfig: {
170
- controllerUrl: 'https://controller.aifabrix.ai',
171
- clientId: 'ctrl-dev-my-app',
170
+ controllerUrl: "https://controller.aifabrix.ai",
171
+ clientId: "ctrl-dev-my-app",
172
172
  // ❌ DO NOT include clientSecret in browser code
173
-
173
+
174
174
  // ✅ Use server-provided token
175
175
  clientToken: initialClientToken,
176
176
  clientTokenExpiresAt: tokenExpiresAt,
177
-
177
+
178
178
  // ✅ Refresh callback calls your server endpoint
179
179
  onClientTokenRefresh: async () => {
180
- const response = await fetch('/api/client-token', {
181
- credentials: 'include', // Include cookies for auth
180
+ const response = await fetch("/api/client-token", {
181
+ credentials: "include", // Include cookies for auth
182
182
  });
183
183
  return await response.json(); // { token: string, expiresIn: number }
184
184
  },
@@ -186,8 +186,8 @@ const dataClient = new DataClient({
186
186
  });
187
187
 
188
188
  // Make authenticated requests with automatic audit logging
189
- const users = await dataClient.get('/api/users');
190
- const newUser = await dataClient.post('/api/users', { name: 'John' });
189
+ const users = await dataClient.get("/api/users");
190
+ const newUser = await dataClient.post("/api/users", { name: "John" });
191
191
 
192
192
  // OAuth callback is automatically handled on initialization
193
193
  // Token is extracted from URL hash fragment (#token=...) and stored securely
@@ -195,15 +195,26 @@ const newUser = await dataClient.post('/api/users', { name: 'John' });
195
195
 
196
196
  // Token refresh callback (automatic refresh on 401 errors)
197
197
  const dataClientWithRefresh = new DataClient({
198
- baseUrl: 'https://api.example.com',
199
- misoConfig: { /* ... */ },
198
+ baseUrl: "https://api.example.com",
199
+ misoConfig: {
200
+ /* ... */
201
+ },
200
202
  onTokenRefresh: async () => {
201
203
  // Call your backend endpoint that handles refresh token securely
202
- const response = await fetch('/api/refresh-token', {
203
- credentials: 'include', // Include cookies for auth
204
+ const response = await fetch("/api/refresh-token", {
205
+ credentials: "include", // Include cookies for auth
204
206
  });
205
207
  return await response.json(); // { token: string, expiresIn: number }
206
208
  },
209
+
210
+ // Optional cookie-first restore callback (preferred for enterprise SSO)
211
+ onSessionRestore: async () => {
212
+ const response = await fetch("/api/session/restore", {
213
+ credentials: "include",
214
+ });
215
+ if (!response.ok) return null;
216
+ return await response.json(); // { token: string, expiresAt?: string }
217
+ },
207
218
  });
208
219
  ```
209
220
 
@@ -243,7 +254,7 @@ aifabrix run miso-controller
243
254
  **What happens:** Your app validates user tokens from Keycloak.
244
255
 
245
256
  ```typescript
246
- import { MisoClient, loadConfig } from '@aifabrix/miso-client';
257
+ import { MisoClient, loadConfig } from "@aifabrix/miso-client";
247
258
 
248
259
  // Create client (loads from .env automatically)
249
260
  const client = new MisoClient(loadConfig());
@@ -256,7 +267,7 @@ if (token) {
256
267
  const isValid = await client.validateToken(token);
257
268
  if (isValid) {
258
269
  const user = await client.getUser(token);
259
- console.log('User:', user);
270
+ console.log("User:", user);
260
271
  }
261
272
  }
262
273
  ```
@@ -284,7 +295,7 @@ const result = await client.exchangeUserToken(entraOrExternalToken);
284
295
  **What happens:** Check user roles to control access. Roles are cached in Redis for performance. Token validation is also cached (15-minute TTL) to reduce API calls.
285
296
 
286
297
  ```typescript
287
- import { MisoClient, loadConfig } from '@aifabrix/miso-client';
298
+ import { MisoClient, loadConfig } from "@aifabrix/miso-client";
288
299
 
289
300
  // Build on Step 3 - add Redis in .env file
290
301
  const client = new MisoClient(loadConfig());
@@ -293,7 +304,7 @@ await client.initialize();
293
304
  const token = client.getToken(req);
294
305
 
295
306
  // Check if user has role
296
- const isAdmin = await client.hasRole(token, 'admin');
307
+ const isAdmin = await client.hasRole(token, "admin");
297
308
  const roles = await client.getRoles(token);
298
309
 
299
310
  // Gate features by role
@@ -316,7 +327,7 @@ if (isAdmin) {
316
327
  **Basic Logging:**
317
328
 
318
329
  ```typescript
319
- import { MisoClient, loadConfig } from '@aifabrix/miso-client';
330
+ import { MisoClient, loadConfig } from "@aifabrix/miso-client";
320
331
 
321
332
  // Client token is automatically managed - no API key needed
322
333
  const client = new MisoClient(loadConfig());
@@ -326,21 +337,19 @@ const token = client.getToken(req);
326
337
  const user = await client.getUser(token);
327
338
 
328
339
  // Log messages
329
- await client.log.info('User accessed dashboard', { userId: user?.id });
330
- await client.log.error('Operation failed', { error: err.message });
331
- await client.log.warn('Unusual activity', { details: '...' });
340
+ await client.log.info("User accessed dashboard", { userId: user?.id });
341
+ await client.log.error("Operation failed", { error: err.message });
342
+ await client.log.warn("Unusual activity", { details: "..." });
332
343
  ```
333
344
 
334
345
  **Fluent API with Request Context (Express):**
335
346
 
336
347
  ```typescript
337
- import { Request } from 'express';
348
+ import { Request } from "express";
338
349
 
339
350
  // Auto-extract context from Express Request
340
- app.get('/api/users', async (req: Request, res) => {
341
- await client.log
342
- .withRequest(req)
343
- .info('Users list accessed');
351
+ app.get("/api/users", async (req: Request, res) => {
352
+ await client.log.withRequest(req).info("Users list accessed");
344
353
  // Automatically includes: IP, method, path, userAgent, correlationId, userId
345
354
  });
346
355
  ```
@@ -348,21 +357,21 @@ app.get('/api/users', async (req: Request, res) => {
348
357
  **Indexed Context for Fast Queries:**
349
358
 
350
359
  ```typescript
351
- import { extractLoggingContext } from '@aifabrix/miso-client';
360
+ import { extractLoggingContext } from "@aifabrix/miso-client";
352
361
 
353
362
  const logContext = extractLoggingContext({
354
363
  source: {
355
- key: 'datasource-1',
356
- displayName: 'PostgreSQL DB',
357
- externalSystem: { key: 'system-1', displayName: 'External API' }
364
+ key: "datasource-1",
365
+ displayName: "PostgreSQL DB",
366
+ externalSystem: { key: "system-1", displayName: "External API" },
358
367
  },
359
- record: { key: 'record-123', displayName: 'User Profile' }
368
+ record: { key: "record-123", displayName: "User Profile" },
360
369
  });
361
370
 
362
371
  await client.log
363
372
  .withIndexedContext(logContext)
364
373
  .withContext({ correlationId, userId })
365
- .error('Sync failed');
374
+ .error("Sync failed");
366
375
  ```
367
376
 
368
377
  **What happens to logs?** They're sent to the Miso Controller for centralized monitoring and analysis. Client token is automatically included. Indexed context fields enable fast database queries for observability and compliance.
@@ -372,11 +381,11 @@ await client.log
372
381
  ```typescript
373
382
  const client = new MisoClient({
374
383
  ...loadConfig(),
375
- emitEvents: true // Enable event emission mode
384
+ emitEvents: true, // Enable event emission mode
376
385
  });
377
386
 
378
387
  // Listen to log events
379
- client.log.on('log', (logEntry: LogEntry) => {
388
+ client.log.on("log", (logEntry: LogEntry) => {
380
389
  // Save directly to DB without HTTP
381
390
  db.saveLog(logEntry);
382
391
  });
@@ -393,7 +402,7 @@ client.log.on('log', (logEntry: LogEntry) => {
393
402
  **What happens:** Create audit trails for compliance and security monitoring.
394
403
 
395
404
  ```typescript
396
- import { MisoClient, loadConfig } from '@aifabrix/miso-client';
405
+ import { MisoClient, loadConfig } from "@aifabrix/miso-client";
397
406
 
398
407
  // Complete configuration (all in .env)
399
408
  const client = new MisoClient(loadConfig());
@@ -401,28 +410,28 @@ await client.initialize();
401
410
 
402
411
  const token = client.getToken(req);
403
412
  const isValid = await client.validateToken(token);
404
- const canEdit = await client.hasPermission(token, 'edit:content');
413
+ const canEdit = await client.hasPermission(token, "edit:content");
405
414
  const user = await client.getUser(token);
406
415
 
407
416
  // Audit: User actions
408
- await client.log.audit('user.login', 'authentication', {
417
+ await client.log.audit("user.login", "authentication", {
409
418
  userId: user?.id,
410
419
  ip: req.ip,
411
- userAgent: req.headers['user-agent'],
420
+ userAgent: req.headers["user-agent"],
412
421
  });
413
422
 
414
423
  // Audit: Content changes
415
- await client.log.audit('post.created', 'content', {
424
+ await client.log.audit("post.created", "content", {
416
425
  userId: user?.id,
417
- postId: 'post-123',
426
+ postId: "post-123",
418
427
  postTitle: req.body.title,
419
428
  });
420
429
 
421
430
  // Audit: Permission checks
422
- await client.log.audit('access.denied', 'authorization', {
431
+ await client.log.audit("access.denied", "authorization", {
423
432
  userId: user?.id,
424
- requiredPermission: 'edit:content',
425
- resource: 'posts',
433
+ requiredPermission: "edit:content",
434
+ resource: "posts",
426
435
  });
427
436
  ```
428
437
 
@@ -438,7 +447,7 @@ await client.log.audit('access.denied', 'authorization', {
438
447
  **What happens:** All HTTP requests are automatically audited with sensitive data masking for ISO 27001 compliance.
439
448
 
440
449
  ```typescript
441
- import { MisoClient, loadConfig } from '@aifabrix/miso-client';
450
+ import { MisoClient, loadConfig } from "@aifabrix/miso-client";
442
451
 
443
452
  const client = new MisoClient(loadConfig());
444
453
  await client.initialize();
@@ -477,10 +486,10 @@ The SDK automatically optimizes audit logging performance:
477
486
  const client = new MisoClient({
478
487
  ...loadConfig(),
479
488
  audit: {
480
- level: 'standard', // Light masking, good performance
489
+ level: "standard", // Light masking, good performance
481
490
  batchSize: 20, // Batch 20 logs per request
482
- maxResponseSize: 10000 // Truncate large responses
483
- }
491
+ maxResponseSize: 10000, // Truncate large responses
492
+ },
484
493
  });
485
494
  ```
486
495
 
@@ -511,23 +520,23 @@ const client = new MisoClient({
511
520
  **What happens:** Use encryption for sensitive data and generic caching for improved performance.
512
521
 
513
522
  ```typescript
514
- import { MisoClient, loadConfig } from '@aifabrix/miso-client';
523
+ import { MisoClient, loadConfig } from "@aifabrix/miso-client";
515
524
 
516
525
  const client = new MisoClient(loadConfig());
517
526
  await client.initialize();
518
527
 
519
528
  // Encryption (requires ENCRYPTION_KEY in .env or config.encryptionKey)
520
529
  if (client.encryption) {
521
- const encrypted = client.encryption.encrypt('sensitive-data');
530
+ const encrypted = client.encryption.encrypt("sensitive-data");
522
531
  const decrypted = client.encryption.decrypt(encrypted);
523
- console.log('Decrypted:', decrypted);
532
+ console.log("Decrypted:", decrypted);
524
533
  }
525
534
 
526
535
  // Generic caching (automatically uses Redis if available, falls back to memory)
527
- await client.cache.set('user:123', { name: 'John', age: 30 }, 600); // 10 minutes TTL
528
- const user = await client.cache.get<{ name: string; age: number }>('user:123');
536
+ await client.cache.set("user:123", { name: "John", age: 30 }, 600); // 10 minutes TTL
537
+ const user = await client.cache.get<{ name: string; age: number }>("user:123");
529
538
  if (user) {
530
- console.log('Cached user:', user);
539
+ console.log("Cached user:", user);
531
540
  }
532
541
  ```
533
542
 
@@ -548,47 +557,50 @@ ENCRYPTION_KEY=your-32-byte-encryption-key
548
557
  **What happens:** Use reusable utilities for pagination, filtering, and sorting following enterprise application best practices and industry standards (ISO 27001 compliant).
549
558
 
550
559
  ```typescript
551
- import {
552
- FilterBuilder,
553
- parsePaginationParams,
560
+ import {
561
+ FilterBuilder,
562
+ parsePaginationParams,
554
563
  parseSortParams,
555
564
  buildQueryString,
556
- createPaginatedListResponse
557
- } from '@aifabrix/miso-client';
565
+ createPaginatedListResponse,
566
+ } from "@aifabrix/miso-client";
558
567
 
559
568
  const client = new MisoClient(loadConfig());
560
569
  await client.initialize();
561
570
 
562
571
  // Dynamic filter building (FilterBuilder)
563
572
  const filterBuilder = new FilterBuilder()
564
- .add('status', 'eq', 'active')
565
- .add('region', 'in', ['eu', 'us'])
566
- .add('created_at', 'gte', '2024-01-01');
573
+ .add("status", "eq", "active")
574
+ .add("region", "in", ["eu", "us"])
575
+ .add("created_at", "gte", "2024-01-01");
567
576
 
568
577
  const queryString = filterBuilder.toQueryString();
569
578
  // Returns: "filter=status:eq:active&filter=region:in:eu,us&filter=created_at:gte:2024-01-01"
570
579
 
571
580
  // Parse pagination from query string
572
- const { currentPage, pageSize } = parsePaginationParams({ page: '1', page_size: '25' });
581
+ const { currentPage, pageSize } = parsePaginationParams({
582
+ page: "1",
583
+ page_size: "25",
584
+ });
573
585
 
574
586
  // Parse sort from query string
575
- const sortOptions = parseSortParams({ sort: '-updated_at' });
587
+ const sortOptions = parseSortParams({ sort: "-updated_at" });
576
588
 
577
589
  // Build complete query
578
590
  const completeQuery = buildQueryString({
579
591
  filters: filterBuilder.build(),
580
- sort: ['-updated_at'],
592
+ sort: ["-updated_at"],
581
593
  page: currentPage,
582
- pageSize: pageSize
594
+ pageSize: pageSize,
583
595
  });
584
596
 
585
597
  // Create paginated response
586
598
  const response = createPaginatedListResponse(
587
599
  items,
588
600
  120, // totalItems
589
- 1, // currentPage
590
- 25, // pageSize
591
- 'application' // type
601
+ 1, // currentPage
602
+ 25, // pageSize
603
+ "application", // type
592
604
  );
593
605
  ```
594
606
 
@@ -615,14 +627,14 @@ pnpm add @aifabrix/miso-client express
615
627
  #### Quick Start
616
628
 
617
629
  ```typescript
618
- import express from 'express';
619
- import {
630
+ import express from "express";
631
+ import {
620
632
  injectResponseHelpers,
621
633
  asyncHandler,
622
634
  ValidationHelper,
623
635
  setErrorLogger,
624
- EncryptionUtil
625
- } from '@aifabrix/miso-client';
636
+ EncryptionUtil,
637
+ } from "@aifabrix/miso-client";
626
638
 
627
639
  const app = express();
628
640
 
@@ -633,18 +645,21 @@ app.use(injectResponseHelpers);
633
645
  setErrorLogger({
634
646
  async logError(message, options) {
635
647
  console.error(message, options);
636
- }
648
+ },
637
649
  });
638
650
 
639
651
  // Use asyncHandler for automatic error handling
640
- app.get('/users/:id', asyncHandler(async (req, res) => {
641
- const user = await ValidationHelper.findOrFail(
642
- () => db.user.findById(req.params.id),
643
- 'User',
644
- req.params.id
645
- );
646
- res.success(user, 'User retrieved');
647
- }));
652
+ app.get(
653
+ "/users/:id",
654
+ asyncHandler(async (req, res) => {
655
+ const user = await ValidationHelper.findOrFail(
656
+ () => db.user.findById(req.params.id),
657
+ "User",
658
+ req.params.id,
659
+ );
660
+ res.success(user, "User retrieved");
661
+ }),
662
+ );
648
663
  ```
649
664
 
650
665
  #### Response Helpers
@@ -652,27 +667,27 @@ app.get('/users/:id', asyncHandler(async (req, res) => {
652
667
  Standardized API response formatting:
653
668
 
654
669
  ```typescript
655
- import { ResponseHelper } from '@aifabrix/miso-client';
670
+ import { ResponseHelper } from "@aifabrix/miso-client";
656
671
 
657
672
  // Success response (200)
658
- return ResponseHelper.success(res, data, 'Success message');
673
+ return ResponseHelper.success(res, data, "Success message");
659
674
 
660
675
  // Created response (201)
661
- return ResponseHelper.created(res, newResource, 'Resource created');
676
+ return ResponseHelper.created(res, newResource, "Resource created");
662
677
 
663
678
  // Paginated response
664
679
  return ResponseHelper.paginated(res, items, {
665
680
  currentPage: 1,
666
681
  pageSize: 20,
667
682
  totalItems: 100,
668
- type: 'user'
683
+ type: "user",
669
684
  });
670
685
 
671
686
  // No content (204)
672
687
  return ResponseHelper.noContent(res);
673
688
 
674
689
  // Accepted (202)
675
- return ResponseHelper.accepted(res, { jobId: '123' }, 'Job queued');
690
+ return ResponseHelper.accepted(res, { jobId: "123" }, "Job queued");
676
691
 
677
692
  // Or use injected methods on res object
678
693
  res.success(user);
@@ -687,19 +702,25 @@ res.accepted(data);
687
702
  Eliminates try-catch blocks in route handlers:
688
703
 
689
704
  ```typescript
690
- import { asyncHandler } from '@aifabrix/miso-client';
705
+ import { asyncHandler } from "@aifabrix/miso-client";
691
706
 
692
707
  // Automatic error handling
693
- router.post('/users', asyncHandler(async (req, res) => {
694
- const user = await userService.create(req.body);
695
- res.created(user, 'User created');
696
- }));
708
+ router.post(
709
+ "/users",
710
+ asyncHandler(async (req, res) => {
711
+ const user = await userService.create(req.body);
712
+ res.created(user, "User created");
713
+ }),
714
+ );
697
715
 
698
716
  // Named variant for better error messages
699
- router.get('/users/:id', asyncHandlerNamed('getUser', async (req, res) => {
700
- const user = await userService.findById(req.params.id);
701
- res.success(user);
702
- }));
717
+ router.get(
718
+ "/users/:id",
719
+ asyncHandlerNamed("getUser", async (req, res) => {
720
+ const user = await userService.findById(req.params.id);
721
+ res.success(user);
722
+ }),
723
+ );
703
724
  ```
704
725
 
705
726
  #### Validation Helper
@@ -707,30 +728,30 @@ router.get('/users/:id', asyncHandlerNamed('getUser', async (req, res) => {
707
728
  Common validation patterns:
708
729
 
709
730
  ```typescript
710
- import { ValidationHelper } from '@aifabrix/miso-client';
731
+ import { ValidationHelper } from "@aifabrix/miso-client";
711
732
 
712
733
  // Find or throw 404
713
734
  const user = await ValidationHelper.findOrFail(
714
735
  () => prisma.user.findUnique({ where: { id } }),
715
- 'User',
716
- id
736
+ "User",
737
+ id,
717
738
  );
718
739
 
719
740
  // Ensure doesn't exist or throw 409
720
741
  await ValidationHelper.ensureNotExists(
721
742
  () => prisma.user.findUnique({ where: { email } }),
722
- 'User',
723
- email
743
+ "User",
744
+ email,
724
745
  );
725
746
 
726
747
  // Check ownership or admin role
727
748
  ValidationHelper.ensureOwnershipOrAdmin(req, resourceUserId);
728
749
 
729
750
  // Validate required fields
730
- ValidationHelper.validateRequiredFields(data, ['name', 'email'], 'User');
751
+ ValidationHelper.validateRequiredFields(data, ["name", "email"], "User");
731
752
 
732
753
  // Validate string length
733
- ValidationHelper.validateStringLength(password, 'password', 8, 128);
754
+ ValidationHelper.validateStringLength(password, "password", 8, 128);
734
755
  ```
735
756
 
736
757
  #### Error Handling
@@ -738,13 +759,13 @@ ValidationHelper.validateStringLength(password, 'password', 8, 128);
738
759
  RFC 7807 compliant error responses with optional custom logger:
739
760
 
740
761
  ```typescript
741
- import { setErrorLogger } from '@aifabrix/miso-client';
762
+ import { setErrorLogger } from "@aifabrix/miso-client";
742
763
 
743
764
  // Configure during app initialization
744
765
  setErrorLogger({
745
766
  async logError(message, options) {
746
767
  await yourLogger.error(message, options);
747
- }
768
+ },
748
769
  });
749
770
 
750
771
  // Errors are automatically handled by asyncHandler
@@ -756,20 +777,20 @@ setErrorLogger({
756
777
  AES-256-GCM encryption for sensitive data:
757
778
 
758
779
  ```typescript
759
- import { EncryptionUtil } from '@aifabrix/miso-client';
780
+ import { EncryptionUtil } from "@aifabrix/miso-client";
760
781
 
761
782
  // Initialize once at startup (uses ENCRYPTION_KEY env var)
762
783
  EncryptionUtil.initialize();
763
784
 
764
785
  // Encrypt sensitive data
765
- const encrypted = EncryptionUtil.encrypt('sensitive-data');
786
+ const encrypted = EncryptionUtil.encrypt("sensitive-data");
766
787
 
767
788
  // Decrypt
768
789
  const decrypted = EncryptionUtil.decrypt(encrypted);
769
790
 
770
791
  // Generate new key (for setup)
771
792
  const key = EncryptionUtil.generateKey();
772
- console.log('ENCRYPTION_KEY=' + key);
793
+ console.log("ENCRYPTION_KEY=" + key);
773
794
  ```
774
795
 
775
796
  #### Sort Utilities
@@ -777,21 +798,21 @@ console.log('ENCRYPTION_KEY=' + key);
777
798
  Parse and apply sorting for API queries:
778
799
 
779
800
  ```typescript
780
- import { parseSortParams, applySorting } from '@aifabrix/miso-client';
801
+ import { parseSortParams, applySorting } from "@aifabrix/miso-client";
781
802
 
782
803
  // Parse sort query parameters
783
- const sortOptions = parseSortParams({ sort: ['-createdAt', 'name'] });
804
+ const sortOptions = parseSortParams({ sort: ["-createdAt", "name"] });
784
805
  // Returns: [{ field: 'createdAt', order: 'desc' }, { field: 'name', order: 'asc' }]
785
806
 
786
807
  // Apply sorting to in-memory data (client-side)
787
808
  const sortedData = applySorting(users, sortOptions);
788
809
 
789
810
  // Or parse from Express request query
790
- app.get('/users', (req, res) => {
811
+ app.get("/users", (req, res) => {
791
812
  const sortOptions = parseSortParams(req.query);
792
813
  // Use sortOptions to build database query with Prisma/SQL
793
814
  const users = await prisma.user.findMany({
794
- orderBy: sortOptions.map(s => ({ [s.field]: s.order }))
815
+ orderBy: sortOptions.map((s) => ({ [s.field]: s.order })),
795
816
  });
796
817
  res.success(users);
797
818
  });
@@ -809,7 +830,7 @@ app.get('/users', (req, res) => {
809
830
  **What happens:** Configure flexible authentication methods with priority-based fallback for advanced authentication scenarios.
810
831
 
811
832
  ```typescript
812
- import { MisoClient, loadConfig } from '@aifabrix/miso-client';
833
+ import { MisoClient, loadConfig } from "@aifabrix/miso-client";
813
834
 
814
835
  const client = new MisoClient(loadConfig());
815
836
  await client.initialize();
@@ -818,17 +839,21 @@ await client.initialize();
818
839
  const client = new MisoClient({
819
840
  ...loadConfig(),
820
841
  authStrategy: {
821
- methods: ['bearer', 'client-token', 'client-credentials']
822
- }
842
+ methods: ["bearer", "client-token", "client-credentials"],
843
+ },
823
844
  });
824
845
 
825
846
  // Per-request strategy override
826
- const strategy = client.createAuthStrategy(['bearer', 'api-key'], 'token-123', 'api-key-456');
847
+ const strategy = client.createAuthStrategy(
848
+ ["bearer", "api-key"],
849
+ "token-123",
850
+ "api-key-456",
851
+ );
827
852
  await client.getRoles(token, strategy);
828
853
 
829
854
  // Using requestWithAuthStrategy for custom requests
830
- await client.requestWithAuthStrategy('GET', '/api/data', {
831
- methods: ['client-token']
855
+ await client.requestWithAuthStrategy("GET", "/api/data", {
856
+ methods: ["client-token"],
832
857
  });
833
858
 
834
859
  // Get default strategy
@@ -863,27 +888,27 @@ MISO_API_KEY=optional-api-key
863
888
 
864
889
  ```typescript
865
890
  interface MisoClientConfig {
866
- controllerUrl: string; // Required: Controller URL
867
- clientId: string; // Required: Client ID (e.g., 'ctrl-dev-my-app')
868
- clientSecret: string; // Required: Client secret
869
- redis?: RedisConfig; // Optional: For caching
870
- logLevel?: 'debug' | 'info' | 'warn' | 'error';
871
- encryptionKey?: string; // Optional: Encryption key (or use ENCRYPTION_KEY env var)
891
+ controllerUrl: string; // Required: Controller URL
892
+ clientId: string; // Required: Client ID (e.g., 'ctrl-dev-my-app')
893
+ clientSecret: string; // Required: Client secret
894
+ redis?: RedisConfig; // Optional: For caching
895
+ logLevel?: "debug" | "info" | "warn" | "error";
896
+ encryptionKey?: string; // Optional: Encryption key (or use ENCRYPTION_KEY env var)
872
897
  sensitiveFieldsConfig?: string; // Optional: Path to ISO 27001 sensitive fields config JSON
873
- emitEvents?: boolean; // Optional: Emit log events instead of HTTP/Redis (for direct SDK embedding)
898
+ emitEvents?: boolean; // Optional: Emit log events instead of HTTP/Redis (for direct SDK embedding)
874
899
  authStrategy?: AuthStrategy; // Optional: Default authentication strategy
875
900
  cache?: {
876
- roleTTL?: number; // Role cache TTL (default: 900s)
877
- permissionTTL?: number; // Permission cache TTL (default: 900s)
901
+ roleTTL?: number; // Role cache TTL (default: 900s)
902
+ permissionTTL?: number; // Permission cache TTL (default: 900s)
878
903
  tokenValidationTTL?: number; // Token validation cache TTL (default: 900s)
879
904
  };
880
- audit?: AuditConfig; // Optional: Audit logging configuration
905
+ audit?: AuditConfig; // Optional: Audit logging configuration
881
906
  }
882
907
 
883
908
  interface AuthStrategy {
884
- methods: ('bearer' | 'client-token' | 'client-credentials' | 'api-key')[];
885
- bearerToken?: string; // Optional: Bearer token for bearer authentication
886
- apiKey?: string; // Optional: API key for api-key authentication
909
+ methods: ("bearer" | "client-token" | "client-credentials" | "api-key")[];
910
+ bearerToken?: string; // Optional: Bearer token for bearer authentication
911
+ apiKey?: string; // Optional: API key for api-key authentication
887
912
  }
888
913
  ```
889
914
 
@@ -972,15 +997,15 @@ app.use(async (req, res, next) => {
972
997
  **Protect routes by role:**
973
998
 
974
999
  ```typescript
975
- app.get('/admin', async (req, res) => {
1000
+ app.get("/admin", async (req, res) => {
976
1001
  const token = client.getToken(req);
977
- if (!token) return res.status(401).json({ error: 'Unauthorized' });
978
-
979
- const isAdmin = await client.hasRole(token, 'admin');
980
- if (!isAdmin) return res.status(403).json({ error: 'Forbidden' });
981
-
1002
+ if (!token) return res.status(401).json({ error: "Unauthorized" });
1003
+
1004
+ const isAdmin = await client.hasRole(token, "admin");
1005
+ if (!isAdmin) return res.status(403).json({ error: "Forbidden" });
1006
+
982
1007
  // Admin only code
983
- res.json({ message: 'Admin panel' });
1008
+ res.json({ message: "Admin panel" });
984
1009
  });
985
1010
  ```
986
1011