@proofkit/fmodata
Version:
FileMaker OData API client
239 lines (238 loc) • 8.54 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
import { QueryBuilder } from "./query-builder.js";
import { getTableIdentifiers, transformFieldNamesToIds } from "../transform.js";
class UpdateBuilder {
constructor(config) {
__publicField(this, "tableName");
__publicField(this, "databaseName");
__publicField(this, "context");
__publicField(this, "occurrence");
__publicField(this, "data");
__publicField(this, "returnPreference");
__publicField(this, "databaseUseEntityIds");
this.occurrence = config.occurrence;
this.tableName = config.tableName;
this.databaseName = config.databaseName;
this.context = config.context;
this.data = config.data;
this.returnPreference = config.returnPreference;
this.databaseUseEntityIds = config.databaseUseEntityIds ?? false;
}
/**
* Update a single record by ID
* Returns updated count by default, or full record if returnFullRecord was set to true
*/
byId(id) {
return new ExecutableUpdateBuilder({
occurrence: this.occurrence,
tableName: this.tableName,
databaseName: this.databaseName,
context: this.context,
data: this.data,
mode: "byId",
recordId: id,
returnPreference: this.returnPreference,
databaseUseEntityIds: this.databaseUseEntityIds
});
}
/**
* Update records matching a filter query
* Returns updated count by default, or full record if returnFullRecord was set to true
* @param fn Callback that receives a QueryBuilder for building the filter
*/
where(fn) {
const queryBuilder = new QueryBuilder({
occurrence: void 0,
tableName: this.tableName,
databaseName: this.databaseName,
context: this.context
});
const configuredBuilder = fn(queryBuilder);
return new ExecutableUpdateBuilder({
occurrence: this.occurrence,
tableName: this.tableName,
databaseName: this.databaseName,
context: this.context,
data: this.data,
mode: "byFilter",
queryBuilder: configuredBuilder,
returnPreference: this.returnPreference,
databaseUseEntityIds: this.databaseUseEntityIds
});
}
}
class ExecutableUpdateBuilder {
constructor(config) {
__publicField(this, "tableName");
__publicField(this, "databaseName");
__publicField(this, "context");
__publicField(this, "occurrence");
__publicField(this, "data");
__publicField(this, "mode");
__publicField(this, "recordId");
__publicField(this, "queryBuilder");
__publicField(this, "returnPreference");
__publicField(this, "databaseUseEntityIds");
this.occurrence = config.occurrence;
this.tableName = config.tableName;
this.databaseName = config.databaseName;
this.context = config.context;
this.data = config.data;
this.mode = config.mode;
this.recordId = config.recordId;
this.queryBuilder = config.queryBuilder;
this.returnPreference = config.returnPreference;
this.databaseUseEntityIds = config.databaseUseEntityIds ?? false;
}
/**
* Helper to merge database-level useEntityIds with per-request options
*/
mergeExecuteOptions(options) {
return {
...options,
useEntityIds: (options == null ? void 0 : options.useEntityIds) ?? this.databaseUseEntityIds
};
}
/**
* Gets the table ID (FMTID) if using entity IDs, otherwise returns the table name
* @param useEntityIds - Optional override for entity ID usage
*/
getTableId(useEntityIds) {
var _a, _b;
if (!this.occurrence) {
return this.tableName;
}
const contextDefault = ((_b = (_a = this.context)._getUseEntityIds) == null ? void 0 : _b.call(_a)) ?? false;
const shouldUseIds = useEntityIds ?? contextDefault;
if (shouldUseIds) {
const identifiers = getTableIdentifiers(this.occurrence);
if (!identifiers.id) {
throw new Error(
`useEntityIds is true but TableOccurrence "${identifiers.name}" does not have an fmtId defined`
);
}
return identifiers.id;
}
return this.occurrence.getTableName();
}
async execute(options) {
var _a;
const mergedOptions = this.mergeExecuteOptions(options);
const tableId = this.getTableId(mergedOptions.useEntityIds);
const shouldUseIds = mergedOptions.useEntityIds ?? false;
const transformedData = ((_a = this.occurrence) == null ? void 0 : _a.baseTable) && shouldUseIds ? transformFieldNamesToIds(this.data, this.occurrence.baseTable) : this.data;
let url;
if (this.mode === "byId") {
url = `/${this.databaseName}/${tableId}('${this.recordId}')`;
} else {
if (!this.queryBuilder) {
throw new Error("Query builder is required for filter-based update");
}
const queryString = this.queryBuilder.getQueryString();
const queryParams = queryString.startsWith(`/${tableId}`) ? queryString.slice(`/${tableId}`.length) : queryString.startsWith(`/${this.tableName}`) ? queryString.slice(`/${this.tableName}`.length) : queryString;
url = `/${this.databaseName}/${tableId}${queryParams}`;
}
const headers = {
"Content-Type": "application/json"
};
if (this.returnPreference === "representation") {
headers["Prefer"] = "return=representation";
}
const result = await this.context._makeRequest(url, {
method: "PATCH",
headers,
body: JSON.stringify(transformedData),
...mergedOptions
});
if (result.error) {
return { data: void 0, error: result.error };
}
const response = result.data;
if (this.returnPreference === "representation") {
return {
data: response,
error: void 0
};
} else {
let updatedCount = 0;
if (typeof response === "number") {
updatedCount = response;
} else if (response && typeof response === "object") {
updatedCount = response.updatedCount || 0;
}
return {
data: { updatedCount },
error: void 0
};
}
}
getRequestConfig() {
var _a;
const tableId = this.getTableId(this.databaseUseEntityIds);
const transformedData = ((_a = this.occurrence) == null ? void 0 : _a.baseTable) && this.databaseUseEntityIds ? transformFieldNamesToIds(this.data, this.occurrence.baseTable) : this.data;
let url;
if (this.mode === "byId") {
url = `/${this.databaseName}/${tableId}('${this.recordId}')`;
} else {
if (!this.queryBuilder) {
throw new Error("Query builder is required for filter-based update");
}
const queryString = this.queryBuilder.getQueryString();
const queryParams = queryString.startsWith(`/${tableId}`) ? queryString.slice(`/${tableId}`.length) : queryString.startsWith(`/${this.tableName}`) ? queryString.slice(`/${this.tableName}`.length) : queryString;
url = `/${this.databaseName}/${tableId}${queryParams}`;
}
return {
method: "PATCH",
url,
body: JSON.stringify(transformedData)
};
}
toRequest(baseUrl) {
const config = this.getRequestConfig();
const fullUrl = `${baseUrl}${config.url}`;
return new Request(fullUrl, {
method: config.method,
headers: {
"Content-Type": "application/json",
Accept: "application/json"
},
body: config.body
});
}
async processResponse(response, options) {
const text = await response.text();
if (!text || text.trim() === "") {
const affectedRows = response.headers.get("fmodata.affected_rows");
const updatedCount = affectedRows ? parseInt(affectedRows, 10) : 1;
return {
data: { updatedCount },
error: void 0
};
}
const rawResponse = JSON.parse(text);
if (this.returnPreference === "representation") {
return {
data: rawResponse,
error: void 0
};
} else {
let updatedCount = 0;
if (typeof rawResponse === "number") {
updatedCount = rawResponse;
} else if (rawResponse && typeof rawResponse === "object") {
updatedCount = rawResponse.updatedCount || 0;
}
return {
data: { updatedCount },
error: void 0
};
}
}
}
export {
ExecutableUpdateBuilder,
UpdateBuilder
};
//# sourceMappingURL=update-builder.js.map