@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,180 +1,180 @@
1
- import { createId } from "@paralleldrive/cuid2";
2
- import {
3
- boolean,
4
- decimal,
5
- index,
6
- integer,
7
- jsonb,
8
- pgTable,
9
- text,
10
- timestamp,
11
- varchar,
12
- } from "drizzle-orm/pg-core";
13
-
14
- // Content Scans Table
15
- export const contentScans = pgTable(
16
- "content_scans",
17
- {
18
- id: text("id")
19
- .primaryKey()
20
- .$defaultFn(() => createId()),
21
-
22
- // Content Information
23
- contentId: text("content_id").notNull(),
24
- contentType: varchar("content_type", { length: 50 })
25
- .notNull()
26
- .$type<
27
- | "STORE_DESCRIPTION"
28
- | "PRODUCT_TITLE"
29
- | "PRODUCT_DESCRIPTION"
30
- | "BLOG_POST"
31
- | "USER_REVIEW"
32
- | "STORE_NAME"
33
- | "IMAGE"
34
- | "VIDEO"
35
- >(),
36
-
37
- storeId: text("store_id"),
38
- userId: text("user_id"),
39
-
40
- // Scan Configuration
41
- scanType: varchar("scan_type", { length: 30 })
42
- .$type<"AUTOMATED" | "MANUAL" | "SCHEDULED" | "TRIGGERED">()
43
- .default("AUTOMATED"),
44
-
45
- provider: varchar("provider", { length: 30 })
46
- .default("OPENAI")
47
- .$type<
48
- "OPENAI" | "GOOGLE_PERSPECTIVE" | "AZURE_CONTENT_SAFETY" | "INTERNAL"
49
- >(),
50
-
51
- // Content Data
52
- originalContent: text("original_content").notNull(),
53
- processedContent: text("processed_content"), // Cleaned/normalized content
54
- contentHash: varchar("content_hash", { length: 64 }), // SHA-256 for deduplication
55
-
56
- // Scan Results
57
- flagged: boolean("flagged").notNull().default(false),
58
- confidence: decimal("confidence", { precision: 5, scale: 4 }), // 0-1
59
-
60
- // OpenAI Moderation Categories
61
- categories: jsonb("categories").$type<{
62
- sexual?: boolean;
63
- hate?: boolean;
64
- harassment?: boolean;
65
- selfHarm?: boolean;
66
- sexualMinors?: boolean;
67
- hateThreatening?: boolean;
68
- violenceGraphic?: boolean;
69
- selfHarmIntent?: boolean;
70
- selfHarmInstructions?: boolean;
71
- harassmentThreatening?: boolean;
72
- violence?: boolean;
73
- }>(),
74
-
75
- categoryScores: jsonb("category_scores").$type<{
76
- sexual?: number;
77
- hate?: number;
78
- harassment?: number;
79
- selfHarm?: number;
80
- sexualMinors?: number;
81
- hateThreatening?: number;
82
- violenceGraphic?: number;
83
- selfHarmIntent?: number;
84
- selfHarmInstructions?: number;
85
- harassmentThreatening?: number;
86
- violence?: number;
87
- }>(),
88
-
89
- // Custom Rules and Patterns
90
- customViolations: jsonb("custom_violations")
91
- .$type<
92
- Array<{
93
- ruleId: string;
94
- ruleName: string;
95
- matched: boolean;
96
- confidence: number;
97
- matchedText?: string;
98
- }>
99
- >()
100
- .default([]),
101
-
102
- // Status and Actions
103
- status: varchar("status", { length: 20 })
104
- .notNull()
105
- .default("COMPLETED")
106
- .$type<"PENDING" | "PROCESSING" | "COMPLETED" | "FAILED" | "CANCELLED">(),
107
-
108
- actionTaken: varchar("action_taken", { length: 30 }).$type<
109
- "NONE" | "FLAGGED" | "BLOCKED" | "QUARANTINED" | "REPORTED"
110
- >(),
111
-
112
- // Processing Metadata
113
- processingTime: integer("processing_time"), // milliseconds
114
- cost: decimal("cost", { precision: 8, scale: 6 }), // API cost in USD
115
-
116
- createdAt: timestamp("created_at", { withTimezone: true })
117
- .defaultNow()
118
- .notNull(),
119
- },
120
- (table) => ({
121
- contentIdIndex: index("idx_scans_content").on(table.contentId),
122
- storeIdIndex: index("idx_scans_store").on(table.storeId),
123
- flaggedIndex: index("idx_scans_flagged").on(
124
- table.flagged,
125
- table.confidence,
126
- ),
127
- statusIndex: index("idx_scans_status").on(table.status),
128
- contentTypeIndex: index("idx_scans_content_type").on(table.contentType),
129
- hashIndex: index("idx_scans_hash").on(table.contentHash),
130
- }),
131
- );
132
-
133
- // Moderation Rules Table
134
- export const moderationRules = pgTable(
135
- "moderation_rules",
136
- {
137
- id: text("id")
138
- .primaryKey()
139
- .$defaultFn(() => createId()),
140
-
141
- name: varchar("name", { length: 100 }).notNull(),
142
- description: text("description"),
143
-
144
- ruleType: varchar("rule_type", { length: 30 })
145
- .notNull()
146
- .$type<
147
- "KEYWORD_FILTER" | "PATTERN_MATCH" | "ML_CLASSIFIER" | "CUSTOM_LOGIC"
148
- >(),
149
-
150
- severity: varchar("severity", { length: 20 })
151
- .notNull()
152
- .$type<"LOW" | "MEDIUM" | "HIGH" | "CRITICAL">(),
153
-
154
- // Rule Configuration
155
- configuration: jsonb("configuration").$type<{
156
- keywords?: string[];
157
- patterns?: string[];
158
- threshold?: number;
159
- customLogic?: string;
160
- }>(),
161
-
162
- // Targeting
163
- contentTypes: jsonb("content_types").$type<string[]>().default([]),
164
- storeTypes: jsonb("store_types").$type<string[]>().default([]),
165
-
166
- isActive: boolean("is_active").notNull().default(true),
167
-
168
- createdAt: timestamp("created_at", { withTimezone: true })
169
- .defaultNow()
170
- .notNull(),
171
- updatedAt: timestamp("updated_at", { withTimezone: true })
172
- .defaultNow()
173
- .notNull(),
174
- },
175
- (table) => ({
176
- nameIndex: index("idx_rules_name").on(table.name),
177
- typeIndex: index("idx_rules_type").on(table.ruleType),
178
- activeIndex: index("idx_rules_active").on(table.isActive),
179
- }),
180
- );
1
+ import { createId } from "@paralleldrive/cuid2";
2
+ import {
3
+ boolean,
4
+ decimal,
5
+ index,
6
+ integer,
7
+ jsonb,
8
+ pgTable,
9
+ text,
10
+ timestamp,
11
+ varchar,
12
+ } from "drizzle-orm/pg-core";
13
+
14
+ // Content Scans Table
15
+ export const contentScans = pgTable(
16
+ "content_scans",
17
+ {
18
+ id: text("id")
19
+ .primaryKey()
20
+ .$defaultFn(() => createId()),
21
+
22
+ // Content Information
23
+ contentId: text("content_id").notNull(),
24
+ contentType: varchar("content_type", { length: 50 })
25
+ .notNull()
26
+ .$type<
27
+ | "STORE_DESCRIPTION"
28
+ | "PRODUCT_TITLE"
29
+ | "PRODUCT_DESCRIPTION"
30
+ | "BLOG_POST"
31
+ | "USER_REVIEW"
32
+ | "STORE_NAME"
33
+ | "IMAGE"
34
+ | "VIDEO"
35
+ >(),
36
+
37
+ storeId: text("store_id"),
38
+ userId: text("user_id"),
39
+
40
+ // Scan Configuration
41
+ scanType: varchar("scan_type", { length: 30 })
42
+ .$type<"AUTOMATED" | "MANUAL" | "SCHEDULED" | "TRIGGERED">()
43
+ .default("AUTOMATED"),
44
+
45
+ provider: varchar("provider", { length: 30 })
46
+ .default("OPENAI")
47
+ .$type<
48
+ "OPENAI" | "GOOGLE_PERSPECTIVE" | "AZURE_CONTENT_SAFETY" | "INTERNAL"
49
+ >(),
50
+
51
+ // Content Data
52
+ originalContent: text("original_content").notNull(),
53
+ processedContent: text("processed_content"), // Cleaned/normalized content
54
+ contentHash: varchar("content_hash", { length: 64 }), // SHA-256 for deduplication
55
+
56
+ // Scan Results
57
+ flagged: boolean("flagged").notNull().default(false),
58
+ confidence: decimal("confidence", { precision: 5, scale: 4 }), // 0-1
59
+
60
+ // OpenAI Moderation Categories
61
+ categories: jsonb("categories").$type<{
62
+ sexual?: boolean;
63
+ hate?: boolean;
64
+ harassment?: boolean;
65
+ selfHarm?: boolean;
66
+ sexualMinors?: boolean;
67
+ hateThreatening?: boolean;
68
+ violenceGraphic?: boolean;
69
+ selfHarmIntent?: boolean;
70
+ selfHarmInstructions?: boolean;
71
+ harassmentThreatening?: boolean;
72
+ violence?: boolean;
73
+ }>(),
74
+
75
+ categoryScores: jsonb("category_scores").$type<{
76
+ sexual?: number;
77
+ hate?: number;
78
+ harassment?: number;
79
+ selfHarm?: number;
80
+ sexualMinors?: number;
81
+ hateThreatening?: number;
82
+ violenceGraphic?: number;
83
+ selfHarmIntent?: number;
84
+ selfHarmInstructions?: number;
85
+ harassmentThreatening?: number;
86
+ violence?: number;
87
+ }>(),
88
+
89
+ // Custom Rules and Patterns
90
+ customViolations: jsonb("custom_violations")
91
+ .$type<
92
+ Array<{
93
+ ruleId: string;
94
+ ruleName: string;
95
+ matched: boolean;
96
+ confidence: number;
97
+ matchedText?: string;
98
+ }>
99
+ >()
100
+ .default([]),
101
+
102
+ // Status and Actions
103
+ status: varchar("status", { length: 20 })
104
+ .notNull()
105
+ .default("COMPLETED")
106
+ .$type<"PENDING" | "PROCESSING" | "COMPLETED" | "FAILED" | "CANCELLED">(),
107
+
108
+ actionTaken: varchar("action_taken", { length: 30 }).$type<
109
+ "NONE" | "FLAGGED" | "BLOCKED" | "QUARANTINED" | "REPORTED"
110
+ >(),
111
+
112
+ // Processing Metadata
113
+ processingTime: integer("processing_time"), // milliseconds
114
+ cost: decimal("cost", { precision: 8, scale: 6 }), // API cost in USD
115
+
116
+ createdAt: timestamp("created_at", { withTimezone: true })
117
+ .defaultNow()
118
+ .notNull(),
119
+ },
120
+ (table) => ({
121
+ contentIdIndex: index("idx_scans_content").on(table.contentId),
122
+ storeIdIndex: index("idx_scans_store").on(table.storeId),
123
+ flaggedIndex: index("idx_scans_flagged").on(
124
+ table.flagged,
125
+ table.confidence,
126
+ ),
127
+ statusIndex: index("idx_scans_status").on(table.status),
128
+ contentTypeIndex: index("idx_scans_content_type").on(table.contentType),
129
+ hashIndex: index("idx_scans_hash").on(table.contentHash),
130
+ }),
131
+ );
132
+
133
+ // Moderation Rules Table
134
+ export const moderationRules = pgTable(
135
+ "moderation_rules",
136
+ {
137
+ id: text("id")
138
+ .primaryKey()
139
+ .$defaultFn(() => createId()),
140
+
141
+ name: varchar("name", { length: 100 }).notNull(),
142
+ description: text("description"),
143
+
144
+ ruleType: varchar("rule_type", { length: 30 })
145
+ .notNull()
146
+ .$type<
147
+ "KEYWORD_FILTER" | "PATTERN_MATCH" | "ML_CLASSIFIER" | "CUSTOM_LOGIC"
148
+ >(),
149
+
150
+ severity: varchar("severity", { length: 20 })
151
+ .notNull()
152
+ .$type<"LOW" | "MEDIUM" | "HIGH" | "CRITICAL">(),
153
+
154
+ // Rule Configuration
155
+ configuration: jsonb("configuration").$type<{
156
+ keywords?: string[];
157
+ patterns?: string[];
158
+ threshold?: number;
159
+ customLogic?: string;
160
+ }>(),
161
+
162
+ // Targeting
163
+ contentTypes: jsonb("content_types").$type<string[]>().default([]),
164
+ storeTypes: jsonb("store_types").$type<string[]>().default([]),
165
+
166
+ isActive: boolean("is_active").notNull().default(true),
167
+
168
+ createdAt: timestamp("created_at", { withTimezone: true })
169
+ .defaultNow()
170
+ .notNull(),
171
+ updatedAt: timestamp("updated_at", { withTimezone: true })
172
+ .defaultNow()
173
+ .notNull(),
174
+ },
175
+ (table) => ({
176
+ nameIndex: index("idx_rules_name").on(table.name),
177
+ typeIndex: index("idx_rules_type").on(table.ruleType),
178
+ activeIndex: index("idx_rules_active").on(table.isActive),
179
+ }),
180
+ );
@@ -1,108 +1,108 @@
1
- import { z } from "zod";
2
-
3
- // =====================================================
4
- // SHARED COMMON SCHEMAS
5
- // =====================================================
6
-
7
- // CUID2 validation schema aligned with createId() from @paralleldrive/cuid2
8
- export const CuidSchema = z.string().cuid2();
9
-
10
- export const GeoLocationSchema = z.object({
11
- lat: z.number().min(-90).max(90),
12
- lng: z.number().min(-180).max(180),
13
- address: z.object({
14
- line1: z.string(),
15
- line2: z.string().optional(),
16
- city: z.string(),
17
- state: z.string(),
18
- postalCode: z.string(),
19
- country: z.string(),
20
- }),
21
- });
22
-
23
- export const AuditTrailSchema = z.object({
24
- action: z.string(),
25
- performedBy: z.string(),
26
- performedAt: z.date(),
27
- details: z.record(z.any()).optional(),
28
- ipAddress: z.string().optional(),
29
- userAgent: z.string().optional(),
30
- });
31
-
32
- export const MoneySchema = z.object({
33
- amount: z.number(),
34
- currency: z.string().length(3).default("USD"),
35
- });
36
-
37
- export const ContactInfoSchema = z.object({
38
- name: z.string().optional(),
39
- phone: z.string().optional(),
40
- email: z.string().email().optional(),
41
- alternatePhone: z.string().optional(),
42
- });
43
-
44
- // Allow days that are explicitly closed to omit open/close times
45
- const DayHoursSchema = z.union([
46
- z.object({
47
- closed: z.literal(true),
48
- open: z.string().optional(),
49
- close: z.string().optional(),
50
- }),
51
- z.object({
52
- open: z.string(),
53
- close: z.string(),
54
- closed: z.literal(false).optional(),
55
- }),
56
- ]);
57
-
58
- export const BusinessHoursSchema = z.object({
59
- timezone: z.string(),
60
- monday: DayHoursSchema.optional(),
61
- tuesday: DayHoursSchema.optional(),
62
- wednesday: DayHoursSchema.optional(),
63
- thursday: DayHoursSchema.optional(),
64
- friday: DayHoursSchema.optional(),
65
- saturday: DayHoursSchema.optional(),
66
- sunday: DayHoursSchema.optional(),
67
- holidays: z
68
- .array(
69
- z.object({
70
- date: z.string(),
71
- name: z.string(),
72
- closed: z.boolean().default(true),
73
- }),
74
- )
75
- .optional(),
76
- });
77
-
78
- // Common enum types
79
- export const CurrencyEnum = z.enum([
80
- "USD",
81
- "EUR",
82
- "GBP",
83
- "CAD",
84
- "AUD",
85
- "JPY",
86
- "CNY",
87
- "INR",
88
- ]);
89
- export const TimezoneEnum = z.enum([
90
- "UTC",
91
- "America/New_York",
92
- "America/Chicago",
93
- "America/Denver",
94
- "America/Los_Angeles",
95
- "Europe/London",
96
- "Europe/Paris",
97
- "Europe/Berlin",
98
- "Asia/Tokyo",
99
- "Asia/Shanghai",
100
- "Asia/Kolkata",
101
- "Australia/Sydney",
102
- ]);
103
-
104
- export type GeoLocation = z.infer<typeof GeoLocationSchema>;
105
- export type AuditTrail = z.infer<typeof AuditTrailSchema>;
106
- export type Money = z.infer<typeof MoneySchema>;
107
- export type ContactInfo = z.infer<typeof ContactInfoSchema>;
108
- export type BusinessHours = z.infer<typeof BusinessHoursSchema>;
1
+ import { z } from "zod";
2
+
3
+ // =====================================================
4
+ // SHARED COMMON SCHEMAS
5
+ // =====================================================
6
+
7
+ // CUID2 validation schema aligned with createId() from @paralleldrive/cuid2
8
+ export const CuidSchema = z.string().cuid2();
9
+
10
+ export const GeoLocationSchema = z.object({
11
+ lat: z.number().min(-90).max(90),
12
+ lng: z.number().min(-180).max(180),
13
+ address: z.object({
14
+ line1: z.string(),
15
+ line2: z.string().optional(),
16
+ city: z.string(),
17
+ state: z.string(),
18
+ postalCode: z.string(),
19
+ country: z.string(),
20
+ }),
21
+ });
22
+
23
+ export const AuditTrailSchema = z.object({
24
+ action: z.string(),
25
+ performedBy: z.string(),
26
+ performedAt: z.date(),
27
+ details: z.record(z.any()).optional(),
28
+ ipAddress: z.string().optional(),
29
+ userAgent: z.string().optional(),
30
+ });
31
+
32
+ export const MoneySchema = z.object({
33
+ amount: z.number(),
34
+ currency: z.string().length(3).default("USD"),
35
+ });
36
+
37
+ export const ContactInfoSchema = z.object({
38
+ name: z.string().optional(),
39
+ phone: z.string().optional(),
40
+ email: z.string().email().optional(),
41
+ alternatePhone: z.string().optional(),
42
+ });
43
+
44
+ // Allow days that are explicitly closed to omit open/close times
45
+ const DayHoursSchema = z.union([
46
+ z.object({
47
+ closed: z.literal(true),
48
+ open: z.string().optional(),
49
+ close: z.string().optional(),
50
+ }),
51
+ z.object({
52
+ open: z.string(),
53
+ close: z.string(),
54
+ closed: z.literal(false).optional(),
55
+ }),
56
+ ]);
57
+
58
+ export const BusinessHoursSchema = z.object({
59
+ timezone: z.string(),
60
+ monday: DayHoursSchema.optional(),
61
+ tuesday: DayHoursSchema.optional(),
62
+ wednesday: DayHoursSchema.optional(),
63
+ thursday: DayHoursSchema.optional(),
64
+ friday: DayHoursSchema.optional(),
65
+ saturday: DayHoursSchema.optional(),
66
+ sunday: DayHoursSchema.optional(),
67
+ holidays: z
68
+ .array(
69
+ z.object({
70
+ date: z.string(),
71
+ name: z.string(),
72
+ closed: z.boolean().default(true),
73
+ }),
74
+ )
75
+ .optional(),
76
+ });
77
+
78
+ // Common enum types
79
+ export const CurrencyEnum = z.enum([
80
+ "USD",
81
+ "EUR",
82
+ "GBP",
83
+ "CAD",
84
+ "AUD",
85
+ "JPY",
86
+ "CNY",
87
+ "INR",
88
+ ]);
89
+ export const TimezoneEnum = z.enum([
90
+ "UTC",
91
+ "America/New_York",
92
+ "America/Chicago",
93
+ "America/Denver",
94
+ "America/Los_Angeles",
95
+ "Europe/London",
96
+ "Europe/Paris",
97
+ "Europe/Berlin",
98
+ "Asia/Tokyo",
99
+ "Asia/Shanghai",
100
+ "Asia/Kolkata",
101
+ "Australia/Sydney",
102
+ ]);
103
+
104
+ export type GeoLocation = z.infer<typeof GeoLocationSchema>;
105
+ export type AuditTrail = z.infer<typeof AuditTrailSchema>;
106
+ export type Money = z.infer<typeof MoneySchema>;
107
+ export type ContactInfo = z.infer<typeof ContactInfoSchema>;
108
+ export type BusinessHours = z.infer<typeof BusinessHoursSchema>;