11import { QUICKBOOKS_MAX_RESPONSE_BYTES } from '@/tools/quickbooks/client'
22import { ErrorExtractorId } from '@/tools/error-extractors'
33import type {
4+ QuickBooksAddress ,
5+ QuickBooksEmployee ,
46 QuickBooksMasterDataRecord ,
57 QuickBooksReadMasterDataParams ,
68 QuickBooksReadMasterDataResponse ,
@@ -19,6 +21,102 @@ import {
1921} from '@/tools/quickbooks/utils'
2022import type { ToolConfig } from '@/tools/types'
2123
24+ function optionalString ( value : unknown ) : string | undefined {
25+ return typeof value === 'string' ? value : undefined
26+ }
27+
28+ function optionalBoolean ( value : unknown ) : boolean | undefined {
29+ return typeof value === 'boolean' ? value : undefined
30+ }
31+
32+ function sanitizeEmployeeAddress ( value : unknown ) : QuickBooksAddress | undefined {
33+ if ( ! value || typeof value !== 'object' || Array . isArray ( value ) ) return undefined
34+ const source = value as Record < string , unknown >
35+ const address : QuickBooksAddress = { }
36+ for ( const key of [
37+ 'Id' ,
38+ 'Line1' ,
39+ 'Line2' ,
40+ 'Line3' ,
41+ 'Line4' ,
42+ 'Line5' ,
43+ 'City' ,
44+ 'Country' ,
45+ 'CountrySubDivisionCode' ,
46+ 'PostalCode' ,
47+ 'Lat' ,
48+ 'Long' ,
49+ ] as const ) {
50+ const field = optionalString ( source [ key ] )
51+ if ( field !== undefined ) address [ key ] = field
52+ }
53+ return Object . keys ( address ) . length > 0 ? address : undefined
54+ }
55+
56+ function sanitizeEmployee ( value : QuickBooksMasterDataRecord ) : QuickBooksEmployee {
57+ const source = value as Record < string , unknown >
58+ const id = optionalString ( source . Id ) ?. trim ( )
59+ if ( ! id ) throw new Error ( 'QuickBooks Employee response is missing Id' )
60+
61+ const employee : QuickBooksEmployee = { Id : id }
62+ for ( const key of [
63+ 'SyncToken' ,
64+ 'DisplayName' ,
65+ 'GivenName' ,
66+ 'MiddleName' ,
67+ 'FamilyName' ,
68+ 'Suffix' ,
69+ 'Title' ,
70+ 'PrintOnCheckName' ,
71+ ] as const ) {
72+ const field = optionalString ( source [ key ] )
73+ if ( field !== undefined ) employee [ key ] = field
74+ }
75+ for ( const key of [ 'Active' , 'BillableTime' , 'sparse' ] as const ) {
76+ const field = optionalBoolean ( source [ key ] )
77+ if ( field !== undefined ) employee [ key ] = field
78+ }
79+
80+ const primaryPhone = source . PrimaryPhone
81+ if ( primaryPhone && typeof primaryPhone === 'object' && ! Array . isArray ( primaryPhone ) ) {
82+ const freeFormNumber = optionalString ( ( primaryPhone as Record < string , unknown > ) . FreeFormNumber )
83+ if ( freeFormNumber !== undefined ) employee . PrimaryPhone = { FreeFormNumber : freeFormNumber }
84+ }
85+ const mobile = source . Mobile
86+ if ( mobile && typeof mobile === 'object' && ! Array . isArray ( mobile ) ) {
87+ const freeFormNumber = optionalString ( ( mobile as Record < string , unknown > ) . FreeFormNumber )
88+ if ( freeFormNumber !== undefined ) employee . Mobile = { FreeFormNumber : freeFormNumber }
89+ }
90+ const primaryEmail = source . PrimaryEmailAddr
91+ if ( primaryEmail && typeof primaryEmail === 'object' && ! Array . isArray ( primaryEmail ) ) {
92+ const address = optionalString ( ( primaryEmail as Record < string , unknown > ) . Address )
93+ if ( address !== undefined ) employee . PrimaryEmailAddr = { Address : address }
94+ }
95+
96+ employee . PrimaryAddr = sanitizeEmployeeAddress ( source . PrimaryAddr )
97+ const metadata = source . MetaData
98+ if ( metadata && typeof metadata === 'object' && ! Array . isArray ( metadata ) ) {
99+ const metadataSource = metadata as Record < string , unknown >
100+ const createTime = optionalString ( metadataSource . CreateTime )
101+ const lastUpdatedTime = optionalString ( metadataSource . LastUpdatedTime )
102+ if ( createTime !== undefined || lastUpdatedTime !== undefined ) {
103+ employee . MetaData = {
104+ ...( createTime !== undefined ? { CreateTime : createTime } : { } ) ,
105+ ...( lastUpdatedTime !== undefined ? { LastUpdatedTime : lastUpdatedTime } : { } ) ,
106+ }
107+ }
108+ }
109+
110+ return employee
111+ }
112+
113+ function sanitizeMasterDataRecord (
114+ recordType : QuickBooksReadMasterDataParams [ 'recordType' ] ,
115+ value : QuickBooksMasterDataRecord
116+ ) : QuickBooksMasterDataRecord {
117+ return recordType === 'employee' ? sanitizeEmployee ( value ) : value
118+ }
119+
22120export const quickbooksReadMasterDataTool : ToolConfig <
23121 QuickBooksReadMasterDataParams ,
24122 QuickBooksReadMasterDataResponse
@@ -121,6 +219,9 @@ export const quickbooksReadMasterDataTool: ToolConfig<
121219 output : {
122220 recordType : params . recordType ,
123221 ...result . output ,
222+ items : result . output . items . map ( ( item ) =>
223+ sanitizeMasterDataRecord ( params . recordType , item )
224+ ) ,
124225 } ,
125226 }
126227 }
@@ -133,7 +234,7 @@ export const quickbooksReadMasterDataTool: ToolConfig<
133234 success : true ,
134235 output : {
135236 recordType : params . recordType ,
136- item : result . item ,
237+ item : sanitizeMasterDataRecord ( params . recordType , result . item ) ,
137238 time : result . time ,
138239 } ,
139240 }
0 commit comments