@path58/n8n-mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENT_INSTALL.md +223 -0
- package/CHANGELOG.md +38 -0
- package/LICENSE +21 -0
- package/README.md +187 -0
- package/dist/autofix/suggestion-fixers/deprecated-node-fixer.js +465 -0
- package/dist/autofix/suggestion-fixers/deprecated-node-fixer.js.map +1 -0
- package/dist/autofix/suggestion-fixers/fixer-registry.js +495 -0
- package/dist/autofix/suggestion-fixers/fixer-registry.js.map +1 -0
- package/dist/autofix/suggestion-fixers/l1-structure-fixer.js +639 -0
- package/dist/autofix/suggestion-fixers/l1-structure-fixer.js.map +1 -0
- package/dist/autofix/suggestion-fixers/l4-connection-fixer.js +449 -0
- package/dist/autofix/suggestion-fixers/l4-connection-fixer.js.map +1 -0
- package/dist/autofix/suggestion-fixers/l5-parameter-fixer.js +575 -0
- package/dist/autofix/suggestion-fixers/l5-parameter-fixer.js.map +1 -0
- package/dist/autofix/suggestion-fixers/l5-typeversion-fixer.js +431 -0
- package/dist/autofix/suggestion-fixers/l5-typeversion-fixer.js.map +1 -0
- package/dist/autofix/suggestion-fixers/l5-webhook-path-fixer.js +356 -0
- package/dist/autofix/suggestion-fixers/l5-webhook-path-fixer.js.map +1 -0
- package/dist/autofix/suggestion-fixers/l6-ai-tool-variant-fixer.js +618 -0
- package/dist/autofix/suggestion-fixers/l6-ai-tool-variant-fixer.js.map +1 -0
- package/dist/autofix/suggestion-fixers/l6-pattern-fixer.js +1475 -0
- package/dist/autofix/suggestion-fixers/l6-pattern-fixer.js.map +1 -0
- package/dist/autofix/suggestion-fixers/llm-fixer.js +716 -0
- package/dist/autofix/suggestion-fixers/llm-fixer.js.map +1 -0
- package/dist/autofix/suggestion-fixers/missing-credential-fixer.js +336 -0
- package/dist/autofix/suggestion-fixers/missing-credential-fixer.js.map +1 -0
- package/dist/autofix/suggestion-fixers/types.js +29 -0
- package/dist/autofix/suggestion-fixers/types.js.map +1 -0
- package/dist/autofix/suggestion-fixers/typo-fixer.js +197 -0
- package/dist/autofix/suggestion-fixers/typo-fixer.js.map +1 -0
- package/dist/classification/certification-engine.js +208 -0
- package/dist/classification/certification-engine.js.map +1 -0
- package/dist/classification/feedback-collector.js +516 -0
- package/dist/classification/feedback-collector.js.map +1 -0
- package/dist/classification/l5-parameter-analyzer.js +670 -0
- package/dist/classification/l5-parameter-analyzer.js.map +1 -0
- package/dist/classification/l6-graph-analyzer.js +613 -0
- package/dist/classification/l6-graph-analyzer.js.map +1 -0
- package/dist/classification/severity-classifier.js +237 -0
- package/dist/classification/severity-classifier.js.map +1 -0
- package/dist/config/env.js +280 -0
- package/dist/config/env.js.map +1 -0
- package/dist/config/env.schema.js +234 -0
- package/dist/config/env.schema.js.map +1 -0
- package/dist/config/scraperEnv.js +55 -0
- package/dist/config/scraperEnv.js.map +1 -0
- package/dist/db/postgresClient.js +38 -0
- package/dist/db/postgresClient.js.map +1 -0
- package/dist/db/scraperDb.js +6 -0
- package/dist/db/scraperDb.js.map +1 -0
- package/dist/db/scraperPostgresClient.js +118 -0
- package/dist/db/scraperPostgresClient.js.map +1 -0
- package/dist/db/validationRepository.js +55 -0
- package/dist/db/validationRepository.js.map +1 -0
- package/dist/db/validatorPostgresClient.js +248 -0
- package/dist/db/validatorPostgresClient.js.map +1 -0
- package/dist/db/workflowInstanceMappingRepository.js +128 -0
- package/dist/db/workflowInstanceMappingRepository.js.map +1 -0
- package/dist/errors/AppError.js +156 -0
- package/dist/errors/AppError.js.map +1 -0
- package/dist/errors/index.js +7 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/factory/error-to-problem-mappers.js +385 -0
- package/dist/factory/error-to-problem-mappers.js.map +1 -0
- package/dist/factory/gap-recorder.js +260 -0
- package/dist/factory/gap-recorder.js.map +1 -0
- package/dist/factory/problem-recorder.js +94 -0
- package/dist/factory/problem-recorder.js.map +1 -0
- package/dist/factory/warning-to-gap-mappers.js +493 -0
- package/dist/factory/warning-to-gap-mappers.js.map +1 -0
- package/dist/factory/workflow-normalizer.js +247 -0
- package/dist/factory/workflow-normalizer.js.map +1 -0
- package/dist/mcp/adapters/catalog.js +13 -0
- package/dist/mcp/adapters/catalog.js.map +1 -0
- package/dist/mcp/adapters/index.js +36 -0
- package/dist/mcp/adapters/index.js.map +1 -0
- package/dist/mcp/adapters/supabase-catalog.js +467 -0
- package/dist/mcp/adapters/supabase-catalog.js.map +1 -0
- package/dist/mcp/adapters/test-catalog-adapter.js +100 -0
- package/dist/mcp/adapters/test-catalog-adapter.js.map +1 -0
- package/dist/mcp/adapters/validation.js +258 -0
- package/dist/mcp/adapters/validation.js.map +1 -0
- package/dist/mcp/build-email-workflow.js +113 -0
- package/dist/mcp/build-email-workflow.js.map +1 -0
- package/dist/mcp/config.js +22 -0
- package/dist/mcp/config.js.map +1 -0
- package/dist/mcp/formatters/errors.js +217 -0
- package/dist/mcp/formatters/errors.js.map +1 -0
- package/dist/mcp/formatters/index.js +12 -0
- package/dist/mcp/formatters/index.js.map +1 -0
- package/dist/mcp/formatters/response.js +141 -0
- package/dist/mcp/formatters/response.js.map +1 -0
- package/dist/mcp/quick-test.js +33 -0
- package/dist/mcp/quick-test.js.map +1 -0
- package/dist/mcp/server.js +70 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/test-mcp-error.js +81 -0
- package/dist/mcp/test-mcp-error.js.map +1 -0
- package/dist/mcp/test-mcp.js +80 -0
- package/dist/mcp/test-mcp.js.map +1 -0
- package/dist/mcp/tools/fixes/expression-fixes.js +166 -0
- package/dist/mcp/tools/fixes/expression-fixes.js.map +1 -0
- package/dist/mcp/tools/fixes/flow-fixes.js +155 -0
- package/dist/mcp/tools/fixes/flow-fixes.js.map +1 -0
- package/dist/mcp/tools/fixes/index.js +91 -0
- package/dist/mcp/tools/fixes/index.js.map +1 -0
- package/dist/mcp/tools/fixes/node-fixes.js +233 -0
- package/dist/mcp/tools/fixes/node-fixes.js.map +1 -0
- package/dist/mcp/tools/fixes/parameter-fixes.js +277 -0
- package/dist/mcp/tools/fixes/parameter-fixes.js.map +1 -0
- package/dist/mcp/tools/fixes/types.js +10 -0
- package/dist/mcp/tools/fixes/types.js.map +1 -0
- package/dist/mcp/tools/handlers/check-parameter.js +300 -0
- package/dist/mcp/tools/handlers/check-parameter.js.map +1 -0
- package/dist/mcp/tools/handlers/find-similar-pattern.js +121 -0
- package/dist/mcp/tools/handlers/find-similar-pattern.js.map +1 -0
- package/dist/mcp/tools/handlers/get-node-info.js +131 -0
- package/dist/mcp/tools/handlers/get-node-info.js.map +1 -0
- package/dist/mcp/tools/handlers/get-operation-schema.js +141 -0
- package/dist/mcp/tools/handlers/get-operation-schema.js.map +1 -0
- package/dist/mcp/tools/handlers/list-nodes.js +126 -0
- package/dist/mcp/tools/handlers/list-nodes.js.map +1 -0
- package/dist/mcp/tools/handlers/list-operations.js +138 -0
- package/dist/mcp/tools/handlers/list-operations.js.map +1 -0
- package/dist/mcp/tools/handlers/suggest-fix.js +120 -0
- package/dist/mcp/tools/handlers/suggest-fix.js.map +1 -0
- package/dist/mcp/tools/handlers/validate-workflow.js +92 -0
- package/dist/mcp/tools/handlers/validate-workflow.js.map +1 -0
- package/dist/mcp/tools/index.js +190 -0
- package/dist/mcp/tools/index.js.map +1 -0
- package/dist/mcp/tools/schemas.js +195 -0
- package/dist/mcp/tools/schemas.js.map +1 -0
- package/dist/mcp/tools/validate.js +95 -0
- package/dist/mcp/tools/validate.js.map +1 -0
- package/dist/mcp/types/mcp.js +7 -0
- package/dist/mcp/types/mcp.js.map +1 -0
- package/dist/mcp/utils/timeout.js +78 -0
- package/dist/mcp/utils/timeout.js.map +1 -0
- package/dist/services/BatchProcessor.js +433 -0
- package/dist/services/BatchProcessor.js.map +1 -0
- package/dist/services/CheckpointManager.js +281 -0
- package/dist/services/CheckpointManager.js.map +1 -0
- package/dist/services/CostCalculator.js +211 -0
- package/dist/services/CostCalculator.js.map +1 -0
- package/dist/services/EmbeddingCache.js +68 -0
- package/dist/services/EmbeddingCache.js.map +1 -0
- package/dist/services/EmbeddingService.js +143 -0
- package/dist/services/EmbeddingService.js.map +1 -0
- package/dist/services/RankingService.js +81 -0
- package/dist/services/RankingService.js.map +1 -0
- package/dist/services/RedisCache.js +376 -0
- package/dist/services/RedisCache.js.map +1 -0
- package/dist/services/RedisCatalogCache.js +680 -0
- package/dist/services/RedisCatalogCache.js.map +1 -0
- package/dist/services/ResumeManager.js +252 -0
- package/dist/services/ResumeManager.js.map +1 -0
- package/dist/services/SearchService.js +282 -0
- package/dist/services/SearchService.js.map +1 -0
- package/dist/services/SemanticCatalogSearch.js +405 -0
- package/dist/services/SemanticCatalogSearch.js.map +1 -0
- package/dist/services/ValidationCache.js +157 -0
- package/dist/services/ValidationCache.js.map +1 -0
- package/dist/services/WorkflowPipelineService.js +1997 -0
- package/dist/services/WorkflowPipelineService.js.map +1 -0
- package/dist/services/catalog/index.js +34 -0
- package/dist/services/catalog/index.js.map +1 -0
- package/dist/services/catalog/interfaces.js +17 -0
- package/dist/services/catalog/interfaces.js.map +1 -0
- package/dist/services/catalog/loaders.js +169 -0
- package/dist/services/catalog/loaders.js.map +1 -0
- package/dist/services/catalog/types.js +138 -0
- package/dist/services/catalog/types.js.map +1 -0
- package/dist/services/documentation-normalization/docUrlUtils.js +88 -0
- package/dist/services/documentation-normalization/docUrlUtils.js.map +1 -0
- package/dist/services/error-quality/ErrorQualityService.js +262 -0
- package/dist/services/error-quality/ErrorQualityService.js.map +1 -0
- package/dist/services/error-quality/analyzers/CredentialAnalyzer.js +260 -0
- package/dist/services/error-quality/analyzers/CredentialAnalyzer.js.map +1 -0
- package/dist/services/error-quality/analyzers/IssuePredictor.js +380 -0
- package/dist/services/error-quality/analyzers/IssuePredictor.js.map +1 -0
- package/dist/services/error-quality/analyzers/MockCoverageAnalyzer.js +267 -0
- package/dist/services/error-quality/analyzers/MockCoverageAnalyzer.js.map +1 -0
- package/dist/services/error-quality/data/ErrorPatternSeeder.js +963 -0
- package/dist/services/error-quality/data/ErrorPatternSeeder.js.map +1 -0
- package/dist/services/error-quality/index.js +25 -0
- package/dist/services/error-quality/index.js.map +1 -0
- package/dist/services/error-quality/reports/ReportGenerator.js +343 -0
- package/dist/services/error-quality/reports/ReportGenerator.js.map +1 -0
- package/dist/services/error-quality/taxonomy/ErrorTaxonomy.js +698 -0
- package/dist/services/error-quality/taxonomy/ErrorTaxonomy.js.map +1 -0
- package/dist/services/error-quality/types.js +11 -0
- package/dist/services/error-quality/types.js.map +1 -0
- package/dist/services/progress/ProgressTracker.js +288 -0
- package/dist/services/progress/ProgressTracker.js.map +1 -0
- package/dist/services/progress/formatters.js +122 -0
- package/dist/services/progress/formatters.js.map +1 -0
- package/dist/services/progress/index.js +36 -0
- package/dist/services/progress/index.js.map +1 -0
- package/dist/services/progress/types.js +7 -0
- package/dist/services/progress/types.js.map +1 -0
- package/dist/services/search/embeddingGenerator.js +112 -0
- package/dist/services/search/embeddingGenerator.js.map +1 -0
- package/dist/types/aiCapabilities.js +7 -0
- package/dist/types/aiCapabilities.js.map +1 -0
- package/dist/types/aiConfigSchema.js +7 -0
- package/dist/types/aiConfigSchema.js.map +1 -0
- package/dist/utils/bannerLogger.js +186 -0
- package/dist/utils/bannerLogger.js.map +1 -0
- package/dist/utils/bannerService.js +23 -0
- package/dist/utils/bannerService.js.map +1 -0
- package/dist/utils/bannerServiceAdapter.js +54 -0
- package/dist/utils/bannerServiceAdapter.js.map +1 -0
- package/dist/utils/batchLogger.js +171 -0
- package/dist/utils/batchLogger.js.map +1 -0
- package/dist/utils/bottomStickyBanner.js +239 -0
- package/dist/utils/bottomStickyBanner.js.map +1 -0
- package/dist/utils/credentialMatcher.js +206 -0
- package/dist/utils/credentialMatcher.js.map +1 -0
- package/dist/utils/credentialNormalizer.js +442 -0
- package/dist/utils/credentialNormalizer.js.map +1 -0
- package/dist/utils/integratedBannerLogger.js +59 -0
- package/dist/utils/integratedBannerLogger.js.map +1 -0
- package/dist/utils/n8nSourceGit.js +195 -0
- package/dist/utils/n8nSourceGit.js.map +1 -0
- package/dist/utils/nodeTypeNormalizer.js +131 -0
- package/dist/utils/nodeTypeNormalizer.js.map +1 -0
- package/dist/utils/openaiClient.js +397 -0
- package/dist/utils/openaiClient.js.map +1 -0
- package/dist/utils/productionLogger.js +16 -0
- package/dist/utils/productionLogger.js.map +1 -0
- package/dist/utils/progressBarBanner.js +132 -0
- package/dist/utils/progressBarBanner.js.map +1 -0
- package/dist/utils/scriptHeartbeat.js +117 -0
- package/dist/utils/scriptHeartbeat.js.map +1 -0
- package/dist/utils/scriptLogger.js +125 -0
- package/dist/utils/scriptLogger.js.map +1 -0
- package/dist/utils/scriptRunner.js +95 -0
- package/dist/utils/scriptRunner.js.map +1 -0
- package/dist/utils/scriptTimeout.js +128 -0
- package/dist/utils/scriptTimeout.js.map +1 -0
- package/dist/utils/scriptWrapper.js +219 -0
- package/dist/utils/scriptWrapper.js.map +1 -0
- package/dist/utils/stickyBanner.js +226 -0
- package/dist/utils/stickyBanner.js.map +1 -0
- package/dist/utils/terminalSpinner.js +97 -0
- package/dist/utils/terminalSpinner.js.map +1 -0
- package/dist/utils/threeLineBanner.js +427 -0
- package/dist/utils/threeLineBanner.js.map +1 -0
- package/dist/utils/validatorCheckpointManager.js +170 -0
- package/dist/utils/validatorCheckpointManager.js.map +1 -0
- package/dist/utils/validatorConnectionManager.js +124 -0
- package/dist/utils/validatorConnectionManager.js.map +1 -0
- package/dist/validation/catalog.js +56 -0
- package/dist/validation/catalog.js.map +1 -0
- package/dist/validation/config/deprecated-nodes.js +234 -0
- package/dist/validation/config/deprecated-nodes.js.map +1 -0
- package/dist/validation/config/l6-severity.js +227 -0
- package/dist/validation/config/l6-severity.js.map +1 -0
- package/dist/validation/config/terminal-nodes.js +132 -0
- package/dist/validation/config/terminal-nodes.js.map +1 -0
- package/dist/validation/config/unreachable-nodes.js +67 -0
- package/dist/validation/config/unreachable-nodes.js.map +1 -0
- package/dist/validation/core.js +47 -0
- package/dist/validation/core.js.map +1 -0
- package/dist/validation/docExtraction.js +12 -0
- package/dist/validation/docExtraction.js.map +1 -0
- package/dist/validation/dryRunMockRunner.js +128 -0
- package/dist/validation/dryRunMockRunner.js.map +1 -0
- package/dist/validation/fixtureEngine.js +61 -0
- package/dist/validation/fixtureEngine.js.map +1 -0
- package/dist/validation/index.js +15 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/k-levels/k2-blockers.js +222 -0
- package/dist/validation/k-levels/k2-blockers.js.map +1 -0
- package/dist/validation/l1-structure.js +296 -0
- package/dist/validation/l1-structure.js.map +1 -0
- package/dist/validation/l2-nodes.js +282 -0
- package/dist/validation/l2-nodes.js.map +1 -0
- package/dist/validation/l3-credentials.js +322 -0
- package/dist/validation/l3-credentials.js.map +1 -0
- package/dist/validation/l4-connections.js +698 -0
- package/dist/validation/l4-connections.js.map +1 -0
- package/dist/validation/l5-parameters.js +803 -0
- package/dist/validation/l5-parameters.js.map +1 -0
- package/dist/validation/l6-checks/ai-tool-variants.js +407 -0
- package/dist/validation/l6-checks/ai-tool-variants.js.map +1 -0
- package/dist/validation/l6-checks/catalog-checks.js +260 -0
- package/dist/validation/l6-checks/catalog-checks.js.map +1 -0
- package/dist/validation/l6-checks/data-contracts.js +197 -0
- package/dist/validation/l6-checks/data-contracts.js.map +1 -0
- package/dist/validation/l6-checks/deprecation.js +133 -0
- package/dist/validation/l6-checks/deprecation.js.map +1 -0
- package/dist/validation/l6-checks/error-handling.js +193 -0
- package/dist/validation/l6-checks/error-handling.js.map +1 -0
- package/dist/validation/l6-checks/expression-syntax.js +387 -0
- package/dist/validation/l6-checks/expression-syntax.js.map +1 -0
- package/dist/validation/l6-checks/flow-integrity.js +504 -0
- package/dist/validation/l6-checks/flow-integrity.js.map +1 -0
- package/dist/validation/l6-checks/index.js +106 -0
- package/dist/validation/l6-checks/index.js.map +1 -0
- package/dist/validation/l6-checks/loops.js +370 -0
- package/dist/validation/l6-checks/loops.js.map +1 -0
- package/dist/validation/l6-checks/performance.js +182 -0
- package/dist/validation/l6-checks/performance.js.map +1 -0
- package/dist/validation/l6-checks/security.js +273 -0
- package/dist/validation/l6-checks/security.js.map +1 -0
- package/dist/validation/l6-patterns.js +472 -0
- package/dist/validation/l6-patterns.js.map +1 -0
- package/dist/validation/mockLevelResolver.js +95 -0
- package/dist/validation/mockLevelResolver.js.map +1 -0
- package/dist/validation/n8nApiClient.js +21 -0
- package/dist/validation/n8nApiClient.js.map +1 -0
- package/dist/validation/n8nCli.js +87 -0
- package/dist/validation/n8nCli.js.map +1 -0
- package/dist/validation/types.js +8 -0
- package/dist/validation/types.js.map +1 -0
- package/dist/validation/usageStats.js +82 -0
- package/dist/validation/usageStats.js.map +1 -0
- package/package.json +274 -0
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semantic Catalog Search Service
|
|
3
|
+
*
|
|
4
|
+
* Provides semantic similarity search across the bluelime catalog using
|
|
5
|
+
* pre-computed embeddings (77,958 vectors) and pgvector for similarity queries.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Search nodes, operations, parameters, and credentials semantically
|
|
9
|
+
* - Redis caching for search results (1h TTL)
|
|
10
|
+
* - Graceful fallback when Redis unavailable
|
|
11
|
+
* - Uses existing bluelime.search_*_multi() database functions
|
|
12
|
+
*
|
|
13
|
+
* @module services/SemanticCatalogSearch
|
|
14
|
+
*/
|
|
15
|
+
import OpenAI from 'openai';
|
|
16
|
+
import Redis from 'ioredis';
|
|
17
|
+
import { logger } from '@tsvika58/shared-utilities/logging';
|
|
18
|
+
import { validatorQuery } from '../db/validatorPostgresClient.js';
|
|
19
|
+
import { generateQueryEmbedding, hashQuery, normalizeQueryText, } from './search/embeddingGenerator.js';
|
|
20
|
+
/** Default TTL for search result cache (1 hour) */
|
|
21
|
+
const DEFAULT_CACHE_TTL_SECONDS = 3600;
|
|
22
|
+
/** Redis key prefix for semantic search results */
|
|
23
|
+
const CACHE_PREFIX = 'semantic:';
|
|
24
|
+
/**
|
|
25
|
+
* SemanticCatalogSearch provides semantic similarity search across the
|
|
26
|
+
* bluelime catalog using pre-computed embeddings.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* const search = new SemanticCatalogSearch();
|
|
31
|
+
* await search.initialize();
|
|
32
|
+
*
|
|
33
|
+
* // Find nodes similar to "send email"
|
|
34
|
+
* const nodes = await search.searchNodes('send email', 5);
|
|
35
|
+
* console.log(nodes[0].nodeType); // e.g., 'n8n-nodes-base.gmail'
|
|
36
|
+
*
|
|
37
|
+
* // Get suggestions for typo correction
|
|
38
|
+
* const suggestions = await search.searchNodes('httpRequst');
|
|
39
|
+
* console.log(suggestions[0].nodeType); // 'n8n-nodes-base.httpRequest'
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export class SemanticCatalogSearch {
|
|
43
|
+
openai;
|
|
44
|
+
redis = null;
|
|
45
|
+
dbQuery;
|
|
46
|
+
cacheTtl;
|
|
47
|
+
minSimilarity;
|
|
48
|
+
isRedisConnected = false;
|
|
49
|
+
stats = {
|
|
50
|
+
cacheHits: 0,
|
|
51
|
+
cacheMisses: 0,
|
|
52
|
+
totalSearches: 0,
|
|
53
|
+
totalLatencyMs: 0,
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Create a new SemanticCatalogSearch instance.
|
|
57
|
+
*
|
|
58
|
+
* @param config - Configuration options
|
|
59
|
+
* @param deps - Optional dependencies for testing
|
|
60
|
+
*/
|
|
61
|
+
constructor(config, deps) {
|
|
62
|
+
// Use injected dependencies or create defaults
|
|
63
|
+
if (deps) {
|
|
64
|
+
this.openai = deps.openai;
|
|
65
|
+
this.dbQuery = deps.dbQuery;
|
|
66
|
+
this.redis = deps.redis ?? null;
|
|
67
|
+
this.isRedisConnected = deps.redis !== null && deps.redis !== undefined;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
const apiKey = config?.openaiApiKey || process.env.OPENAI_API_KEY;
|
|
71
|
+
if (!apiKey) {
|
|
72
|
+
throw new Error('OpenAI API key required: set OPENAI_API_KEY or pass openaiApiKey in config');
|
|
73
|
+
}
|
|
74
|
+
this.openai = new OpenAI({ apiKey });
|
|
75
|
+
this.dbQuery = validatorQuery;
|
|
76
|
+
}
|
|
77
|
+
this.cacheTtl = config?.cacheTtlSeconds ?? DEFAULT_CACHE_TTL_SECONDS;
|
|
78
|
+
this.minSimilarity = config?.minSimilarity ?? 0.5;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Initialize the service and connect to Redis.
|
|
82
|
+
* Must be called before using search methods when not using injected dependencies.
|
|
83
|
+
*/
|
|
84
|
+
async initialize() {
|
|
85
|
+
if (this.redis) {
|
|
86
|
+
return; // Already initialized via deps
|
|
87
|
+
}
|
|
88
|
+
const redisUrl = process.env.REDIS_URL || 'redis://localhost:6379';
|
|
89
|
+
try {
|
|
90
|
+
this.redis = new Redis(redisUrl, {
|
|
91
|
+
maxRetriesPerRequest: 3,
|
|
92
|
+
connectTimeout: 5000,
|
|
93
|
+
retryStrategy: (times) => {
|
|
94
|
+
if (times > 3)
|
|
95
|
+
return null;
|
|
96
|
+
return Math.min(times * 100, 2000);
|
|
97
|
+
},
|
|
98
|
+
enableReadyCheck: true,
|
|
99
|
+
});
|
|
100
|
+
await new Promise((resolve, reject) => {
|
|
101
|
+
const timeout = setTimeout(() => {
|
|
102
|
+
reject(new Error('Redis connection timeout'));
|
|
103
|
+
}, 5000);
|
|
104
|
+
this.redis.on('ready', () => {
|
|
105
|
+
clearTimeout(timeout);
|
|
106
|
+
this.isRedisConnected = true;
|
|
107
|
+
resolve();
|
|
108
|
+
});
|
|
109
|
+
this.redis.on('error', (err) => {
|
|
110
|
+
clearTimeout(timeout);
|
|
111
|
+
reject(err);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
await this.redis.ping();
|
|
115
|
+
this.isRedisConnected = true;
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
if (this.redis) {
|
|
119
|
+
await this.redis.quit().catch((err) => {
|
|
120
|
+
logger.debug('Redis quit failed during connection cleanup', { error: err.message });
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
this.redis = null;
|
|
124
|
+
this.isRedisConnected = false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Search for nodes semantically similar to the query.
|
|
129
|
+
*
|
|
130
|
+
* @param query - Search query (e.g., "send email", "make http request")
|
|
131
|
+
* @param limit - Maximum results to return (default: 5)
|
|
132
|
+
* @returns Array of matching nodes with similarity scores
|
|
133
|
+
*/
|
|
134
|
+
async searchNodes(query, limit = 5) {
|
|
135
|
+
const cacheKey = this.getCacheKey('nodes', query);
|
|
136
|
+
const cached = await this.getFromCache(cacheKey);
|
|
137
|
+
if (cached) {
|
|
138
|
+
return cached.slice(0, limit);
|
|
139
|
+
}
|
|
140
|
+
const startTime = performance.now();
|
|
141
|
+
const embedding = await this.getEmbedding(query);
|
|
142
|
+
const result = await this.dbQuery(`SELECT node_type, name, category, is_trigger,
|
|
143
|
+
1 - (embedding <=> $1::vector) as similarity
|
|
144
|
+
FROM bluelime.nodes
|
|
145
|
+
WHERE embedding IS NOT NULL
|
|
146
|
+
ORDER BY embedding <=> $1::vector
|
|
147
|
+
LIMIT $2`, [`[${embedding.join(',')}]`, limit * 2]);
|
|
148
|
+
const matches = result.rows
|
|
149
|
+
.filter((row) => row.similarity >= this.minSimilarity)
|
|
150
|
+
.map((row) => ({
|
|
151
|
+
nodeType: row.node_type,
|
|
152
|
+
name: row.name,
|
|
153
|
+
category: row.category,
|
|
154
|
+
isTrigger: row.is_trigger,
|
|
155
|
+
similarity: row.similarity,
|
|
156
|
+
}));
|
|
157
|
+
await this.setCache(cacheKey, matches);
|
|
158
|
+
this.recordSearchLatency(startTime);
|
|
159
|
+
return matches.slice(0, limit);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Search for operations semantically similar to the query.
|
|
163
|
+
*
|
|
164
|
+
* @param query - Search query (e.g., "send message", "create record")
|
|
165
|
+
* @param nodeType - Optional node type to filter by
|
|
166
|
+
* @param limit - Maximum results to return (default: 5)
|
|
167
|
+
* @returns Array of matching operations with similarity scores
|
|
168
|
+
*/
|
|
169
|
+
async searchOperations(query, nodeType, limit = 5) {
|
|
170
|
+
const cacheKey = this.getCacheKey('operations', query, nodeType);
|
|
171
|
+
const cached = await this.getFromCache(cacheKey);
|
|
172
|
+
if (cached) {
|
|
173
|
+
return cached.slice(0, limit);
|
|
174
|
+
}
|
|
175
|
+
const startTime = performance.now();
|
|
176
|
+
const embedding = await this.getEmbedding(query);
|
|
177
|
+
let sql = `
|
|
178
|
+
SELECT o.id, n.node_type, o.display_name as operation_name,
|
|
179
|
+
o.operation as operation_value, o.description,
|
|
180
|
+
1 - (o.embedding <=> $1::vector) as similarity
|
|
181
|
+
FROM bluelime.operations o
|
|
182
|
+
JOIN bluelime.nodes n ON o.node_id = n.id
|
|
183
|
+
WHERE o.embedding IS NOT NULL
|
|
184
|
+
`;
|
|
185
|
+
const params = [`[${embedding.join(',')}]`];
|
|
186
|
+
if (nodeType) {
|
|
187
|
+
sql += ` AND LOWER(n.node_type) = LOWER($2)`;
|
|
188
|
+
params.push(nodeType);
|
|
189
|
+
}
|
|
190
|
+
sql += ` ORDER BY o.embedding <=> $1::vector LIMIT $${params.length + 1}`;
|
|
191
|
+
params.push(limit * 2);
|
|
192
|
+
const result = await this.dbQuery(sql, params);
|
|
193
|
+
const matches = result.rows
|
|
194
|
+
.filter((row) => row.similarity >= this.minSimilarity)
|
|
195
|
+
.map((row) => ({
|
|
196
|
+
id: row.id,
|
|
197
|
+
nodeType: row.node_type,
|
|
198
|
+
operationName: row.operation_name,
|
|
199
|
+
operationValue: row.operation_value,
|
|
200
|
+
description: row.description,
|
|
201
|
+
similarity: row.similarity,
|
|
202
|
+
}));
|
|
203
|
+
await this.setCache(cacheKey, matches);
|
|
204
|
+
this.recordSearchLatency(startTime);
|
|
205
|
+
return matches.slice(0, limit);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Search for parameters semantically similar to the query.
|
|
209
|
+
*
|
|
210
|
+
* @param query - Search query (e.g., "recipient email", "message body")
|
|
211
|
+
* @param operationId - Optional operation ID to filter by
|
|
212
|
+
* @param limit - Maximum results to return (default: 5)
|
|
213
|
+
* @returns Array of matching parameters with similarity scores
|
|
214
|
+
*/
|
|
215
|
+
async searchParameters(query, operationId, limit = 5) {
|
|
216
|
+
const cacheKey = this.getCacheKey('parameters', query, operationId?.toString());
|
|
217
|
+
const cached = await this.getFromCache(cacheKey);
|
|
218
|
+
if (cached) {
|
|
219
|
+
return cached.slice(0, limit);
|
|
220
|
+
}
|
|
221
|
+
const startTime = performance.now();
|
|
222
|
+
const embedding = await this.getEmbedding(query);
|
|
223
|
+
let sql = `
|
|
224
|
+
SELECT id, operation_id, parameter_name, parameter_type, is_required,
|
|
225
|
+
1 - (embedding <=> $1::vector) as similarity
|
|
226
|
+
FROM bluelime.parameters
|
|
227
|
+
WHERE embedding IS NOT NULL
|
|
228
|
+
`;
|
|
229
|
+
const params = [`[${embedding.join(',')}]`];
|
|
230
|
+
if (operationId !== undefined) {
|
|
231
|
+
sql += ` AND operation_id = $2`;
|
|
232
|
+
params.push(operationId);
|
|
233
|
+
}
|
|
234
|
+
sql += ` ORDER BY embedding <=> $1::vector LIMIT $${params.length + 1}`;
|
|
235
|
+
params.push(limit * 2);
|
|
236
|
+
const result = await this.dbQuery(sql, params);
|
|
237
|
+
const matches = result.rows
|
|
238
|
+
.filter((row) => row.similarity >= this.minSimilarity)
|
|
239
|
+
.map((row) => ({
|
|
240
|
+
id: row.id,
|
|
241
|
+
operationId: row.operation_id,
|
|
242
|
+
parameterName: row.parameter_name,
|
|
243
|
+
parameterType: row.parameter_type,
|
|
244
|
+
isRequired: row.is_required,
|
|
245
|
+
similarity: row.similarity,
|
|
246
|
+
}));
|
|
247
|
+
await this.setCache(cacheKey, matches);
|
|
248
|
+
this.recordSearchLatency(startTime);
|
|
249
|
+
return matches.slice(0, limit);
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Search for credentials semantically similar to the query.
|
|
253
|
+
*
|
|
254
|
+
* @param query - Search query (e.g., "google oauth", "api key")
|
|
255
|
+
* @param limit - Maximum results to return (default: 5)
|
|
256
|
+
* @returns Array of matching credentials with similarity scores
|
|
257
|
+
*/
|
|
258
|
+
async searchCredentials(query, limit = 5) {
|
|
259
|
+
const cacheKey = this.getCacheKey('credentials', query);
|
|
260
|
+
const cached = await this.getFromCache(cacheKey);
|
|
261
|
+
if (cached) {
|
|
262
|
+
return cached.slice(0, limit);
|
|
263
|
+
}
|
|
264
|
+
const startTime = performance.now();
|
|
265
|
+
const embedding = await this.getEmbedding(query);
|
|
266
|
+
const result = await this.dbQuery(`SELECT credential_type, name, auth_type, is_oauth,
|
|
267
|
+
1 - (embedding <=> $1::vector) as similarity
|
|
268
|
+
FROM bluelime.credentials
|
|
269
|
+
WHERE embedding IS NOT NULL
|
|
270
|
+
ORDER BY embedding <=> $1::vector
|
|
271
|
+
LIMIT $2`, [`[${embedding.join(',')}]`, limit * 2]);
|
|
272
|
+
const matches = result.rows
|
|
273
|
+
.filter((row) => row.similarity >= this.minSimilarity)
|
|
274
|
+
.map((row) => ({
|
|
275
|
+
credentialType: row.credential_type,
|
|
276
|
+
name: row.name,
|
|
277
|
+
authType: row.auth_type,
|
|
278
|
+
isOauth: row.is_oauth,
|
|
279
|
+
similarity: row.similarity,
|
|
280
|
+
}));
|
|
281
|
+
await this.setCache(cacheKey, matches);
|
|
282
|
+
this.recordSearchLatency(startTime);
|
|
283
|
+
return matches.slice(0, limit);
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Get search statistics.
|
|
287
|
+
*/
|
|
288
|
+
getStats() {
|
|
289
|
+
return {
|
|
290
|
+
cacheHits: this.stats.cacheHits,
|
|
291
|
+
cacheMisses: this.stats.cacheMisses,
|
|
292
|
+
redisConnected: this.isRedisConnected,
|
|
293
|
+
avgSearchLatencyMs: this.stats.totalSearches > 0
|
|
294
|
+
? Math.round(this.stats.totalLatencyMs / this.stats.totalSearches)
|
|
295
|
+
: 0,
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Clear all search caches.
|
|
300
|
+
*/
|
|
301
|
+
async clearCache() {
|
|
302
|
+
if (!this.redis || !this.isRedisConnected) {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
try {
|
|
306
|
+
const keys = await this.redis.keys(`${CACHE_PREFIX}*`);
|
|
307
|
+
if (keys.length > 0) {
|
|
308
|
+
await this.redis.del(...keys);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
catch {
|
|
312
|
+
// Ignore cache clear errors
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Dispose of resources (close Redis connection).
|
|
317
|
+
*/
|
|
318
|
+
async dispose() {
|
|
319
|
+
if (this.redis) {
|
|
320
|
+
await this.redis.quit().catch((err) => {
|
|
321
|
+
logger.debug('Redis quit failed during dispose', { error: err.message });
|
|
322
|
+
});
|
|
323
|
+
this.redis = null;
|
|
324
|
+
this.isRedisConnected = false;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
// ============================================================
|
|
328
|
+
// Private Methods
|
|
329
|
+
// ============================================================
|
|
330
|
+
async getEmbedding(query) {
|
|
331
|
+
const result = await generateQueryEmbedding(query, this.openai);
|
|
332
|
+
return result.embedding;
|
|
333
|
+
}
|
|
334
|
+
getCacheKey(type, query, filter) {
|
|
335
|
+
const normalizedQuery = normalizeQueryText(query);
|
|
336
|
+
const queryHash = hashQuery(normalizedQuery);
|
|
337
|
+
return filter
|
|
338
|
+
? `${CACHE_PREFIX}${type}:${filter}:${queryHash}`
|
|
339
|
+
: `${CACHE_PREFIX}${type}:${queryHash}`;
|
|
340
|
+
}
|
|
341
|
+
async getFromCache(key) {
|
|
342
|
+
if (!this.redis || !this.isRedisConnected) {
|
|
343
|
+
this.stats.cacheMisses++;
|
|
344
|
+
return null;
|
|
345
|
+
}
|
|
346
|
+
try {
|
|
347
|
+
const cached = await this.redis.get(key);
|
|
348
|
+
if (cached) {
|
|
349
|
+
this.stats.cacheHits++;
|
|
350
|
+
return JSON.parse(cached);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
catch {
|
|
354
|
+
// Fall through to miss
|
|
355
|
+
}
|
|
356
|
+
this.stats.cacheMisses++;
|
|
357
|
+
return null;
|
|
358
|
+
}
|
|
359
|
+
async setCache(key, value) {
|
|
360
|
+
if (!this.redis || !this.isRedisConnected) {
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
try {
|
|
364
|
+
await this.redis.setex(key, this.cacheTtl, JSON.stringify(value));
|
|
365
|
+
}
|
|
366
|
+
catch {
|
|
367
|
+
// Ignore cache set errors
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
recordSearchLatency(startTime) {
|
|
371
|
+
this.stats.totalSearches++;
|
|
372
|
+
this.stats.totalLatencyMs += performance.now() - startTime;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
/** Singleton instance for shared use */
|
|
376
|
+
let instance = null;
|
|
377
|
+
/**
|
|
378
|
+
* Get or create the singleton SemanticCatalogSearch instance.
|
|
379
|
+
*/
|
|
380
|
+
export function getSemanticCatalogSearch(config) {
|
|
381
|
+
if (!instance) {
|
|
382
|
+
instance = new SemanticCatalogSearch(config);
|
|
383
|
+
}
|
|
384
|
+
return instance;
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Initialize and return the singleton instance.
|
|
388
|
+
*/
|
|
389
|
+
export async function initSemanticCatalogSearch(config) {
|
|
390
|
+
const search = getSemanticCatalogSearch(config);
|
|
391
|
+
await search.initialize();
|
|
392
|
+
return search;
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Reset the singleton instance (for testing).
|
|
396
|
+
*/
|
|
397
|
+
export function resetSemanticCatalogSearch() {
|
|
398
|
+
if (instance) {
|
|
399
|
+
instance.dispose().catch((err) => {
|
|
400
|
+
logger.debug('Dispose failed during reset', { error: err.message });
|
|
401
|
+
});
|
|
402
|
+
instance = null;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
//# sourceMappingURL=SemanticCatalogSearch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SemanticCatalogSearch.js","sourceRoot":"","sources":["../../src/services/SemanticCatalogSearch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation Cache Service
|
|
3
|
+
* ------------------------
|
|
4
|
+
*
|
|
5
|
+
* Caches validation results to avoid redundant database queries.
|
|
6
|
+
* Uses Redis when available, falls back to in-memory cache.
|
|
7
|
+
*
|
|
8
|
+
* RAG-2.2.7: Unified Validation Service (Database + Redis)
|
|
9
|
+
* Created: January 1, 2026
|
|
10
|
+
* Based on: EmbeddingCache.ts pattern
|
|
11
|
+
*/
|
|
12
|
+
import NodeCache from 'node-cache';
|
|
13
|
+
import { logger } from '@tsvika58/shared-utilities/logging';
|
|
14
|
+
import { RedisCache } from './RedisCache.js';
|
|
15
|
+
/**
|
|
16
|
+
* In-memory cache fallback
|
|
17
|
+
*/
|
|
18
|
+
class MemoryValidationCache {
|
|
19
|
+
cache;
|
|
20
|
+
constructor() {
|
|
21
|
+
const ttl = process.env.VALIDATION_CACHE_TTL
|
|
22
|
+
? Number(process.env.VALIDATION_CACHE_TTL)
|
|
23
|
+
: 3600; // Default: 1 hour
|
|
24
|
+
const maxKeys = process.env.VALIDATION_CACHE_MAX_SIZE
|
|
25
|
+
? Number(process.env.VALIDATION_CACHE_MAX_SIZE)
|
|
26
|
+
: 10000; // Default: 10,000 entries
|
|
27
|
+
this.cache = new NodeCache({
|
|
28
|
+
stdTTL: ttl,
|
|
29
|
+
checkperiod: 600, // Check for expired keys every 10 minutes
|
|
30
|
+
useClones: true, // Clone values to prevent mutations
|
|
31
|
+
maxKeys: maxKeys,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
async get(key) {
|
|
35
|
+
const value = this.cache.get(key);
|
|
36
|
+
return value !== undefined ? value : null;
|
|
37
|
+
}
|
|
38
|
+
async set(key, value, ttlSeconds) {
|
|
39
|
+
if (ttlSeconds) {
|
|
40
|
+
this.cache.set(key, value, ttlSeconds);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
this.cache.set(key, value);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
async delete(key) {
|
|
47
|
+
this.cache.del(key);
|
|
48
|
+
}
|
|
49
|
+
async clear() {
|
|
50
|
+
this.cache.flushAll();
|
|
51
|
+
}
|
|
52
|
+
async has(key) {
|
|
53
|
+
return this.cache.has(key);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Validation Cache Service
|
|
58
|
+
*
|
|
59
|
+
* Uses Redis if available, otherwise falls back to in-memory cache.
|
|
60
|
+
*/
|
|
61
|
+
class ValidationCacheService {
|
|
62
|
+
redisCache = null;
|
|
63
|
+
memoryCache;
|
|
64
|
+
useRedis;
|
|
65
|
+
constructor() {
|
|
66
|
+
this.memoryCache = new MemoryValidationCache();
|
|
67
|
+
// Try to use Redis if available
|
|
68
|
+
try {
|
|
69
|
+
this.redisCache = new RedisCache();
|
|
70
|
+
this.useRedis = true;
|
|
71
|
+
logger.debug('ValidationCache: Using Redis cache');
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
this.useRedis = false;
|
|
75
|
+
logger.debug('ValidationCache: Redis not available, using in-memory cache');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async get(key) {
|
|
79
|
+
if (this.useRedis && this.redisCache) {
|
|
80
|
+
try {
|
|
81
|
+
const value = await this.redisCache.get(key);
|
|
82
|
+
return value;
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
logger.warn('Redis cache get failed, falling back to memory', { key, error });
|
|
86
|
+
return await this.memoryCache.get(key);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return await this.memoryCache.get(key);
|
|
90
|
+
}
|
|
91
|
+
async set(key, value, ttlSeconds) {
|
|
92
|
+
if (this.useRedis && this.redisCache) {
|
|
93
|
+
try {
|
|
94
|
+
await this.redisCache.setGeneric(key, value, ttlSeconds);
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
logger.warn('Redis cache set failed, falling back to memory', { key, error });
|
|
98
|
+
await this.memoryCache.set(key, value, ttlSeconds);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
await this.memoryCache.set(key, value, ttlSeconds);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
async delete(key) {
|
|
106
|
+
if (this.useRedis && this.redisCache) {
|
|
107
|
+
try {
|
|
108
|
+
await this.redisCache.delete(key);
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
logger.warn('Redis cache delete failed, falling back to memory', { key, error });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
await this.memoryCache.delete(key);
|
|
115
|
+
}
|
|
116
|
+
async clear() {
|
|
117
|
+
if (this.useRedis && this.redisCache) {
|
|
118
|
+
try {
|
|
119
|
+
await this.redisCache.clear();
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
logger.warn('Redis cache clear failed', { error });
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
await this.memoryCache.clear();
|
|
126
|
+
}
|
|
127
|
+
// Credential mock specific methods
|
|
128
|
+
async getMock(type) {
|
|
129
|
+
return await this.get(`credential_mock:${type}`);
|
|
130
|
+
}
|
|
131
|
+
async setMock(type, mock) {
|
|
132
|
+
await this.set(`credential_mock:${type}`, mock);
|
|
133
|
+
}
|
|
134
|
+
async getAllMocks() {
|
|
135
|
+
return await this.get('credential_mocks:all');
|
|
136
|
+
}
|
|
137
|
+
async setAllMocks(mocks) {
|
|
138
|
+
await this.set('credential_mocks:all', mocks);
|
|
139
|
+
}
|
|
140
|
+
async has(key) {
|
|
141
|
+
if (this.useRedis && this.redisCache) {
|
|
142
|
+
try {
|
|
143
|
+
return await this.redisCache.has(key);
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
logger.warn('Redis cache has failed, falling back to memory', { key, error });
|
|
147
|
+
return await this.memoryCache.has(key);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return await this.memoryCache.has(key);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Singleton instance of validation cache
|
|
155
|
+
*/
|
|
156
|
+
export const validationCache = new ValidationCacheService();
|
|
157
|
+
//# sourceMappingURL=ValidationCache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ValidationCache.js","sourceRoot":"","sources":["../../src/services/ValidationCache.ts"],"names":[],"mappings":"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"}
|