@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.
Files changed (234) 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 +32 -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 +9 -5
  72. package/market/index.ts +1 -1
  73. package/market/types.ts +19 -4
  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 +80 -7
  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 -4
  87. package/plugin/providers/market-client.ts +6 -3
  88. package/plugin/providers/npm-provider.ts +22 -7
  89. package/plugin/providers/tpex-provider.ts +22 -8
  90. package/plugin/sdk/box-items.ts +14 -0
  91. package/plugin/sdk/box-sdk.ts +64 -0
  92. package/plugin/sdk/channel.ts +119 -4
  93. package/plugin/sdk/clipboard.ts +26 -12
  94. package/plugin/sdk/cloud-sync.ts +113 -0
  95. package/plugin/sdk/common.ts +19 -11
  96. package/plugin/sdk/core-box.ts +6 -15
  97. package/plugin/sdk/division-box.ts +160 -65
  98. package/plugin/sdk/examples/storage-onDidChange-example.js +5 -2
  99. package/plugin/sdk/feature-sdk.ts +111 -76
  100. package/plugin/sdk/flow.ts +146 -45
  101. package/plugin/sdk/hooks/bridge.ts +13 -6
  102. package/plugin/sdk/hooks/life-cycle.ts +35 -16
  103. package/plugin/sdk/index.ts +14 -3
  104. package/plugin/sdk/intelligence.ts +87 -0
  105. package/plugin/sdk/meta/README.md +179 -0
  106. package/plugin/sdk/meta-sdk.ts +244 -0
  107. package/plugin/sdk/notification.ts +9 -0
  108. package/plugin/sdk/plugin-info.ts +64 -0
  109. package/plugin/sdk/power.ts +155 -0
  110. package/plugin/sdk/recommend.ts +21 -0
  111. package/plugin/sdk/service/index.ts +12 -8
  112. package/plugin/sdk/sqlite.ts +141 -0
  113. package/plugin/sdk/storage.ts +2 -6
  114. package/plugin/sdk/system.ts +2 -9
  115. package/plugin/sdk/temp-files.ts +41 -0
  116. package/plugin/sdk/touch-sdk.ts +18 -0
  117. package/plugin/sdk/types.ts +44 -4
  118. package/plugin/sdk/window/index.ts +12 -9
  119. package/plugin/sdk-version.ts +231 -0
  120. package/preload/renderer.ts +3 -2
  121. package/renderer/hooks/arg-mapper.ts +16 -2
  122. package/renderer/hooks/index.ts +13 -0
  123. package/renderer/hooks/initialize.ts +2 -1
  124. package/renderer/hooks/use-agent-market-sdk.ts +7 -0
  125. package/renderer/hooks/use-agent-market.ts +106 -0
  126. package/renderer/hooks/use-agents-sdk.ts +7 -0
  127. package/renderer/hooks/use-app-sdk.ts +7 -0
  128. package/renderer/hooks/use-channel.ts +33 -4
  129. package/renderer/hooks/use-download-sdk.ts +21 -0
  130. package/renderer/hooks/use-intelligence-sdk.ts +7 -0
  131. package/renderer/hooks/use-intelligence-stats.ts +290 -0
  132. package/renderer/hooks/use-intelligence.ts +55 -214
  133. package/renderer/hooks/use-market-sdk.ts +16 -0
  134. package/renderer/hooks/use-notification-sdk.ts +7 -0
  135. package/renderer/hooks/use-permission-sdk.ts +7 -0
  136. package/renderer/hooks/use-permission.ts +325 -0
  137. package/renderer/hooks/use-platform-sdk.ts +7 -0
  138. package/renderer/hooks/use-plugin-sdk.ts +16 -0
  139. package/renderer/hooks/use-settings-sdk.ts +7 -0
  140. package/renderer/hooks/use-update-sdk.ts +21 -0
  141. package/renderer/index.ts +1 -0
  142. package/renderer/ref.ts +19 -10
  143. package/renderer/shared/components/SharedPluginDetailContent.vue +84 -0
  144. package/renderer/shared/components/SharedPluginDetailHeader.vue +116 -0
  145. package/renderer/shared/components/SharedPluginDetailMetaList.vue +39 -0
  146. package/renderer/shared/components/SharedPluginDetailReadme.vue +45 -0
  147. package/renderer/shared/components/SharedPluginDetailVersions.vue +98 -0
  148. package/renderer/shared/components/index.ts +5 -0
  149. package/renderer/shared/components/shims-vue.d.ts +5 -0
  150. package/renderer/shared/index.ts +2 -0
  151. package/renderer/shared/plugin-detail.ts +62 -0
  152. package/renderer/storage/app-settings.ts +3 -1
  153. package/renderer/storage/base-storage.ts +508 -82
  154. package/renderer/storage/intelligence-storage.ts +31 -40
  155. package/renderer/storage/openers.ts +3 -1
  156. package/renderer/storage/storage-subscription.ts +126 -42
  157. package/renderer/touch-sdk/env.ts +10 -10
  158. package/renderer/touch-sdk/index.ts +114 -18
  159. package/renderer/touch-sdk/terminal.ts +24 -13
  160. package/search/feature-matcher.ts +279 -0
  161. package/search/fuzzy-match.ts +64 -34
  162. package/search/index.ts +10 -0
  163. package/search/levenshtein-utils.ts +17 -11
  164. package/transport/errors.ts +310 -0
  165. package/transport/event/builder.ts +378 -0
  166. package/transport/event/index.ts +7 -0
  167. package/transport/event/types.ts +292 -0
  168. package/transport/events/index.ts +2690 -0
  169. package/transport/events/meta-overlay.ts +79 -0
  170. package/transport/events/types/agents.ts +177 -0
  171. package/transport/events/types/app-index.ts +20 -0
  172. package/transport/events/types/app.ts +475 -0
  173. package/transport/events/types/box-item.ts +222 -0
  174. package/transport/events/types/clipboard.ts +80 -0
  175. package/transport/events/types/core-box.ts +534 -0
  176. package/transport/events/types/device-idle.ts +7 -0
  177. package/transport/events/types/division-box.ts +99 -0
  178. package/transport/events/types/download.ts +115 -0
  179. package/transport/events/types/file-index.ts +84 -0
  180. package/transport/events/types/flow.ts +149 -0
  181. package/transport/events/types/index.ts +70 -0
  182. package/transport/events/types/market.ts +39 -0
  183. package/transport/events/types/meta-overlay.ts +184 -0
  184. package/transport/events/types/notification.ts +140 -0
  185. package/transport/events/types/permission.ts +90 -0
  186. package/transport/events/types/platform.ts +8 -0
  187. package/transport/events/types/plugin.ts +631 -0
  188. package/transport/events/types/sentry.ts +20 -0
  189. package/transport/events/types/storage.ts +208 -0
  190. package/transport/events/types/transport.ts +60 -0
  191. package/transport/events/types/tray.ts +16 -0
  192. package/transport/events/types/update.ts +78 -0
  193. package/transport/index.ts +141 -0
  194. package/transport/main.ts +2 -0
  195. package/transport/prelude.ts +208 -0
  196. package/transport/sdk/constants.ts +29 -0
  197. package/transport/sdk/domains/agents-market.ts +47 -0
  198. package/transport/sdk/domains/agents.ts +62 -0
  199. package/transport/sdk/domains/app.ts +48 -0
  200. package/transport/sdk/domains/disposable.ts +35 -0
  201. package/transport/sdk/domains/download.ts +139 -0
  202. package/transport/sdk/domains/index.ts +13 -0
  203. package/transport/sdk/domains/intelligence.ts +616 -0
  204. package/transport/sdk/domains/market.ts +35 -0
  205. package/transport/sdk/domains/notification.ts +62 -0
  206. package/transport/sdk/domains/permission.ts +85 -0
  207. package/transport/sdk/domains/platform.ts +19 -0
  208. package/transport/sdk/domains/plugin.ts +144 -0
  209. package/transport/sdk/domains/settings.ts +102 -0
  210. package/transport/sdk/domains/update.ts +64 -0
  211. package/transport/sdk/index.ts +60 -0
  212. package/transport/sdk/main-transport.ts +710 -0
  213. package/transport/sdk/main.ts +9 -0
  214. package/transport/sdk/plugin-transport.ts +654 -0
  215. package/transport/sdk/port-policy.ts +38 -0
  216. package/transport/sdk/renderer-transport.ts +1165 -0
  217. package/transport/types.ts +605 -0
  218. package/types/agent.ts +399 -0
  219. package/types/cloud-sync.ts +157 -0
  220. package/types/division-box.ts +31 -31
  221. package/types/download.ts +1 -0
  222. package/types/flow.ts +63 -12
  223. package/types/icon.ts +2 -1
  224. package/types/index.ts +5 -0
  225. package/types/intelligence.ts +166 -173
  226. package/types/modules/base.ts +2 -0
  227. package/types/path-browserify.d.ts +5 -0
  228. package/types/platform.ts +12 -0
  229. package/types/startup-info.ts +32 -0
  230. package/types/touch-app-core.ts +8 -8
  231. package/types/update.ts +94 -1
  232. package/vitest.config.ts +25 -0
  233. package/auth/useClerkConfig.ts +0 -40
  234. package/auth/useClerkProvider.ts +0 -52
@@ -0,0 +1,310 @@
1
+ /**
2
+ * @fileoverview Error types for TuffTransport
3
+ * @module @talex-touch/utils/transport/errors
4
+ */
5
+
6
+ // ============================================================================
7
+ // Error Codes
8
+ // ============================================================================
9
+
10
+ /**
11
+ * Error codes for TuffTransport operations.
12
+ */
13
+ export enum TuffTransportErrorCode {
14
+ /**
15
+ * Event is not a valid TuffEvent instance.
16
+ */
17
+ INVALID_EVENT = 'INVALID_EVENT',
18
+
19
+ /**
20
+ * No handler registered for the event.
21
+ */
22
+ UNKNOWN_EVENT = 'UNKNOWN_EVENT',
23
+
24
+ /**
25
+ * Request timed out waiting for response.
26
+ */
27
+ TIMEOUT = 'TIMEOUT',
28
+
29
+ /**
30
+ * Stream was cancelled by the client.
31
+ */
32
+ STREAM_CANCELLED = 'STREAM_CANCELLED',
33
+
34
+ /**
35
+ * Batch request failed.
36
+ */
37
+ BATCH_FAILED = 'BATCH_FAILED',
38
+
39
+ /**
40
+ * Failed to serialize request payload.
41
+ */
42
+ SERIALIZE_FAILED = 'SERIALIZE_FAILED',
43
+
44
+ /**
45
+ * Failed to deserialize response payload.
46
+ */
47
+ DESERIALIZE_FAILED = 'DESERIALIZE_FAILED',
48
+
49
+ /**
50
+ * Target window/WebContents not found or destroyed.
51
+ */
52
+ TARGET_NOT_FOUND = 'TARGET_NOT_FOUND',
53
+
54
+ /**
55
+ * Plugin security key is invalid or expired.
56
+ */
57
+ INVALID_PLUGIN_KEY = 'INVALID_PLUGIN_KEY',
58
+
59
+ /**
60
+ * Plugin attempted unauthorized operation.
61
+ */
62
+ PLUGIN_UNAUTHORIZED = 'PLUGIN_UNAUTHORIZED',
63
+
64
+ /**
65
+ * IPC channel error (e.g., EPIPE).
66
+ */
67
+ IPC_ERROR = 'IPC_ERROR',
68
+
69
+ /**
70
+ * Transport instance has been destroyed.
71
+ */
72
+ TRANSPORT_DESTROYED = 'TRANSPORT_DESTROYED',
73
+
74
+ /**
75
+ * Generic internal error.
76
+ */
77
+ INTERNAL_ERROR = 'INTERNAL_ERROR',
78
+ }
79
+
80
+ // ============================================================================
81
+ // Error Class
82
+ // ============================================================================
83
+
84
+ /**
85
+ * Custom error class for TuffTransport operations.
86
+ *
87
+ * @remarks
88
+ * Provides structured error information including error codes,
89
+ * event context, and optional cause for error chaining.
90
+ *
91
+ * @example
92
+ * ```typescript
93
+ * try {
94
+ * await transport.send(event, payload)
95
+ * } catch (err) {
96
+ * if (err instanceof TuffTransportError) {
97
+ * switch (err.code) {
98
+ * case TuffTransportErrorCode.TIMEOUT:
99
+ * // Handle timeout
100
+ * break
101
+ * case TuffTransportErrorCode.INVALID_PLUGIN_KEY:
102
+ * // Handle auth error
103
+ * break
104
+ * }
105
+ * }
106
+ * }
107
+ * ```
108
+ */
109
+ export class TuffTransportError extends Error {
110
+ /**
111
+ * Error code for programmatic handling.
112
+ */
113
+ readonly code: TuffTransportErrorCode
114
+
115
+ /**
116
+ * Event name associated with this error (if applicable).
117
+ */
118
+ readonly eventName?: string
119
+
120
+ /**
121
+ * Plugin name associated with this error (if applicable).
122
+ */
123
+ readonly pluginName?: string
124
+
125
+ /**
126
+ * Original error that caused this error (if applicable).
127
+ */
128
+ override readonly cause?: Error
129
+
130
+ /**
131
+ * Timestamp when this error occurred.
132
+ */
133
+ readonly timestamp: number
134
+
135
+ /**
136
+ * Creates a new TuffTransportError.
137
+ *
138
+ * @param code - Error code
139
+ * @param message - Human-readable error message
140
+ * @param options - Additional error context
141
+ */
142
+ constructor(
143
+ code: TuffTransportErrorCode,
144
+ message: string,
145
+ options?: {
146
+ eventName?: string
147
+ pluginName?: string
148
+ cause?: Error
149
+ },
150
+ ) {
151
+ super(message)
152
+ this.name = 'TuffTransportError'
153
+ this.code = code
154
+ this.eventName = options?.eventName
155
+ this.pluginName = options?.pluginName
156
+ this.cause = options?.cause
157
+ this.timestamp = Date.now()
158
+
159
+ // Maintain proper stack trace in V8 environments
160
+ if (Error.captureStackTrace) {
161
+ Error.captureStackTrace(this, TuffTransportError)
162
+ }
163
+ }
164
+
165
+ /**
166
+ * Creates a serializable representation of this error.
167
+ *
168
+ * @returns Plain object representation
169
+ */
170
+ toJSON(): Record<string, unknown> {
171
+ return {
172
+ name: this.name,
173
+ code: this.code,
174
+ message: this.message,
175
+ eventName: this.eventName,
176
+ pluginName: this.pluginName,
177
+ timestamp: this.timestamp,
178
+ stack: this.stack,
179
+ }
180
+ }
181
+
182
+ /**
183
+ * Creates a TuffTransportError from a plain object.
184
+ *
185
+ * @param obj - Plain object (e.g., from IPC)
186
+ * @returns TuffTransportError instance
187
+ */
188
+ static fromJSON(obj: Record<string, unknown>): TuffTransportError {
189
+ const error = new TuffTransportError(
190
+ (obj.code as TuffTransportErrorCode) || TuffTransportErrorCode.INTERNAL_ERROR,
191
+ (obj.message as string) || 'Unknown error',
192
+ {
193
+ eventName: obj.eventName as string | undefined,
194
+ pluginName: obj.pluginName as string | undefined,
195
+ },
196
+ )
197
+ if (obj.stack && typeof obj.stack === 'string') {
198
+ error.stack = obj.stack
199
+ }
200
+ return error
201
+ }
202
+ }
203
+
204
+ // ============================================================================
205
+ // Error Factory Functions
206
+ // ============================================================================
207
+
208
+ /**
209
+ * Creates an INVALID_EVENT error.
210
+ *
211
+ * @param context - Context where the error occurred
212
+ * @returns TuffTransportError
213
+ */
214
+ export function createInvalidEventError(context: string): TuffTransportError {
215
+ return new TuffTransportError(
216
+ TuffTransportErrorCode.INVALID_EVENT,
217
+ `[${context}] Invalid event. Expected TuffEvent created via defineEvent(), `
218
+ + `received a string or invalid object. String event names are not allowed.`,
219
+ )
220
+ }
221
+
222
+ /**
223
+ * Creates a TIMEOUT error.
224
+ *
225
+ * @param eventName - Event that timed out
226
+ * @param timeoutMs - Timeout duration in milliseconds
227
+ * @returns TuffTransportError
228
+ */
229
+ export function createTimeoutError(eventName: string, timeoutMs: number): TuffTransportError {
230
+ return new TuffTransportError(
231
+ TuffTransportErrorCode.TIMEOUT,
232
+ `Request "${eventName}" timed out after ${timeoutMs}ms`,
233
+ { eventName },
234
+ )
235
+ }
236
+
237
+ /**
238
+ * Creates an UNKNOWN_EVENT error.
239
+ *
240
+ * @param eventName - Event name that was not found
241
+ * @returns TuffTransportError
242
+ */
243
+ export function createUnknownEventError(eventName: string): TuffTransportError {
244
+ return new TuffTransportError(
245
+ TuffTransportErrorCode.UNKNOWN_EVENT,
246
+ `No handler registered for event "${eventName}"`,
247
+ { eventName },
248
+ )
249
+ }
250
+
251
+ /**
252
+ * Creates an INVALID_PLUGIN_KEY error.
253
+ *
254
+ * @param pluginName - Plugin name (if known)
255
+ * @returns TuffTransportError
256
+ */
257
+ export function createInvalidPluginKeyError(pluginName?: string): TuffTransportError {
258
+ return new TuffTransportError(
259
+ TuffTransportErrorCode.INVALID_PLUGIN_KEY,
260
+ pluginName
261
+ ? `Invalid or expired security key for plugin "${pluginName}"`
262
+ : 'Invalid or expired plugin security key',
263
+ { pluginName },
264
+ )
265
+ }
266
+
267
+ /**
268
+ * Creates a TARGET_NOT_FOUND error.
269
+ *
270
+ * @param target - Description of the target
271
+ * @param eventName - Event name (if applicable)
272
+ * @returns TuffTransportError
273
+ */
274
+ export function createTargetNotFoundError(target: string, eventName?: string): TuffTransportError {
275
+ return new TuffTransportError(
276
+ TuffTransportErrorCode.TARGET_NOT_FOUND,
277
+ `Target "${target}" not found or has been destroyed`,
278
+ { eventName },
279
+ )
280
+ }
281
+
282
+ /**
283
+ * Creates a SERIALIZE_FAILED error.
284
+ *
285
+ * @param eventName - Event name
286
+ * @param cause - Original error
287
+ * @returns TuffTransportError
288
+ */
289
+ export function createSerializeError(eventName: string, cause: Error): TuffTransportError {
290
+ return new TuffTransportError(
291
+ TuffTransportErrorCode.SERIALIZE_FAILED,
292
+ `Failed to serialize payload for "${eventName}": ${cause.message}`,
293
+ { eventName, cause },
294
+ )
295
+ }
296
+
297
+ /**
298
+ * Creates a STREAM_CANCELLED error.
299
+ *
300
+ * @param eventName - Event name
301
+ * @param streamId - Stream identifier
302
+ * @returns TuffTransportError
303
+ */
304
+ export function createStreamCancelledError(eventName: string, streamId: string): TuffTransportError {
305
+ return new TuffTransportError(
306
+ TuffTransportErrorCode.STREAM_CANCELLED,
307
+ `Stream "${streamId}" for event "${eventName}" was cancelled`,
308
+ { eventName },
309
+ )
310
+ }
@@ -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,7 @@
1
+ /**
2
+ * @fileoverview Event module exports
3
+ * @module @talex-touch/utils/transport/event
4
+ */
5
+
6
+ export * from './builder'
7
+ export * from './types'