@talex-touch/utils 1.0.40 → 1.0.44
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/.eslintcache +1 -0
- package/__tests__/cloud-sync-sdk.test.ts +442 -0
- package/__tests__/icons/icons.test.ts +84 -0
- package/__tests__/plugin-sdk-lifecycle.test.ts +130 -0
- package/__tests__/power-sdk.test.ts +143 -0
- package/__tests__/preset-export-types.test.ts +108 -0
- package/__tests__/search/fuzzy-match.test.ts +137 -0
- package/__tests__/transport/port-policy.test.ts +44 -0
- package/__tests__/transport-domain-sdks.test.ts +152 -0
- package/__tests__/types/update.test.ts +67 -0
- package/account/account-sdk.ts +915 -0
- package/account/index.ts +2 -0
- package/account/types.ts +321 -0
- package/analytics/client.ts +136 -0
- package/analytics/index.ts +2 -0
- package/analytics/types.ts +156 -0
- package/animation/auto-resize.ts +322 -0
- package/animation/window-node.ts +26 -19
- package/auth/clerk-types.ts +12 -30
- package/auth/index.ts +0 -2
- package/auth/useAuthState.ts +6 -14
- package/base/index.ts +2 -0
- package/base/log-level.ts +105 -0
- package/channel/index.ts +170 -69
- package/cloud-sync/cloud-sync-sdk.ts +450 -0
- package/cloud-sync/index.ts +1 -0
- package/common/file-scan-utils.ts +17 -9
- package/common/index.ts +4 -0
- package/common/logger/index.ts +46 -0
- package/common/logger/logger-manager.ts +303 -0
- package/common/logger/module-logger.ts +270 -0
- package/common/logger/transport-logger.ts +234 -0
- package/common/logger/types.ts +93 -0
- package/common/search/gather.ts +48 -6
- package/common/search/index.ts +8 -0
- package/common/storage/constants.ts +13 -0
- package/common/storage/entity/app-settings.ts +245 -0
- package/common/storage/entity/index.ts +3 -0
- package/common/storage/entity/layout-atom-types.ts +147 -0
- package/common/storage/entity/openers.ts +1 -0
- package/common/storage/entity/preset-cloud-api.ts +132 -0
- package/common/storage/entity/preset-export-types.ts +256 -0
- package/common/storage/entity/shortcut-settings.ts +1 -0
- package/common/storage/shortcut-storage.ts +11 -0
- package/common/utils/clone-diagnostics.ts +105 -0
- package/common/utils/file.ts +16 -8
- package/common/utils/index.ts +6 -2
- package/common/utils/payload-preview.ts +173 -0
- package/common/utils/polling.ts +167 -13
- package/common/utils/safe-path.ts +103 -0
- package/common/utils/safe-shell.ts +115 -0
- package/common/utils/task-queue.ts +4 -1
- package/core-box/builder/tuff-builder.ts +0 -1
- package/core-box/index.ts +1 -1
- package/core-box/recommendation.ts +38 -1
- package/core-box/tuff/tuff-dsl.ts +97 -0
- package/electron/download-manager.ts +10 -7
- package/electron/env-tool.ts +42 -40
- package/electron/index.ts +0 -1
- package/env/index.ts +156 -0
- package/eslint.config.js +55 -0
- package/i18n/index.ts +62 -0
- package/i18n/locales/en.json +226 -0
- package/i18n/locales/zh.json +226 -0
- package/i18n/message-keys.ts +236 -0
- package/i18n/resolver.ts +181 -0
- package/icons/index.ts +257 -0
- package/icons/svg.ts +69 -0
- package/index.ts +9 -1
- package/intelligence/client.ts +72 -42
- package/market/constants.ts +21 -3
- package/market/index.ts +1 -1
- package/market/types.ts +20 -5
- package/package.json +15 -5
- package/permission/index.ts +143 -46
- package/permission/legacy.ts +26 -0
- package/permission/registry.ts +304 -0
- package/permission/types.ts +164 -0
- package/plugin/channel.ts +68 -39
- package/plugin/index.ts +82 -8
- package/plugin/install.ts +3 -0
- package/plugin/log/types.ts +22 -5
- package/plugin/node/logger-manager.ts +11 -3
- package/plugin/node/logger.ts +24 -17
- package/plugin/preload.ts +25 -2
- package/plugin/providers/index.ts +4 -0
- package/plugin/providers/market-client.ts +218 -0
- package/plugin/providers/npm-provider.ts +228 -0
- package/plugin/providers/tpex-provider.ts +297 -0
- package/plugin/providers/tpex-types.ts +34 -0
- package/plugin/sdk/box-items.ts +14 -0
- package/plugin/sdk/box-sdk.ts +64 -0
- package/plugin/sdk/channel.ts +119 -4
- package/plugin/sdk/clipboard.ts +26 -12
- package/plugin/sdk/cloud-sync.ts +113 -0
- package/plugin/sdk/common.ts +19 -11
- package/plugin/sdk/core-box.ts +6 -15
- package/plugin/sdk/division-box.ts +160 -65
- package/plugin/sdk/examples/storage-onDidChange-example.js +5 -2
- package/plugin/sdk/feature-sdk.ts +111 -76
- package/plugin/sdk/flow.ts +146 -45
- package/plugin/sdk/hooks/bridge.ts +113 -49
- package/plugin/sdk/hooks/life-cycle.ts +35 -16
- package/plugin/sdk/index.ts +14 -3
- package/plugin/sdk/intelligence.ts +87 -0
- package/plugin/sdk/meta/README.md +179 -0
- package/plugin/sdk/meta-sdk.ts +244 -0
- package/plugin/sdk/notification.ts +9 -0
- package/plugin/sdk/performance.ts +1 -16
- package/plugin/sdk/plugin-info.ts +64 -0
- package/plugin/sdk/power.ts +155 -0
- package/plugin/sdk/recommend.ts +21 -0
- package/plugin/sdk/service/index.ts +12 -8
- package/plugin/sdk/sqlite.ts +141 -0
- package/plugin/sdk/storage.ts +2 -6
- package/plugin/sdk/system.ts +2 -9
- package/plugin/sdk/temp-files.ts +41 -0
- package/plugin/sdk/touch-sdk.ts +18 -0
- package/plugin/sdk/types.ts +44 -4
- package/plugin/sdk/window/index.ts +12 -9
- package/plugin/sdk-version.ts +231 -0
- package/preload/renderer.ts +3 -2
- package/renderer/hooks/arg-mapper.ts +34 -6
- package/renderer/hooks/index.ts +13 -0
- package/renderer/hooks/initialize.ts +2 -1
- package/renderer/hooks/use-agent-market-sdk.ts +7 -0
- package/renderer/hooks/use-agent-market.ts +106 -0
- package/renderer/hooks/use-agents-sdk.ts +7 -0
- package/renderer/hooks/use-app-sdk.ts +7 -0
- package/renderer/hooks/use-channel.ts +33 -4
- package/renderer/hooks/use-download-sdk.ts +21 -0
- package/renderer/hooks/use-intelligence-sdk.ts +7 -0
- package/renderer/hooks/use-intelligence-stats.ts +290 -0
- package/renderer/hooks/use-intelligence.ts +202 -104
- package/renderer/hooks/use-market-sdk.ts +16 -0
- package/renderer/hooks/use-notification-sdk.ts +7 -0
- package/renderer/hooks/use-permission-sdk.ts +7 -0
- package/renderer/hooks/use-permission.ts +325 -0
- package/renderer/hooks/use-platform-sdk.ts +7 -0
- package/renderer/hooks/use-plugin-sdk.ts +16 -0
- package/renderer/hooks/use-settings-sdk.ts +7 -0
- package/renderer/hooks/use-update-sdk.ts +21 -0
- package/renderer/index.ts +1 -0
- package/renderer/ref.ts +19 -10
- package/renderer/shared/components/SharedPluginDetailContent.vue +84 -0
- package/renderer/shared/components/SharedPluginDetailHeader.vue +116 -0
- package/renderer/shared/components/SharedPluginDetailMetaList.vue +39 -0
- package/renderer/shared/components/SharedPluginDetailReadme.vue +45 -0
- package/renderer/shared/components/SharedPluginDetailVersions.vue +98 -0
- package/renderer/shared/components/index.ts +5 -0
- package/renderer/shared/components/shims-vue.d.ts +5 -0
- package/renderer/shared/index.ts +2 -0
- package/renderer/shared/plugin-detail.ts +62 -0
- package/renderer/storage/app-settings.ts +3 -1
- package/renderer/storage/base-storage.ts +508 -82
- package/renderer/storage/intelligence-storage.ts +37 -46
- package/renderer/storage/openers.ts +3 -1
- package/renderer/storage/storage-subscription.ts +126 -42
- package/renderer/touch-sdk/env.ts +10 -10
- package/renderer/touch-sdk/index.ts +114 -18
- package/renderer/touch-sdk/terminal.ts +24 -13
- package/search/feature-matcher.ts +279 -0
- package/search/fuzzy-match.ts +64 -34
- package/search/index.ts +10 -0
- package/search/levenshtein-utils.ts +17 -11
- package/transport/errors.ts +310 -0
- package/transport/event/builder.ts +378 -0
- package/transport/event/index.ts +7 -0
- package/transport/event/types.ts +292 -0
- package/transport/events/index.ts +2670 -0
- package/transport/events/meta-overlay.ts +79 -0
- package/transport/events/types/agents.ts +177 -0
- package/transport/events/types/app-index.ts +9 -0
- package/transport/events/types/app.ts +475 -0
- package/transport/events/types/box-item.ts +222 -0
- package/transport/events/types/clipboard.ts +80 -0
- package/transport/events/types/core-box.ts +534 -0
- package/transport/events/types/device-idle.ts +7 -0
- package/transport/events/types/division-box.ts +99 -0
- package/transport/events/types/download.ts +115 -0
- package/transport/events/types/file-index.ts +73 -0
- package/transport/events/types/flow.ts +149 -0
- package/transport/events/types/index.ts +70 -0
- package/transport/events/types/market.ts +39 -0
- package/transport/events/types/meta-overlay.ts +184 -0
- package/transport/events/types/notification.ts +140 -0
- package/transport/events/types/permission.ts +90 -0
- package/transport/events/types/platform.ts +8 -0
- package/transport/events/types/plugin.ts +620 -0
- package/transport/events/types/sentry.ts +20 -0
- package/transport/events/types/storage.ts +208 -0
- package/transport/events/types/transport.ts +60 -0
- package/transport/events/types/tray.ts +16 -0
- package/transport/events/types/update.ts +78 -0
- package/transport/index.ts +139 -0
- package/transport/main.ts +2 -0
- package/transport/sdk/constants.ts +29 -0
- package/transport/sdk/domains/agents-market.ts +47 -0
- package/transport/sdk/domains/agents.ts +62 -0
- package/transport/sdk/domains/app.ts +48 -0
- package/transport/sdk/domains/disposable.ts +35 -0
- package/transport/sdk/domains/download.ts +139 -0
- package/transport/sdk/domains/index.ts +13 -0
- package/transport/sdk/domains/intelligence.ts +616 -0
- package/transport/sdk/domains/market.ts +35 -0
- package/transport/sdk/domains/notification.ts +62 -0
- package/transport/sdk/domains/permission.ts +85 -0
- package/transport/sdk/domains/platform.ts +19 -0
- package/transport/sdk/domains/plugin.ts +144 -0
- package/transport/sdk/domains/settings.ts +92 -0
- package/transport/sdk/domains/update.ts +64 -0
- package/transport/sdk/index.ts +60 -0
- package/transport/sdk/main-transport.ts +710 -0
- package/transport/sdk/main.ts +9 -0
- package/transport/sdk/plugin-transport.ts +654 -0
- package/transport/sdk/port-policy.ts +38 -0
- package/transport/sdk/renderer-transport.ts +1165 -0
- package/transport/types.ts +605 -0
- package/types/agent.ts +399 -0
- package/types/cloud-sync.ts +157 -0
- package/types/division-box.ts +47 -27
- package/types/download.ts +1 -0
- package/types/flow.ts +63 -12
- package/types/icon.ts +2 -1
- package/types/index.ts +5 -0
- package/types/intelligence.ts +1492 -81
- package/types/modules/base.ts +2 -0
- package/types/path-browserify.d.ts +5 -0
- package/types/platform.ts +12 -0
- package/types/startup-info.ts +32 -0
- package/types/touch-app-core.ts +8 -8
- package/types/update.ts +94 -1
- package/vitest.config.ts +25 -0
- package/auth/useClerkConfig.ts +0 -40
- package/auth/useClerkProvider.ts +0 -52
|
@@ -380,6 +380,7 @@ export interface TuffCustomRender {
|
|
|
380
380
|
|
|
381
381
|
/**
|
|
382
382
|
* Icon definition
|
|
383
|
+
* @deprecated
|
|
383
384
|
*
|
|
384
385
|
* @description
|
|
385
386
|
* Unified icon type supporting only ITuffIcon object format
|
|
@@ -803,6 +804,65 @@ export interface TuffContext {
|
|
|
803
804
|
tags?: string[]
|
|
804
805
|
}
|
|
805
806
|
|
|
807
|
+
// ==================== Footer Hints 配置 ====================
|
|
808
|
+
|
|
809
|
+
/**
|
|
810
|
+
* Footer hint 单项配置
|
|
811
|
+
*/
|
|
812
|
+
export interface TuffFooterHintItem {
|
|
813
|
+
/** 快捷键显示文本 */
|
|
814
|
+
key: string
|
|
815
|
+
/** 提示标签 */
|
|
816
|
+
label: string
|
|
817
|
+
/** 是否显示此提示 */
|
|
818
|
+
visible?: boolean
|
|
819
|
+
/** 触发的事件名称 */
|
|
820
|
+
event?: string
|
|
821
|
+
/** 事件携带的数据 */
|
|
822
|
+
eventData?: Record<string, unknown>
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
/**
|
|
826
|
+
* Footer hints 配置
|
|
827
|
+
* @description 控制 CoreBox 底部快捷键提示的显示和行为
|
|
828
|
+
*/
|
|
829
|
+
export interface TuffFooterHints {
|
|
830
|
+
/**
|
|
831
|
+
* 主操作提示(回车键)
|
|
832
|
+
* @description 自定义回车键的文案,如 "发送"、"执行"、"打开" 等
|
|
833
|
+
*/
|
|
834
|
+
primary?: {
|
|
835
|
+
/** 自定义标签文案 */
|
|
836
|
+
label?: string
|
|
837
|
+
/** 是否显示 */
|
|
838
|
+
visible?: boolean
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
/**
|
|
842
|
+
* 辅助操作提示(Meta+K)
|
|
843
|
+
* @description 控制 Meta+K 快捷键的显示和行为
|
|
844
|
+
*/
|
|
845
|
+
secondary?: {
|
|
846
|
+
/** 自定义标签文案 */
|
|
847
|
+
label?: string
|
|
848
|
+
/** 是否显示,默认 false(隐藏) */
|
|
849
|
+
visible?: boolean
|
|
850
|
+
/** 触发的事件名称 */
|
|
851
|
+
event?: string
|
|
852
|
+
/** 事件携带的数据 */
|
|
853
|
+
eventData?: Record<string, unknown>
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
/**
|
|
857
|
+
* 快速选择提示(Meta+1-0)
|
|
858
|
+
* @description 控制快速选择快捷键的显示
|
|
859
|
+
*/
|
|
860
|
+
quickSelect?: {
|
|
861
|
+
/** 是否显示,默认根据场景自动判断 */
|
|
862
|
+
visible?: boolean
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
|
|
806
866
|
// ==================== 扩展元数据 ====================
|
|
807
867
|
|
|
808
868
|
/**
|
|
@@ -1030,6 +1090,12 @@ export interface TuffMeta {
|
|
|
1030
1090
|
* @warning 不建议添加太多关键词(建议 <= 10),过多会影响搜索性能
|
|
1031
1091
|
*/
|
|
1032
1092
|
keywords?: string[]
|
|
1093
|
+
|
|
1094
|
+
/**
|
|
1095
|
+
* Footer hints 配置
|
|
1096
|
+
* @description 控制 CoreBox 底部快捷键提示的显示和行为
|
|
1097
|
+
*/
|
|
1098
|
+
footerHints?: TuffFooterHints
|
|
1033
1099
|
}
|
|
1034
1100
|
|
|
1035
1101
|
// ==================== 前端展示结构 ====================
|
|
@@ -1304,6 +1370,8 @@ export interface TuffContainerLayout {
|
|
|
1304
1370
|
export interface TuffSectionMeta {
|
|
1305
1371
|
/** 是否为智能推荐分组 */
|
|
1306
1372
|
intelligence?: boolean
|
|
1373
|
+
/** 是否为置顶分组 */
|
|
1374
|
+
pinned?: boolean
|
|
1307
1375
|
/** 扩展字段 */
|
|
1308
1376
|
[key: string]: unknown
|
|
1309
1377
|
}
|
|
@@ -1355,6 +1423,18 @@ export interface IProviderActivate {
|
|
|
1355
1423
|
icon?: TuffIcon
|
|
1356
1424
|
time?: number
|
|
1357
1425
|
meta?: Record<string, any>
|
|
1426
|
+
/**
|
|
1427
|
+
* Whether the results area should be hidden when this provider is active.
|
|
1428
|
+
* - true: Hide results (webcontent mode - plugin UI view is attached)
|
|
1429
|
+
* - false/undefined: Show results (push mode - plugin pushes items to list)
|
|
1430
|
+
*/
|
|
1431
|
+
hideResults?: boolean
|
|
1432
|
+
/**
|
|
1433
|
+
* Whether the input box should be shown when this provider is active.
|
|
1434
|
+
* - true: Show input (feature accepts input via acceptedInputTypes or allowInput)
|
|
1435
|
+
* - false/undefined: Hide input in webcontent mode, show in push mode
|
|
1436
|
+
*/
|
|
1437
|
+
showInput?: boolean
|
|
1358
1438
|
}
|
|
1359
1439
|
|
|
1360
1440
|
/**
|
|
@@ -1417,6 +1497,23 @@ export interface ISearchProvider<C> {
|
|
|
1417
1497
|
*/
|
|
1418
1498
|
readonly supportedInputTypes?: TuffInputType[]
|
|
1419
1499
|
|
|
1500
|
+
/**
|
|
1501
|
+
* Search priority layer
|
|
1502
|
+
* @description Determines when this provider's results are returned:
|
|
1503
|
+
* - 'fast': Results are returned immediately with the first batch (blocking)
|
|
1504
|
+
* - 'deferred': Results are appended asynchronously after fast layer completes
|
|
1505
|
+
* @default 'deferred'
|
|
1506
|
+
*/
|
|
1507
|
+
readonly priority?: 'fast' | 'deferred'
|
|
1508
|
+
|
|
1509
|
+
/**
|
|
1510
|
+
* Expected search duration in milliseconds
|
|
1511
|
+
* @description Used for sorting providers within the same layer and timeout estimation.
|
|
1512
|
+
* Providers with lower expected duration run first within their layer.
|
|
1513
|
+
* @default 1000
|
|
1514
|
+
*/
|
|
1515
|
+
readonly expectedDuration?: number
|
|
1516
|
+
|
|
1420
1517
|
/**
|
|
1421
1518
|
* Core search method (PULL mode).
|
|
1422
1519
|
* The engine calls this method to get results from the provider.
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
2
|
import { net } from 'electron'
|
|
3
3
|
import fse from 'fs-extra'
|
|
4
|
+
import { getLogger } from '../common/logger'
|
|
5
|
+
|
|
6
|
+
const downloadLog = getLogger('download-manager')
|
|
4
7
|
|
|
5
8
|
interface DownloadItem {
|
|
6
9
|
url: string
|
|
@@ -52,16 +55,16 @@ export class DownloadManager {
|
|
|
52
55
|
const item = this.downloadQueue.shift()!
|
|
53
56
|
|
|
54
57
|
try {
|
|
55
|
-
|
|
58
|
+
downloadLog.info(`Starting to download ${item.filename} from ${item.url}`)
|
|
56
59
|
const filePath = await this.downloadFile(item.url, item.filename)
|
|
57
|
-
|
|
60
|
+
downloadLog.info(`Download ${item.filename} completed`)
|
|
58
61
|
|
|
59
62
|
if (item.apply) {
|
|
60
63
|
item.apply(filePath)
|
|
61
64
|
}
|
|
62
65
|
}
|
|
63
66
|
catch (error) {
|
|
64
|
-
|
|
67
|
+
downloadLog.error(`Download ${item.filename} failed`, { error })
|
|
65
68
|
}
|
|
66
69
|
|
|
67
70
|
this.processQueue()
|
|
@@ -78,10 +81,10 @@ export class DownloadManager {
|
|
|
78
81
|
const request = net.request(url)
|
|
79
82
|
const filePath = this.basePath ? path.join(this.basePath, filename) : filename
|
|
80
83
|
|
|
81
|
-
|
|
84
|
+
downloadLog.info(`File download request sent for ${filename}.`)
|
|
82
85
|
|
|
83
86
|
request.addListener('error', (error) => {
|
|
84
|
-
|
|
87
|
+
downloadLog.error(`Download request error for ${filename}`, { error })
|
|
85
88
|
reject(error)
|
|
86
89
|
})
|
|
87
90
|
|
|
@@ -89,12 +92,12 @@ export class DownloadManager {
|
|
|
89
92
|
fse.createFileSync(filePath)
|
|
90
93
|
|
|
91
94
|
response.addListener('data', (chunk: any) => {
|
|
92
|
-
|
|
95
|
+
downloadLog.debug(`Downloading ${filename}...`)
|
|
93
96
|
fse.appendFile(filePath, chunk, 'utf8')
|
|
94
97
|
})
|
|
95
98
|
|
|
96
99
|
response.addListener('end', () => {
|
|
97
|
-
|
|
100
|
+
downloadLog.info(`Download ${filename} finished.`)
|
|
98
101
|
resolve(filePath)
|
|
99
102
|
})
|
|
100
103
|
})
|
package/electron/env-tool.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { ExecException } from 'node:child_process'
|
|
2
|
-
import { exec } from 'node:child_process'
|
|
3
2
|
import { platform } from 'node:process'
|
|
3
|
+
import { execFileSafe } from '../common/utils/safe-shell'
|
|
4
|
+
|
|
5
|
+
type ExecError = { error?: unknown }
|
|
4
6
|
|
|
5
7
|
export interface IGlobalPkgResult {
|
|
6
8
|
exist: boolean
|
|
@@ -9,53 +11,53 @@ export interface IGlobalPkgResult {
|
|
|
9
11
|
version?: string
|
|
10
12
|
}
|
|
11
13
|
|
|
12
|
-
export function checkGlobalPackageExist(packageName: string): Promise<IGlobalPkgResult> {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
exits: false,
|
|
18
|
-
error,
|
|
19
|
-
})
|
|
20
|
-
return
|
|
21
|
-
}
|
|
22
|
-
if (stderr) {
|
|
23
|
-
reject({
|
|
24
|
-
exits: false,
|
|
25
|
-
error: stderr,
|
|
26
|
-
})
|
|
27
|
-
return
|
|
28
|
-
}
|
|
14
|
+
export async function checkGlobalPackageExist(packageName: string): Promise<IGlobalPkgResult> {
|
|
15
|
+
const name = packageName.trim()
|
|
16
|
+
if (!name) {
|
|
17
|
+
throw new Error('Package name is required')
|
|
18
|
+
}
|
|
29
19
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
} as IGlobalPkgResult)
|
|
39
|
-
return
|
|
40
|
-
}
|
|
20
|
+
try {
|
|
21
|
+
const { stdout, stderr } = await execFileSafe('npm', ['list', '-g', name])
|
|
22
|
+
if (stderr) {
|
|
23
|
+
const stderrError = Object.assign(new Error('Failed to check global package'), {
|
|
24
|
+
error: stderr
|
|
25
|
+
})
|
|
26
|
+
throw stderrError
|
|
27
|
+
}
|
|
41
28
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
29
|
+
const lines = stdout.split('\n')
|
|
30
|
+
const lastLine = lines[lines.length - 3]
|
|
31
|
+
const match = lastLine.match(/([^@\s]+)@(\S+)/)
|
|
32
|
+
if (match) {
|
|
33
|
+
return {
|
|
34
|
+
exist: true,
|
|
35
|
+
name: match[1],
|
|
36
|
+
version: match[2]
|
|
37
|
+
} as IGlobalPkgResult
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
exist: false
|
|
42
|
+
} as IGlobalPkgResult
|
|
43
|
+
} catch (error) {
|
|
44
|
+
const execError = Object.assign(new Error('Failed to check global package'), {
|
|
45
|
+
error: error as ExecError
|
|
45
46
|
})
|
|
46
|
-
|
|
47
|
+
return Promise.reject(execError)
|
|
48
|
+
}
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
// Check npm version
|
|
50
52
|
export function getNpmVersion(): Promise<string | null> {
|
|
51
|
-
return
|
|
52
|
-
|
|
53
|
-
if (
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
return execFileSafe('npm', ['--version'])
|
|
54
|
+
.then(({ stdout, stderr }) => {
|
|
55
|
+
if (stderr) {
|
|
56
|
+
return null
|
|
57
|
+
}
|
|
58
|
+
return stdout.trim()
|
|
57
59
|
})
|
|
58
|
-
|
|
60
|
+
.catch(() => null)
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
export interface OSAdapter<R, T> {
|
package/electron/index.ts
CHANGED
package/env/index.ts
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
export const NEXUS_BASE_URL = 'https://tuff.tagzxia.com'
|
|
2
|
+
|
|
3
|
+
export interface EnvLike {
|
|
4
|
+
[key: string]: unknown
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function getProcess(): any {
|
|
8
|
+
return (globalThis as any)?.process
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function readGlobalEnv(): Record<string, string | undefined> {
|
|
12
|
+
const g: any = globalThis as any
|
|
13
|
+
const fromGlobal = g.__TUFF_ENV && typeof g.__TUFF_ENV === 'object' ? g.__TUFF_ENV : null
|
|
14
|
+
const record: Record<string, string | undefined> = {}
|
|
15
|
+
|
|
16
|
+
if (fromGlobal) {
|
|
17
|
+
for (const [k, v] of Object.entries(fromGlobal)) {
|
|
18
|
+
if (typeof v === 'string') {
|
|
19
|
+
record[k] = v
|
|
20
|
+
}
|
|
21
|
+
else if (typeof v === 'number' || typeof v === 'boolean') {
|
|
22
|
+
record[k] = String(v)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const p: any = getProcess()
|
|
28
|
+
if (p && p.env && typeof p.env === 'object') {
|
|
29
|
+
for (const [k, v] of Object.entries(p.env)) {
|
|
30
|
+
if (typeof v === 'string') {
|
|
31
|
+
record[k] = v
|
|
32
|
+
}
|
|
33
|
+
else if (typeof v === 'number' || typeof v === 'boolean') {
|
|
34
|
+
record[k] = String(v)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return record
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function setRuntimeEnv(env: Record<string, string | undefined>): void {
|
|
43
|
+
const g: any = globalThis as any
|
|
44
|
+
const normalized: Record<string, string | undefined> = {}
|
|
45
|
+
for (const [k, v] of Object.entries(env ?? {})) {
|
|
46
|
+
if (typeof v === 'string') {
|
|
47
|
+
normalized[k] = v
|
|
48
|
+
}
|
|
49
|
+
else if (typeof v === 'number' || typeof v === 'boolean') {
|
|
50
|
+
normalized[k] = String(v)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
g.__TUFF_ENV = { ...(g.__TUFF_ENV || {}), ...normalized }
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function getEnv(key: string): string | undefined {
|
|
57
|
+
return readGlobalEnv()[key]
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function getEnvOrDefault(key: string, fallback: string): string {
|
|
61
|
+
return getEnv(key) ?? fallback
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function getBooleanEnv(key: string, fallback = false): boolean {
|
|
65
|
+
const raw = getEnv(key)
|
|
66
|
+
if (raw === undefined)
|
|
67
|
+
return fallback
|
|
68
|
+
if (raw === '1' || raw === 'true')
|
|
69
|
+
return true
|
|
70
|
+
if (raw === '0' || raw === 'false')
|
|
71
|
+
return false
|
|
72
|
+
return fallback
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function hasWindow(): boolean {
|
|
76
|
+
return typeof window !== 'undefined'
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function hasDocument(): boolean {
|
|
80
|
+
return typeof document !== 'undefined'
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function hasNavigator(): boolean {
|
|
84
|
+
return typeof navigator !== 'undefined'
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function isBrowserRuntime(): boolean {
|
|
88
|
+
return hasWindow() && hasDocument()
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function isNodeRuntime(): boolean {
|
|
92
|
+
const proc: any = getProcess()
|
|
93
|
+
return typeof proc !== 'undefined'
|
|
94
|
+
&& Boolean(proc?.versions?.node)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function isElectronRuntime(): boolean {
|
|
98
|
+
const proc: any = getProcess()
|
|
99
|
+
return Boolean(proc?.versions?.electron)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function isElectronRenderer(): boolean {
|
|
103
|
+
const proc: any = getProcess()
|
|
104
|
+
return Boolean(proc?.versions?.electron)
|
|
105
|
+
&& proc?.type === 'renderer'
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function isElectronMain(): boolean {
|
|
109
|
+
const proc: any = getProcess()
|
|
110
|
+
return Boolean(proc?.versions?.electron)
|
|
111
|
+
&& (proc?.type === 'browser' || !proc?.type)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function isDevEnv(): boolean {
|
|
115
|
+
const nodeEnv = getEnv('NODE_ENV')
|
|
116
|
+
if (nodeEnv) {
|
|
117
|
+
return nodeEnv === 'development' || nodeEnv === 'test'
|
|
118
|
+
}
|
|
119
|
+
const mode = getEnv('MODE') || getEnv('VITE_MODE')
|
|
120
|
+
if (mode) {
|
|
121
|
+
return mode === 'development'
|
|
122
|
+
}
|
|
123
|
+
return getBooleanEnv('DEV', false)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function isProdEnv(): boolean {
|
|
127
|
+
const nodeEnv = getEnv('NODE_ENV')
|
|
128
|
+
if (nodeEnv) {
|
|
129
|
+
return nodeEnv === 'production'
|
|
130
|
+
}
|
|
131
|
+
const mode = getEnv('MODE') || getEnv('VITE_MODE')
|
|
132
|
+
if (mode) {
|
|
133
|
+
return mode === 'production'
|
|
134
|
+
}
|
|
135
|
+
return getBooleanEnv('PROD', false)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function normalizeBaseUrl(input: string): string {
|
|
139
|
+
return input.replace(/\/$/, '')
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function getTuffBaseUrl(): string {
|
|
143
|
+
return normalizeBaseUrl(getEnvOrDefault('VITE_NEXUS_URL', NEXUS_BASE_URL))
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function getTelemetryApiBase(): string {
|
|
147
|
+
const url = normalizeBaseUrl(getEnvOrDefault('NEXUS_API_BASE', NEXUS_BASE_URL))
|
|
148
|
+
if (!url) {
|
|
149
|
+
throw new Error('Telemetry API base URL is not configured')
|
|
150
|
+
}
|
|
151
|
+
return url
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function getTpexApiBase(): string {
|
|
155
|
+
return normalizeBaseUrl(getEnvOrDefault('TPEX_API_BASE', NEXUS_BASE_URL))
|
|
156
|
+
}
|
package/eslint.config.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const antfu = require('@antfu/eslint-config').default
|
|
2
|
+
|
|
3
|
+
module.exports = antfu(
|
|
4
|
+
{
|
|
5
|
+
type: 'lib',
|
|
6
|
+
typescript: true,
|
|
7
|
+
stylistic: false,
|
|
8
|
+
unicorn: false,
|
|
9
|
+
test: false,
|
|
10
|
+
markdown: false,
|
|
11
|
+
regexp: false,
|
|
12
|
+
ignores: [
|
|
13
|
+
'plugin/sdk/examples/**',
|
|
14
|
+
],
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
rules: {
|
|
18
|
+
'antfu/if-newline': 'off',
|
|
19
|
+
'jsdoc/check-param-names': 'off',
|
|
20
|
+
'jsdoc/empty-tags': 'off',
|
|
21
|
+
'import/consistent-type-specifier-style': 'off',
|
|
22
|
+
'import/first': 'off',
|
|
23
|
+
'node/prefer-global/buffer': 'off',
|
|
24
|
+
'node/prefer-global/process': 'off',
|
|
25
|
+
'no-console': 'off',
|
|
26
|
+
'no-useless-return': 'off',
|
|
27
|
+
'perfectionist/sort-exports': 'off',
|
|
28
|
+
'perfectionist/sort-imports': 'off',
|
|
29
|
+
'perfectionist/sort-named-exports': 'off',
|
|
30
|
+
'perfectionist/sort-named-imports': 'off',
|
|
31
|
+
'prefer-promise-reject-errors': 'off',
|
|
32
|
+
'test/prefer-lowercase-title': 'off',
|
|
33
|
+
'ts/consistent-type-definitions': 'off',
|
|
34
|
+
'ts/ban-ts-comment': 'off',
|
|
35
|
+
'ts/explicit-function-return-type': 'off',
|
|
36
|
+
'ts/method-signature-style': 'off',
|
|
37
|
+
'ts/no-namespace': 'off',
|
|
38
|
+
'ts/no-empty-object-type': 'off',
|
|
39
|
+
'ts/no-require-imports': 'off',
|
|
40
|
+
'ts/no-unsafe-function-type': 'off',
|
|
41
|
+
'ts/no-use-before-define': 'off',
|
|
42
|
+
'unicorn/escape-case': 'off',
|
|
43
|
+
'unicorn/new-for-builtins': 'off',
|
|
44
|
+
'unicorn/no-instanceof-builtins': 'off',
|
|
45
|
+
'unicorn/no-new-array': 'off',
|
|
46
|
+
'vars-on-top': 'off',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
files: ['plugin/channel.ts'],
|
|
51
|
+
rules: {
|
|
52
|
+
'no-eval': 'off',
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
)
|
package/i18n/index.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* I18n Utilities
|
|
3
|
+
*
|
|
4
|
+
* Shared i18n utilities for backend-frontend communication.
|
|
5
|
+
*
|
|
6
|
+
* ## Backend Usage (Main Process)
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { i18nMsg, DevServerKeys } from '@talex-touch/utils/i18n'
|
|
9
|
+
*
|
|
10
|
+
* // Send i18n message to frontend
|
|
11
|
+
* win.webContents.send('notification', {
|
|
12
|
+
* message: i18nMsg(DevServerKeys.DISCONNECTED)
|
|
13
|
+
* })
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* ## Frontend Usage (Renderer)
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { resolveI18nMessage, i18nResolver } from '@talex-touch/utils/i18n'
|
|
19
|
+
*
|
|
20
|
+
* // Set locale
|
|
21
|
+
* i18nResolver.setLocale('zh')
|
|
22
|
+
*
|
|
23
|
+
* // Resolve message
|
|
24
|
+
* const text = resolveI18nMessage('$i18n:devServer.disconnected')
|
|
25
|
+
* // => '开发服务器已断开'
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
// Locale data
|
|
30
|
+
export { default as enMessages } from './locales/en.json'
|
|
31
|
+
|
|
32
|
+
export { default as zhMessages } from './locales/zh.json'
|
|
33
|
+
|
|
34
|
+
// Message keys and utilities for backend
|
|
35
|
+
export {
|
|
36
|
+
type DevServerKey,
|
|
37
|
+
DevServerKeys,
|
|
38
|
+
type FlowTransferKey,
|
|
39
|
+
FlowTransferKeys,
|
|
40
|
+
I18N_PREFIX,
|
|
41
|
+
i18nMsg,
|
|
42
|
+
i18nMsgWithParams,
|
|
43
|
+
isI18nMessage,
|
|
44
|
+
MessageKeys,
|
|
45
|
+
parseI18nMessage,
|
|
46
|
+
type PluginKey,
|
|
47
|
+
PluginKeys,
|
|
48
|
+
type SystemKey,
|
|
49
|
+
SystemKeys,
|
|
50
|
+
type WidgetKey,
|
|
51
|
+
WidgetKeys,
|
|
52
|
+
} from './message-keys'
|
|
53
|
+
// Resolver for frontend
|
|
54
|
+
export {
|
|
55
|
+
createI18nMessage,
|
|
56
|
+
I18nResolver,
|
|
57
|
+
i18nResolver,
|
|
58
|
+
type MessageLocale,
|
|
59
|
+
type Messages,
|
|
60
|
+
resolveI18nMessage,
|
|
61
|
+
useI18nResolver,
|
|
62
|
+
} from './resolver'
|