@360works/fmpromise
Version:
Richer FileMaker WebViewer
108 lines (98 loc) • 3.21 kB
text/typescript
import PerformScript from "./perform-script";
interface QueryRow {
any: any
omit?: 'true'
}
interface SortRow {
fieldName: string,
sortOrder?: 'ascend' | 'descend'
}
interface DataRequest {
layouts: string,
action?: 'metadata' | 'read'
'layout.response'?: string,
limit?: number
offset?: number
query?: QueryRow[]
recordId?:number
sort?: SortRow[]
portal?: string[]
}
interface DataResponse {
layouts?: { name: string, table: string }[]
fieldMetaData?: {}[]
portalMetaData?: {}[]
valueLists?: {}[]
dataInfo?: { database: string, layout: string, table: string, totalRecordCount: number, foundCount: number, returnedCount: number }
data?: { recordId: number, modId: number, fieldData: {}, portalData: {}, portalDataInfo: {}[] }[]
}
class DataResponseRecord extends Object {
recId: number
modId: number
constructor(value: any, recId: number, modId: number) {
super(value);
this.recId = recId;
this.modId = modId;
Object.defineProperty(this, 'recId', {
enumerable: false,
value: recId
});
Object.defineProperty(this, 'modId', {
enumerable: false,
value: modId
});
}
}
/**
* Execute a FileMaker Data API call with the given parameter.
* <p>
* If you are simply fetching record data, you may want to use #executeFileMakeDataAPIRecords which returns an array of just the fieldData objects without any of the other metadata.
*
* For example, to perform a multi-part find request on a layout, returning the first 10 rows:
* await fmPromise.executeFileMakerDataAPI(
* {
* layouts:'Contacts',
* limit: 10,
* query: [
* {City: 'San Francisco'},
* {City: 'Atlanta'}
* ],
* sort: [
* {fieldName:'lastName', sortOrder:'ascend'},
* {fieldName:'firstName', sortOrder:'ascend'}
* ]
* }
* )
*/
function ExecuteFileMakerDataAPI(param: DataRequest): Promise<DataResponse> {
return PerformScript('fmPromise.executeFileMakerDataAPI', param)
.then((result) => {
// do error-checking on the data API result here instead of in FileMaker, as JSON parsing for large payloads is faster
if (!result || !result.messages || !result.messages.length) {
throw new FMPromiseError({code: -1, message: 'Empty data API response'});
} else if (result.messages[0].code !== '0') {
throw new FMPromiseError(result.messages[0]); // has a code and message, conveniently
} else {
return result.response;
}
})
}
/**
* This is syntactic sugar for {@link #ExecuteFileMakerDataAPI} when all you want is the `fieldData` from the `data` array, which is most of the time.
* Don't pass `action:metadata` to this, it's only for `action:read`
*/
function ExecuteFileMakerDataAPIRecords(param: DataRequest): Promise<DataResponseRecord[]> {
return ExecuteFileMakerDataAPI(param)
.then(response => {
if (!response.data) {
throw new FMPromiseError({message: 'No data'});
}
return response.data.map(o => {
// rec.recordId = o.recordId;
// rec.modId = o.modId;
// Object.assign(rec, o.portalData); // copy portal data onto the record
return new DataResponseRecord(o.fieldData, o.recordId, o.modId)
})
})
}
export {ExecuteFileMakerDataAPI, ExecuteFileMakerDataAPIRecords}