@axova/shared 1.0.0 → 1.0.2

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 (33) hide show
  1. package/dist/index.d.ts +0 -1
  2. package/dist/index.js +0 -2
  3. package/dist/middleware/storeOwnership.js +3 -22
  4. package/dist/middleware/storeValidationMiddleware.js +39 -16
  5. package/dist/schemas/admin/admin-schema.d.ts +2 -2
  6. package/dist/schemas/ai-moderation/ai-moderation-schema.d.ts +2 -2
  7. package/dist/schemas/index.d.ts +0 -26
  8. package/dist/schemas/index.js +3 -121
  9. package/dist/schemas/store/storefront-config-schema.d.ts +1320 -0
  10. package/dist/schemas/store/storefront-config-schema.js +109 -0
  11. package/dist/utils/subdomain.d.ts +1 -1
  12. package/dist/utils/subdomain.js +15 -10
  13. package/package.json +1 -1
  14. package/src/index.ts +0 -3
  15. package/src/middleware/storeOwnership.ts +3 -21
  16. package/src/middleware/storeValidationMiddleware.ts +50 -17
  17. package/src/schemas/index.ts +5 -189
  18. package/src/utils/subdomain.ts +15 -11
  19. package/nul +0 -8
  20. package/src/schemas/compliance/compliance-schema.ts +0 -927
  21. package/src/schemas/compliance/kyc-schema.ts +0 -649
  22. package/src/schemas/customer/customer-schema.ts +0 -576
  23. package/src/schemas/inventory/inventory-tables.ts +0 -1927
  24. package/src/schemas/inventory/lot-tables.ts +0 -799
  25. package/src/schemas/order/order-schema.ts +0 -1400
  26. package/src/schemas/product/discount-relations.ts +0 -44
  27. package/src/schemas/product/discount-schema.ts +0 -464
  28. package/src/schemas/product/product-relations.ts +0 -187
  29. package/src/schemas/product/product-schema.ts +0 -955
  30. package/src/schemas/store/ethiopian_business_api.md.resolved +0 -212
  31. package/src/schemas/store/store-audit-schema.ts +0 -1257
  32. package/src/schemas/store/store-schema.ts +0 -661
  33. package/src/schemas/store/store-settings-schema.ts +0 -231
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.storefrontConfigRelations = exports.storefrontConfigs = void 0;
4
+ const cuid2_1 = require("@paralleldrive/cuid2");
5
+ const drizzle_orm_1 = require("drizzle-orm");
6
+ const pg_core_1 = require("drizzle-orm/pg-core");
7
+ const store_schema_1 = require("./store-schema");
8
+ exports.storefrontConfigs = (0, pg_core_1.pgTable)("storefront_configs", {
9
+ id: (0, pg_core_1.text)("id")
10
+ .primaryKey()
11
+ .$defaultFn(() => (0, cuid2_1.createId)()),
12
+ storeId: (0, pg_core_1.text)("store_id")
13
+ .notNull()
14
+ .references(() => store_schema_1.stores.id, { onDelete: "cascade" }),
15
+ // Setup Status Tracking
16
+ setupStatus: (0, pg_core_1.varchar)("setup_status", { length: 30 })
17
+ .notNull()
18
+ .default("INCOMPLETE")
19
+ .$type(),
20
+ setupProgress: (0, pg_core_1.integer)("setup_progress").notNull().default(0), // 0-100
21
+ setupSteps: (0, pg_core_1.jsonb)("setup_steps")
22
+ .$type()
23
+ .default({
24
+ branding: { completed: false },
25
+ layout: { completed: false },
26
+ pages: { completed: false },
27
+ localization: { completed: false },
28
+ theme: { completed: false },
29
+ seo: { completed: false },
30
+ }),
31
+ // Branding Configuration
32
+ branding: (0, pg_core_1.jsonb)("branding")
33
+ .$type()
34
+ .notNull(),
35
+ // Layout Configuration
36
+ layout: (0, pg_core_1.jsonb)("layout")
37
+ .$type()
38
+ .notNull(),
39
+ // Pages Configuration
40
+ pages: (0, pg_core_1.jsonb)("pages")
41
+ .$type()
42
+ .notNull(),
43
+ // Localization Configuration
44
+ localization: (0, pg_core_1.jsonb)("localization")
45
+ .$type()
46
+ .notNull(),
47
+ // Theme Configuration
48
+ theme: (0, pg_core_1.jsonb)("theme")
49
+ .$type()
50
+ .default({
51
+ mode: "light",
52
+ radius: 8,
53
+ animations: true,
54
+ transitions: true,
55
+ effects: {
56
+ blur: true,
57
+ shadows: true,
58
+ gradients: true,
59
+ },
60
+ }),
61
+ // SEO Configuration
62
+ seo: (0, pg_core_1.jsonb)("seo")
63
+ .$type()
64
+ .default({}),
65
+ // Text Limits and Validation
66
+ textLimits: (0, pg_core_1.jsonb)("text_limits")
67
+ .$type()
68
+ .default({
69
+ homeHero: {
70
+ badgeTextMax: 48,
71
+ titleMax: 64,
72
+ subtitleMax: 160,
73
+ newsletterPlaceholderMax: 48,
74
+ newsletterButtonTextMax: 24,
75
+ trustedByTextMax: 48,
76
+ },
77
+ }),
78
+ // Advanced Features
79
+ features: (0, pg_core_1.jsonb)("features")
80
+ .$type()
81
+ .default({}),
82
+ // Version Control
83
+ version: (0, pg_core_1.integer)("version").notNull().default(1),
84
+ publishedVersion: (0, pg_core_1.integer)("published_version"),
85
+ isDraft: (0, pg_core_1.boolean)("is_draft").notNull().default(true),
86
+ // Metadata
87
+ lastEditedBy: (0, pg_core_1.text)("last_edited_by"),
88
+ publishedAt: (0, pg_core_1.timestamp)("published_at", { withTimezone: true }),
89
+ publishedBy: (0, pg_core_1.text)("published_by"),
90
+ createdAt: (0, pg_core_1.timestamp)("created_at", { withTimezone: true })
91
+ .defaultNow()
92
+ .notNull(),
93
+ updatedAt: (0, pg_core_1.timestamp)("updated_at", { withTimezone: true })
94
+ .defaultNow()
95
+ .notNull(),
96
+ }, (table) => ({
97
+ storeIdIndex: (0, pg_core_1.index)("idx_storefront_configs_store_id").on(table.storeId),
98
+ storeIdUnique: (0, pg_core_1.unique)("idx_storefront_configs_store_unique").on(table.storeId),
99
+ setupStatusIndex: (0, pg_core_1.index)("idx_storefront_configs_setup_status").on(table.setupStatus),
100
+ setupProgressIndex: (0, pg_core_1.index)("idx_storefront_configs_setup_progress").on(table.setupProgress),
101
+ versionIndex: (0, pg_core_1.index)("idx_storefront_configs_version").on(table.version),
102
+ isDraftIndex: (0, pg_core_1.index)("idx_storefront_configs_draft").on(table.isDraft),
103
+ }));
104
+ exports.storefrontConfigRelations = (0, drizzle_orm_1.relations)(exports.storefrontConfigs, ({ one }) => ({
105
+ store: one(store_schema_1.stores, {
106
+ fields: [exports.storefrontConfigs.storeId],
107
+ references: [store_schema_1.stores.id],
108
+ }),
109
+ }));
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Checks if a subdomain is available.
2
+ * Checks if a subdomain is available by calling the store service API.
3
3
  * @param subdomain The subdomain to check.
4
4
  * @returns {Promise<boolean>} True if available, false if taken.
5
5
  */
@@ -1,20 +1,25 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isSubdomainAvailable = void 0;
4
- const drizzle_orm_1 = require("drizzle-orm");
5
- const db_1 = require("../lib/db");
6
- const store_schema_1 = require("../schemas/store/store-schema");
7
4
  /**
8
- * Checks if a subdomain is available.
5
+ * Checks if a subdomain is available by calling the store service API.
9
6
  * @param subdomain The subdomain to check.
10
7
  * @returns {Promise<boolean>} True if available, false if taken.
11
8
  */
12
9
  const isSubdomainAvailable = async (subdomain) => {
13
- const existingStore = await db_1.db
14
- .select()
15
- .from(store_schema_1.stores)
16
- .where((0, drizzle_orm_1.eq)(store_schema_1.stores.subdomain, subdomain))
17
- .limit(1);
18
- return existingStore.length === 0;
10
+ const baseUrl = process.env.STORE_SERVICE_URL || "http://localhost:3001";
11
+ const url = `${baseUrl}/api/stores/subdomain/${encodeURIComponent(subdomain)}/check`;
12
+ try {
13
+ const res = await fetch(url, { method: "GET" });
14
+ if (res.ok) {
15
+ const data = (await res.json());
16
+ return data.available;
17
+ }
18
+ }
19
+ catch (error) {
20
+ console.error('Failed to check subdomain availability:', error);
21
+ }
22
+ // Default to unavailable on error to be safe
23
+ return false;
19
24
  };
20
25
  exports.isSubdomainAvailable = isSubdomainAvailable;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axova/shared",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Shared utilities, models, and libraries for Axova platform",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/index.ts CHANGED
@@ -15,9 +15,6 @@ export * from "./middleware/storeOwnership";
15
15
  export * from "./middleware/storeValidationMiddleware";
16
16
  export * from "./middleware/userAuth";
17
17
 
18
- // Schemas - Organized by Service
19
- export * from "./schemas";
20
-
21
18
  // Types and Interfaces
22
19
  export * from "./types/events";
23
20
 
@@ -1,7 +1,4 @@
1
- import { eq } from "drizzle-orm";
2
1
  import type { FastifyReply, FastifyRequest } from "fastify";
3
- import { db } from "../lib/db";
4
- import { stores } from "../schemas/store/store-schema";
5
2
  import {
6
3
  createServiceAuthenticator,
7
4
  getServiceAuthConfigFromEnv,
@@ -158,25 +155,10 @@ async function fetchStoreById(storeId: string): Promise<{
158
155
  const store = data?.store || data?.data?.store || null;
159
156
  if (store) return store;
160
157
  }
161
- } catch {
162
- // ignore network error and try DB fallback when possible
163
- }
164
- // DB fallback (primarily for in-process store-service)
165
- try {
166
- const result = await db
167
- .select({
168
- id: stores.id,
169
- storeName: stores.storeName,
170
- isActive: stores.isActive,
171
- userId: stores.userId,
172
- })
173
- .from(stores)
174
- .where(eq(stores.id, storeId))
175
- .limit(1);
176
- return result[0] || null;
177
- } catch {
178
- return null;
158
+ } catch (error) {
159
+ console.error('Failed to fetch store from store service:', error);
179
160
  }
161
+ return null;
180
162
  }
181
163
 
182
164
  async function attachStoreInfoIfPossible(
@@ -1,7 +1,8 @@
1
- import { eq } from "drizzle-orm";
2
1
  import { FastifyReply, FastifyRequest } from "fastify";
3
- import { db } from "../lib/db";
4
- import { stores } from "../schemas/store/store-schema";
2
+ import {
3
+ createServiceAuthenticator,
4
+ getServiceAuthConfigFromEnv,
5
+ } from "./serviceAuth";
5
6
 
6
7
  // Store cache to reduce database calls
7
8
  const storeCache = new Map<
@@ -143,19 +144,10 @@ export const validateStoreMiddleware = (
143
144
  }
144
145
  }
145
146
 
146
- // Validate store exists and get details from database
147
- const store = await db
148
- .select({
149
- id: stores.id,
150
- storeName: stores.storeName,
151
- isActive: stores.isActive,
152
- userId: stores.userId,
153
- })
154
- .from(stores)
155
- .where(eq(stores.id, storeId))
156
- .limit(1);
157
-
158
- if (store.length === 0) {
147
+ // Validate store exists and get details from store service API
148
+ const fetchedStore = await fetchStoreById(storeId);
149
+
150
+ if (!fetchedStore) {
159
151
  // Cache negative result
160
152
  storeCache.set(storeId, { isValid: false, timestamp: Date.now() });
161
153
 
@@ -166,7 +158,7 @@ export const validateStoreMiddleware = (
166
158
  });
167
159
  }
168
160
 
169
- const storeData = store[0];
161
+ const storeData = fetchedStore;
170
162
 
171
163
  // Check if store is active when required
172
164
  if (requireActive && !storeData.isActive) {
@@ -245,3 +237,44 @@ export const requireOwnedStore = validateStoreMiddleware({
245
237
  export const requireAnyStore = validateStoreMiddleware({
246
238
  requireActive: false,
247
239
  });
240
+
241
+ // Helper function to fetch store from store service
242
+ async function fetchStoreById(storeId: string): Promise<{
243
+ id: string;
244
+ storeName: string;
245
+ isActive: boolean;
246
+ userId: string;
247
+ } | null> {
248
+ const baseUrl = process.env.STORE_SERVICE_URL || "http://localhost:3001";
249
+ const url = `${baseUrl}/internal/stores/${encodeURIComponent(storeId)}`;
250
+
251
+ let token: string | undefined;
252
+ try {
253
+ const cfg = getServiceAuthConfigFromEnv();
254
+ token = createServiceAuthenticator(cfg).generateServiceToken(
255
+ process.env.SERVICE_NAME || "shared-middleware",
256
+ ["store:read"],
257
+ );
258
+ } catch {
259
+ // Development fallback tokens accepted by store service
260
+ const isDev = process.env.NODE_ENV !== "production";
261
+ if (isDev) token = "dev-access";
262
+ }
263
+
264
+ const headers: Record<string, string> = {
265
+ "Content-Type": "application/json",
266
+ };
267
+ if (token) headers["x-service-token"] = token;
268
+
269
+ try {
270
+ const res = await fetch(url, { method: "GET", headers });
271
+ if (res.ok) {
272
+ const data = (await res.json()) as any;
273
+ const store = data?.store || data?.data?.store || null;
274
+ if (store) return store;
275
+ }
276
+ } catch (error) {
277
+ console.error('Failed to fetch store from store service:', error);
278
+ }
279
+ return null;
280
+ }
@@ -1,189 +1,5 @@
1
- // Export the ACTUAL Drizzle table objects for database operations
2
-
3
- // Export event and Kafka functionality
4
- export {
5
- type AxovaKafkaConfig,
6
- createKafkaInstance,
7
- getKafkaConfigFromEnv,
8
- getKafkaInstance,
9
- } from "../events/kafka";
10
- // Export customer events and configuration
11
- export {
12
- CustomerServiceConfig,
13
- CustomerServiceEvents,
14
- } from "../interfaces/customer-events";
15
-
16
- // Export inventory events and configuration
17
- export { ServiceConfig, ServiceEvents } from "../interfaces/inventory-events";
18
- // Export inventory-specific types
19
- export type {
20
- ABCClassification,
21
- AIRecommendation,
22
- // Automation types
23
- AutomationRule,
24
- AutomationRuleFilter,
25
- BatchFilter,
26
- // Batch tracking types
27
- BatchInfo,
28
- CountItemRequest,
29
- CreateAutomationRuleRequest,
30
- CreateBatchRequest,
31
- CreateCycleCountRequest,
32
- CreateInventoryItemRequest,
33
- CreatePOSLocationRequest,
34
- CreateWarehouseRequest,
35
- // Cycle count types
36
- CycleCount,
37
- CycleCountFilter,
38
- CycleCountItem,
39
- DashboardMetrics,
40
- ExpiryReport,
41
- ForecastData,
42
- InventoryFilter,
43
- InventoryInsight,
44
- // Core types
45
- InventoryItem,
46
- InventoryOverview,
47
- // Insights and analytics types
48
- InventorySnapshot,
49
- LowStockAlert,
50
- // Common operation types
51
- OperationResult,
52
- PaginatedResult,
53
- POSLocation,
54
- QuantityUpdate,
55
- ReorderRecommendation,
56
- StockMovementReport,
57
- StockValuation,
58
- TenantContext,
59
- TransferFilter,
60
- TransferItem,
61
- // Transfer types
62
- TransferRequest,
63
- UpdateInventoryItemRequest,
64
- UserContext,
65
- VelocityAnalysis,
66
- Warehouse,
67
- } from "../interfaces/inventory-types";
68
- export * from "../types/events";
69
- // Admin Management
70
- export * from "./admin/admin-schema";
71
- // AI Moderation
72
- export * from "./ai-moderation/ai-moderation-schema";
73
- // Common Schemas
74
- export * from "./common/common-schemas";
75
- // Compliance Schemas
76
- export * from "./compliance/compliance-schema";
77
- export * from "./compliance/kyc-schema";
78
- export {
79
- storeKyc,
80
- kycVerificationHistory,
81
- kycDocuments,
82
- kycAnalytics,
83
- kycWebhooksLog,
84
- } from "./compliance/kyc-schema";
85
- // Customer Management Schemas
86
- export * from "./customer/customer-schema";
87
- // Customer Schema Exports
88
- export {
89
- customerAddresses,
90
- customerInteractionHistory,
91
- customerNotes,
92
- customerPreferences,
93
- customerReviews,
94
- customerSupportTickets,
95
- customers,
96
- customerVisitHistory,
97
- } from "./customer/customer-schema";
98
- // Core Inventory tables and co-located schemas
99
- export * from "./inventory/inventory-tables";
100
- export {
101
- inventory,
102
- inventoryMovements,
103
- inventoryTransferItems,
104
- inventoryTransfers,
105
- posLocations,
106
- productSuppliers,
107
- purchaseOrderItems,
108
- purchaseOrders,
109
- qualityControls,
110
- qualityTemplates,
111
- supplierQualityRatings,
112
- suppliers,
113
- warehouses,
114
- } from "./inventory/inventory-tables";
115
-
116
- // Lot & Batch Management schemas
117
- export {
118
- alertSeverityEnum,
119
- alertStatusEnum,
120
- alertTypeEnum,
121
- inventoryLotAlerts,
122
- inventoryLotMerges,
123
- inventoryLotMovements,
124
- inventoryLots,
125
- inventoryLotSplits,
126
- lotMovementTypeEnum,
127
- lotStatusEnum,
128
- // Zod Schemas for Lot Operations
129
- LotSchema,
130
- InitializeProductInventorySchema,
131
- CreateLotSchema,
132
- ReserveLotQuantitySchema,
133
- ReleaseLotReservationSchema,
134
- AdjustLotQuantitySchema,
135
- TransferLotSchema,
136
- MergeLotsSchema,
137
- SplitLotSchema,
138
- GetLotsQuerySchema,
139
- GetAvailableLotsSchema,
140
- LotAnalyticsSchema,
141
- } from "./inventory/lot-tables";
142
-
143
- // Order schemas
144
- export {
145
- addressTypeEnum,
146
- discountTypeEnum,
147
- fulfillmentStatusEnum,
148
- orderAddresses,
149
- orderAddressesRelations,
150
- orderDiscounts,
151
- orderDiscountsRelations,
152
- orderFulfillments,
153
- orderFulfillmentsRelations,
154
- orderHistory,
155
- orderHistoryRelations,
156
- orderItems,
157
- orderItemsRelations,
158
- orderNotes,
159
- orderNotesRelations,
160
- orderPayments,
161
- orderPaymentsRelations,
162
- orderPriorityEnum,
163
- orderStatusEnum,
164
- orders,
165
- ordersRelations,
166
- // Enums
167
- orderTypeEnum,
168
- paymentMethodEnum,
169
- paymentStatusEnum,
170
- refundReasonEnum,
171
- } from "./order/order-schema";
172
- export * from "./product/product-relations";
173
- // Product Management Schemas
174
- export * from "./product/product-schema";
175
- export * from "./product/product-relations";
176
- export * from "./product/discount-schema";
177
- export * from "./product/discount-relations";
178
- // Store Management
179
- export * from "./store/store-schema";
180
- export * from "./store/store-settings-schema";
181
- export * from "./store/store-audit-schema";
182
- export {
183
- storeSettings,
184
- marketRegions,
185
- storeSettingsRelations,
186
- marketRegionsRelations,
187
- } from "./store/store-settings-schema";
188
- // Types
189
- export * from "./types";
1
+ // Schemas have been moved to individual services
2
+ // Each service now maintains its own schemas in their src/[service-name]-schema folder
3
+
4
+ // Common types used across services
5
+ export * from "./types";
@@ -1,19 +1,23 @@
1
- import { eq } from "drizzle-orm";
2
- import { db } from "../lib/db";
3
- import { stores } from "../schemas/store/store-schema";
4
-
5
1
  /**
6
- * Checks if a subdomain is available.
2
+ * Checks if a subdomain is available by calling the store service API.
7
3
  * @param subdomain The subdomain to check.
8
4
  * @returns {Promise<boolean>} True if available, false if taken.
9
5
  */
10
6
  export const isSubdomainAvailable = async (
11
7
  subdomain: string,
12
8
  ): Promise<boolean> => {
13
- const existingStore = await db
14
- .select()
15
- .from(stores)
16
- .where(eq(stores.subdomain, subdomain))
17
- .limit(1);
18
- return existingStore.length === 0;
9
+ const baseUrl = process.env.STORE_SERVICE_URL || "http://localhost:3001";
10
+ const url = `${baseUrl}/api/stores/subdomain/${encodeURIComponent(subdomain)}/check`;
11
+
12
+ try {
13
+ const res = await fetch(url, { method: "GET" });
14
+ if (res.ok) {
15
+ const data = (await res.json()) as { available: boolean };
16
+ return data.available;
17
+ }
18
+ } catch (error) {
19
+ console.error('Failed to check subdomain availability:', error);
20
+ }
21
+ // Default to unavailable on error to be safe
22
+ return false;
19
23
  };
package/nul DELETED
@@ -1,8 +0,0 @@
1
- At line:1 char:40
2
- + Get-NetTCPConnection -LocalPort 3005 2> | Select-Object LocalAddress, ...
3
- + ~
4
- Missing file specification after redirection operator.
5
- + CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordEx
6
- ception
7
- + FullyQualifiedErrorId : MissingFileSpecification
8
-