Skip to content

Commit 193202b

Browse files
authored
feat: add pglite support (#174)
1 parent 8ca399d commit 193202b

File tree

9 files changed

+389
-129
lines changed

9 files changed

+389
-129
lines changed

config/config.example.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Database settings
22
database:
3-
# You can use url or separate fields
3+
# Database type: postgres, pglite
4+
type: postgres
5+
# PostgreSQL configuration (used when type: postgres)
6+
# Can use URL or separate field configuration
47
# url: postgres://postgres:postgres@localhost:5432/tg_search
58
host: localhost
69
port: 5433

cspell.config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ words:
1919
- ofetch
2020
- ollama
2121
- onnotice
22+
- pglite
2223
- pgvector
2324
- pinia
2425
- reka

docker-compose.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@ services:
99
POSTGRES_PASSWORD: '123456'
1010
volumes:
1111
- ./sql/init.sql:/docker-entrypoint-initdb.d/init.sql
12-
- ./.postgres/data:/var/lib/postgresql/data
12+
- pgvector_data:/var/lib/postgresql/data
1313
healthcheck:
1414
test: [CMD-SHELL, pg_isready -d $$POSTGRES_DB -U $$POSTGRES_USER]
1515
interval: 10s
1616
timeout: 5s
1717
retries: 5
1818
restart: unless-stopped
19+
20+
volumes:
21+
pgvector_data:

packages/common/src/composable/config.ts

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,28 @@ import { dirname, join, resolve } from 'node:path'
66
import { cwd } from 'node:process'
77
import { findWorkspaceDir } from '@pnpm/find-workspace-dir'
88
import defu from 'defu'
9+
import path from 'path-browserify-esm'
910
import { safeParse } from 'valibot'
1011
import { parse, stringify } from 'yaml'
1112

12-
import { configSchema } from '../helper/config-schema'
13+
import { configSchema, DatabaseType } from '../helper/config-schema'
1314
import { generateDefaultConfig } from '../helper/default-config'
1415
import { useLogger } from '../helper/logger'
1516

1617
let config: Config
1718
const logger = useLogger('common:config')
1819

19-
export async function useConfigPath(): Promise<string> {
20+
async function getWorkspacePath() {
2021
const workspaceDir = await findWorkspaceDir(cwd())
2122
if (!workspaceDir) {
2223
throw new Error('Failed to find workspace directory')
2324
}
2425

25-
const configPath = resolve(workspaceDir, 'config', 'config.yaml')
26+
return workspaceDir
27+
}
28+
29+
export async function useConfigPath(): Promise<string> {
30+
const configPath = resolve(await getWorkspacePath(), 'config', 'config.yaml')
2631

2732
logger.withFields({ configPath }).log('Config path')
2833

@@ -34,12 +39,15 @@ export async function useConfigPath(): Promise<string> {
3439
return configPath
3540
}
3641

37-
export async function useAssetsPath(): Promise<string> {
38-
const workspaceDir = await findWorkspaceDir(cwd())
39-
if (!workspaceDir) {
40-
throw new Error('Failed to find workspace directory')
41-
}
42+
export async function getDrizzlePath(): Promise<string> {
43+
const workspaceDir = await getWorkspacePath()
44+
const drizzlePath = resolve(workspaceDir, 'drizzle')
45+
logger.withFields({ drizzlePath }).log('Drizzle migrations path')
46+
return drizzlePath
47+
}
4248

49+
export async function useAssetsPath(): Promise<string> {
50+
const workspaceDir = await getWorkspacePath()
4351
const assetsPath = resolve(workspaceDir, 'assets')
4452

4553
logger.withFields({ assetsPath }).log('Assets path')
@@ -77,6 +85,21 @@ export function getDatabaseDSN(config: Config): string {
7785
return database.url || `postgres://${database.user}:${database.password}@${database.host}:${database.port}/${database.database}`
7886
}
7987

88+
export function getDatabaseFilePath(config: Config): string {
89+
const { database, path: configPath } = config
90+
91+
let extension = ''
92+
switch (database.type) {
93+
case DatabaseType.PGLITE:
94+
extension = '.pglite'
95+
break
96+
default:
97+
return ''
98+
}
99+
100+
return path.join(configPath.storage, `db${extension}`)
101+
}
102+
80103
export function resolveStoragePath(path: string): string {
81104
if (path.startsWith('~')) {
82105
path = path.replace('~', homedir())

packages/common/src/helper/config-schema.ts

Lines changed: 39 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,14 @@ export enum EmbeddingDimension {
1818
DIMENSION_768 = 768,
1919
}
2020

21+
export enum DatabaseType {
22+
POSTGRES = 'postgres',
23+
PGLITE = 'pglite',
24+
}
25+
2126
export const proxyConfigSchema = object({
22-
ip: string(),
23-
port: number(),
27+
ip: optional(string(), ''),
28+
port: optional(number(), 0),
2429
MTProxy: optional(boolean()),
2530
secret: optional(string()),
2631
socksType: optional(enumType(SocksType)),
@@ -30,57 +35,58 @@ export const proxyConfigSchema = object({
3035
})
3136

3237
export const databaseConfigSchema = object({
33-
host: string(),
34-
port: number(),
35-
user: string(),
36-
password: string(),
37-
database: string(),
38-
38+
type: optional(enumType(DatabaseType), DatabaseType.POSTGRES),
39+
host: optional(string(), 'localhost'),
40+
port: optional(number(), 5432),
41+
user: optional(string(), 'postgres'),
42+
password: optional(string(), 'postgres'),
43+
database: optional(string(), 'postgres'),
3944
url: optional(string()),
4045
})
4146

4247
export const messageConfigSchema = object({
43-
export: object({
44-
batchSize: number(),
45-
concurrent: number(),
46-
retryTimes: number(),
47-
maxTakeoutRetries: number(),
48-
}),
49-
batch: object({
50-
size: number(),
51-
}),
48+
export: optional(object({
49+
batchSize: optional(number(), 200),
50+
concurrent: optional(number(), 3),
51+
retryTimes: optional(number(), 3),
52+
maxTakeoutRetries: optional(number(), 3),
53+
}), {}),
54+
batch: optional(object({
55+
size: optional(number(), 100),
56+
}), {}),
5257
})
5358

5459
export const pathConfigSchema = object({
55-
storage: string(),
56-
dict: string(),
60+
storage: optional(string(), '~/.telegram-search'),
61+
dict: optional(string(), ''),
62+
assets: optional(string(), ''),
5763
})
5864

5965
export const telegramConfigSchema = object({
60-
apiId: string(),
61-
apiHash: string(),
62-
phoneNumber: string(),
66+
apiId: optional(string(), ''),
67+
apiHash: optional(string(), ''),
68+
phoneNumber: optional(string(), ''),
6369
proxy: optional(proxyConfigSchema),
6470
})
6571

6672
export const embeddingConfigSchema = object({
67-
provider: enumType(EmbeddingProvider),
68-
model: string(),
69-
dimension: optional(enumType(EmbeddingDimension)),
70-
apiKey: optional(string()),
71-
apiBase: optional(string()),
73+
provider: optional(enumType(EmbeddingProvider), EmbeddingProvider.OPENAI),
74+
model: optional(string(), 'text-embedding-3-small'),
75+
dimension: optional(enumType(EmbeddingDimension), EmbeddingDimension.DIMENSION_1536),
76+
apiKey: optional(string(), ''),
77+
apiBase: optional(string(), ''),
7278
})
7379

7480
export const apiConfigSchema = object({
75-
telegram: telegramConfigSchema,
76-
embedding: embeddingConfigSchema,
81+
telegram: optional(telegramConfigSchema, {}),
82+
embedding: optional(embeddingConfigSchema, {}),
7783
})
7884

7985
export const configSchema = object({
80-
database: databaseConfigSchema,
81-
message: messageConfigSchema,
82-
path: pathConfigSchema,
83-
api: apiConfigSchema,
86+
database: optional(databaseConfigSchema, {}),
87+
message: optional(messageConfigSchema, {}),
88+
path: optional(pathConfigSchema, {}),
89+
api: optional(apiConfigSchema, {}),
8490
})
8591

8692
export type Config = InferOutput<typeof configSchema>

packages/common/src/helper/default-config.ts

Lines changed: 1 addition & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -7,81 +7,15 @@ import { configSchema } from './config-schema'
77

88
export function generateDefaultConfig(paths?: { storagePath?: string, assetsPath?: string }): Config {
99
const defaultConfig = safeParse(configSchema, {
10-
// Database settings
11-
database: {
12-
// Default database connection settings
13-
host: 'localhost',
14-
port: 5432,
15-
user: 'postgres',
16-
password: 'postgres',
17-
database: 'postgres',
18-
},
19-
20-
// Message settings
21-
message: {
22-
// Export settings
23-
export: {
24-
// Number of messages to fetch in each request
25-
batchSize: 200,
26-
// Number of concurrent requests
27-
concurrent: 3,
28-
// Number of retry attempts
29-
retryTimes: 3,
30-
// Number of retry attempts for takeout session (0 means infinite retries)
31-
maxTakeoutRetries: 3,
32-
},
33-
// Database batch settings
34-
batch: {
35-
// Number of messages to save in each batch
36-
size: 100,
37-
},
38-
},
39-
40-
// Path settings
4110
path: {
4211
storage: paths?.storagePath ?? '~/.telegram-search',
4312
assets: paths?.assetsPath ?? '',
4413
dict: path.join(paths?.assetsPath ?? '', 'dict.txt.big'),
4514
},
46-
47-
// API settings
48-
api: {
49-
// Telegram API settings
50-
telegram: {
51-
// These values should be provided in config.yaml
52-
apiId: '',
53-
apiHash: '',
54-
phoneNumber: '',
55-
// Optional proxy settings - will be used if provided
56-
// proxy: {
57-
// ip: '', // Proxy host (IP or hostname)
58-
// port: 0, // Proxy port
59-
// MTProxy: false, // Whether it's an MTProxy or a normal Socks proxy
60-
// secret: '', // If using MTProxy, provide a secret
61-
// socksType: 5, // If using Socks, choose 4 or 5
62-
// timeout: 2, // Timeout (in seconds) for connection
63-
// username: '', // Optional username for proxy auth
64-
// password: '', // Optional password for proxy auth
65-
// }
66-
},
67-
// OpenAI API settings
68-
embedding: {
69-
// Embedding provider
70-
provider: 'openai',
71-
// Embedding model
72-
model: 'text-embedding-3-small',
73-
// API key should be provided in config.yaml
74-
apiKey: '',
75-
// Optional API base URL
76-
apiBase: '',
77-
// Embedding dimension
78-
dimension: 1536,
79-
},
80-
},
8115
})
8216

8317
if (!defaultConfig.success) {
84-
throw new Error('Failed to generate default config')
18+
throw new Error('Failed to generate default config', { cause: defaultConfig.issues })
8519
}
8620

8721
return defaultConfig.output

packages/core/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"lint:fix": "eslint src --fix"
2121
},
2222
"dependencies": {
23+
"@electric-sql/pglite": "^0.3.1",
2324
"@tg-search/common": "workspace:*",
2425
"@xsai-ext/providers-cloud": "catalog:",
2526
"@xsai/embed": "catalog:",
@@ -33,7 +34,8 @@
3334
"postgres": "^3.4.5",
3435
"telegram": "^2.26.22",
3536
"unbuild": "^3.5.0",
36-
"valibot": "^1.1.0"
37+
"valibot": "^1.1.0",
38+
"vectorlite": "^0.2.0"
3739
},
3840
"devDependencies": {
3941
"@types/node": "^22.15.18",

0 commit comments

Comments
 (0)