mcp-quickbase
Version:
Work with Quickbase via Model Context Protocol
168 lines • 7.29 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.UpdateRelationshipTool = void 0;
const base_1 = require("../base");
const logger_1 = require("../../utils/logger");
const logger = (0, logger_1.createLogger)("UpdateRelationshipTool");
/**
* Tool for updating an existing table-to-table relationship in Quickbase.
*
* ADDITIVE ONLY - adds lookup fields and/or summary fields to existing relationships.
* Does not delete existing fields from the relationship.
*/
class UpdateRelationshipTool extends base_1.BaseTool {
/**
* Constructor
* @param client Quickbase client
*/
constructor(client) {
super(client);
this.name = "update_relationship";
this.description = "Adds lookup fields and/or summary fields to an existing relationship. This operation " +
"is ADDITIVE ONLY - it will not delete existing lookup or summary fields. Use this to " +
"enhance relationships with additional calculated fields. To remove fields from a " +
"relationship, you must delete them individually using the field deletion tools.";
/**
* Parameter schema for update_relationship with conditional validation
*/
this.paramSchema = {
type: "object",
properties: {
table_id: {
type: "string",
description: "The ID of the child Quickbase table (DBID) containing the relationship",
},
relationship_id: {
type: "number",
description: "The ID of the relationship to update (same as the foreign key field ID)",
},
lookup_field_ids: {
type: "array",
items: {
type: "number",
},
description: "Optional array of parent field IDs to add as lookup fields in the child table",
},
summary_field_id: {
type: "number",
description: "Optional child field ID to summarize in the parent table",
},
summary_label: {
type: "string",
description: "Optional label for the summary field created in the parent table",
},
summary_accumulation_type: {
type: "string",
enum: ["SUM", "COUNT", "AVG", "MAX", "MIN"],
description: "Accumulation type for the summary field. Required when summary_field_id is provided. " +
"Valid values: SUM, COUNT, AVG, MAX, MIN",
},
summary_where: {
type: "string",
description: "Optional Quickbase query filter for the summary field (e.g., \"{6.EX.'Active'}\")",
},
},
required: ["table_id", "relationship_id"],
// Conditional validation: summary_accumulation_type is required when summary_field_id is provided
if: {
properties: { summary_field_id: { type: "number" } },
required: ["summary_field_id"],
},
then: {
required: ["summary_accumulation_type"],
},
};
}
/**
* Run the update_relationship tool
* @param params Tool parameters
* @returns Updated relationship details
*/
async run(params) {
const { table_id, relationship_id, lookup_field_ids, summary_field_id, summary_label, summary_accumulation_type, summary_where, } = params;
logger.info("Updating relationship", {
childTableId: table_id,
relationshipId: relationship_id,
hasLookupFields: !!lookup_field_ids?.length,
hasSummaryField: !!summary_field_id,
});
// Validate conditional requirement: summary_accumulation_type required when summary_field_id is provided
if (summary_field_id !== undefined && !summary_accumulation_type) {
const errorMessage = "summary_accumulation_type is required when summary_field_id is provided. " +
"Valid values: SUM, COUNT, AVG, MAX, MIN";
logger.error("Validation failed", { error: errorMessage });
throw new Error(errorMessage);
}
// Build the request body according to Quickbase API format
const body = {};
// Add lookup fields if provided
if (lookup_field_ids && lookup_field_ids.length > 0) {
body.lookupFieldIds = lookup_field_ids;
}
// Add summary field configuration if provided
if (summary_field_id !== undefined && summary_accumulation_type) {
const summaryField = {
summaryFid: summary_field_id,
accumulationType: summary_accumulation_type,
};
if (summary_label) {
summaryField.label = summary_label;
}
if (summary_where) {
summaryField.where = summary_where;
}
body.summaryFields = [summaryField];
}
// Update the relationship
const response = await this.client.request({
method: "POST",
path: `/tables/${table_id}/relationship/${relationship_id}`,
body,
});
if (!response.success || !response.data) {
logger.error("Failed to update relationship", {
error: response.error,
childTableId: table_id,
relationshipId: relationship_id,
});
throw new Error(response.error?.message || "Failed to update relationship");
}
// Parse and transform the API response
const data = response.data;
const foreignKeyField = data.foreignKeyField;
const lookupFields = data.lookupFields;
const summaryFields = data.summaryFields;
const result = {
id: data.id,
parentTableId: data.parentTableId,
childTableId: data.childTableId,
foreignKeyField: foreignKeyField
? {
id: foreignKeyField.id,
label: foreignKeyField.label,
type: foreignKeyField.type,
}
: { id: 0, label: "", type: "" },
lookupFields: (lookupFields || []).map((field) => ({
id: field.id,
label: field.label,
type: field.type,
})),
summaryFields: (summaryFields || []).map((field) => ({
id: field.id,
label: field.label,
type: field.type,
})),
};
logger.info("Successfully updated relationship", {
relationshipId: result.id,
childTableId: result.childTableId,
parentTableId: result.parentTableId,
totalLookupFields: result.lookupFields.length,
totalSummaryFields: result.summaryFields.length,
});
return result;
}
}
exports.UpdateRelationshipTool = UpdateRelationshipTool;
//# sourceMappingURL=update_relationship.js.map