UNPKG

mcp-quickbase

Version:

Work with Quickbase via Model Context Protocol

181 lines 7.83 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CreateRelationshipTool = void 0; const base_1 = require("../base"); const logger_1 = require("../../utils/logger"); const logger = (0, logger_1.createLogger)("CreateRelationshipTool"); /** * Tool for creating a new table-to-table relationship in Quickbase. * * Creates a reference field in the child table linking to the parent table. * Optionally creates lookup fields and/or summary fields. */ class CreateRelationshipTool extends base_1.BaseTool { /** * Constructor * @param client Quickbase client */ constructor(client) { super(client); this.name = "create_relationship"; this.description = "Creates a new table-to-table relationship linking a child table to a parent table. " + "This creates a reference field in the child table. Optionally creates lookup fields " + "(to display parent data in child records) and/or a summary field (to aggregate child " + "data in parent records). Relationships can only be created between tables in the same " + "application. This operation is SAFE and does not modify existing data."; /** * Parameter schema for create_relationship with conditional validation */ this.paramSchema = { type: "object", properties: { table_id: { type: "string", description: "The ID of the child Quickbase table (DBID) where the relationship reference field will be created", }, parent_table_id: { type: "string", description: "The ID of the parent Quickbase table (DBID) to link to", }, foreign_key_label: { type: "string", description: "Optional label for the foreign key reference field created in the child table", }, lookup_field_ids: { type: "array", items: { type: "number", }, description: "Optional array of parent field IDs to create 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", "parent_table_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 create_relationship tool * @param params Tool parameters * @returns Created relationship details */ async run(params) { const { table_id, parent_table_id, foreign_key_label, lookup_field_ids, summary_field_id, summary_label, summary_accumulation_type, summary_where, } = params; logger.info("Creating relationship between tables", { childTableId: table_id, parentTableId: parent_table_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 = { parentTableId: parent_table_id, }; // Add optional foreign key label if (foreign_key_label) { body.foreignKeyField = { label: foreign_key_label, }; } // 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]; } // Create the relationship const response = await this.client.request({ method: "POST", path: `/tables/${table_id}/relationship`, body, }); if (!response.success || !response.data) { logger.error("Failed to create relationship", { error: response.error, childTableId: table_id, parentTableId: parent_table_id, }); throw new Error(response.error?.message || "Failed to create 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 created relationship", { relationshipId: result.id, childTableId: result.childTableId, parentTableId: result.parentTableId, lookupFieldsCreated: result.lookupFields.length, summaryFieldsCreated: result.summaryFields.length, }); return result; } } exports.CreateRelationshipTool = CreateRelationshipTool; //# sourceMappingURL=create_relationship.js.map