@talex-touch/utils 1.0.42 → 1.0.45
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 +32 -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 +9 -5
- package/market/index.ts +1 -1
- package/market/types.ts +19 -4
- 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 +80 -7
- 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 -4
- package/plugin/providers/market-client.ts +6 -3
- package/plugin/providers/npm-provider.ts +22 -7
- package/plugin/providers/tpex-provider.ts +22 -8
- 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 +13 -6
- 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/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 +16 -2
- 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 +55 -214
- 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 +31 -40
- 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 +2690 -0
- package/transport/events/meta-overlay.ts +79 -0
- package/transport/events/types/agents.ts +177 -0
- package/transport/events/types/app-index.ts +20 -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 +84 -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 +631 -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 +141 -0
- package/transport/main.ts +2 -0
- package/transport/prelude.ts +208 -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 +102 -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 +31 -31
- 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 +166 -173
- 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
|
@@ -1,20 +1,23 @@
|
|
|
1
|
-
import type {
|
|
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
|
-
IntelligenceProviderType,
|
|
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
17
|
export { IntelligenceProviderType }
|
|
15
|
-
export type {
|
|
18
|
+
export type { IntelligenceGlobalConfig, IntelligenceProviderConfig }
|
|
16
19
|
|
|
17
|
-
const defaultIntelligenceData:
|
|
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<
|
|
30
|
+
class IntelligenceStorage extends TouchStorage<IntelligenceStorageData> {
|
|
27
31
|
constructor() {
|
|
28
32
|
super(StorageList.IntelligenceConfig, defaultIntelligenceData)
|
|
29
33
|
this.setAutoSave(true)
|
|
@@ -50,8 +54,11 @@ class IntelligenceStorage extends TouchStorage<AISDKStorageData> {
|
|
|
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
|
-
...
|
|
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<
|
|
88
|
+
updateGlobalConfig(config: Partial<IntelligenceGlobalConfig>): void {
|
|
82
89
|
const currentData = this.get()
|
|
83
90
|
|
|
84
91
|
this.set({
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
186
|
+
intelligenceStorageLog.info(`Migration to v2 complete, capabilities count: ${Object.keys(DEFAULT_CAPABILITIES).length}`)
|
|
186
187
|
}
|
|
187
188
|
else {
|
|
188
|
-
|
|
189
|
+
intelligenceStorageLog.info(`No migration needed, current version: ${currentData.version}`)
|
|
189
190
|
}
|
|
190
191
|
|
|
191
|
-
|
|
192
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
23
|
-
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
66
|
-
if (
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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
|
-
|
|
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
|
|
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 {
|
|
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
|
|
5
|
+
private static transport: ITuffTransport
|
|
6
6
|
|
|
7
|
-
public static init(
|
|
8
|
-
this.
|
|
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.
|
|
17
|
-
throw new Error('EnvDetector not initialized. Call EnvDetector.init(
|
|
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.
|
|
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.
|
|
72
|
-
throw new Error('EnvDetector not initialized. Call EnvDetector.init(
|
|
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.
|
|
75
|
+
const terminal = new Terminal(this.transport)
|
|
76
76
|
let receivedOutput = false
|
|
77
77
|
let resolved = false
|
|
78
78
|
|
|
@@ -1,7 +1,32 @@
|
|
|
1
1
|
import type { ITouchClientChannel } from '@talex-touch/utils/channel'
|
|
2
|
+
import type { ITuffTransport, TuffEvent } from '@talex-touch/utils/transport'
|
|
3
|
+
import { defineRawEvent } from '@talex-touch/utils/transport/event/builder'
|
|
4
|
+
|
|
5
|
+
const legacyCloseEvent = defineRawEvent<void, void>('close')
|
|
6
|
+
const legacyHideEvent = defineRawEvent<void, void>('hide')
|
|
7
|
+
const legacyMinimizeEvent = defineRawEvent<void, void>('minimize')
|
|
8
|
+
const legacyDevToolsEvent = defineRawEvent<void, void>('dev-tools')
|
|
9
|
+
const legacyCwdEvent = defineRawEvent<void, string>('common:cwd')
|
|
10
|
+
const legacyPackageEvent = defineRawEvent<void, any>('get-package')
|
|
11
|
+
const legacyOsEvent = defineRawEvent<void, any>('get-os')
|
|
12
|
+
const legacyFolderOpenEvent = defineRawEvent<FolderOpenOptions, void>('folder:open')
|
|
13
|
+
const legacyExecuteCmdEvent = defineRawEvent<ExecuteCommandOptions, void>('execute:cmd')
|
|
14
|
+
const legacyAppOpenEvent = defineRawEvent<AppOpenOptions, void>('app:open')
|
|
15
|
+
const legacyOpenExternalEvent = defineRawEvent<ExternalUrlOptions, void>('open-external')
|
|
16
|
+
const legacyTempFileCreateEvent = defineRawEvent<TempFileCreateOptions, TempFileCreateResult>(
|
|
17
|
+
'temp-file:create',
|
|
18
|
+
)
|
|
19
|
+
const legacyTempFileDeleteEvent = defineRawEvent<TempFileDeleteOptions, TempFileDeleteResult>(
|
|
20
|
+
'temp-file:delete',
|
|
21
|
+
)
|
|
22
|
+
const legacyPluginFolderEvent = defineRawEvent<string, void>('plugin:explorer')
|
|
23
|
+
const legacyPluginDevToolsEvent = defineRawEvent<string, void>('plugin:open-devtools')
|
|
24
|
+
const legacyPluginReloadEvent = defineRawEvent<{ name: string }, void>('reload-plugin')
|
|
25
|
+
const legacyModuleFolderEvent = defineRawEvent<{ name?: string }, void>('module:folder')
|
|
2
26
|
|
|
3
27
|
export interface TouchSDKOptions {
|
|
4
|
-
|
|
28
|
+
transport?: ITuffTransport
|
|
29
|
+
channel?: ITouchClientChannel
|
|
5
30
|
}
|
|
6
31
|
|
|
7
32
|
export interface FolderOpenOptions {
|
|
@@ -21,68 +46,130 @@ export interface ExternalUrlOptions {
|
|
|
21
46
|
url: string
|
|
22
47
|
}
|
|
23
48
|
|
|
49
|
+
export interface TempFileCreateOptions {
|
|
50
|
+
namespace: string
|
|
51
|
+
ext?: string
|
|
52
|
+
text?: string
|
|
53
|
+
base64?: string
|
|
54
|
+
prefix?: string
|
|
55
|
+
retentionMs?: number
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface TempFileCreateResult {
|
|
59
|
+
url: string
|
|
60
|
+
sizeBytes: number
|
|
61
|
+
createdAt: number
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface TempFileDeleteOptions {
|
|
65
|
+
url?: string
|
|
66
|
+
path?: string
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface TempFileDeleteResult {
|
|
70
|
+
success: boolean
|
|
71
|
+
}
|
|
72
|
+
|
|
24
73
|
export class TouchSDK {
|
|
25
|
-
private
|
|
74
|
+
private transport: ITuffTransport | null
|
|
75
|
+
private channel: ITouchClientChannel | null
|
|
26
76
|
|
|
27
77
|
constructor(options: TouchSDKOptions) {
|
|
28
|
-
this.
|
|
78
|
+
this.transport = options.transport ?? null
|
|
79
|
+
this.channel = options.channel ?? null
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private async sendEvent<TReq, TRes>(event: TuffEvent<TReq, TRes>, payload?: TReq): Promise<TRes> {
|
|
83
|
+
if (this.transport) {
|
|
84
|
+
const shouldPassPayload = payload !== undefined
|
|
85
|
+
if (shouldPassPayload) {
|
|
86
|
+
return this.transport.send(event, payload)
|
|
87
|
+
}
|
|
88
|
+
return this.transport.send(event as TuffEvent<void, TRes>)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (this.channel) {
|
|
92
|
+
return this.channel.send(event.toEventName(), payload as any) as Promise<TRes>
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
throw new Error('[TouchSDK] Transport or channel not initialized.')
|
|
29
96
|
}
|
|
30
97
|
|
|
31
98
|
/**
|
|
32
99
|
* System Operations
|
|
33
100
|
*/
|
|
34
101
|
async closeApp(): Promise<void> {
|
|
35
|
-
return this.
|
|
102
|
+
return this.sendEvent(legacyCloseEvent)
|
|
36
103
|
}
|
|
37
104
|
|
|
38
105
|
async hideApp(): Promise<void> {
|
|
39
|
-
return this.
|
|
106
|
+
return this.sendEvent(legacyHideEvent)
|
|
40
107
|
}
|
|
41
108
|
|
|
42
109
|
async minimizeApp(): Promise<void> {
|
|
43
|
-
return this.
|
|
110
|
+
return this.sendEvent(legacyMinimizeEvent)
|
|
44
111
|
}
|
|
45
112
|
|
|
46
113
|
async openDevTools(): Promise<void> {
|
|
47
|
-
return this.
|
|
114
|
+
return this.sendEvent(legacyDevToolsEvent)
|
|
48
115
|
}
|
|
49
116
|
|
|
50
117
|
async getCurrentWorkingDirectory(): Promise<string> {
|
|
51
|
-
return this.
|
|
118
|
+
return this.sendEvent(legacyCwdEvent)
|
|
52
119
|
}
|
|
53
120
|
|
|
54
121
|
async getPackageInfo(): Promise<any> {
|
|
55
|
-
return this.
|
|
122
|
+
return this.sendEvent(legacyPackageEvent)
|
|
56
123
|
}
|
|
57
124
|
|
|
58
125
|
async getOSInfo(): Promise<any> {
|
|
59
|
-
return this.
|
|
126
|
+
return this.sendEvent(legacyOsEvent)
|
|
60
127
|
}
|
|
61
128
|
|
|
62
129
|
/**
|
|
63
130
|
* File & Folder Operations
|
|
64
131
|
*/
|
|
65
132
|
async openFolder(options: FolderOpenOptions): Promise<void> {
|
|
66
|
-
return this.
|
|
133
|
+
return this.sendEvent(legacyFolderOpenEvent, options)
|
|
67
134
|
}
|
|
68
135
|
|
|
69
136
|
async executeCommand(options: ExecuteCommandOptions): Promise<void> {
|
|
70
|
-
return this.
|
|
137
|
+
return this.sendEvent(legacyExecuteCmdEvent, options)
|
|
71
138
|
}
|
|
72
139
|
|
|
73
140
|
async openApp(options: AppOpenOptions): Promise<void> {
|
|
74
|
-
return this.
|
|
141
|
+
return this.sendEvent(legacyAppOpenEvent, options)
|
|
75
142
|
}
|
|
76
143
|
|
|
77
144
|
async openExternalUrl(options: ExternalUrlOptions): Promise<void> {
|
|
78
|
-
return this.
|
|
145
|
+
return this.sendEvent(legacyOpenExternalEvent, options)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Temp file operations
|
|
150
|
+
*/
|
|
151
|
+
async createTempFile(options: TempFileCreateOptions): Promise<TempFileCreateResult> {
|
|
152
|
+
return this.sendEvent(legacyTempFileCreateEvent, options)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
async deleteTempFile(options: TempFileDeleteOptions): Promise<TempFileDeleteResult> {
|
|
156
|
+
return this.sendEvent(legacyTempFileDeleteEvent, options)
|
|
79
157
|
}
|
|
80
158
|
|
|
81
159
|
/**
|
|
82
160
|
* Plugin Operations
|
|
83
161
|
*/
|
|
84
162
|
async openPluginFolder(pluginName: string): Promise<void> {
|
|
85
|
-
return this.
|
|
163
|
+
return this.sendEvent(legacyPluginFolderEvent, pluginName)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Opens the DevTools for a plugin's Surface WebContents
|
|
168
|
+
* @param pluginName - The name of the plugin to open DevTools for
|
|
169
|
+
* @returns Promise that resolves when DevTools is opened
|
|
170
|
+
*/
|
|
171
|
+
async openPluginDevTools(pluginName: string): Promise<void> {
|
|
172
|
+
return this.sendEvent(legacyPluginDevToolsEvent, pluginName)
|
|
86
173
|
}
|
|
87
174
|
|
|
88
175
|
/**
|
|
@@ -91,27 +178,36 @@ export class TouchSDK {
|
|
|
91
178
|
* @returns Promise that resolves when the reload operation completes
|
|
92
179
|
*/
|
|
93
180
|
async reloadPlugin(pluginName: string): Promise<void> {
|
|
94
|
-
return this.
|
|
181
|
+
return this.sendEvent(legacyPluginReloadEvent, { name: pluginName })
|
|
95
182
|
}
|
|
96
183
|
|
|
97
184
|
/**
|
|
98
185
|
* Module Operations
|
|
99
186
|
*/
|
|
100
187
|
async openModuleFolder(moduleName?: string): Promise<void> {
|
|
101
|
-
return this.
|
|
188
|
+
return this.sendEvent(legacyModuleFolderEvent, { name: moduleName })
|
|
102
189
|
}
|
|
103
190
|
|
|
104
191
|
/**
|
|
105
192
|
* Event Registration
|
|
106
193
|
*/
|
|
107
194
|
onChannelEvent(eventName: string, callback: (data: any) => void): () => void {
|
|
108
|
-
|
|
195
|
+
if (this.transport) {
|
|
196
|
+
return this.transport.on(defineRawEvent<any, any>(eventName), callback)
|
|
197
|
+
}
|
|
198
|
+
if (this.channel) {
|
|
199
|
+
return this.channel.regChannel(eventName, callback)
|
|
200
|
+
}
|
|
201
|
+
throw new Error('[TouchSDK] Transport or channel not initialized.')
|
|
109
202
|
}
|
|
110
203
|
|
|
111
204
|
/**
|
|
112
205
|
* Raw channel access for advanced usage
|
|
113
206
|
*/
|
|
114
207
|
get rawChannel(): ITouchClientChannel {
|
|
208
|
+
if (!this.channel) {
|
|
209
|
+
throw new Error('[TouchSDK] Channel not initialized.')
|
|
210
|
+
}
|
|
115
211
|
return this.channel
|
|
116
212
|
}
|
|
117
213
|
}
|