openpets 1.0.5 → 1.0.6
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/data/api.json +3172 -0
- package/dist/src/core/ai-client-base/index.d.ts +47 -0
- package/dist/src/core/ai-client-base/index.d.ts.map +1 -0
- package/dist/src/core/ai-client-base/index.js +168 -0
- package/dist/src/core/ai-client-base/index.js.map +1 -0
- package/dist/src/core/browser.d.ts +10 -0
- package/dist/src/core/browser.d.ts.map +1 -0
- package/{browser.ts → dist/src/core/browser.js} +4 -4
- package/dist/src/core/browser.js.map +1 -0
- package/dist/src/core/build-pet.d.ts +2 -0
- package/dist/src/core/build-pet.d.ts.map +1 -0
- package/dist/src/core/build-pet.js +364 -0
- package/dist/src/core/build-pet.js.map +1 -0
- package/dist/src/core/cli.d.ts +3 -0
- package/dist/src/core/cli.d.ts.map +1 -0
- package/dist/src/core/cli.js +244 -0
- package/dist/src/core/cli.js.map +1 -0
- package/dist/src/core/config-manager.d.ts +13 -0
- package/dist/src/core/config-manager.d.ts.map +1 -0
- package/dist/src/core/config-manager.js +59 -0
- package/dist/src/core/config-manager.js.map +1 -0
- package/dist/src/core/deploy-pet.d.ts +2 -0
- package/dist/src/core/deploy-pet.d.ts.map +1 -0
- package/dist/src/core/deploy-pet.js +66 -0
- package/dist/src/core/deploy-pet.js.map +1 -0
- package/dist/src/core/index.d.ts +11 -0
- package/dist/src/core/index.d.ts.map +1 -0
- package/dist/src/core/index.js +11 -0
- package/dist/src/core/index.js.map +1 -0
- package/dist/src/core/local-cache.d.ts +69 -0
- package/dist/src/core/local-cache.d.ts.map +1 -0
- package/dist/src/core/local-cache.js +212 -0
- package/dist/src/core/local-cache.js.map +1 -0
- package/dist/src/core/logger.d.ts.map +1 -0
- package/{logger.js → dist/src/core/logger.js} +8 -9
- package/dist/src/core/logger.js.map +1 -0
- package/dist/src/core/mcp-factory.d.ts +12 -0
- package/dist/src/core/mcp-factory.d.ts.map +1 -0
- package/dist/src/core/mcp-factory.js +143 -0
- package/dist/src/core/mcp-factory.js.map +1 -0
- package/dist/src/core/mcp-server.d.ts +3 -0
- package/dist/src/core/mcp-server.d.ts.map +1 -0
- package/dist/src/core/mcp-server.js +55 -0
- package/dist/src/core/mcp-server.js.map +1 -0
- package/dist/src/core/migrate-plugin.d.ts +15 -0
- package/dist/src/core/migrate-plugin.d.ts.map +1 -0
- package/dist/src/core/migrate-plugin.js +181 -0
- package/dist/src/core/migrate-plugin.js.map +1 -0
- package/dist/src/core/pets-registry.d.ts +47 -0
- package/dist/src/core/pets-registry.d.ts.map +1 -0
- package/dist/src/core/pets-registry.js +109 -0
- package/dist/src/core/pets-registry.js.map +1 -0
- package/dist/src/core/plugin-factory.d.ts +58 -0
- package/dist/src/core/plugin-factory.d.ts.map +1 -0
- package/dist/src/core/plugin-factory.js +212 -0
- package/dist/src/core/plugin-factory.js.map +1 -0
- package/dist/src/core/prompt-utils.d.ts +14 -0
- package/dist/src/core/prompt-utils.d.ts.map +1 -0
- package/dist/src/core/prompt-utils.js +106 -0
- package/dist/src/core/prompt-utils.js.map +1 -0
- package/dist/src/core/schema-helpers.d.ts +33 -0
- package/dist/src/core/schema-helpers.d.ts.map +1 -0
- package/dist/src/core/schema-helpers.js +46 -0
- package/dist/src/core/schema-helpers.js.map +1 -0
- package/dist/src/core/search-pets.d.ts +29 -0
- package/dist/src/core/search-pets.d.ts.map +1 -0
- package/dist/src/core/search-pets.js +196 -0
- package/dist/src/core/search-pets.js.map +1 -0
- package/dist/src/core/types.d.ts +63 -0
- package/dist/src/core/types.d.ts.map +1 -0
- package/dist/src/core/types.js +2 -0
- package/dist/src/core/types.js.map +1 -0
- package/dist/src/core/validate-pet.d.ts +40 -0
- package/dist/src/core/validate-pet.d.ts.map +1 -0
- package/dist/src/core/validate-pet.js +650 -0
- package/dist/src/core/validate-pet.js.map +1 -0
- package/package.json +8 -21
- package/ai-client-base/index.ts +0 -229
- package/build-pet.ts +0 -429
- package/cli.ts +0 -268
- package/config-manager.ts +0 -82
- package/deploy-pet.ts +0 -91
- package/index.ts +0 -10
- package/local-cache.ts +0 -280
- package/logger.ts +0 -143
- package/mcp-factory.ts +0 -180
- package/mcp-server.ts +0 -69
- package/migrate-plugin.ts +0 -220
- package/pets-registry.ts +0 -160
- package/plugin-factory.ts +0 -300
- package/prompt-utils.ts +0 -130
- package/schema-helpers.ts +0 -59
- package/search-pets.ts +0 -267
- package/types.ts +0 -68
- package/validate-pet.ts +0 -749
- /package/{logger.d.ts → dist/src/core/logger.d.ts} +0 -0
package/config-manager.ts
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs'
|
|
2
|
-
import { join } from 'path'
|
|
3
|
-
import { homedir } from 'os'
|
|
4
|
-
|
|
5
|
-
export interface PetsConfig {
|
|
6
|
-
folderHistory: Array<{
|
|
7
|
-
path: string
|
|
8
|
-
timestamp: number
|
|
9
|
-
name?: string
|
|
10
|
-
}>
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const CONFIG_DIR = join(homedir(), '.pets')
|
|
14
|
-
const CONFIG_FILE = join(CONFIG_DIR, 'config.json')
|
|
15
|
-
const MAX_HISTORY_ITEMS = 20
|
|
16
|
-
|
|
17
|
-
function ensureConfigDir(): void {
|
|
18
|
-
if (!existsSync(CONFIG_DIR)) {
|
|
19
|
-
mkdirSync(CONFIG_DIR, { recursive: true })
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function readConfig(): PetsConfig {
|
|
24
|
-
ensureConfigDir()
|
|
25
|
-
|
|
26
|
-
if (!existsSync(CONFIG_FILE)) {
|
|
27
|
-
return { folderHistory: [] }
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
try {
|
|
31
|
-
const content = readFileSync(CONFIG_FILE, 'utf-8')
|
|
32
|
-
return JSON.parse(content)
|
|
33
|
-
} catch (error) {
|
|
34
|
-
console.error('Error reading config file:', error)
|
|
35
|
-
return { folderHistory: [] }
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function writeConfig(config: PetsConfig): void {
|
|
40
|
-
ensureConfigDir()
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf-8')
|
|
44
|
-
} catch (error) {
|
|
45
|
-
console.error('Error writing config file:', error)
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function addFolderToHistory(folderPath: string): void {
|
|
50
|
-
const config = readConfig()
|
|
51
|
-
|
|
52
|
-
const existingIndex = config.folderHistory.findIndex(
|
|
53
|
-
entry => entry.path === folderPath
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
if (existingIndex !== -1) {
|
|
57
|
-
config.folderHistory.splice(existingIndex, 1)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const folderName = folderPath.split('/').pop() || folderPath
|
|
61
|
-
|
|
62
|
-
config.folderHistory.unshift({
|
|
63
|
-
path: folderPath,
|
|
64
|
-
timestamp: Date.now(),
|
|
65
|
-
name: folderName
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
if (config.folderHistory.length > MAX_HISTORY_ITEMS) {
|
|
69
|
-
config.folderHistory = config.folderHistory.slice(0, MAX_HISTORY_ITEMS)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
writeConfig(config)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export function getFolderHistory(): PetsConfig['folderHistory'] {
|
|
76
|
-
const config = readConfig()
|
|
77
|
-
return config.folderHistory
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export function clearFolderHistory(): void {
|
|
81
|
-
writeConfig({ folderHistory: [] })
|
|
82
|
-
}
|
package/deploy-pet.ts
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { join, dirname } from 'path'
|
|
2
|
-
import { fileURLToPath } from 'url'
|
|
3
|
-
import { existsSync, readdirSync, readFileSync, writeFileSync, statSync, mkdirSync } from 'fs'
|
|
4
|
-
import { buildPet } from './build-pet.js'
|
|
5
|
-
|
|
6
|
-
const __filename = fileURLToPath(import.meta.url)
|
|
7
|
-
const __dirname = dirname(__filename)
|
|
8
|
-
const projectRoot = dirname(dirname(__dirname))
|
|
9
|
-
|
|
10
|
-
interface PetData {
|
|
11
|
-
name: string
|
|
12
|
-
version: string
|
|
13
|
-
description: string
|
|
14
|
-
source_code_url: string
|
|
15
|
-
[key: string]: any
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export async function deployPet(petName?: string): Promise<void> {
|
|
19
|
-
if (!petName) {
|
|
20
|
-
const cwd = process.cwd()
|
|
21
|
-
const petsDir = join(projectRoot, 'pets')
|
|
22
|
-
|
|
23
|
-
if (cwd.includes('/pets/')) {
|
|
24
|
-
petName = cwd.split('/pets/')[1].split('/')[0]
|
|
25
|
-
console.log(`📦 Auto-detected pet: ${petName}`)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (!petName) {
|
|
29
|
-
console.error('Usage: pets deploy <pet-name>')
|
|
30
|
-
console.error('Example: pets deploy postgres')
|
|
31
|
-
console.error('')
|
|
32
|
-
console.error('Available pets:')
|
|
33
|
-
if (existsSync(petsDir)) {
|
|
34
|
-
const pets = readdirSync(petsDir).filter(dir => {
|
|
35
|
-
const petPath = join(petsDir, dir)
|
|
36
|
-
return statSync(petPath).isDirectory() && dir !== '_TEMPLATE_'
|
|
37
|
-
})
|
|
38
|
-
pets.forEach(pet => console.error(` - ${pet}`))
|
|
39
|
-
}
|
|
40
|
-
process.exit(1)
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
console.log(`🚀 Deploying ${petName}...`)
|
|
45
|
-
|
|
46
|
-
await buildPet(petName)
|
|
47
|
-
|
|
48
|
-
const petDir = join(projectRoot, 'pets', petName)
|
|
49
|
-
const packageJsonPath = join(petDir, 'package.json')
|
|
50
|
-
|
|
51
|
-
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'))
|
|
52
|
-
|
|
53
|
-
const sourceCodeUrl = `https://github.com/raggle-ai/pets/tree/main/pets/${petName}`
|
|
54
|
-
|
|
55
|
-
const fieldsToExclude = ['$schema', 'version', 'main', 'types', 'scripts', 'license', 'repository', 'dependencies', 'author', 'utils', 'devDependencies']
|
|
56
|
-
|
|
57
|
-
const filteredData = Object.keys(packageJson).reduce((acc, key) => {
|
|
58
|
-
if (!fieldsToExclude.includes(key)) {
|
|
59
|
-
acc[key] = packageJson[key]
|
|
60
|
-
}
|
|
61
|
-
return acc
|
|
62
|
-
}, {} as Record<string, any>)
|
|
63
|
-
|
|
64
|
-
const petData = {
|
|
65
|
-
...filteredData,
|
|
66
|
-
name: packageJson.name,
|
|
67
|
-
version: packageJson.version,
|
|
68
|
-
description: packageJson.description,
|
|
69
|
-
source_code_url: sourceCodeUrl,
|
|
70
|
-
} as PetData
|
|
71
|
-
|
|
72
|
-
const dataDir = join(projectRoot, 'data')
|
|
73
|
-
if (!existsSync(dataDir)) {
|
|
74
|
-
mkdirSync(dataDir, { recursive: true })
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const petsJsonPath = join(dataDir, 'pets.json')
|
|
78
|
-
let petsData: Record<string, PetData> = {}
|
|
79
|
-
|
|
80
|
-
if (existsSync(petsJsonPath)) {
|
|
81
|
-
petsData = JSON.parse(readFileSync(petsJsonPath, 'utf8'))
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
petsData[packageJson.name] = petData
|
|
85
|
-
|
|
86
|
-
writeFileSync(petsJsonPath, JSON.stringify(petsData, null, 2), 'utf8')
|
|
87
|
-
|
|
88
|
-
console.log(`✅ ${petName} deployed successfully!`)
|
|
89
|
-
console.log(` Source URL: ${sourceCodeUrl}`)
|
|
90
|
-
console.log(` Data saved to: ${petsJsonPath}`)
|
|
91
|
-
}
|
package/index.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export * from './plugin-factory'
|
|
2
|
-
export * from './schema-helpers'
|
|
3
|
-
export * from './validate-pet'
|
|
4
|
-
export * from './pets-registry'
|
|
5
|
-
export * from './build-pet'
|
|
6
|
-
export * from './types'
|
|
7
|
-
export * from './ai-client-base'
|
|
8
|
-
export * from './search-pets'
|
|
9
|
-
export * from './logger'
|
|
10
|
-
export * from './local-cache'
|
package/local-cache.ts
DELETED
|
@@ -1,280 +0,0 @@
|
|
|
1
|
-
export interface CacheEntry<T> {
|
|
2
|
-
data: T
|
|
3
|
-
timestamp: number
|
|
4
|
-
hits: number
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export interface CacheStats {
|
|
8
|
-
hits: number
|
|
9
|
-
misses: number
|
|
10
|
-
size: number
|
|
11
|
-
oldestEntry?: number
|
|
12
|
-
newestEntry?: number
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface CacheConfig {
|
|
16
|
-
ttl?: number
|
|
17
|
-
maxSize?: number
|
|
18
|
-
cleanupInterval?: number
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export class LocalCache<T = any> {
|
|
22
|
-
private cache: Map<string, CacheEntry<T>> = new Map()
|
|
23
|
-
private stats = { hits: 0, misses: 0 }
|
|
24
|
-
private ttl: number
|
|
25
|
-
private maxSize: number
|
|
26
|
-
private cleanupInterval: number | null
|
|
27
|
-
private cleanupTimer: NodeJS.Timeout | null = null
|
|
28
|
-
|
|
29
|
-
constructor(config: CacheConfig = {}) {
|
|
30
|
-
this.ttl = config.ttl || 3600000
|
|
31
|
-
this.maxSize = config.maxSize || 1000
|
|
32
|
-
this.cleanupInterval = config.cleanupInterval || null
|
|
33
|
-
|
|
34
|
-
if (this.cleanupInterval) {
|
|
35
|
-
this.startCleanup()
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
private startCleanup(): void {
|
|
40
|
-
if (this.cleanupInterval) {
|
|
41
|
-
this.cleanupTimer = setInterval(() => {
|
|
42
|
-
this.cleanup()
|
|
43
|
-
}, this.cleanupInterval)
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
private stopCleanup(): void {
|
|
48
|
-
if (this.cleanupTimer) {
|
|
49
|
-
clearInterval(this.cleanupTimer)
|
|
50
|
-
this.cleanupTimer = null
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
get(key: string): T | null {
|
|
55
|
-
const entry = this.cache.get(key)
|
|
56
|
-
|
|
57
|
-
if (!entry) {
|
|
58
|
-
this.stats.misses++
|
|
59
|
-
return null
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const now = Date.now()
|
|
63
|
-
if (now - entry.timestamp > this.ttl) {
|
|
64
|
-
this.cache.delete(key)
|
|
65
|
-
this.stats.misses++
|
|
66
|
-
return null
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
entry.hits++
|
|
70
|
-
this.stats.hits++
|
|
71
|
-
return entry.data
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
set(key: string, data: T): void {
|
|
75
|
-
if (this.cache.size >= this.maxSize && !this.cache.has(key)) {
|
|
76
|
-
this.evictOldest()
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
this.cache.set(key, {
|
|
80
|
-
data,
|
|
81
|
-
timestamp: Date.now(),
|
|
82
|
-
hits: 0
|
|
83
|
-
})
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
has(key: string): boolean {
|
|
87
|
-
const entry = this.cache.get(key)
|
|
88
|
-
if (!entry) return false
|
|
89
|
-
|
|
90
|
-
const now = Date.now()
|
|
91
|
-
if (now - entry.timestamp > this.ttl) {
|
|
92
|
-
this.cache.delete(key)
|
|
93
|
-
return false
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return true
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
delete(key: string): boolean {
|
|
100
|
-
return this.cache.delete(key)
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
clear(): void {
|
|
104
|
-
this.cache.clear()
|
|
105
|
-
this.stats = { hits: 0, misses: 0 }
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
cleanup(): number {
|
|
109
|
-
const now = Date.now()
|
|
110
|
-
let removed = 0
|
|
111
|
-
|
|
112
|
-
for (const [key, entry] of this.cache.entries()) {
|
|
113
|
-
if (now - entry.timestamp > this.ttl) {
|
|
114
|
-
this.cache.delete(key)
|
|
115
|
-
removed++
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return removed
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
private evictOldest(): void {
|
|
123
|
-
let oldestKey: string | null = null
|
|
124
|
-
let oldestTime = Infinity
|
|
125
|
-
|
|
126
|
-
for (const [key, entry] of this.cache.entries()) {
|
|
127
|
-
if (entry.timestamp < oldestTime) {
|
|
128
|
-
oldestTime = entry.timestamp
|
|
129
|
-
oldestKey = key
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
if (oldestKey) {
|
|
134
|
-
this.cache.delete(oldestKey)
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
getStats(): CacheStats {
|
|
139
|
-
const entries = Array.from(this.cache.values())
|
|
140
|
-
const timestamps = entries.map(e => e.timestamp)
|
|
141
|
-
|
|
142
|
-
return {
|
|
143
|
-
hits: this.stats.hits,
|
|
144
|
-
misses: this.stats.misses,
|
|
145
|
-
size: this.cache.size,
|
|
146
|
-
oldestEntry: timestamps.length > 0 ? Math.min(...timestamps) : undefined,
|
|
147
|
-
newestEntry: timestamps.length > 0 ? Math.max(...timestamps) : undefined
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
keys(): string[] {
|
|
152
|
-
return Array.from(this.cache.keys())
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
values(): T[] {
|
|
156
|
-
return Array.from(this.cache.values()).map(entry => entry.data)
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
entries(): Array<[string, T]> {
|
|
160
|
-
return Array.from(this.cache.entries()).map(([key, entry]) => [key, entry.data])
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
getHitRate(): number {
|
|
164
|
-
const total = this.stats.hits + this.stats.misses
|
|
165
|
-
return total === 0 ? 0 : this.stats.hits / total
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
destroy(): void {
|
|
169
|
-
this.stopCleanup()
|
|
170
|
-
this.clear()
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
export class SingleValueCache<T = any> {
|
|
175
|
-
private data: T | null = null
|
|
176
|
-
private timestamp: number = 0
|
|
177
|
-
private ttl: number
|
|
178
|
-
private hits: number = 0
|
|
179
|
-
private misses: number = 0
|
|
180
|
-
|
|
181
|
-
constructor(config: { ttl?: number } = {}) {
|
|
182
|
-
this.ttl = config.ttl || 3600000
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
get(): T | null {
|
|
186
|
-
if (!this.data) {
|
|
187
|
-
this.misses++
|
|
188
|
-
return null
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
const now = Date.now()
|
|
192
|
-
if (now - this.timestamp > this.ttl) {
|
|
193
|
-
this.data = null
|
|
194
|
-
this.misses++
|
|
195
|
-
return null
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
this.hits++
|
|
199
|
-
return this.data
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
set(data: T): void {
|
|
203
|
-
this.data = data
|
|
204
|
-
this.timestamp = Date.now()
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
has(): boolean {
|
|
208
|
-
if (!this.data) return false
|
|
209
|
-
|
|
210
|
-
const now = Date.now()
|
|
211
|
-
if (now - this.timestamp > this.ttl) {
|
|
212
|
-
this.data = null
|
|
213
|
-
return false
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
return true
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
clear(): void {
|
|
220
|
-
this.data = null
|
|
221
|
-
this.timestamp = 0
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
getAge(): number {
|
|
225
|
-
if (!this.data) return -1
|
|
226
|
-
return Date.now() - this.timestamp
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
getStats(): { hits: number; misses: number; hasData: boolean; age: number } {
|
|
230
|
-
return {
|
|
231
|
-
hits: this.hits,
|
|
232
|
-
misses: this.misses,
|
|
233
|
-
hasData: this.has(),
|
|
234
|
-
age: this.getAge()
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
getHitRate(): number {
|
|
239
|
-
const total = this.hits + this.misses
|
|
240
|
-
return total === 0 ? 0 : this.hits / total
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
export async function withCache<T>(
|
|
245
|
-
cache: LocalCache<T> | SingleValueCache<T>,
|
|
246
|
-
key: string | null,
|
|
247
|
-
fetcher: () => Promise<T>
|
|
248
|
-
): Promise<T> {
|
|
249
|
-
if (cache instanceof SingleValueCache) {
|
|
250
|
-
const cached = cache.get()
|
|
251
|
-
if (cached !== null) {
|
|
252
|
-
return cached
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
const data = await fetcher()
|
|
256
|
-
cache.set(data)
|
|
257
|
-
return data
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
if (key === null) {
|
|
261
|
-
throw new Error('Key is required for LocalCache')
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
const cached = cache.get(key)
|
|
265
|
-
if (cached !== null) {
|
|
266
|
-
return cached
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
const data = await fetcher()
|
|
270
|
-
cache.set(key, data)
|
|
271
|
-
return data
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
export function createCache<T = any>(config: CacheConfig = {}): LocalCache<T> {
|
|
275
|
-
return new LocalCache<T>(config)
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
export function createSingleValueCache<T = any>(config: { ttl?: number } = {}): SingleValueCache<T> {
|
|
279
|
-
return new SingleValueCache<T>(config)
|
|
280
|
-
}
|
package/logger.ts
DELETED
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
export enum LogLevel {
|
|
2
|
-
DEBUG = 0,
|
|
3
|
-
INFO = 1,
|
|
4
|
-
WARN = 2,
|
|
5
|
-
ERROR = 3,
|
|
6
|
-
NONE = 4
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const LOG_LEVEL_NAMES: Record<LogLevel, string> = {
|
|
10
|
-
[LogLevel.DEBUG]: 'DEBUG',
|
|
11
|
-
[LogLevel.INFO]: 'INFO',
|
|
12
|
-
[LogLevel.WARN]: 'WARN',
|
|
13
|
-
[LogLevel.ERROR]: 'ERROR',
|
|
14
|
-
[LogLevel.NONE]: 'NONE'
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
interface LoggerOptions {
|
|
18
|
-
namespace: string
|
|
19
|
-
level?: LogLevel
|
|
20
|
-
enabled?: boolean
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export class Logger {
|
|
24
|
-
private namespace: string
|
|
25
|
-
private level: LogLevel
|
|
26
|
-
private enabled: boolean
|
|
27
|
-
|
|
28
|
-
constructor(options: LoggerOptions) {
|
|
29
|
-
this.namespace = options.namespace
|
|
30
|
-
this.enabled = options.enabled ?? this.detectLoggingEnabled()
|
|
31
|
-
this.level = options.level ?? this.detectLogLevel()
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
private detectLoggingEnabled(): boolean {
|
|
35
|
-
return process.env.ENABLE_LOGGING === 'true' ||
|
|
36
|
-
process.env.DEBUG === 'true' ||
|
|
37
|
-
process.argv.includes('--print-logs')
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
private detectLogLevel(): LogLevel {
|
|
41
|
-
const envLevel = process.env.LOG_LEVEL?.toUpperCase()
|
|
42
|
-
const argLevel = this.getArgLogLevel()
|
|
43
|
-
|
|
44
|
-
const levelStr = argLevel || envLevel || 'INFO'
|
|
45
|
-
|
|
46
|
-
switch (levelStr) {
|
|
47
|
-
case 'DEBUG':
|
|
48
|
-
return LogLevel.DEBUG
|
|
49
|
-
case 'INFO':
|
|
50
|
-
return LogLevel.INFO
|
|
51
|
-
case 'WARN':
|
|
52
|
-
return LogLevel.WARN
|
|
53
|
-
case 'ERROR':
|
|
54
|
-
return LogLevel.ERROR
|
|
55
|
-
case 'NONE':
|
|
56
|
-
return LogLevel.NONE
|
|
57
|
-
default:
|
|
58
|
-
return LogLevel.INFO
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
private getArgLogLevel(): string | undefined {
|
|
63
|
-
const logLevelIndex = process.argv.indexOf('--log-level')
|
|
64
|
-
if (logLevelIndex !== -1 && process.argv[logLevelIndex + 1]) {
|
|
65
|
-
return process.argv[logLevelIndex + 1].toUpperCase()
|
|
66
|
-
}
|
|
67
|
-
return undefined
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
private shouldLog(level: LogLevel): boolean {
|
|
71
|
-
return this.enabled && level >= this.level
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
private formatTimestamp(): string {
|
|
75
|
-
const now = new Date()
|
|
76
|
-
const year = now.getFullYear()
|
|
77
|
-
const month = String(now.getMonth() + 1).padStart(2, '0')
|
|
78
|
-
const day = String(now.getDate()).padStart(2, '0')
|
|
79
|
-
const hours = String(now.getHours()).padStart(2, '0')
|
|
80
|
-
const minutes = String(now.getMinutes()).padStart(2, '0')
|
|
81
|
-
const seconds = String(now.getSeconds()).padStart(2, '0')
|
|
82
|
-
return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}`
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
private formatMessage(level: LogLevel, message: string, ...args: any[]): string {
|
|
86
|
-
const timestamp = this.formatTimestamp()
|
|
87
|
-
const levelName = LOG_LEVEL_NAMES[level].padEnd(5, ' ')
|
|
88
|
-
const prefix = `${levelName} ${timestamp} service=${this.namespace}`
|
|
89
|
-
|
|
90
|
-
if (args.length === 0) {
|
|
91
|
-
return `${prefix} ${message}`
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const formattedArgs = args.map(arg => {
|
|
95
|
-
if (typeof arg === 'object') {
|
|
96
|
-
return JSON.stringify(arg, null, 2)
|
|
97
|
-
}
|
|
98
|
-
return String(arg)
|
|
99
|
-
}).join(' ')
|
|
100
|
-
|
|
101
|
-
return `${prefix} ${message} ${formattedArgs}`
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
debug(message: string, ...args: any[]): void {
|
|
105
|
-
if (this.shouldLog(LogLevel.DEBUG)) {
|
|
106
|
-
console.log(this.formatMessage(LogLevel.DEBUG, message, ...args))
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
info(message: string, ...args: any[]): void {
|
|
111
|
-
if (this.shouldLog(LogLevel.INFO)) {
|
|
112
|
-
console.log(this.formatMessage(LogLevel.INFO, message, ...args))
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
warn(message: string, ...args: any[]): void {
|
|
117
|
-
if (this.shouldLog(LogLevel.WARN)) {
|
|
118
|
-
console.warn(this.formatMessage(LogLevel.WARN, message, ...args))
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
error(message: string, ...args: any[]): void {
|
|
123
|
-
if (this.shouldLog(LogLevel.ERROR)) {
|
|
124
|
-
console.error(this.formatMessage(LogLevel.ERROR, message, ...args))
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
child(subNamespace: string): Logger {
|
|
129
|
-
return new Logger({
|
|
130
|
-
namespace: `${this.namespace}:${subNamespace}`,
|
|
131
|
-
level: this.level,
|
|
132
|
-
enabled: this.enabled
|
|
133
|
-
})
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export function createLogger(namespace: string, options?: Partial<LoggerOptions>): Logger {
|
|
138
|
-
return new Logger({
|
|
139
|
-
namespace,
|
|
140
|
-
level: options?.level,
|
|
141
|
-
enabled: options?.enabled
|
|
142
|
-
})
|
|
143
|
-
}
|