@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.
Files changed (235) hide show
  1. package/.eslintcache +1 -0
  2. package/__tests__/cloud-sync-sdk.test.ts +442 -0
  3. package/__tests__/icons/icons.test.ts +84 -0
  4. package/__tests__/plugin-sdk-lifecycle.test.ts +130 -0
  5. package/__tests__/power-sdk.test.ts +143 -0
  6. package/__tests__/preset-export-types.test.ts +108 -0
  7. package/__tests__/search/fuzzy-match.test.ts +137 -0
  8. package/__tests__/transport/port-policy.test.ts +44 -0
  9. package/__tests__/transport-domain-sdks.test.ts +152 -0
  10. package/__tests__/types/update.test.ts +67 -0
  11. package/account/account-sdk.ts +915 -0
  12. package/account/index.ts +2 -0
  13. package/account/types.ts +321 -0
  14. package/analytics/client.ts +136 -0
  15. package/analytics/index.ts +2 -0
  16. package/analytics/types.ts +156 -0
  17. package/animation/auto-resize.ts +322 -0
  18. package/animation/window-node.ts +26 -19
  19. package/auth/clerk-types.ts +12 -30
  20. package/auth/index.ts +0 -2
  21. package/auth/useAuthState.ts +6 -14
  22. package/base/index.ts +2 -0
  23. package/base/log-level.ts +105 -0
  24. package/channel/index.ts +170 -69
  25. package/cloud-sync/cloud-sync-sdk.ts +450 -0
  26. package/cloud-sync/index.ts +1 -0
  27. package/common/file-scan-utils.ts +17 -9
  28. package/common/index.ts +4 -0
  29. package/common/logger/index.ts +46 -0
  30. package/common/logger/logger-manager.ts +303 -0
  31. package/common/logger/module-logger.ts +270 -0
  32. package/common/logger/transport-logger.ts +234 -0
  33. package/common/logger/types.ts +93 -0
  34. package/common/search/gather.ts +48 -6
  35. package/common/search/index.ts +8 -0
  36. package/common/storage/constants.ts +13 -0
  37. package/common/storage/entity/app-settings.ts +245 -0
  38. package/common/storage/entity/index.ts +3 -0
  39. package/common/storage/entity/layout-atom-types.ts +147 -0
  40. package/common/storage/entity/openers.ts +1 -0
  41. package/common/storage/entity/preset-cloud-api.ts +132 -0
  42. package/common/storage/entity/preset-export-types.ts +256 -0
  43. package/common/storage/entity/shortcut-settings.ts +1 -0
  44. package/common/storage/shortcut-storage.ts +11 -0
  45. package/common/utils/clone-diagnostics.ts +105 -0
  46. package/common/utils/file.ts +16 -8
  47. package/common/utils/index.ts +6 -2
  48. package/common/utils/payload-preview.ts +173 -0
  49. package/common/utils/polling.ts +167 -13
  50. package/common/utils/safe-path.ts +103 -0
  51. package/common/utils/safe-shell.ts +115 -0
  52. package/common/utils/task-queue.ts +4 -1
  53. package/core-box/builder/tuff-builder.ts +0 -1
  54. package/core-box/index.ts +1 -1
  55. package/core-box/recommendation.ts +38 -1
  56. package/core-box/tuff/tuff-dsl.ts +97 -0
  57. package/electron/download-manager.ts +10 -7
  58. package/electron/env-tool.ts +42 -40
  59. package/electron/index.ts +0 -1
  60. package/env/index.ts +156 -0
  61. package/eslint.config.js +55 -0
  62. package/i18n/index.ts +62 -0
  63. package/i18n/locales/en.json +226 -0
  64. package/i18n/locales/zh.json +226 -0
  65. package/i18n/message-keys.ts +236 -0
  66. package/i18n/resolver.ts +181 -0
  67. package/icons/index.ts +257 -0
  68. package/icons/svg.ts +69 -0
  69. package/index.ts +9 -1
  70. package/intelligence/client.ts +72 -42
  71. package/market/constants.ts +21 -3
  72. package/market/index.ts +1 -1
  73. package/market/types.ts +20 -5
  74. package/package.json +15 -5
  75. package/permission/index.ts +143 -46
  76. package/permission/legacy.ts +26 -0
  77. package/permission/registry.ts +304 -0
  78. package/permission/types.ts +164 -0
  79. package/plugin/channel.ts +68 -39
  80. package/plugin/index.ts +82 -8
  81. package/plugin/install.ts +3 -0
  82. package/plugin/log/types.ts +22 -5
  83. package/plugin/node/logger-manager.ts +11 -3
  84. package/plugin/node/logger.ts +24 -17
  85. package/plugin/preload.ts +25 -2
  86. package/plugin/providers/index.ts +4 -0
  87. package/plugin/providers/market-client.ts +218 -0
  88. package/plugin/providers/npm-provider.ts +228 -0
  89. package/plugin/providers/tpex-provider.ts +297 -0
  90. package/plugin/providers/tpex-types.ts +34 -0
  91. package/plugin/sdk/box-items.ts +14 -0
  92. package/plugin/sdk/box-sdk.ts +64 -0
  93. package/plugin/sdk/channel.ts +119 -4
  94. package/plugin/sdk/clipboard.ts +26 -12
  95. package/plugin/sdk/cloud-sync.ts +113 -0
  96. package/plugin/sdk/common.ts +19 -11
  97. package/plugin/sdk/core-box.ts +6 -15
  98. package/plugin/sdk/division-box.ts +160 -65
  99. package/plugin/sdk/examples/storage-onDidChange-example.js +5 -2
  100. package/plugin/sdk/feature-sdk.ts +111 -76
  101. package/plugin/sdk/flow.ts +146 -45
  102. package/plugin/sdk/hooks/bridge.ts +113 -49
  103. package/plugin/sdk/hooks/life-cycle.ts +35 -16
  104. package/plugin/sdk/index.ts +14 -3
  105. package/plugin/sdk/intelligence.ts +87 -0
  106. package/plugin/sdk/meta/README.md +179 -0
  107. package/plugin/sdk/meta-sdk.ts +244 -0
  108. package/plugin/sdk/notification.ts +9 -0
  109. package/plugin/sdk/performance.ts +1 -16
  110. package/plugin/sdk/plugin-info.ts +64 -0
  111. package/plugin/sdk/power.ts +155 -0
  112. package/plugin/sdk/recommend.ts +21 -0
  113. package/plugin/sdk/service/index.ts +12 -8
  114. package/plugin/sdk/sqlite.ts +141 -0
  115. package/plugin/sdk/storage.ts +2 -6
  116. package/plugin/sdk/system.ts +2 -9
  117. package/plugin/sdk/temp-files.ts +41 -0
  118. package/plugin/sdk/touch-sdk.ts +18 -0
  119. package/plugin/sdk/types.ts +44 -4
  120. package/plugin/sdk/window/index.ts +12 -9
  121. package/plugin/sdk-version.ts +231 -0
  122. package/preload/renderer.ts +3 -2
  123. package/renderer/hooks/arg-mapper.ts +34 -6
  124. package/renderer/hooks/index.ts +13 -0
  125. package/renderer/hooks/initialize.ts +2 -1
  126. package/renderer/hooks/use-agent-market-sdk.ts +7 -0
  127. package/renderer/hooks/use-agent-market.ts +106 -0
  128. package/renderer/hooks/use-agents-sdk.ts +7 -0
  129. package/renderer/hooks/use-app-sdk.ts +7 -0
  130. package/renderer/hooks/use-channel.ts +33 -4
  131. package/renderer/hooks/use-download-sdk.ts +21 -0
  132. package/renderer/hooks/use-intelligence-sdk.ts +7 -0
  133. package/renderer/hooks/use-intelligence-stats.ts +290 -0
  134. package/renderer/hooks/use-intelligence.ts +202 -104
  135. package/renderer/hooks/use-market-sdk.ts +16 -0
  136. package/renderer/hooks/use-notification-sdk.ts +7 -0
  137. package/renderer/hooks/use-permission-sdk.ts +7 -0
  138. package/renderer/hooks/use-permission.ts +325 -0
  139. package/renderer/hooks/use-platform-sdk.ts +7 -0
  140. package/renderer/hooks/use-plugin-sdk.ts +16 -0
  141. package/renderer/hooks/use-settings-sdk.ts +7 -0
  142. package/renderer/hooks/use-update-sdk.ts +21 -0
  143. package/renderer/index.ts +1 -0
  144. package/renderer/ref.ts +19 -10
  145. package/renderer/shared/components/SharedPluginDetailContent.vue +84 -0
  146. package/renderer/shared/components/SharedPluginDetailHeader.vue +116 -0
  147. package/renderer/shared/components/SharedPluginDetailMetaList.vue +39 -0
  148. package/renderer/shared/components/SharedPluginDetailReadme.vue +45 -0
  149. package/renderer/shared/components/SharedPluginDetailVersions.vue +98 -0
  150. package/renderer/shared/components/index.ts +5 -0
  151. package/renderer/shared/components/shims-vue.d.ts +5 -0
  152. package/renderer/shared/index.ts +2 -0
  153. package/renderer/shared/plugin-detail.ts +62 -0
  154. package/renderer/storage/app-settings.ts +3 -1
  155. package/renderer/storage/base-storage.ts +508 -82
  156. package/renderer/storage/intelligence-storage.ts +37 -46
  157. package/renderer/storage/openers.ts +3 -1
  158. package/renderer/storage/storage-subscription.ts +126 -42
  159. package/renderer/touch-sdk/env.ts +10 -10
  160. package/renderer/touch-sdk/index.ts +114 -18
  161. package/renderer/touch-sdk/terminal.ts +24 -13
  162. package/search/feature-matcher.ts +279 -0
  163. package/search/fuzzy-match.ts +64 -34
  164. package/search/index.ts +10 -0
  165. package/search/levenshtein-utils.ts +17 -11
  166. package/transport/errors.ts +310 -0
  167. package/transport/event/builder.ts +378 -0
  168. package/transport/event/index.ts +7 -0
  169. package/transport/event/types.ts +292 -0
  170. package/transport/events/index.ts +2670 -0
  171. package/transport/events/meta-overlay.ts +79 -0
  172. package/transport/events/types/agents.ts +177 -0
  173. package/transport/events/types/app-index.ts +9 -0
  174. package/transport/events/types/app.ts +475 -0
  175. package/transport/events/types/box-item.ts +222 -0
  176. package/transport/events/types/clipboard.ts +80 -0
  177. package/transport/events/types/core-box.ts +534 -0
  178. package/transport/events/types/device-idle.ts +7 -0
  179. package/transport/events/types/division-box.ts +99 -0
  180. package/transport/events/types/download.ts +115 -0
  181. package/transport/events/types/file-index.ts +73 -0
  182. package/transport/events/types/flow.ts +149 -0
  183. package/transport/events/types/index.ts +70 -0
  184. package/transport/events/types/market.ts +39 -0
  185. package/transport/events/types/meta-overlay.ts +184 -0
  186. package/transport/events/types/notification.ts +140 -0
  187. package/transport/events/types/permission.ts +90 -0
  188. package/transport/events/types/platform.ts +8 -0
  189. package/transport/events/types/plugin.ts +620 -0
  190. package/transport/events/types/sentry.ts +20 -0
  191. package/transport/events/types/storage.ts +208 -0
  192. package/transport/events/types/transport.ts +60 -0
  193. package/transport/events/types/tray.ts +16 -0
  194. package/transport/events/types/update.ts +78 -0
  195. package/transport/index.ts +139 -0
  196. package/transport/main.ts +2 -0
  197. package/transport/sdk/constants.ts +29 -0
  198. package/transport/sdk/domains/agents-market.ts +47 -0
  199. package/transport/sdk/domains/agents.ts +62 -0
  200. package/transport/sdk/domains/app.ts +48 -0
  201. package/transport/sdk/domains/disposable.ts +35 -0
  202. package/transport/sdk/domains/download.ts +139 -0
  203. package/transport/sdk/domains/index.ts +13 -0
  204. package/transport/sdk/domains/intelligence.ts +616 -0
  205. package/transport/sdk/domains/market.ts +35 -0
  206. package/transport/sdk/domains/notification.ts +62 -0
  207. package/transport/sdk/domains/permission.ts +85 -0
  208. package/transport/sdk/domains/platform.ts +19 -0
  209. package/transport/sdk/domains/plugin.ts +144 -0
  210. package/transport/sdk/domains/settings.ts +92 -0
  211. package/transport/sdk/domains/update.ts +64 -0
  212. package/transport/sdk/index.ts +60 -0
  213. package/transport/sdk/main-transport.ts +710 -0
  214. package/transport/sdk/main.ts +9 -0
  215. package/transport/sdk/plugin-transport.ts +654 -0
  216. package/transport/sdk/port-policy.ts +38 -0
  217. package/transport/sdk/renderer-transport.ts +1165 -0
  218. package/transport/types.ts +605 -0
  219. package/types/agent.ts +399 -0
  220. package/types/cloud-sync.ts +157 -0
  221. package/types/division-box.ts +47 -27
  222. package/types/download.ts +1 -0
  223. package/types/flow.ts +63 -12
  224. package/types/icon.ts +2 -1
  225. package/types/index.ts +5 -0
  226. package/types/intelligence.ts +1492 -81
  227. package/types/modules/base.ts +2 -0
  228. package/types/path-browserify.d.ts +5 -0
  229. package/types/platform.ts +12 -0
  230. package/types/startup-info.ts +32 -0
  231. package/types/touch-app-core.ts +8 -8
  232. package/types/update.ts +94 -1
  233. package/vitest.config.ts +25 -0
  234. package/auth/useClerkConfig.ts +0 -40
  235. package/auth/useClerkProvider.ts +0 -52
@@ -1,20 +1,23 @@
1
- import type { AiProviderConfig, AISDKGlobalConfig, AISDKStorageData } from '../../types/intelligence'
1
+ import type {
2
+ IntelligenceGlobalConfig,
3
+ IntelligenceProviderConfig,
4
+ IntelligenceStorageData,
5
+ } from '../../types/intelligence'
6
+ import { getLogger } from '../../common/logger'
2
7
  import { StorageList } from '../../common/storage/constants'
3
8
  import {
4
-
5
- AiProviderType,
6
-
7
9
  DEFAULT_CAPABILITIES,
8
10
  DEFAULT_GLOBAL_CONFIG,
9
11
  DEFAULT_PROVIDERS,
12
+ IntelligenceProviderType,
10
13
  } from '../../types/intelligence'
11
- import { createStorageProxy, TouchStorage } from './base-storage'
14
+ import { createStorageDataProxy, createStorageProxy, TouchStorage } from './base-storage'
12
15
 
13
16
  // Re-export types for convenience
14
- export { AiProviderType }
15
- export type { AiProviderConfig, AISDKGlobalConfig }
17
+ export { IntelligenceProviderType }
18
+ export type { IntelligenceGlobalConfig, IntelligenceProviderConfig }
16
19
 
17
- const defaultIntelligenceData: AISDKStorageData = {
20
+ const defaultIntelligenceData: IntelligenceStorageData = {
18
21
  providers: [...DEFAULT_PROVIDERS],
19
22
  globalConfig: { ...DEFAULT_GLOBAL_CONFIG },
20
23
  capabilities: { ...DEFAULT_CAPABILITIES },
@@ -22,8 +25,9 @@ const defaultIntelligenceData: AISDKStorageData = {
22
25
  }
23
26
 
24
27
  const INTELLIGENCE_STORAGE_KEY = `storage:${StorageList.IntelligenceConfig}`
28
+ const intelligenceStorageLog = getLogger('intelligence-storage')
25
29
 
26
- class IntelligenceStorage extends TouchStorage<AISDKStorageData> {
30
+ class IntelligenceStorage extends TouchStorage<IntelligenceStorageData> {
27
31
  constructor() {
28
32
  super(StorageList.IntelligenceConfig, defaultIntelligenceData)
29
33
  this.setAutoSave(true)
@@ -32,7 +36,7 @@ class IntelligenceStorage extends TouchStorage<AISDKStorageData> {
32
36
  /**
33
37
  * 添加新的提供商
34
38
  */
35
- addProvider(provider: AiProviderConfig): void {
39
+ addProvider(provider: IntelligenceProviderConfig): void {
36
40
  const currentData = this.get()
37
41
  const updatedProviders = [...currentData.providers, provider]
38
42
  this.set({
@@ -44,14 +48,17 @@ class IntelligenceStorage extends TouchStorage<AISDKStorageData> {
44
48
  /**
45
49
  * 更新提供商配置
46
50
  */
47
- updateProvider(id: string, updatedProvider: Partial<AiProviderConfig>): void {
51
+ updateProvider(id: string, updatedProvider: Partial<IntelligenceProviderConfig>): void {
48
52
  const currentData = this.get()
49
53
  const providerIndex = currentData.providers.findIndex(p => p.id === id)
50
54
 
51
55
  if (providerIndex !== -1) {
52
56
  const updatedProviders = [...currentData.providers]
57
+ const currentProvider = updatedProviders[providerIndex]
58
+ if (!currentProvider)
59
+ return
53
60
  updatedProviders[providerIndex] = {
54
- ...updatedProviders[providerIndex],
61
+ ...currentProvider,
55
62
  ...updatedProvider,
56
63
  }
57
64
 
@@ -78,7 +85,7 @@ class IntelligenceStorage extends TouchStorage<AISDKStorageData> {
78
85
  /**
79
86
  * 更新全局配置
80
87
  */
81
- updateGlobalConfig(config: Partial<AISDKGlobalConfig>): void {
88
+ updateGlobalConfig(config: Partial<IntelligenceGlobalConfig>): void {
82
89
  const currentData = this.get()
83
90
 
84
91
  this.set({
@@ -93,14 +100,14 @@ class IntelligenceStorage extends TouchStorage<AISDKStorageData> {
93
100
  /**
94
101
  * 获取特定类型的提供商
95
102
  */
96
- getProvidersByType(type: AiProviderType): AiProviderConfig[] {
103
+ getProvidersByType(type: IntelligenceProviderType): IntelligenceProviderConfig[] {
97
104
  return this.get().providers.filter(p => p.type === type)
98
105
  }
99
106
 
100
107
  /**
101
108
  * 获取启用的提供商
102
109
  */
103
- getEnabledProviders(): AiProviderConfig[] {
110
+ getEnabledProviders(): IntelligenceProviderConfig[] {
104
111
  return this.get().providers.filter(p => p.enabled)
105
112
  }
106
113
 
@@ -113,7 +120,7 @@ class IntelligenceStorage extends TouchStorage<AISDKStorageData> {
113
120
  return false
114
121
 
115
122
  // 检查是否有必要的配置项
116
- const hasApiKey = provider.type === AiProviderType.LOCAL || !!provider.apiKey
123
+ const hasApiKey = provider.type === IntelligenceProviderType.LOCAL || !!provider.apiKey
117
124
  const hasModels = !!(provider.models && provider.models.length > 0)
118
125
 
119
126
  return hasApiKey && hasModels
@@ -129,25 +136,19 @@ export const intelligenceStorage = createStorageProxy<IntelligenceStorage>(
129
136
  () => new IntelligenceStorage(),
130
137
  )
131
138
 
132
- /**
133
- * Alias for backward compatibility
134
- * @deprecated Use intelligenceStorage instead
135
- */
136
- export const aisdkStorage = intelligenceStorage
139
+ export const intelligenceData = createStorageDataProxy(intelligenceStorage)
137
140
 
138
- /**
139
- * Alias for backward compatibility
140
- * @deprecated Use intelligenceStorage instead
141
- */
142
141
  export const intelligenceSettings = intelligenceStorage
143
142
 
143
+ export const intelligenceSettingsData = intelligenceData
144
+
144
145
  export async function migrateIntelligenceSettings(): Promise<void> {
145
- console.log('[Intelligence Storage] Starting migration check...')
146
+ intelligenceStorageLog.info('Starting migration check...')
146
147
  const currentData = intelligenceStorage.data
147
148
 
148
149
  // Version 2: Force update capabilities to include all new ones
149
150
  if (!currentData.version || currentData.version < 2) {
150
- console.log('[Intelligence Storage] Migrating settings to version 2')
151
+ intelligenceStorageLog.info('Migrating settings to version 2')
151
152
 
152
153
  const migratedProviders = currentData.providers.map(provider => ({
153
154
  ...provider,
@@ -163,7 +164,7 @@ export async function migrateIntelligenceSettings(): Promise<void> {
163
164
  const normalizedStrategy
164
165
  = storedStrategy === 'priority' ? 'rule-based-default' : storedStrategy ?? 'adaptive-default'
165
166
 
166
- const migratedGlobalConfig: AISDKGlobalConfig = {
167
+ const migratedGlobalConfig: IntelligenceGlobalConfig = {
167
168
  defaultStrategy: normalizedStrategy,
168
169
  enableAudit: currentData.globalConfig?.enableAudit ?? false,
169
170
  enableCache: currentData.globalConfig?.enableCache ?? true,
@@ -171,8 +172,8 @@ export async function migrateIntelligenceSettings(): Promise<void> {
171
172
  }
172
173
 
173
174
  // Force update to latest DEFAULT_CAPABILITIES (version 2)
174
- console.log('[Intelligence Storage] Updating capabilities to latest defaults')
175
-
175
+ intelligenceStorageLog.info('Updating capabilities to latest defaults')
176
+
176
177
  intelligenceStorage.applyData({
177
178
  providers: migratedProviders,
178
179
  globalConfig: migratedGlobalConfig,
@@ -182,23 +183,18 @@ export async function migrateIntelligenceSettings(): Promise<void> {
182
183
 
183
184
  await intelligenceStorage.saveToRemote({ force: true })
184
185
 
185
- console.log('[Intelligence Storage] Migration to v2 complete, capabilities count:', Object.keys(DEFAULT_CAPABILITIES).length)
186
+ intelligenceStorageLog.info(`Migration to v2 complete, capabilities count: ${Object.keys(DEFAULT_CAPABILITIES).length}`)
186
187
  }
187
188
  else {
188
- console.log('[Intelligence Storage] No migration needed, current version:', currentData.version)
189
+ intelligenceStorageLog.info(`No migration needed, current version: ${currentData.version}`)
189
190
  }
190
191
 
191
- console.log('[Intelligence Storage] Final providers count:', intelligenceStorage.data.providers.length)
192
- console.log('[Intelligence Storage] Final capabilities count:', Object.keys(intelligenceStorage.data.capabilities).length)
192
+ intelligenceStorageLog.info(`Final providers count: ${intelligenceStorage.data.providers.length}`)
193
+ intelligenceStorageLog.info(`Final capabilities count: ${Object.keys(intelligenceStorage.data.capabilities).length}`)
193
194
  }
194
195
 
195
- /**
196
- * @deprecated Use migrateIntelligenceSettings instead
197
- */
198
- export const migrateAISDKSettings = migrateIntelligenceSettings
199
-
200
196
  export async function resetIntelligenceConfig(): Promise<void> {
201
- console.log('[Intelligence Storage] Resetting to default configuration')
197
+ intelligenceStorageLog.info('Resetting to default configuration')
202
198
 
203
199
  intelligenceStorage.applyData({
204
200
  providers: [...DEFAULT_PROVIDERS],
@@ -209,10 +205,5 @@ export async function resetIntelligenceConfig(): Promise<void> {
209
205
 
210
206
  await intelligenceStorage.saveToRemote({ force: true })
211
207
 
212
- console.log('[Intelligence Storage] Reset complete')
208
+ intelligenceStorageLog.info('Reset complete')
213
209
  }
214
-
215
- /**
216
- * @deprecated Use resetIntelligenceConfig instead
217
- */
218
- export const resetAISDKConfig = resetIntelligenceConfig
@@ -1,6 +1,6 @@
1
1
  import type { OpenersMap } from '../..'
2
2
  import { openersOriginData, StorageList } from '../..'
3
- import { createStorageProxy, TouchStorage } from './base-storage'
3
+ import { createStorageDataProxy, createStorageProxy, TouchStorage } from './base-storage'
4
4
 
5
5
  class OpenersStorage extends TouchStorage<OpenersMap> {
6
6
  constructor() {
@@ -19,3 +19,5 @@ export const openersStorage = createStorageProxy<OpenersStorage>(
19
19
  OPENERS_STORAGE_KEY,
20
20
  () => new OpenersStorage(),
21
21
  )
22
+
23
+ export const openersData = createStorageDataProxy(openersStorage)
@@ -1,4 +1,8 @@
1
+ import type { ITuffTransport } from '../../transport'
2
+ import type { StorageUpdateNotification } from '../../transport/events/types'
1
3
  import type { IStorageChannel } from './base-storage'
4
+ import { defineRawEvent } from '../../transport/event/builder'
5
+ import { StorageEvents } from '../../transport/events'
2
6
 
3
7
  /**
4
8
  * Storage subscription callback type
@@ -11,34 +15,68 @@ export type StorageSubscriptionCallback = (data: any) => void
11
15
  */
12
16
  class StorageSubscriptionManager {
13
17
  private channel: IStorageChannel | null = null
18
+ private transport: ITuffTransport | null = null
14
19
  private subscribers = new Map<string, Set<StorageSubscriptionCallback>>()
15
20
  private channelListenerRegistered = false
16
21
  private pendingUpdates = new Map<string, NodeJS.Timeout>()
17
22
  private configVersions = new Map<string, number>()
23
+ private cachedData = new Map<string, unknown>()
18
24
 
19
25
  /**
20
26
  * Initialize the subscription manager with a channel
21
27
  */
22
- init(channel: IStorageChannel): void {
23
- this.channel = channel
28
+ init(channel?: IStorageChannel, transport?: ITuffTransport): void {
29
+ if (channel) {
30
+ this.channel = channel
31
+ }
32
+ if (transport) {
33
+ this.transport = transport
34
+ }
24
35
 
25
36
  if (!this.channelListenerRegistered) {
26
- // Listen to storage:update events from main process
27
- this.channel.regChannel('storage:update', ({ data }) => {
28
- const { name, version } = data as { name: string, version?: number }
29
- // Only handle update if version is newer or unknown
30
- const currentVersion = this.configVersions.get(name) ?? 0
31
- if (version === undefined || version > currentVersion) {
32
- if (version !== undefined) {
33
- this.configVersions.set(name, version)
34
- }
35
- this.handleStorageUpdate(name)
36
- }
37
- })
37
+ if (this.transport) {
38
+ this.transport
39
+ .stream(StorageEvents.app.updated, undefined, {
40
+ onData: (payload: StorageUpdateNotification) => {
41
+ this.handleVersionedUpdate(payload.key, payload.version)
42
+ },
43
+ })
44
+ .catch((error) => {
45
+ console.error('[StorageSubscription] Failed to subscribe to storage updates:', error)
46
+ })
47
+
48
+ const legacyStorageUpdateEvent = defineRawEvent<{ name: string; version?: number }, void>(
49
+ StorageEvents.legacy.update.toEventName()
50
+ )
51
+ this.transport.on(legacyStorageUpdateEvent, (payload) => {
52
+ if (!payload || typeof payload !== 'object') return
53
+ const { name, version } = payload as { name?: string; version?: number }
54
+ if (!name) return
55
+ this.handleVersionedUpdate(name, version)
56
+ })
57
+ }
58
+
59
+ if (this.channel) {
60
+ // Listen to storage:update events from main process
61
+ this.channel.regChannel(StorageEvents.legacy.update.toEventName(), ({ data }) => {
62
+ const { name, version } = data as { name: string, version?: number }
63
+ this.handleVersionedUpdate(name, version)
64
+ })
65
+ }
38
66
  this.channelListenerRegistered = true
39
67
  }
40
68
  }
41
69
 
70
+ private handleVersionedUpdate(name: string, version?: number): void {
71
+ const currentVersion = this.configVersions.get(name) ?? 0
72
+ if (version === undefined || version > currentVersion) {
73
+ if (version !== undefined) {
74
+ this.configVersions.set(name, version)
75
+ }
76
+ void this.handleStorageUpdate(name)
77
+ }
78
+ }
79
+
42
80
  /**
43
81
  * Subscribe to storage changes for a specific config
44
82
  * @param configName - The configuration file name (e.g., 'app-setting.ini')
@@ -62,18 +100,51 @@ class StorageSubscriptionManager {
62
100
 
63
101
  this.subscribers.get(configName)!.add(callback)
64
102
 
65
- // Immediately load and call with current data
66
- if (this.channel) {
67
- const currentData = this.channel.sendSync('storage:get', configName)
68
- if (currentData) {
69
- try {
70
- callback(currentData)
71
- }
72
- catch (error) {
73
- console.error(`[StorageSubscription] Callback error for "${configName}":`, error)
74
- }
103
+ const cached = this.cachedData.get(configName)
104
+ if (cached !== undefined) {
105
+ try {
106
+ callback(cached)
107
+ }
108
+ catch (error) {
109
+ console.error(`[StorageSubscription] Callback error for "${configName}":`, error)
75
110
  }
76
111
  }
112
+ else if (this.channel) {
113
+ this.channel
114
+ .send('storage:get', configName)
115
+ .then((data) => {
116
+ if (data === undefined || data === null)
117
+ return
118
+ this.cachedData.set(configName, data)
119
+ try {
120
+ callback(data)
121
+ }
122
+ catch (error) {
123
+ console.error(`[StorageSubscription] Callback error for "${configName}":`, error)
124
+ }
125
+ })
126
+ .catch((error) => {
127
+ console.error(`[StorageSubscription] Failed to load "${configName}":`, error)
128
+ })
129
+ }
130
+ else if (this.transport) {
131
+ this.transport
132
+ .send(StorageEvents.app.get, { key: configName })
133
+ .then((data) => {
134
+ if (data === undefined || data === null)
135
+ return
136
+ this.cachedData.set(configName, data)
137
+ try {
138
+ callback(data)
139
+ }
140
+ catch (error) {
141
+ console.error(`[StorageSubscription] Callback error for "${configName}":`, error)
142
+ }
143
+ })
144
+ .catch((error) => {
145
+ console.error(`[StorageSubscription] Failed to load "${configName}":`, error)
146
+ })
147
+ }
77
148
 
78
149
  // Return unsubscribe function
79
150
  return () => {
@@ -92,6 +163,7 @@ class StorageSubscriptionManager {
92
163
  callbacks.delete(callback)
93
164
  if (callbacks.size === 0) {
94
165
  this.subscribers.delete(configName)
166
+ this.cachedData.delete(configName)
95
167
  }
96
168
  }
97
169
  }
@@ -106,7 +178,7 @@ class StorageSubscriptionManager {
106
178
  return
107
179
  }
108
180
 
109
- if (!this.channel) {
181
+ if (!this.channel && !this.transport) {
110
182
  return
111
183
  }
112
184
 
@@ -117,24 +189,35 @@ class StorageSubscriptionManager {
117
189
  }
118
190
 
119
191
  const timer = setTimeout(async () => {
120
- // Fetch latest data
121
- const data = await this.channel!.send('storage:get', configName)
122
- if (!data) {
123
- this.pendingUpdates.delete(configName)
124
- return
125
- }
192
+ try {
193
+ // Fetch latest data
194
+ const data = this.channel
195
+ ? await this.channel.send('storage:get', configName)
196
+ : await this.transport!.send(StorageEvents.app.get, { key: configName })
126
197
 
127
- // Notify all subscribers
128
- callbacks.forEach((callback) => {
129
- try {
130
- callback(data)
131
- }
132
- catch (error) {
133
- console.error(`[StorageSubscription] Callback error for "${configName}":`, error)
198
+ if (data === undefined || data === null) {
199
+ this.pendingUpdates.delete(configName)
200
+ return
134
201
  }
135
- })
136
202
 
137
- this.pendingUpdates.delete(configName)
203
+ this.cachedData.set(configName, data)
204
+
205
+ // Notify all subscribers
206
+ callbacks.forEach((callback) => {
207
+ try {
208
+ callback(data)
209
+ }
210
+ catch (error) {
211
+ console.error(`[StorageSubscription] Callback error for "${configName}":`, error)
212
+ }
213
+ })
214
+ }
215
+ catch (error) {
216
+ console.error(`[StorageSubscription] Failed to reload "${configName}":`, error)
217
+ }
218
+ finally {
219
+ this.pendingUpdates.delete(configName)
220
+ }
138
221
  }, 50) // 50ms debounce window
139
222
 
140
223
  this.pendingUpdates.set(configName, timer)
@@ -154,6 +237,7 @@ class StorageSubscriptionManager {
154
237
  */
155
238
  clear(): void {
156
239
  this.subscribers.clear()
240
+ this.cachedData.clear()
157
241
  }
158
242
  }
159
243
 
@@ -166,8 +250,8 @@ const subscriptionManager = new StorageSubscriptionManager()
166
250
  *
167
251
  * @param channel - The storage channel
168
252
  */
169
- export function initStorageSubscription(channel: IStorageChannel): void {
170
- subscriptionManager.init(channel)
253
+ export function initStorageSubscription(channel?: IStorageChannel, transport?: ITuffTransport): void {
254
+ subscriptionManager.init(channel, transport)
171
255
  }
172
256
 
173
257
  /**
@@ -1,11 +1,11 @@
1
- import type { ITouchClientChannel } from '@talex-touch/utils/channel'
1
+ import type { ITuffTransport } from '@talex-touch/utils/transport'
2
2
  import { Terminal } from './terminal'
3
3
 
4
4
  export class EnvDetector {
5
- private static channel: ITouchClientChannel
5
+ private static transport: ITuffTransport
6
6
 
7
- public static init(channel: ITouchClientChannel) {
8
- this.channel = channel
7
+ public static init(transport: ITuffTransport) {
8
+ this.transport = transport
9
9
  }
10
10
 
11
11
  private static async checkCommand(
@@ -13,11 +13,11 @@ export class EnvDetector {
13
13
  versionArgs: string = '--version',
14
14
  versionRegex: RegExp = /(\d+\.\d+\.\d+)/,
15
15
  ): Promise<string | false> {
16
- if (!this.channel) {
17
- throw new Error('EnvDetector not initialized. Call EnvDetector.init(channel) first.')
16
+ if (!this.transport) {
17
+ throw new Error('EnvDetector not initialized. Call EnvDetector.init(transport) first.')
18
18
  }
19
19
  return new Promise((resolve) => {
20
- const terminal = new Terminal(this.channel)
20
+ const terminal = new Terminal(this.transport)
21
21
  let output = ''
22
22
  let resolved = false
23
23
 
@@ -68,11 +68,11 @@ export class EnvDetector {
68
68
  }
69
69
 
70
70
  static async getDegit(): Promise<boolean> {
71
- if (!this.channel) {
72
- throw new Error('EnvDetector not initialized. Call EnvDetector.init(channel) first.')
71
+ if (!this.transport) {
72
+ throw new Error('EnvDetector not initialized. Call EnvDetector.init(transport) first.')
73
73
  }
74
74
  return new Promise((resolve) => {
75
- const terminal = new Terminal(this.channel)
75
+ const terminal = new Terminal(this.transport)
76
76
  let receivedOutput = false
77
77
  let resolved = false
78
78