tiny-essentials 1.28.18 → 1.29.0

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 (567) hide show
  1. package/README.md +1 -1
  2. package/changelog/1/28/19.md +24 -0
  3. package/changelog/1/29/0.md +58 -0
  4. package/dist/v1/ColorSafeStringify.min.js +1 -1
  5. package/dist/v1/TinyAdvancedRaffle.min.js +1 -1
  6. package/dist/v1/TinyAfterScrollWatcher.min.js +1 -1
  7. package/dist/v1/TinyAnalogClock.min.js +1 -1
  8. package/dist/v1/TinyArrayComparator.min.js +1 -1
  9. package/dist/v1/TinyArrayPaginator.min.js +1 -1
  10. package/dist/v1/TinyBasicsEs.min.js +1 -1
  11. package/dist/v1/TinyBrowserMonitor.min.js +1 -0
  12. package/dist/v1/TinyClassManager.min.js +1 -1
  13. package/dist/v1/TinyClipboard.min.js +1 -1
  14. package/dist/v1/TinyCloner.min.js +1 -0
  15. package/dist/v1/TinyColorConverter.min.js +1 -1
  16. package/dist/v1/TinyColorValidator.min.js +1 -1
  17. package/dist/v1/TinyCookieConsent.min.js +1 -1
  18. package/dist/v1/TinyDayNightCycle.min.js +1 -1
  19. package/dist/v1/TinyDebugger.min.js +1 -1
  20. package/dist/v1/TinyDomReadyManager.min.js +1 -1
  21. package/dist/v1/TinyDragDropDetector.min.js +1 -1
  22. package/dist/v1/TinyDragger.min.js +1 -1
  23. package/dist/v1/TinyElementObserver.min.js +1 -1
  24. package/dist/v1/TinyEssentials.min.js +1 -1
  25. package/dist/v1/TinyGamepad.min.js +1 -1
  26. package/dist/v1/TinyHtml.min.js +1 -1
  27. package/dist/v1/TinyHtmlTagRegexBuilder.min.js +1 -0
  28. package/dist/v1/TinyHttpResponseRegistry.min.js +1 -0
  29. package/dist/v1/TinyI18.min.js +1 -1
  30. package/dist/v1/TinyIframeEvents.min.js +1 -1
  31. package/dist/v1/TinyInventory.min.js +1 -1
  32. package/dist/v1/TinyInventoryTrader.min.js +1 -1
  33. package/dist/v1/TinyLevelUp.min.js +1 -1
  34. package/dist/v1/TinyLoadingScreen.min.js +1 -1
  35. package/dist/v1/TinyLocalStorage.min.js +1 -1
  36. package/dist/v1/TinyMaInSys.min.js +1 -1
  37. package/dist/v1/TinyMapCache.min.js +1 -0
  38. package/dist/v1/TinyMediaPlayer.min.js +1 -1
  39. package/dist/v1/TinyNeedBar.min.js +1 -1
  40. package/dist/v1/TinyNewWinEvents.min.js +1 -1
  41. package/dist/v1/TinyNotificationAdapter.min.js +1 -0
  42. package/dist/v1/TinyNotifications.min.js +1 -1
  43. package/dist/v1/TinyNotifyCenter.min.js +1 -1
  44. package/dist/v1/TinyOPFSFileSystem.min.js +1 -0
  45. package/dist/v1/TinyPasswordValidator.min.js +1 -0
  46. package/dist/v1/TinyPluginPackage.min.js +1 -0
  47. package/dist/v1/TinyPromiseQueue.min.js +1 -1
  48. package/dist/v1/TinyPushManager.min.js +1 -0
  49. package/dist/v1/TinyPushPayload.min.js +1 -0
  50. package/dist/v1/TinyPushRouter.min.js +1 -0
  51. package/dist/v1/TinyRadioFm.min.js +1 -1
  52. package/dist/v1/TinyRateLimiter.min.js +1 -1
  53. package/dist/v1/TinyRegexEs.min.js +1 -0
  54. package/dist/v1/TinyRouter.min.js +1 -0
  55. package/dist/v1/TinyServiceWorker.min.js +1 -0
  56. package/dist/v1/TinyServiceWorkerEngine.min.js +1 -0
  57. package/dist/v1/TinySetMapPackage.min.js +1 -0
  58. package/dist/v1/TinySimpleDice.min.js +1 -1
  59. package/dist/v1/TinySmartScroller.min.js +1 -1
  60. package/dist/v1/TinyStorageBucketFileSystem.min.js +1 -0
  61. package/dist/v1/TinyTextDiffer.min.js +1 -1
  62. package/dist/v1/TinyTextRangeEditor.min.js +1 -1
  63. package/dist/v1/TinyTextarea.min.js +1 -1
  64. package/dist/v1/TinyThrottledApi.min.js +1 -0
  65. package/dist/v1/TinyTimeout.min.js +1 -1
  66. package/dist/v1/TinyToastNotify.min.js +1 -1
  67. package/dist/v1/TinyUploadClicker.min.js +1 -1
  68. package/dist/v1/TinyUriParser.min.js +1 -0
  69. package/dist/v1/TinyVersion.min.js +1 -0
  70. package/dist/v1/TinyWebWorker.min.js +1 -0
  71. package/dist/v1/TinyWebWorkerEngine.min.js +1 -0
  72. package/dist/v1/UltraRandomMsgGen.min.js +1 -1
  73. package/dist/v1/basics/array.cjs +2 -2
  74. package/dist/v1/basics/array.d.mts +2 -0
  75. package/dist/v1/basics/array.d.mts.map +1 -1
  76. package/dist/v1/basics/array.mjs +2 -1
  77. package/dist/v1/basics/browserDetector.cjs +37 -12
  78. package/dist/v1/basics/browserDetector.d.mts +8 -0
  79. package/dist/v1/basics/browserDetector.d.mts.map +1 -1
  80. package/dist/v1/basics/browserDetector.mjs +32 -13
  81. package/dist/v1/basics/crypto.cjs +23 -0
  82. package/dist/v1/basics/crypto.d.mts +10 -0
  83. package/dist/v1/basics/crypto.d.mts.map +1 -0
  84. package/dist/v1/basics/crypto.mjs +18 -0
  85. package/dist/v1/basics/html.cjs +0 -3
  86. package/dist/v1/basics/html.d.mts.map +1 -1
  87. package/dist/v1/basics/html.mjs +0 -2
  88. package/dist/v1/basics/index.cjs +8 -1
  89. package/dist/v1/basics/index.d.mts +6 -5
  90. package/dist/v1/basics/index.d.mts.map +1 -1
  91. package/dist/v1/basics/index.mjs +6 -5
  92. package/dist/v1/basics/objChecker.cjs +88 -0
  93. package/dist/v1/basics/objChecker.d.mts +26 -0
  94. package/dist/v1/basics/objChecker.d.mts.map +1 -1
  95. package/dist/v1/basics/objChecker.mjs +74 -0
  96. package/dist/v1/basics/objFilter.cjs +234 -93
  97. package/dist/v1/basics/objFilter.d.mts +96 -22
  98. package/dist/v1/basics/objFilter.d.mts.map +1 -1
  99. package/dist/v1/basics/objFilter.mjs +216 -92
  100. package/dist/v1/basics/promiseUtils.cjs +48 -12
  101. package/dist/v1/basics/promiseUtils.d.mts +45 -12
  102. package/dist/v1/basics/promiseUtils.d.mts.map +1 -1
  103. package/dist/v1/basics/promiseUtils.mjs +47 -12
  104. package/dist/v1/basics/text.cjs +0 -12
  105. package/dist/v1/basics/text.d.mts +0 -10
  106. package/dist/v1/basics/text.d.mts.map +1 -1
  107. package/dist/v1/basics/text.mjs +0 -10
  108. package/dist/v1/css/TinyCookieConsent.min.css +1 -0
  109. package/dist/v1/css/TinyCookieConsent.min.css.map +1 -0
  110. package/dist/v1/css/TinyDraggerExample.min.css +1 -0
  111. package/dist/v1/css/TinyDraggerExample.min.css.map +1 -0
  112. package/dist/v1/css/TinyLoadingScreen.min.css +1 -0
  113. package/dist/v1/css/TinyLoadingScreen.min.css.map +1 -0
  114. package/dist/v1/css/TinyNotify.min.css +1 -0
  115. package/dist/v1/css/TinyNotify.min.css.map +1 -0
  116. package/dist/v1/css/aiMarker.min.css +1 -0
  117. package/dist/v1/css/aiMarker.min.css.map +1 -0
  118. package/dist/v1/index.cjs +88 -3
  119. package/dist/v1/index.d.mts +31 -6
  120. package/dist/v1/index.d.mts.map +1 -1
  121. package/dist/v1/index.mjs +32 -7
  122. package/dist/v1/jsdoc/EventEmitter.cjs +4 -0
  123. package/dist/v1/jsdoc/EventEmitter.d.mts +33 -0
  124. package/dist/v1/jsdoc/EventEmitter.d.mts.map +1 -0
  125. package/dist/v1/jsdoc/EventEmitter.mjs +18 -0
  126. package/dist/v1/libs/array/TinyArrayComparator.cjs +240 -25
  127. package/dist/v1/libs/array/TinyArrayComparator.d.mts +130 -22
  128. package/dist/v1/libs/array/TinyArrayComparator.d.mts.map +1 -1
  129. package/dist/v1/libs/array/TinyArrayComparator.mjs +210 -24
  130. package/dist/v1/libs/fs/constants.cjs +74 -0
  131. package/dist/v1/libs/fs/constants.d.mts +22 -0
  132. package/dist/v1/libs/fs/constants.d.mts.map +1 -0
  133. package/dist/v1/libs/fs/constants.mjs +53 -0
  134. package/dist/v1/libs/fs/encoding.cjs +118 -0
  135. package/dist/v1/libs/fs/encoding.d.mts +50 -0
  136. package/dist/v1/libs/fs/encoding.d.mts.map +1 -0
  137. package/dist/v1/libs/fs/encoding.mjs +102 -0
  138. package/dist/v1/libs/fs/error.cjs +188 -0
  139. package/dist/v1/libs/fs/error.d.mts +105 -0
  140. package/dist/v1/libs/fs/error.d.mts.map +1 -0
  141. package/dist/v1/libs/fs/error.mjs +158 -0
  142. package/dist/v1/libs/fs/handle.cjs +121 -0
  143. package/dist/v1/libs/fs/handle.d.mts +56 -0
  144. package/dist/v1/libs/fs/handle.d.mts.map +1 -0
  145. package/dist/v1/libs/fs/handle.mjs +100 -0
  146. package/dist/v1/libs/fs/index.cjs +700 -0
  147. package/dist/v1/libs/fs/index.d.mts +377 -0
  148. package/dist/v1/libs/fs/index.d.mts.map +1 -0
  149. package/dist/v1/libs/fs/index.mjs +630 -0
  150. package/dist/v1/libs/fs/path.cjs +234 -0
  151. package/dist/v1/libs/fs/path.d.mts +176 -0
  152. package/dist/v1/libs/fs/path.d.mts.map +1 -0
  153. package/dist/v1/libs/fs/path.mjs +197 -0
  154. package/dist/v1/libs/fs/plugins/OPFS/StorageBucket.cjs +202 -0
  155. package/dist/v1/libs/fs/plugins/OPFS/StorageBucket.d.mts +121 -0
  156. package/dist/v1/libs/fs/plugins/OPFS/StorageBucket.d.mts.map +1 -0
  157. package/dist/v1/libs/fs/plugins/OPFS/StorageBucket.mjs +172 -0
  158. package/dist/v1/libs/fs/plugins/OPFS/index.cjs +334 -0
  159. package/dist/v1/libs/fs/plugins/OPFS/index.d.mts +98 -0
  160. package/dist/v1/libs/fs/plugins/OPFS/index.d.mts.map +1 -0
  161. package/dist/v1/libs/fs/plugins/OPFS/index.mjs +300 -0
  162. package/dist/v1/libs/fs/stats.cjs +245 -0
  163. package/dist/v1/libs/fs/stats.d.mts +226 -0
  164. package/dist/v1/libs/fs/stats.d.mts.map +1 -0
  165. package/dist/v1/libs/fs/stats.mjs +197 -0
  166. package/dist/v1/libs/html/events/TinyIframeEvents.cjs +10 -1
  167. package/dist/v1/libs/html/events/TinyIframeEvents.d.mts +9 -2
  168. package/dist/v1/libs/html/events/TinyIframeEvents.d.mts.map +1 -1
  169. package/dist/v1/libs/html/events/TinyIframeEvents.mjs +8 -1
  170. package/dist/v1/libs/html/events/TinyNewWinEvents.cjs +14 -3
  171. package/dist/v1/libs/html/events/TinyNewWinEvents.d.mts +21 -5
  172. package/dist/v1/libs/html/events/TinyNewWinEvents.d.mts.map +1 -1
  173. package/dist/v1/libs/html/events/TinyNewWinEvents.mjs +12 -3
  174. package/dist/v1/libs/html/scroll/TinySmartScroller.cjs +13 -1
  175. package/dist/v1/libs/html/scroll/TinySmartScroller.d.mts +29 -2
  176. package/dist/v1/libs/html/scroll/TinySmartScroller.d.mts.map +1 -1
  177. package/dist/v1/libs/html/scroll/TinySmartScroller.mjs +11 -1
  178. package/dist/v1/libs/math/TinyAdvancedRaffle.cjs +13 -1
  179. package/dist/v1/libs/math/TinyAdvancedRaffle.d.mts +32 -2
  180. package/dist/v1/libs/math/TinyAdvancedRaffle.d.mts.map +1 -1
  181. package/dist/v1/libs/math/TinyAdvancedRaffle.mjs +11 -1
  182. package/dist/v1/libs/math/TinyTimeout.cjs +0 -14
  183. package/dist/v1/libs/math/TinyTimeout.d.mts +0 -11
  184. package/dist/v1/libs/math/TinyTimeout.d.mts.map +1 -1
  185. package/dist/v1/libs/math/TinyTimeout.mjs +0 -13
  186. package/dist/v1/libs/media/TinyMediaPlayer/index.cjs +25 -1
  187. package/dist/v1/libs/media/TinyMediaPlayer/index.d.mts +35 -2
  188. package/dist/v1/libs/media/TinyMediaPlayer/index.d.mts.map +1 -1
  189. package/dist/v1/libs/media/TinyMediaPlayer/index.mjs +23 -1
  190. package/dist/v1/libs/media/TinyMediaPlayer.cjs +2 -2
  191. package/dist/v1/libs/media/TinyMediaPlayer.d.mts +2 -2
  192. package/dist/v1/libs/media/TinyMediaPlayer.d.mts.map +1 -1
  193. package/dist/v1/libs/media/TinyMediaPlayer.mjs +2 -2
  194. package/dist/v1/libs/media/TinyRadioFm.cjs +19 -1
  195. package/dist/v1/libs/media/TinyRadioFm.d.mts +78 -2
  196. package/dist/v1/libs/media/TinyRadioFm.d.mts.map +1 -1
  197. package/dist/v1/libs/media/TinyRadioFm.mjs +17 -1
  198. package/dist/v1/libs/plugin/TinyPlugin.cjs +1630 -0
  199. package/dist/v1/libs/plugin/TinyPlugin.d.mts +753 -0
  200. package/dist/v1/libs/plugin/TinyPlugin.d.mts.map +1 -0
  201. package/dist/v1/libs/plugin/TinyPlugin.mjs +1376 -0
  202. package/dist/v1/libs/plugin/TinyVersion.cjs +204 -0
  203. package/dist/v1/libs/plugin/TinyVersion.d.mts +70 -0
  204. package/dist/v1/libs/plugin/TinyVersion.d.mts.map +1 -0
  205. package/dist/v1/libs/plugin/TinyVersion.mjs +179 -0
  206. package/dist/v1/libs/router/TinyRouter.cjs +661 -0
  207. package/dist/v1/libs/router/TinyRouter.d.mts +320 -0
  208. package/dist/v1/libs/router/TinyRouter.d.mts.map +1 -0
  209. package/dist/v1/libs/router/TinyRouter.mjs +572 -0
  210. package/dist/v1/libs/storage/TinyLocalStorage.cjs +20 -1
  211. package/dist/v1/libs/storage/TinyLocalStorage.d.mts +64 -2
  212. package/dist/v1/libs/storage/TinyLocalStorage.d.mts.map +1 -1
  213. package/dist/v1/libs/storage/TinyLocalStorage.mjs +18 -1
  214. package/dist/v1/libs/storage/TinyMapCache.cjs +373 -0
  215. package/dist/v1/libs/storage/TinyMapCache.d.mts +274 -0
  216. package/dist/v1/libs/storage/TinyMapCache.d.mts.map +1 -0
  217. package/dist/v1/libs/storage/TinyMapCache.mjs +333 -0
  218. package/dist/v1/libs/storage/TinySetMapDatabase.cjs +1167 -0
  219. package/dist/v1/libs/storage/TinySetMapDatabase.d.mts +603 -0
  220. package/dist/v1/libs/storage/TinySetMapDatabase.d.mts.map +1 -0
  221. package/dist/v1/libs/storage/TinySetMapDatabase.mjs +1059 -0
  222. package/dist/v1/libs/sw/browser/TinyNotificationAdapter.cjs +126 -0
  223. package/dist/v1/libs/sw/browser/TinyNotificationAdapter.d.mts +132 -0
  224. package/dist/v1/libs/sw/browser/TinyNotificationAdapter.d.mts.map +1 -0
  225. package/dist/v1/libs/sw/browser/TinyNotificationAdapter.mjs +109 -0
  226. package/dist/v1/libs/sw/browser/TinyPushManager.cjs +310 -0
  227. package/dist/v1/libs/sw/browser/TinyPushManager.d.mts +168 -0
  228. package/dist/v1/libs/sw/browser/TinyPushManager.d.mts.map +1 -0
  229. package/dist/v1/libs/sw/browser/TinyPushManager.mjs +264 -0
  230. package/dist/v1/libs/sw/browser/TinyServiceWorker.cjs +1060 -0
  231. package/dist/v1/libs/sw/browser/TinyServiceWorker.d.mts +348 -0
  232. package/dist/v1/libs/sw/browser/TinyServiceWorker.d.mts.map +1 -0
  233. package/dist/v1/libs/sw/browser/TinyServiceWorker.mjs +933 -0
  234. package/dist/v1/libs/sw/browser/plugins/TabManager.cjs +315 -0
  235. package/dist/v1/libs/sw/browser/plugins/TabManager.d.mts +178 -0
  236. package/dist/v1/libs/sw/browser/plugins/TabManager.d.mts.map +1 -0
  237. package/dist/v1/libs/sw/browser/plugins/TabManager.mjs +274 -0
  238. package/dist/v1/libs/sw/browser/utils.cjs +28 -0
  239. package/dist/v1/libs/sw/browser/utils.d.mts +8 -0
  240. package/dist/v1/libs/sw/browser/utils.d.mts.map +1 -0
  241. package/dist/v1/libs/sw/browser/utils.mjs +21 -0
  242. package/dist/v1/libs/sw/service/TinyPushRouter.cjs +222 -0
  243. package/dist/v1/libs/sw/service/TinyPushRouter.d.mts +138 -0
  244. package/dist/v1/libs/sw/service/TinyPushRouter.d.mts.map +1 -0
  245. package/dist/v1/libs/sw/service/TinyPushRouter.mjs +201 -0
  246. package/dist/v1/libs/sw/service/TinyServiceWorkerEngine.cjs +3016 -0
  247. package/dist/v1/libs/sw/service/TinyServiceWorkerEngine.d.mts +993 -0
  248. package/dist/v1/libs/sw/service/TinyServiceWorkerEngine.d.mts.map +1 -0
  249. package/dist/v1/libs/sw/service/TinyServiceWorkerEngine.mjs +2558 -0
  250. package/dist/v1/libs/sw/service/plugins/GlobBypassPlugin.cjs +88 -0
  251. package/dist/v1/libs/sw/service/plugins/GlobBypassPlugin.d.mts +32 -0
  252. package/dist/v1/libs/sw/service/plugins/GlobBypassPlugin.d.mts.map +1 -0
  253. package/dist/v1/libs/sw/service/plugins/GlobBypassPlugin.mjs +69 -0
  254. package/dist/v1/libs/sw/service/plugins/GlobCachePlugin.cjs +112 -0
  255. package/dist/v1/libs/sw/service/plugins/GlobCachePlugin.d.mts +31 -0
  256. package/dist/v1/libs/sw/service/plugins/GlobCachePlugin.d.mts.map +1 -0
  257. package/dist/v1/libs/sw/service/plugins/GlobCachePlugin.mjs +91 -0
  258. package/dist/v1/libs/sw/service/plugins/Ping.cjs +32 -0
  259. package/dist/v1/libs/sw/service/plugins/Ping.d.mts +9 -0
  260. package/dist/v1/libs/sw/service/plugins/Ping.d.mts.map +1 -0
  261. package/dist/v1/libs/sw/service/plugins/Ping.mjs +25 -0
  262. package/dist/v1/libs/sw/service/plugins/TabManager.cjs +457 -0
  263. package/dist/v1/libs/sw/service/plugins/TabManager.d.mts +91 -0
  264. package/dist/v1/libs/sw/service/plugins/TabManager.d.mts.map +1 -0
  265. package/dist/v1/libs/sw/service/plugins/TabManager.mjs +372 -0
  266. package/dist/v1/libs/sw/service/plugins/ViteFileDetector.cjs +180 -0
  267. package/dist/v1/libs/sw/service/plugins/ViteFileDetector.d.mts +28 -0
  268. package/dist/v1/libs/sw/service/plugins/ViteFileDetector.d.mts.map +1 -0
  269. package/dist/v1/libs/sw/service/plugins/ViteFileDetector.mjs +148 -0
  270. package/dist/v1/libs/sw/service/shared/TinyPushPayload.cjs +199 -0
  271. package/dist/v1/libs/sw/service/shared/TinyPushPayload.d.mts +80 -0
  272. package/dist/v1/libs/sw/service/shared/TinyPushPayload.d.mts.map +1 -0
  273. package/dist/v1/libs/sw/service/shared/TinyPushPayload.mjs +174 -0
  274. package/dist/v1/libs/sw/utils.cjs +57 -0
  275. package/dist/v1/libs/sw/utils.d.mts +173 -0
  276. package/dist/v1/libs/sw/utils.d.mts.map +1 -0
  277. package/dist/v1/libs/sw/utils.mjs +50 -0
  278. package/dist/v1/libs/text/TinyI18/Browser-NON-DOM.cjs +57 -0
  279. package/dist/v1/libs/text/TinyI18/Browser-NON-DOM.d.mts +39 -0
  280. package/dist/v1/libs/text/TinyI18/Browser-NON-DOM.d.mts.map +1 -0
  281. package/dist/v1/libs/text/TinyI18/Browser-NON-DOM.mjs +48 -0
  282. package/dist/v1/libs/text/TinyI18/Browser.cjs +64 -0
  283. package/dist/v1/libs/text/TinyI18/Browser.d.mts +47 -0
  284. package/dist/v1/libs/text/TinyI18/Browser.d.mts.map +1 -0
  285. package/dist/v1/libs/text/TinyI18/Browser.mjs +57 -0
  286. package/dist/v1/libs/text/TinyI18/Node.cjs +49 -0
  287. package/dist/v1/libs/text/TinyI18/Node.d.mts +38 -0
  288. package/dist/v1/libs/text/TinyI18/Node.d.mts.map +1 -0
  289. package/dist/v1/libs/text/TinyI18/Node.mjs +43 -0
  290. package/dist/v1/libs/text/TinyI18/browser-utils.cjs +17 -0
  291. package/dist/v1/libs/text/TinyI18/browser-utils.d.mts +8 -0
  292. package/dist/v1/libs/text/TinyI18/browser-utils.d.mts.map +1 -0
  293. package/dist/v1/libs/text/TinyI18/browser-utils.mjs +13 -0
  294. package/dist/v1/libs/text/{TinyI18.cjs → TinyI18/index.cjs} +205 -104
  295. package/dist/v1/libs/text/{TinyI18.d.mts → TinyI18/index.d.mts} +141 -92
  296. package/dist/v1/libs/text/TinyI18/index.d.mts.map +1 -0
  297. package/dist/v1/libs/text/{TinyI18.mjs → TinyI18/index.mjs} +195 -101
  298. package/dist/v1/libs/tools/TinyBrowserMonitor.cjs +1088 -0
  299. package/dist/v1/libs/tools/TinyBrowserMonitor.d.mts +621 -0
  300. package/dist/v1/libs/tools/TinyBrowserMonitor.d.mts.map +1 -0
  301. package/dist/v1/libs/tools/TinyBrowserMonitor.mjs +940 -0
  302. package/dist/v1/libs/tools/TinyDebugger.cjs +180 -19
  303. package/dist/v1/libs/tools/TinyDebugger.d.mts +220 -24
  304. package/dist/v1/libs/tools/TinyDebugger.d.mts.map +1 -1
  305. package/dist/v1/libs/tools/TinyDebugger.mjs +161 -19
  306. package/dist/v1/libs/tools/TinyHtmlTagRegexBuilder.cjs +256 -0
  307. package/dist/v1/libs/tools/TinyHtmlTagRegexBuilder.d.mts +125 -0
  308. package/dist/v1/libs/tools/TinyHtmlTagRegexBuilder.d.mts.map +1 -0
  309. package/dist/v1/libs/tools/TinyHtmlTagRegexBuilder.mjs +223 -0
  310. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Browser-NON-DOM.cjs +23 -0
  311. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Browser-NON-DOM.d.mts +17 -0
  312. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Browser-NON-DOM.d.mts.map +1 -0
  313. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Browser-NON-DOM.mjs +19 -0
  314. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Browser.cjs +23 -0
  315. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Browser.d.mts +17 -0
  316. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Browser.d.mts.map +1 -0
  317. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Browser.mjs +19 -0
  318. package/dist/v1/libs/tools/TinyHttpResponseRegistry/EmptyRequestCodes.cjs +390 -0
  319. package/dist/v1/libs/tools/TinyHttpResponseRegistry/EmptyRequestCodes.d.mts +9 -0
  320. package/dist/v1/libs/tools/TinyHttpResponseRegistry/EmptyRequestCodes.d.mts.map +1 -0
  321. package/dist/v1/libs/tools/TinyHttpResponseRegistry/EmptyRequestCodes.mjs +387 -0
  322. package/dist/v1/libs/tools/TinyHttpResponseRegistry/JsDoc.cjs +2 -0
  323. package/dist/v1/libs/tools/TinyHttpResponseRegistry/JsDoc.d.mts +27 -0
  324. package/dist/v1/libs/tools/TinyHttpResponseRegistry/JsDoc.d.mts.map +1 -0
  325. package/dist/v1/libs/tools/TinyHttpResponseRegistry/JsDoc.mjs +12 -0
  326. package/dist/v1/libs/tools/TinyHttpResponseRegistry/MozillaRequestCodes/LICENSE +53 -0
  327. package/dist/v1/libs/tools/TinyHttpResponseRegistry/MozillaRequestCodes/index.cjs +405 -0
  328. package/dist/v1/libs/tools/TinyHttpResponseRegistry/MozillaRequestCodes/index.d.mts +34 -0
  329. package/dist/v1/libs/tools/TinyHttpResponseRegistry/MozillaRequestCodes/index.d.mts.map +1 -0
  330. package/dist/v1/libs/tools/TinyHttpResponseRegistry/MozillaRequestCodes/index.mjs +342 -0
  331. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Node.cjs +23 -0
  332. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Node.d.mts +17 -0
  333. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Node.d.mts.map +1 -0
  334. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Node.mjs +19 -0
  335. package/dist/v1/libs/tools/TinyHttpResponseRegistry/RequestCodes.cjs +327 -0
  336. package/dist/v1/libs/tools/TinyHttpResponseRegistry/RequestCodes.d.mts +9 -0
  337. package/dist/v1/libs/tools/TinyHttpResponseRegistry/RequestCodes.d.mts.map +1 -0
  338. package/dist/v1/libs/tools/TinyHttpResponseRegistry/RequestCodes.mjs +324 -0
  339. package/dist/v1/libs/tools/TinyHttpResponseRegistry/index.cjs +268 -0
  340. package/dist/v1/libs/tools/TinyHttpResponseRegistry/index.d.mts +107 -0
  341. package/dist/v1/libs/tools/TinyHttpResponseRegistry/index.d.mts.map +1 -0
  342. package/dist/v1/libs/tools/TinyHttpResponseRegistry/index.mjs +238 -0
  343. package/dist/v1/libs/tools/TinyPasswordValidator.cjs +491 -0
  344. package/dist/v1/libs/tools/TinyPasswordValidator.d.mts +246 -0
  345. package/dist/v1/libs/tools/TinyPasswordValidator.d.mts.map +1 -0
  346. package/dist/v1/libs/tools/TinyPasswordValidator.mjs +434 -0
  347. package/dist/v1/libs/tools/TinyPkgExportValidator.cjs +48 -0
  348. package/dist/v1/libs/tools/TinyPkgExportValidator.d.mts +14 -0
  349. package/dist/v1/libs/tools/TinyPkgExportValidator.d.mts.map +1 -1
  350. package/dist/v1/libs/tools/TinyPkgExportValidator.mjs +44 -0
  351. package/dist/v1/libs/tools/TinySiteMap.cjs +1029 -0
  352. package/dist/v1/libs/tools/TinySiteMap.d.mts +429 -0
  353. package/dist/v1/libs/tools/TinySiteMap.d.mts.map +1 -0
  354. package/dist/v1/libs/tools/TinySiteMap.mjs +910 -0
  355. package/dist/v1/libs/tools/TinySiteMapStream.cjs +121 -0
  356. package/dist/v1/libs/tools/TinySiteMapStream.d.mts +51 -0
  357. package/dist/v1/libs/tools/TinySiteMapStream.d.mts.map +1 -0
  358. package/dist/v1/libs/tools/TinySiteMapStream.mjs +85 -0
  359. package/dist/v1/libs/tools/TinyURLSecurityVerifier.cjs +444 -0
  360. package/dist/v1/libs/tools/TinyURLSecurityVerifier.d.mts +217 -0
  361. package/dist/v1/libs/tools/TinyURLSecurityVerifier.d.mts.map +1 -0
  362. package/dist/v1/libs/tools/TinyURLSecurityVerifier.mjs +394 -0
  363. package/dist/v1/libs/tools/TinyUriParser/BlueSky.cjs +613 -0
  364. package/dist/v1/libs/tools/TinyUriParser/BlueSky.d.mts +152 -0
  365. package/dist/v1/libs/tools/TinyUriParser/BlueSky.d.mts.map +1 -0
  366. package/dist/v1/libs/tools/TinyUriParser/BlueSky.mjs +527 -0
  367. package/dist/v1/libs/tools/TinyUriParser/Discord.cjs +1119 -0
  368. package/dist/v1/libs/tools/TinyUriParser/Discord.d.mts +306 -0
  369. package/dist/v1/libs/tools/TinyUriParser/Discord.d.mts.map +1 -0
  370. package/dist/v1/libs/tools/TinyUriParser/Discord.mjs +968 -0
  371. package/dist/v1/libs/tools/TinyUriParser/MatrixProtocol.cjs +469 -0
  372. package/dist/v1/libs/tools/TinyUriParser/MatrixProtocol.d.mts +80 -0
  373. package/dist/v1/libs/tools/TinyUriParser/MatrixProtocol.d.mts.map +1 -0
  374. package/dist/v1/libs/tools/TinyUriParser/MatrixProtocol.mjs +379 -0
  375. package/dist/v1/libs/tools/TinyUriParser.cjs +217 -0
  376. package/dist/v1/libs/tools/TinyUriParser.d.mts +109 -0
  377. package/dist/v1/libs/tools/TinyUriParser.d.mts.map +1 -0
  378. package/dist/v1/libs/tools/TinyUriParser.mjs +183 -0
  379. package/dist/v1/libs/utils/TinyCloner.cjs +466 -0
  380. package/dist/v1/libs/utils/TinyCloner.d.mts +221 -0
  381. package/dist/v1/libs/utils/TinyCloner.d.mts.map +1 -0
  382. package/dist/v1/libs/utils/TinyCloner.mjs +416 -0
  383. package/dist/v1/libs/utils/TinyPromiseQueue.cjs +1 -1
  384. package/dist/v1/libs/utils/TinyPromiseQueue.d.mts +2 -2
  385. package/dist/v1/libs/utils/TinyPromiseQueue.d.mts.map +1 -1
  386. package/dist/v1/libs/utils/TinyPromiseQueue.mjs +1 -1
  387. package/dist/v1/libs/utils/TinyThrottledApi.cjs +333 -0
  388. package/dist/v1/libs/utils/TinyThrottledApi.d.mts +163 -0
  389. package/dist/v1/libs/utils/TinyThrottledApi.d.mts.map +1 -0
  390. package/dist/v1/libs/utils/TinyThrottledApi.mjs +294 -0
  391. package/dist/v1/libs/worker/browser/TinyWebWorker.cjs +342 -0
  392. package/dist/v1/libs/worker/browser/TinyWebWorker.d.mts +97 -0
  393. package/dist/v1/libs/worker/browser/TinyWebWorker.d.mts.map +1 -0
  394. package/dist/v1/libs/worker/browser/TinyWebWorker.mjs +305 -0
  395. package/dist/v1/libs/worker/engine/TinyWebWorkerEngine.cjs +346 -0
  396. package/dist/v1/libs/worker/engine/TinyWebWorkerEngine.d.mts +127 -0
  397. package/dist/v1/libs/worker/engine/TinyWebWorkerEngine.d.mts.map +1 -0
  398. package/dist/v1/libs/worker/engine/TinyWebWorkerEngine.mjs +304 -0
  399. package/dist/v1/regexp/Email.cjs +185 -0
  400. package/dist/v1/regexp/Email.d.mts +73 -0
  401. package/dist/v1/regexp/Email.d.mts.map +1 -0
  402. package/dist/v1/regexp/Email.mjs +153 -0
  403. package/dist/v1/regexp/Glob.cjs +293 -0
  404. package/dist/v1/regexp/Glob.d.mts +45 -0
  405. package/dist/v1/regexp/Glob.d.mts.map +1 -0
  406. package/dist/v1/regexp/Glob.mjs +260 -0
  407. package/dist/v1/regexp/Ipv4.cjs +57 -0
  408. package/dist/v1/regexp/Ipv4.d.mts +29 -0
  409. package/dist/v1/regexp/Ipv4.d.mts.map +1 -0
  410. package/dist/v1/regexp/Ipv4.mjs +45 -0
  411. package/dist/v1/regexp/Ipv6.cjs +67 -0
  412. package/dist/v1/regexp/Ipv6.d.mts +29 -0
  413. package/dist/v1/regexp/Ipv6.d.mts.map +1 -0
  414. package/dist/v1/regexp/Ipv6.mjs +54 -0
  415. package/dist/v1/regexp/SegmentExtractor.cjs +145 -0
  416. package/dist/v1/regexp/SegmentExtractor.d.mts +91 -0
  417. package/dist/v1/regexp/SegmentExtractor.d.mts.map +1 -0
  418. package/dist/v1/regexp/SegmentExtractor.mjs +116 -0
  419. package/dist/v1/regexp/UrlDetector.cjs +125 -0
  420. package/dist/v1/regexp/UrlDetector.d.mts +67 -0
  421. package/dist/v1/regexp/UrlDetector.d.mts.map +1 -0
  422. package/dist/v1/regexp/UrlDetector.mjs +102 -0
  423. package/dist/v1/regexp/Username/index.cjs +233 -0
  424. package/dist/v1/regexp/Username/index.d.mts +77 -0
  425. package/dist/v1/regexp/Username/index.d.mts.map +1 -0
  426. package/dist/v1/regexp/Username/index.mjs +199 -0
  427. package/dist/v1/regexp/Username/jsDoc.cjs +2 -0
  428. package/dist/v1/regexp/Username/jsDoc.d.mts +57 -0
  429. package/dist/v1/regexp/Username/jsDoc.d.mts.map +1 -0
  430. package/dist/v1/regexp/Username/jsDoc.mjs +18 -0
  431. package/dist/v1/regexp/Username/templates/BlueSky.cjs +56 -0
  432. package/dist/v1/regexp/Username/templates/BlueSky.d.mts +35 -0
  433. package/dist/v1/regexp/Username/templates/BlueSky.d.mts.map +1 -0
  434. package/dist/v1/regexp/Username/templates/BlueSky.mjs +52 -0
  435. package/dist/v1/regexp/Username/templates/Discord.cjs +505 -0
  436. package/dist/v1/regexp/Username/templates/Discord.d.mts +209 -0
  437. package/dist/v1/regexp/Username/templates/Discord.d.mts.map +1 -0
  438. package/dist/v1/regexp/Username/templates/Discord.mjs +458 -0
  439. package/dist/v1/regexp/Username/templates/MatrixProtocol.cjs +143 -0
  440. package/dist/v1/regexp/Username/templates/MatrixProtocol.d.mts +70 -0
  441. package/dist/v1/regexp/Username/templates/MatrixProtocol.d.mts.map +1 -0
  442. package/dist/v1/regexp/Username/templates/MatrixProtocol.mjs +128 -0
  443. package/dist/v1/regexp/Username/templates/deprecated/Discord.cjs +24 -0
  444. package/dist/v1/regexp/Username/templates/deprecated/Discord.d.mts +17 -0
  445. package/dist/v1/regexp/Username/templates/deprecated/Discord.d.mts.map +1 -0
  446. package/dist/v1/regexp/Username/templates/deprecated/Discord.mjs +20 -0
  447. package/dist/v1/regexp/Username/templates/index.cjs +11 -0
  448. package/dist/v1/regexp/Username/templates/index.d.mts +5 -0
  449. package/dist/v1/regexp/Username/templates/index.d.mts.map +1 -0
  450. package/dist/v1/regexp/Username/templates/index.mjs +4 -0
  451. package/dist/v1/regexp/index.cjs +41 -0
  452. package/dist/v1/regexp/index.d.mts +9 -0
  453. package/dist/v1/regexp/index.d.mts.map +1 -0
  454. package/dist/v1/regexp/index.mjs +8 -0
  455. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Browser.cjs +64 -0
  456. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Browser.d.mts +11 -0
  457. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Browser.d.mts.map +1 -0
  458. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Browser.mjs +51 -0
  459. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/FileInput.cjs +66 -0
  460. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/FileInput.d.mts +11 -0
  461. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/FileInput.d.mts.map +1 -0
  462. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/FileInput.mjs +51 -0
  463. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Node.cjs +39 -0
  464. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Node.d.mts +11 -0
  465. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Node.d.mts.map +1 -0
  466. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Node.mjs +28 -0
  467. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Template.cjs +494 -0
  468. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Template.d.mts +142 -0
  469. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Template.d.mts.map +1 -0
  470. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Template.mjs +445 -0
  471. package/dist/v1/webTemplates/bootstrap/5.3/html/BootstrapDialogs.cjs +725 -0
  472. package/dist/v1/webTemplates/bootstrap/5.3/html/BootstrapDialogs.d.mts +293 -0
  473. package/dist/v1/webTemplates/bootstrap/5.3/html/BootstrapDialogs.d.mts.map +1 -0
  474. package/dist/v1/webTemplates/bootstrap/5.3/html/BootstrapDialogs.mjs +614 -0
  475. package/dist/v1/webTemplates/bootstrap/5.3/scss/input/Placeholder-Colors-Fix.scss +64 -0
  476. package/dist/v1/webTemplates/bootstrap/5.3/scss/spacing/Spacing-Plus.scss +31 -0
  477. package/dist/v1/webTemplates/media/MediaValidator/v1/Browser/index.cjs +135 -0
  478. package/dist/v1/webTemplates/media/MediaValidator/v1/Browser/index.d.mts +83 -0
  479. package/dist/v1/webTemplates/media/MediaValidator/v1/Browser/index.d.mts.map +1 -0
  480. package/dist/v1/webTemplates/media/MediaValidator/v1/Browser/index.mjs +120 -0
  481. package/dist/v1/webTemplates/media/MediaValidator/v1/Node/index.cjs +127 -0
  482. package/dist/v1/webTemplates/media/MediaValidator/v1/Node/index.d.mts +95 -0
  483. package/dist/v1/webTemplates/media/MediaValidator/v1/Node/index.d.mts.map +1 -0
  484. package/dist/v1/webTemplates/media/MediaValidator/v1/Node/index.mjs +109 -0
  485. package/dist/v1/webTemplates/multiformats/14.0/IPFSHasher/index.cjs +83 -0
  486. package/dist/v1/webTemplates/multiformats/14.0/IPFSHasher/index.d.mts +46 -0
  487. package/dist/v1/webTemplates/multiformats/14.0/IPFSHasher/index.d.mts.map +1 -0
  488. package/dist/v1/webTemplates/multiformats/14.0/IPFSHasher/index.mjs +71 -0
  489. package/dist/v1/webTemplates/vite/7.3/plugins/TinyVitePwaPlugin.cjs +493 -0
  490. package/dist/v1/webTemplates/vite/7.3/plugins/TinyVitePwaPlugin.d.mts +67 -0
  491. package/dist/v1/webTemplates/vite/7.3/plugins/TinyVitePwaPlugin.d.mts.map +1 -0
  492. package/dist/v1/webTemplates/vite/7.3/plugins/TinyVitePwaPlugin.mjs +399 -0
  493. package/dist/v1/webTemplates/vite/7.3/plugins/githubUtils.cjs +35 -0
  494. package/dist/v1/webTemplates/vite/7.3/plugins/githubUtils.d.mts +6 -0
  495. package/dist/v1/webTemplates/vite/7.3/plugins/githubUtils.d.mts.map +1 -0
  496. package/dist/v1/webTemplates/vite/7.3/plugins/githubUtils.mjs +29 -0
  497. package/docs/info/RegExp.md +74 -0
  498. package/docs/v1/Exports.md +111 -0
  499. package/docs/v1/README.md +117 -13
  500. package/docs/v1/basics/asyncReplace.md +2 -0
  501. package/docs/v1/basics/browserDetector.md +28 -11
  502. package/docs/v1/basics/crypto.md +85 -0
  503. package/docs/v1/basics/deprecated/html.md +2 -0
  504. package/docs/v1/basics/deprecated/objFilter.md +2 -0
  505. package/docs/v1/basics/html.md +2 -0
  506. package/docs/v1/basics/objChecker.md +55 -0
  507. package/docs/v1/basics/objFilter.md +57 -86
  508. package/docs/v1/basics/promiseUtils.md +12 -3
  509. package/docs/v1/basics/text.md +0 -1
  510. package/docs/v1/libs/array/TinyArrayComparator.md +50 -39
  511. package/docs/v1/libs/fs/TinyFS.md +752 -0
  512. package/docs/v1/libs/fs/TinyOPFSFileSystem.md +495 -0
  513. package/docs/v1/libs/fs/TinyStorageBucketFileSystem.md +407 -0
  514. package/docs/v1/libs/plugin/TinyPlugin.md +441 -0
  515. package/docs/v1/libs/plugin/TinyVersion.md +145 -0
  516. package/docs/v1/libs/router/TinyRouter.md +216 -0
  517. package/docs/v1/libs/storage/TinyMapCache.md +219 -0
  518. package/docs/v1/libs/storage/TinySetMapDatabase.md +478 -0
  519. package/docs/v1/libs/sw/browser/TinyNotificationAdapter.md +280 -0
  520. package/docs/v1/libs/sw/browser/TinyPushManager.md +782 -0
  521. package/docs/v1/libs/sw/browser/TinyServiceWorker.md +365 -0
  522. package/docs/v1/libs/sw/browser/plugins/TabManager.md +133 -0
  523. package/docs/v1/libs/sw/service/TinyPushRouter.md +314 -0
  524. package/docs/v1/libs/sw/service/TinyServiceWorkerEngine.md +748 -0
  525. package/docs/v1/libs/sw/service/plugins/GlobBypassPlugin.md +229 -0
  526. package/docs/v1/libs/sw/service/plugins/GlobCachePlugin.md +91 -0
  527. package/docs/v1/libs/sw/service/plugins/Ping.md +36 -0
  528. package/docs/v1/libs/sw/service/plugins/TabManager.md +64 -0
  529. package/docs/v1/libs/sw/service/plugins/ViteFileDetector.md +92 -0
  530. package/docs/v1/libs/sw/service/shared/TinyPushPayload.md +316 -0
  531. package/docs/v1/libs/text/TinyI18.md +80 -56
  532. package/docs/v1/libs/tools/TinyBrowserMonitor.md +170 -0
  533. package/docs/v1/libs/tools/TinyDebugger.md +117 -1
  534. package/docs/v1/libs/tools/TinyHtmlTagRegexBuilder.md +141 -0
  535. package/docs/v1/libs/tools/TinyHttpResponseRegistry.md +129 -0
  536. package/docs/v1/libs/tools/TinyPasswordValidator.md +153 -0
  537. package/docs/v1/libs/tools/TinyPkgExportValidator.md +45 -1
  538. package/docs/v1/libs/tools/TinySiteMap.md +134 -0
  539. package/docs/v1/libs/tools/TinySiteMapStream.md +97 -0
  540. package/docs/v1/libs/tools/TinyURLSecurityVerifier.md +146 -0
  541. package/docs/v1/libs/tools/TinyUriParser/Discord.md +374 -0
  542. package/docs/v1/libs/tools/TinyUriParser/MatrixProtocol.md +54 -0
  543. package/docs/v1/libs/tools/TinyUriParser.md +128 -0
  544. package/docs/v1/libs/utils/TinyCloner.md +126 -0
  545. package/docs/v1/libs/utils/TinyPromiseQueue.md +1 -1
  546. package/docs/v1/libs/utils/TinyThrottledApi.md +219 -0
  547. package/docs/v1/libs/worker/browser/TinyWebWorker.md +331 -0
  548. package/docs/v1/libs/worker/engine/TinyWebWorkerEngine.md +137 -0
  549. package/docs/v1/regexp/Email.md +127 -0
  550. package/docs/v1/regexp/Glob.md +155 -0
  551. package/docs/v1/regexp/IPv4.md +103 -0
  552. package/docs/v1/regexp/IPv6.md +122 -0
  553. package/docs/v1/regexp/SegmentExtractor.md +120 -0
  554. package/docs/v1/regexp/UrlDetector.md +117 -0
  555. package/docs/v1/regexp/Username/Base.md +131 -0
  556. package/docs/v1/regexp/Username/Discord.md +267 -0
  557. package/docs/v1/regexp/Username/MatrixProtocol.md +131 -0
  558. package/docs/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters.md +569 -0
  559. package/docs/v1/webTemplates/bootstrap/5.3/html/BootstrapDialogs.md +174 -0
  560. package/docs/v1/webTemplates/media/MediaValidator/v1/Browser.md +123 -0
  561. package/docs/v1/webTemplates/media/MediaValidator/v1/Node.md +136 -0
  562. package/docs/v1/webTemplates/multiformats/14.0/IPFSHasher.md +310 -0
  563. package/docs/v1/webTemplates/vite/7.3/plugins/TinyVitePwaPlugin.md +131 -0
  564. package/docs/v1/webTemplates/vite/7.3/plugins/githubUtils.md +50 -0
  565. package/package.json +313 -18
  566. package/types/EventEmitter.d.ts +48 -0
  567. package/dist/v1/libs/text/TinyI18.d.mts.map +0 -1
@@ -0,0 +1,1376 @@
1
+ import { isJsonObject } from '../../basics/objChecker.mjs';
2
+ import TinyDebugger from '../tools/TinyDebugger.mjs';
3
+ import TinyVersion from './TinyVersion.mjs';
4
+ import { createCheckDestroyed } from '../utils/tools.mjs';
5
+ const checkDestroy = createCheckDestroyed('TinyPlugin');
6
+ /**
7
+ * Helper to check if a value matches a set or if the set allows all via '*'
8
+ * @param {string} val - The value to be checked against the set.
9
+ * @param {Set<BlackListValue>| readonly BlackListValue[]} set - The set containing the allowed or blocked values.
10
+ * @returns {boolean} True if the value matches the set or the set contains a wildcard.
11
+ */
12
+ const isMatch = (val, set) => set instanceof Set
13
+ ? set.has('*') || set.has(val)
14
+ : set.indexOf('*') > -1 || set.indexOf(val) > -1;
15
+ /** @typedef {AlgorithmIdentifier | RsaPssParams | EcdsaParams} CryptoAlgorithm - A valid Web Crypto API algorithm identifier or parameter object. */
16
+ /**
17
+ * @typedef {"pkcs8" | "raw" | "spki"} ImportKeyFormat - The format used when importing a cryptographic key.
18
+ */
19
+ /**
20
+ * @typedef {Object} PluginIdentity
21
+ * @property {string} id - The unique identifier of the plugin.
22
+ * @property {string[]} authors - The list of authors of the plugin.
23
+ * @property {string[]} categories - The list of categories of the plugin.
24
+ * @property {string[]} tags - The list of tags of the plugin.
25
+ */
26
+ /**
27
+ * Signs a plugin's identity using a private key.
28
+ * This function is intended to be used by plugin authors during the build/release process.
29
+ *
30
+ * @param {string} pluginId - The unique identifier of the plugin.
31
+ * @param {string[]} authors - The list of authors of the plugin.
32
+ * @param {string[]} categories - The list of categories the plugin belongs to.
33
+ * @param {string[]} tags - The list of tags the plugin has.
34
+ * @param {CryptoKey} privateKey - The RSA private key used for signing.
35
+ * @param {CryptoAlgorithm} [algorithm] - The cryptographic algorithm to use for signing.
36
+ * @returns {Promise<ArrayBuffer>} A promise that resolves to the digital signature.
37
+ * @throws {TypeError} If the inputs are invalid or the signing process fails.
38
+ */
39
+ export async function signPluginIdentity(pluginId, authors, categories, tags, privateKey, algorithm = { name: 'RSASSA-PKCS1-v1_5' }) {
40
+ // 1. Validate inputs
41
+ if (typeof pluginId !== 'string' || pluginId.length === 0) {
42
+ throw new TypeError('pluginId must be a non-empty string.');
43
+ }
44
+ if (!Array.isArray(authors) || authors.some((a) => typeof a !== 'string')) {
45
+ throw new TypeError('authors must be an array of strings.');
46
+ }
47
+ if (!Array.isArray(categories) || categories.some((c) => typeof c !== 'string')) {
48
+ throw new TypeError('categories must be an array of strings.');
49
+ }
50
+ if (!Array.isArray(tags) || tags.some((t) => typeof t !== 'string')) {
51
+ throw new TypeError('tags must be an array of strings.');
52
+ }
53
+ if (!(privateKey instanceof CryptoKey)) {
54
+ throw new TypeError('privateKey must be a valid CryptoKey instance.');
55
+ }
56
+ // 2. Replicate the identity logic used in TinyPluginCore
57
+ // We sort authors, categories, and tags to ensure the identity is deterministic
58
+ /** @type {PluginIdentity} */
59
+ const identityObject = {
60
+ id: pluginId,
61
+ authors: [...authors].sort(),
62
+ categories: [...categories].sort(),
63
+ tags: [...tags].sort(),
64
+ };
65
+ const identityString = JSON.stringify(identityObject);
66
+ // 3. Encode the identity string to bytes
67
+ const encoder = new TextEncoder();
68
+ const dataBytes = encoder.encode(identityString);
69
+ try {
70
+ // 4. Sign the data using RSASSA-PKCS1-v1_5
71
+ const signature = await crypto.subtle.sign(algorithm, privateKey, dataBytes);
72
+ return signature;
73
+ }
74
+ catch (error) {
75
+ throw new Error(`Failed to sign plugin identity: ${error instanceof Error ? error.message : 'Unknown error'}`);
76
+ }
77
+ }
78
+ /**
79
+ * Create a deterministic identity string.
80
+ * @param {string} pluginId - The unique identifier of the plugin.
81
+ * @param {string[]} authors - The list of authors of the plugin.
82
+ * @param {string[]} categories - The list of categories of the plugin.
83
+ * @param {string[]} tags - The list of tags of the plugin.
84
+ * @returns {string} The deterministic identity string used for verification.
85
+ */
86
+ export const createPluginIdChecker = (pluginId, authors, categories, tags) => {
87
+ if (typeof pluginId !== 'string') {
88
+ throw new TypeError('Security Error: Cryptographic mode enabled, but pluginId is missing.');
89
+ }
90
+ if (!Array.isArray(authors)) {
91
+ throw new TypeError('Security Error: Cryptographic mode enabled, but authors is missing.');
92
+ }
93
+ if (!authors.every((author) => typeof author === 'string')) {
94
+ throw new TypeError('Security Error: Cryptographic mode enabled, but authors is invalid.');
95
+ }
96
+ // We sort authors to ensure the string is identical regardless of input order
97
+ return JSON.stringify({
98
+ id: pluginId,
99
+ authors: [...authors].sort(),
100
+ categories: [...categories].sort(),
101
+ tags: [...tags].sort(),
102
+ });
103
+ };
104
+ /**
105
+ * @typedef {Object} TinyPluginConstructor - The configuration options.
106
+ * @property {DebuggerConstructor} config.logCfg - The logging configuration.
107
+ * @property {BlackListCorePartial} [sandboxBlacklist] - A list of keys to be blacklisted.
108
+ * @property {PluginAccessControlPartial} [accessControl] - Configuration for identity-based engine access.
109
+ */
110
+ /**
111
+ * Configures the access control and sandbox blacklist for the plugin system.
112
+ *
113
+ * @param {Partial<TinyPluginConstructor>} ops - The configuration options for the constructor.
114
+ * @param {PluginAccessControl} accessControl - The access control object to be configured.
115
+ * @param {BlackListCore|null} [sandboxBlacklist] - An optional blacklist for the sandbox.
116
+ */
117
+ const pluginConstrctor = (ops, accessControl, sandboxBlacklist) => {
118
+ /**
119
+ * Validates that the provided blacklist values are an array of strings or symbols.
120
+ *
121
+ * @param {string} key - The key to check.
122
+ * @param {BlackListValue[]} values - The values to check.
123
+ */
124
+ const checkBlackList = (key, values) => {
125
+ if (!Array.isArray(values) ||
126
+ !values.every((k) => typeof k === 'string' || typeof k === 'symbol')) {
127
+ throw new TypeError(`The ${key} of sandbox blacklist must be an array of strings.`);
128
+ }
129
+ };
130
+ if (isJsonObject(sandboxBlacklist) && isJsonObject(ops?.sandboxBlacklist)) {
131
+ const { get, set } = ops.sandboxBlacklist;
132
+ if (typeof get !== 'undefined') {
133
+ checkBlackList('get', get);
134
+ get.forEach((v) => sandboxBlacklist.get.add(v));
135
+ }
136
+ if (typeof set !== 'undefined') {
137
+ checkBlackList('set', set);
138
+ set.forEach((v) => sandboxBlacklist.set.add(v));
139
+ }
140
+ }
141
+ if (isJsonObject(ops?.accessControl)) {
142
+ const { mode, whitelist, blacklist, publicKey, cryptoAlgorithm, importAlgorithm, importKeyFormat, } = ops.accessControl;
143
+ if (mode !== 'none' &&
144
+ mode !== 'whitelist' &&
145
+ mode !== 'blacklist' &&
146
+ mode !== 'cryptographic') {
147
+ throw new TypeError('accessControl.mode must be "none", "whitelist", "blacklist", or "cryptographic".');
148
+ }
149
+ if (mode === 'cryptographic') {
150
+ if (typeof publicKey !== 'string') {
151
+ throw new TypeError('In cryptographic mode, accessControl.publicKey must be a string (PEM format).');
152
+ }
153
+ }
154
+ if (isJsonObject(whitelist)) {
155
+ if (typeof whitelist.ids !== 'undefined') {
156
+ checkBlackList('whitelist ids', whitelist.ids);
157
+ whitelist.ids.forEach((id) => accessControl.whitelist.ids.add(id));
158
+ }
159
+ if (typeof whitelist.authors !== 'undefined') {
160
+ checkBlackList('whistlist authors', whitelist.authors);
161
+ whitelist.authors.forEach((id) => accessControl.whitelist.authors.add(id));
162
+ }
163
+ if (typeof whitelist.categories !== 'undefined') {
164
+ checkBlackList('whistlist categories', whitelist.categories);
165
+ whitelist.categories.forEach((id) => accessControl.whitelist.categories.add(id));
166
+ }
167
+ if (typeof whitelist.tags !== 'undefined') {
168
+ checkBlackList('whistlist tags', whitelist.tags);
169
+ whitelist.tags.forEach((id) => accessControl.whitelist.tags.add(id));
170
+ }
171
+ }
172
+ if (isJsonObject(blacklist)) {
173
+ if (typeof blacklist.ids !== 'undefined') {
174
+ checkBlackList('blacklist ids', blacklist.ids);
175
+ blacklist.ids.forEach((id) => accessControl.blacklist.ids.add(id));
176
+ }
177
+ if (typeof blacklist.authors !== 'undefined') {
178
+ checkBlackList('blacklist authors', blacklist.authors);
179
+ blacklist.authors.forEach((id) => accessControl.blacklist.authors.add(id));
180
+ }
181
+ if (typeof blacklist.categories !== 'undefined') {
182
+ checkBlackList('blacklist categories', blacklist.categories);
183
+ blacklist.categories.forEach((id) => accessControl.blacklist.categories.add(id));
184
+ }
185
+ if (typeof blacklist.tags !== 'undefined') {
186
+ checkBlackList('blacklist tags', blacklist.tags);
187
+ blacklist.tags.forEach((id) => accessControl.blacklist.tags.add(id));
188
+ }
189
+ }
190
+ if (typeof mode === 'string')
191
+ accessControl.mode = mode;
192
+ if (typeof publicKey === 'string')
193
+ accessControl.publicKey = publicKey;
194
+ if (typeof cryptoAlgorithm !== 'undefined')
195
+ accessControl.cryptoAlgorithm = cryptoAlgorithm;
196
+ if (typeof importAlgorithm !== 'undefined')
197
+ accessControl.importAlgorithm = importAlgorithm;
198
+ if (typeof importKeyFormat !== 'undefined')
199
+ accessControl.importKeyFormat = importKeyFormat;
200
+ }
201
+ };
202
+ /**
203
+ * Converts a Base64 string to an ArrayBuffer.
204
+ * @param {string} base64 - The Base64 string to convert.
205
+ * @returns {ArrayBuffer} The resulting ArrayBuffer.
206
+ */
207
+ const base64ToArrayBuffer = (base64) => {
208
+ const binaryString = globalThis.atob(base64);
209
+ const bytes = new Uint8Array(binaryString.length);
210
+ for (let i = 0; i < binaryString.length; i++) {
211
+ bytes[i] = binaryString.charCodeAt(i);
212
+ }
213
+ return bytes.buffer;
214
+ };
215
+ /**
216
+ * Converts a PEM formatted key string into an ArrayBuffer by stripping headers and decoding Base64.
217
+ * @param {string} pem - The PEM string.
218
+ * @returns {ArrayBuffer} The decoded ArrayBuffer.
219
+ */
220
+ const pemToArrayBuffer = (pem) => {
221
+ const b64Lines = pem.replace(/(-----(BEGIN|END) [^-]+-----)/g, '').replace(/\s+/g, '');
222
+ return base64ToArrayBuffer(b64Lines);
223
+ };
224
+ /**
225
+ * Validate asynchronous encryption signature using the native browser API.
226
+ *
227
+ * @param {PluginAccessControl} accessControl - The access control configuration used for verification.
228
+ * @param {Set<string>} verifiedPlugins - The set of plugins that have already been verified.
229
+ * @param {string} pluginId - The unique identifier of the plugin.
230
+ * @param {string[]} authors - The list of authors of the plugin.
231
+ * @param {string[]} categories - The list of categories of the plugin.
232
+ * @param {string[]} tags - The list of tags of the plugin.
233
+ * @param {string|BufferSource} signature - The cryptographic signature provided by the plugin.
234
+ * @returns {Promise<boolean>} A promise that resolves to true if the signature is valid, false otherwise.
235
+ */
236
+ export const verifyPluginSignature = async (accessControl, verifiedPlugins, pluginId, authors, categories, tags, signature) => {
237
+ const { publicKey, cryptoAlgorithm, importKeyFormat, importAlgorithm } = accessControl;
238
+ const identity = createPluginIdChecker(pluginId, authors, categories, tags);
239
+ try {
240
+ if (typeof publicKey !== 'string') {
241
+ throw new TypeError('Security Error: Cryptographic mode enabled, but public key is missing.');
242
+ }
243
+ if (typeof signature !== 'string' &&
244
+ !(signature instanceof ArrayBuffer) &&
245
+ !(signature instanceof Uint8Array)) {
246
+ throw new TypeError('Security Error: Cryptographic mode enabled, but signature is invalid (must be string, ArrayBuffer, or Uint8Array).');
247
+ }
248
+ const encoder = new TextEncoder();
249
+ const dataBytes = encoder.encode(identity);
250
+ /** @type {ArrayBuffer} */
251
+ let importedPublicKey;
252
+ if (importKeyFormat === 'spki' || importKeyFormat === 'pkcs8') {
253
+ importedPublicKey = pemToArrayBuffer(publicKey);
254
+ }
255
+ else {
256
+ importedPublicKey =
257
+ typeof publicKey === 'string' ? base64ToArrayBuffer(publicKey) : publicKey;
258
+ }
259
+ const signatureBuffer = typeof signature === 'string' ? base64ToArrayBuffer(signature) : signature;
260
+ const cryptoKey = await crypto.subtle.importKey(importKeyFormat, importedPublicKey, importAlgorithm, false, ['verify']);
261
+ const isValid = await crypto.subtle.verify(cryptoAlgorithm, cryptoKey, signatureBuffer, dataBytes);
262
+ if (isValid)
263
+ verifiedPlugins.add(pluginId);
264
+ return isValid;
265
+ }
266
+ catch (err) {
267
+ console.error(err);
268
+ return false;
269
+ }
270
+ };
271
+ /**
272
+ * Determines if a plugin is allowed to access the specified scope based on the current mode.
273
+ *
274
+ * @param {PluginAccessControlMode} mode - The operational mode for engine access control.
275
+ * @param {string} pluginId - The unique identifier of the plugin.
276
+ * @param {readonly string[]} authors - The list of authors of the plugin.
277
+ * @param {readonly string[]} categories - The list of categories of the plugin.
278
+ * @param {readonly string[]} tags - The list of tags of the plugin.
279
+ * @param {BwList|BwListProtected} whitelist - The whitelist configuration.
280
+ * @param {BwList|BwListProtected} blacklist - The blacklist configuration.
281
+ * @param {Set<string>} verifiedPlugins - The set of plugins that have already been verified.
282
+ * @returns {boolean} True if the plugin is allowed, false otherwise.
283
+ */
284
+ const isAllowedPlugin = (mode, pluginId, authors, categories, tags, whitelist, blacklist, verifiedPlugins) => {
285
+ // Cryptographic mode: Only plugins that have been successfully verified are returned.
286
+ if (mode === 'cryptographic') {
287
+ return verifiedPlugins.has(pluginId);
288
+ }
289
+ // Whitelist mode: Only plugins whose ID or authors match the whitelist are returned.
290
+ if (mode === 'whitelist') {
291
+ const isIdAllowed = isMatch(pluginId, whitelist.ids);
292
+ const isAuthorAllowed = authors.some((a) => isMatch(a, whitelist.authors));
293
+ const isCategoryAllowed = categories.some((c) => isMatch(c, whitelist.categories));
294
+ const isTagAllowed = tags.some((t) => isMatch(t, whitelist.tags));
295
+ return isIdAllowed || isAuthorAllowed || isCategoryAllowed || isTagAllowed;
296
+ }
297
+ // Blacklist mode: Plugins matching the blacklist (ID or Author) are blocked.
298
+ if (mode === 'blacklist') {
299
+ const isIdBlocked = isMatch(pluginId, blacklist.ids);
300
+ const isAuthorBlocked = authors.some((a) => isMatch(a, blacklist.authors));
301
+ const isCategoryBlocked = categories.some((c) => isMatch(c, blacklist.categories));
302
+ const isTagBlocked = tags.some((t) => isMatch(t, blacklist.tags));
303
+ return !isIdBlocked && !isAuthorBlocked && !isCategoryBlocked && !isTagBlocked;
304
+ }
305
+ return true; // 'none' mode allows everyone
306
+ };
307
+ /**
308
+ * Creates a default access control object.
309
+ *
310
+ * @returns {PluginAccessControl} A new access control object with default settings.
311
+ */
312
+ const createAccessControl = () => ({
313
+ mode: 'none',
314
+ importKeyFormat: 'spki',
315
+ importAlgorithm: { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' },
316
+ cryptoAlgorithm: { name: 'RSASSA-PKCS1-v1_5' },
317
+ publicKey: null,
318
+ whitelist: { ids: new Set(), authors: new Set(), categories: new Set(), tags: new Set() },
319
+ blacklist: { ids: new Set(), authors: new Set(), categories: new Set(), tags: new Set() },
320
+ });
321
+ /**
322
+ * Creates a sandboxed proxy to restrict access to the provided instance.
323
+ *
324
+ * @template {TinyPlugin<any, TinyPluginLayer, string, string, any[]>|TinyPluginLayer} InstanceObj - The object to be proxied.
325
+ * @param {InstanceObj} instance - The object to be proxied.
326
+ * @param {BlackListCoreProtected|null} engineSandboxBlacklist - The blacklist from the engine sandbox.
327
+ * @param {BlackListCore|null} sandboxBlacklist - The blacklist for the plugin sandbox.
328
+ * @param {BlackListValue[]} setKeys - The list of keys allowed to be set.
329
+ * @param {BlackListValue[]} getKeys - The list of keys allowed to be accessed.
330
+ * @param {BlackListValue[]} [beGetKeys] - Additional engine keys to be blocked for getting.
331
+ * @param {BlackListValue[]} [beSetKeys] - Additional engine keys to be blocked for setting.
332
+ * @returns {InstanceObj} A proxied version of the instance with restricted access.
333
+ */
334
+ const createSandbox = (instance, engineSandboxBlacklist, sandboxBlacklist, setKeys, getKeys, beGetKeys, beSetKeys) => {
335
+ /** @type {BlackListValue[]} */
336
+ const allowedSetKeys = [...setKeys];
337
+ /** @type {BlackListValue[]} */
338
+ const allowedGetKeys = [...getKeys];
339
+ /** @type {BlackListCoreProtected} */
340
+ const coreBlacklist = engineSandboxBlacklist ?? { get: [], set: [] };
341
+ /** @type {BlackListValue[]} */
342
+ const blockedGetKeys = [...(beGetKeys ?? []), ...coreBlacklist.get];
343
+ /** @type {BlackListValue[]} */
344
+ const blockedSetKeys = [...blockedGetKeys, ...coreBlacklist.set, ...(beSetKeys ?? [])];
345
+ if (isJsonObject(sandboxBlacklist)) {
346
+ blockedGetKeys.forEach((key) => sandboxBlacklist.get.add(key));
347
+ blockedSetKeys.forEach((key) => sandboxBlacklist.set.add(key));
348
+ }
349
+ return new Proxy(instance, {
350
+ get(target, prop) {
351
+ if (allowedGetKeys.includes(prop) || allowedGetKeys.includes('*')) {
352
+ const value = Reflect.get(target, prop, target);
353
+ return typeof value === 'function' ? value.bind(target) : value;
354
+ }
355
+ // Prevent access to blocked private/internal methods
356
+ throw new Error(`Security Error: Access to property "${String(prop)}" is denied by the sandbox.`);
357
+ },
358
+ set(target, prop, newValue) {
359
+ if (allowedSetKeys.includes(prop) || allowedSetKeys.includes('*')) {
360
+ return Reflect.set(target, prop, newValue);
361
+ }
362
+ // Prevent the plugin from modifying blocked properties on the sandbox
363
+ throw new Error('Security Error: Cannot modify read-only properties on the plugin sandbox.');
364
+ },
365
+ // Ensure the prototype is protected
366
+ setPrototypeOf() {
367
+ throw new Error('Security Error: Prototype manipulation is forbidden.');
368
+ },
369
+ });
370
+ };
371
+ /** @typedef {import('../tools/TinyDebugger.mjs').DebuggerConstructor} DebuggerConstructor - The constructor function for a debugger instance. */
372
+ /**
373
+ * @typedef {Object} LayerSecurityConfig
374
+ * @property {PluginAccessControl} accessControl - The access control configuration for the layer.
375
+ * @property {BlackListCorePartial} [sandboxBlacklist] - Configuration for the layer's sandbox.
376
+ */
377
+ /**
378
+ * Represents the isolated runtime environment or state container for a plugin.
379
+ * It manages the 'ready' state and provides a secondary security layer
380
+ * mirroring the TinyPluginCore security ecosystem.
381
+ */
382
+ class TinyPluginLayer extends TinyDebugger {
383
+ #isReady = false;
384
+ /** @type {Set<string>} */
385
+ #verifiedPlugins = new Set();
386
+ /** @type {PluginAccessControl} */
387
+ #accessControl = createAccessControl();
388
+ /**
389
+ * Gets whether the layer is initialized and ready.
390
+ * @returns {boolean} True if the layer is ready, false otherwise.
391
+ */
392
+ get isReady() {
393
+ return this.#isReady;
394
+ }
395
+ /**
396
+ * Gets the current layer access control whitelist.
397
+ * @returns {BwListProtected} The current layer access control whitelist.
398
+ */
399
+ get accessControlWhitelist() {
400
+ return Object.freeze({
401
+ ids: Object.freeze([...this.#accessControl.whitelist.ids]),
402
+ authors: Object.freeze([...this.#accessControl.whitelist.authors]),
403
+ categories: Object.freeze([...this.#accessControl.whitelist.categories]),
404
+ tags: Object.freeze([...this.#accessControl.whitelist.tags]),
405
+ });
406
+ }
407
+ /**
408
+ * Gets the current layer access control blacklist.
409
+ * @returns {BwListProtected} The current layer access control blacklist.
410
+ */
411
+ get accessControlBlacklist() {
412
+ return Object.freeze({
413
+ ids: Object.freeze([...this.#accessControl.blacklist.ids]),
414
+ authors: Object.freeze([...this.#accessControl.blacklist.authors]),
415
+ categories: Object.freeze([...this.#accessControl.blacklist.categories]),
416
+ tags: Object.freeze([...this.#accessControl.blacklist.tags]),
417
+ });
418
+ }
419
+ /**
420
+ * Gets the current layer access control mode.
421
+ * @returns {PluginAccessControlMode} The current layer access control mode.
422
+ */
423
+ get accessControlMode() {
424
+ return this.#accessControl.mode;
425
+ }
426
+ /**
427
+ * Initializes a new instance of the TinyPluginLayer class.
428
+ * @param {TinyPluginConstructor} [ops] - The configuration options for the constructor.
429
+ */
430
+ constructor(ops) {
431
+ super(ops?.logCfg ?? {
432
+ id: '[_main_class_TinyPluginLayer_reset_]',
433
+ logger: console,
434
+ autoHideId: true,
435
+ debugMode: false,
436
+ useLogColors: false,
437
+ });
438
+ pluginConstrctor(ops ?? {}, this.#accessControl);
439
+ }
440
+ /**
441
+ * Internal method to initialize the layer state.
442
+ * @template {TinyPlugin<any, any, any, any, any>} Plugin - The TinyPlugin template.
443
+ * @template {any[]} Args - The type of arguments passed to the callback.
444
+ * @param {Plugin} plugin - The TinyPlugin instance.
445
+ * @param {(...args: Args) => void} [callback] - An optional callback function to execute during initialization.
446
+ * @param {Args} args - The arguments to be passed to the callback.
447
+ * @returns {this} The current instance of the TinyPluginLayer.
448
+ * @throws {Error} If the layer has already been initialized.
449
+ */
450
+ _startLayer(plugin, callback, ...args) {
451
+ if (this.#isReady) {
452
+ throw new Error('TinyPluginLayer: The layer has already been initialized.');
453
+ }
454
+ this.logSubId = plugin.logSubId;
455
+ if (typeof callback === 'function')
456
+ callback(...args);
457
+ this.#isReady = true;
458
+ return this;
459
+ }
460
+ /**
461
+ * Validates if a plugin is permitted to access the layer based on identity.
462
+ * @param {string} pluginId - The unique identifier of the plugin.
463
+ * @param {readonly string[]} authors - The list of authors of the plugin.
464
+ * @param {readonly string[]} categories - The list of categories of the plugin.
465
+ * @param {readonly string[]} tags - The list of tags of the plugin.
466
+ * @returns {boolean} True if access is granted, false otherwise.
467
+ */
468
+ canAccessLayer(pluginId, authors, categories, tags) {
469
+ const { mode, whitelist, blacklist } = this.#accessControl;
470
+ return isAllowedPlugin(mode, pluginId, authors, categories, tags, whitelist, blacklist, this.#verifiedPlugins);
471
+ }
472
+ /**
473
+ * Validates an asynchronous signature for the layer's scope.
474
+ * @param {string} pluginId - The unique identifier.
475
+ * @param {string[]} authors - The authors list.
476
+ * @param {string[]} categories - The categories list.
477
+ * @param {string[]} tags - The tags list.
478
+ * @param {string} signature - The cryptographic signature.
479
+ * @returns {Promise<boolean>} A promise that resolves to true if the signature is valid, false otherwise.
480
+ */
481
+ async verifyPluginSignature(pluginId, authors, categories, tags, signature) {
482
+ return verifyPluginSignature(this.#accessControl, this.#verifiedPlugins, pluginId, authors, categories, tags, signature);
483
+ }
484
+ /**
485
+ * Creates a secure proxy to restrict plugin access to the host.
486
+ * This ensures that even if the layer is passed to external entities,
487
+ * its internal state and lifecycle methods remain protected.
488
+ * @param {BlackListValue[]} allowedSets - The list of keys allowed to be set.
489
+ * @param {BlackListValue[]} allowedGets - The list of keys allowed to be accessed.
490
+ * @returns {this} The proxied instance of the layer.
491
+ */
492
+ _createSandbox(allowedSets, allowedGets) {
493
+ return createSandbox(this, null, null,
494
+ // Allowed set keys.
495
+ [...allowedSets],
496
+ // Allowed get keys.
497
+ [
498
+ 'isReady',
499
+ 'accessControlMode',
500
+ 'accessControlWhitelist',
501
+ 'accessControlBlacklist',
502
+ 'verifyPluginSignature',
503
+ 'canAccessLayer',
504
+ ...allowedGets,
505
+ ]);
506
+ }
507
+ }
508
+ /** @typedef {string|symbol} BlackListValue - The type of value that can be stored in a blacklist (either a string or a symbol). */
509
+ /**
510
+ * @typedef {Object} BlackListCore
511
+ * @property {Set<BlackListValue>} get - The set of restricted keys for getting.
512
+ * @property {Set<BlackListValue>} set - The set of restricted keys for setting.
513
+ */
514
+ /**
515
+ * @typedef {Object} BlackListCorePartial
516
+ * @property {BlackListValue[]} [get] - A list of restricted keys for getting.
517
+ * @property {BlackListValue[]} [set] - A list of restricted keys for setting.
518
+ */
519
+ /**
520
+ * @typedef {Object} BlackListCoreProtected
521
+ * @property {Readonly<BlackListValue[]>} get - A read-only array of restricted keys for getting.
522
+ * @property {Readonly<BlackListValue[]>} set - A read-only array of restricted keys for setting.
523
+ */
524
+ /**
525
+ * @typedef {Object} BwList
526
+ * @property {Set<BlackListValue>} ids - A set of restricted plugin IDs.
527
+ * @property {Set<BlackListValue>} authors - A set of restricted author names.
528
+ * @property {Set<BlackListValue>} categories - A set of restricted plugin categories.
529
+ * @property {Set<BlackListValue>} tags - A set of restricted plugin tags.
530
+ */
531
+ /**
532
+ * @typedef {Object} BwListArray
533
+ * @property {BlackListValue[]} ids - An array of restricted plugin IDs.
534
+ * @property {BlackListValue[]} authors - An array of restricted author names.
535
+ * @property {BlackListValue[]} categories - An array of restricted plugin categories.
536
+ * @property {BlackListValue[]} tags - An array of restricted plugin tags.
537
+ */
538
+ /**
539
+ * @typedef {Object} BwListProtected
540
+ * @property {Readonly<BlackListValue[]>} ids - A read-only array of restricted plugin IDs.
541
+ * @property {Readonly<BlackListValue[]>} authors - A read-only array of restricted author names.
542
+ * @property {Readonly<BlackListValue[]>} categories - A read-only array of restricted plugin categories.
543
+ * @property {Readonly<BlackListValue[]>} tags - A read-only array of restricted plugin tags.
544
+ */
545
+ /**
546
+ * The operational mode for engine access control.
547
+ * @typedef {'none' | 'whitelist' | 'blacklist' | 'cryptographic'} PluginAccessControlMode
548
+ */
549
+ /**
550
+ * @typedef {Object} PluginAccessControlPartial
551
+ * @property {PluginAccessControlMode} mode - The operational mode for engine access control.
552
+ * @property {BwListArray} [whitelist] - The whitelist configuration.
553
+ * @property {BwListArray} [blacklist] - The blacklist configuration.
554
+ * @property {string} [publicKey] - The public key used for cryptographic verification.
555
+ * @property {CryptoAlgorithm} [cryptoAlgorithm] - The algorithm used for signature verification.
556
+ * @property {CryptoAlgorithm} [importAlgorithm] - The algorithm used for importing the public key.
557
+ * @property {ImportKeyFormat} [importKeyFormat] - The format of the key being imported.
558
+ */
559
+ /**
560
+ * @typedef {Object} PluginAccessControl
561
+ * @property {PluginAccessControlMode} mode - The operational mode for engine access control.
562
+ * @property {BwList} whitelist - The whitelist configuration.
563
+ * @property {BwList} blacklist - The blacklist configuration.
564
+ * @property {string|null} publicKey - The public key used for cryptographic verification.
565
+ * @property {CryptoAlgorithm} cryptoAlgorithm - The algorithm used for signature verification.
566
+ * @property {CryptoAlgorithm} importAlgorithm - The algorithm used for importing the public key.
567
+ * @property {ImportKeyFormat} importKeyFormat - The format of the key being imported.
568
+ */
569
+ /**
570
+ * The core engine class responsible for managing the plugin lifecycle and registry.
571
+ * It extends TinyDebugger to provide debugging capabilities alongside plugin management.
572
+ */
573
+ class TinyPluginCore extends TinyDebugger {
574
+ /** @type {typeof TinyPluginLayer} */
575
+ static #TinyPluginLayer = TinyPluginLayer;
576
+ /** @returns {typeof TinyPluginLayer} */
577
+ static get TinyPluginLayer() {
578
+ return TinyPluginCore.#TinyPluginLayer;
579
+ }
580
+ static #pluginsDestroyEventName = 'pluginsDestroyed';
581
+ /** @type {BlackListCore} */
582
+ #sandboxBlacklist = { get: new Set(), set: new Set() };
583
+ /** @type {PluginAccessControl} */
584
+ #accessControl = createAccessControl();
585
+ /** @type {Set<string>} */
586
+ #verifiedPlugins = new Set();
587
+ /**
588
+ * Gets the event name used when all plugins are destroyed.
589
+ * @returns {string} The event name.
590
+ */
591
+ static get pluginsDestroyEventName() {
592
+ return TinyPluginCore.pluginsDestroyEventName;
593
+ }
594
+ /**
595
+ * Sets the event name used when all plugins are destroyed.
596
+ * @param {string} value - The new event name.
597
+ * @throws {TypeError} If the value is not a string.
598
+ */
599
+ static set pluginsDestroyEventName(value) {
600
+ if (typeof value !== 'string')
601
+ throw new TypeError('pluginsDestroyEventName must be a string.');
602
+ TinyPluginCore.pluginsDestroyEventName = value;
603
+ }
604
+ /** @type {Map<string, TinyPlugin<this, TinyPluginLayer, string, string, any[]>>} A map of registered plugins. */
605
+ #plugins = new Map();
606
+ /**
607
+ * Gets the blacklist of restricted keys for the engine.
608
+ * @returns {BlackListCoreProtected} A read-only array of restricted keys.
609
+ */
610
+ get sandboxBlacklist() {
611
+ return Object.freeze({
612
+ set: Object.freeze([...this.#sandboxBlacklist.set]),
613
+ get: Object.freeze([...this.#sandboxBlacklist.get]),
614
+ });
615
+ }
616
+ /**
617
+ * Returns a plain object representation of the registered plugins.
618
+ * This converts the internal Map into a standard object, providing a snapshot
619
+ * of the plugins for easier external access.
620
+ * @returns {Record<string, TinyPlugin<this, TinyPluginLayer, string, string, any[]>>} An object where keys are plugin names and values are the plugin instances.
621
+ */
622
+ get plugins() {
623
+ return Object.fromEntries(this.#plugins);
624
+ }
625
+ /**
626
+ * Gets the total number of registered plugins in the engine.
627
+ * @returns {number} The total number of registered plugins in the engine.
628
+ */
629
+ get pluginsSize() {
630
+ return this.#plugins.size;
631
+ }
632
+ /**
633
+ * Gets the current engine access control whitelist.
634
+ * @returns {BwListProtected} The current engine access control whitelist.
635
+ */
636
+ get accessControlWhitelist() {
637
+ return Object.freeze({
638
+ ids: Object.freeze([...this.#accessControl.whitelist.ids]),
639
+ authors: Object.freeze([...this.#accessControl.whitelist.authors]),
640
+ categories: Object.freeze([...this.#accessControl.whitelist.categories]),
641
+ tags: Object.freeze([...this.#accessControl.whitelist.tags]),
642
+ });
643
+ }
644
+ /**
645
+ * Gets the current engine access control blacklist.
646
+ * @returns {BwListProtected} The current engine access control blacklist.
647
+ */
648
+ get accessControlBlacklist() {
649
+ return Object.freeze({
650
+ ids: Object.freeze([...this.#accessControl.blacklist.ids]),
651
+ authors: Object.freeze([...this.#accessControl.blacklist.authors]),
652
+ categories: Object.freeze([...this.#accessControl.blacklist.categories]),
653
+ tags: Object.freeze([...this.#accessControl.blacklist.tags]),
654
+ });
655
+ }
656
+ /**
657
+ * Gets the current engine access control mode.
658
+ * @returns {PluginAccessControlMode} The current engine access control mode.
659
+ */
660
+ get accessControlMode() {
661
+ return this.#accessControl.mode;
662
+ }
663
+ /**
664
+ * Initializes a new instance of the TinyPluginCore class.
665
+ * @param {TinyPluginConstructor} ops - The configuration options.
666
+ */
667
+ constructor(ops) {
668
+ super(ops.logCfg);
669
+ pluginConstrctor(ops, this.#accessControl, this.#sandboxBlacklist);
670
+ }
671
+ /**
672
+ * Validates if a plugin is permitted to access the engine's properties based on identity.
673
+ * @param {string} pluginId - The unique identifier of the plugin.
674
+ * @param {readonly string[]} authors - The list of authors of the plugin.
675
+ * @param {readonly string[]} categories - The list of categories of the plugin.
676
+ * @param {readonly string[]} tags - The list of tags of the plugin.
677
+ * @returns {boolean} True if access is granted, false otherwise.
678
+ */
679
+ canAccessEngine(pluginId, authors, categories, tags) {
680
+ const { mode, whitelist, blacklist } = this.#accessControl;
681
+ return isAllowedPlugin(mode, pluginId, authors, categories, tags, whitelist, blacklist, this.#verifiedPlugins);
682
+ }
683
+ /**
684
+ * Validate asynchronous encryption signature using the native browser API.
685
+ * @param {string} pluginId - The unique identifier of the plugin.
686
+ * @param {string[]} authors - The list of authors of the plugin.
687
+ * @param {string[]} categories - The list of categories of the plugin.
688
+ * @param {string[]} tags - The list of tags of the plugin.
689
+ * @param {string} signature - The cryptographic signature.
690
+ * @returns {Promise<boolean>} A promise that resolves to true if the signature is valid, false otherwise.
691
+ */
692
+ async verifyPluginSignature(pluginId, authors, categories, tags, signature) {
693
+ return verifyPluginSignature(this.#accessControl, this.#verifiedPlugins, pluginId, authors, categories, tags, signature);
694
+ }
695
+ /**
696
+ * Registers a plugin instance into the engine's internal plugin registry.
697
+ *
698
+ * @param {TinyPlugin<this, TinyPluginLayer, string, string, any[]>} plugin - The plugin instance to be registered.
699
+ * @throws {TypeError} If the provided plugin is not an instance of TinyPlugin.
700
+ * @throws {Error} If the plugin is denied access to the core based on current access control rules.
701
+ */
702
+ _addPlugin(plugin) {
703
+ if (!(plugin instanceof TinyPlugin))
704
+ throw new TypeError('The provided plugin must be an instance of TinyPlugin.');
705
+ if (!this.canAccessEngine(plugin.id, plugin.authors, plugin.categories, plugin.tags)) {
706
+ throw new Error(`Security Error: Access to the core is denied for plugin "${plugin.id}" based on current access control rules.`);
707
+ }
708
+ this.#plugins.set(plugin.id, plugin);
709
+ }
710
+ /**
711
+ * Installs a new plugin into the engine and starts its lifecycle.
712
+ *
713
+ * @template {TinyPluginLayer} Layer - The type of the plugin layer.
714
+ * @template {string} Id - The type of the plugin ID.
715
+ * @template {string} Version - The type of the plugin version.
716
+ * @template {any[]} Options - The type of the configuration options.
717
+ * @param {TinyPluginInstaller<this, Layer, Id, Version, Options>} plugin - The plugin instance to be registered.
718
+ * @param {Options} options - Configuration options for the plugin.
719
+ * @returns {TinyPlugin<this, Layer, Id, Version, Options>} The newly installed plugin instance.
720
+ */
721
+ installPlugin(plugin, ...options) {
722
+ return TinyPlugin._addModuleToCore(this, plugin, ...options);
723
+ }
724
+ /**
725
+ * Checks if a specific plugin is already registered in the engine's internal registry.
726
+ * @param {TinyPlugin<this, TinyPluginLayer, string, string, any[]>|string} plugin - The plugin instance or ID to check.
727
+ * @returns {boolean} True if the plugin is registered, false otherwise.
728
+ */
729
+ hasPlugin(plugin) {
730
+ return this.#plugins.has(typeof plugin === 'string' ? plugin : plugin.id);
731
+ }
732
+ /**
733
+ * Retrieves a plugin instance by its unique identifier.
734
+ * @param {string} key - The unique identifier of the plugin.
735
+ * @returns {TinyPlugin<this, TinyPluginLayer, string, string, any[]>|undefined} The plugin instance if found, otherwise undefined.
736
+ */
737
+ getPlugin(key) {
738
+ const plugin = this.#plugins.get(key);
739
+ return plugin && !plugin.isDestroyed ? plugin : undefined;
740
+ }
741
+ /**
742
+ * Retrieves a plugin instance by its unique identifier with security enforcement.
743
+ * This method checks the target plugin's identity against the engine's
744
+ * access control rules (whitelist/blacklist/cryptographic).
745
+ *
746
+ * @template {any} ExternalPlugin - The external plugin trying to get the target plugin.
747
+ * @param {string} targetId - The unique identifier of the target plugin.
748
+ * @param {ExternalPlugin} externalPlugin - The external plugin trying to get the target plugin.
749
+ * @returns {TinyPlugin<this, TinyPluginLayer, string, string, any[]>|undefined} The plugin instance if access is granted, otherwise undefined.
750
+ */
751
+ _getPlugin(targetId, externalPlugin) {
752
+ if (!(externalPlugin instanceof TinyPlugin))
753
+ throw new TypeError('The provided external plugin must be an instance of TinyPlugin.');
754
+ const plugin = this.#plugins.get(targetId);
755
+ // If the plugin doesn't exist or has been destroyed, it is not available.
756
+ if (!plugin || plugin.isDestroyed) {
757
+ return undefined;
758
+ }
759
+ if (!plugin.layer.canAccessLayer(externalPlugin.id, externalPlugin.authors, externalPlugin.categories, externalPlugin.tags)) {
760
+ throw new Error(`Security Error: Access to the plugin "${targetId}" is denied for plugin "${externalPlugin.id}" based on current plugin access control rules.`);
761
+ }
762
+ return plugin;
763
+ }
764
+ /**
765
+ * Destroys all registered plugins and emits the destruction event.
766
+ */
767
+ destroyPlugins() {
768
+ this.#verifiedPlugins.clear();
769
+ this.#plugins.forEach((plugin) => plugin.destroy());
770
+ this.emit(TinyPluginCore.#pluginsDestroyEventName);
771
+ }
772
+ }
773
+ /**
774
+ * A function used to install a plugin into the engine.
775
+ * This function is responsible for the actual initialization logic of the plugin,
776
+ * setting up its layer and validating its configuration.
777
+ *
778
+ * @template {TinyPluginCore} Engine - The type of the engine instance.
779
+ * @template {TinyPluginLayer} Layer - The type of the layer returned by the installer.
780
+ * @template {string} IdString - The type of the plugin's unique identifier.
781
+ * @template {string} VersionString - The type of the plugin's version.
782
+ * @template {any[]} Options - The type of the plugin's configuration options.
783
+ *
784
+ * @typedef { (plugin: TinyPlugin<Engine, Layer, IdString, VersionString, Options>, ...options: Options) => Layer } TinyPluginInstaller - The plugin instance being initialized.
785
+ */
786
+ /**
787
+ * Represents a plugin instance designed to be integrated into a main engine.
788
+ * It encapsulates the plugin's identity (id and version), its connection to the engine,
789
+ * its installation logic, and any associated configuration options.
790
+ *
791
+ * @template {TinyPluginCore} Engine - The type of the engine.
792
+ * @template {TinyPluginLayer} Layer - The type of the plugin layer.
793
+ * @template {string} IdString - The type of the plugin's unique identifier.
794
+ * @template {string} VersionString - The type of the plugin's version.
795
+ * @template {any[]} Options - The type of the plugin's configuration options.
796
+ */
797
+ class TinyPlugin extends TinyDebugger {
798
+ /** @type {DebuggerConstructor} */
799
+ static #logCfg = {
800
+ id: '[_main_class_TinyPlugin_reset_]',
801
+ autoHideId: true,
802
+ logger: console,
803
+ debugMode: false,
804
+ canEmitLogs: false,
805
+ useLogColors: true,
806
+ };
807
+ /**
808
+ * Gets the logging configuration for the TinyPlugin class.
809
+ * @returns {DebuggerConstructor} The logging configuration constructor.
810
+ */
811
+ static get logCfg() {
812
+ return { ...TinyPlugin.#logCfg };
813
+ }
814
+ /**
815
+ * Sets the logging configuration for the TinyPlugin class.
816
+ * @param {DebuggerConstructor} value - The new logging configuration.
817
+ */
818
+ static set logCfg(value) {
819
+ this.#logCfg = value;
820
+ }
821
+ /**
822
+ * Installs a new plugin into a engine and starts its lifecycle.
823
+ * @template {TinyPluginCore} ExternalEngine - The type of the engine.
824
+ * @template {TinyPluginLayer} ExternalLayer - The type of the plugin layer.
825
+ * @template {string} ExternalIdString - The type of the plugin ID.
826
+ * @template {string} ExternalVersionString - The type of the plugin version.
827
+ * @template {any[]} ExternalOptions - The type of the plugin's configuration options.
828
+ * @param {ExternalEngine} engine - The main instance connected to plugin.
829
+ * @param {TinyPluginInstaller<ExternalEngine, ExternalLayer, ExternalIdString, ExternalVersionString, ExternalOptions>} plugin - The plugin instance to be registered.
830
+ * @param {ExternalOptions} options - Configuration options for the plugin.
831
+ * @returns {TinyPlugin<ExternalEngine, ExternalLayer, ExternalIdString, ExternalVersionString, ExternalOptions>} - The plugin instance.
832
+ * @throws {TypeError} If the provided engine is not an instance of TinyPluginCore.
833
+ */
834
+ static _addModuleToCore(engine, plugin, ...options) {
835
+ if (!(engine instanceof TinyPluginCore))
836
+ throw new TypeError('The provided engine must be an instance of TinyPluginCore.');
837
+ /** @type {TinyPlugin<ExternalEngine, ExternalLayer, ExternalIdString, ExternalVersionString, ExternalOptions>} */
838
+ const instance = new TinyPlugin({
839
+ engine: engine,
840
+ installer: plugin,
841
+ logCfg: { ...TinyPlugin.#logCfg, debugMode: engine.debugMode },
842
+ }, ...options);
843
+ instance._startPlugin();
844
+ // @ts-ignore
845
+ if (engine.hasPlugin(instance))
846
+ throw new Error(`A plugin with the name "${instance.id}" is already registered.`);
847
+ // @ts-ignore
848
+ engine._addPlugin(instance);
849
+ return instance;
850
+ }
851
+ /** @type {BlackListCore} */
852
+ #sandboxBlacklist = { get: new Set(), set: new Set() };
853
+ /** @type {IdString} The unique id of the plugin. */
854
+ // @ts-ignore
855
+ #id = '';
856
+ /** @type {string} The description of the plugin. */
857
+ #description = '';
858
+ /** @type {Set<string>} The list of authors of the plugin. */
859
+ #authors = new Set();
860
+ /** @type {Set<string>} The list of contributors to the plugin. */
861
+ #contributors = new Set();
862
+ /** @type {Set<string>} The categories of the plugin. */
863
+ #categories = new Set();
864
+ /** @type {Set<string>} The tags of the plugin. */
865
+ #tags = new Set();
866
+ /** @type {TinyVersion<VersionString>|null} The version string of the plugin. */
867
+ #version = null;
868
+ /** @type {Engine} The engine instance this plugin is attached to. */
869
+ #engine;
870
+ /** @type {TinyPluginInstaller<Engine, Layer, IdString, VersionString, Options>} The installer function used to initialize the plugin. */
871
+ #installer;
872
+ /** @type {Options} An array of configuration options provided to the plugin. */
873
+ #options;
874
+ /** @type {boolean} Indicates whether the plugin has already been started and is ready. */
875
+ #isReady = false;
876
+ /** @type {Layer|null} */
877
+ #layer = null;
878
+ /** @type {boolean} */
879
+ #isDestroyed = false;
880
+ /** @type {Set<BlackListValue>} */
881
+ #allowedGets = new Set();
882
+ /** @type {Set<BlackListValue>} */
883
+ #allowedSets = new Set();
884
+ /**
885
+ * Gets whether the plugin has been destroyed.
886
+ * @returns {boolean} True if the plugin has been destroyed, false otherwise.
887
+ */
888
+ get isDestroyed() {
889
+ return this.#isDestroyed;
890
+ }
891
+ /**
892
+ * Gets the plugins object from the engine.
893
+ * @returns {string[]} The plugins object from the engine.
894
+ */
895
+ get plugins() {
896
+ checkDestroy(this.#isDestroyed);
897
+ return Object.keys(this.#engine.plugins);
898
+ }
899
+ /**
900
+ * Gets the total number of plugins in the engine.
901
+ * @returns {number} The total number of plugins in the engine.
902
+ */
903
+ get pluginsSize() {
904
+ checkDestroy(this.#isDestroyed);
905
+ return this.#engine.pluginsSize;
906
+ }
907
+ /**
908
+ * Retrieves the plugin instance associated with the given ID from the engine.
909
+ * @param {string} id - The unique identifier of the plugin.
910
+ * @returns {TinyPlugin<Engine, TinyPluginLayer, string, string, any[]>|undefined} The plugin instance if found, otherwise undefined.
911
+ */
912
+ getPlugin(id) {
913
+ checkDestroy(this.#isDestroyed);
914
+ return this.#engine._getPlugin(id, this);
915
+ }
916
+ /**
917
+ * Checks if the specified plugin or ID is registered in the engine.
918
+ * @param {TinyPlugin<Engine, TinyPluginLayer, string, string, any[]>|string} plugin - The plugin instance or ID to check.
919
+ * @returns {boolean} True if the plugin is registered, false otherwise.
920
+ */
921
+ hasPlugin(plugin) {
922
+ checkDestroy(this.#isDestroyed);
923
+ return this.#engine.hasPlugin(plugin);
924
+ }
925
+ /**
926
+ * Gets the readiness status of the plugin.
927
+ * @returns {boolean} True if the plugin is ready, false otherwise.
928
+ */
929
+ get isReady() {
930
+ checkDestroy(this.#isDestroyed);
931
+ return this.#isReady;
932
+ }
933
+ /**
934
+ * Gets the unique identifier of the plugin.
935
+ * @returns {IdString} The plugin id.
936
+ */
937
+ get id() {
938
+ checkDestroy(this.#isDestroyed);
939
+ if (this.#id.length === 0)
940
+ throw new Error('Plugin id is not set.');
941
+ return this.#id;
942
+ }
943
+ /**
944
+ * Sets the unique identifier for the plugin.
945
+ * @param {IdString} value - The new unique identifier for the plugin.
946
+ * @throws {Error} If the id is already set.
947
+ * @throws {TypeError} If the value is not a string or is empty.
948
+ */
949
+ set id(value) {
950
+ checkDestroy(this.#isDestroyed);
951
+ if (this.#id.length !== 0)
952
+ throw new Error('Id is already set.');
953
+ if (typeof value !== 'string')
954
+ throw new TypeError('Id must be a string.');
955
+ if (value.length === 0)
956
+ throw new TypeError('Id cannot be empty.');
957
+ this.#id = value;
958
+ this.logSubId = `${this.#engine.logId} [_sub_class_${value}_reset_]`;
959
+ }
960
+ /**
961
+ * Gets the description of the plugin.
962
+ * @returns {string} The plugin description.
963
+ */
964
+ get description() {
965
+ checkDestroy(this.#isDestroyed);
966
+ if (this.#description.length === 0)
967
+ throw new Error('Plugin description is not set.');
968
+ return this.#description;
969
+ }
970
+ /**
971
+ * Sets the description for the plugin.
972
+ * @param {string} value - The new description for the plugin.
973
+ * @throws {Error} If the description is already set.
974
+ * @throws {TypeError} If the value is not a string or is empty.
975
+ */
976
+ set description(value) {
977
+ checkDestroy(this.#isDestroyed);
978
+ if (this.#description.length !== 0)
979
+ throw new Error('Description is already set.');
980
+ if (typeof value !== 'string')
981
+ throw new TypeError('Description must be a string.');
982
+ if (value.length === 0)
983
+ throw new TypeError('Description cannot be empty.');
984
+ this.#description = value;
985
+ }
986
+ /**
987
+ * Gets the list of authors for the plugin.
988
+ * @returns {readonly string[]} The plugin authors.
989
+ * @throws {Error} If the plugin authors are not set.
990
+ */
991
+ get authors() {
992
+ checkDestroy(this.#isDestroyed);
993
+ if (this.#authors.size === 0)
994
+ throw new Error('Plugin authors is not set.');
995
+ return Object.freeze([...this.#authors]);
996
+ }
997
+ /**
998
+ * Sets the list of authors for the plugin.
999
+ * @param {string[]} value - The new list of authors for the plugin.
1000
+ * @throws {Error} If the authors are already set.
1001
+ * @throws {TypeError} If the value is not an array of non-empty strings or is empty.
1002
+ */
1003
+ set authors(value) {
1004
+ checkDestroy(this.#isDestroyed);
1005
+ if (this.#authors.size !== 0)
1006
+ throw new Error('Authors is already set.');
1007
+ if (!Array.isArray(value) ||
1008
+ !value.every((v) => typeof v === 'string' && v.trim().length !== 0))
1009
+ throw new TypeError('Authors must be a array of non-empty strings.');
1010
+ if (value.length === 0)
1011
+ throw new TypeError('Authors cannot be empty.');
1012
+ value.forEach((v) => this.#authors.add(v));
1013
+ }
1014
+ /**
1015
+ * Gets the list of contributors to the plugin.
1016
+ * @returns {readonly string[]} The plugin contributors.
1017
+ * @throws {Error} If the plugin contributors are not set.
1018
+ */
1019
+ get contributors() {
1020
+ checkDestroy(this.#isDestroyed);
1021
+ if (this.#contributors.size === 0)
1022
+ throw new Error('Plugin contributors is not set.');
1023
+ return Object.freeze([...this.#contributors]);
1024
+ }
1025
+ /**
1026
+ * Sets the list of contributors for the plugin.
1027
+ * @param {string[]} value - The new list of contributors for the plugin.
1028
+ * @throws {Error} If the contributors are already set.
1029
+ * @throws {TypeError} If the value is not an array of non-empty strings or is empty.
1030
+ */
1031
+ set contributors(value) {
1032
+ checkDestroy(this.#isDestroyed);
1033
+ if (this.#contributors.size !== 0)
1034
+ throw new Error('Authors is already set.');
1035
+ if (!Array.isArray(value) ||
1036
+ !value.every((v) => typeof v === 'string' && v.trim().length !== 0))
1037
+ throw new TypeError('Authors must be a array of non-empty strings.');
1038
+ if (value.length === 0)
1039
+ throw new TypeError('Authors cannot be empty.');
1040
+ value.forEach((v) => this.#contributors.add(v));
1041
+ }
1042
+ /**
1043
+ * Gets the categories of the plugin.
1044
+ * @returns {readonly string[]} The plugin categories.
1045
+ * @throws {Error} If the plugin categories are not set.
1046
+ */
1047
+ get categories() {
1048
+ checkDestroy(this.#isDestroyed);
1049
+ if (this.#categories.size === 0)
1050
+ throw new Error('Plugin categories are not set.');
1051
+ return Object.freeze([...this.#categories]);
1052
+ }
1053
+ /**
1054
+ * Sets the categories for the plugin.
1055
+ * @param {string[]} value - The new list of the plugin categories.
1056
+ * @throws {Error} If the categories are already set.
1057
+ * @throws {TypeError} If the value is not an array of non-empty strings or is empty.
1058
+ */
1059
+ set categories(value) {
1060
+ checkDestroy(this.#isDestroyed);
1061
+ if (this.#categories.size !== 0)
1062
+ throw new Error('Categories are already set.');
1063
+ if (!Array.isArray(value) ||
1064
+ !value.every((v) => typeof v === 'string' && v.trim().length !== 0))
1065
+ throw new TypeError('Categories must be an array of non-empty strings.');
1066
+ if (value.length === 0)
1067
+ throw new TypeError('Categories cannot be empty.');
1068
+ value.forEach((v) => this.#categories.add(v));
1069
+ }
1070
+ /**
1071
+ * Gets the tags of the plugin.
1072
+ * @returns {readonly string[]} The plugin tags.
1073
+ * @throws {Error} If the plugin tags are not set.
1074
+ */
1075
+ get tags() {
1076
+ checkDestroy(this.#isDestroyed);
1077
+ if (this.#tags.size === 0)
1078
+ throw new Error('Plugin tags are not set.');
1079
+ return Object.freeze([...this.#tags]);
1080
+ }
1081
+ /**
1082
+ * Sets the tags for the plugin.
1083
+ * @param {string[]} value - The new list of the plugin tags.
1084
+ * @throws {Error} If the tags are already set.
1085
+ * @throws {TypeError} If the value is not an array of non-empty strings or is empty.
1086
+ */
1087
+ set tags(value) {
1088
+ checkDestroy(this.#isDestroyed);
1089
+ if (this.#tags.size !== 0)
1090
+ throw new Error('Tags are already set.');
1091
+ if (!Array.isArray(value) ||
1092
+ !value.every((v) => typeof v === 'string' && v.trim().length !== 0))
1093
+ throw new TypeError('Tags must be an array of non-empty strings.');
1094
+ if (value.length === 0)
1095
+ throw new TypeError('Tags cannot be empty.');
1096
+ value.forEach((v) => this.#tags.add(v));
1097
+ }
1098
+ /**
1099
+ * Gets the list of keys allowed to be set.
1100
+ * @returns {BlackListValue[]} The list of allowed keys for setting.
1101
+ */
1102
+ get allowedSets() {
1103
+ checkDestroy(this.#isDestroyed);
1104
+ return [...this.#allowedSets];
1105
+ }
1106
+ /**
1107
+ * Sets the list of keys allowed to be modified by the plugin.
1108
+ * @param {BlackListValue[]} value - The array of keys to be added to the allowed set.
1109
+ * @throws {Error} If the tags are already set.
1110
+ * @throws {TypeError} If the value is not an array of non-empty strings or is empty.
1111
+ */
1112
+ set allowedSets(value) {
1113
+ checkDestroy(this.#isDestroyed);
1114
+ if (this.#allowedSets.size !== 0 || this.#isReady)
1115
+ throw new Error('AllowedSets are already set.');
1116
+ if (!Array.isArray(value) ||
1117
+ !value.every((v) => typeof v === 'string' && v.trim().length !== 0))
1118
+ throw new TypeError('AllowedSets must be an array of non-empty strings.');
1119
+ if (value.length === 0)
1120
+ throw new TypeError('AllowedSets cannot be empty.');
1121
+ value.forEach((v) => this.#allowedSets.add(v));
1122
+ }
1123
+ /**
1124
+ * Gets the list of keys allowed to be accessed.
1125
+ * @returns {BlackListValue[]} The list of allowed keys for getting.
1126
+ */
1127
+ get allowedGets() {
1128
+ checkDestroy(this.#isDestroyed);
1129
+ return [...this.#allowedGets];
1130
+ }
1131
+ /**
1132
+ * Sets the list of keys allowed to be accessed by the plugin.
1133
+ * @param {BlackListValue[]} value - The array of keys to be added to the allowed get list.
1134
+ * @throws {Error} If the tags are already set.
1135
+ * @throws {TypeError} If the value is not an array of non-empty strings or is empty.
1136
+ */
1137
+ set allowedGets(value) {
1138
+ checkDestroy(this.#isDestroyed);
1139
+ if (this.#allowedGets.size !== 0 || this.#isReady)
1140
+ throw new Error('AllowedGets are already set.');
1141
+ if (!Array.isArray(value) ||
1142
+ !value.every((v) => typeof v === 'string' && v.trim().length !== 0))
1143
+ throw new TypeError('AllowedGets must be an array of non-empty strings.');
1144
+ if (value.length === 0)
1145
+ throw new TypeError('AllowedGets cannot be empty.');
1146
+ value.forEach((v) => this.#allowedGets.add(v));
1147
+ }
1148
+ /**
1149
+ * Gets the version of the plugin as a string.
1150
+ * @returns {VersionString} The plugin version.
1151
+ * @throws {Error} If the plugin version is not set.
1152
+ */
1153
+ get version() {
1154
+ checkDestroy(this.#isDestroyed);
1155
+ if (!this.#version)
1156
+ throw new Error('Plugin version is not set.');
1157
+ return this.#version.toString();
1158
+ }
1159
+ /**
1160
+ * Sets the version of the plugin.
1161
+ * @param {VersionString} value - The new version string for the plugin.
1162
+ * @throws {Error} If the version is already set.
1163
+ * @throws {TypeError} If the value is not a string or is empty.
1164
+ */
1165
+ set version(value) {
1166
+ checkDestroy(this.#isDestroyed);
1167
+ if (this.#version)
1168
+ throw new Error('Version is already set.');
1169
+ if (typeof value !== 'string')
1170
+ throw new TypeError('Version must be a string.');
1171
+ if (value.length === 0)
1172
+ throw new TypeError('Version cannot be empty.');
1173
+ this.#version = new TinyVersion(value);
1174
+ }
1175
+ /**
1176
+ * Retrieves the current version of the plugin as a TinyVersion instance.
1177
+ * @returns {TinyVersion<VersionString>} The TinyVersion instance representing the plugin's version.
1178
+ * @throws {Error} If the plugin version is not set.
1179
+ */
1180
+ get tinyVersion() {
1181
+ checkDestroy(this.#isDestroyed);
1182
+ if (!this.#version)
1183
+ throw new Error('Plugin version is not set.');
1184
+ return this.#version;
1185
+ }
1186
+ /**
1187
+ * Gets the plugin's layer instance.
1188
+ * @returns {Layer} The proxied plugin layer.
1189
+ */
1190
+ get layer() {
1191
+ checkDestroy(this.#isDestroyed);
1192
+ if (this.#layer === null)
1193
+ throw new Error('Plugin layer is not set.');
1194
+ return this.#layer._createSandbox([...this.#allowedSets], [...this.#allowedGets]);
1195
+ }
1196
+ /**
1197
+ * Gets the engine instance associated with this plugin.
1198
+ * The engine is proxied to prevent unauthorized access to internal methods.
1199
+ * @returns {Engine} The engine instance.
1200
+ * @throws {Error} If the plugin is denied access to the engine by the access control rules.
1201
+ */
1202
+ get engine() {
1203
+ checkDestroy(this.#isDestroyed);
1204
+ // Identity-based security check
1205
+ if (!this.#engine.canAccessEngine(this.#id, [...this.#authors], [...this.#categories], [...this.#tags])) {
1206
+ throw new Error(`Security Error: Access to the engine is denied for plugin "${this.id}" based on current access control rules.`);
1207
+ }
1208
+ const sandboxBlacklist = this.#sandboxBlacklist;
1209
+ return new Proxy(this.#engine, {
1210
+ get(target, prop) {
1211
+ if (sandboxBlacklist.get.has(prop)) {
1212
+ // Prevent access to blocked private/internal methods
1213
+ throw new Error(`Security Error: Access to property "${String(prop)}" is denied by the sandbox.`);
1214
+ }
1215
+ const value = Reflect.get(target, prop, target);
1216
+ return typeof value === 'function' ? value.bind(target) : value;
1217
+ },
1218
+ set(target, prop, newValue) {
1219
+ if (sandboxBlacklist.set.has(prop)) {
1220
+ // Prevent the plugin from modifying blocked properties on the sandbox
1221
+ throw new Error('Security Error: Cannot modify read-only properties on the plugin sandbox.');
1222
+ }
1223
+ return Reflect.set(target, prop, newValue);
1224
+ },
1225
+ // Ensure the prototype is protected
1226
+ setPrototypeOf() {
1227
+ throw new Error('Security Error: Prototype manipulation is forbidden.');
1228
+ },
1229
+ });
1230
+ }
1231
+ /**
1232
+ * Gets the configuration options of the plugin.
1233
+ * @returns {Options} The configuration options of the plugin.
1234
+ */
1235
+ get options() {
1236
+ checkDestroy(this.#isDestroyed);
1237
+ return this.#options;
1238
+ }
1239
+ /**
1240
+ * Gets the blacklist of restricted keys from the engine.
1241
+ * This is accessible within the plugin's sandbox for inspection.
1242
+ * @returns {BlackListCoreProtected} The blacklist from the engine.
1243
+ */
1244
+ get engineBlacklist() {
1245
+ checkDestroy(this.#isDestroyed);
1246
+ return this.#engine.sandboxBlacklist;
1247
+ }
1248
+ /**
1249
+ * Initializes a new instance of TinyPlugin.
1250
+ * @param {Object} config - The configuration object.
1251
+ * @param {Engine} config.engine - The engine instance.
1252
+ * @param {DebuggerConstructor} config.logCfg - The logging configuration.
1253
+ * @param {TinyPluginInstaller<Engine, Layer, IdString, VersionString, Options>} config.installer - The installer function.
1254
+ * @param {Options} ops - Additional configuration options.
1255
+ */
1256
+ constructor({ engine, logCfg, installer }, ...ops) {
1257
+ super(logCfg);
1258
+ this.#engine = engine;
1259
+ this.#installer = installer;
1260
+ this.#options = ops;
1261
+ }
1262
+ /**
1263
+ * Creates a secure proxy to restrict plugin access to the host.
1264
+ * This prevents the plugin from accessing the 'engine' or mutating the plugin instance.
1265
+ */
1266
+ #createSandbox() {
1267
+ const allowedSets = [
1268
+ 'id',
1269
+ 'version',
1270
+ 'description',
1271
+ 'authors',
1272
+ 'contributors',
1273
+ 'categories',
1274
+ 'tags',
1275
+ 'allowedGets',
1276
+ 'allowedSets',
1277
+ ];
1278
+ return createSandbox(this, this.#engine.sandboxBlacklist, this.#sandboxBlacklist,
1279
+ // Allowed set keys.
1280
+ allowedSets,
1281
+ // Allowed get keys.
1282
+ [
1283
+ ...allowedSets,
1284
+ 'tinyVersion',
1285
+ 'isReady',
1286
+ 'layer',
1287
+ 'options',
1288
+ 'engine',
1289
+ 'engineBlacklist',
1290
+ 'isDestroyed',
1291
+ 'pluginsSize',
1292
+ 'plugins',
1293
+ 'hasPlugin',
1294
+ 'getPlugin',
1295
+ 'log',
1296
+ 'logClear',
1297
+ 'logGroupEnd',
1298
+ 'logLabel',
1299
+ 'logTimeLabel',
1300
+ 'logAssert',
1301
+ 'logDir',
1302
+ 'logTable',
1303
+ 'toConsole',
1304
+ 'isDestroyed',
1305
+ ],
1306
+ // Blocked engine get keys
1307
+ ['getPlugin', '_getPlugin', 'plugins', 'installPlugin', '_addPlugin', 'destroyPlugins'],
1308
+ // Blocked engine set keys
1309
+ [
1310
+ 'accessControlMode',
1311
+ 'accessControlWhitelist',
1312
+ 'accessControlBlacklist',
1313
+ 'verifyPluginSignature',
1314
+ 'canAccessEngine',
1315
+ ]);
1316
+ }
1317
+ /**
1318
+ * Starts the plugin lifecycle by calling the installer.
1319
+ * @throws {Error} If the plugin is already ready.
1320
+ * @throws {Error} If the initialization fails.
1321
+ */
1322
+ _startPlugin() {
1323
+ checkDestroy(this.#isDestroyed);
1324
+ if (this.#isReady)
1325
+ throw new Error('Plugin is already ready.');
1326
+ // 1. Freeze options to prevent mutation of the configuration object
1327
+ if (this.#options) {
1328
+ Object.freeze(this.#options);
1329
+ }
1330
+ // 2. Create a sandboxed version of 'this' to pass to the installer
1331
+ const sandbox = this.#createSandbox();
1332
+ try {
1333
+ // 3. Execute installer with the sandbox and frozen options
1334
+ this.#layer = this.#installer(sandbox, ...this.#options);
1335
+ if (!(this.#layer instanceof TinyPluginLayer)) {
1336
+ throw new TypeError('Plugin layer is not a valid TinyPluginLayer instance.');
1337
+ }
1338
+ // 4. Final validation of core identity
1339
+ this.#layer.debugMode = this.debugMode;
1340
+ if (!this.#layer.isReady)
1341
+ this.#layer._startLayer(this);
1342
+ if (this.#id.length === 0)
1343
+ throw new Error('Plugin id is not set.');
1344
+ if (this.#description.length === 0)
1345
+ throw new Error('Plugin description is not set.');
1346
+ if (this.#authors.size === 0)
1347
+ throw new Error('Plugin authors are not set.');
1348
+ if (this.#contributors.size === 0)
1349
+ throw new Error('Plugin contributors are not set.');
1350
+ if (this.#categories.size === 0)
1351
+ throw new Error('Plugin categories are not set.');
1352
+ if (this.#tags.size === 0)
1353
+ throw new Error('Plugin tags are not set.');
1354
+ if (!this.#version)
1355
+ throw new Error('Plugin version is not set.');
1356
+ this.#isReady = true;
1357
+ }
1358
+ catch (error) {
1359
+ // 5. Catch initialization errors to prevent host crash
1360
+ this.emit('error', error);
1361
+ this.destroy();
1362
+ throw new Error(`Plugin initialization failed: ${error instanceof Error ? error.message : 'Unknown Error'}`);
1363
+ }
1364
+ }
1365
+ /**
1366
+ * Destroys the plugin instance.
1367
+ */
1368
+ destroy() {
1369
+ if (this.#isDestroyed)
1370
+ return;
1371
+ this.emit('destroyed');
1372
+ this.#layer?.emit('destroyed');
1373
+ this.#isDestroyed = true;
1374
+ }
1375
+ }
1376
+ export { TinyPlugin, TinyPluginCore, TinyPluginLayer };