rag-lite-ts 2.0.4 → 2.0.5
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/dist/config.js +3 -0
- package/dist/core/database-connection-manager.js +5 -9
- package/dist/core/ingestion.js +3 -0
- package/dist/mcp-server.js +20 -15
- package/package.json +105 -105
package/dist/config.js
CHANGED
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
* Extends core configuration with implementation-specific properties
|
|
4
4
|
*/
|
|
5
5
|
import { getDefaultModelCachePath } from './core/config.js';
|
|
6
|
+
import { createRequire } from 'module';
|
|
7
|
+
// Create require for CommonJS modules in ES module context
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
6
9
|
/**
|
|
7
10
|
* Default configuration object with both core and text-specific settings
|
|
8
11
|
*/
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Addresses production issues with MCP server + CLI concurrent usage
|
|
5
5
|
*/
|
|
6
6
|
import { openDatabase } from './db.js';
|
|
7
|
+
import { resolve as pathResolve } from 'node:path';
|
|
7
8
|
/**
|
|
8
9
|
* Database Connection Manager
|
|
9
10
|
* Manages shared database connections to prevent locking issues
|
|
@@ -186,15 +187,10 @@ export class DatabaseConnectionManager {
|
|
|
186
187
|
*/
|
|
187
188
|
static normalizePath(dbPath) {
|
|
188
189
|
// Convert to absolute path and normalize separators
|
|
189
|
-
// Use
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}
|
|
194
|
-
catch {
|
|
195
|
-
// Fallback: simple normalization
|
|
196
|
-
return dbPath.replace(/\\/g, '/');
|
|
197
|
-
}
|
|
190
|
+
// Use Node.js path.resolve for proper relative path handling
|
|
191
|
+
const absolutePath = pathResolve(dbPath);
|
|
192
|
+
// Normalize separators for cross-platform consistency
|
|
193
|
+
return absolutePath.replace(/\\/g, '/');
|
|
198
194
|
}
|
|
199
195
|
/**
|
|
200
196
|
* Start the cleanup timer for idle connections
|
package/dist/core/ingestion.js
CHANGED
|
@@ -9,6 +9,9 @@ import { config } from './config.js';
|
|
|
9
9
|
import { DocumentPathManager } from './path-manager.js';
|
|
10
10
|
import { existsSync } from 'fs';
|
|
11
11
|
import { ContentManager } from './content-manager.js';
|
|
12
|
+
import { createRequire } from 'module';
|
|
13
|
+
// Create require for CommonJS modules in ES module context
|
|
14
|
+
const require = createRequire(import.meta.url);
|
|
12
15
|
/**
|
|
13
16
|
* Main ingestion pipeline class
|
|
14
17
|
* Coordinates the entire process from file discovery to vector storage
|
package/dist/mcp-server.js
CHANGED
|
@@ -24,11 +24,11 @@
|
|
|
24
24
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
25
25
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
26
26
|
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
27
|
-
import { existsSync, statSync } from 'fs';
|
|
27
|
+
import { existsSync, statSync, createWriteStream } from 'fs';
|
|
28
28
|
import { resolve } from 'path';
|
|
29
29
|
import { SearchFactory } from './factories/search-factory.js';
|
|
30
30
|
import { IngestionFactory } from './factories/ingestion-factory.js';
|
|
31
|
-
import {
|
|
31
|
+
import { getSystemInfo } from './core/db.js';
|
|
32
32
|
import { DatabaseConnectionManager } from './core/database-connection-manager.js';
|
|
33
33
|
import { config, validateCoreConfig, ConfigurationError } from './core/config.js';
|
|
34
34
|
/**
|
|
@@ -746,7 +746,7 @@ class RagLiteMCPServer {
|
|
|
746
746
|
reject(new Error(`Failed to download image: HTTP ${redirectResponse.statusCode}`));
|
|
747
747
|
return;
|
|
748
748
|
}
|
|
749
|
-
const fileStream =
|
|
749
|
+
const fileStream = createWriteStream(tempFilePath);
|
|
750
750
|
redirectResponse.pipe(fileStream);
|
|
751
751
|
fileStream.on('finish', () => {
|
|
752
752
|
fileStream.close();
|
|
@@ -761,7 +761,7 @@ class RagLiteMCPServer {
|
|
|
761
761
|
return;
|
|
762
762
|
}
|
|
763
763
|
else {
|
|
764
|
-
const fileStream =
|
|
764
|
+
const fileStream = createWriteStream(tempFilePath);
|
|
765
765
|
response.pipe(fileStream);
|
|
766
766
|
fileStream.on('finish', () => {
|
|
767
767
|
fileStream.close();
|
|
@@ -916,8 +916,8 @@ class RagLiteMCPServer {
|
|
|
916
916
|
// Create ingestion pipeline with force rebuild using factory
|
|
917
917
|
const pipeline = await IngestionFactory.create(config.db_file, config.index_file, { forceRebuild: true });
|
|
918
918
|
try {
|
|
919
|
-
// Get all documents from database and re-ingest them
|
|
920
|
-
const db = await
|
|
919
|
+
// Get all documents from database and re-ingest them - use shared connection
|
|
920
|
+
const db = await DatabaseConnectionManager.getConnection(config.db_file);
|
|
921
921
|
try {
|
|
922
922
|
const documents = await db.all('SELECT DISTINCT source FROM documents ORDER BY source');
|
|
923
923
|
if (documents.length === 0) {
|
|
@@ -971,7 +971,8 @@ class RagLiteMCPServer {
|
|
|
971
971
|
};
|
|
972
972
|
}
|
|
973
973
|
finally {
|
|
974
|
-
|
|
974
|
+
// Release instead of close - keeps connection alive for reuse
|
|
975
|
+
await DatabaseConnectionManager.releaseConnection(config.db_file);
|
|
975
976
|
}
|
|
976
977
|
}
|
|
977
978
|
finally {
|
|
@@ -1009,7 +1010,7 @@ class RagLiteMCPServer {
|
|
|
1009
1010
|
// Check model compatibility if database exists
|
|
1010
1011
|
if (stats.database_exists) {
|
|
1011
1012
|
try {
|
|
1012
|
-
const db = await
|
|
1013
|
+
const db = await DatabaseConnectionManager.getConnection(config.db_file);
|
|
1013
1014
|
try {
|
|
1014
1015
|
const systemInfo = await getSystemInfo(db);
|
|
1015
1016
|
if (systemInfo && systemInfo.modelName && systemInfo.modelDimensions) {
|
|
@@ -1040,7 +1041,8 @@ class RagLiteMCPServer {
|
|
|
1040
1041
|
stats.total_chunks = chunkCount?.count || 0;
|
|
1041
1042
|
}
|
|
1042
1043
|
finally {
|
|
1043
|
-
|
|
1044
|
+
// Release instead of close - keeps connection alive for reuse
|
|
1045
|
+
await DatabaseConnectionManager.releaseConnection(config.db_file);
|
|
1044
1046
|
}
|
|
1045
1047
|
}
|
|
1046
1048
|
catch (error) {
|
|
@@ -1500,7 +1502,7 @@ class RagLiteMCPServer {
|
|
|
1500
1502
|
};
|
|
1501
1503
|
// Add content breakdown if requested
|
|
1502
1504
|
if (args.include_content_breakdown) {
|
|
1503
|
-
const db = await
|
|
1505
|
+
const db = await DatabaseConnectionManager.getConnection(config.db_file);
|
|
1504
1506
|
try {
|
|
1505
1507
|
// Get document count by content type
|
|
1506
1508
|
const docsByType = await db.all(`
|
|
@@ -1526,7 +1528,8 @@ class RagLiteMCPServer {
|
|
|
1526
1528
|
};
|
|
1527
1529
|
}
|
|
1528
1530
|
finally {
|
|
1529
|
-
|
|
1531
|
+
// Release instead of close - keeps connection alive for reuse
|
|
1532
|
+
await DatabaseConnectionManager.releaseConnection(config.db_file);
|
|
1530
1533
|
}
|
|
1531
1534
|
}
|
|
1532
1535
|
// Add performance metrics if requested
|
|
@@ -1600,6 +1603,8 @@ class RagLiteMCPServer {
|
|
|
1600
1603
|
this.isSearchEngineInitialized = true;
|
|
1601
1604
|
}
|
|
1602
1605
|
catch (error) {
|
|
1606
|
+
console.error('❌ MCP Server: Search engine initialization failed');
|
|
1607
|
+
console.error(`❌ Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
1603
1608
|
// Check if this is a mode detection error
|
|
1604
1609
|
if (error instanceof Error && error.message.includes('mode detection')) {
|
|
1605
1610
|
console.error('⚠️ MCP Server: Mode detection failed, falling back to text mode');
|
|
@@ -1612,7 +1617,6 @@ class RagLiteMCPServer {
|
|
|
1612
1617
|
throw error;
|
|
1613
1618
|
}
|
|
1614
1619
|
// For other initialization errors, provide a generic wrapper
|
|
1615
|
-
console.error('❌ MCP Server: Search engine initialization failed');
|
|
1616
1620
|
throw new Error(`Failed to initialize search engine: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
1617
1621
|
}
|
|
1618
1622
|
}
|
|
@@ -1635,8 +1639,8 @@ class RagLiteMCPServer {
|
|
|
1635
1639
|
const { ModeDetectionService } = await import('./core/mode-detection-service.js');
|
|
1636
1640
|
const modeService = new ModeDetectionService(config.db_file);
|
|
1637
1641
|
const systemInfo = await modeService.detectMode();
|
|
1638
|
-
// Check if database has any images
|
|
1639
|
-
const db = await
|
|
1642
|
+
// Check if database has any images - use shared connection
|
|
1643
|
+
const db = await DatabaseConnectionManager.getConnection(config.db_file);
|
|
1640
1644
|
let hasImages = false;
|
|
1641
1645
|
let documentCount = 0;
|
|
1642
1646
|
try {
|
|
@@ -1646,7 +1650,8 @@ class RagLiteMCPServer {
|
|
|
1646
1650
|
documentCount = docCount?.count || 0;
|
|
1647
1651
|
}
|
|
1648
1652
|
finally {
|
|
1649
|
-
|
|
1653
|
+
// Release instead of close - keeps connection alive for reuse
|
|
1654
|
+
await DatabaseConnectionManager.releaseConnection(config.db_file);
|
|
1650
1655
|
}
|
|
1651
1656
|
return {
|
|
1652
1657
|
mode: systemInfo.mode,
|
package/package.json
CHANGED
|
@@ -1,105 +1,105 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "rag-lite-ts",
|
|
3
|
-
"version": "2.0.
|
|
4
|
-
"description": "Local-first TypeScript retrieval engine with Chameleon Multimodal Architecture for semantic search over text and image content",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "./dist/index.js",
|
|
7
|
-
"types": "./dist/index.d.ts",
|
|
8
|
-
"bin": {
|
|
9
|
-
"raglite": "./dist/cli.js",
|
|
10
|
-
"raglite-mcp": "./dist/mcp-server.js"
|
|
11
|
-
},
|
|
12
|
-
"exports": {
|
|
13
|
-
".": {
|
|
14
|
-
"import": "./dist/index.js",
|
|
15
|
-
"types": "./dist/index.d.ts"
|
|
16
|
-
},
|
|
17
|
-
"./mcp": {
|
|
18
|
-
"import": "./dist/mcp-server.js",
|
|
19
|
-
"types": "./dist/mcp-server.d.ts"
|
|
20
|
-
}
|
|
21
|
-
},
|
|
22
|
-
"files": [
|
|
23
|
-
"dist/**/*.js",
|
|
24
|
-
"dist/**/*.d.ts",
|
|
25
|
-
"!dist/**/*.map",
|
|
26
|
-
"README.md",
|
|
27
|
-
"LICENSE"
|
|
28
|
-
],
|
|
29
|
-
"scripts": {
|
|
30
|
-
"build": "tsc",
|
|
31
|
-
"build:test": "tsc --project tsconfig.test.json",
|
|
32
|
-
"clean": "rimraf dist",
|
|
33
|
-
"dev": "tsc --watch",
|
|
34
|
-
"test": "npm run build:test && node --expose-gc --test --test-concurrency=1 dist/__tests__/core dist/__tests__/text dist/__tests__/preprocessors dist/__tests__/cli dist/__tests__/factories",
|
|
35
|
-
"test:verbose": "npm run build:test && node --expose-gc --test --test-concurrency=1 --test-reporter=tap dist/__tests__/core dist/__tests__/text dist/__tests__/preprocessors dist/__tests__/cli dist/__tests__/factories",
|
|
36
|
-
"test:core": "npm run build:test && node --expose-gc --test --test-concurrency=1 dist/__tests__/core",
|
|
37
|
-
"test:core:verbose": "npm run build:test && node --expose-gc --test --test-concurrency=1 --test-reporter=tap dist/__tests__/core",
|
|
38
|
-
"test:text": "npm run build:test && node --expose-gc --test --test-concurrency=1 dist/__tests__/text",
|
|
39
|
-
"test:preprocessors": "npm run build:test && node --expose-gc --test --test-concurrency=1 dist/__tests__/preprocessors",
|
|
40
|
-
"test:cli": "npm run build:test && node --expose-gc --test --test-concurrency=1 dist/__tests__/cli",
|
|
41
|
-
"test:factories": "npm run build:test && node --expose-gc --test --test-concurrency=1 dist/__tests__/factories",
|
|
42
|
-
"test:datasets": "npm run build:test && node --expose-gc --test --test-concurrency=1 dist/__tests__/datasets",
|
|
43
|
-
"test:unit": "npm run build:test && node --expose-gc --test --test-concurrency=1 dist/__tests__/core dist/__tests__/text dist/__tests__/preprocessors dist/__tests__/cli dist/__tests__/factories",
|
|
44
|
-
"test:integration": "npm run build && npm run build:test && node --expose-gc --test --test-concurrency=1 dist/__tests__/integration",
|
|
45
|
-
"test:integration:verbose": "npm run build && npm run build:test && node --expose-gc --test --test-concurrency=1 --test-reporter=tap dist/__tests__/integration",
|
|
46
|
-
"test:all": "npm run build:test && node --expose-gc --test --test-concurrency=1 dist/__tests__",
|
|
47
|
-
"test:all:verbose": "npm run build:test && node --expose-gc --test --test-concurrency=1 --test-reporter=tap dist/__tests__",
|
|
48
|
-
"prepublishOnly": "npm run clean && npm run build"
|
|
49
|
-
},
|
|
50
|
-
"keywords": [
|
|
51
|
-
"rag",
|
|
52
|
-
"retrieval",
|
|
53
|
-
"semantic-search",
|
|
54
|
-
"embeddings",
|
|
55
|
-
"typescript",
|
|
56
|
-
"local-first",
|
|
57
|
-
"multimodal",
|
|
58
|
-
"chameleon-architecture",
|
|
59
|
-
"clip",
|
|
60
|
-
"image-search",
|
|
61
|
-
"polymorphic-runtime",
|
|
62
|
-
"mdx",
|
|
63
|
-
"mermaid",
|
|
64
|
-
"preprocessing",
|
|
65
|
-
"pdf",
|
|
66
|
-
"docx",
|
|
67
|
-
"document-processing"
|
|
68
|
-
],
|
|
69
|
-
"repository": {
|
|
70
|
-
"type": "git",
|
|
71
|
-
"url": "https://github.com/raglite/rag-lite-ts.git"
|
|
72
|
-
},
|
|
73
|
-
"bugs": {
|
|
74
|
-
"url": "https://github.com/raglite/rag-lite-ts/issues"
|
|
75
|
-
},
|
|
76
|
-
"homepage": "https://github.com/raglite/rag-lite-ts#readme",
|
|
77
|
-
"author": "RAG-lite TS Contributors",
|
|
78
|
-
"license": "MIT",
|
|
79
|
-
"engines": {
|
|
80
|
-
"node": ">=18.0.0"
|
|
81
|
-
},
|
|
82
|
-
"dependencies": {
|
|
83
|
-
"@huggingface/transformers": "^3.7.5",
|
|
84
|
-
"@modelcontextprotocol/sdk": "^1.18.2",
|
|
85
|
-
"csv-parse": "^6.1.0",
|
|
86
|
-
"hnswlib-wasm": "^0.8.2",
|
|
87
|
-
"jsdom": "^27.0.0",
|
|
88
|
-
"lru-cache": "^11.2.2",
|
|
89
|
-
"mammoth": "^1.11.0",
|
|
90
|
-
"pdf-parse": "^2.1.10",
|
|
91
|
-
"sqlite3": "^5.1.
|
|
92
|
-
},
|
|
93
|
-
"devDependencies": {
|
|
94
|
-
"@types/jsdom": "^21.1.7",
|
|
95
|
-
"@types/lru-cache": "^7.10.9",
|
|
96
|
-
"@types/node": "^20.11.0",
|
|
97
|
-
"js-yaml": "^4.1.0",
|
|
98
|
-
"rimraf": "^5.0.5",
|
|
99
|
-
"tsx": "^4.20.6",
|
|
100
|
-
"typescript": "^5.3.0"
|
|
101
|
-
},
|
|
102
|
-
"optionalDependencies": {
|
|
103
|
-
"sharp": "^0.34.5"
|
|
104
|
-
}
|
|
105
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "rag-lite-ts",
|
|
3
|
+
"version": "2.0.5",
|
|
4
|
+
"description": "Local-first TypeScript retrieval engine with Chameleon Multimodal Architecture for semantic search over text and image content",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"raglite": "./dist/cli.js",
|
|
10
|
+
"raglite-mcp": "./dist/mcp-server.js"
|
|
11
|
+
},
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts"
|
|
16
|
+
},
|
|
17
|
+
"./mcp": {
|
|
18
|
+
"import": "./dist/mcp-server.js",
|
|
19
|
+
"types": "./dist/mcp-server.d.ts"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist/**/*.js",
|
|
24
|
+
"dist/**/*.d.ts",
|
|
25
|
+
"!dist/**/*.map",
|
|
26
|
+
"README.md",
|
|
27
|
+
"LICENSE"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsc",
|
|
31
|
+
"build:test": "tsc --project tsconfig.test.json",
|
|
32
|
+
"clean": "rimraf dist",
|
|
33
|
+
"dev": "tsc --watch",
|
|
34
|
+
"test": "npm run build:test && node --expose-gc --test --test-concurrency=1 dist/__tests__/core dist/__tests__/text dist/__tests__/preprocessors dist/__tests__/cli dist/__tests__/factories",
|
|
35
|
+
"test:verbose": "npm run build:test && node --expose-gc --test --test-concurrency=1 --test-reporter=tap dist/__tests__/core dist/__tests__/text dist/__tests__/preprocessors dist/__tests__/cli dist/__tests__/factories",
|
|
36
|
+
"test:core": "npm run build:test && node --expose-gc --test --test-concurrency=1 dist/__tests__/core",
|
|
37
|
+
"test:core:verbose": "npm run build:test && node --expose-gc --test --test-concurrency=1 --test-reporter=tap dist/__tests__/core",
|
|
38
|
+
"test:text": "npm run build:test && node --expose-gc --test --test-concurrency=1 dist/__tests__/text",
|
|
39
|
+
"test:preprocessors": "npm run build:test && node --expose-gc --test --test-concurrency=1 dist/__tests__/preprocessors",
|
|
40
|
+
"test:cli": "npm run build:test && node --expose-gc --test --test-concurrency=1 dist/__tests__/cli",
|
|
41
|
+
"test:factories": "npm run build:test && node --expose-gc --test --test-concurrency=1 dist/__tests__/factories",
|
|
42
|
+
"test:datasets": "npm run build:test && node --expose-gc --test --test-concurrency=1 dist/__tests__/datasets",
|
|
43
|
+
"test:unit": "npm run build:test && node --expose-gc --test --test-concurrency=1 dist/__tests__/core dist/__tests__/text dist/__tests__/preprocessors dist/__tests__/cli dist/__tests__/factories",
|
|
44
|
+
"test:integration": "npm run build && npm run build:test && node --expose-gc --test --test-concurrency=1 dist/__tests__/integration",
|
|
45
|
+
"test:integration:verbose": "npm run build && npm run build:test && node --expose-gc --test --test-concurrency=1 --test-reporter=tap dist/__tests__/integration",
|
|
46
|
+
"test:all": "npm run build:test && node --expose-gc --test --test-concurrency=1 dist/__tests__",
|
|
47
|
+
"test:all:verbose": "npm run build:test && node --expose-gc --test --test-concurrency=1 --test-reporter=tap dist/__tests__",
|
|
48
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
49
|
+
},
|
|
50
|
+
"keywords": [
|
|
51
|
+
"rag",
|
|
52
|
+
"retrieval",
|
|
53
|
+
"semantic-search",
|
|
54
|
+
"embeddings",
|
|
55
|
+
"typescript",
|
|
56
|
+
"local-first",
|
|
57
|
+
"multimodal",
|
|
58
|
+
"chameleon-architecture",
|
|
59
|
+
"clip",
|
|
60
|
+
"image-search",
|
|
61
|
+
"polymorphic-runtime",
|
|
62
|
+
"mdx",
|
|
63
|
+
"mermaid",
|
|
64
|
+
"preprocessing",
|
|
65
|
+
"pdf",
|
|
66
|
+
"docx",
|
|
67
|
+
"document-processing"
|
|
68
|
+
],
|
|
69
|
+
"repository": {
|
|
70
|
+
"type": "git",
|
|
71
|
+
"url": "https://github.com/raglite/rag-lite-ts.git"
|
|
72
|
+
},
|
|
73
|
+
"bugs": {
|
|
74
|
+
"url": "https://github.com/raglite/rag-lite-ts/issues"
|
|
75
|
+
},
|
|
76
|
+
"homepage": "https://github.com/raglite/rag-lite-ts#readme",
|
|
77
|
+
"author": "RAG-lite TS Contributors",
|
|
78
|
+
"license": "MIT",
|
|
79
|
+
"engines": {
|
|
80
|
+
"node": ">=18.0.0"
|
|
81
|
+
},
|
|
82
|
+
"dependencies": {
|
|
83
|
+
"@huggingface/transformers": "^3.7.5",
|
|
84
|
+
"@modelcontextprotocol/sdk": "^1.18.2",
|
|
85
|
+
"csv-parse": "^6.1.0",
|
|
86
|
+
"hnswlib-wasm": "^0.8.2",
|
|
87
|
+
"jsdom": "^27.0.0",
|
|
88
|
+
"lru-cache": "^11.2.2",
|
|
89
|
+
"mammoth": "^1.11.0",
|
|
90
|
+
"pdf-parse": "^2.1.10",
|
|
91
|
+
"sqlite3": "^5.1.7"
|
|
92
|
+
},
|
|
93
|
+
"devDependencies": {
|
|
94
|
+
"@types/jsdom": "^21.1.7",
|
|
95
|
+
"@types/lru-cache": "^7.10.9",
|
|
96
|
+
"@types/node": "^20.11.0",
|
|
97
|
+
"js-yaml": "^4.1.0",
|
|
98
|
+
"rimraf": "^5.0.5",
|
|
99
|
+
"tsx": "^4.20.6",
|
|
100
|
+
"typescript": "^5.3.0"
|
|
101
|
+
},
|
|
102
|
+
"optionalDependencies": {
|
|
103
|
+
"sharp": "^0.34.5"
|
|
104
|
+
}
|
|
105
|
+
}
|