@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
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview TuffEvent Builder - Type-safe event definition system
|
|
3
|
+
* @module @talex-touch/utils/transport/event/builder
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { EventOptions, TuffEvent } from './types'
|
|
7
|
+
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// Builder Classes
|
|
10
|
+
// ============================================================================
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Namespace builder - Entry point for event definition.
|
|
14
|
+
*
|
|
15
|
+
* @typeParam TNamespace - The namespace string type
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const builder = TuffEventBuilder.namespace('core-box')
|
|
20
|
+
* // or use the shorthand:
|
|
21
|
+
* const builder = defineEvent('core-box')
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export class TuffEventBuilder<TNamespace extends string> {
|
|
25
|
+
private readonly _namespace: TNamespace
|
|
26
|
+
|
|
27
|
+
private constructor(namespace: TNamespace) {
|
|
28
|
+
this._namespace = namespace
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Creates a new event builder with the specified namespace.
|
|
33
|
+
*
|
|
34
|
+
* @param ns - The namespace string (e.g., 'core-box', 'storage')
|
|
35
|
+
* @returns A new TuffEventBuilder instance
|
|
36
|
+
* @throws {Error} If namespace is empty or not a string
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* const builder = TuffEventBuilder.namespace('my-plugin')
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
static namespace<T extends string>(ns: T): TuffEventBuilder<T> {
|
|
44
|
+
if (!ns || typeof ns !== 'string') {
|
|
45
|
+
throw new Error('[TuffEvent] Namespace must be a non-empty string')
|
|
46
|
+
}
|
|
47
|
+
return new TuffEventBuilder(ns)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Defines the module for this event.
|
|
52
|
+
*
|
|
53
|
+
* @param module - The module string (e.g., 'search', 'ui')
|
|
54
|
+
* @returns A TuffModuleBuilder instance
|
|
55
|
+
* @throws {Error} If module is empty or not a string
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```typescript
|
|
59
|
+
* defineEvent('core-box').module('search')
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
module<TModule extends string>(module: TModule): TuffModuleBuilder<TNamespace, TModule> {
|
|
63
|
+
if (!module || typeof module !== 'string') {
|
|
64
|
+
throw new Error('[TuffEvent] Module must be a non-empty string')
|
|
65
|
+
}
|
|
66
|
+
return new TuffModuleBuilder(this._namespace, module)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Module builder - Second stage of event definition.
|
|
72
|
+
*
|
|
73
|
+
* @typeParam TNamespace - The namespace string type
|
|
74
|
+
* @typeParam TModule - The module string type
|
|
75
|
+
*/
|
|
76
|
+
export class TuffModuleBuilder<
|
|
77
|
+
TNamespace extends string,
|
|
78
|
+
TModule extends string,
|
|
79
|
+
> {
|
|
80
|
+
/**
|
|
81
|
+
* @internal
|
|
82
|
+
*/
|
|
83
|
+
constructor(
|
|
84
|
+
private readonly _namespace: TNamespace,
|
|
85
|
+
private readonly _module: TModule,
|
|
86
|
+
) {}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Defines the action for this event.
|
|
90
|
+
*
|
|
91
|
+
* @param action - The action string (e.g., 'query', 'hide')
|
|
92
|
+
* @returns A TuffActionBuilder instance
|
|
93
|
+
* @throws {Error} If action is empty or not a string
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* defineEvent('core-box').module('search').event('query')
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
event<TAction extends string>(action: TAction): TuffActionBuilder<TNamespace, TModule, TAction> {
|
|
101
|
+
if (!action || typeof action !== 'string') {
|
|
102
|
+
throw new Error('[TuffEvent] Action must be a non-empty string')
|
|
103
|
+
}
|
|
104
|
+
return new TuffActionBuilder(this._namespace, this._module, action)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Action builder - Final stage of event definition.
|
|
110
|
+
*
|
|
111
|
+
* @typeParam TNamespace - The namespace string type
|
|
112
|
+
* @typeParam TModule - The module string type
|
|
113
|
+
* @typeParam TAction - The action string type
|
|
114
|
+
*/
|
|
115
|
+
export class TuffActionBuilder<
|
|
116
|
+
TNamespace extends string,
|
|
117
|
+
TModule extends string,
|
|
118
|
+
TAction extends string,
|
|
119
|
+
> {
|
|
120
|
+
/**
|
|
121
|
+
* @internal
|
|
122
|
+
*/
|
|
123
|
+
constructor(
|
|
124
|
+
private readonly _namespace: TNamespace,
|
|
125
|
+
private readonly _module: TModule,
|
|
126
|
+
private readonly _action: TAction,
|
|
127
|
+
) {}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Finalizes the event definition with request/response types.
|
|
131
|
+
*
|
|
132
|
+
* @typeParam TRequest - Type of the request payload (default: void)
|
|
133
|
+
* @typeParam TResponse - Type of the response payload (default: void)
|
|
134
|
+
* @param options - Optional batch/stream configuration
|
|
135
|
+
* @returns An immutable TuffEvent instance
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```typescript
|
|
139
|
+
* // Simple event with no payload
|
|
140
|
+
* const hideEvent = defineEvent('core-box')
|
|
141
|
+
* .module('ui')
|
|
142
|
+
* .event('hide')
|
|
143
|
+
* .define()
|
|
144
|
+
*
|
|
145
|
+
* // Event with typed request/response
|
|
146
|
+
* const queryEvent = defineEvent('core-box')
|
|
147
|
+
* .module('search')
|
|
148
|
+
* .event('query')
|
|
149
|
+
* .define<{ text: string }, SearchResult[]>()
|
|
150
|
+
*
|
|
151
|
+
* // Event with batch configuration
|
|
152
|
+
* const getEvent = defineEvent('storage')
|
|
153
|
+
* .module('app')
|
|
154
|
+
* .event('get')
|
|
155
|
+
* .define<{ key: string }, unknown>({
|
|
156
|
+
* batch: { enabled: true, windowMs: 50 }
|
|
157
|
+
* })
|
|
158
|
+
*
|
|
159
|
+
* // Stream event
|
|
160
|
+
* const streamEvent = defineEvent('core-box')
|
|
161
|
+
* .module('search')
|
|
162
|
+
* .event('stream')
|
|
163
|
+
* .define<{ text: string }, AsyncIterable<SearchResult>>({
|
|
164
|
+
* stream: { enabled: true }
|
|
165
|
+
* })
|
|
166
|
+
* ```
|
|
167
|
+
*/
|
|
168
|
+
define<TRequest = void, TResponse = void>(
|
|
169
|
+
options?: EventOptions,
|
|
170
|
+
): TuffEvent<TRequest, TResponse, TNamespace, TModule, TAction> {
|
|
171
|
+
const namespace = this._namespace
|
|
172
|
+
const module = this._module
|
|
173
|
+
const action = this._action
|
|
174
|
+
const eventName = `${namespace}:${module}:${action}`
|
|
175
|
+
|
|
176
|
+
// Create immutable event object
|
|
177
|
+
const event: TuffEvent<TRequest, TResponse, TNamespace, TModule, TAction> = Object.freeze({
|
|
178
|
+
__brand: 'TuffEvent' as const,
|
|
179
|
+
namespace,
|
|
180
|
+
module,
|
|
181
|
+
action,
|
|
182
|
+
_batch: options?.batch,
|
|
183
|
+
_stream: options?.stream,
|
|
184
|
+
_request: undefined as unknown as TRequest,
|
|
185
|
+
_response: undefined as unknown as TResponse,
|
|
186
|
+
|
|
187
|
+
toString(): string {
|
|
188
|
+
return eventName
|
|
189
|
+
},
|
|
190
|
+
|
|
191
|
+
toEventName(): string {
|
|
192
|
+
return eventName
|
|
193
|
+
},
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
return event
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// ============================================================================
|
|
201
|
+
// Shorthand Functions
|
|
202
|
+
// ============================================================================
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Creates a new event definition builder.
|
|
206
|
+
*
|
|
207
|
+
* @remarks
|
|
208
|
+
* This is the primary entry point for defining TuffEvents.
|
|
209
|
+
* All events MUST be created using this builder to ensure type safety.
|
|
210
|
+
*
|
|
211
|
+
* @param namespace - The event namespace (e.g., 'core-box', 'storage', 'plugin')
|
|
212
|
+
* @returns A TuffEventBuilder instance
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* ```typescript
|
|
216
|
+
* // Define a simple event
|
|
217
|
+
* const hideEvent = defineEvent('core-box')
|
|
218
|
+
* .module('ui')
|
|
219
|
+
* .event('hide')
|
|
220
|
+
* .define()
|
|
221
|
+
*
|
|
222
|
+
* // Define an event with typed payloads
|
|
223
|
+
* const queryEvent = defineEvent('core-box')
|
|
224
|
+
* .module('search')
|
|
225
|
+
* .event('query')
|
|
226
|
+
* .define<QueryRequest, QueryResponse>()
|
|
227
|
+
*
|
|
228
|
+
* // Define a batch-enabled event
|
|
229
|
+
* const getEvent = defineEvent('storage')
|
|
230
|
+
* .module('app')
|
|
231
|
+
* .event('get')
|
|
232
|
+
* .define<{ key: string }, unknown>({
|
|
233
|
+
* batch: { enabled: true, windowMs: 50, maxSize: 20 }
|
|
234
|
+
* })
|
|
235
|
+
* ```
|
|
236
|
+
*/
|
|
237
|
+
export const defineEvent = TuffEventBuilder.namespace
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Defines a TuffEvent using a raw event name string.
|
|
241
|
+
*
|
|
242
|
+
* @remarks
|
|
243
|
+
* This is intended for incremental migrations from legacy IPC event names that
|
|
244
|
+
* don't follow the `namespace:module:action` convention yet.
|
|
245
|
+
*
|
|
246
|
+
* Prefer `defineEvent(namespace).module(module).event(action)` for new code.
|
|
247
|
+
*/
|
|
248
|
+
export function defineRawEvent<TRequest = void, TResponse = void>(
|
|
249
|
+
eventName: string,
|
|
250
|
+
options?: EventOptions,
|
|
251
|
+
): TuffEvent<TRequest, TResponse, string, string, string> {
|
|
252
|
+
if (!eventName || typeof eventName !== 'string') {
|
|
253
|
+
throw new Error('[TuffEvent] Raw event name must be a non-empty string')
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const parts = eventName.split(':')
|
|
257
|
+
const namespace = parts[0] || 'raw'
|
|
258
|
+
const module = parts.length >= 2 ? (parts[1] || 'raw') : 'raw'
|
|
259
|
+
const action = parts.length >= 3 ? (parts.slice(2).join(':') || 'raw') : 'raw'
|
|
260
|
+
|
|
261
|
+
const event: TuffEvent<TRequest, TResponse, string, string, string> = Object.freeze({
|
|
262
|
+
__brand: 'TuffEvent' as const,
|
|
263
|
+
namespace,
|
|
264
|
+
module,
|
|
265
|
+
action,
|
|
266
|
+
_batch: options?.batch,
|
|
267
|
+
_stream: options?.stream,
|
|
268
|
+
_request: undefined as unknown as TRequest,
|
|
269
|
+
_response: undefined as unknown as TResponse,
|
|
270
|
+
|
|
271
|
+
toString(): string {
|
|
272
|
+
return eventName
|
|
273
|
+
},
|
|
274
|
+
|
|
275
|
+
toEventName(): string {
|
|
276
|
+
return eventName
|
|
277
|
+
},
|
|
278
|
+
})
|
|
279
|
+
|
|
280
|
+
return event
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// ============================================================================
|
|
284
|
+
// Type Guards and Assertions
|
|
285
|
+
// ============================================================================
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Runtime type guard to check if a value is a valid TuffEvent.
|
|
289
|
+
*
|
|
290
|
+
* @param value - The value to check
|
|
291
|
+
* @returns `true` if the value is a TuffEvent, `false` otherwise
|
|
292
|
+
*
|
|
293
|
+
* @example
|
|
294
|
+
* ```typescript
|
|
295
|
+
* if (isTuffEvent(maybeEvent)) {
|
|
296
|
+
* // TypeScript now knows maybeEvent is a TuffEvent
|
|
297
|
+
* console.log(maybeEvent.toString())
|
|
298
|
+
* }
|
|
299
|
+
* ```
|
|
300
|
+
*/
|
|
301
|
+
export function isTuffEvent(value: unknown): value is TuffEvent {
|
|
302
|
+
return (
|
|
303
|
+
typeof value === 'object'
|
|
304
|
+
&& value !== null
|
|
305
|
+
&& (value as Record<string, unknown>).__brand === 'TuffEvent'
|
|
306
|
+
&& typeof (value as Record<string, unknown>).toString === 'function'
|
|
307
|
+
&& typeof (value as Record<string, unknown>).namespace === 'string'
|
|
308
|
+
&& typeof (value as Record<string, unknown>).module === 'string'
|
|
309
|
+
&& typeof (value as Record<string, unknown>).action === 'string'
|
|
310
|
+
)
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Asserts that a value is a valid TuffEvent, throwing if not.
|
|
315
|
+
*
|
|
316
|
+
* @param value - The value to assert
|
|
317
|
+
* @param context - Optional context string for error messages
|
|
318
|
+
* @throws {TypeError} If the value is not a TuffEvent
|
|
319
|
+
*
|
|
320
|
+
* @example
|
|
321
|
+
* ```typescript
|
|
322
|
+
* function sendEvent(event: unknown, payload: unknown) {
|
|
323
|
+
* assertTuffEvent(event, 'sendEvent')
|
|
324
|
+
* // TypeScript now knows event is a TuffEvent
|
|
325
|
+
* console.log(`Sending: ${event.toString()}`)
|
|
326
|
+
* }
|
|
327
|
+
* ```
|
|
328
|
+
*/
|
|
329
|
+
export function assertTuffEvent(
|
|
330
|
+
value: unknown,
|
|
331
|
+
context?: string,
|
|
332
|
+
): asserts value is TuffEvent {
|
|
333
|
+
if (!isTuffEvent(value)) {
|
|
334
|
+
const prefix = context ? `[${context}] ` : ''
|
|
335
|
+
throw new TypeError(
|
|
336
|
+
`${prefix}Invalid event. Expected TuffEvent created via defineEvent(), `
|
|
337
|
+
+ `got ${value === null ? 'null' : typeof value}. `
|
|
338
|
+
+ `String event names are not allowed - use the event builder.`,
|
|
339
|
+
)
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Extracts the event name string from a TuffEvent.
|
|
345
|
+
*
|
|
346
|
+
* @param event - The TuffEvent to extract from
|
|
347
|
+
* @returns The event name string
|
|
348
|
+
*
|
|
349
|
+
* @example
|
|
350
|
+
* ```typescript
|
|
351
|
+
* const name = getEventName(CoreBoxEvents.ui.hide)
|
|
352
|
+
* // name = 'core-box:ui:hide'
|
|
353
|
+
* ```
|
|
354
|
+
*/
|
|
355
|
+
export function getEventName(event: TuffEvent): string {
|
|
356
|
+
assertTuffEvent(event, 'getEventName')
|
|
357
|
+
return event.toString()
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Checks if an event has batch configuration enabled.
|
|
362
|
+
*
|
|
363
|
+
* @param event - The TuffEvent to check
|
|
364
|
+
* @returns `true` if batch is enabled
|
|
365
|
+
*/
|
|
366
|
+
export function isBatchEnabled(event: TuffEvent): boolean {
|
|
367
|
+
return event._batch?.enabled === true
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Checks if an event has stream configuration enabled.
|
|
372
|
+
*
|
|
373
|
+
* @param event - The TuffEvent to check
|
|
374
|
+
* @returns `true` if stream is enabled
|
|
375
|
+
*/
|
|
376
|
+
export function isStreamEnabled(event: TuffEvent): boolean {
|
|
377
|
+
return event._stream?.enabled === true
|
|
378
|
+
}
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Core type definitions for TuffEvent system
|
|
3
|
+
* @module @talex-touch/utils/transport/event/types
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// Brand Symbol for Type Safety
|
|
8
|
+
// ============================================================================
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Unique symbol used for branding TuffEvent instances.
|
|
12
|
+
* This ensures type-level distinction from plain objects.
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
declare const _TuffEventBrand: unique symbol
|
|
16
|
+
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// Configuration Types
|
|
19
|
+
// ============================================================================
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Merge strategy for batch requests.
|
|
23
|
+
*
|
|
24
|
+
* @remarks
|
|
25
|
+
* - `queue` - All requests are queued in order
|
|
26
|
+
* - `dedupe` - Duplicate payloads share a single request/response
|
|
27
|
+
* - `latest` - Only the latest request for a given key is kept
|
|
28
|
+
*/
|
|
29
|
+
export type BatchMergeStrategy = 'queue' | 'dedupe' | 'latest'
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Backpressure strategy for stream processing.
|
|
33
|
+
*
|
|
34
|
+
* @remarks
|
|
35
|
+
* - `drop` - Drop new data when buffer is full
|
|
36
|
+
* - `buffer` - Buffer data (may cause memory growth)
|
|
37
|
+
* - `error` - Throw error when buffer is full
|
|
38
|
+
*/
|
|
39
|
+
export type StreamBackpressure = 'drop' | 'buffer' | 'error'
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Configuration for batch request merging.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const config: BatchConfig = {
|
|
47
|
+
* enabled: true,
|
|
48
|
+
* windowMs: 50,
|
|
49
|
+
* maxSize: 20,
|
|
50
|
+
* mergeStrategy: 'dedupe'
|
|
51
|
+
* }
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export interface BatchConfig {
|
|
55
|
+
/**
|
|
56
|
+
* Whether batch mode is enabled for this event.
|
|
57
|
+
* @defaultValue false
|
|
58
|
+
*/
|
|
59
|
+
enabled: boolean
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Time window in milliseconds to collect requests before flushing.
|
|
63
|
+
* @defaultValue 50
|
|
64
|
+
*/
|
|
65
|
+
windowMs?: number
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Maximum number of requests to batch before forcing a flush.
|
|
69
|
+
* @defaultValue 50
|
|
70
|
+
*/
|
|
71
|
+
maxSize?: number
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Strategy for merging duplicate requests.
|
|
75
|
+
* @defaultValue 'queue'
|
|
76
|
+
*/
|
|
77
|
+
mergeStrategy?: BatchMergeStrategy
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Configuration for stream-based communication.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```typescript
|
|
85
|
+
* const config: StreamConfig = {
|
|
86
|
+
* enabled: true,
|
|
87
|
+
* bufferSize: 100,
|
|
88
|
+
* backpressure: 'buffer'
|
|
89
|
+
* }
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
export interface StreamConfig {
|
|
93
|
+
/**
|
|
94
|
+
* Whether stream mode is enabled for this event.
|
|
95
|
+
* @defaultValue false
|
|
96
|
+
*/
|
|
97
|
+
enabled: boolean
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Maximum number of items to buffer.
|
|
101
|
+
* @defaultValue 100
|
|
102
|
+
*/
|
|
103
|
+
bufferSize?: number
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Strategy for handling backpressure.
|
|
107
|
+
* @defaultValue 'buffer'
|
|
108
|
+
*/
|
|
109
|
+
backpressure?: StreamBackpressure
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Options for event definition.
|
|
114
|
+
*/
|
|
115
|
+
export interface EventOptions {
|
|
116
|
+
/**
|
|
117
|
+
* Batch configuration for this event.
|
|
118
|
+
*/
|
|
119
|
+
batch?: BatchConfig
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Stream configuration for this event.
|
|
123
|
+
*/
|
|
124
|
+
stream?: StreamConfig
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ============================================================================
|
|
128
|
+
// TuffEvent Core Interface
|
|
129
|
+
// ============================================================================
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Type-safe event definition for TuffTransport.
|
|
133
|
+
*
|
|
134
|
+
* @remarks
|
|
135
|
+
* TuffEvent instances are immutable and created via the event builder.
|
|
136
|
+
* They encode request/response types at the type level for compile-time safety.
|
|
137
|
+
*
|
|
138
|
+
* @typeParam TRequest - Type of the request payload
|
|
139
|
+
* @typeParam TResponse - Type of the response payload
|
|
140
|
+
* @typeParam TNamespace - Event namespace (e.g., 'core-box')
|
|
141
|
+
* @typeParam TModule - Event module (e.g., 'search')
|
|
142
|
+
* @typeParam TAction - Event action (e.g., 'query')
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* ```typescript
|
|
146
|
+
* const event: TuffEvent<{ text: string }, SearchResult[]> = defineEvent('core-box')
|
|
147
|
+
* .module('search')
|
|
148
|
+
* .event('query')
|
|
149
|
+
* .define()
|
|
150
|
+
*
|
|
151
|
+
* // event.toString() returns 'core-box:search:query'
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
export interface TuffEvent<
|
|
155
|
+
TRequest = void,
|
|
156
|
+
TResponse = void,
|
|
157
|
+
TNamespace extends string = string,
|
|
158
|
+
TModule extends string = string,
|
|
159
|
+
TAction extends string = string,
|
|
160
|
+
> {
|
|
161
|
+
/**
|
|
162
|
+
* Brand identifier for runtime type checking.
|
|
163
|
+
* @internal
|
|
164
|
+
*/
|
|
165
|
+
readonly __brand: 'TuffEvent'
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Event namespace (first segment of event name).
|
|
169
|
+
* @example 'core-box', 'storage', 'plugin'
|
|
170
|
+
*/
|
|
171
|
+
readonly namespace: TNamespace
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Event module (second segment of event name).
|
|
175
|
+
* @example 'search', 'ui', 'lifecycle'
|
|
176
|
+
*/
|
|
177
|
+
readonly module: TModule
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Event action (third segment of event name).
|
|
181
|
+
* @example 'query', 'hide', 'load'
|
|
182
|
+
*/
|
|
183
|
+
readonly action: TAction
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Batch configuration for this event.
|
|
187
|
+
* @internal
|
|
188
|
+
*/
|
|
189
|
+
readonly _batch?: BatchConfig
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Stream configuration for this event.
|
|
193
|
+
* @internal
|
|
194
|
+
*/
|
|
195
|
+
readonly _stream?: StreamConfig
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Type marker for request payload (compile-time only).
|
|
199
|
+
* @internal
|
|
200
|
+
*/
|
|
201
|
+
readonly _request: TRequest
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Type marker for response payload (compile-time only).
|
|
205
|
+
* @internal
|
|
206
|
+
*/
|
|
207
|
+
readonly _response: TResponse
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Converts event to its string representation.
|
|
211
|
+
* @returns Event name in format 'namespace:module:action'
|
|
212
|
+
*/
|
|
213
|
+
toString: () => string
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Gets the full event name.
|
|
217
|
+
* @returns Event name in format 'namespace:module:action'
|
|
218
|
+
*/
|
|
219
|
+
toEventName: () => string
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// ============================================================================
|
|
223
|
+
// Type Utilities
|
|
224
|
+
// ============================================================================
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Extracts the request type from a TuffEvent.
|
|
228
|
+
*
|
|
229
|
+
* @typeParam E - The TuffEvent type
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* ```typescript
|
|
233
|
+
* type Req = EventRequest<typeof CoreBoxEvents.search.query>
|
|
234
|
+
* // Req = { text: string }
|
|
235
|
+
* ```
|
|
236
|
+
*/
|
|
237
|
+
export type EventRequest<E> = E extends TuffEvent<infer R, any, any, any, any> ? R : never
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Extracts the response type from a TuffEvent.
|
|
241
|
+
*
|
|
242
|
+
* @typeParam E - The TuffEvent type
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* ```typescript
|
|
246
|
+
* type Res = EventResponse<typeof CoreBoxEvents.search.query>
|
|
247
|
+
* // Res = TuffSearchResult
|
|
248
|
+
* ```
|
|
249
|
+
*/
|
|
250
|
+
export type EventResponse<E> = E extends TuffEvent<any, infer R, any, any, any> ? R : never
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Checks if an event is a stream event (response is AsyncIterable).
|
|
254
|
+
*
|
|
255
|
+
* @typeParam E - The TuffEvent type
|
|
256
|
+
*/
|
|
257
|
+
export type IsStreamEvent<E> = E extends TuffEvent<any, AsyncIterable<any>, any, any, any>
|
|
258
|
+
? true
|
|
259
|
+
: false
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Extracts the chunk type from a stream event.
|
|
263
|
+
*
|
|
264
|
+
* @typeParam E - The TuffEvent type (must be a stream event)
|
|
265
|
+
*
|
|
266
|
+
* @example
|
|
267
|
+
* ```typescript
|
|
268
|
+
* type Chunk = StreamChunk<typeof CoreBoxEvents.search.stream>
|
|
269
|
+
* // Chunk = SearchResult
|
|
270
|
+
* ```
|
|
271
|
+
*/
|
|
272
|
+
export type StreamChunk<E> = E extends TuffEvent<any, AsyncIterable<infer C>, any, any, any>
|
|
273
|
+
? C
|
|
274
|
+
: never
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Extracts the namespace from a TuffEvent.
|
|
278
|
+
* @internal
|
|
279
|
+
*/
|
|
280
|
+
export type EventNamespace<E> = E extends TuffEvent<any, any, infer N, any, any> ? N : never
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Extracts the module from a TuffEvent.
|
|
284
|
+
* @internal
|
|
285
|
+
*/
|
|
286
|
+
export type EventModule<E> = E extends TuffEvent<any, any, any, infer M, any> ? M : never
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Extracts the action from a TuffEvent.
|
|
290
|
+
* @internal
|
|
291
|
+
*/
|
|
292
|
+
export type EventAction<E> = E extends TuffEvent<any, any, any, any, infer A> ? A : never
|