@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,153 +1,153 @@
1
- import { createId } from "@paralleldrive/cuid2";
2
- import { APIError } from "../utils/errorHandler";
3
-
4
- export interface AuthOrganizationCreateRequest {
5
- name: string;
6
- slug: string;
7
- logo?: string;
8
- metadata?: Record<string, unknown>;
9
- userId?: string;
10
- keepCurrentActiveOrganization?: boolean;
11
- }
12
-
13
- export interface AuthOrganizationResponse {
14
- id: string;
15
- name: string;
16
- slug: string;
17
- logo?: string;
18
- metadata?: Record<string, unknown>;
19
- createdAt: Date;
20
- updatedAt?: Date;
21
- }
22
-
23
- /**
24
- * Creates an organization using the auth service
25
- * @param organizationData Organization data to create
26
- * @param headers Authentication headers to forward
27
- * @returns Promise resolving to created organization data
28
- */
29
- export const createAuthOrganization = async (
30
- organizationData: AuthOrganizationCreateRequest,
31
- headers?: Record<string, string>,
32
- ): Promise<AuthOrganizationResponse> => {
33
- try {
34
- console.log("Creating organization:", {
35
- name: organizationData.name,
36
- slug: organizationData.slug,
37
- userId: organizationData.userId,
38
- hasHeaders: !!headers,
39
- });
40
-
41
- // Prepare payload matching auth service expectations
42
- const payload = {
43
- name: organizationData.name,
44
- slug: organizationData.slug,
45
- ...(organizationData.logo && { logo: organizationData.logo }),
46
- ...(organizationData.metadata && { metadata: organizationData.metadata }),
47
- };
48
-
49
- // Make direct HTTP request to auth service
50
- const authBaseUrl =
51
- process.env.NEXT_PUBLIC_AUTH_URL || "http://localhost:4000";
52
- const url = `${authBaseUrl}/api/auth/organization/create`;
53
-
54
- const fetchOptions: RequestInit = {
55
- method: "POST",
56
- headers: {
57
- "Content-Type": "application/json",
58
- ...headers,
59
- },
60
- body: JSON.stringify(payload),
61
- };
62
-
63
- console.log("Sending request to auth service:", url);
64
- const response = await fetch(url, fetchOptions);
65
-
66
- console.log("Auth service response:", {
67
- status: response.status,
68
- statusText: response.statusText,
69
- ok: response.ok,
70
- headers: Object.fromEntries(response.headers.entries()),
71
- });
72
-
73
- // Check HTTP response status
74
- if (!response.ok) {
75
- const errorText = await response.text();
76
- console.error("Auth service HTTP error:", {
77
- status: response.status,
78
- statusText: response.statusText,
79
- body: errorText,
80
- });
81
-
82
- throw new APIError(
83
- `Auth service error: ${response.status} ${response.statusText}`,
84
- response.status,
85
- { code: "AUTH_HTTP_ERROR", response: errorText },
86
- );
87
- }
88
-
89
- // Parse JSON response
90
- let responseData: any;
91
- try {
92
- responseData = await response.json();
93
- } catch (parseError) {
94
- console.error("Failed to parse auth service response:", parseError);
95
- throw new APIError("Invalid response format from auth service", 500, {
96
- code: "JSON_PARSE_ERROR",
97
- originalError: parseError,
98
- });
99
- }
100
-
101
- // Auth service returns organization data directly
102
- // Check if response has the required organization fields
103
- if (responseData.id && responseData.name) {
104
- console.log("Organization created successfully:", {
105
- id: responseData.id,
106
- name: responseData.name,
107
- slug: responseData.slug,
108
- });
109
- } else {
110
- console.error("Invalid organization response:", responseData);
111
- throw new APIError(
112
- "Invalid organization data format from auth service",
113
- 500,
114
- { code: "INVALID_ORGANIZATION_DATA", response: responseData },
115
- );
116
- }
117
-
118
- // Return structured organization data (responseData contains the org data directly)
119
- return {
120
- id: responseData.id,
121
- name: responseData.name,
122
- slug: responseData.slug,
123
- logo: responseData.logo || undefined,
124
- metadata: responseData.metadata,
125
- createdAt: new Date(responseData.createdAt),
126
- updatedAt: undefined,
127
- };
128
- } catch (error: any) {
129
- console.error("Organization creation failed:", {
130
- message: error.message,
131
- status: error.status || error.statusCode,
132
- code: error.code,
133
- });
134
-
135
- // Handle different error types
136
- if (error instanceof APIError) {
137
- throw error;
138
- }
139
-
140
- if (error.message && error.message.includes("JSON")) {
141
- throw new APIError("Invalid response format from auth service", 500, {
142
- code: "JSON_PARSE_ERROR",
143
- originalError: error.message,
144
- });
145
- }
146
-
147
- throw new APIError(
148
- error.message || "Failed to create organization",
149
- error.status || error.statusCode || 500,
150
- { code: "ORGANIZATION_CREATION_FAILED", originalError: error },
151
- );
152
- }
153
- };
1
+ import { createId } from "@paralleldrive/cuid2";
2
+ import { APIError } from "../utils/errorHandler";
3
+
4
+ export interface AuthOrganizationCreateRequest {
5
+ name: string;
6
+ slug: string;
7
+ logo?: string;
8
+ metadata?: Record<string, unknown>;
9
+ userId?: string;
10
+ keepCurrentActiveOrganization?: boolean;
11
+ }
12
+
13
+ export interface AuthOrganizationResponse {
14
+ id: string;
15
+ name: string;
16
+ slug: string;
17
+ logo?: string;
18
+ metadata?: Record<string, unknown>;
19
+ createdAt: Date;
20
+ updatedAt?: Date;
21
+ }
22
+
23
+ /**
24
+ * Creates an organization using the auth service
25
+ * @param organizationData Organization data to create
26
+ * @param headers Authentication headers to forward
27
+ * @returns Promise resolving to created organization data
28
+ */
29
+ export const createAuthOrganization = async (
30
+ organizationData: AuthOrganizationCreateRequest,
31
+ headers?: Record<string, string>,
32
+ ): Promise<AuthOrganizationResponse> => {
33
+ try {
34
+ console.log("Creating organization:", {
35
+ name: organizationData.name,
36
+ slug: organizationData.slug,
37
+ userId: organizationData.userId,
38
+ hasHeaders: !!headers,
39
+ });
40
+
41
+ // Prepare payload matching auth service expectations
42
+ const payload = {
43
+ name: organizationData.name,
44
+ slug: organizationData.slug,
45
+ ...(organizationData.logo && { logo: organizationData.logo }),
46
+ ...(organizationData.metadata && { metadata: organizationData.metadata }),
47
+ };
48
+
49
+ // Make direct HTTP request to auth service
50
+ const authBaseUrl =
51
+ process.env.NEXT_PUBLIC_AUTH_URL || "http://localhost:4000";
52
+ const url = `${authBaseUrl}/api/auth/organization/create`;
53
+
54
+ const fetchOptions: RequestInit = {
55
+ method: "POST",
56
+ headers: {
57
+ "Content-Type": "application/json",
58
+ ...headers,
59
+ },
60
+ body: JSON.stringify(payload),
61
+ };
62
+
63
+ console.log("Sending request to auth service:", url);
64
+ const response = await fetch(url, fetchOptions);
65
+
66
+ console.log("Auth service response:", {
67
+ status: response.status,
68
+ statusText: response.statusText,
69
+ ok: response.ok,
70
+ headers: Object.fromEntries(response.headers.entries()),
71
+ });
72
+
73
+ // Check HTTP response status
74
+ if (!response.ok) {
75
+ const errorText = await response.text();
76
+ console.error("Auth service HTTP error:", {
77
+ status: response.status,
78
+ statusText: response.statusText,
79
+ body: errorText,
80
+ });
81
+
82
+ throw new APIError(
83
+ `Auth service error: ${response.status} ${response.statusText}`,
84
+ response.status,
85
+ { code: "AUTH_HTTP_ERROR", response: errorText },
86
+ );
87
+ }
88
+
89
+ // Parse JSON response
90
+ let responseData: any;
91
+ try {
92
+ responseData = await response.json();
93
+ } catch (parseError) {
94
+ console.error("Failed to parse auth service response:", parseError);
95
+ throw new APIError("Invalid response format from auth service", 500, {
96
+ code: "JSON_PARSE_ERROR",
97
+ originalError: parseError,
98
+ });
99
+ }
100
+
101
+ // Auth service returns organization data directly
102
+ // Check if response has the required organization fields
103
+ if (responseData.id && responseData.name) {
104
+ console.log("Organization created successfully:", {
105
+ id: responseData.id,
106
+ name: responseData.name,
107
+ slug: responseData.slug,
108
+ });
109
+ } else {
110
+ console.error("Invalid organization response:", responseData);
111
+ throw new APIError(
112
+ "Invalid organization data format from auth service",
113
+ 500,
114
+ { code: "INVALID_ORGANIZATION_DATA", response: responseData },
115
+ );
116
+ }
117
+
118
+ // Return structured organization data (responseData contains the org data directly)
119
+ return {
120
+ id: responseData.id,
121
+ name: responseData.name,
122
+ slug: responseData.slug,
123
+ logo: responseData.logo || undefined,
124
+ metadata: responseData.metadata,
125
+ createdAt: new Date(responseData.createdAt),
126
+ updatedAt: undefined,
127
+ };
128
+ } catch (error: any) {
129
+ console.error("Organization creation failed:", {
130
+ message: error.message,
131
+ status: error.status || error.statusCode,
132
+ code: error.code,
133
+ });
134
+
135
+ // Handle different error types
136
+ if (error instanceof APIError) {
137
+ throw error;
138
+ }
139
+
140
+ if (error.message && error.message.includes("JSON")) {
141
+ throw new APIError("Invalid response format from auth service", 500, {
142
+ code: "JSON_PARSE_ERROR",
143
+ originalError: error.message,
144
+ });
145
+ }
146
+
147
+ throw new APIError(
148
+ error.message || "Failed to create organization",
149
+ error.status || error.statusCode || 500,
150
+ { code: "ORGANIZATION_CREATION_FAILED", originalError: error },
151
+ );
152
+ }
153
+ };
package/src/lib/db.ts CHANGED
@@ -1,64 +1,84 @@
1
- import * as dotenv from "dotenv";
2
- import { drizzle } from "drizzle-orm/node-postgres";
3
- import { Pool } from "pg";
4
-
5
- // Load environment variables from .env file
6
- dotenv.config();
7
-
8
- // Configure PostgreSQL connection
9
- const connectionString = process.env.DATABASE_URL;
10
-
11
- if (!connectionString) {
12
- throw new Error("DATABASE_URL environment variable is not set");
13
- }
14
-
15
- // Configure PostgreSQL to handle timestamps and dates properly
16
- const pool = new Pool({
17
- connectionString,
18
- ssl:
19
- process.env.NODE_ENV === "production"
20
- ? { rejectUnauthorized: false }
21
- : false,
22
- // Connection pool configuration to prevent "Connection is closed" errors
23
- max: 20, // Maximum number of clients in the pool
24
- min: 2, // Minimum number of clients in the pool
25
- idleTimeoutMillis: 30000, // Close idle clients after 30 seconds
26
- connectionTimeoutMillis: 10000, // Wait 10 seconds for a connection
27
- // Keep connections alive
28
- keepAlive: true,
29
- keepAliveInitialDelayMillis: 10000,
30
- // Add parsing configuration for timestamps
31
- types: {
32
- getTypeParser: (typeId: number, _format?: string) => {
33
- // Handle dates and timestamps to ensure they're properly converted to JavaScript Date objects
34
- if (
35
- typeId === 1082 ||
36
- typeId === 1083 ||
37
- typeId === 1114 ||
38
- typeId === 1184
39
- ) {
40
- return (val: string) => (val === null ? null : new Date(val));
41
- }
42
- return undefined;
43
- },
44
- },
45
- });
46
-
47
- // Add error handler to the pool
48
- pool.on("error", (err) => {
49
- console.error("❌ Unexpected database pool error:", err);
50
- });
51
-
52
- pool.on("connect", () => {
53
- if (process.env.NODE_ENV === "development") {
54
- console.log("✅ Database pool connection established");
55
- }
56
- });
57
-
58
- // Create a Drizzle ORM instance
59
- export const db = drizzle(pool, {
60
- logger: process.env.NODE_ENV === "development",
61
- });
62
-
63
- // Exported for testing
64
- export { pool };
1
+ import * as dotenv from "dotenv";
2
+ import { drizzle } from "drizzle-orm/node-postgres";
3
+ import { Pool } from "pg";
4
+ import * as storeSchema from "../schemas/store/store-schema";
5
+ import * as storeAuditSchema from "../schemas/store/store-audit-schema";
6
+ import * as storeSettingsSchema from "../schemas/store/store-settings-schema";
7
+ import * as storefrontConfigSchema from "../schemas/store/storefront-config-schema";
8
+ import * as orderSchema from "../schemas/order/order-schema";
9
+ import * as cartSchema from "../schemas/order/cart-schema";
10
+ import * as productSchema from "../schemas/product/product-schema";
11
+ import * as inventorySchema from "../schemas/inventory/inventory-tables";
12
+ import * as customerSchema from "../schemas/customer/customer-schema";
13
+
14
+ // Load environment variables from .env file
15
+ dotenv.config();
16
+
17
+ // Configure PostgreSQL connection
18
+ const connectionString = process.env.DATABASE_URL;
19
+
20
+ if (!connectionString) {
21
+ throw new Error("DATABASE_URL environment variable is not set");
22
+ }
23
+
24
+ // Configure PostgreSQL to handle timestamps and dates properly
25
+ const pool = new Pool({
26
+ connectionString,
27
+ ssl:
28
+ process.env.NODE_ENV === "production"
29
+ ? { rejectUnauthorized: false }
30
+ : false,
31
+ // Connection pool configuration to prevent "Connection is closed" errors
32
+ max: 20, // Maximum number of clients in the pool
33
+ min: 2, // Minimum number of clients in the pool
34
+ idleTimeoutMillis: 30000, // Close idle clients after 30 seconds
35
+ connectionTimeoutMillis: 10000, // Wait 10 seconds for a connection
36
+ // Keep connections alive
37
+ keepAlive: true,
38
+ keepAliveInitialDelayMillis: 10000,
39
+ // Add parsing configuration for timestamps
40
+ types: {
41
+ getTypeParser: (typeId: number, _format?: string) => {
42
+ // Handle dates and timestamps to ensure they're properly converted to JavaScript Date objects
43
+ if (
44
+ typeId === 1082 ||
45
+ typeId === 1083 ||
46
+ typeId === 1114 ||
47
+ typeId === 1184
48
+ ) {
49
+ return (val: string) => (val === null ? null : new Date(val));
50
+ }
51
+ return undefined;
52
+ },
53
+ },
54
+ });
55
+
56
+ // Add error handler to the pool
57
+ pool.on("error", (err) => {
58
+ console.error("❌ Unexpected database pool error:", err);
59
+ });
60
+
61
+ pool.on("connect", () => {
62
+ if (process.env.NODE_ENV === "development") {
63
+ console.log("✅ Database pool connection established");
64
+ }
65
+ });
66
+
67
+ // Create a Drizzle ORM instance with all schemas registered
68
+ export const db = drizzle(pool, {
69
+ schema: {
70
+ ...storeSchema,
71
+ ...storeAuditSchema,
72
+ ...storeSettingsSchema,
73
+ ...storefrontConfigSchema,
74
+ ...orderSchema,
75
+ ...cartSchema,
76
+ ...productSchema,
77
+ ...inventorySchema,
78
+ ...customerSchema,
79
+ },
80
+ logger: process.env.NODE_ENV === "development",
81
+ });
82
+
83
+ // Exported for testing
84
+ export { pool };