@simpleapps-com/augur-api
Version:
TypeScript client library for Augur microservices API endpoints
962 lines • 36 kB
JavaScript
"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