@axova/shared 1.0.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 (112) hide show
  1. package/CONFIGURATION_GUIDE.md +1 -0
  2. package/README.md +384 -0
  3. package/SCHEMA_ORGANIZATION.md +209 -0
  4. package/dist/configs/index.d.ts +85 -0
  5. package/dist/configs/index.js +555 -0
  6. package/dist/events/kafka.d.ts +40 -0
  7. package/dist/events/kafka.js +311 -0
  8. package/dist/index.d.ts +13 -0
  9. package/dist/index.js +41 -0
  10. package/dist/interfaces/customer-events.d.ts +85 -0
  11. package/dist/interfaces/customer-events.js +2 -0
  12. package/dist/interfaces/inventory-events.d.ts +453 -0
  13. package/dist/interfaces/inventory-events.js +3 -0
  14. package/dist/interfaces/inventory-types.d.ts +894 -0
  15. package/dist/interfaces/inventory-types.js +3 -0
  16. package/dist/interfaces/order-events.d.ts +320 -0
  17. package/dist/interfaces/order-events.js +3 -0
  18. package/dist/lib/auditLogger.d.ts +162 -0
  19. package/dist/lib/auditLogger.js +626 -0
  20. package/dist/lib/authOrganization.d.ts +24 -0
  21. package/dist/lib/authOrganization.js +110 -0
  22. package/dist/lib/db.d.ts +6 -0
  23. package/dist/lib/db.js +88 -0
  24. package/dist/middleware/serviceAuth.d.ts +60 -0
  25. package/dist/middleware/serviceAuth.js +272 -0
  26. package/dist/middleware/storeOwnership.d.ts +15 -0
  27. package/dist/middleware/storeOwnership.js +156 -0
  28. package/dist/middleware/storeValidationMiddleware.d.ts +44 -0
  29. package/dist/middleware/storeValidationMiddleware.js +180 -0
  30. package/dist/middleware/userAuth.d.ts +27 -0
  31. package/dist/middleware/userAuth.js +218 -0
  32. package/dist/schemas/admin/admin-schema.d.ts +741 -0
  33. package/dist/schemas/admin/admin-schema.js +111 -0
  34. package/dist/schemas/ai-moderation/ai-moderation-schema.d.ts +648 -0
  35. package/dist/schemas/ai-moderation/ai-moderation-schema.js +88 -0
  36. package/dist/schemas/common/common-schemas.d.ts +436 -0
  37. package/dist/schemas/common/common-schemas.js +94 -0
  38. package/dist/schemas/compliance/compliance-schema.d.ts +3388 -0
  39. package/dist/schemas/compliance/compliance-schema.js +472 -0
  40. package/dist/schemas/compliance/kyc-schema.d.ts +2642 -0
  41. package/dist/schemas/compliance/kyc-schema.js +361 -0
  42. package/dist/schemas/customer/customer-schema.d.ts +2727 -0
  43. package/dist/schemas/customer/customer-schema.js +399 -0
  44. package/dist/schemas/index.d.ts +27 -0
  45. package/dist/schemas/index.js +138 -0
  46. package/dist/schemas/inventory/inventory-tables.d.ts +9476 -0
  47. package/dist/schemas/inventory/inventory-tables.js +1470 -0
  48. package/dist/schemas/inventory/lot-tables.d.ts +3281 -0
  49. package/dist/schemas/inventory/lot-tables.js +608 -0
  50. package/dist/schemas/order/order-schema.d.ts +5825 -0
  51. package/dist/schemas/order/order-schema.js +954 -0
  52. package/dist/schemas/product/discount-relations.d.ts +15 -0
  53. package/dist/schemas/product/discount-relations.js +34 -0
  54. package/dist/schemas/product/discount-schema.d.ts +1975 -0
  55. package/dist/schemas/product/discount-schema.js +297 -0
  56. package/dist/schemas/product/product-relations.d.ts +41 -0
  57. package/dist/schemas/product/product-relations.js +133 -0
  58. package/dist/schemas/product/product-schema.d.ts +4544 -0
  59. package/dist/schemas/product/product-schema.js +671 -0
  60. package/dist/schemas/store/store-audit-schema.d.ts +4135 -0
  61. package/dist/schemas/store/store-audit-schema.js +556 -0
  62. package/dist/schemas/store/store-schema.d.ts +3100 -0
  63. package/dist/schemas/store/store-schema.js +381 -0
  64. package/dist/schemas/store/store-settings-schema.d.ts +665 -0
  65. package/dist/schemas/store/store-settings-schema.js +141 -0
  66. package/dist/schemas/types.d.ts +50 -0
  67. package/dist/schemas/types.js +3 -0
  68. package/dist/types/events.d.ts +2396 -0
  69. package/dist/types/events.js +505 -0
  70. package/dist/utils/errorHandler.d.ts +12 -0
  71. package/dist/utils/errorHandler.js +36 -0
  72. package/dist/utils/subdomain.d.ts +6 -0
  73. package/dist/utils/subdomain.js +20 -0
  74. package/nul +8 -0
  75. package/package.json +43 -0
  76. package/src/configs/index.ts +654 -0
  77. package/src/events/kafka.ts +429 -0
  78. package/src/index.ts +26 -0
  79. package/src/interfaces/customer-events.ts +106 -0
  80. package/src/interfaces/inventory-events.ts +545 -0
  81. package/src/interfaces/inventory-types.ts +1004 -0
  82. package/src/interfaces/order-events.ts +381 -0
  83. package/src/lib/auditLogger.ts +1117 -0
  84. package/src/lib/authOrganization.ts +153 -0
  85. package/src/lib/db.ts +64 -0
  86. package/src/middleware/serviceAuth.ts +328 -0
  87. package/src/middleware/storeOwnership.ts +199 -0
  88. package/src/middleware/storeValidationMiddleware.ts +247 -0
  89. package/src/middleware/userAuth.ts +248 -0
  90. package/src/schemas/admin/admin-schema.ts +208 -0
  91. package/src/schemas/ai-moderation/ai-moderation-schema.ts +180 -0
  92. package/src/schemas/common/common-schemas.ts +108 -0
  93. package/src/schemas/compliance/compliance-schema.ts +927 -0
  94. package/src/schemas/compliance/kyc-schema.ts +649 -0
  95. package/src/schemas/customer/customer-schema.ts +576 -0
  96. package/src/schemas/index.ts +189 -0
  97. package/src/schemas/inventory/inventory-tables.ts +1927 -0
  98. package/src/schemas/inventory/lot-tables.ts +799 -0
  99. package/src/schemas/order/order-schema.ts +1400 -0
  100. package/src/schemas/product/discount-relations.ts +44 -0
  101. package/src/schemas/product/discount-schema.ts +464 -0
  102. package/src/schemas/product/product-relations.ts +187 -0
  103. package/src/schemas/product/product-schema.ts +955 -0
  104. package/src/schemas/store/ethiopian_business_api.md.resolved +212 -0
  105. package/src/schemas/store/store-audit-schema.ts +1257 -0
  106. package/src/schemas/store/store-schema.ts +661 -0
  107. package/src/schemas/store/store-settings-schema.ts +231 -0
  108. package/src/schemas/types.ts +67 -0
  109. package/src/types/events.ts +646 -0
  110. package/src/utils/errorHandler.ts +44 -0
  111. package/src/utils/subdomain.ts +19 -0
  112. package/tsconfig.json +21 -0
@@ -0,0 +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
+ }