@voyantjs/facilities 0.2.0 → 0.3.1

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.
@@ -0,0 +1,85 @@
1
+ import { and, desc, eq, sql } from "drizzle-orm";
2
+ import { facilityFeatures, facilityOperationSchedules } from "./schema.js";
3
+ import { ensureFacilityExists, paginate } from "./service-shared.js";
4
+ export async function listFacilityFeatures(db, query) {
5
+ const conditions = [];
6
+ if (query.facilityId)
7
+ conditions.push(eq(facilityFeatures.facilityId, query.facilityId));
8
+ if (query.category)
9
+ conditions.push(eq(facilityFeatures.category, query.category));
10
+ const where = conditions.length > 0 ? and(...conditions) : undefined;
11
+ return paginate(db
12
+ .select()
13
+ .from(facilityFeatures)
14
+ .where(where)
15
+ .limit(query.limit)
16
+ .offset(query.offset)
17
+ .orderBy(facilityFeatures.sortOrder, facilityFeatures.name), db.select({ count: sql `count(*)::int` }).from(facilityFeatures).where(where), query.limit, query.offset);
18
+ }
19
+ export async function createFacilityFeature(db, facilityId, data) {
20
+ const facility = await ensureFacilityExists(db, facilityId);
21
+ if (!facility)
22
+ return null;
23
+ const [row] = await db
24
+ .insert(facilityFeatures)
25
+ .values({ ...data, facilityId })
26
+ .returning();
27
+ return row ?? null;
28
+ }
29
+ export async function updateFacilityFeature(db, id, data) {
30
+ const [row] = await db
31
+ .update(facilityFeatures)
32
+ .set({ ...data, updatedAt: new Date() })
33
+ .where(eq(facilityFeatures.id, id))
34
+ .returning();
35
+ return row ?? null;
36
+ }
37
+ export async function deleteFacilityFeature(db, id) {
38
+ const [row] = await db
39
+ .delete(facilityFeatures)
40
+ .where(eq(facilityFeatures.id, id))
41
+ .returning({ id: facilityFeatures.id });
42
+ return row ?? null;
43
+ }
44
+ export async function listFacilityOperationSchedules(db, query) {
45
+ const conditions = [];
46
+ if (query.facilityId) {
47
+ conditions.push(eq(facilityOperationSchedules.facilityId, query.facilityId));
48
+ }
49
+ if (query.dayOfWeek) {
50
+ conditions.push(eq(facilityOperationSchedules.dayOfWeek, query.dayOfWeek));
51
+ }
52
+ const where = conditions.length > 0 ? and(...conditions) : undefined;
53
+ return paginate(db
54
+ .select()
55
+ .from(facilityOperationSchedules)
56
+ .where(where)
57
+ .limit(query.limit)
58
+ .offset(query.offset)
59
+ .orderBy(facilityOperationSchedules.dayOfWeek, desc(facilityOperationSchedules.validFrom)), db.select({ count: sql `count(*)::int` }).from(facilityOperationSchedules).where(where), query.limit, query.offset);
60
+ }
61
+ export async function createFacilityOperationSchedule(db, facilityId, data) {
62
+ const facility = await ensureFacilityExists(db, facilityId);
63
+ if (!facility)
64
+ return null;
65
+ const [row] = await db
66
+ .insert(facilityOperationSchedules)
67
+ .values({ ...data, facilityId })
68
+ .returning();
69
+ return row ?? null;
70
+ }
71
+ export async function updateFacilityOperationSchedule(db, id, data) {
72
+ const [row] = await db
73
+ .update(facilityOperationSchedules)
74
+ .set({ ...data, updatedAt: new Date() })
75
+ .where(eq(facilityOperationSchedules.id, id))
76
+ .returning();
77
+ return row ?? null;
78
+ }
79
+ export async function deleteFacilityOperationSchedule(db, id) {
80
+ const [row] = await db
81
+ .delete(facilityOperationSchedules)
82
+ .where(eq(facilityOperationSchedules.id, id))
83
+ .returning({ id: facilityOperationSchedules.id });
84
+ return row ?? null;
85
+ }
@@ -0,0 +1,195 @@
1
+ import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
2
+ import type { CreatePropertyGroupInput, CreatePropertyGroupMemberInput, CreatePropertyInput, PropertyGroupListQuery, PropertyGroupMemberListQuery, PropertyListQuery, UpdatePropertyGroupInput, UpdatePropertyGroupMemberInput, UpdatePropertyInput } from "./service-shared.js";
3
+ export declare function listProperties(db: PostgresJsDatabase, query: PropertyListQuery): Promise<{
4
+ data: {
5
+ id: string;
6
+ facilityId: string;
7
+ propertyType: "other" | "hotel" | "resort" | "camp" | "lodge" | "villa" | "apartment" | "hostel";
8
+ brandName: string | null;
9
+ groupName: string | null;
10
+ rating: number | null;
11
+ ratingScale: number | null;
12
+ checkInTime: string | null;
13
+ checkOutTime: string | null;
14
+ policyNotes: string | null;
15
+ amenityNotes: string | null;
16
+ createdAt: Date;
17
+ updatedAt: Date;
18
+ }[];
19
+ total: number;
20
+ limit: number;
21
+ offset: number;
22
+ }>;
23
+ export declare function getPropertyById(db: PostgresJsDatabase, id: string): Promise<{
24
+ id: string;
25
+ facilityId: string;
26
+ propertyType: "other" | "hotel" | "resort" | "camp" | "lodge" | "villa" | "apartment" | "hostel";
27
+ brandName: string | null;
28
+ groupName: string | null;
29
+ rating: number | null;
30
+ ratingScale: number | null;
31
+ checkInTime: string | null;
32
+ checkOutTime: string | null;
33
+ policyNotes: string | null;
34
+ amenityNotes: string | null;
35
+ createdAt: Date;
36
+ updatedAt: Date;
37
+ } | null>;
38
+ export declare function createProperty(db: PostgresJsDatabase, data: CreatePropertyInput): Promise<{
39
+ id: string;
40
+ createdAt: Date;
41
+ updatedAt: Date;
42
+ facilityId: string;
43
+ propertyType: "other" | "hotel" | "resort" | "camp" | "lodge" | "villa" | "apartment" | "hostel";
44
+ brandName: string | null;
45
+ groupName: string | null;
46
+ rating: number | null;
47
+ ratingScale: number | null;
48
+ checkInTime: string | null;
49
+ checkOutTime: string | null;
50
+ policyNotes: string | null;
51
+ amenityNotes: string | null;
52
+ } | null>;
53
+ export declare function updateProperty(db: PostgresJsDatabase, id: string, data: UpdatePropertyInput): Promise<{
54
+ id: string;
55
+ facilityId: string;
56
+ propertyType: "other" | "hotel" | "resort" | "camp" | "lodge" | "villa" | "apartment" | "hostel";
57
+ brandName: string | null;
58
+ groupName: string | null;
59
+ rating: number | null;
60
+ ratingScale: number | null;
61
+ checkInTime: string | null;
62
+ checkOutTime: string | null;
63
+ policyNotes: string | null;
64
+ amenityNotes: string | null;
65
+ createdAt: Date;
66
+ updatedAt: Date;
67
+ } | null>;
68
+ export declare function deleteProperty(db: PostgresJsDatabase, id: string): Promise<{
69
+ id: string;
70
+ } | null>;
71
+ export declare function listPropertyGroups(db: PostgresJsDatabase, query: PropertyGroupListQuery): Promise<{
72
+ data: {
73
+ id: string;
74
+ parentGroupId: string | null;
75
+ groupType: "other" | "brand" | "chain" | "management_company" | "collection" | "portfolio" | "cluster";
76
+ status: "active" | "inactive" | "archived";
77
+ name: string;
78
+ code: string | null;
79
+ brandName: string | null;
80
+ legalName: string | null;
81
+ website: string | null;
82
+ notes: string | null;
83
+ metadata: Record<string, unknown> | null;
84
+ createdAt: Date;
85
+ updatedAt: Date;
86
+ }[];
87
+ total: number;
88
+ limit: number;
89
+ offset: number;
90
+ }>;
91
+ export declare function getPropertyGroupById(db: PostgresJsDatabase, id: string): Promise<{
92
+ id: string;
93
+ parentGroupId: string | null;
94
+ groupType: "other" | "brand" | "chain" | "management_company" | "collection" | "portfolio" | "cluster";
95
+ status: "active" | "inactive" | "archived";
96
+ name: string;
97
+ code: string | null;
98
+ brandName: string | null;
99
+ legalName: string | null;
100
+ website: string | null;
101
+ notes: string | null;
102
+ metadata: Record<string, unknown> | null;
103
+ createdAt: Date;
104
+ updatedAt: Date;
105
+ } | null>;
106
+ export declare function createPropertyGroup(db: PostgresJsDatabase, data: CreatePropertyGroupInput): Promise<{
107
+ name: string;
108
+ website: string | null;
109
+ notes: string | null;
110
+ metadata: Record<string, unknown> | null;
111
+ id: string;
112
+ createdAt: Date;
113
+ updatedAt: Date;
114
+ status: "active" | "inactive" | "archived";
115
+ code: string | null;
116
+ brandName: string | null;
117
+ parentGroupId: string | null;
118
+ groupType: "other" | "brand" | "chain" | "management_company" | "collection" | "portfolio" | "cluster";
119
+ legalName: string | null;
120
+ } | null>;
121
+ export declare function updatePropertyGroup(db: PostgresJsDatabase, id: string, data: UpdatePropertyGroupInput): Promise<{
122
+ id: string;
123
+ parentGroupId: string | null;
124
+ groupType: "other" | "brand" | "chain" | "management_company" | "collection" | "portfolio" | "cluster";
125
+ status: "active" | "inactive" | "archived";
126
+ name: string;
127
+ code: string | null;
128
+ brandName: string | null;
129
+ legalName: string | null;
130
+ website: string | null;
131
+ notes: string | null;
132
+ metadata: Record<string, unknown> | null;
133
+ createdAt: Date;
134
+ updatedAt: Date;
135
+ } | null>;
136
+ export declare function deletePropertyGroup(db: PostgresJsDatabase, id: string): Promise<{
137
+ id: string;
138
+ } | null>;
139
+ export declare function listPropertyGroupMembers(db: PostgresJsDatabase, query: PropertyGroupMemberListQuery): Promise<{
140
+ data: {
141
+ id: string;
142
+ groupId: string;
143
+ propertyId: string;
144
+ membershipRole: "other" | "member" | "flagship" | "managed" | "franchise";
145
+ isPrimary: boolean;
146
+ validFrom: string | null;
147
+ validTo: string | null;
148
+ notes: string | null;
149
+ createdAt: Date;
150
+ updatedAt: Date;
151
+ }[];
152
+ total: number;
153
+ limit: number;
154
+ offset: number;
155
+ }>;
156
+ export declare function getPropertyGroupMemberById(db: PostgresJsDatabase, id: string): Promise<{
157
+ id: string;
158
+ groupId: string;
159
+ propertyId: string;
160
+ membershipRole: "other" | "member" | "flagship" | "managed" | "franchise";
161
+ isPrimary: boolean;
162
+ validFrom: string | null;
163
+ validTo: string | null;
164
+ notes: string | null;
165
+ createdAt: Date;
166
+ updatedAt: Date;
167
+ } | null>;
168
+ export declare function createPropertyGroupMember(db: PostgresJsDatabase, data: CreatePropertyGroupMemberInput): Promise<{
169
+ isPrimary: boolean;
170
+ notes: string | null;
171
+ id: string;
172
+ createdAt: Date;
173
+ updatedAt: Date;
174
+ validFrom: string | null;
175
+ validTo: string | null;
176
+ groupId: string;
177
+ propertyId: string;
178
+ membershipRole: "other" | "member" | "flagship" | "managed" | "franchise";
179
+ } | null>;
180
+ export declare function updatePropertyGroupMember(db: PostgresJsDatabase, id: string, data: UpdatePropertyGroupMemberInput): Promise<{
181
+ id: string;
182
+ groupId: string;
183
+ propertyId: string;
184
+ membershipRole: "other" | "member" | "flagship" | "managed" | "franchise";
185
+ isPrimary: boolean;
186
+ validFrom: string | null;
187
+ validTo: string | null;
188
+ notes: string | null;
189
+ createdAt: Date;
190
+ updatedAt: Date;
191
+ } | null>;
192
+ export declare function deletePropertyGroupMember(db: PostgresJsDatabase, id: string): Promise<{
193
+ id: string;
194
+ } | null>;
195
+ //# sourceMappingURL=service-properties.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-properties.d.ts","sourceRoot":"","sources":["../src/service-properties.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAGjE,OAAO,KAAK,EACV,wBAAwB,EACxB,8BAA8B,EAC9B,mBAAmB,EACnB,sBAAsB,EACtB,4BAA4B,EAC5B,iBAAiB,EACjB,wBAAwB,EACxB,8BAA8B,EAC9B,mBAAmB,EACpB,MAAM,qBAAqB,CAAA;AAG5B,wBAAsB,cAAc,CAAC,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE,iBAAiB;;;;;;;;;;;;;;;;;;;GAuBpF;AAED,wBAAsB,eAAe,CAAC,EAAE,EAAE,kBAAkB,EAAE,EAAE,EAAE,MAAM;;;;;;;;;;;;;;UAGvE;AAED,wBAAsB,cAAc,CAAC,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,mBAAmB;;;;;;;;;;;;;;UAUrF;AAED,wBAAsB,cAAc,CAClC,EAAE,EAAE,kBAAkB,EACtB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,mBAAmB;;;;;;;;;;;;;;UAQ1B;AAED,wBAAsB,cAAc,CAAC,EAAE,EAAE,kBAAkB,EAAE,EAAE,EAAE,MAAM;;UAMtE;AAED,wBAAsB,kBAAkB,CAAC,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE,sBAAsB;;;;;;;;;;;;;;;;;;;GA8B7F;AAED,wBAAsB,oBAAoB,CAAC,EAAE,EAAE,kBAAkB,EAAE,EAAE,EAAE,MAAM;;;;;;;;;;;;;;UAG5E;AAED,wBAAsB,mBAAmB,CAAC,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,wBAAwB;;;;;;;;;;;;;;UAG/F;AAED,wBAAsB,mBAAmB,CACvC,EAAE,EAAE,kBAAkB,EACtB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,wBAAwB;;;;;;;;;;;;;;UAQ/B;AAED,wBAAsB,mBAAmB,CAAC,EAAE,EAAE,kBAAkB,EAAE,EAAE,EAAE,MAAM;;UAM3E;AAED,wBAAsB,wBAAwB,CAC5C,EAAE,EAAE,kBAAkB,EACtB,KAAK,EAAE,4BAA4B;;;;;;;;;;;;;;;;GAsBpC;AAED,wBAAsB,0BAA0B,CAAC,EAAE,EAAE,kBAAkB,EAAE,EAAE,EAAE,MAAM;;;;;;;;;;;UAOlF;AAED,wBAAsB,yBAAyB,CAC7C,EAAE,EAAE,kBAAkB,EACtB,IAAI,EAAE,8BAA8B;;;;;;;;;;;UAkBrC;AAED,wBAAsB,yBAAyB,CAC7C,EAAE,EAAE,kBAAkB,EACtB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,8BAA8B;;;;;;;;;;;UAQrC;AAED,wBAAsB,yBAAyB,CAAC,EAAE,EAAE,kBAAkB,EAAE,EAAE,EAAE,MAAM;;UAMjF"}
@@ -0,0 +1,157 @@
1
+ import { and, desc, eq, ilike, or, sql } from "drizzle-orm";
2
+ import { facilities, properties, propertyGroupMembers, propertyGroups } from "./schema.js";
3
+ import { paginate } from "./service-shared.js";
4
+ export async function listProperties(db, query) {
5
+ const conditions = [];
6
+ if (query.facilityId)
7
+ conditions.push(eq(properties.facilityId, query.facilityId));
8
+ if (query.propertyType)
9
+ conditions.push(eq(properties.propertyType, query.propertyType));
10
+ if (query.groupName)
11
+ conditions.push(eq(properties.groupName, query.groupName));
12
+ if (query.search) {
13
+ const term = `%${query.search}%`;
14
+ conditions.push(or(ilike(properties.brandName, term), ilike(properties.groupName, term)));
15
+ }
16
+ const where = conditions.length > 0 ? and(...conditions) : undefined;
17
+ return paginate(db
18
+ .select()
19
+ .from(properties)
20
+ .where(where)
21
+ .limit(query.limit)
22
+ .offset(query.offset)
23
+ .orderBy(desc(properties.updatedAt)), db.select({ count: sql `count(*)::int` }).from(properties).where(where), query.limit, query.offset);
24
+ }
25
+ export async function getPropertyById(db, id) {
26
+ const [row] = await db.select().from(properties).where(eq(properties.id, id)).limit(1);
27
+ return row ?? null;
28
+ }
29
+ export async function createProperty(db, data) {
30
+ const [facility] = await db
31
+ .select({ id: facilities.id })
32
+ .from(facilities)
33
+ .where(eq(facilities.id, data.facilityId))
34
+ .limit(1);
35
+ if (!facility)
36
+ return null;
37
+ const [row] = await db.insert(properties).values(data).returning();
38
+ return row ?? null;
39
+ }
40
+ export async function updateProperty(db, id, data) {
41
+ const [row] = await db
42
+ .update(properties)
43
+ .set({ ...data, updatedAt: new Date() })
44
+ .where(eq(properties.id, id))
45
+ .returning();
46
+ return row ?? null;
47
+ }
48
+ export async function deleteProperty(db, id) {
49
+ const [row] = await db
50
+ .delete(properties)
51
+ .where(eq(properties.id, id))
52
+ .returning({ id: properties.id });
53
+ return row ?? null;
54
+ }
55
+ export async function listPropertyGroups(db, query) {
56
+ const conditions = [];
57
+ if (query.parentGroupId)
58
+ conditions.push(eq(propertyGroups.parentGroupId, query.parentGroupId));
59
+ if (query.groupType)
60
+ conditions.push(eq(propertyGroups.groupType, query.groupType));
61
+ if (query.status)
62
+ conditions.push(eq(propertyGroups.status, query.status));
63
+ if (query.search) {
64
+ const term = `%${query.search}%`;
65
+ conditions.push(or(ilike(propertyGroups.name, term), ilike(propertyGroups.code, term), ilike(propertyGroups.brandName, term), ilike(propertyGroups.legalName, term)));
66
+ }
67
+ const where = conditions.length > 0 ? and(...conditions) : undefined;
68
+ return paginate(db
69
+ .select()
70
+ .from(propertyGroups)
71
+ .where(where)
72
+ .limit(query.limit)
73
+ .offset(query.offset)
74
+ .orderBy(desc(propertyGroups.updatedAt)), db.select({ count: sql `count(*)::int` }).from(propertyGroups).where(where), query.limit, query.offset);
75
+ }
76
+ export async function getPropertyGroupById(db, id) {
77
+ const [row] = await db.select().from(propertyGroups).where(eq(propertyGroups.id, id)).limit(1);
78
+ return row ?? null;
79
+ }
80
+ export async function createPropertyGroup(db, data) {
81
+ const [row] = await db.insert(propertyGroups).values(data).returning();
82
+ return row ?? null;
83
+ }
84
+ export async function updatePropertyGroup(db, id, data) {
85
+ const [row] = await db
86
+ .update(propertyGroups)
87
+ .set({ ...data, updatedAt: new Date() })
88
+ .where(eq(propertyGroups.id, id))
89
+ .returning();
90
+ return row ?? null;
91
+ }
92
+ export async function deletePropertyGroup(db, id) {
93
+ const [row] = await db
94
+ .delete(propertyGroups)
95
+ .where(eq(propertyGroups.id, id))
96
+ .returning({ id: propertyGroups.id });
97
+ return row ?? null;
98
+ }
99
+ export async function listPropertyGroupMembers(db, query) {
100
+ const conditions = [];
101
+ if (query.groupId)
102
+ conditions.push(eq(propertyGroupMembers.groupId, query.groupId));
103
+ if (query.propertyId)
104
+ conditions.push(eq(propertyGroupMembers.propertyId, query.propertyId));
105
+ if (query.membershipRole) {
106
+ conditions.push(eq(propertyGroupMembers.membershipRole, query.membershipRole));
107
+ }
108
+ const where = conditions.length > 0 ? and(...conditions) : undefined;
109
+ return paginate(db
110
+ .select()
111
+ .from(propertyGroupMembers)
112
+ .where(where)
113
+ .limit(query.limit)
114
+ .offset(query.offset)
115
+ .orderBy(desc(propertyGroupMembers.updatedAt)), db.select({ count: sql `count(*)::int` }).from(propertyGroupMembers).where(where), query.limit, query.offset);
116
+ }
117
+ export async function getPropertyGroupMemberById(db, id) {
118
+ const [row] = await db
119
+ .select()
120
+ .from(propertyGroupMembers)
121
+ .where(eq(propertyGroupMembers.id, id))
122
+ .limit(1);
123
+ return row ?? null;
124
+ }
125
+ export async function createPropertyGroupMember(db, data) {
126
+ const [group, property] = await Promise.all([
127
+ db
128
+ .select({ id: propertyGroups.id })
129
+ .from(propertyGroups)
130
+ .where(eq(propertyGroups.id, data.groupId))
131
+ .limit(1),
132
+ db
133
+ .select({ id: properties.id })
134
+ .from(properties)
135
+ .where(eq(properties.id, data.propertyId))
136
+ .limit(1),
137
+ ]);
138
+ if (!group[0] || !property[0])
139
+ return null;
140
+ const [row] = await db.insert(propertyGroupMembers).values(data).returning();
141
+ return row ?? null;
142
+ }
143
+ export async function updatePropertyGroupMember(db, id, data) {
144
+ const [row] = await db
145
+ .update(propertyGroupMembers)
146
+ .set({ ...data, updatedAt: new Date() })
147
+ .where(eq(propertyGroupMembers.id, id))
148
+ .returning();
149
+ return row ?? null;
150
+ }
151
+ export async function deletePropertyGroupMember(db, id) {
152
+ const [row] = await db
153
+ .delete(propertyGroupMembers)
154
+ .where(eq(propertyGroupMembers.id, id))
155
+ .returning({ id: propertyGroupMembers.id });
156
+ return row ?? null;
157
+ }
@@ -0,0 +1,63 @@
1
+ import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
2
+ import type { z } from "zod";
3
+ import type { facilityContactListQuerySchema, facilityFeatureListQuerySchema, facilityListQuerySchema, facilityOperationScheduleListQuerySchema, insertFacilityContactSchema, insertFacilityFeatureSchema, insertFacilityOperationScheduleSchema, insertFacilitySchema, insertPropertyGroupMemberSchema, insertPropertyGroupSchema, insertPropertySchema, propertyGroupListQuerySchema, propertyGroupMemberListQuerySchema, propertyListQuerySchema, updateFacilityContactSchema, updateFacilityFeatureSchema, updateFacilityOperationScheduleSchema, updateFacilitySchema, updatePropertyGroupMemberSchema, updatePropertyGroupSchema, updatePropertySchema } from "./validation.js";
4
+ export type FacilityListQuery = z.infer<typeof facilityListQuerySchema>;
5
+ export type CreateFacilityInput = z.infer<typeof insertFacilitySchema>;
6
+ export type UpdateFacilityInput = z.infer<typeof updateFacilitySchema>;
7
+ export type FacilityContactListQuery = z.infer<typeof facilityContactListQuerySchema>;
8
+ export type CreateFacilityContactInput = z.infer<typeof insertFacilityContactSchema>;
9
+ export type UpdateFacilityContactInput = z.infer<typeof updateFacilityContactSchema>;
10
+ export type FacilityFeatureListQuery = z.infer<typeof facilityFeatureListQuerySchema>;
11
+ export type CreateFacilityFeatureInput = z.infer<typeof insertFacilityFeatureSchema>;
12
+ export type UpdateFacilityFeatureInput = z.infer<typeof updateFacilityFeatureSchema>;
13
+ export type FacilityOperationScheduleListQuery = z.infer<typeof facilityOperationScheduleListQuerySchema>;
14
+ export type CreateFacilityOperationScheduleInput = z.infer<typeof insertFacilityOperationScheduleSchema>;
15
+ export type UpdateFacilityOperationScheduleInput = z.infer<typeof updateFacilityOperationScheduleSchema>;
16
+ export type PropertyListQuery = z.infer<typeof propertyListQuerySchema>;
17
+ export type CreatePropertyInput = z.infer<typeof insertPropertySchema>;
18
+ export type UpdatePropertyInput = z.infer<typeof updatePropertySchema>;
19
+ export type PropertyGroupListQuery = z.infer<typeof propertyGroupListQuerySchema>;
20
+ export type CreatePropertyGroupInput = z.infer<typeof insertPropertyGroupSchema>;
21
+ export type UpdatePropertyGroupInput = z.infer<typeof updatePropertyGroupSchema>;
22
+ export type PropertyGroupMemberListQuery = z.infer<typeof propertyGroupMemberListQuerySchema>;
23
+ export type CreatePropertyGroupMemberInput = z.infer<typeof insertPropertyGroupMemberSchema>;
24
+ export type UpdatePropertyGroupMemberInput = z.infer<typeof updatePropertyGroupMemberSchema>;
25
+ export declare const facilityEntityType = "facility";
26
+ export declare const facilityBaseIdentitySource = "facilities.base";
27
+ export declare const facilityContactIdentitySource = "facilities.contacts";
28
+ export declare function paginate<T extends object>(rowsQuery: Promise<T[]>, countQuery: Promise<Array<{
29
+ count: number;
30
+ }>>, limit: number, offset: number): Promise<{
31
+ data: T[];
32
+ total: number;
33
+ limit: number;
34
+ offset: number;
35
+ }>;
36
+ export declare function formatAddress(address: {
37
+ fullText: string | null;
38
+ line1: string | null;
39
+ line2: string | null;
40
+ city: string | null;
41
+ region: string | null;
42
+ postalCode: string | null;
43
+ country: string | null;
44
+ }): string | null;
45
+ export type FacilityAddressInput = Pick<CreateFacilityInput, "addressLine1" | "addressLine2" | "city" | "region" | "postalCode" | "country" | "latitude" | "longitude">;
46
+ export declare function ensureFacilityExists(db: PostgresJsDatabase, facilityId: string): Promise<{
47
+ id: string;
48
+ } | null>;
49
+ export declare function syncFacilityAddress(db: PostgresJsDatabase, facilityId: string, data: FacilityAddressInput): Promise<void>;
50
+ export declare function hydrateFacilities<T extends {
51
+ id: string;
52
+ }>(db: PostgresJsDatabase, rows: T[]): Promise<(T & {
53
+ addressLine1: string | null;
54
+ addressLine2: string | null;
55
+ city: string | null;
56
+ region: string | null;
57
+ country: string | null;
58
+ postalCode: string | null;
59
+ latitude: number | null;
60
+ longitude: number | null;
61
+ address: string | null;
62
+ })[]>;
63
+ //# sourceMappingURL=service-shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-shared.d.ts","sourceRoot":"","sources":["../src/service-shared.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,136 @@
1
+ import { identityAddresses } from "@voyantjs/identity/schema";
2
+ import { identityService } from "@voyantjs/identity/service";
3
+ import { and, eq, inArray } from "drizzle-orm";
4
+ import { facilities } from "./schema.js";
5
+ export const facilityEntityType = "facility";
6
+ export const facilityBaseIdentitySource = "facilities.base";
7
+ export const facilityContactIdentitySource = "facilities.contacts";
8
+ export async function paginate(rowsQuery, countQuery, limit, offset) {
9
+ const [data, countResult] = await Promise.all([rowsQuery, countQuery]);
10
+ return {
11
+ data,
12
+ total: countResult[0]?.count ?? 0,
13
+ limit,
14
+ offset,
15
+ };
16
+ }
17
+ function isManagedBySource(metadata, source) {
18
+ return metadata?.managedBy === source;
19
+ }
20
+ function toNullableTrimmed(value) {
21
+ const trimmed = value?.trim();
22
+ return trimmed ? trimmed : null;
23
+ }
24
+ export function formatAddress(address) {
25
+ if (address.fullText) {
26
+ return address.fullText;
27
+ }
28
+ const parts = [
29
+ address.line1,
30
+ address.line2,
31
+ address.city,
32
+ address.region,
33
+ address.postalCode,
34
+ address.country,
35
+ ].filter(Boolean);
36
+ return parts.length > 0 ? parts.join(", ") : null;
37
+ }
38
+ export async function ensureFacilityExists(db, facilityId) {
39
+ const [facility] = await db
40
+ .select({ id: facilities.id })
41
+ .from(facilities)
42
+ .where(eq(facilities.id, facilityId))
43
+ .limit(1);
44
+ return facility ?? null;
45
+ }
46
+ export async function syncFacilityAddress(db, facilityId, data) {
47
+ const existingAddresses = await identityService.listAddressesForEntity(db, facilityEntityType, facilityId);
48
+ const managedAddress = existingAddresses.find((address) => isManagedBySource(address.metadata, facilityBaseIdentitySource));
49
+ const line1 = toNullableTrimmed(data.addressLine1);
50
+ const line2 = toNullableTrimmed(data.addressLine2);
51
+ const city = toNullableTrimmed(data.city);
52
+ const region = toNullableTrimmed(data.region);
53
+ const postalCode = toNullableTrimmed(data.postalCode);
54
+ const country = toNullableTrimmed(data.country);
55
+ const hasAddress = Boolean(line1 ||
56
+ line2 ||
57
+ city ||
58
+ region ||
59
+ postalCode ||
60
+ country ||
61
+ data.latitude !== null ||
62
+ data.longitude !== null);
63
+ if (!hasAddress) {
64
+ if (managedAddress) {
65
+ await identityService.deleteAddress(db, managedAddress.id);
66
+ }
67
+ return;
68
+ }
69
+ const payload = {
70
+ entityType: facilityEntityType,
71
+ entityId: facilityId,
72
+ label: "primary",
73
+ fullText: null,
74
+ line1,
75
+ line2,
76
+ city,
77
+ region,
78
+ postalCode,
79
+ country,
80
+ latitude: data.latitude ?? null,
81
+ longitude: data.longitude ?? null,
82
+ isPrimary: true,
83
+ metadata: {
84
+ managedBy: facilityBaseIdentitySource,
85
+ },
86
+ };
87
+ if (managedAddress) {
88
+ await identityService.updateAddress(db, managedAddress.id, payload);
89
+ }
90
+ else {
91
+ await identityService.createAddress(db, payload);
92
+ }
93
+ }
94
+ export async function hydrateFacilities(db, rows) {
95
+ if (rows.length === 0) {
96
+ return rows.map((row) => ({
97
+ ...row,
98
+ addressLine1: null,
99
+ addressLine2: null,
100
+ city: null,
101
+ region: null,
102
+ country: null,
103
+ postalCode: null,
104
+ latitude: null,
105
+ longitude: null,
106
+ address: null,
107
+ }));
108
+ }
109
+ const ids = rows.map((row) => row.id);
110
+ const addresses = await db
111
+ .select()
112
+ .from(identityAddresses)
113
+ .where(and(eq(identityAddresses.entityType, facilityEntityType), inArray(identityAddresses.entityId, ids)));
114
+ const addressMap = new Map();
115
+ for (const address of addresses) {
116
+ const bucket = addressMap.get(address.entityId) ?? [];
117
+ bucket.push(address);
118
+ addressMap.set(address.entityId, bucket);
119
+ }
120
+ return rows.map((row) => {
121
+ const entityAddresses = addressMap.get(row.id) ?? [];
122
+ const primaryAddress = entityAddresses.find((address) => address.isPrimary) ?? entityAddresses[0] ?? null;
123
+ return {
124
+ ...row,
125
+ addressLine1: primaryAddress?.line1 ?? null,
126
+ addressLine2: primaryAddress?.line2 ?? null,
127
+ city: primaryAddress?.city ?? null,
128
+ region: primaryAddress?.region ?? null,
129
+ country: primaryAddress?.country ?? null,
130
+ postalCode: primaryAddress?.postalCode ?? null,
131
+ latitude: primaryAddress?.latitude ?? null,
132
+ longitude: primaryAddress?.longitude ?? null,
133
+ address: primaryAddress ? formatAddress(primaryAddress) : null,
134
+ };
135
+ });
136
+ }