codebuddy-stats 1.1.0 → 1.1.1
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/index.js +0 -1
- package/dist/lib/data-loader.js +0 -1
- package/dist/lib/paths.js +0 -1
- package/dist/lib/pricing.js +0 -1
- package/dist/lib/utils.js +0 -1
- package/dist/lib/workspace-resolver.js +0 -1
- package/package.json +4 -1
- package/.github/workflows/publish.yml +0 -41
- package/dist/index.js.map +0 -1
- package/dist/lib/data-loader.js.map +0 -1
- package/dist/lib/paths.js.map +0 -1
- package/dist/lib/pricing.js.map +0 -1
- package/dist/lib/utils.js.map +0 -1
- package/dist/lib/workspace-resolver.js.map +0 -1
- package/src/index.ts +0 -615
- package/src/lib/data-loader.ts +0 -581
- package/src/lib/paths.ts +0 -70
- package/src/lib/pricing.ts +0 -128
- package/src/lib/utils.ts +0 -61
- package/src/lib/workspace-resolver.ts +0 -235
- package/tsconfig.json +0 -25
package/src/lib/pricing.ts
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
export interface PricingTier {
|
|
2
|
-
limit: number
|
|
3
|
-
pricePerMTok: number
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export interface ModelPricing {
|
|
7
|
-
prompt: PricingTier[]
|
|
8
|
-
completion: PricingTier[]
|
|
9
|
-
cacheRead: PricingTier[]
|
|
10
|
-
cacheWrite: PricingTier[]
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// 模型价格 (USD / 1M tokens)
|
|
14
|
-
function createPricing(
|
|
15
|
-
inputPrice: number,
|
|
16
|
-
cachedInputPrice: number,
|
|
17
|
-
outputPrice: number,
|
|
18
|
-
cacheWritePrice?: number
|
|
19
|
-
): ModelPricing {
|
|
20
|
-
return {
|
|
21
|
-
prompt: [{ limit: Number.POSITIVE_INFINITY, pricePerMTok: inputPrice }],
|
|
22
|
-
completion: [{ limit: Number.POSITIVE_INFINITY, pricePerMTok: outputPrice }],
|
|
23
|
-
cacheRead: [{ limit: Number.POSITIVE_INFINITY, pricePerMTok: cachedInputPrice }],
|
|
24
|
-
cacheWrite: [
|
|
25
|
-
{ limit: Number.POSITIVE_INFINITY, pricePerMTok: cacheWritePrice ?? inputPrice },
|
|
26
|
-
],
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export const MODEL_PRICING: Record<string, ModelPricing> = {
|
|
31
|
-
'gpt-5.2': createPricing(1.75, 0.175, 14.0),
|
|
32
|
-
'gpt-5.1': createPricing(1.25, 0.125, 10.0),
|
|
33
|
-
'gpt-5': createPricing(1.25, 0.125, 10.0),
|
|
34
|
-
'gpt-5-mini': createPricing(0.25, 0.025, 2.0),
|
|
35
|
-
'gpt-5-nano': createPricing(0.05, 0.005, 0.4),
|
|
36
|
-
'gpt-5.1-chat-latest': createPricing(1.25, 0.125, 10.0),
|
|
37
|
-
'gpt-5-chat-latest': createPricing(1.25, 0.125, 10.0),
|
|
38
|
-
'gpt-5.1-codex': createPricing(1.25, 0.125, 10.0),
|
|
39
|
-
'gpt-5-codex': createPricing(1.25, 0.125, 10.0),
|
|
40
|
-
|
|
41
|
-
'claude-opus-4.5': createPricing(5.0, 0.5, 25.0, 10.0),
|
|
42
|
-
|
|
43
|
-
'claude-4.5': {
|
|
44
|
-
prompt: [
|
|
45
|
-
{ limit: 200_000, pricePerMTok: 3.0 },
|
|
46
|
-
{ limit: Number.POSITIVE_INFINITY, pricePerMTok: 6.0 },
|
|
47
|
-
],
|
|
48
|
-
completion: [
|
|
49
|
-
{ limit: 200_000, pricePerMTok: 15.0 },
|
|
50
|
-
{ limit: Number.POSITIVE_INFINITY, pricePerMTok: 22.5 },
|
|
51
|
-
],
|
|
52
|
-
cacheRead: [
|
|
53
|
-
{ limit: 200_000, pricePerMTok: 0.3 },
|
|
54
|
-
{ limit: Number.POSITIVE_INFINITY, pricePerMTok: 0.6 },
|
|
55
|
-
],
|
|
56
|
-
cacheWrite: [
|
|
57
|
-
{ limit: 200_000, pricePerMTok: 6.0 },
|
|
58
|
-
{ limit: Number.POSITIVE_INFINITY, pricePerMTok: 12.0 },
|
|
59
|
-
],
|
|
60
|
-
},
|
|
61
|
-
|
|
62
|
-
'gemini-3-pro': {
|
|
63
|
-
prompt: [
|
|
64
|
-
{ limit: 200_000, pricePerMTok: 2.0 },
|
|
65
|
-
{ limit: Number.POSITIVE_INFINITY, pricePerMTok: 4.0 },
|
|
66
|
-
],
|
|
67
|
-
completion: [
|
|
68
|
-
{ limit: 200_000, pricePerMTok: 12.0 },
|
|
69
|
-
{ limit: Number.POSITIVE_INFINITY, pricePerMTok: 18.0 },
|
|
70
|
-
],
|
|
71
|
-
cacheRead: [
|
|
72
|
-
{ limit: 200_000, pricePerMTok: 0.2 },
|
|
73
|
-
{ limit: Number.POSITIVE_INFINITY, pricePerMTok: 0.4 },
|
|
74
|
-
],
|
|
75
|
-
cacheWrite: [
|
|
76
|
-
{ limit: 200_000, pricePerMTok: 0.2 },
|
|
77
|
-
{ limit: Number.POSITIVE_INFINITY, pricePerMTok: 0.4 },
|
|
78
|
-
],
|
|
79
|
-
},
|
|
80
|
-
|
|
81
|
-
'gemini-2.5-pro': {
|
|
82
|
-
prompt: [
|
|
83
|
-
{ limit: 200_000, pricePerMTok: 1.25 },
|
|
84
|
-
{ limit: Number.POSITIVE_INFINITY, pricePerMTok: 2.5 },
|
|
85
|
-
],
|
|
86
|
-
completion: [
|
|
87
|
-
{ limit: 200_000, pricePerMTok: 10.0 },
|
|
88
|
-
{ limit: Number.POSITIVE_INFINITY, pricePerMTok: 15.0 },
|
|
89
|
-
],
|
|
90
|
-
cacheRead: [
|
|
91
|
-
{ limit: 200_000, pricePerMTok: 0.125 },
|
|
92
|
-
{ limit: Number.POSITIVE_INFINITY, pricePerMTok: 0.25 },
|
|
93
|
-
],
|
|
94
|
-
cacheWrite: [
|
|
95
|
-
{ limit: 200_000, pricePerMTok: 0.125 },
|
|
96
|
-
{ limit: Number.POSITIVE_INFINITY, pricePerMTok: 0.25 },
|
|
97
|
-
],
|
|
98
|
-
},
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export const DEFAULT_MODEL_ID = 'gpt-5.1' as const
|
|
102
|
-
|
|
103
|
-
export function selectTierPrice(tokens: number, tiers: PricingTier[]): number {
|
|
104
|
-
if (tokens <= 0) return tiers[0]?.pricePerMTok ?? 0
|
|
105
|
-
for (const tier of tiers) {
|
|
106
|
-
if (tokens <= tier.limit) {
|
|
107
|
-
return tier.pricePerMTok
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
return tiers[tiers.length - 1]?.pricePerMTok ?? 0
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export function tokensToCost(tokens: number, tiers: PricingTier[]): number {
|
|
114
|
-
if (!tokens) return 0
|
|
115
|
-
const price = selectTierPrice(tokens, tiers)
|
|
116
|
-
return (tokens / 1_000_000) * price
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export function getPricingForModel(modelId: string | null | undefined): ModelPricing {
|
|
120
|
-
if (modelId && MODEL_PRICING[modelId]) {
|
|
121
|
-
return MODEL_PRICING[modelId]
|
|
122
|
-
}
|
|
123
|
-
const fallback = MODEL_PRICING[DEFAULT_MODEL_ID]
|
|
124
|
-
if (!fallback) {
|
|
125
|
-
throw new Error(`Missing pricing for default model: ${DEFAULT_MODEL_ID}`)
|
|
126
|
-
}
|
|
127
|
-
return fallback
|
|
128
|
-
}
|
package/src/lib/utils.ts
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 格式化数字,添加千分位分隔符
|
|
3
|
-
*/
|
|
4
|
-
export function formatNumber(num: number | string | null | undefined): string {
|
|
5
|
-
const n = typeof num === 'number' ? num : Number(num ?? 0)
|
|
6
|
-
if (!Number.isFinite(n)) return '0'
|
|
7
|
-
return n.toLocaleString('en-US')
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* 格式化金额
|
|
12
|
-
*/
|
|
13
|
-
export function formatCost(cost: number): string {
|
|
14
|
-
const n = Number.isFinite(cost) ? cost : 0
|
|
15
|
-
return `$${n.toFixed(2)}`
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* 格式化 tokens 数量 (K/M/B)
|
|
20
|
-
*/
|
|
21
|
-
export function formatTokens(tokens: number): string {
|
|
22
|
-
if (tokens >= 1_000_000_000) {
|
|
23
|
-
return `${(tokens / 1_000_000_000).toFixed(1)}B`
|
|
24
|
-
}
|
|
25
|
-
if (tokens >= 1_000_000) {
|
|
26
|
-
return `${(tokens / 1_000_000).toFixed(1)}M`
|
|
27
|
-
}
|
|
28
|
-
if (tokens >= 1_000) {
|
|
29
|
-
return `${(tokens / 1_000).toFixed(1)}K`
|
|
30
|
-
}
|
|
31
|
-
return String(tokens)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* 格式化百分比
|
|
36
|
-
*/
|
|
37
|
-
export function formatPercent(ratio: number): string {
|
|
38
|
-
return `${(ratio * 100).toFixed(1)}%`
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* 截断字符串
|
|
43
|
-
*/
|
|
44
|
-
export function truncate(str: string, maxLen: number): string {
|
|
45
|
-
if (str.length <= maxLen) return str
|
|
46
|
-
return str.slice(0, maxLen - 3) + '...'
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* 右对齐字符串
|
|
51
|
-
*/
|
|
52
|
-
export function padLeft(str: string, len: number): string {
|
|
53
|
-
return str.padStart(len)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* 左对齐字符串
|
|
58
|
-
*/
|
|
59
|
-
export function padRight(str: string, len: number): string {
|
|
60
|
-
return str.padEnd(len)
|
|
61
|
-
}
|
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs/promises'
|
|
2
|
-
import fsSync from 'node:fs'
|
|
3
|
-
import path from 'node:path'
|
|
4
|
-
import os from 'node:os'
|
|
5
|
-
import crypto from 'node:crypto'
|
|
6
|
-
|
|
7
|
-
import { getWorkspaceStorageDir } from './paths.js'
|
|
8
|
-
|
|
9
|
-
export interface WorkspaceMapping {
|
|
10
|
-
hash: string
|
|
11
|
-
folderUri: string
|
|
12
|
-
displayPath: string
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// 缓存已解析的 CodeBuddy Code 路径名
|
|
16
|
-
const codePathCache = new Map<string, string>()
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* 从 folder URI 提取纯路径(用于计算 MD5)
|
|
20
|
-
*/
|
|
21
|
-
function extractPathFromUri(folderUri: string): string | null {
|
|
22
|
-
// 处理本地文件路径: file:///path/to/folder
|
|
23
|
-
if (folderUri.startsWith('file://')) {
|
|
24
|
-
try {
|
|
25
|
-
const url = new URL(folderUri)
|
|
26
|
-
return decodeURIComponent(url.pathname)
|
|
27
|
-
} catch {
|
|
28
|
-
return decodeURIComponent(folderUri.replace('file://', ''))
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// 处理远程路径: vscode-remote://codebuddy-remote-ssh%2B.../path
|
|
33
|
-
if (folderUri.startsWith('vscode-remote://')) {
|
|
34
|
-
try {
|
|
35
|
-
const url = new URL(folderUri)
|
|
36
|
-
return decodeURIComponent(url.pathname)
|
|
37
|
-
} catch {
|
|
38
|
-
const match = folderUri.match(/vscode-remote:\/\/[^/]+(.+)$/)
|
|
39
|
-
if (match?.[1]) {
|
|
40
|
-
return decodeURIComponent(match[1])
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return null
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* 格式化路径用于显示(简化 home 目录)
|
|
50
|
-
*/
|
|
51
|
-
function formatDisplayPath(p: string): string {
|
|
52
|
-
const home = os.homedir()
|
|
53
|
-
if (p.startsWith(home)) {
|
|
54
|
-
return '~' + p.slice(home.length)
|
|
55
|
-
}
|
|
56
|
-
return p
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* 从 folder URI 生成用于显示的友好路径
|
|
61
|
-
*/
|
|
62
|
-
function getDisplayPath(folderUri: string): string {
|
|
63
|
-
// 本地路径
|
|
64
|
-
if (folderUri.startsWith('file://')) {
|
|
65
|
-
const p = extractPathFromUri(folderUri)
|
|
66
|
-
if (p) {
|
|
67
|
-
return formatDisplayPath(p)
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// 远程路径
|
|
72
|
-
if (folderUri.startsWith('vscode-remote://')) {
|
|
73
|
-
const p = extractPathFromUri(folderUri)
|
|
74
|
-
if (p) {
|
|
75
|
-
const hostMatch = folderUri.match(/vscode-remote:\/\/codebuddy-remote-ssh%2B([^/]+)/)
|
|
76
|
-
if (hostMatch?.[1]) {
|
|
77
|
-
let host = decodeURIComponent(hostMatch[1])
|
|
78
|
-
host = host.replace(/_x([0-9a-fA-F]{2})_/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
|
|
79
|
-
host = host.replace(/\\x([0-9a-fA-F]{2})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
|
|
80
|
-
if (host.includes('@')) {
|
|
81
|
-
const parts = host.split('@')
|
|
82
|
-
host = parts[parts.length - 1]?.split(':')[0] || host
|
|
83
|
-
}
|
|
84
|
-
if (host.length > 20) {
|
|
85
|
-
host = host.slice(0, 17) + '...'
|
|
86
|
-
}
|
|
87
|
-
return `[${host}]${p}`
|
|
88
|
-
}
|
|
89
|
-
return `[remote]${p}`
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return folderUri
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* 计算路径的 MD5 hash(CodeBuddyExtension 使用纯路径计算)
|
|
98
|
-
*/
|
|
99
|
-
function computePathHash(p: string): string {
|
|
100
|
-
return crypto.createHash('md5').update(p).digest('hex')
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* 加载所有工作区映射
|
|
105
|
-
*/
|
|
106
|
-
export async function loadWorkspaceMappings(): Promise<Map<string, WorkspaceMapping>> {
|
|
107
|
-
const mappings = new Map<string, WorkspaceMapping>()
|
|
108
|
-
const storageDir = getWorkspaceStorageDir()
|
|
109
|
-
|
|
110
|
-
let entries: fsSync.Dirent[] = []
|
|
111
|
-
try {
|
|
112
|
-
entries = await fs.readdir(storageDir, { withFileTypes: true })
|
|
113
|
-
} catch {
|
|
114
|
-
return mappings
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
for (const entry of entries) {
|
|
118
|
-
if (!entry.isDirectory()) continue
|
|
119
|
-
|
|
120
|
-
const workspaceJsonPath = path.join(storageDir, entry.name, 'workspace.json')
|
|
121
|
-
try {
|
|
122
|
-
const content = await fs.readFile(workspaceJsonPath, 'utf8')
|
|
123
|
-
const data = JSON.parse(content) as { folder?: string }
|
|
124
|
-
const folderUri = data.folder
|
|
125
|
-
if (!folderUri) continue
|
|
126
|
-
|
|
127
|
-
const extractedPath = extractPathFromUri(folderUri)
|
|
128
|
-
if (!extractedPath) continue
|
|
129
|
-
|
|
130
|
-
const hash = computePathHash(extractedPath)
|
|
131
|
-
const displayPath = getDisplayPath(folderUri)
|
|
132
|
-
|
|
133
|
-
mappings.set(hash, { hash, folderUri, displayPath })
|
|
134
|
-
} catch {
|
|
135
|
-
// 跳过无法读取的文件
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return mappings
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* 检查路径是否存在(同步版本,用于路径探测)
|
|
144
|
-
*/
|
|
145
|
-
function pathExistsSync(p: string): boolean {
|
|
146
|
-
try {
|
|
147
|
-
fsSync.accessSync(p)
|
|
148
|
-
return true
|
|
149
|
-
} catch {
|
|
150
|
-
return false
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* 尝试将 CodeBuddy Code 的项目名(路径中 / 替换为 -)还原为真实路径
|
|
156
|
-
* 使用回溯搜索,因为目录名本身可能包含 -
|
|
157
|
-
*
|
|
158
|
-
* 例如: "Users-anoti-Documents-project-codebudy-cost-analyzer"
|
|
159
|
-
* -> "/Users/anoti/Documents/project/codebudy-cost-analyzer"
|
|
160
|
-
*/
|
|
161
|
-
function tryResolveCodePath(name: string): string | null {
|
|
162
|
-
// 检查缓存
|
|
163
|
-
const cached = codePathCache.get(name)
|
|
164
|
-
if (cached !== undefined) {
|
|
165
|
-
return cached || null
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const parts = name.split('-')
|
|
169
|
-
if (parts.length < 2) {
|
|
170
|
-
codePathCache.set(name, '')
|
|
171
|
-
return null
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// 回溯搜索:尝试不同的分割方式
|
|
175
|
-
function backtrack(index: number, currentPath: string): string | null {
|
|
176
|
-
if (index >= parts.length) {
|
|
177
|
-
// 检查完整路径是否存在
|
|
178
|
-
if (pathExistsSync(currentPath)) {
|
|
179
|
-
return currentPath
|
|
180
|
-
}
|
|
181
|
-
return null
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// 尝试从当前位置开始,合并不同数量的 parts
|
|
185
|
-
for (let end = index; end < parts.length; end++) {
|
|
186
|
-
const segment = parts.slice(index, end + 1).join('-')
|
|
187
|
-
const newPath = currentPath ? `${currentPath}/${segment}` : `/${segment}`
|
|
188
|
-
|
|
189
|
-
// 如果这不是最后一段,检查目录是否存在
|
|
190
|
-
if (end < parts.length - 1) {
|
|
191
|
-
if (pathExistsSync(newPath)) {
|
|
192
|
-
const result = backtrack(end + 1, newPath)
|
|
193
|
-
if (result) return result
|
|
194
|
-
}
|
|
195
|
-
} else {
|
|
196
|
-
// 最后一段,检查完整路径
|
|
197
|
-
if (pathExistsSync(newPath)) {
|
|
198
|
-
return newPath
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
return null
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
const result = backtrack(0, '')
|
|
207
|
-
codePathCache.set(name, result || '')
|
|
208
|
-
return result
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* 解析项目名称
|
|
213
|
-
* - MD5 hash (32位十六进制): 从 IDE workspaceMappings 查找
|
|
214
|
-
* - 路径格式 (包含 -): 尝试还原 CodeBuddy Code 的路径格式
|
|
215
|
-
*/
|
|
216
|
-
export function resolveProjectName(name: string, mappings?: Map<string, WorkspaceMapping>): string {
|
|
217
|
-
// IDE source: MD5 hash
|
|
218
|
-
if (mappings && /^[a-f0-9]{32}$/.test(name)) {
|
|
219
|
-
const mapping = mappings.get(name)
|
|
220
|
-
if (mapping) {
|
|
221
|
-
return mapping.displayPath
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// Code source: 路径中 / 替换为 - 的格式
|
|
226
|
-
// 特征:以大写字母开头(如 Users-、home-),包含 -
|
|
227
|
-
if (/^[A-Za-z]/.test(name) && name.includes('-')) {
|
|
228
|
-
const resolved = tryResolveCodePath(name)
|
|
229
|
-
if (resolved) {
|
|
230
|
-
return formatDisplayPath(resolved)
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
return name
|
|
235
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"target": "ES2022",
|
|
5
|
-
"lib": ["ES2022"],
|
|
6
|
-
|
|
7
|
-
"module": "NodeNext",
|
|
8
|
-
"moduleResolution": "NodeNext",
|
|
9
|
-
"verbatimModuleSyntax": true,
|
|
10
|
-
|
|
11
|
-
"rootDir": "./src",
|
|
12
|
-
"outDir": "./dist",
|
|
13
|
-
|
|
14
|
-
"strict": true,
|
|
15
|
-
"noUncheckedIndexedAccess": true,
|
|
16
|
-
|
|
17
|
-
"esModuleInterop": true,
|
|
18
|
-
"resolveJsonModule": true,
|
|
19
|
-
"skipLibCheck": true,
|
|
20
|
-
|
|
21
|
-
"sourceMap": true
|
|
22
|
-
},
|
|
23
|
-
"include": ["src/**/*"],
|
|
24
|
-
"exclude": ["node_modules", "dist"]
|
|
25
|
-
}
|