@axova/shared 1.0.2 → 1.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 (68) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.js +2 -0
  3. package/dist/lib/db.d.ts +34406 -1
  4. package/dist/lib/db.js +21 -1
  5. package/dist/middleware/storeOwnership.js +22 -3
  6. package/dist/middleware/storeValidationMiddleware.js +16 -39
  7. package/dist/schemas/admin/admin-schema.d.ts +2 -2
  8. package/dist/schemas/ai-moderation/ai-moderation-schema.d.ts +6 -6
  9. package/dist/schemas/common/common-schemas.d.ts +71 -71
  10. package/dist/schemas/compliance/compliance-schema.d.ts +20 -20
  11. package/dist/schemas/compliance/kyc-schema.d.ts +8 -8
  12. package/dist/schemas/customer/customer-schema.d.ts +18 -18
  13. package/dist/schemas/index.d.ts +28 -0
  14. package/dist/schemas/index.js +134 -3
  15. package/dist/schemas/inventory/inventory-tables.d.ts +188 -188
  16. package/dist/schemas/inventory/lot-tables.d.ts +102 -102
  17. package/dist/schemas/order/cart-schema.d.ts +2865 -0
  18. package/dist/schemas/order/cart-schema.js +396 -0
  19. package/dist/schemas/order/order-schema.d.ts +19 -19
  20. package/dist/schemas/order/order-schema.js +8 -2
  21. package/dist/schemas/product/discount-schema.d.ts +3 -3
  22. package/dist/schemas/product/product-schema.d.ts +3 -3
  23. package/dist/schemas/store/store-audit-schema.d.ts +20 -20
  24. package/dist/schemas/store/store-schema.d.ts +182 -2
  25. package/dist/schemas/store/store-schema.js +19 -0
  26. package/dist/schemas/store/storefront-config-schema.d.ts +434 -823
  27. package/dist/schemas/store/storefront-config-schema.js +35 -62
  28. package/dist/utils/subdomain.d.ts +1 -1
  29. package/dist/utils/subdomain.js +10 -15
  30. package/package.json +1 -1
  31. package/src/configs/index.ts +654 -654
  32. package/src/index.ts +26 -23
  33. package/src/interfaces/customer-events.ts +106 -106
  34. package/src/interfaces/inventory-events.ts +545 -545
  35. package/src/interfaces/inventory-types.ts +1004 -1004
  36. package/src/interfaces/order-events.ts +381 -381
  37. package/src/lib/auditLogger.ts +1117 -1117
  38. package/src/lib/authOrganization.ts +153 -153
  39. package/src/lib/db.ts +84 -64
  40. package/src/middleware/serviceAuth.ts +328 -328
  41. package/src/middleware/storeOwnership.ts +199 -181
  42. package/src/middleware/storeValidationMiddleware.ts +17 -50
  43. package/src/middleware/userAuth.ts +248 -248
  44. package/src/schemas/admin/admin-schema.ts +208 -208
  45. package/src/schemas/ai-moderation/ai-moderation-schema.ts +180 -180
  46. package/src/schemas/common/common-schemas.ts +108 -108
  47. package/src/schemas/compliance/compliance-schema.ts +927 -0
  48. package/src/schemas/compliance/kyc-schema.ts +649 -0
  49. package/src/schemas/customer/customer-schema.ts +576 -0
  50. package/src/schemas/index.ts +202 -3
  51. package/src/schemas/inventory/inventory-tables.ts +1927 -0
  52. package/src/schemas/inventory/lot-tables.ts +799 -0
  53. package/src/schemas/order/cart-schema.ts +652 -0
  54. package/src/schemas/order/order-schema.ts +1406 -0
  55. package/src/schemas/product/discount-relations.ts +44 -0
  56. package/src/schemas/product/discount-schema.ts +464 -0
  57. package/src/schemas/product/product-relations.ts +187 -0
  58. package/src/schemas/product/product-schema.ts +955 -0
  59. package/src/schemas/store/ethiopian_business_api.md.resolved +212 -0
  60. package/src/schemas/store/store-audit-schema.ts +1257 -0
  61. package/src/schemas/store/store-schema.ts +682 -0
  62. package/src/schemas/store/store-settings-schema.ts +231 -0
  63. package/src/schemas/store/storefront-config-schema.ts +382 -0
  64. package/src/schemas/types.ts +67 -67
  65. package/src/types/events.ts +646 -646
  66. package/src/utils/errorHandler.ts +44 -44
  67. package/src/utils/subdomain.ts +19 -23
  68. package/tsconfig.json +21 -21
@@ -1,654 +1,654 @@
1
- // =============================================================================
2
- // AXOVA SHARED CONFIGURATIONS
3
- // Service-specific configuration profiles for the Axova platform
4
- // =============================================================================
5
-
6
- import { getKafkaConfigFromEnv } from "../events/kafka";
7
- import { getServiceAuthConfigFromEnv } from "../middleware/serviceAuth";
8
-
9
- // =============================================================================
10
- // Base Configuration Interfaces
11
- // =============================================================================
12
-
13
- export interface BaseServiceConfig {
14
- serviceName: string;
15
- port: number;
16
- host: string;
17
- environment: "development" | "staging" | "production";
18
- cors: {
19
- origins: string[];
20
- credentials: boolean;
21
- };
22
- rateLimiting: {
23
- max: number;
24
- timeWindow: string;
25
- };
26
- }
27
-
28
- export interface DatabaseConfig {
29
- url: string;
30
- host: string;
31
- port: number;
32
- user: string;
33
- password: string;
34
- database: string;
35
- ssl: boolean;
36
- poolSize: number;
37
- }
38
-
39
- export interface KafkaServiceConfig {
40
- enabled: boolean;
41
- clientId: string;
42
- groupId: string;
43
- topics: string[];
44
- autoCommit: boolean;
45
- }
46
-
47
- export interface RedisConfig {
48
- host: string;
49
- port: number;
50
- password?: string;
51
- db: number;
52
- ttl: number;
53
- }
54
-
55
- export interface AuditConfig {
56
- enabled: boolean;
57
- level: "minimal" | "standard" | "comprehensive";
58
- bufferSize: number;
59
- flushInterval: number;
60
- sensitiveFieldMasking: boolean;
61
- }
62
-
63
- export interface ServiceProfile {
64
- base: BaseServiceConfig;
65
- database: DatabaseConfig;
66
- kafka: KafkaServiceConfig;
67
- redis?: RedisConfig;
68
- audit: AuditConfig;
69
- features: Record<string, boolean>;
70
- customConfig?: Record<string, unknown>;
71
- }
72
-
73
- // =============================================================================
74
- // Service-Specific Configurations
75
- // =============================================================================
76
-
77
- export const STORE_SERVICE_PROFILE: ServiceProfile = {
78
- base: {
79
- serviceName: "store-service",
80
- port: Number(process.env.PORT) || 3001,
81
- host: process.env.HOST || "0.0.0.0",
82
- environment: (process.env.NODE_ENV as any) || "development",
83
- cors: {
84
- origins: process.env.CORS_ORIGINS?.split(",") || [
85
- "http://localhost:3000",
86
- ],
87
- credentials: true,
88
- },
89
- rateLimiting: {
90
- max: Number(process.env.RATE_LIMIT_MAX) || 100,
91
- timeWindow: process.env.RATE_LIMIT_WINDOW || "1 minute",
92
- },
93
- },
94
- database: {
95
- url:
96
- process.env.DATABASE_URL ||
97
- "postgresql://postgres:password@localhost:5432/axova_store_db",
98
- host: process.env.POSTGRES_HOST || "localhost",
99
- port: Number(process.env.POSTGRES_PORT) || 5432,
100
- user: process.env.POSTGRES_USER || "postgres",
101
- password: process.env.POSTGRES_PASSWORD || "password",
102
- database: process.env.POSTGRES_DB || "axova_store_db",
103
- ssl: process.env.DB_SSL === "true",
104
- poolSize: Number(process.env.DB_POOL_SIZE) || 10,
105
- },
106
- kafka: {
107
- enabled: process.env.KAFKA_ENABLED !== "false",
108
- clientId: process.env.KAFKA_CLIENT_ID || "store-service",
109
- groupId: process.env.KAFKA_GROUP_ID || "store-service-group",
110
- topics: [
111
- "store.created",
112
- "store.updated",
113
- "store.deleted",
114
- "store.business.updated",
115
- "store.social.updated",
116
- "store.blog.created",
117
- "store.blog.updated",
118
- "store.contact.updated",
119
- ],
120
- autoCommit: process.env.KAFKA_AUTO_COMMIT !== "false",
121
- },
122
- redis: {
123
- host: process.env.REDIS_HOST || "localhost",
124
- port: Number(process.env.REDIS_PORT) || 6379,
125
- password: process.env.REDIS_PASSWORD,
126
- db: Number(process.env.REDIS_DB) || 0,
127
- ttl: Number(process.env.REDIS_TTL) || 3600,
128
- },
129
- audit: {
130
- enabled: process.env.AUDIT_ENABLED !== "false",
131
- level: (process.env.AUDIT_LEVEL as any) || "comprehensive",
132
- bufferSize: Number(process.env.AUDIT_BUFFER_SIZE) || 100,
133
- flushInterval: Number(process.env.AUDIT_FLUSH_INTERVAL) || 5000,
134
- sensitiveFieldMasking: process.env.AUDIT_MASK_SENSITIVE !== "false",
135
- },
136
- features: {
137
- realTimeSync: process.env.ENABLE_REAL_TIME_SYNC !== "false",
138
- auditLogging: process.env.ENABLE_AUDIT_LOGGING !== "false",
139
- advancedAnalytics: process.env.ENABLE_ADVANCED_ANALYTICS === "true",
140
- multiTenant: true,
141
- storeCustomization: true,
142
- blogManagement: true,
143
- socialProfiles: true,
144
- businessDetails: true,
145
- contactManagement: true,
146
- },
147
- customConfig: {
148
- storeDomain: process.env.STORE_DOMAIN || "myaxova.store",
149
- maxStoresPerUser: Number(process.env.MAX_STORES_PER_USER) || 5,
150
- storeCustomizationLimits: {
151
- maxThemes: 10,
152
- maxPages: 50,
153
- maxProducts: 10000,
154
- },
155
- },
156
- };
157
-
158
- export const COMPLIANCE_SERVICE_PROFILE: ServiceProfile = {
159
- base: {
160
- serviceName: "compliance-service",
161
- port: Number(process.env.PORT) || 3002,
162
- host: process.env.HOST || "0.0.0.0",
163
- environment: (process.env.NODE_ENV as any) || "development",
164
- cors: {
165
- origins: process.env.CORS_ORIGINS?.split(",") || [
166
- "http://localhost:3000",
167
- ],
168
- credentials: true,
169
- },
170
- rateLimiting: {
171
- max: Number(process.env.RATE_LIMIT_MAX) || 200,
172
- timeWindow: process.env.RATE_LIMIT_WINDOW || "1 minute",
173
- },
174
- },
175
- database: {
176
- url:
177
- process.env.DATABASE_URL ||
178
- "postgresql://postgres:password@localhost:5432/axova_compliance_db",
179
- host: process.env.POSTGRES_HOST || "localhost",
180
- port: Number(process.env.POSTGRES_PORT) || 5432,
181
- user: process.env.POSTGRES_USER || "postgres",
182
- password: process.env.POSTGRES_PASSWORD || "password",
183
- database: process.env.POSTGRES_DB || "axova_compliance_db",
184
- ssl: process.env.DB_SSL === "true",
185
- poolSize: Number(process.env.DB_POOL_SIZE) || 15,
186
- },
187
- kafka: {
188
- enabled: process.env.KAFKA_ENABLED !== "false",
189
- clientId: process.env.KAFKA_CLIENT_ID || "compliance-service",
190
- groupId: process.env.KAFKA_GROUP_ID || "compliance-service-group",
191
- topics: [
192
- "store.created",
193
- "store.updated",
194
- "compliance.violation.detected",
195
- "compliance.violation.resolved",
196
- "appeal.submitted",
197
- "appeal.reviewed",
198
- "store.suspended",
199
- "store.unbanned",
200
- "audit.logged",
201
- ],
202
- autoCommit: process.env.KAFKA_AUTO_COMMIT !== "false",
203
- },
204
- audit: {
205
- enabled: process.env.AUDIT_ENABLED !== "false",
206
- level: (process.env.AUDIT_LEVEL as any) || "comprehensive",
207
- bufferSize: Number(process.env.AUDIT_BUFFER_SIZE) || 200,
208
- flushInterval: Number(process.env.AUDIT_FLUSH_INTERVAL) || 3000,
209
- sensitiveFieldMasking: process.env.AUDIT_MASK_SENSITIVE !== "false",
210
- },
211
- features: {
212
- realTimeMonitoring: true,
213
- automaticViolationDetection: true,
214
- appealManagement: true,
215
- riskAssessment: true,
216
- complianceReporting: true,
217
- auditTrails: true,
218
- escalationMatrix: true,
219
- mlBasedDetection: process.env.ENABLE_ML_DETECTION === "true",
220
- },
221
- customConfig: {
222
- violationThresholds: {
223
- low: 3,
224
- medium: 5,
225
- high: 2,
226
- critical: 1,
227
- },
228
- appealProcessing: {
229
- autoReviewEnabled: process.env.AUTO_REVIEW_APPEALS === "true",
230
- maxAppealTime: Number(process.env.MAX_APPEAL_TIME) || 72, // hours
231
- escalationLevels: 3,
232
- },
233
- suspensionRules: {
234
- automaticSuspension: process.env.AUTO_SUSPEND === "true",
235
- gracePeriod: Number(process.env.SUSPENSION_GRACE_PERIOD) || 24, // hours
236
- },
237
- },
238
- };
239
-
240
- export const PRODUCT_SERVICE_PROFILE: ServiceProfile = {
241
- base: {
242
- serviceName: "product-service",
243
- port: Number(process.env.PORT) || 3003,
244
- host: process.env.HOST || "0.0.0.0",
245
- environment: (process.env.NODE_ENV as any) || "development",
246
- cors: {
247
- origins: process.env.CORS_ORIGINS?.split(",") || [
248
- "http://localhost:3000",
249
- ],
250
- credentials: true,
251
- },
252
- rateLimiting: {
253
- max: Number(process.env.RATE_LIMIT_MAX) || 500,
254
- timeWindow: process.env.RATE_LIMIT_WINDOW || "1 minute",
255
- },
256
- },
257
- database: {
258
- url:
259
- process.env.DATABASE_URL ||
260
- "postgresql://postgres:password@localhost:5432/axova_product_db",
261
- host: process.env.POSTGRES_HOST || "localhost",
262
- port: Number(process.env.POSTGRES_PORT) || 5432,
263
- user: process.env.POSTGRES_USER || "postgres",
264
- password: process.env.POSTGRES_PASSWORD || "password",
265
- database: process.env.POSTGRES_DB || "axova_product_db",
266
- ssl: process.env.DB_SSL === "true",
267
- poolSize: Number(process.env.DB_POOL_SIZE) || 20,
268
- },
269
- kafka: {
270
- enabled: process.env.KAFKA_ENABLED !== "false",
271
- clientId: process.env.KAFKA_CLIENT_ID || "product-service",
272
- groupId: process.env.KAFKA_GROUP_ID || "product-service-group",
273
- topics: [
274
- "product.created",
275
- "product.updated",
276
- "product.deleted",
277
- "variant.created",
278
- "variant.updated",
279
- "variant.deleted",
280
- "collection.created",
281
- "collection.updated",
282
- "collection.deleted",
283
- "inventory.updated",
284
- ],
285
- autoCommit: process.env.KAFKA_AUTO_COMMIT !== "false",
286
- },
287
- redis: {
288
- host: process.env.REDIS_HOST || "localhost",
289
- port: Number(process.env.REDIS_PORT) || 6379,
290
- password: process.env.REDIS_PASSWORD,
291
- db: Number(process.env.REDIS_DB) || 1,
292
- ttl: Number(process.env.REDIS_TTL) || 7200,
293
- },
294
- audit: {
295
- enabled: process.env.AUDIT_ENABLED !== "false",
296
- level: (process.env.AUDIT_LEVEL as any) || "standard",
297
- bufferSize: Number(process.env.AUDIT_BUFFER_SIZE) || 150,
298
- flushInterval: Number(process.env.AUDIT_FLUSH_INTERVAL) || 4000,
299
- sensitiveFieldMasking: process.env.AUDIT_MASK_SENSITIVE !== "false",
300
- },
301
- features: {
302
- searchOptimization: true,
303
- imageProcessing: true,
304
- variantManagement: true,
305
- collectionManagement: true,
306
- bulkOperations: true,
307
- seoOptimization: true,
308
- analyticsIntegration: true,
309
- recommendationEngine: process.env.ENABLE_RECOMMENDATIONS === "true",
310
- },
311
- customConfig: {
312
- searchConfig: {
313
- indexingEnabled: process.env.SEARCH_INDEXING !== "false",
314
- elasticsearchUrl: process.env.ELASTICSEARCH_URL,
315
- algoliaAppId: process.env.ALGOLIA_APP_ID,
316
- algoliaApiKey: process.env.ALGOLIA_API_KEY,
317
- },
318
- imageProcessing: {
319
- maxFileSize: Number(process.env.MAX_IMAGE_SIZE) || 10485760, // 10MB
320
- allowedFormats: ["jpg", "jpeg", "png", "webp"],
321
- autoOptimization: process.env.AUTO_OPTIMIZE_IMAGES !== "false",
322
- },
323
- productLimits: {
324
- maxVariants: Number(process.env.MAX_VARIANTS_PER_PRODUCT) || 100,
325
- maxImages: Number(process.env.MAX_IMAGES_PER_PRODUCT) || 20,
326
- maxCategories: Number(process.env.MAX_CATEGORIES_PER_PRODUCT) || 5,
327
- },
328
- },
329
- };
330
-
331
- export const INVENTORY_SERVICE_PROFILE: ServiceProfile = {
332
- base: {
333
- serviceName: "inventory-core-service",
334
- port: Number(process.env.PORT) || 3005,
335
- host: process.env.HOST || "0.0.0.0",
336
- environment: (process.env.NODE_ENV as any) || "development",
337
- cors: {
338
- origins: process.env.CORS_ORIGINS?.split(",") || [
339
- "http://localhost:3000",
340
- ],
341
- credentials: true,
342
- },
343
- rateLimiting: {
344
- max: Number(process.env.RATE_LIMIT_MAX) || 300,
345
- timeWindow: process.env.RATE_LIMIT_WINDOW || "1 minute",
346
- },
347
- },
348
- database: {
349
- url:
350
- process.env.DATABASE_URL ||
351
- "postgresql://postgres:password@localhost:5432/inventory_core_db",
352
- host: process.env.DB_HOST || "localhost",
353
- port: Number(process.env.DB_PORT) || 5432,
354
- user: process.env.DB_USER || "postgres",
355
- password: process.env.DB_PASSWORD || "password",
356
- database: process.env.DB_NAME || "inventory_core_db",
357
- ssl: process.env.DB_SSL === "true",
358
- poolSize: Number(process.env.DB_POOL_SIZE) || 15,
359
- },
360
- kafka: {
361
- enabled: process.env.KAFKA_ENABLED !== "false",
362
- clientId: process.env.KAFKA_CLIENT_ID || "inventory-core-service",
363
- groupId: process.env.KAFKA_GROUP_ID || "inventory-core-group",
364
- topics: [
365
- "inventory.created",
366
- "inventory.updated",
367
- "inventory.adjusted",
368
- "inventory.reserved",
369
- "inventory.released",
370
- "warehouse.created",
371
- "warehouse.updated",
372
- "pos.location.created",
373
- "pos.location.updated",
374
- ],
375
- autoCommit: process.env.KAFKA_AUTO_COMMIT !== "false",
376
- },
377
- redis: {
378
- host: process.env.REDIS_HOST || "localhost",
379
- port: Number(process.env.REDIS_PORT) || 6379,
380
- password: process.env.REDIS_PASSWORD,
381
- db: Number(process.env.REDIS_DB) || 2,
382
- ttl: Number(process.env.REDIS_TTL) || 1800,
383
- },
384
- audit: {
385
- enabled: process.env.ENABLE_AUDIT_LOGGING !== "false",
386
- level: (process.env.AUDIT_LEVEL as any) || "comprehensive",
387
- bufferSize: Number(process.env.AUDIT_BUFFER_SIZE) || 200,
388
- flushInterval: Number(process.env.AUDIT_FLUSH_INTERVAL) || 3000,
389
- sensitiveFieldMasking: process.env.AUDIT_MASK_SENSITIVE !== "false",
390
- },
391
- features: {
392
- realTimeSync: process.env.ENABLE_REAL_TIME_SYNC !== "false",
393
- batchProcessing: process.env.ENABLE_BATCH_PROCESSING !== "false",
394
- warehouseManagement: true,
395
- posLocationManagement: true,
396
- inventoryReservations: true,
397
- movementTracking: true,
398
- qualityControl: true,
399
- supplierManagement: true,
400
- },
401
- customConfig: {
402
- inventoryLimits: {
403
- maxReservationTime: Number(process.env.MAX_RESERVATION_TIME) || 1440, // minutes
404
- lowStockThreshold: Number(process.env.LOW_STOCK_THRESHOLD) || 10,
405
- criticalStockThreshold: Number(process.env.CRITICAL_STOCK_THRESHOLD) || 5,
406
- },
407
- warehouseConfig: {
408
- maxWarehouses: Number(process.env.MAX_WAREHOUSES) || 100,
409
- maxLocationsPerWarehouse:
410
- Number(process.env.MAX_LOCATIONS_PER_WAREHOUSE) || 1000,
411
- },
412
- posConfig: {
413
- maxPosLocations: Number(process.env.MAX_POS_LOCATIONS) || 500,
414
- syncInterval: Number(process.env.POS_SYNC_INTERVAL) || 300, // seconds
415
- },
416
- },
417
- };
418
-
419
- export const ADMIN_API_SERVICE_PROFILE: ServiceProfile = {
420
- base: {
421
- serviceName: "admin-api-service",
422
- port: Number(process.env.PORT) || 3004,
423
- host: process.env.HOST || "0.0.0.0",
424
- environment: (process.env.NODE_ENV as any) || "development",
425
- cors: {
426
- origins: process.env.CORS_ORIGINS?.split(",") || [
427
- "http://localhost:3000",
428
- ],
429
- credentials: true,
430
- },
431
- rateLimiting: {
432
- max: Number(process.env.RATE_LIMIT_MAX) || 100,
433
- timeWindow: process.env.RATE_LIMIT_WINDOW || "1 minute",
434
- },
435
- },
436
- database: {
437
- url:
438
- process.env.DATABASE_URL ||
439
- "postgresql://postgres:password@localhost:5432/axova_admin_db",
440
- host: process.env.POSTGRES_HOST || "localhost",
441
- port: Number(process.env.POSTGRES_PORT) || 5432,
442
- user: process.env.POSTGRES_USER || "postgres",
443
- password: process.env.POSTGRES_PASSWORD || "password",
444
- database: process.env.POSTGRES_DB || "axova_admin_db",
445
- ssl: process.env.DB_SSL === "true",
446
- poolSize: Number(process.env.DB_POOL_SIZE) || 10,
447
- },
448
- kafka: {
449
- enabled: process.env.KAFKA_ENABLED !== "false",
450
- clientId: process.env.KAFKA_CLIENT_ID || "admin-api-service",
451
- groupId: process.env.KAFKA_GROUP_ID || "admin-api-service-group",
452
- topics: [
453
- "admin.action.performed",
454
- "user.created",
455
- "user.updated",
456
- "user.deleted",
457
- "system.configuration.changed",
458
- "audit.requested",
459
- ],
460
- autoCommit: process.env.KAFKA_AUTO_COMMIT !== "false",
461
- },
462
- audit: {
463
- enabled: process.env.AUDIT_ENABLED !== "false",
464
- level: (process.env.AUDIT_LEVEL as any) || "comprehensive",
465
- bufferSize: Number(process.env.AUDIT_BUFFER_SIZE) || 50,
466
- flushInterval: Number(process.env.AUDIT_FLUSH_INTERVAL) || 2000,
467
- sensitiveFieldMasking: process.env.AUDIT_MASK_SENSITIVE !== "false",
468
- },
469
- features: {
470
- userManagement: true,
471
- systemConfiguration: true,
472
- auditReporting: true,
473
- complianceMonitoring: true,
474
- serviceManagement: true,
475
- analyticsAccess: true,
476
- backupManagement: true,
477
- securityMonitoring: true,
478
- },
479
- customConfig: {
480
- adminSecurity: {
481
- mfaRequired: process.env.ADMIN_MFA_REQUIRED !== "false",
482
- sessionTimeout: Number(process.env.ADMIN_SESSION_TIMEOUT) || 1800, // seconds
483
- maxLoginAttempts: Number(process.env.MAX_LOGIN_ATTEMPTS) || 3,
484
- },
485
- permissions: {
486
- superAdminRoles: process.env.SUPER_ADMIN_ROLES?.split(",") || [
487
- "super_admin",
488
- ],
489
- adminRoles: process.env.ADMIN_ROLES?.split(",") || [
490
- "admin",
491
- "super_admin",
492
- ],
493
- moderatorRoles: process.env.MODERATOR_ROLES?.split(",") || [
494
- "moderator",
495
- "admin",
496
- "super_admin",
497
- ],
498
- },
499
- },
500
- };
501
-
502
- export const OXA_SERVICE_PROFILE: ServiceProfile = {
503
- base: {
504
- serviceName: "oxa-service",
505
- port: Number(process.env.PORT) || 3010,
506
- host: process.env.HOST || "0.0.0.0",
507
- environment: (process.env.NODE_ENV as any) || "development",
508
- cors: {
509
- origins: process.env.CORS_ORIGINS?.split(",") || [
510
- "http://localhost:3000",
511
- "http://localhost:3010",
512
- ],
513
- credentials: true,
514
- },
515
- rateLimiting: {
516
- max: Number(process.env.RATE_LIMIT_MAX) || 600,
517
- timeWindow: process.env.RATE_LIMIT_WINDOW || "1 minute",
518
- },
519
- },
520
- database: {
521
- url:
522
- process.env.DATABASE_URL ||
523
- "postgresql://postgres:password@localhost:5432/axova_oxa_db",
524
- host: process.env.POSTGRES_HOST || "localhost",
525
- port: Number(process.env.POSTGRES_PORT) || 5432,
526
- user: process.env.POSTGRES_USER || "postgres",
527
- password: process.env.POSTGRES_PASSWORD || "password",
528
- database: process.env.POSTGRES_DB || "axova_oxa_db",
529
- ssl: process.env.DB_SSL === "true",
530
- poolSize: Number(process.env.DB_POOL_SIZE) || 10,
531
- },
532
- kafka: {
533
- enabled: process.env.KAFKA_ENABLED === "true",
534
- clientId: process.env.KAFKA_CLIENT_ID || "oxa-service",
535
- groupId: process.env.KAFKA_GROUP_ID || "oxa-service-group",
536
- topics: ["audit.logged", "notification.send"],
537
- autoCommit: process.env.KAFKA_AUTO_COMMIT !== "false",
538
- },
539
- audit: {
540
- enabled: process.env.AUDIT_ENABLED !== "false",
541
- level: (process.env.AUDIT_LEVEL as any) || "comprehensive",
542
- bufferSize: Number(process.env.AUDIT_BUFFER_SIZE) || 100,
543
- flushInterval: Number(process.env.AUDIT_FLUSH_INTERVAL) || 5000,
544
- sensitiveFieldMasking: process.env.AUDIT_MASK_SENSITIVE !== "false",
545
- },
546
- features: {
547
- aiChat: true,
548
- aiStreaming: true,
549
- embeddings: true,
550
- moderation: true,
551
- tracing: process.env.OXA_TRACING === "true",
552
- ratelimit: true,
553
- },
554
- customConfig: {
555
- oxa: {
556
- defaultModel: process.env.OXA_DEFAULT_MODEL || "gpt-4o-mini",
557
- defaultEmbeddingModel:
558
- process.env.OXA_EMBEDDING_MODEL || "text-embedding-3-small",
559
- requestTimeoutMs: Number(process.env.OXA_REQUEST_TIMEOUT_MS) || 60000,
560
- maxRetries: Number(process.env.OXA_MAX_RETRIES) || 2,
561
- },
562
- },
563
- };
564
-
565
- // =============================================================================
566
- // Configuration Factory and Utilities
567
- // =============================================================================
568
-
569
- export type ServiceName =
570
- | "store-service"
571
- | "compliance-service"
572
- | "product-service"
573
- | "inventory-core-service"
574
- | "admin-api-service"
575
- | "oxa-service";
576
-
577
- export const SERVICE_PROFILES: Record<ServiceName, ServiceProfile> = {
578
- "store-service": STORE_SERVICE_PROFILE,
579
- "compliance-service": COMPLIANCE_SERVICE_PROFILE,
580
- "product-service": PRODUCT_SERVICE_PROFILE,
581
- "inventory-core-service": INVENTORY_SERVICE_PROFILE,
582
- "admin-api-service": ADMIN_API_SERVICE_PROFILE,
583
- "oxa-service": OXA_SERVICE_PROFILE,
584
- };
585
-
586
- /**
587
- * Get configuration profile for a specific service
588
- */
589
- export function getServiceProfile(serviceName: ServiceName): ServiceProfile {
590
- const profile = SERVICE_PROFILES[serviceName];
591
- if (!profile) {
592
- throw new Error(`Unknown service: ${serviceName}`);
593
- }
594
- return profile;
595
- }
596
-
597
- /**
598
- * Initialize service with its profile and return configured instances
599
- */
600
- export async function initializeServiceWithProfile(serviceName: ServiceName) {
601
- const profile = getServiceProfile(serviceName);
602
-
603
- // Get base configurations
604
- const kafkaConfig = getKafkaConfigFromEnv();
605
- const serviceAuthConfig = getServiceAuthConfigFromEnv();
606
-
607
- // Return initialized configuration
608
- return {
609
- profile,
610
- kafkaConfig,
611
- serviceAuthConfig,
612
- // Add convenience methods
613
- isFeatureEnabled: (feature: string) => profile.features[feature] === true,
614
- getCustomConfig: (key: string) => profile.customConfig?.[key],
615
- isDevelopment: () => profile.base.environment === "development",
616
- isProduction: () => profile.base.environment === "production",
617
- };
618
- }
619
-
620
- /**
621
- * Validate service configuration
622
- */
623
- export function validateServiceConfig(profile: ServiceProfile): {
624
- valid: boolean;
625
- errors: string[];
626
- } {
627
- const errors: string[] = [];
628
-
629
- // Validate required fields
630
- if (!profile.base.serviceName) errors.push("Service name is required");
631
- if (
632
- !profile.base.port ||
633
- profile.base.port < 1 ||
634
- profile.base.port > 65535
635
- ) {
636
- errors.push("Valid port number is required");
637
- }
638
- if (!profile.database.url) errors.push("Database URL is required");
639
-
640
- // Validate kafka configuration
641
- if (profile.kafka.enabled && !profile.kafka.clientId) {
642
- errors.push("Kafka client ID is required when Kafka is enabled");
643
- }
644
-
645
- // Validate audit configuration
646
- if (profile.audit.enabled && profile.audit.bufferSize < 1) {
647
- errors.push("Valid audit buffer size is required when audit is enabled");
648
- }
649
-
650
- return {
651
- valid: errors.length === 0,
652
- errors,
653
- };
654
- }
1
+ // =============================================================================
2
+ // AXOVA SHARED CONFIGURATIONS
3
+ // Service-specific configuration profiles for the Axova platform
4
+ // =============================================================================
5
+
6
+ import { getKafkaConfigFromEnv } from "../events/kafka";
7
+ import { getServiceAuthConfigFromEnv } from "../middleware/serviceAuth";
8
+
9
+ // =============================================================================
10
+ // Base Configuration Interfaces
11
+ // =============================================================================
12
+
13
+ export interface BaseServiceConfig {
14
+ serviceName: string;
15
+ port: number;
16
+ host: string;
17
+ environment: "development" | "staging" | "production";
18
+ cors: {
19
+ origins: string[];
20
+ credentials: boolean;
21
+ };
22
+ rateLimiting: {
23
+ max: number;
24
+ timeWindow: string;
25
+ };
26
+ }
27
+
28
+ export interface DatabaseConfig {
29
+ url: string;
30
+ host: string;
31
+ port: number;
32
+ user: string;
33
+ password: string;
34
+ database: string;
35
+ ssl: boolean;
36
+ poolSize: number;
37
+ }
38
+
39
+ export interface KafkaServiceConfig {
40
+ enabled: boolean;
41
+ clientId: string;
42
+ groupId: string;
43
+ topics: string[];
44
+ autoCommit: boolean;
45
+ }
46
+
47
+ export interface RedisConfig {
48
+ host: string;
49
+ port: number;
50
+ password?: string;
51
+ db: number;
52
+ ttl: number;
53
+ }
54
+
55
+ export interface AuditConfig {
56
+ enabled: boolean;
57
+ level: "minimal" | "standard" | "comprehensive";
58
+ bufferSize: number;
59
+ flushInterval: number;
60
+ sensitiveFieldMasking: boolean;
61
+ }
62
+
63
+ export interface ServiceProfile {
64
+ base: BaseServiceConfig;
65
+ database: DatabaseConfig;
66
+ kafka: KafkaServiceConfig;
67
+ redis?: RedisConfig;
68
+ audit: AuditConfig;
69
+ features: Record<string, boolean>;
70
+ customConfig?: Record<string, unknown>;
71
+ }
72
+
73
+ // =============================================================================
74
+ // Service-Specific Configurations
75
+ // =============================================================================
76
+
77
+ export const STORE_SERVICE_PROFILE: ServiceProfile = {
78
+ base: {
79
+ serviceName: "store-service",
80
+ port: Number(process.env.PORT) || 3001,
81
+ host: process.env.HOST || "0.0.0.0",
82
+ environment: (process.env.NODE_ENV as any) || "development",
83
+ cors: {
84
+ origins: process.env.CORS_ORIGINS?.split(",") || [
85
+ "http://localhost:3000",
86
+ ],
87
+ credentials: true,
88
+ },
89
+ rateLimiting: {
90
+ max: Number(process.env.RATE_LIMIT_MAX) || 100,
91
+ timeWindow: process.env.RATE_LIMIT_WINDOW || "1 minute",
92
+ },
93
+ },
94
+ database: {
95
+ url:
96
+ process.env.DATABASE_URL ||
97
+ "postgresql://postgres:password@localhost:5432/axova_store_db",
98
+ host: process.env.POSTGRES_HOST || "localhost",
99
+ port: Number(process.env.POSTGRES_PORT) || 5432,
100
+ user: process.env.POSTGRES_USER || "postgres",
101
+ password: process.env.POSTGRES_PASSWORD || "password",
102
+ database: process.env.POSTGRES_DB || "axova_store_db",
103
+ ssl: process.env.DB_SSL === "true",
104
+ poolSize: Number(process.env.DB_POOL_SIZE) || 10,
105
+ },
106
+ kafka: {
107
+ enabled: process.env.KAFKA_ENABLED !== "false",
108
+ clientId: process.env.KAFKA_CLIENT_ID || "store-service",
109
+ groupId: process.env.KAFKA_GROUP_ID || "store-service-group",
110
+ topics: [
111
+ "store.created",
112
+ "store.updated",
113
+ "store.deleted",
114
+ "store.business.updated",
115
+ "store.social.updated",
116
+ "store.blog.created",
117
+ "store.blog.updated",
118
+ "store.contact.updated",
119
+ ],
120
+ autoCommit: process.env.KAFKA_AUTO_COMMIT !== "false",
121
+ },
122
+ redis: {
123
+ host: process.env.REDIS_HOST || "localhost",
124
+ port: Number(process.env.REDIS_PORT) || 6379,
125
+ password: process.env.REDIS_PASSWORD,
126
+ db: Number(process.env.REDIS_DB) || 0,
127
+ ttl: Number(process.env.REDIS_TTL) || 3600,
128
+ },
129
+ audit: {
130
+ enabled: process.env.AUDIT_ENABLED !== "false",
131
+ level: (process.env.AUDIT_LEVEL as any) || "comprehensive",
132
+ bufferSize: Number(process.env.AUDIT_BUFFER_SIZE) || 100,
133
+ flushInterval: Number(process.env.AUDIT_FLUSH_INTERVAL) || 5000,
134
+ sensitiveFieldMasking: process.env.AUDIT_MASK_SENSITIVE !== "false",
135
+ },
136
+ features: {
137
+ realTimeSync: process.env.ENABLE_REAL_TIME_SYNC !== "false",
138
+ auditLogging: process.env.ENABLE_AUDIT_LOGGING !== "false",
139
+ advancedAnalytics: process.env.ENABLE_ADVANCED_ANALYTICS === "true",
140
+ multiTenant: true,
141
+ storeCustomization: true,
142
+ blogManagement: true,
143
+ socialProfiles: true,
144
+ businessDetails: true,
145
+ contactManagement: true,
146
+ },
147
+ customConfig: {
148
+ storeDomain: process.env.STORE_DOMAIN || "myaxova.store",
149
+ maxStoresPerUser: Number(process.env.MAX_STORES_PER_USER) || 5,
150
+ storeCustomizationLimits: {
151
+ maxThemes: 10,
152
+ maxPages: 50,
153
+ maxProducts: 10000,
154
+ },
155
+ },
156
+ };
157
+
158
+ export const COMPLIANCE_SERVICE_PROFILE: ServiceProfile = {
159
+ base: {
160
+ serviceName: "compliance-service",
161
+ port: Number(process.env.PORT) || 3002,
162
+ host: process.env.HOST || "0.0.0.0",
163
+ environment: (process.env.NODE_ENV as any) || "development",
164
+ cors: {
165
+ origins: process.env.CORS_ORIGINS?.split(",") || [
166
+ "http://localhost:3000",
167
+ ],
168
+ credentials: true,
169
+ },
170
+ rateLimiting: {
171
+ max: Number(process.env.RATE_LIMIT_MAX) || 200,
172
+ timeWindow: process.env.RATE_LIMIT_WINDOW || "1 minute",
173
+ },
174
+ },
175
+ database: {
176
+ url:
177
+ process.env.DATABASE_URL ||
178
+ "postgresql://postgres:password@localhost:5432/axova_compliance_db",
179
+ host: process.env.POSTGRES_HOST || "localhost",
180
+ port: Number(process.env.POSTGRES_PORT) || 5432,
181
+ user: process.env.POSTGRES_USER || "postgres",
182
+ password: process.env.POSTGRES_PASSWORD || "password",
183
+ database: process.env.POSTGRES_DB || "axova_compliance_db",
184
+ ssl: process.env.DB_SSL === "true",
185
+ poolSize: Number(process.env.DB_POOL_SIZE) || 15,
186
+ },
187
+ kafka: {
188
+ enabled: process.env.KAFKA_ENABLED !== "false",
189
+ clientId: process.env.KAFKA_CLIENT_ID || "compliance-service",
190
+ groupId: process.env.KAFKA_GROUP_ID || "compliance-service-group",
191
+ topics: [
192
+ "store.created",
193
+ "store.updated",
194
+ "compliance.violation.detected",
195
+ "compliance.violation.resolved",
196
+ "appeal.submitted",
197
+ "appeal.reviewed",
198
+ "store.suspended",
199
+ "store.unbanned",
200
+ "audit.logged",
201
+ ],
202
+ autoCommit: process.env.KAFKA_AUTO_COMMIT !== "false",
203
+ },
204
+ audit: {
205
+ enabled: process.env.AUDIT_ENABLED !== "false",
206
+ level: (process.env.AUDIT_LEVEL as any) || "comprehensive",
207
+ bufferSize: Number(process.env.AUDIT_BUFFER_SIZE) || 200,
208
+ flushInterval: Number(process.env.AUDIT_FLUSH_INTERVAL) || 3000,
209
+ sensitiveFieldMasking: process.env.AUDIT_MASK_SENSITIVE !== "false",
210
+ },
211
+ features: {
212
+ realTimeMonitoring: true,
213
+ automaticViolationDetection: true,
214
+ appealManagement: true,
215
+ riskAssessment: true,
216
+ complianceReporting: true,
217
+ auditTrails: true,
218
+ escalationMatrix: true,
219
+ mlBasedDetection: process.env.ENABLE_ML_DETECTION === "true",
220
+ },
221
+ customConfig: {
222
+ violationThresholds: {
223
+ low: 3,
224
+ medium: 5,
225
+ high: 2,
226
+ critical: 1,
227
+ },
228
+ appealProcessing: {
229
+ autoReviewEnabled: process.env.AUTO_REVIEW_APPEALS === "true",
230
+ maxAppealTime: Number(process.env.MAX_APPEAL_TIME) || 72, // hours
231
+ escalationLevels: 3,
232
+ },
233
+ suspensionRules: {
234
+ automaticSuspension: process.env.AUTO_SUSPEND === "true",
235
+ gracePeriod: Number(process.env.SUSPENSION_GRACE_PERIOD) || 24, // hours
236
+ },
237
+ },
238
+ };
239
+
240
+ export const PRODUCT_SERVICE_PROFILE: ServiceProfile = {
241
+ base: {
242
+ serviceName: "product-service",
243
+ port: Number(process.env.PORT) || 3003,
244
+ host: process.env.HOST || "0.0.0.0",
245
+ environment: (process.env.NODE_ENV as any) || "development",
246
+ cors: {
247
+ origins: process.env.CORS_ORIGINS?.split(",") || [
248
+ "http://localhost:3000",
249
+ ],
250
+ credentials: true,
251
+ },
252
+ rateLimiting: {
253
+ max: Number(process.env.RATE_LIMIT_MAX) || 500,
254
+ timeWindow: process.env.RATE_LIMIT_WINDOW || "1 minute",
255
+ },
256
+ },
257
+ database: {
258
+ url:
259
+ process.env.DATABASE_URL ||
260
+ "postgresql://postgres:password@localhost:5432/axova_product_db",
261
+ host: process.env.POSTGRES_HOST || "localhost",
262
+ port: Number(process.env.POSTGRES_PORT) || 5432,
263
+ user: process.env.POSTGRES_USER || "postgres",
264
+ password: process.env.POSTGRES_PASSWORD || "password",
265
+ database: process.env.POSTGRES_DB || "axova_product_db",
266
+ ssl: process.env.DB_SSL === "true",
267
+ poolSize: Number(process.env.DB_POOL_SIZE) || 20,
268
+ },
269
+ kafka: {
270
+ enabled: process.env.KAFKA_ENABLED !== "false",
271
+ clientId: process.env.KAFKA_CLIENT_ID || "product-service",
272
+ groupId: process.env.KAFKA_GROUP_ID || "product-service-group",
273
+ topics: [
274
+ "product.created",
275
+ "product.updated",
276
+ "product.deleted",
277
+ "variant.created",
278
+ "variant.updated",
279
+ "variant.deleted",
280
+ "collection.created",
281
+ "collection.updated",
282
+ "collection.deleted",
283
+ "inventory.updated",
284
+ ],
285
+ autoCommit: process.env.KAFKA_AUTO_COMMIT !== "false",
286
+ },
287
+ redis: {
288
+ host: process.env.REDIS_HOST || "localhost",
289
+ port: Number(process.env.REDIS_PORT) || 6379,
290
+ password: process.env.REDIS_PASSWORD,
291
+ db: Number(process.env.REDIS_DB) || 1,
292
+ ttl: Number(process.env.REDIS_TTL) || 7200,
293
+ },
294
+ audit: {
295
+ enabled: process.env.AUDIT_ENABLED !== "false",
296
+ level: (process.env.AUDIT_LEVEL as any) || "standard",
297
+ bufferSize: Number(process.env.AUDIT_BUFFER_SIZE) || 150,
298
+ flushInterval: Number(process.env.AUDIT_FLUSH_INTERVAL) || 4000,
299
+ sensitiveFieldMasking: process.env.AUDIT_MASK_SENSITIVE !== "false",
300
+ },
301
+ features: {
302
+ searchOptimization: true,
303
+ imageProcessing: true,
304
+ variantManagement: true,
305
+ collectionManagement: true,
306
+ bulkOperations: true,
307
+ seoOptimization: true,
308
+ analyticsIntegration: true,
309
+ recommendationEngine: process.env.ENABLE_RECOMMENDATIONS === "true",
310
+ },
311
+ customConfig: {
312
+ searchConfig: {
313
+ indexingEnabled: process.env.SEARCH_INDEXING !== "false",
314
+ elasticsearchUrl: process.env.ELASTICSEARCH_URL,
315
+ algoliaAppId: process.env.ALGOLIA_APP_ID,
316
+ algoliaApiKey: process.env.ALGOLIA_API_KEY,
317
+ },
318
+ imageProcessing: {
319
+ maxFileSize: Number(process.env.MAX_IMAGE_SIZE) || 10485760, // 10MB
320
+ allowedFormats: ["jpg", "jpeg", "png", "webp"],
321
+ autoOptimization: process.env.AUTO_OPTIMIZE_IMAGES !== "false",
322
+ },
323
+ productLimits: {
324
+ maxVariants: Number(process.env.MAX_VARIANTS_PER_PRODUCT) || 100,
325
+ maxImages: Number(process.env.MAX_IMAGES_PER_PRODUCT) || 20,
326
+ maxCategories: Number(process.env.MAX_CATEGORIES_PER_PRODUCT) || 5,
327
+ },
328
+ },
329
+ };
330
+
331
+ export const INVENTORY_SERVICE_PROFILE: ServiceProfile = {
332
+ base: {
333
+ serviceName: "inventory-core-service",
334
+ port: Number(process.env.PORT) || 3005,
335
+ host: process.env.HOST || "0.0.0.0",
336
+ environment: (process.env.NODE_ENV as any) || "development",
337
+ cors: {
338
+ origins: process.env.CORS_ORIGINS?.split(",") || [
339
+ "http://localhost:3000",
340
+ ],
341
+ credentials: true,
342
+ },
343
+ rateLimiting: {
344
+ max: Number(process.env.RATE_LIMIT_MAX) || 300,
345
+ timeWindow: process.env.RATE_LIMIT_WINDOW || "1 minute",
346
+ },
347
+ },
348
+ database: {
349
+ url:
350
+ process.env.DATABASE_URL ||
351
+ "postgresql://postgres:password@localhost:5432/inventory_core_db",
352
+ host: process.env.DB_HOST || "localhost",
353
+ port: Number(process.env.DB_PORT) || 5432,
354
+ user: process.env.DB_USER || "postgres",
355
+ password: process.env.DB_PASSWORD || "password",
356
+ database: process.env.DB_NAME || "inventory_core_db",
357
+ ssl: process.env.DB_SSL === "true",
358
+ poolSize: Number(process.env.DB_POOL_SIZE) || 15,
359
+ },
360
+ kafka: {
361
+ enabled: process.env.KAFKA_ENABLED !== "false",
362
+ clientId: process.env.KAFKA_CLIENT_ID || "inventory-core-service",
363
+ groupId: process.env.KAFKA_GROUP_ID || "inventory-core-group",
364
+ topics: [
365
+ "inventory.created",
366
+ "inventory.updated",
367
+ "inventory.adjusted",
368
+ "inventory.reserved",
369
+ "inventory.released",
370
+ "warehouse.created",
371
+ "warehouse.updated",
372
+ "pos.location.created",
373
+ "pos.location.updated",
374
+ ],
375
+ autoCommit: process.env.KAFKA_AUTO_COMMIT !== "false",
376
+ },
377
+ redis: {
378
+ host: process.env.REDIS_HOST || "localhost",
379
+ port: Number(process.env.REDIS_PORT) || 6379,
380
+ password: process.env.REDIS_PASSWORD,
381
+ db: Number(process.env.REDIS_DB) || 2,
382
+ ttl: Number(process.env.REDIS_TTL) || 1800,
383
+ },
384
+ audit: {
385
+ enabled: process.env.ENABLE_AUDIT_LOGGING !== "false",
386
+ level: (process.env.AUDIT_LEVEL as any) || "comprehensive",
387
+ bufferSize: Number(process.env.AUDIT_BUFFER_SIZE) || 200,
388
+ flushInterval: Number(process.env.AUDIT_FLUSH_INTERVAL) || 3000,
389
+ sensitiveFieldMasking: process.env.AUDIT_MASK_SENSITIVE !== "false",
390
+ },
391
+ features: {
392
+ realTimeSync: process.env.ENABLE_REAL_TIME_SYNC !== "false",
393
+ batchProcessing: process.env.ENABLE_BATCH_PROCESSING !== "false",
394
+ warehouseManagement: true,
395
+ posLocationManagement: true,
396
+ inventoryReservations: true,
397
+ movementTracking: true,
398
+ qualityControl: true,
399
+ supplierManagement: true,
400
+ },
401
+ customConfig: {
402
+ inventoryLimits: {
403
+ maxReservationTime: Number(process.env.MAX_RESERVATION_TIME) || 1440, // minutes
404
+ lowStockThreshold: Number(process.env.LOW_STOCK_THRESHOLD) || 10,
405
+ criticalStockThreshold: Number(process.env.CRITICAL_STOCK_THRESHOLD) || 5,
406
+ },
407
+ warehouseConfig: {
408
+ maxWarehouses: Number(process.env.MAX_WAREHOUSES) || 100,
409
+ maxLocationsPerWarehouse:
410
+ Number(process.env.MAX_LOCATIONS_PER_WAREHOUSE) || 1000,
411
+ },
412
+ posConfig: {
413
+ maxPosLocations: Number(process.env.MAX_POS_LOCATIONS) || 500,
414
+ syncInterval: Number(process.env.POS_SYNC_INTERVAL) || 300, // seconds
415
+ },
416
+ },
417
+ };
418
+
419
+ export const ADMIN_API_SERVICE_PROFILE: ServiceProfile = {
420
+ base: {
421
+ serviceName: "admin-api-service",
422
+ port: Number(process.env.PORT) || 3004,
423
+ host: process.env.HOST || "0.0.0.0",
424
+ environment: (process.env.NODE_ENV as any) || "development",
425
+ cors: {
426
+ origins: process.env.CORS_ORIGINS?.split(",") || [
427
+ "http://localhost:3000",
428
+ ],
429
+ credentials: true,
430
+ },
431
+ rateLimiting: {
432
+ max: Number(process.env.RATE_LIMIT_MAX) || 100,
433
+ timeWindow: process.env.RATE_LIMIT_WINDOW || "1 minute",
434
+ },
435
+ },
436
+ database: {
437
+ url:
438
+ process.env.DATABASE_URL ||
439
+ "postgresql://postgres:password@localhost:5432/axova_admin_db",
440
+ host: process.env.POSTGRES_HOST || "localhost",
441
+ port: Number(process.env.POSTGRES_PORT) || 5432,
442
+ user: process.env.POSTGRES_USER || "postgres",
443
+ password: process.env.POSTGRES_PASSWORD || "password",
444
+ database: process.env.POSTGRES_DB || "axova_admin_db",
445
+ ssl: process.env.DB_SSL === "true",
446
+ poolSize: Number(process.env.DB_POOL_SIZE) || 10,
447
+ },
448
+ kafka: {
449
+ enabled: process.env.KAFKA_ENABLED !== "false",
450
+ clientId: process.env.KAFKA_CLIENT_ID || "admin-api-service",
451
+ groupId: process.env.KAFKA_GROUP_ID || "admin-api-service-group",
452
+ topics: [
453
+ "admin.action.performed",
454
+ "user.created",
455
+ "user.updated",
456
+ "user.deleted",
457
+ "system.configuration.changed",
458
+ "audit.requested",
459
+ ],
460
+ autoCommit: process.env.KAFKA_AUTO_COMMIT !== "false",
461
+ },
462
+ audit: {
463
+ enabled: process.env.AUDIT_ENABLED !== "false",
464
+ level: (process.env.AUDIT_LEVEL as any) || "comprehensive",
465
+ bufferSize: Number(process.env.AUDIT_BUFFER_SIZE) || 50,
466
+ flushInterval: Number(process.env.AUDIT_FLUSH_INTERVAL) || 2000,
467
+ sensitiveFieldMasking: process.env.AUDIT_MASK_SENSITIVE !== "false",
468
+ },
469
+ features: {
470
+ userManagement: true,
471
+ systemConfiguration: true,
472
+ auditReporting: true,
473
+ complianceMonitoring: true,
474
+ serviceManagement: true,
475
+ analyticsAccess: true,
476
+ backupManagement: true,
477
+ securityMonitoring: true,
478
+ },
479
+ customConfig: {
480
+ adminSecurity: {
481
+ mfaRequired: process.env.ADMIN_MFA_REQUIRED !== "false",
482
+ sessionTimeout: Number(process.env.ADMIN_SESSION_TIMEOUT) || 1800, // seconds
483
+ maxLoginAttempts: Number(process.env.MAX_LOGIN_ATTEMPTS) || 3,
484
+ },
485
+ permissions: {
486
+ superAdminRoles: process.env.SUPER_ADMIN_ROLES?.split(",") || [
487
+ "super_admin",
488
+ ],
489
+ adminRoles: process.env.ADMIN_ROLES?.split(",") || [
490
+ "admin",
491
+ "super_admin",
492
+ ],
493
+ moderatorRoles: process.env.MODERATOR_ROLES?.split(",") || [
494
+ "moderator",
495
+ "admin",
496
+ "super_admin",
497
+ ],
498
+ },
499
+ },
500
+ };
501
+
502
+ export const OXA_SERVICE_PROFILE: ServiceProfile = {
503
+ base: {
504
+ serviceName: "oxa-service",
505
+ port: Number(process.env.PORT) || 3010,
506
+ host: process.env.HOST || "0.0.0.0",
507
+ environment: (process.env.NODE_ENV as any) || "development",
508
+ cors: {
509
+ origins: process.env.CORS_ORIGINS?.split(",") || [
510
+ "http://localhost:3000",
511
+ "http://localhost:3010",
512
+ ],
513
+ credentials: true,
514
+ },
515
+ rateLimiting: {
516
+ max: Number(process.env.RATE_LIMIT_MAX) || 600,
517
+ timeWindow: process.env.RATE_LIMIT_WINDOW || "1 minute",
518
+ },
519
+ },
520
+ database: {
521
+ url:
522
+ process.env.DATABASE_URL ||
523
+ "postgresql://postgres:password@localhost:5432/axova_oxa_db",
524
+ host: process.env.POSTGRES_HOST || "localhost",
525
+ port: Number(process.env.POSTGRES_PORT) || 5432,
526
+ user: process.env.POSTGRES_USER || "postgres",
527
+ password: process.env.POSTGRES_PASSWORD || "password",
528
+ database: process.env.POSTGRES_DB || "axova_oxa_db",
529
+ ssl: process.env.DB_SSL === "true",
530
+ poolSize: Number(process.env.DB_POOL_SIZE) || 10,
531
+ },
532
+ kafka: {
533
+ enabled: process.env.KAFKA_ENABLED === "true",
534
+ clientId: process.env.KAFKA_CLIENT_ID || "oxa-service",
535
+ groupId: process.env.KAFKA_GROUP_ID || "oxa-service-group",
536
+ topics: ["audit.logged", "notification.send"],
537
+ autoCommit: process.env.KAFKA_AUTO_COMMIT !== "false",
538
+ },
539
+ audit: {
540
+ enabled: process.env.AUDIT_ENABLED !== "false",
541
+ level: (process.env.AUDIT_LEVEL as any) || "comprehensive",
542
+ bufferSize: Number(process.env.AUDIT_BUFFER_SIZE) || 100,
543
+ flushInterval: Number(process.env.AUDIT_FLUSH_INTERVAL) || 5000,
544
+ sensitiveFieldMasking: process.env.AUDIT_MASK_SENSITIVE !== "false",
545
+ },
546
+ features: {
547
+ aiChat: true,
548
+ aiStreaming: true,
549
+ embeddings: true,
550
+ moderation: true,
551
+ tracing: process.env.OXA_TRACING === "true",
552
+ ratelimit: true,
553
+ },
554
+ customConfig: {
555
+ oxa: {
556
+ defaultModel: process.env.OXA_DEFAULT_MODEL || "gpt-4o-mini",
557
+ defaultEmbeddingModel:
558
+ process.env.OXA_EMBEDDING_MODEL || "text-embedding-3-small",
559
+ requestTimeoutMs: Number(process.env.OXA_REQUEST_TIMEOUT_MS) || 60000,
560
+ maxRetries: Number(process.env.OXA_MAX_RETRIES) || 2,
561
+ },
562
+ },
563
+ };
564
+
565
+ // =============================================================================
566
+ // Configuration Factory and Utilities
567
+ // =============================================================================
568
+
569
+ export type ServiceName =
570
+ | "store-service"
571
+ | "compliance-service"
572
+ | "product-service"
573
+ | "inventory-core-service"
574
+ | "admin-api-service"
575
+ | "oxa-service";
576
+
577
+ export const SERVICE_PROFILES: Record<ServiceName, ServiceProfile> = {
578
+ "store-service": STORE_SERVICE_PROFILE,
579
+ "compliance-service": COMPLIANCE_SERVICE_PROFILE,
580
+ "product-service": PRODUCT_SERVICE_PROFILE,
581
+ "inventory-core-service": INVENTORY_SERVICE_PROFILE,
582
+ "admin-api-service": ADMIN_API_SERVICE_PROFILE,
583
+ "oxa-service": OXA_SERVICE_PROFILE,
584
+ };
585
+
586
+ /**
587
+ * Get configuration profile for a specific service
588
+ */
589
+ export function getServiceProfile(serviceName: ServiceName): ServiceProfile {
590
+ const profile = SERVICE_PROFILES[serviceName];
591
+ if (!profile) {
592
+ throw new Error(`Unknown service: ${serviceName}`);
593
+ }
594
+ return profile;
595
+ }
596
+
597
+ /**
598
+ * Initialize service with its profile and return configured instances
599
+ */
600
+ export async function initializeServiceWithProfile(serviceName: ServiceName) {
601
+ const profile = getServiceProfile(serviceName);
602
+
603
+ // Get base configurations
604
+ const kafkaConfig = getKafkaConfigFromEnv();
605
+ const serviceAuthConfig = getServiceAuthConfigFromEnv();
606
+
607
+ // Return initialized configuration
608
+ return {
609
+ profile,
610
+ kafkaConfig,
611
+ serviceAuthConfig,
612
+ // Add convenience methods
613
+ isFeatureEnabled: (feature: string) => profile.features[feature] === true,
614
+ getCustomConfig: (key: string) => profile.customConfig?.[key],
615
+ isDevelopment: () => profile.base.environment === "development",
616
+ isProduction: () => profile.base.environment === "production",
617
+ };
618
+ }
619
+
620
+ /**
621
+ * Validate service configuration
622
+ */
623
+ export function validateServiceConfig(profile: ServiceProfile): {
624
+ valid: boolean;
625
+ errors: string[];
626
+ } {
627
+ const errors: string[] = [];
628
+
629
+ // Validate required fields
630
+ if (!profile.base.serviceName) errors.push("Service name is required");
631
+ if (
632
+ !profile.base.port ||
633
+ profile.base.port < 1 ||
634
+ profile.base.port > 65535
635
+ ) {
636
+ errors.push("Valid port number is required");
637
+ }
638
+ if (!profile.database.url) errors.push("Database URL is required");
639
+
640
+ // Validate kafka configuration
641
+ if (profile.kafka.enabled && !profile.kafka.clientId) {
642
+ errors.push("Kafka client ID is required when Kafka is enabled");
643
+ }
644
+
645
+ // Validate audit configuration
646
+ if (profile.audit.enabled && profile.audit.bufferSize < 1) {
647
+ errors.push("Valid audit buffer size is required when audit is enabled");
648
+ }
649
+
650
+ return {
651
+ valid: errors.length === 0,
652
+ errors,
653
+ };
654
+ }