@talex-touch/utils 1.0.40 → 1.0.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (235) hide show
  1. package/.eslintcache +1 -0
  2. package/__tests__/cloud-sync-sdk.test.ts +442 -0
  3. package/__tests__/icons/icons.test.ts +84 -0
  4. package/__tests__/plugin-sdk-lifecycle.test.ts +130 -0
  5. package/__tests__/power-sdk.test.ts +143 -0
  6. package/__tests__/preset-export-types.test.ts +108 -0
  7. package/__tests__/search/fuzzy-match.test.ts +137 -0
  8. package/__tests__/transport/port-policy.test.ts +44 -0
  9. package/__tests__/transport-domain-sdks.test.ts +152 -0
  10. package/__tests__/types/update.test.ts +67 -0
  11. package/account/account-sdk.ts +915 -0
  12. package/account/index.ts +2 -0
  13. package/account/types.ts +321 -0
  14. package/analytics/client.ts +136 -0
  15. package/analytics/index.ts +2 -0
  16. package/analytics/types.ts +156 -0
  17. package/animation/auto-resize.ts +322 -0
  18. package/animation/window-node.ts +26 -19
  19. package/auth/clerk-types.ts +12 -30
  20. package/auth/index.ts +0 -2
  21. package/auth/useAuthState.ts +6 -14
  22. package/base/index.ts +2 -0
  23. package/base/log-level.ts +105 -0
  24. package/channel/index.ts +170 -69
  25. package/cloud-sync/cloud-sync-sdk.ts +450 -0
  26. package/cloud-sync/index.ts +1 -0
  27. package/common/file-scan-utils.ts +17 -9
  28. package/common/index.ts +4 -0
  29. package/common/logger/index.ts +46 -0
  30. package/common/logger/logger-manager.ts +303 -0
  31. package/common/logger/module-logger.ts +270 -0
  32. package/common/logger/transport-logger.ts +234 -0
  33. package/common/logger/types.ts +93 -0
  34. package/common/search/gather.ts +48 -6
  35. package/common/search/index.ts +8 -0
  36. package/common/storage/constants.ts +13 -0
  37. package/common/storage/entity/app-settings.ts +245 -0
  38. package/common/storage/entity/index.ts +3 -0
  39. package/common/storage/entity/layout-atom-types.ts +147 -0
  40. package/common/storage/entity/openers.ts +1 -0
  41. package/common/storage/entity/preset-cloud-api.ts +132 -0
  42. package/common/storage/entity/preset-export-types.ts +256 -0
  43. package/common/storage/entity/shortcut-settings.ts +1 -0
  44. package/common/storage/shortcut-storage.ts +11 -0
  45. package/common/utils/clone-diagnostics.ts +105 -0
  46. package/common/utils/file.ts +16 -8
  47. package/common/utils/index.ts +6 -2
  48. package/common/utils/payload-preview.ts +173 -0
  49. package/common/utils/polling.ts +167 -13
  50. package/common/utils/safe-path.ts +103 -0
  51. package/common/utils/safe-shell.ts +115 -0
  52. package/common/utils/task-queue.ts +4 -1
  53. package/core-box/builder/tuff-builder.ts +0 -1
  54. package/core-box/index.ts +1 -1
  55. package/core-box/recommendation.ts +38 -1
  56. package/core-box/tuff/tuff-dsl.ts +97 -0
  57. package/electron/download-manager.ts +10 -7
  58. package/electron/env-tool.ts +42 -40
  59. package/electron/index.ts +0 -1
  60. package/env/index.ts +156 -0
  61. package/eslint.config.js +55 -0
  62. package/i18n/index.ts +62 -0
  63. package/i18n/locales/en.json +226 -0
  64. package/i18n/locales/zh.json +226 -0
  65. package/i18n/message-keys.ts +236 -0
  66. package/i18n/resolver.ts +181 -0
  67. package/icons/index.ts +257 -0
  68. package/icons/svg.ts +69 -0
  69. package/index.ts +9 -1
  70. package/intelligence/client.ts +72 -42
  71. package/market/constants.ts +21 -3
  72. package/market/index.ts +1 -1
  73. package/market/types.ts +20 -5
  74. package/package.json +15 -5
  75. package/permission/index.ts +143 -46
  76. package/permission/legacy.ts +26 -0
  77. package/permission/registry.ts +304 -0
  78. package/permission/types.ts +164 -0
  79. package/plugin/channel.ts +68 -39
  80. package/plugin/index.ts +82 -8
  81. package/plugin/install.ts +3 -0
  82. package/plugin/log/types.ts +22 -5
  83. package/plugin/node/logger-manager.ts +11 -3
  84. package/plugin/node/logger.ts +24 -17
  85. package/plugin/preload.ts +25 -2
  86. package/plugin/providers/index.ts +4 -0
  87. package/plugin/providers/market-client.ts +218 -0
  88. package/plugin/providers/npm-provider.ts +228 -0
  89. package/plugin/providers/tpex-provider.ts +297 -0
  90. package/plugin/providers/tpex-types.ts +34 -0
  91. package/plugin/sdk/box-items.ts +14 -0
  92. package/plugin/sdk/box-sdk.ts +64 -0
  93. package/plugin/sdk/channel.ts +119 -4
  94. package/plugin/sdk/clipboard.ts +26 -12
  95. package/plugin/sdk/cloud-sync.ts +113 -0
  96. package/plugin/sdk/common.ts +19 -11
  97. package/plugin/sdk/core-box.ts +6 -15
  98. package/plugin/sdk/division-box.ts +160 -65
  99. package/plugin/sdk/examples/storage-onDidChange-example.js +5 -2
  100. package/plugin/sdk/feature-sdk.ts +111 -76
  101. package/plugin/sdk/flow.ts +146 -45
  102. package/plugin/sdk/hooks/bridge.ts +113 -49
  103. package/plugin/sdk/hooks/life-cycle.ts +35 -16
  104. package/plugin/sdk/index.ts +14 -3
  105. package/plugin/sdk/intelligence.ts +87 -0
  106. package/plugin/sdk/meta/README.md +179 -0
  107. package/plugin/sdk/meta-sdk.ts +244 -0
  108. package/plugin/sdk/notification.ts +9 -0
  109. package/plugin/sdk/performance.ts +1 -16
  110. package/plugin/sdk/plugin-info.ts +64 -0
  111. package/plugin/sdk/power.ts +155 -0
  112. package/plugin/sdk/recommend.ts +21 -0
  113. package/plugin/sdk/service/index.ts +12 -8
  114. package/plugin/sdk/sqlite.ts +141 -0
  115. package/plugin/sdk/storage.ts +2 -6
  116. package/plugin/sdk/system.ts +2 -9
  117. package/plugin/sdk/temp-files.ts +41 -0
  118. package/plugin/sdk/touch-sdk.ts +18 -0
  119. package/plugin/sdk/types.ts +44 -4
  120. package/plugin/sdk/window/index.ts +12 -9
  121. package/plugin/sdk-version.ts +231 -0
  122. package/preload/renderer.ts +3 -2
  123. package/renderer/hooks/arg-mapper.ts +34 -6
  124. package/renderer/hooks/index.ts +13 -0
  125. package/renderer/hooks/initialize.ts +2 -1
  126. package/renderer/hooks/use-agent-market-sdk.ts +7 -0
  127. package/renderer/hooks/use-agent-market.ts +106 -0
  128. package/renderer/hooks/use-agents-sdk.ts +7 -0
  129. package/renderer/hooks/use-app-sdk.ts +7 -0
  130. package/renderer/hooks/use-channel.ts +33 -4
  131. package/renderer/hooks/use-download-sdk.ts +21 -0
  132. package/renderer/hooks/use-intelligence-sdk.ts +7 -0
  133. package/renderer/hooks/use-intelligence-stats.ts +290 -0
  134. package/renderer/hooks/use-intelligence.ts +202 -104
  135. package/renderer/hooks/use-market-sdk.ts +16 -0
  136. package/renderer/hooks/use-notification-sdk.ts +7 -0
  137. package/renderer/hooks/use-permission-sdk.ts +7 -0
  138. package/renderer/hooks/use-permission.ts +325 -0
  139. package/renderer/hooks/use-platform-sdk.ts +7 -0
  140. package/renderer/hooks/use-plugin-sdk.ts +16 -0
  141. package/renderer/hooks/use-settings-sdk.ts +7 -0
  142. package/renderer/hooks/use-update-sdk.ts +21 -0
  143. package/renderer/index.ts +1 -0
  144. package/renderer/ref.ts +19 -10
  145. package/renderer/shared/components/SharedPluginDetailContent.vue +84 -0
  146. package/renderer/shared/components/SharedPluginDetailHeader.vue +116 -0
  147. package/renderer/shared/components/SharedPluginDetailMetaList.vue +39 -0
  148. package/renderer/shared/components/SharedPluginDetailReadme.vue +45 -0
  149. package/renderer/shared/components/SharedPluginDetailVersions.vue +98 -0
  150. package/renderer/shared/components/index.ts +5 -0
  151. package/renderer/shared/components/shims-vue.d.ts +5 -0
  152. package/renderer/shared/index.ts +2 -0
  153. package/renderer/shared/plugin-detail.ts +62 -0
  154. package/renderer/storage/app-settings.ts +3 -1
  155. package/renderer/storage/base-storage.ts +508 -82
  156. package/renderer/storage/intelligence-storage.ts +37 -46
  157. package/renderer/storage/openers.ts +3 -1
  158. package/renderer/storage/storage-subscription.ts +126 -42
  159. package/renderer/touch-sdk/env.ts +10 -10
  160. package/renderer/touch-sdk/index.ts +114 -18
  161. package/renderer/touch-sdk/terminal.ts +24 -13
  162. package/search/feature-matcher.ts +279 -0
  163. package/search/fuzzy-match.ts +64 -34
  164. package/search/index.ts +10 -0
  165. package/search/levenshtein-utils.ts +17 -11
  166. package/transport/errors.ts +310 -0
  167. package/transport/event/builder.ts +378 -0
  168. package/transport/event/index.ts +7 -0
  169. package/transport/event/types.ts +292 -0
  170. package/transport/events/index.ts +2670 -0
  171. package/transport/events/meta-overlay.ts +79 -0
  172. package/transport/events/types/agents.ts +177 -0
  173. package/transport/events/types/app-index.ts +9 -0
  174. package/transport/events/types/app.ts +475 -0
  175. package/transport/events/types/box-item.ts +222 -0
  176. package/transport/events/types/clipboard.ts +80 -0
  177. package/transport/events/types/core-box.ts +534 -0
  178. package/transport/events/types/device-idle.ts +7 -0
  179. package/transport/events/types/division-box.ts +99 -0
  180. package/transport/events/types/download.ts +115 -0
  181. package/transport/events/types/file-index.ts +73 -0
  182. package/transport/events/types/flow.ts +149 -0
  183. package/transport/events/types/index.ts +70 -0
  184. package/transport/events/types/market.ts +39 -0
  185. package/transport/events/types/meta-overlay.ts +184 -0
  186. package/transport/events/types/notification.ts +140 -0
  187. package/transport/events/types/permission.ts +90 -0
  188. package/transport/events/types/platform.ts +8 -0
  189. package/transport/events/types/plugin.ts +620 -0
  190. package/transport/events/types/sentry.ts +20 -0
  191. package/transport/events/types/storage.ts +208 -0
  192. package/transport/events/types/transport.ts +60 -0
  193. package/transport/events/types/tray.ts +16 -0
  194. package/transport/events/types/update.ts +78 -0
  195. package/transport/index.ts +139 -0
  196. package/transport/main.ts +2 -0
  197. package/transport/sdk/constants.ts +29 -0
  198. package/transport/sdk/domains/agents-market.ts +47 -0
  199. package/transport/sdk/domains/agents.ts +62 -0
  200. package/transport/sdk/domains/app.ts +48 -0
  201. package/transport/sdk/domains/disposable.ts +35 -0
  202. package/transport/sdk/domains/download.ts +139 -0
  203. package/transport/sdk/domains/index.ts +13 -0
  204. package/transport/sdk/domains/intelligence.ts +616 -0
  205. package/transport/sdk/domains/market.ts +35 -0
  206. package/transport/sdk/domains/notification.ts +62 -0
  207. package/transport/sdk/domains/permission.ts +85 -0
  208. package/transport/sdk/domains/platform.ts +19 -0
  209. package/transport/sdk/domains/plugin.ts +144 -0
  210. package/transport/sdk/domains/settings.ts +92 -0
  211. package/transport/sdk/domains/update.ts +64 -0
  212. package/transport/sdk/index.ts +60 -0
  213. package/transport/sdk/main-transport.ts +710 -0
  214. package/transport/sdk/main.ts +9 -0
  215. package/transport/sdk/plugin-transport.ts +654 -0
  216. package/transport/sdk/port-policy.ts +38 -0
  217. package/transport/sdk/renderer-transport.ts +1165 -0
  218. package/transport/types.ts +605 -0
  219. package/types/agent.ts +399 -0
  220. package/types/cloud-sync.ts +157 -0
  221. package/types/division-box.ts +47 -27
  222. package/types/download.ts +1 -0
  223. package/types/flow.ts +63 -12
  224. package/types/icon.ts +2 -1
  225. package/types/index.ts +5 -0
  226. package/types/intelligence.ts +1492 -81
  227. package/types/modules/base.ts +2 -0
  228. package/types/path-browserify.d.ts +5 -0
  229. package/types/platform.ts +12 -0
  230. package/types/startup-info.ts +32 -0
  231. package/types/touch-app-core.ts +8 -8
  232. package/types/update.ts +94 -1
  233. package/vitest.config.ts +25 -0
  234. package/auth/useClerkConfig.ts +0 -40
  235. package/auth/useClerkProvider.ts +0 -52
@@ -24,7 +24,7 @@ export interface FuzzyMatchResult {
24
24
  export function fuzzyMatch(
25
25
  target: string,
26
26
  query: string,
27
- maxErrors = 2
27
+ maxErrors = 2,
28
28
  ): FuzzyMatchResult {
29
29
  if (!query || !target) {
30
30
  return { matched: false, score: 0, matchedIndices: [] }
@@ -38,7 +38,7 @@ export function fuzzyMatch(
38
38
  return {
39
39
  matched: true,
40
40
  score: 1,
41
- matchedIndices: Array.from({ length: target.length }, (_, i) => i)
41
+ matchedIndices: Array.from({ length: target.length }, (_, i) => i),
42
42
  }
43
43
  }
44
44
 
@@ -48,7 +48,7 @@ export function fuzzyMatch(
48
48
  return {
49
49
  matched: true,
50
50
  score: 0.95,
51
- matchedIndices: Array.from({ length: query.length }, (_, i) => substringIndex + i)
51
+ matchedIndices: Array.from({ length: query.length }, (_, i) => substringIndex + i),
52
52
  }
53
53
  }
54
54
 
@@ -58,7 +58,7 @@ export function fuzzyMatch(
58
58
  return {
59
59
  matched: true,
60
60
  score: 0.8 + (subsequenceResult.matchedIndices.length / target.length) * 0.1,
61
- matchedIndices: subsequenceResult.matchedIndices
61
+ matchedIndices: subsequenceResult.matchedIndices,
62
62
  }
63
63
  }
64
64
 
@@ -77,8 +77,8 @@ export function fuzzyMatch(
77
77
  */
78
78
  function subsequenceMatch(
79
79
  target: string,
80
- query: string
81
- ): { matched: boolean; matchedIndices: number[] } {
80
+ query: string,
81
+ ): { matched: boolean, matchedIndices: number[] } {
82
82
  const matchedIndices: number[] = []
83
83
  let queryIdx = 0
84
84
 
@@ -91,7 +91,7 @@ function subsequenceMatch(
91
91
 
92
92
  return {
93
93
  matched: queryIdx === query.length,
94
- matchedIndices
94
+ matchedIndices,
95
95
  }
96
96
  }
97
97
 
@@ -102,13 +102,15 @@ function subsequenceMatch(
102
102
  function fuzzyMatchWithErrors(
103
103
  target: string,
104
104
  query: string,
105
- maxErrors: number
105
+ maxErrors: number,
106
106
  ): FuzzyMatchResult {
107
107
  const m = query.length
108
108
  const n = target.length
109
109
 
110
- if (m === 0) return { matched: true, score: 1, matchedIndices: [] }
111
- if (n === 0) return { matched: false, score: 0, matchedIndices: [] }
110
+ if (m === 0)
111
+ return { matched: true, score: 1, matchedIndices: [] }
112
+ if (n === 0)
113
+ return { matched: false, score: 0, matchedIndices: [] }
112
114
 
113
115
  // Allow more errors for longer queries
114
116
  const allowedErrors = Math.min(maxErrors, Math.floor(m / 3) + 1)
@@ -135,7 +137,7 @@ function fuzzyMatchWithErrors(
135
137
  bestScore = score
136
138
  bestStart = start
137
139
  // Adjust indices to be relative to the full target string
138
- bestMatchedIndices = matchedIndices.map((i) => start + i)
140
+ bestMatchedIndices = matchedIndices.map(i => start + i)
139
141
  }
140
142
  }
141
143
  }
@@ -145,7 +147,7 @@ function fuzzyMatchWithErrors(
145
147
  return {
146
148
  matched: true,
147
149
  score: bestScore,
148
- matchedIndices: bestMatchedIndices
150
+ matchedIndices: bestMatchedIndices,
149
151
  }
150
152
  }
151
153
 
@@ -157,25 +159,41 @@ function fuzzyMatchWithErrors(
157
159
  */
158
160
  function editDistanceWithPath(
159
161
  s1: string,
160
- s2: string
161
- ): { distance: number; matchedIndices: number[] } {
162
+ s2: string,
163
+ ): { distance: number, matchedIndices: number[] } {
162
164
  const m = s1.length
163
165
  const n = s2.length
164
166
 
165
167
  // DP table
166
- const dp: number[][] = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0))
168
+ const dp: number[][] = Array.from({ length: m + 1 }, () => Array.from({ length: n + 1 }, () => 0))
167
169
 
168
170
  // Initialize
169
- for (let i = 0; i <= m; i++) dp[i][0] = i
170
- for (let j = 0; j <= n; j++) dp[0][j] = j
171
+ for (let i = 0; i <= m; i++) {
172
+ const row = dp[i]
173
+ if (row)
174
+ row[0] = i
175
+ }
176
+ const firstRow = dp[0]
177
+ if (firstRow) {
178
+ for (let j = 0; j <= n; j++)
179
+ firstRow[j] = j
180
+ }
171
181
 
172
182
  // Fill DP table
173
183
  for (let i = 1; i <= m; i++) {
174
184
  for (let j = 1; j <= n; j++) {
185
+ const row = dp[i]
186
+ const prevRow = dp[i - 1]
187
+ if (!row || !prevRow)
188
+ continue
175
189
  if (s1[i - 1] === s2[j - 1]) {
176
- dp[i][j] = dp[i - 1][j - 1]
177
- } else {
178
- dp[i][j] = 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1])
190
+ row[j] = prevRow[j - 1] ?? 0
191
+ }
192
+ else {
193
+ const up = prevRow[j] ?? 0
194
+ const left = row[j - 1] ?? 0
195
+ const diag = prevRow[j - 1] ?? 0
196
+ row[j] = 1 + Math.min(up, left, diag)
179
197
  }
180
198
  }
181
199
  }
@@ -190,20 +208,24 @@ function editDistanceWithPath(
190
208
  matchedIndices.unshift(i - 1)
191
209
  i--
192
210
  j--
193
- } else if (dp[i - 1][j - 1] <= dp[i - 1][j] && dp[i - 1][j - 1] <= dp[i][j - 1]) {
211
+ }
212
+ else if ((dp[i - 1]?.[j - 1] ?? 0) <= (dp[i - 1]?.[j] ?? 0)
213
+ && (dp[i - 1]?.[j - 1] ?? 0) <= (dp[i]?.[j - 1] ?? 0)) {
194
214
  // Substitution
195
215
  i--
196
216
  j--
197
- } else if (dp[i - 1][j] <= dp[i][j - 1]) {
217
+ }
218
+ else if ((dp[i - 1]?.[j] ?? 0) <= (dp[i]?.[j - 1] ?? 0)) {
198
219
  // Deletion from s1
199
220
  i--
200
- } else {
221
+ }
222
+ else {
201
223
  // Insertion into s1
202
224
  j--
203
225
  }
204
226
  }
205
227
 
206
- return { distance: dp[m][n], matchedIndices }
228
+ return { distance: dp[m]?.[n] ?? 0, matchedIndices }
207
229
  }
208
230
 
209
231
  /**
@@ -213,7 +235,7 @@ function calculateFuzzyScore(
213
235
  editDistance: number,
214
236
  queryLength: number,
215
237
  matchStart: number,
216
- targetLength: number
238
+ targetLength: number,
217
239
  ): number {
218
240
  // Base score from edit distance (0.5 - 0.7 range for fuzzy matches)
219
241
  const distanceScore = Math.max(0, 1 - editDistance / queryLength) * 0.3 + 0.4
@@ -230,22 +252,30 @@ function calculateFuzzyScore(
230
252
  /**
231
253
  * Convert matched indices to Range array for highlighting
232
254
  */
233
- export function indicesToRanges(indices: number[]): Array<{ start: number; end: number }> {
234
- if (!indices.length) return []
255
+ export function indicesToRanges(indices: number[]): Array<{ start: number, end: number }> {
256
+ if (!indices.length)
257
+ return []
235
258
 
236
259
  const sorted = Array.from(new Set(indices)).sort((a, b) => a - b)
237
- const ranges: Array<{ start: number; end: number }> = []
260
+ const ranges: Array<{ start: number, end: number }> = []
238
261
 
239
- let start = sorted[0]
240
- let end = sorted[0] + 1
262
+ const first = sorted[0]
263
+ if (first === undefined)
264
+ return []
265
+ let start = first
266
+ let end = first + 1
241
267
 
242
268
  for (let i = 1; i < sorted.length; i++) {
243
- if (sorted[i] === end) {
269
+ const current = sorted[i]
270
+ if (current === undefined)
271
+ continue
272
+ if (current === end) {
244
273
  end++
245
- } else {
274
+ }
275
+ else {
246
276
  ranges.push({ start, end })
247
- start = sorted[i]
248
- end = sorted[i] + 1
277
+ start = current
278
+ end = current + 1
249
279
  }
250
280
  }
251
281
  ranges.push({ start, end })
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Search utilities and types
3
+ *
4
+ * @module search
5
+ */
6
+
7
+ export * from './feature-matcher'
8
+ export * from './fuzzy-match'
9
+ export * from './levenshtein-utils'
10
+ export * from './types'
@@ -11,29 +11,35 @@ export function levenshteinDistance(s1: string, s2: string): number {
11
11
  const n = s2.length
12
12
 
13
13
  // Create a 2D array (m+1)x(n+1) to store distances
14
- const dp: number[][] = new Array(m + 1)
15
- .fill(0)
16
- .map(() => new Array(n + 1).fill(0))
14
+ const dp: number[][] = Array.from({ length: m + 1 }, () => Array.from({ length: n + 1 }, () => 0))
17
15
 
18
16
  // Initialize the DP table
19
17
  for (let i = 0; i <= m; i++) {
20
- dp[i][0] = i
18
+ const row = dp[i]
19
+ if (row)
20
+ row[0] = i
21
21
  }
22
- for (let j = 0; j <= n; j++) {
23
- dp[0][j] = j
22
+ const firstRow = dp[0]
23
+ if (firstRow) {
24
+ for (let j = 0; j <= n; j++)
25
+ firstRow[j] = j
24
26
  }
25
27
 
26
28
  // Fill the DP table
27
29
  for (let i = 1; i <= m; i++) {
28
30
  for (let j = 1; j <= n; j++) {
29
31
  const cost = s1[i - 1] === s2[j - 1] ? 0 : 1
30
- dp[i][j] = Math.min(
31
- dp[i - 1][j] + 1, // Deletion
32
- dp[i][j - 1] + 1, // Insertion
33
- dp[i - 1][j - 1] + cost, // Substitution
32
+ const row = dp[i]
33
+ const prevRow = dp[i - 1]
34
+ if (!row || !prevRow)
35
+ continue
36
+ row[j] = Math.min(
37
+ (prevRow[j] ?? 0) + 1, // Deletion
38
+ (row[j - 1] ?? 0) + 1, // Insertion
39
+ (prevRow[j - 1] ?? 0) + cost, // Substitution
34
40
  )
35
41
  }
36
42
  }
37
43
 
38
- return dp[m][n]
44
+ return dp[m]?.[n] ?? 0
39
45
  }
@@ -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
+ }