@aprovan/patchwork 0.1.0-dev.6bd527d → 0.1.0-dev.c680591
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/.turbo/turbo-build.log +4 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +4 -4
- package/src/services/index.ts +2 -2
- package/src/services/proxy.ts +5 -5
package/.turbo/turbo-build.log
CHANGED
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
[34mCLI[39m Target: node20
|
|
10
10
|
[34mCLI[39m Cleaning output folder
|
|
11
11
|
[34mESM[39m Build start
|
|
12
|
-
[32mESM[39m [1mdist/index.js [22m[32m3.
|
|
12
|
+
[32mESM[39m [1mdist/index.js [22m[32m3.15 KB[39m
|
|
13
13
|
[32mESM[39m [1mdist/index.js.map [22m[32m10.96 KB[39m
|
|
14
|
-
[32mESM[39m ⚡️ Build success in
|
|
14
|
+
[32mESM[39m ⚡️ Build success in 30ms
|
|
15
15
|
[34mDTS[39m Build start
|
|
16
|
-
[32mDTS[39m ⚡️ Build success in
|
|
17
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[32m4.
|
|
16
|
+
[32mDTS[39m ⚡️ Build success in 2377ms
|
|
17
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m4.93 KB[39m
|
package/dist/index.d.ts
CHANGED
|
@@ -149,7 +149,7 @@ declare function setServiceBackend(backend: ServiceBackend): void;
|
|
|
149
149
|
/**
|
|
150
150
|
* Create a service proxy that wraps the backend with caching
|
|
151
151
|
*/
|
|
152
|
-
declare function
|
|
152
|
+
declare function createProxy(): ServiceBackend;
|
|
153
153
|
/**
|
|
154
154
|
* Call a service procedure
|
|
155
155
|
*
|
|
@@ -187,4 +187,4 @@ interface BatchCall {
|
|
|
187
187
|
}
|
|
188
188
|
declare function batchCall(calls: BatchCall[]): Promise<ServiceResult[]>;
|
|
189
189
|
|
|
190
|
-
export { type AggregatedContext, type CacheConfig, type ComposedLayout, type CompositionRules, type ContextManagerOptions, type ContextProvider, DEFAULT_COMPOSITION_RULES, type GitContext, type ProjectContext, type SelectionOptions, type ServiceBackend, type ServiceResult, type ShellContext, type UsagePattern, type UsageRecord, type Viewport, type WidgetSuggestion, batchCall, callProcedure, configureCacheTtl,
|
|
190
|
+
export { type AggregatedContext, type CacheConfig, type ComposedLayout, type CompositionRules, type ContextManagerOptions, type ContextProvider, DEFAULT_COMPOSITION_RULES, type GitContext, type ProjectContext, type SelectionOptions, type ServiceBackend, type ServiceResult, type ShellContext, type UsagePattern, type UsageRecord, type Viewport, type WidgetSuggestion, batchCall, callProcedure, configureCacheTtl, createProxy, getCacheStats, invalidateCache, setServiceBackend };
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var MAX_CACHE_SIZE = 1e3;
|
|
|
14
14
|
function setServiceBackend(backend) {
|
|
15
15
|
currentBackend = backend;
|
|
16
16
|
}
|
|
17
|
-
function
|
|
17
|
+
function createProxy() {
|
|
18
18
|
return {
|
|
19
19
|
call: (service, procedure, args) => callProcedure(service, procedure, args).then((r) => {
|
|
20
20
|
if (!r.success) throw new Error(r.error || "Service call failed");
|
|
@@ -111,7 +111,7 @@ export {
|
|
|
111
111
|
batchCall,
|
|
112
112
|
callProcedure,
|
|
113
113
|
configureCacheTtl,
|
|
114
|
-
|
|
114
|
+
createProxy,
|
|
115
115
|
getCacheStats,
|
|
116
116
|
invalidateCache,
|
|
117
117
|
setServiceBackend
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/services/proxy.ts"],"sourcesContent":["// Patchwork Types - Context providers and selection engine types\n\n// ============================================================================\n// Context Provider Types\n// ============================================================================\n\nexport interface ContextProvider {\n name: string;\n schema?: Record<string, unknown>;\n getContext(): Promise<Record<string, unknown>>;\n subscribe?(callback: (context: Record<string, unknown>) => void): () => void;\n}\n\nexport interface AggregatedContext {\n timestamp: string;\n providers: {\n [providerName: string]: Record<string, unknown>;\n };\n}\n\nexport interface ContextManagerOptions {\n debounce_ms?: number;\n}\n\n// ============================================================================\n// Common Context Shapes\n// ============================================================================\n\nexport interface ShellContext {\n cwd: string;\n recent_commands?: string[];\n shell?: string;\n}\n\nexport interface GitContext {\n is_repo: boolean;\n branch?: string;\n remote_url?: string;\n uncommitted_changes?: number;\n staged_files?: number;\n}\n\nexport interface ProjectContext {\n type?: string;\n package_manager?: string;\n scripts?: string[];\n}\n\n// ============================================================================\n// Selection Engine Types\n// ============================================================================\n\nexport interface Viewport {\n width: number;\n height: number;\n}\n\nexport interface SelectionOptions {\n limit?: number;\n strategy?: 'llm' | 'rules';\n minConfidence?: number;\n}\n\nexport interface WidgetSuggestion {\n name: string;\n confidence: number;\n position: 'primary' | 'secondary' | 'ambient';\n reason: string;\n suggested_size: {\n width: number;\n height: number;\n };\n}\n\nexport interface CompositionRules {\n max_primary: number;\n max_secondary: number;\n max_ambient: number;\n ambient_stacking: boolean;\n}\n\nexport const DEFAULT_COMPOSITION_RULES: CompositionRules = {\n max_primary: 1,\n max_secondary: 3,\n max_ambient: 5,\n ambient_stacking: true,\n};\n\nexport interface ComposedLayout {\n widgets: Array<{\n name: string;\n position: 'primary' | 'secondary' | 'ambient';\n bounds: { x: number; y: number; width: number; height: number };\n }>;\n remaining_space: { width: number; height: number };\n}\n\n// ============================================================================\n// Usage Tracking Types\n// ============================================================================\n\nexport interface UsageRecord {\n widget_name: string;\n context_hash: string;\n was_suggested: boolean;\n viewport: Viewport;\n timestamp: string;\n}\n\nexport interface UsagePattern {\n context_hash: string;\n selected_widget: string;\n was_suggested: boolean;\n viewport_size: Viewport;\n timestamp: string;\n}\n","// Service Proxy - Caching layer for service calls\n//\n// Provides a backend-agnostic service proxy with caching.\n// The actual backend (UTCP, MCP, HTTP, etc.) is set via setServiceBackend().\n\nimport type { ServiceResult, CacheEntry, CacheConfig } from './types';\n\n/**\n * Service backend interface - abstracts the actual service call mechanism\n *\n * Implementations can use UTCP, MCP, HTTP, or any other protocol.\n */\nexport interface ServiceBackend {\n /**\n * Call a service procedure\n * @param service - Service namespace (e.g., \"git\", \"github\")\n * @param procedure - Procedure name (e.g., \"branch\", \"repos.list\")\n * @param args - Arguments to pass\n */\n call(service: string, procedure: string, args: unknown[]): Promise<unknown>;\n}\n\n// Current backend (must be set before use)\nlet currentBackend: ServiceBackend | null = null;\n\n// Cache storage\nconst cache = new Map<string, CacheEntry>();\nconst cacheConfig = new Map<string, CacheConfig>();\nconst MAX_CACHE_SIZE = 1000;\n\n/**\n * Set the service backend\n *\n * This must be called before making any service calls.\n * The backend handles the actual communication with services.\n *\n * @example\n * ```typescript\n * // Using with UTCP\n * setServiceBackend({\n * call: (service, procedure, args) =>\n * utcpClient.callTool(`${service}.${procedure}`, args)\n * });\n *\n * // Using with HTTP proxy\n * setServiceBackend({\n * call: async (service, procedure, args) => {\n * const res = await fetch(`/api/proxy/${service}/${procedure}`, {\n * method: 'POST',\n * body: JSON.stringify({ args })\n * });\n * return res.json();\n * }\n * });\n * ```\n */\nexport function setServiceBackend(backend: ServiceBackend): void {\n currentBackend = backend;\n}\n\n/**\n * Create a service proxy that wraps the backend with caching\n */\nexport function createServiceProxy(): ServiceBackend {\n return {\n call: (service, procedure, args) =>\n callProcedure(service, procedure, args).then((r) => {\n if (!r.success) throw new Error(r.error || 'Service call failed');\n return r.data;\n }),\n };\n}\n\nfunction getCacheKey(\n service: string,\n procedure: string,\n args: unknown[],\n): string {\n return `${service}:${procedure}:${JSON.stringify(args)}`;\n}\n\nfunction evictOldestCache(): void {\n if (cache.size < MAX_CACHE_SIZE) return;\n const oldest = Array.from(cache.entries())\n .sort(([, a], [, b]) => a.expiresAt - b.expiresAt)\n .slice(0, Math.floor(MAX_CACHE_SIZE * 0.2));\n for (const [key] of oldest) cache.delete(key);\n}\n\nfunction getFromCache(key: string): ServiceResult | null {\n const entry = cache.get(key);\n if (!entry) return null;\n if (Date.now() > entry.expiresAt) {\n cache.delete(key);\n return null;\n }\n return { ...entry.result, cached: true };\n}\n\nfunction setCache(key: string, result: ServiceResult, ttl: number): void {\n evictOldestCache();\n cache.set(key, { result, expiresAt: Date.now() + ttl * 1000 });\n}\n\n/**\n * Call a service procedure\n *\n * @param service - Service namespace (e.g., \"git\", \"github\")\n * @param procedure - Procedure name (e.g., \"branch\", \"repos.get\")\n * @param args - Arguments to pass\n * @param options - Call options\n */\nexport async function callProcedure(\n service: string,\n procedure: string,\n args: unknown[] = [],\n options: { bypassCache?: boolean } = {},\n): Promise<ServiceResult> {\n const cacheKey = getCacheKey(service, procedure, args);\n const ttlConfig = cacheConfig.get(service);\n\n // Check cache first\n if (!options.bypassCache && ttlConfig) {\n const cached = getFromCache(cacheKey);\n if (cached) return cached;\n }\n\n // Check if backend is configured\n if (!currentBackend) {\n return {\n success: false,\n error: 'No service backend configured. Call setServiceBackend() first.',\n durationMs: 0,\n };\n }\n\n const startTime = performance.now();\n\n try {\n const data = await currentBackend.call(service, procedure, args);\n\n const serviceResult: ServiceResult = {\n success: true,\n data,\n durationMs: performance.now() - startTime,\n };\n\n // Cache successful results\n if (ttlConfig) {\n setCache(cacheKey, serviceResult, ttlConfig.ttl);\n }\n\n return serviceResult;\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n durationMs: performance.now() - startTime,\n };\n }\n}\n\n/**\n * Configure cache TTL for a service\n */\nexport function configureCacheTtl(service: string, ttl: number): void {\n cacheConfig.set(service, { ttl });\n}\n\n/**\n * Invalidate cache entries\n */\nexport function invalidateCache(service?: string): void {\n if (service) {\n for (const key of cache.keys()) {\n if (key.startsWith(`${service}:`)) cache.delete(key);\n }\n } else {\n cache.clear();\n }\n}\n\n/**\n * Get cache statistics\n */\nexport function getCacheStats(): { size: number; services: string[] } {\n const services = new Set<string>();\n for (const key of cache.keys()) {\n const service = key.split(':')[0];\n if (service) services.add(service);\n }\n return { size: cache.size, services: [...services] };\n}\n\n/**\n * Batch call multiple procedures\n */\nexport interface BatchCall {\n service: string;\n procedure: string;\n args?: unknown[];\n bypassCache?: boolean;\n}\n\nexport async function batchCall(calls: BatchCall[]): Promise<ServiceResult[]> {\n return Promise.all(\n calls.map((c) =>\n callProcedure(c.service, c.procedure, c.args || [], {\n bypassCache: c.bypassCache,\n }),\n ),\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/services/proxy.ts"],"sourcesContent":["// Patchwork Types - Context providers and selection engine types\n\n// ============================================================================\n// Context Provider Types\n// ============================================================================\n\nexport interface ContextProvider {\n name: string;\n schema?: Record<string, unknown>;\n getContext(): Promise<Record<string, unknown>>;\n subscribe?(callback: (context: Record<string, unknown>) => void): () => void;\n}\n\nexport interface AggregatedContext {\n timestamp: string;\n providers: {\n [providerName: string]: Record<string, unknown>;\n };\n}\n\nexport interface ContextManagerOptions {\n debounce_ms?: number;\n}\n\n// ============================================================================\n// Common Context Shapes\n// ============================================================================\n\nexport interface ShellContext {\n cwd: string;\n recent_commands?: string[];\n shell?: string;\n}\n\nexport interface GitContext {\n is_repo: boolean;\n branch?: string;\n remote_url?: string;\n uncommitted_changes?: number;\n staged_files?: number;\n}\n\nexport interface ProjectContext {\n type?: string;\n package_manager?: string;\n scripts?: string[];\n}\n\n// ============================================================================\n// Selection Engine Types\n// ============================================================================\n\nexport interface Viewport {\n width: number;\n height: number;\n}\n\nexport interface SelectionOptions {\n limit?: number;\n strategy?: 'llm' | 'rules';\n minConfidence?: number;\n}\n\nexport interface WidgetSuggestion {\n name: string;\n confidence: number;\n position: 'primary' | 'secondary' | 'ambient';\n reason: string;\n suggested_size: {\n width: number;\n height: number;\n };\n}\n\nexport interface CompositionRules {\n max_primary: number;\n max_secondary: number;\n max_ambient: number;\n ambient_stacking: boolean;\n}\n\nexport const DEFAULT_COMPOSITION_RULES: CompositionRules = {\n max_primary: 1,\n max_secondary: 3,\n max_ambient: 5,\n ambient_stacking: true,\n};\n\nexport interface ComposedLayout {\n widgets: Array<{\n name: string;\n position: 'primary' | 'secondary' | 'ambient';\n bounds: { x: number; y: number; width: number; height: number };\n }>;\n remaining_space: { width: number; height: number };\n}\n\n// ============================================================================\n// Usage Tracking Types\n// ============================================================================\n\nexport interface UsageRecord {\n widget_name: string;\n context_hash: string;\n was_suggested: boolean;\n viewport: Viewport;\n timestamp: string;\n}\n\nexport interface UsagePattern {\n context_hash: string;\n selected_widget: string;\n was_suggested: boolean;\n viewport_size: Viewport;\n timestamp: string;\n}\n","// Service Proxy - Caching layer for service calls\n//\n// Provides a backend-agnostic service proxy with caching.\n// The actual backend (UTCP, MCP, HTTP, etc.) is set via setServiceBackend().\n\nimport type { ServiceResult, CacheEntry, CacheConfig } from \"./types\";\n\n/**\n * Service backend interface - abstracts the actual service call mechanism\n *\n * Implementations can use UTCP, MCP, HTTP, or any other protocol.\n */\nexport interface ServiceBackend {\n /**\n * Call a service procedure\n * @param service - Service namespace (e.g., \"git\", \"github\")\n * @param procedure - Procedure name (e.g., \"branch\", \"repos.list\")\n * @param args - Arguments to pass\n */\n call(service: string, procedure: string, args: unknown[]): Promise<unknown>;\n}\n\n// Current backend (must be set before use)\nlet currentBackend: ServiceBackend | null = null;\n\n// Cache storage\nconst cache = new Map<string, CacheEntry>();\nconst cacheConfig = new Map<string, CacheConfig>();\nconst MAX_CACHE_SIZE = 1000;\n\n/**\n * Set the service backend\n *\n * This must be called before making any service calls.\n * The backend handles the actual communication with services.\n *\n * @example\n * ```typescript\n * // Using with UTCP\n * setServiceBackend({\n * call: (service, procedure, args) =>\n * utcpClient.callTool(`${service}.${procedure}`, args)\n * });\n *\n * // Using with HTTP proxy\n * setServiceBackend({\n * call: async (service, procedure, args) => {\n * const res = await fetch(`/api/proxy/${service}/${procedure}`, {\n * method: 'POST',\n * body: JSON.stringify({ args })\n * });\n * return res.json();\n * }\n * });\n * ```\n */\nexport function setServiceBackend(backend: ServiceBackend): void {\n currentBackend = backend;\n}\n\n/**\n * Create a service proxy that wraps the backend with caching\n */\nexport function createProxy(): ServiceBackend {\n return {\n call: (service, procedure, args) =>\n callProcedure(service, procedure, args).then((r) => {\n if (!r.success) throw new Error(r.error || \"Service call failed\");\n return r.data;\n }),\n };\n}\n\nfunction getCacheKey(\n service: string,\n procedure: string,\n args: unknown[],\n): string {\n return `${service}:${procedure}:${JSON.stringify(args)}`;\n}\n\nfunction evictOldestCache(): void {\n if (cache.size < MAX_CACHE_SIZE) return;\n const oldest = Array.from(cache.entries())\n .sort(([, a], [, b]) => a.expiresAt - b.expiresAt)\n .slice(0, Math.floor(MAX_CACHE_SIZE * 0.2));\n for (const [key] of oldest) cache.delete(key);\n}\n\nfunction getFromCache(key: string): ServiceResult | null {\n const entry = cache.get(key);\n if (!entry) return null;\n if (Date.now() > entry.expiresAt) {\n cache.delete(key);\n return null;\n }\n return { ...entry.result, cached: true };\n}\n\nfunction setCache(key: string, result: ServiceResult, ttl: number): void {\n evictOldestCache();\n cache.set(key, { result, expiresAt: Date.now() + ttl * 1000 });\n}\n\n/**\n * Call a service procedure\n *\n * @param service - Service namespace (e.g., \"git\", \"github\")\n * @param procedure - Procedure name (e.g., \"branch\", \"repos.get\")\n * @param args - Arguments to pass\n * @param options - Call options\n */\nexport async function callProcedure(\n service: string,\n procedure: string,\n args: unknown[] = [],\n options: { bypassCache?: boolean } = {},\n): Promise<ServiceResult> {\n const cacheKey = getCacheKey(service, procedure, args);\n const ttlConfig = cacheConfig.get(service);\n\n // Check cache first\n if (!options.bypassCache && ttlConfig) {\n const cached = getFromCache(cacheKey);\n if (cached) return cached;\n }\n\n // Check if backend is configured\n if (!currentBackend) {\n return {\n success: false,\n error: \"No service backend configured. Call setServiceBackend() first.\",\n durationMs: 0,\n };\n }\n\n const startTime = performance.now();\n\n try {\n const data = await currentBackend.call(service, procedure, args);\n\n const serviceResult: ServiceResult = {\n success: true,\n data,\n durationMs: performance.now() - startTime,\n };\n\n // Cache successful results\n if (ttlConfig) {\n setCache(cacheKey, serviceResult, ttlConfig.ttl);\n }\n\n return serviceResult;\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n durationMs: performance.now() - startTime,\n };\n }\n}\n\n/**\n * Configure cache TTL for a service\n */\nexport function configureCacheTtl(service: string, ttl: number): void {\n cacheConfig.set(service, { ttl });\n}\n\n/**\n * Invalidate cache entries\n */\nexport function invalidateCache(service?: string): void {\n if (service) {\n for (const key of cache.keys()) {\n if (key.startsWith(`${service}:`)) cache.delete(key);\n }\n } else {\n cache.clear();\n }\n}\n\n/**\n * Get cache statistics\n */\nexport function getCacheStats(): { size: number; services: string[] } {\n const services = new Set<string>();\n for (const key of cache.keys()) {\n const service = key.split(\":\")[0];\n if (service) services.add(service);\n }\n return { size: cache.size, services: [...services] };\n}\n\n/**\n * Batch call multiple procedures\n */\nexport interface BatchCall {\n service: string;\n procedure: string;\n args?: unknown[];\n bypassCache?: boolean;\n}\n\nexport async function batchCall(calls: BatchCall[]): Promise<ServiceResult[]> {\n return Promise.all(\n calls.map((c) =>\n callProcedure(c.service, c.procedure, c.args || [], {\n bypassCache: c.bypassCache,\n }),\n ),\n );\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aprovan/patchwork",
|
|
3
|
-
"version": "0.1.0-dev.
|
|
3
|
+
"version": "0.1.0-dev.c680591",
|
|
4
4
|
"description": "Patchwork, a platform for building LLM-powered applications with pluggable UI components and a flexible compiler.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
package/src/index.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export * from
|
|
1
|
+
export * from "./types";
|
|
2
2
|
|
|
3
|
-
export type { CacheConfig, ServiceResult } from
|
|
3
|
+
export type { CacheConfig, ServiceResult } from "./services/types.js";
|
|
4
4
|
|
|
5
5
|
// Services
|
|
6
6
|
export {
|
|
7
|
-
|
|
7
|
+
createProxy,
|
|
8
8
|
callProcedure,
|
|
9
9
|
batchCall,
|
|
10
10
|
configureCacheTtl,
|
|
@@ -12,4 +12,4 @@ export {
|
|
|
12
12
|
getCacheStats,
|
|
13
13
|
setServiceBackend,
|
|
14
14
|
type ServiceBackend,
|
|
15
|
-
} from
|
|
15
|
+
} from "./services/index.js";
|
package/src/services/index.ts
CHANGED
package/src/services/proxy.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Provides a backend-agnostic service proxy with caching.
|
|
4
4
|
// The actual backend (UTCP, MCP, HTTP, etc.) is set via setServiceBackend().
|
|
5
5
|
|
|
6
|
-
import type { ServiceResult, CacheEntry, CacheConfig } from
|
|
6
|
+
import type { ServiceResult, CacheEntry, CacheConfig } from "./types";
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Service backend interface - abstracts the actual service call mechanism
|
|
@@ -61,11 +61,11 @@ export function setServiceBackend(backend: ServiceBackend): void {
|
|
|
61
61
|
/**
|
|
62
62
|
* Create a service proxy that wraps the backend with caching
|
|
63
63
|
*/
|
|
64
|
-
export function
|
|
64
|
+
export function createProxy(): ServiceBackend {
|
|
65
65
|
return {
|
|
66
66
|
call: (service, procedure, args) =>
|
|
67
67
|
callProcedure(service, procedure, args).then((r) => {
|
|
68
|
-
if (!r.success) throw new Error(r.error ||
|
|
68
|
+
if (!r.success) throw new Error(r.error || "Service call failed");
|
|
69
69
|
return r.data;
|
|
70
70
|
}),
|
|
71
71
|
};
|
|
@@ -129,7 +129,7 @@ export async function callProcedure(
|
|
|
129
129
|
if (!currentBackend) {
|
|
130
130
|
return {
|
|
131
131
|
success: false,
|
|
132
|
-
error:
|
|
132
|
+
error: "No service backend configured. Call setServiceBackend() first.",
|
|
133
133
|
durationMs: 0,
|
|
134
134
|
};
|
|
135
135
|
}
|
|
@@ -186,7 +186,7 @@ export function invalidateCache(service?: string): void {
|
|
|
186
186
|
export function getCacheStats(): { size: number; services: string[] } {
|
|
187
187
|
const services = new Set<string>();
|
|
188
188
|
for (const key of cache.keys()) {
|
|
189
|
-
const service = key.split(
|
|
189
|
+
const service = key.split(":")[0];
|
|
190
190
|
if (service) services.add(service);
|
|
191
191
|
}
|
|
192
192
|
return { size: cache.size, services: [...services] };
|