UNPKG

@simpleapps-com/augur-api

Version:

TypeScript client library for Augur microservices API endpoints

962 lines 36 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AugurAPI = exports.ContextCreationError = void 0; const client_1 = require("./core/client"); const config_1 = require("./core/config"); const joomla_1 = require("./services/joomla"); const commerce_1 = require("./services/commerce"); const pricing_1 = require("./services/pricing"); const vmi_1 = require("./services/vmi"); const open_search_1 = require("./services/open-search"); const items_1 = require("./services/items"); const legacy_1 = require("./services/legacy"); const nexus_1 = require("./services/nexus"); const agr_site_1 = require("./services/agr-site"); const customers_1 = require("./services/customers"); const orders_1 = require("./services/orders"); const p21_pim_1 = require("./services/p21-pim"); const payments_1 = require("./services/payments"); const agr_info_1 = require("./services/agr-info"); const agr_work_1 = require("./services/agr-work"); const avalara_1 = require("./services/avalara"); const brand_folder_1 = require("./services/brand-folder"); const gregorovich_1 = require("./services/gregorovich"); const logistics_1 = require("./services/logistics"); const p21_apis_1 = require("./services/p21-apis"); const p21_core_1 = require("./services/p21-core"); const p21_sism_1 = require("./services/p21-sism"); const shipping_1 = require("./services/shipping"); const slack_1 = require("./services/slack"); const smarty_streets_1 = require("./services/smarty-streets"); const ups_1 = require("./services/ups"); var config_2 = require("./core/config"); Object.defineProperty(exports, "ContextCreationError", { enumerable: true, get: function () { return config_2.ContextCreationError; } }); /** * Main client factory for accessing Augur microservices * * @example * ```typescript * // Traditional approach * const api = new AugurAPI({ * siteId: 'my-site-id', * bearerToken: 'my-bearer-token' * }); * * // Context-aware approach (recommended) * const api = AugurAPI.fromContext(context); * * // Access Joomla service * const users = await api.joomla.users.list(); * * // Access Commerce service * const cart = await api.commerce.cartHeaders.lookup({ userId: 123, customerId: 456, contactId: 789 }); * * // Access Pricing service * const price = await api.pricing.getPrice({ customerId: 12345, itemId: 'ABC123', quantity: 10 }); * * // Access VMI service * const warehouses = await api.vmi.warehouses.list({ customerId: 12345 }); * * // Access OpenSearch service * const searchResults = await api.opensearch.itemSearch.search({ q: 'electrical wire', searchType: 'query' }); * * // Access Items service * const product = await api.items.products.get(12345); * const categories = await api.items.categories.get(100); * * // Access Legacy service * const states = await api.legacy.states.list({ twoLetterCode: 'CA' }); * const alsoBought = await api.legacy.inventory.getAlsoBought(12345); * * // Access Nexus service * const binTransfer = await api.nexus.binTransfers.create({ * usersId: 1001, * locationId: 5.0, * transfers: [{ lineNo: 1, invMastUid: 67890, itemId: 'ITEM001', toBin: 'A1-01', fromBin: 'B2-05', lot: 'LOT123', uom: 'EA', quantity: 10 }] * }); * * // Access AGR Site service * const health = await api.agrSite.getHealthCheck(); * const settings = await api.agrSite.settings.list({ serviceName: 'commerce' }); * const transcript = await api.agrSite.fyxerTranscripts.create({ link: 'https://example.com/doc.pdf' }); * * // Access Customers service * const customers = await api.customers.customer.list({ limit: 10 }); * const customer = await api.customers.customer.get(12345); * const contacts = await api.customers.customer.contacts.list(12345, { q: 'John' }); * const newContact = await api.customers.customer.contacts.create(12345, { * firstName: 'Jane', lastName: 'Doe', email: 'jane@example.com' * }); * * // Access Orders service * const orders = await api.orders.orders.lookup({ limit: 10, q: '12345' }); * const orderDoc = await api.orders.orders.getDocument(12345678, { postalCode: '12345' }); * const salesRepOrders = await api.orders.salesRep.getOrders(123); * const purchaseOrders = await api.orders.purchaseOrders.list({ complete: 'N', limit: 20 }); * const invoiceReprint = await api.orders.invoices.reprint('INV123456'); * * // Access P21 PIM service * const invExtensions = await api.p21Pim.inventoryMasterExtensions.list({ limit: 20 }); * const displaySuggestions = await api.p21Pim.items.suggestDisplayDescription(12345); * const webSuggestions = await api.p21Pim.items.suggestWebDescription(12345, { limit: 5 }); * const podcasts = await api.p21Pim.podcasts.list({ q: 'manufacturing' }); * * // Access Payments service * const transactionSetup = await api.payments.unified.transactionSetup({ customerId: '123' }); * const accountQuery = await api.payments.unified.accountQuery({ * customerId: '123', * transactionSetupId: transactionSetup.data.transactionSetupId * }); * const surcharge = await api.payments.unified.surcharge({ * customerId: '123', * paymentAccountId: '456', * amount: '100.00', * fromState: 'CA', * toState: 'NY', * country: 'US' * }); * ``` */ class AugurAPI { constructor(config) { this.config = config; } /** * Create AugurAPI client from context object * * Automatically extracts siteId and authentication token from context, * eliminating the need for manual configuration boilerplate. * * @param context Context object containing siteId and authentication * @param options Optional configuration overrides * @returns AugurAPI instance configured from context * * @example * ```typescript * // Instead of manual configuration: * const userJwt = await getToken({ req: request }); * const api = new AugurAPI({ siteId: context.siteId, bearerToken: userJwt.jwtToken }); * * // Simply use: * const api = AugurAPI.fromContext(context); * * // With optional overrides: * const api = AugurAPI.fromContext(context, { timeout: 10000 }); * ``` * * @throws {ContextCreationError} When context is invalid or missing required fields */ static fromContext(context, options = {}) { // Validate context if (!context) { throw new config_1.ContextCreationError('Context is required', 'context'); } if (!context.siteId) { throw new config_1.ContextCreationError('Context must contain siteId', 'siteId'); } // Extract bearer token from jwt or bearerToken field const bearerToken = context.jwt || context.bearerToken; if (!bearerToken) { throw new config_1.ContextCreationError('Context must contain jwt or bearerToken for authentication', 'bearerToken'); } // Create configuration from context const config = { siteId: context.siteId, bearerToken, ...options, // Allow overrides }; return new AugurAPI(config); } /** * Access Joomla service endpoints */ get joomla() { if (!this._joomla) { const httpClient = new client_1.HTTPClient('joomla', this.config); this._joomla = new joomla_1.JoomlaClient(httpClient); } return this._joomla; } /** * Access Commerce service endpoints */ get commerce() { if (!this._commerce) { const httpClient = new client_1.HTTPClient('commerce', this.config); this._commerce = new commerce_1.CommerceClient(httpClient); } return this._commerce; } /** * Access Pricing service endpoints */ get pricing() { if (!this._pricing) { const httpClient = new client_1.HTTPClient('pricing', this.config); this._pricing = new pricing_1.PricingClient(httpClient); } return this._pricing; } /** * Access VMI (Vendor Managed Inventory) service endpoints */ get vmi() { if (!this._vmi) { const httpClient = new client_1.HTTPClient('vmi', this.config); this._vmi = new vmi_1.VMIClient(httpClient); } return this._vmi; } /** * Access OpenSearch service endpoints */ get opensearch() { if (!this._opensearch) { const httpClient = new client_1.HTTPClient('open-search', this.config); this._opensearch = new open_search_1.OpenSearchClient(httpClient); } return this._opensearch; } /** * Access Items service endpoints */ get items() { if (!this._items) { const httpClient = new client_1.HTTPClient('items', this.config); this._items = new items_1.ItemsClient(httpClient); } return this._items; } /** * Access Legacy service endpoints */ get legacy() { if (!this._legacy) { const httpClient = new client_1.HTTPClient('legacy', this.config); this._legacy = new legacy_1.LegacyClient(httpClient); } return this._legacy; } /** * Access Nexus (Warehouse Management) service endpoints */ get nexus() { if (!this._nexus) { const httpClient = new client_1.HTTPClient('nexus', this.config); this._nexus = new nexus_1.NexusClient(httpClient); } return this._nexus; } /** * Access AGR Site service endpoints */ get agrSite() { if (!this._agrSite) { const httpClient = new client_1.HTTPClient('agr-site', this.config); this._agrSite = new agr_site_1.AgrSiteClient(httpClient); } return this._agrSite; } /** * Access Customers service endpoints */ get customers() { if (!this._customers) { const httpClient = new client_1.HTTPClient('customers', this.config); this._customers = new customers_1.CustomersClient(httpClient); } return this._customers; } /** * Access Orders service endpoints */ get orders() { if (!this._orders) { const httpClient = new client_1.HTTPClient('orders', this.config); this._orders = new orders_1.OrdersClient(httpClient); } return this._orders; } /** * Access P21 PIM (Product Information Management) service endpoints */ get p21Pim() { if (!this._p21Pim) { const httpClient = new client_1.HTTPClient('p21-pim', this.config); this._p21Pim = new p21_pim_1.P21PimClient(httpClient); } return this._p21Pim; } /** * Access Payments service endpoints */ get payments() { if (!this._payments) { const httpClient = new client_1.HTTPClient('payments', this.config); this._payments = new payments_1.PaymentsClient(httpClient); } return this._payments; } /** * Access AGR Info service endpoints */ get agrInfo() { if (!this._agrInfo) { const httpClient = new client_1.HTTPClient('agr-info', this.config); this._agrInfo = new agr_info_1.AgrInfoClient(httpClient); } return this._agrInfo; } /** * Access AGR Work service endpoints */ get agrWork() { if (!this._agrWork) { const httpClient = new client_1.HTTPClient('agr-work', this.config); this._agrWork = new agr_work_1.AgrWorkClient(httpClient); } return this._agrWork; } /** * Access Avalara service endpoints */ get avalara() { if (!this._avalara) { const httpClient = new client_1.HTTPClient('avalara', this.config); this._avalara = new avalara_1.AvalaraClient(httpClient); } return this._avalara; } /** * Access Brand Folder service endpoints */ get brandFolder() { if (!this._brandFolder) { const httpClient = new client_1.HTTPClient('brand-folder', this.config); this._brandFolder = new brand_folder_1.BrandFolderClient(httpClient); } return this._brandFolder; } /** * Access Gregorovich service endpoints */ get gregorovich() { if (!this._gregorovich) { const httpClient = new client_1.HTTPClient('gregorovich', this.config); this._gregorovich = new gregorovich_1.GregorovichClient(httpClient); } return this._gregorovich; } /** * Access Logistics service endpoints */ get logistics() { if (!this._logistics) { const httpClient = new client_1.HTTPClient('logistics', this.config); this._logistics = new logistics_1.LogisticsClient(httpClient); } return this._logistics; } /** * Access P21 APIs service endpoints */ get p21Apis() { if (!this._p21Apis) { const httpClient = new client_1.HTTPClient('p21-apis', this.config); this._p21Apis = new p21_apis_1.P21ApisClient(httpClient); } return this._p21Apis; } /** * Access P21 Core service endpoints */ get p21Core() { if (!this._p21Core) { const httpClient = new client_1.HTTPClient('p21-core', this.config); this._p21Core = new p21_core_1.P21CoreClient(httpClient); } return this._p21Core; } /** * Access P21 SISM service endpoints */ get p21Sism() { if (!this._p21Sism) { const httpClient = new client_1.HTTPClient('p21-sism', this.config); this._p21Sism = new p21_sism_1.P21SismClient(httpClient); } return this._p21Sism; } /** * Access Shipping service endpoints */ get shipping() { if (!this._shipping) { const httpClient = new client_1.HTTPClient('shipping', this.config); this._shipping = new shipping_1.ShippingClient(httpClient); } return this._shipping; } /** * Access Slack service endpoints */ get slack() { if (!this._slack) { const httpClient = new client_1.HTTPClient('slack', this.config); this._slack = new slack_1.SlackClient(httpClient); } return this._slack; } /** * Access SmartyStreets service endpoints */ get smartyStreets() { if (!this._smartyStreets) { const httpClient = new client_1.HTTPClient('smarty-streets', this.config); this._smartyStreets = new smarty_streets_1.SmartyStreetsClient(httpClient); } return this._smartyStreets; } /** * Access UPS service endpoints */ get ups() { if (!this._ups) { const httpClient = new client_1.HTTPClient('ups', this.config); this._ups = new ups_1.UPSClient(httpClient); } return this._ups; } /** * Update authentication token * @param bearerToken New bearer token */ setAuthToken(bearerToken) { this.config.bearerToken = bearerToken; // Reset clients to use new token this._joomla = undefined; this._commerce = undefined; this._pricing = undefined; this._vmi = undefined; this._opensearch = undefined; this._items = undefined; this._legacy = undefined; this._nexus = undefined; this._agrSite = undefined; this._customers = undefined; this._orders = undefined; this._p21Pim = undefined; this._payments = undefined; this._agrInfo = undefined; this._agrWork = undefined; this._avalara = undefined; this._brandFolder = undefined; this._gregorovich = undefined; this._logistics = undefined; this._p21Apis = undefined; this._p21Core = undefined; this._p21Sism = undefined; this._shipping = undefined; this._slack = undefined; this._smartyStreets = undefined; this._ups = undefined; } /** * Update site ID * @param siteId New site ID */ setSiteId(siteId) { this.config.siteId = siteId; // Reset clients to use new site ID this._joomla = undefined; this._commerce = undefined; this._pricing = undefined; this._vmi = undefined; this._opensearch = undefined; this._items = undefined; this._legacy = undefined; this._nexus = undefined; this._agrSite = undefined; this._customers = undefined; this._orders = undefined; this._p21Pim = undefined; this._payments = undefined; this._agrInfo = undefined; this._agrWork = undefined; this._avalara = undefined; this._brandFolder = undefined; this._gregorovich = undefined; this._logistics = undefined; this._p21Apis = undefined; this._p21Core = undefined; this._p21Sism = undefined; this._shipping = undefined; this._slack = undefined; this._smartyStreets = undefined; this._ups = undefined; } /** * Discover all available services and their capabilities * * Returns a complete service map showing all discoverable endpoints across * all microservices, enabling AI agents to understand the full API topology. * * @returns Promise<ServiceMap[]> Array of service maps with endpoint metadata * * @example * ```typescript * const api = new AugurAPI({ siteId: 'my-site', bearerToken: 'token' }); * const services = await api.discover(); * * // Find all user-related endpoints * const userEndpoints = services.flatMap(s => s.endpoints) * .filter(e => e.searchTerms.some(term => term.includes('user'))); * * // Show service capabilities * services.forEach(service => { * console.log(`${service.serviceName}: ${service.endpointCount} endpoints`); * service.endpoints.forEach(endpoint => { * console.log(` ${endpoint.fullPath} - ${endpoint.description}`); * }); * }); * ``` */ async discover() { const services = []; // Get all available service clients const serviceClients = [ { name: 'joomla', client: this.joomla }, { name: 'commerce', client: this.commerce }, { name: 'pricing', client: this.pricing }, { name: 'vmi', client: this.vmi }, { name: 'opensearch', client: this.opensearch }, { name: 'items', client: this.items }, { name: 'legacy', client: this.legacy }, { name: 'nexus', client: this.nexus }, { name: 'agrSite', client: this.agrSite }, { name: 'customers', client: this.customers }, { name: 'orders', client: this.orders }, { name: 'p21Pim', client: this.p21Pim }, { name: 'payments', client: this.payments }, { name: 'agrInfo', client: this.agrInfo }, { name: 'agrWork', client: this.agrWork }, { name: 'avalara', client: this.avalara }, { name: 'brandFolder', client: this.brandFolder }, { name: 'gregorovich', client: this.gregorovich }, { name: 'logistics', client: this.logistics }, { name: 'p21Apis', client: this.p21Apis }, { name: 'p21Core', client: this.p21Core }, { name: 'p21Sism', client: this.p21Sism }, { name: 'shipping', client: this.shipping }, { name: 'slack', client: this.slack }, { name: 'smartyStreets', client: this.smartyStreets }, { name: 'ups', client: this.ups }, ]; for (const { name, client } of serviceClients) { try { // Get discovery metadata from each service client const metadata = client.getDiscoveryMetadata(); services.push({ serviceName: metadata.serviceName || name, description: metadata.description, baseUrl: metadata.baseUrl, endpointCount: metadata.endpoints.length, endpoints: metadata.endpoints, }); } catch { // Silently skip services that don't support discovery continue; } } return services; } /** * Find endpoints by search term or functionality description * * Searches across all services to find endpoints that match the given search term. * Uses intelligent matching against endpoint descriptions, search terms, domains, * and common usage patterns. * * @param searchTerm The functionality or term to search for * @param options Search options for filtering and ranking * @returns Promise<EndpointSearchResult[]> Array of matching endpoints with relevance scores * * @example * ```typescript * const api = new AugurAPI({ siteId: 'my-site', bearerToken: 'token' }); * * // Find user-related endpoints * const userEndpoints = await api.findEndpoint('users'); * console.log(`Found ${userEndpoints.length} user-related endpoints`); * * // Find authentication endpoints * const authEndpoints = await api.findEndpoint('authentication'); * * // Find inventory management * const inventoryEndpoints = await api.findEndpoint('inventory management'); * * // Show results with scores * userEndpoints.forEach(result => { * console.log(`${result.endpoint.fullPath} (${result.score.toFixed(2)}) - ${result.matchReason}`); * }); * ``` */ async findEndpoint(searchTerm, options = {}) { const { minScore = 0.1, maxResults = 10, service, domain, readOnly = false } = options; // Handle empty search term if (!searchTerm.trim()) { return []; } // Get filtered endpoints const filteredEndpoints = await this.getFilteredEndpoints({ service, domain, readOnly }); // Search and score endpoints const results = this.searchAndScoreEndpoints(filteredEndpoints, searchTerm, { domain, minScore, }); // Sort by relevance score (highest first) and limit results return results.sort((a, b) => b.score - a.score).slice(0, maxResults); } /** * Get endpoints filtered by service, domain, and method options */ async getFilteredEndpoints(filters) { const { service, domain, readOnly } = filters; const services = await this.discover(); let filteredEndpoints = services.flatMap(s => s.endpoints); if (service) { filteredEndpoints = filteredEndpoints.filter(e => e.service === service); } if (domain) { filteredEndpoints = filteredEndpoints.filter(e => e.domain === domain); } if (readOnly) { filteredEndpoints = filteredEndpoints.filter(e => e.method === 'GET'); } return filteredEndpoints; } /** * Search and score endpoints against search term */ searchAndScoreEndpoints(endpoints, searchTerm, options) { const { domain, minScore } = options; const results = []; const searchTermLower = searchTerm.toLowerCase(); for (const endpoint of endpoints) { // Skip malformed endpoints if (!this.isValidEndpoint(endpoint)) { continue; } const { finalScore, finalMatchReason } = this.calculateFinalScore(endpoint, searchTermLower, domain); if (finalScore >= minScore) { results.push({ endpoint, score: finalScore, matchReason: finalMatchReason, }); } } return results; } /** * Check if endpoint has required fields */ isValidEndpoint(endpoint) { return !!(endpoint.domain && endpoint.description && endpoint.method); } /** * Calculate final score with domain filter adjustments */ calculateFinalScore(endpoint, searchTermLower, domain) { const { score, matchReason } = this.calculateEndpointRelevance(endpoint, searchTermLower); // If domain filter is applied and search score is 0, give minimal score if (domain && score === 0) { return { finalScore: 0.1, finalMatchReason: 'Domain filter match', }; } return { finalScore: score, finalMatchReason: matchReason, }; } /** * Calculate relevance score for an endpoint against a search term */ calculateEndpointRelevance(endpoint, searchTermLower) { const exactMatches = this.calculateExactMatches(endpoint, searchTermLower); const partialMatches = this.calculatePartialMatches(endpoint, searchTermLower); // Process exact matches if found if (exactMatches.score > 0) { return this.processExactMatches(exactMatches, partialMatches); } // Fallback to multi-word or partial matches return this.processFallbackMatches(endpoint, searchTermLower, partialMatches); } /** * Process exact matches with appropriate combining logic */ processExactMatches(exactMatches, partialMatches) { // Service and search term matches are exclusive if (this.isExclusiveMatch(exactMatches.reason)) { return { score: exactMatches.score, matchReason: exactMatches.reason, }; } // Combinable matches get partial score boost if (this.isCombinableMatch(exactMatches.reason)) { const totalScore = Math.min(exactMatches.score + partialMatches.score, 1.0); return { score: totalScore, matchReason: exactMatches.reason, }; } // Default to exact match return { score: exactMatches.score, matchReason: exactMatches.reason, }; } /** * Check if match type should be exclusive (no combining) */ isExclusiveMatch(reason) { return reason === 'Service match' || reason.startsWith('Search term match'); } /** * Check if match type can be combined with partial matches */ isCombinableMatch(reason) { const combinableReasons = [ 'Description match', 'Full path match', 'Path substring match', 'Domain match', 'Usage pattern match', ]; return combinableReasons.includes(reason); } /** * Process fallback matches when no exact match found */ processFallbackMatches(endpoint, searchTermLower, partialMatches) { const multiWordMatches = this.calculateMultiWordMatches(endpoint, searchTermLower); if (multiWordMatches.score > partialMatches.score) { return { score: multiWordMatches.score, matchReason: multiWordMatches.reason, }; } return { score: partialMatches.score, matchReason: partialMatches.reason || 'Low relevance match', }; } /** * Calculate exact field matches with high scores */ calculateExactMatches(endpoint, searchTermLower) { // Check matches in priority order (not just highest score) // Priority 1: Exact field matches (domain, service, exact path, exact description) const exactMatch = this.checkExactFieldMatches(endpoint, searchTermLower); if (exactMatch.score > 0) { return exactMatch; } // Priority 2: Path and description substring matches (higher business value) const pathMatch = this.checkPathSubstringMatch(endpoint, searchTermLower); if (pathMatch.score > 0) { return pathMatch; } const descSubstringMatch = this.checkDescriptionSubstringMatch(endpoint, searchTermLower); if (descSubstringMatch.score > 0) { return descSubstringMatch; } // Priority 3: Search terms and patterns const termMatch = this.checkSearchTermsAndPatterns(endpoint, searchTermLower); if (termMatch.score > 0) { return termMatch; } // Priority 4: Other substring matches (domain, service) const otherSubstringMatch = this.checkOtherSubstringMatches(endpoint, searchTermLower); if (otherSubstringMatch.score > 0) { return otherSubstringMatch; } return { score: 0, reason: '' }; } /** * Check for path substring matches */ checkPathSubstringMatch(endpoint, searchTermLower) { if (endpoint.fullPath && (endpoint.fullPath.toLowerCase().includes(searchTermLower) || searchTermLower.includes(endpoint.fullPath.toLowerCase()))) { return { score: 0.9, reason: 'Path substring match' }; } return { score: 0, reason: '' }; } /** * Check for description substring matches */ checkDescriptionSubstringMatch(endpoint, searchTermLower) { if (endpoint.description && endpoint.description.toLowerCase().includes(searchTermLower)) { return { score: 0.65, reason: 'Description substring match' }; } return { score: 0, reason: '' }; } /** * Check for other substring matches (domain, service) */ checkOtherSubstringMatches(endpoint, searchTermLower) { if (endpoint.domain && endpoint.domain.toLowerCase().includes(searchTermLower)) { return { score: 0.5, reason: 'Domain match' }; } if (endpoint.service && endpoint.service.toLowerCase().includes(searchTermLower)) { return { score: 0.3, reason: 'Service match' }; } return { score: 0, reason: '' }; } /** * Check for exact field matches */ checkExactFieldMatches(endpoint, searchTermLower) { if (endpoint.domain && endpoint.domain.toLowerCase() === searchTermLower) { return { score: 0.6, reason: 'Domain match' }; } if (endpoint.service && endpoint.service.toLowerCase() === searchTermLower) { return { score: 0.3, reason: 'Service match' }; } if (endpoint.fullPath && endpoint.fullPath.toLowerCase() === searchTermLower) { return { score: 1.0, reason: 'Full path match' }; } if (endpoint.description && endpoint.description.toLowerCase() === searchTermLower) { return { score: 0.8, reason: 'Description match' }; } return { score: 0, reason: '' }; } /** * Check search terms and common patterns */ checkSearchTermsAndPatterns(endpoint, searchTermLower) { if (Array.isArray(endpoint.searchTerms)) { const searchTermMatches = endpoint.searchTerms.filter(term => term && typeof term === 'string' && term.toLowerCase().includes(searchTermLower)); if (searchTermMatches.length > 0) { return { score: 0.7, reason: `Search term match: ${searchTermMatches[0]}` }; } } if (Array.isArray(endpoint.commonPatterns)) { const patternMatches = endpoint.commonPatterns.filter(pattern => { if (!pattern || typeof pattern !== 'string') return false; const patternLower = pattern.toLowerCase(); return patternLower.includes(searchTermLower); }); if (patternMatches.length > 0) { return { score: 0.5, reason: 'Usage pattern match' }; } } return { score: 0, reason: '' }; } /** * Calculate partial word matches with lower scores */ calculatePartialMatches(endpoint, searchTermLower) { const allText = this.buildSearchableText(endpoint); const wordMatches = this.countWordMatches(searchTermLower, allText); return this.buildPartialMatchResult(wordMatches, searchTermLower); } /** * Build searchable text from endpoint fields */ buildSearchableText(endpoint) { const searchTerms = Array.isArray(endpoint.searchTerms) ? endpoint.searchTerms : []; const commonPatterns = Array.isArray(endpoint.commonPatterns) ? endpoint.commonPatterns : []; return [ endpoint.fullPath || '', endpoint.description || '', endpoint.domain || '', endpoint.service || '', ...searchTerms, ...commonPatterns, ] .filter(text => typeof text === 'string') .join(' ') .toLowerCase(); } /** * Count matching words in text */ countWordMatches(searchTermLower, allText) { const searchWords = searchTermLower.split(/\s+/).filter(word => word.length > 0); let wordMatches = 0; for (const word of searchWords) { if (word.length > 2 && allText.includes(word)) { wordMatches++; } } return wordMatches; } /** * Build partial match result with score and reason */ buildPartialMatchResult(wordMatches, searchTermLower) { if (wordMatches > 0) { const searchWords = searchTermLower.split(/\s+/).filter(word => word.length > 0); const partialScore = (wordMatches / searchWords.length) * 0.2; const reasonText = `Partial word match (${wordMatches}/${searchWords.length})`; return { score: partialScore, reason: reasonText, matchReason: reasonText, }; } return { score: 0, reason: '', matchReason: '' }; } /** * Calculate multi-word matches by finding the best match for each word */ calculateMultiWordMatches(endpoint, searchTermLower) { const searchWords = searchTermLower.split(/\s+/).filter(word => word.length > 0); // If only one word, fall back to exact matching if (searchWords.length <= 1) { return { score: 0, reason: '' }; } let bestScore = 0; let bestReason = ''; const matchedWords = []; // Check each word against the endpoint fields for (const word of searchWords) { const wordMatch = this.calculateExactMatches(endpoint, word); if (wordMatch.score > 0) { // Keep track of the highest scoring match if (wordMatch.score > bestScore) { bestScore = wordMatch.score; bestReason = wordMatch.reason; } matchedWords.push(word); } } // If we matched multiple words, boost the score if (matchedWords.length > 1) { // Base score is the best individual match, with bonus for additional matches const bonusScore = Math.min((matchedWords.length - 1) * 0.1, 0.3); const finalScore = Math.min(bestScore + bonusScore, 1.0); return { score: finalScore, reason: `Multi-word match (${matchedWords.length}/${searchWords.length} words): ${bestReason}`, }; } // Single word match - return as-is if (bestScore > 0) { return { score: bestScore, reason: bestReason, }; } return { score: 0, reason: '' }; } } exports.AugurAPI = AugurAPI; //# sourceMappingURL=client.js.map