tiny-essentials 1.28.19 โ†’ 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 (555) 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/index.cjs +88 -3
  109. package/dist/v1/index.d.mts +31 -6
  110. package/dist/v1/index.d.mts.map +1 -1
  111. package/dist/v1/index.mjs +32 -7
  112. package/dist/v1/jsdoc/EventEmitter.cjs +4 -0
  113. package/dist/v1/jsdoc/EventEmitter.d.mts +33 -0
  114. package/dist/v1/jsdoc/EventEmitter.d.mts.map +1 -0
  115. package/dist/v1/jsdoc/EventEmitter.mjs +18 -0
  116. package/dist/v1/libs/array/TinyArrayComparator.cjs +240 -25
  117. package/dist/v1/libs/array/TinyArrayComparator.d.mts +130 -22
  118. package/dist/v1/libs/array/TinyArrayComparator.d.mts.map +1 -1
  119. package/dist/v1/libs/array/TinyArrayComparator.mjs +210 -24
  120. package/dist/v1/libs/fs/constants.cjs +74 -0
  121. package/dist/v1/libs/fs/constants.d.mts +22 -0
  122. package/dist/v1/libs/fs/constants.d.mts.map +1 -0
  123. package/dist/v1/libs/fs/constants.mjs +53 -0
  124. package/dist/v1/libs/fs/encoding.cjs +118 -0
  125. package/dist/v1/libs/fs/encoding.d.mts +50 -0
  126. package/dist/v1/libs/fs/encoding.d.mts.map +1 -0
  127. package/dist/v1/libs/fs/encoding.mjs +102 -0
  128. package/dist/v1/libs/fs/error.cjs +188 -0
  129. package/dist/v1/libs/fs/error.d.mts +105 -0
  130. package/dist/v1/libs/fs/error.d.mts.map +1 -0
  131. package/dist/v1/libs/fs/error.mjs +158 -0
  132. package/dist/v1/libs/fs/handle.cjs +121 -0
  133. package/dist/v1/libs/fs/handle.d.mts +56 -0
  134. package/dist/v1/libs/fs/handle.d.mts.map +1 -0
  135. package/dist/v1/libs/fs/handle.mjs +100 -0
  136. package/dist/v1/libs/fs/index.cjs +700 -0
  137. package/dist/v1/libs/fs/index.d.mts +377 -0
  138. package/dist/v1/libs/fs/index.d.mts.map +1 -0
  139. package/dist/v1/libs/fs/index.mjs +630 -0
  140. package/dist/v1/libs/fs/path.cjs +234 -0
  141. package/dist/v1/libs/fs/path.d.mts +176 -0
  142. package/dist/v1/libs/fs/path.d.mts.map +1 -0
  143. package/dist/v1/libs/fs/path.mjs +197 -0
  144. package/dist/v1/libs/fs/plugins/OPFS/StorageBucket.cjs +202 -0
  145. package/dist/v1/libs/fs/plugins/OPFS/StorageBucket.d.mts +121 -0
  146. package/dist/v1/libs/fs/plugins/OPFS/StorageBucket.d.mts.map +1 -0
  147. package/dist/v1/libs/fs/plugins/OPFS/StorageBucket.mjs +172 -0
  148. package/dist/v1/libs/fs/plugins/OPFS/index.cjs +334 -0
  149. package/dist/v1/libs/fs/plugins/OPFS/index.d.mts +98 -0
  150. package/dist/v1/libs/fs/plugins/OPFS/index.d.mts.map +1 -0
  151. package/dist/v1/libs/fs/plugins/OPFS/index.mjs +300 -0
  152. package/dist/v1/libs/fs/stats.cjs +245 -0
  153. package/dist/v1/libs/fs/stats.d.mts +226 -0
  154. package/dist/v1/libs/fs/stats.d.mts.map +1 -0
  155. package/dist/v1/libs/fs/stats.mjs +197 -0
  156. package/dist/v1/libs/html/events/TinyIframeEvents.cjs +10 -1
  157. package/dist/v1/libs/html/events/TinyIframeEvents.d.mts +9 -2
  158. package/dist/v1/libs/html/events/TinyIframeEvents.d.mts.map +1 -1
  159. package/dist/v1/libs/html/events/TinyIframeEvents.mjs +8 -1
  160. package/dist/v1/libs/html/events/TinyNewWinEvents.cjs +14 -3
  161. package/dist/v1/libs/html/events/TinyNewWinEvents.d.mts +21 -5
  162. package/dist/v1/libs/html/events/TinyNewWinEvents.d.mts.map +1 -1
  163. package/dist/v1/libs/html/events/TinyNewWinEvents.mjs +12 -3
  164. package/dist/v1/libs/html/scroll/TinySmartScroller.cjs +13 -1
  165. package/dist/v1/libs/html/scroll/TinySmartScroller.d.mts +29 -2
  166. package/dist/v1/libs/html/scroll/TinySmartScroller.d.mts.map +1 -1
  167. package/dist/v1/libs/html/scroll/TinySmartScroller.mjs +11 -1
  168. package/dist/v1/libs/math/TinyAdvancedRaffle.cjs +13 -1
  169. package/dist/v1/libs/math/TinyAdvancedRaffle.d.mts +32 -2
  170. package/dist/v1/libs/math/TinyAdvancedRaffle.d.mts.map +1 -1
  171. package/dist/v1/libs/math/TinyAdvancedRaffle.mjs +11 -1
  172. package/dist/v1/libs/math/TinyTimeout.cjs +0 -14
  173. package/dist/v1/libs/math/TinyTimeout.d.mts +0 -11
  174. package/dist/v1/libs/math/TinyTimeout.d.mts.map +1 -1
  175. package/dist/v1/libs/math/TinyTimeout.mjs +0 -13
  176. package/dist/v1/libs/media/TinyMediaPlayer/index.cjs +25 -1
  177. package/dist/v1/libs/media/TinyMediaPlayer/index.d.mts +35 -2
  178. package/dist/v1/libs/media/TinyMediaPlayer/index.d.mts.map +1 -1
  179. package/dist/v1/libs/media/TinyMediaPlayer/index.mjs +23 -1
  180. package/dist/v1/libs/media/TinyMediaPlayer.cjs +2 -2
  181. package/dist/v1/libs/media/TinyMediaPlayer.d.mts +2 -2
  182. package/dist/v1/libs/media/TinyMediaPlayer.d.mts.map +1 -1
  183. package/dist/v1/libs/media/TinyMediaPlayer.mjs +2 -2
  184. package/dist/v1/libs/media/TinyRadioFm.cjs +19 -1
  185. package/dist/v1/libs/media/TinyRadioFm.d.mts +78 -2
  186. package/dist/v1/libs/media/TinyRadioFm.d.mts.map +1 -1
  187. package/dist/v1/libs/media/TinyRadioFm.mjs +17 -1
  188. package/dist/v1/libs/plugin/TinyPlugin.cjs +1630 -0
  189. package/dist/v1/libs/plugin/TinyPlugin.d.mts +753 -0
  190. package/dist/v1/libs/plugin/TinyPlugin.d.mts.map +1 -0
  191. package/dist/v1/libs/plugin/TinyPlugin.mjs +1376 -0
  192. package/dist/v1/libs/plugin/TinyVersion.cjs +204 -0
  193. package/dist/v1/libs/plugin/TinyVersion.d.mts +70 -0
  194. package/dist/v1/libs/plugin/TinyVersion.d.mts.map +1 -0
  195. package/dist/v1/libs/plugin/TinyVersion.mjs +179 -0
  196. package/dist/v1/libs/router/TinyRouter.cjs +661 -0
  197. package/dist/v1/libs/router/TinyRouter.d.mts +320 -0
  198. package/dist/v1/libs/router/TinyRouter.d.mts.map +1 -0
  199. package/dist/v1/libs/router/TinyRouter.mjs +572 -0
  200. package/dist/v1/libs/storage/TinyLocalStorage.cjs +20 -1
  201. package/dist/v1/libs/storage/TinyLocalStorage.d.mts +64 -2
  202. package/dist/v1/libs/storage/TinyLocalStorage.d.mts.map +1 -1
  203. package/dist/v1/libs/storage/TinyLocalStorage.mjs +18 -1
  204. package/dist/v1/libs/storage/TinyMapCache.cjs +373 -0
  205. package/dist/v1/libs/storage/TinyMapCache.d.mts +274 -0
  206. package/dist/v1/libs/storage/TinyMapCache.d.mts.map +1 -0
  207. package/dist/v1/libs/storage/TinyMapCache.mjs +333 -0
  208. package/dist/v1/libs/storage/TinySetMapDatabase.cjs +1167 -0
  209. package/dist/v1/libs/storage/TinySetMapDatabase.d.mts +603 -0
  210. package/dist/v1/libs/storage/TinySetMapDatabase.d.mts.map +1 -0
  211. package/dist/v1/libs/storage/TinySetMapDatabase.mjs +1059 -0
  212. package/dist/v1/libs/sw/browser/TinyNotificationAdapter.cjs +126 -0
  213. package/dist/v1/libs/sw/browser/TinyNotificationAdapter.d.mts +132 -0
  214. package/dist/v1/libs/sw/browser/TinyNotificationAdapter.d.mts.map +1 -0
  215. package/dist/v1/libs/sw/browser/TinyNotificationAdapter.mjs +109 -0
  216. package/dist/v1/libs/sw/browser/TinyPushManager.cjs +310 -0
  217. package/dist/v1/libs/sw/browser/TinyPushManager.d.mts +168 -0
  218. package/dist/v1/libs/sw/browser/TinyPushManager.d.mts.map +1 -0
  219. package/dist/v1/libs/sw/browser/TinyPushManager.mjs +264 -0
  220. package/dist/v1/libs/sw/browser/TinyServiceWorker.cjs +1060 -0
  221. package/dist/v1/libs/sw/browser/TinyServiceWorker.d.mts +348 -0
  222. package/dist/v1/libs/sw/browser/TinyServiceWorker.d.mts.map +1 -0
  223. package/dist/v1/libs/sw/browser/TinyServiceWorker.mjs +933 -0
  224. package/dist/v1/libs/sw/browser/plugins/TabManager.cjs +315 -0
  225. package/dist/v1/libs/sw/browser/plugins/TabManager.d.mts +178 -0
  226. package/dist/v1/libs/sw/browser/plugins/TabManager.d.mts.map +1 -0
  227. package/dist/v1/libs/sw/browser/plugins/TabManager.mjs +274 -0
  228. package/dist/v1/libs/sw/browser/utils.cjs +28 -0
  229. package/dist/v1/libs/sw/browser/utils.d.mts +8 -0
  230. package/dist/v1/libs/sw/browser/utils.d.mts.map +1 -0
  231. package/dist/v1/libs/sw/browser/utils.mjs +21 -0
  232. package/dist/v1/libs/sw/service/TinyPushRouter.cjs +222 -0
  233. package/dist/v1/libs/sw/service/TinyPushRouter.d.mts +138 -0
  234. package/dist/v1/libs/sw/service/TinyPushRouter.d.mts.map +1 -0
  235. package/dist/v1/libs/sw/service/TinyPushRouter.mjs +201 -0
  236. package/dist/v1/libs/sw/service/TinyServiceWorkerEngine.cjs +3016 -0
  237. package/dist/v1/libs/sw/service/TinyServiceWorkerEngine.d.mts +993 -0
  238. package/dist/v1/libs/sw/service/TinyServiceWorkerEngine.d.mts.map +1 -0
  239. package/dist/v1/libs/sw/service/TinyServiceWorkerEngine.mjs +2558 -0
  240. package/dist/v1/libs/sw/service/plugins/GlobBypassPlugin.cjs +88 -0
  241. package/dist/v1/libs/sw/service/plugins/GlobBypassPlugin.d.mts +32 -0
  242. package/dist/v1/libs/sw/service/plugins/GlobBypassPlugin.d.mts.map +1 -0
  243. package/dist/v1/libs/sw/service/plugins/GlobBypassPlugin.mjs +69 -0
  244. package/dist/v1/libs/sw/service/plugins/GlobCachePlugin.cjs +112 -0
  245. package/dist/v1/libs/sw/service/plugins/GlobCachePlugin.d.mts +31 -0
  246. package/dist/v1/libs/sw/service/plugins/GlobCachePlugin.d.mts.map +1 -0
  247. package/dist/v1/libs/sw/service/plugins/GlobCachePlugin.mjs +91 -0
  248. package/dist/v1/libs/sw/service/plugins/Ping.cjs +32 -0
  249. package/dist/v1/libs/sw/service/plugins/Ping.d.mts +9 -0
  250. package/dist/v1/libs/sw/service/plugins/Ping.d.mts.map +1 -0
  251. package/dist/v1/libs/sw/service/plugins/Ping.mjs +25 -0
  252. package/dist/v1/libs/sw/service/plugins/TabManager.cjs +457 -0
  253. package/dist/v1/libs/sw/service/plugins/TabManager.d.mts +91 -0
  254. package/dist/v1/libs/sw/service/plugins/TabManager.d.mts.map +1 -0
  255. package/dist/v1/libs/sw/service/plugins/TabManager.mjs +372 -0
  256. package/dist/v1/libs/sw/service/plugins/ViteFileDetector.cjs +180 -0
  257. package/dist/v1/libs/sw/service/plugins/ViteFileDetector.d.mts +28 -0
  258. package/dist/v1/libs/sw/service/plugins/ViteFileDetector.d.mts.map +1 -0
  259. package/dist/v1/libs/sw/service/plugins/ViteFileDetector.mjs +148 -0
  260. package/dist/v1/libs/sw/service/shared/TinyPushPayload.cjs +199 -0
  261. package/dist/v1/libs/sw/service/shared/TinyPushPayload.d.mts +80 -0
  262. package/dist/v1/libs/sw/service/shared/TinyPushPayload.d.mts.map +1 -0
  263. package/dist/v1/libs/sw/service/shared/TinyPushPayload.mjs +174 -0
  264. package/dist/v1/libs/sw/utils.cjs +57 -0
  265. package/dist/v1/libs/sw/utils.d.mts +173 -0
  266. package/dist/v1/libs/sw/utils.d.mts.map +1 -0
  267. package/dist/v1/libs/sw/utils.mjs +50 -0
  268. package/dist/v1/libs/text/TinyI18/Browser-NON-DOM.cjs +57 -0
  269. package/dist/v1/libs/text/TinyI18/Browser-NON-DOM.d.mts +39 -0
  270. package/dist/v1/libs/text/TinyI18/Browser-NON-DOM.d.mts.map +1 -0
  271. package/dist/v1/libs/text/TinyI18/Browser-NON-DOM.mjs +48 -0
  272. package/dist/v1/libs/text/TinyI18/Browser.cjs +64 -0
  273. package/dist/v1/libs/text/TinyI18/Browser.d.mts +47 -0
  274. package/dist/v1/libs/text/TinyI18/Browser.d.mts.map +1 -0
  275. package/dist/v1/libs/text/TinyI18/Browser.mjs +57 -0
  276. package/dist/v1/libs/text/TinyI18/Node.cjs +49 -0
  277. package/dist/v1/libs/text/TinyI18/Node.d.mts +38 -0
  278. package/dist/v1/libs/text/TinyI18/Node.d.mts.map +1 -0
  279. package/dist/v1/libs/text/TinyI18/Node.mjs +43 -0
  280. package/dist/v1/libs/text/TinyI18/browser-utils.cjs +17 -0
  281. package/dist/v1/libs/text/TinyI18/browser-utils.d.mts +8 -0
  282. package/dist/v1/libs/text/TinyI18/browser-utils.d.mts.map +1 -0
  283. package/dist/v1/libs/text/TinyI18/browser-utils.mjs +13 -0
  284. package/dist/v1/libs/text/{TinyI18.cjs โ†’ TinyI18/index.cjs} +205 -104
  285. package/dist/v1/libs/text/{TinyI18.d.mts โ†’ TinyI18/index.d.mts} +141 -92
  286. package/dist/v1/libs/text/TinyI18/index.d.mts.map +1 -0
  287. package/dist/v1/libs/text/{TinyI18.mjs โ†’ TinyI18/index.mjs} +195 -101
  288. package/dist/v1/libs/tools/TinyBrowserMonitor.cjs +1088 -0
  289. package/dist/v1/libs/tools/TinyBrowserMonitor.d.mts +621 -0
  290. package/dist/v1/libs/tools/TinyBrowserMonitor.d.mts.map +1 -0
  291. package/dist/v1/libs/tools/TinyBrowserMonitor.mjs +940 -0
  292. package/dist/v1/libs/tools/TinyDebugger.cjs +180 -19
  293. package/dist/v1/libs/tools/TinyDebugger.d.mts +220 -24
  294. package/dist/v1/libs/tools/TinyDebugger.d.mts.map +1 -1
  295. package/dist/v1/libs/tools/TinyDebugger.mjs +161 -19
  296. package/dist/v1/libs/tools/TinyHtmlTagRegexBuilder.cjs +256 -0
  297. package/dist/v1/libs/tools/TinyHtmlTagRegexBuilder.d.mts +125 -0
  298. package/dist/v1/libs/tools/TinyHtmlTagRegexBuilder.d.mts.map +1 -0
  299. package/dist/v1/libs/tools/TinyHtmlTagRegexBuilder.mjs +223 -0
  300. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Browser-NON-DOM.cjs +23 -0
  301. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Browser-NON-DOM.d.mts +17 -0
  302. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Browser-NON-DOM.d.mts.map +1 -0
  303. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Browser-NON-DOM.mjs +19 -0
  304. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Browser.cjs +23 -0
  305. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Browser.d.mts +17 -0
  306. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Browser.d.mts.map +1 -0
  307. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Browser.mjs +19 -0
  308. package/dist/v1/libs/tools/TinyHttpResponseRegistry/EmptyRequestCodes.cjs +390 -0
  309. package/dist/v1/libs/tools/TinyHttpResponseRegistry/EmptyRequestCodes.d.mts +9 -0
  310. package/dist/v1/libs/tools/TinyHttpResponseRegistry/EmptyRequestCodes.d.mts.map +1 -0
  311. package/dist/v1/libs/tools/TinyHttpResponseRegistry/EmptyRequestCodes.mjs +387 -0
  312. package/dist/v1/libs/tools/TinyHttpResponseRegistry/JsDoc.cjs +2 -0
  313. package/dist/v1/libs/tools/TinyHttpResponseRegistry/JsDoc.d.mts +27 -0
  314. package/dist/v1/libs/tools/TinyHttpResponseRegistry/JsDoc.d.mts.map +1 -0
  315. package/dist/v1/libs/tools/TinyHttpResponseRegistry/JsDoc.mjs +12 -0
  316. package/dist/v1/libs/tools/TinyHttpResponseRegistry/MozillaRequestCodes/LICENSE +53 -0
  317. package/dist/v1/libs/tools/TinyHttpResponseRegistry/MozillaRequestCodes/index.cjs +405 -0
  318. package/dist/v1/libs/tools/TinyHttpResponseRegistry/MozillaRequestCodes/index.d.mts +34 -0
  319. package/dist/v1/libs/tools/TinyHttpResponseRegistry/MozillaRequestCodes/index.d.mts.map +1 -0
  320. package/dist/v1/libs/tools/TinyHttpResponseRegistry/MozillaRequestCodes/index.mjs +342 -0
  321. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Node.cjs +23 -0
  322. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Node.d.mts +17 -0
  323. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Node.d.mts.map +1 -0
  324. package/dist/v1/libs/tools/TinyHttpResponseRegistry/Node.mjs +19 -0
  325. package/dist/v1/libs/tools/TinyHttpResponseRegistry/RequestCodes.cjs +327 -0
  326. package/dist/v1/libs/tools/TinyHttpResponseRegistry/RequestCodes.d.mts +9 -0
  327. package/dist/v1/libs/tools/TinyHttpResponseRegistry/RequestCodes.d.mts.map +1 -0
  328. package/dist/v1/libs/tools/TinyHttpResponseRegistry/RequestCodes.mjs +324 -0
  329. package/dist/v1/libs/tools/TinyHttpResponseRegistry/index.cjs +268 -0
  330. package/dist/v1/libs/tools/TinyHttpResponseRegistry/index.d.mts +107 -0
  331. package/dist/v1/libs/tools/TinyHttpResponseRegistry/index.d.mts.map +1 -0
  332. package/dist/v1/libs/tools/TinyHttpResponseRegistry/index.mjs +238 -0
  333. package/dist/v1/libs/tools/TinyPasswordValidator.cjs +491 -0
  334. package/dist/v1/libs/tools/TinyPasswordValidator.d.mts +246 -0
  335. package/dist/v1/libs/tools/TinyPasswordValidator.d.mts.map +1 -0
  336. package/dist/v1/libs/tools/TinyPasswordValidator.mjs +434 -0
  337. package/dist/v1/libs/tools/TinyPkgExportValidator.cjs +48 -0
  338. package/dist/v1/libs/tools/TinyPkgExportValidator.d.mts +14 -0
  339. package/dist/v1/libs/tools/TinyPkgExportValidator.d.mts.map +1 -1
  340. package/dist/v1/libs/tools/TinyPkgExportValidator.mjs +44 -0
  341. package/dist/v1/libs/tools/TinySiteMap.cjs +1029 -0
  342. package/dist/v1/libs/tools/TinySiteMap.d.mts +429 -0
  343. package/dist/v1/libs/tools/TinySiteMap.d.mts.map +1 -0
  344. package/dist/v1/libs/tools/TinySiteMap.mjs +910 -0
  345. package/dist/v1/libs/tools/TinySiteMapStream.cjs +121 -0
  346. package/dist/v1/libs/tools/TinySiteMapStream.d.mts +51 -0
  347. package/dist/v1/libs/tools/TinySiteMapStream.d.mts.map +1 -0
  348. package/dist/v1/libs/tools/TinySiteMapStream.mjs +85 -0
  349. package/dist/v1/libs/tools/TinyURLSecurityVerifier.cjs +444 -0
  350. package/dist/v1/libs/tools/TinyURLSecurityVerifier.d.mts +217 -0
  351. package/dist/v1/libs/tools/TinyURLSecurityVerifier.d.mts.map +1 -0
  352. package/dist/v1/libs/tools/TinyURLSecurityVerifier.mjs +394 -0
  353. package/dist/v1/libs/tools/TinyUriParser/BlueSky.cjs +613 -0
  354. package/dist/v1/libs/tools/TinyUriParser/BlueSky.d.mts +152 -0
  355. package/dist/v1/libs/tools/TinyUriParser/BlueSky.d.mts.map +1 -0
  356. package/dist/v1/libs/tools/TinyUriParser/BlueSky.mjs +527 -0
  357. package/dist/v1/libs/tools/TinyUriParser/Discord.cjs +1119 -0
  358. package/dist/v1/libs/tools/TinyUriParser/Discord.d.mts +306 -0
  359. package/dist/v1/libs/tools/TinyUriParser/Discord.d.mts.map +1 -0
  360. package/dist/v1/libs/tools/TinyUriParser/Discord.mjs +968 -0
  361. package/dist/v1/libs/tools/TinyUriParser/MatrixProtocol.cjs +469 -0
  362. package/dist/v1/libs/tools/TinyUriParser/MatrixProtocol.d.mts +80 -0
  363. package/dist/v1/libs/tools/TinyUriParser/MatrixProtocol.d.mts.map +1 -0
  364. package/dist/v1/libs/tools/TinyUriParser/MatrixProtocol.mjs +379 -0
  365. package/dist/v1/libs/tools/TinyUriParser.cjs +217 -0
  366. package/dist/v1/libs/tools/TinyUriParser.d.mts +109 -0
  367. package/dist/v1/libs/tools/TinyUriParser.d.mts.map +1 -0
  368. package/dist/v1/libs/tools/TinyUriParser.mjs +183 -0
  369. package/dist/v1/libs/utils/TinyCloner.cjs +466 -0
  370. package/dist/v1/libs/utils/TinyCloner.d.mts +221 -0
  371. package/dist/v1/libs/utils/TinyCloner.d.mts.map +1 -0
  372. package/dist/v1/libs/utils/TinyCloner.mjs +416 -0
  373. package/dist/v1/libs/utils/TinyPromiseQueue.cjs +1 -1
  374. package/dist/v1/libs/utils/TinyPromiseQueue.d.mts +2 -2
  375. package/dist/v1/libs/utils/TinyPromiseQueue.d.mts.map +1 -1
  376. package/dist/v1/libs/utils/TinyPromiseQueue.mjs +1 -1
  377. package/dist/v1/libs/utils/TinyThrottledApi.cjs +333 -0
  378. package/dist/v1/libs/utils/TinyThrottledApi.d.mts +163 -0
  379. package/dist/v1/libs/utils/TinyThrottledApi.d.mts.map +1 -0
  380. package/dist/v1/libs/utils/TinyThrottledApi.mjs +294 -0
  381. package/dist/v1/libs/worker/browser/TinyWebWorker.cjs +342 -0
  382. package/dist/v1/libs/worker/browser/TinyWebWorker.d.mts +97 -0
  383. package/dist/v1/libs/worker/browser/TinyWebWorker.d.mts.map +1 -0
  384. package/dist/v1/libs/worker/browser/TinyWebWorker.mjs +305 -0
  385. package/dist/v1/libs/worker/engine/TinyWebWorkerEngine.cjs +346 -0
  386. package/dist/v1/libs/worker/engine/TinyWebWorkerEngine.d.mts +127 -0
  387. package/dist/v1/libs/worker/engine/TinyWebWorkerEngine.d.mts.map +1 -0
  388. package/dist/v1/libs/worker/engine/TinyWebWorkerEngine.mjs +304 -0
  389. package/dist/v1/regexp/Email.cjs +185 -0
  390. package/dist/v1/regexp/Email.d.mts +73 -0
  391. package/dist/v1/regexp/Email.d.mts.map +1 -0
  392. package/dist/v1/regexp/Email.mjs +153 -0
  393. package/dist/v1/regexp/Glob.cjs +293 -0
  394. package/dist/v1/regexp/Glob.d.mts +45 -0
  395. package/dist/v1/regexp/Glob.d.mts.map +1 -0
  396. package/dist/v1/regexp/Glob.mjs +260 -0
  397. package/dist/v1/regexp/Ipv4.cjs +57 -0
  398. package/dist/v1/regexp/Ipv4.d.mts +29 -0
  399. package/dist/v1/regexp/Ipv4.d.mts.map +1 -0
  400. package/dist/v1/regexp/Ipv4.mjs +45 -0
  401. package/dist/v1/regexp/Ipv6.cjs +67 -0
  402. package/dist/v1/regexp/Ipv6.d.mts +29 -0
  403. package/dist/v1/regexp/Ipv6.d.mts.map +1 -0
  404. package/dist/v1/regexp/Ipv6.mjs +54 -0
  405. package/dist/v1/regexp/SegmentExtractor.cjs +145 -0
  406. package/dist/v1/regexp/SegmentExtractor.d.mts +91 -0
  407. package/dist/v1/regexp/SegmentExtractor.d.mts.map +1 -0
  408. package/dist/v1/regexp/SegmentExtractor.mjs +116 -0
  409. package/dist/v1/regexp/UrlDetector.cjs +125 -0
  410. package/dist/v1/regexp/UrlDetector.d.mts +67 -0
  411. package/dist/v1/regexp/UrlDetector.d.mts.map +1 -0
  412. package/dist/v1/regexp/UrlDetector.mjs +102 -0
  413. package/dist/v1/regexp/Username/index.cjs +233 -0
  414. package/dist/v1/regexp/Username/index.d.mts +77 -0
  415. package/dist/v1/regexp/Username/index.d.mts.map +1 -0
  416. package/dist/v1/regexp/Username/index.mjs +199 -0
  417. package/dist/v1/regexp/Username/jsDoc.cjs +2 -0
  418. package/dist/v1/regexp/Username/jsDoc.d.mts +57 -0
  419. package/dist/v1/regexp/Username/jsDoc.d.mts.map +1 -0
  420. package/dist/v1/regexp/Username/jsDoc.mjs +18 -0
  421. package/dist/v1/regexp/Username/templates/BlueSky.cjs +56 -0
  422. package/dist/v1/regexp/Username/templates/BlueSky.d.mts +35 -0
  423. package/dist/v1/regexp/Username/templates/BlueSky.d.mts.map +1 -0
  424. package/dist/v1/regexp/Username/templates/BlueSky.mjs +52 -0
  425. package/dist/v1/regexp/Username/templates/Discord.cjs +505 -0
  426. package/dist/v1/regexp/Username/templates/Discord.d.mts +209 -0
  427. package/dist/v1/regexp/Username/templates/Discord.d.mts.map +1 -0
  428. package/dist/v1/regexp/Username/templates/Discord.mjs +458 -0
  429. package/dist/v1/regexp/Username/templates/MatrixProtocol.cjs +143 -0
  430. package/dist/v1/regexp/Username/templates/MatrixProtocol.d.mts +70 -0
  431. package/dist/v1/regexp/Username/templates/MatrixProtocol.d.mts.map +1 -0
  432. package/dist/v1/regexp/Username/templates/MatrixProtocol.mjs +128 -0
  433. package/dist/v1/regexp/Username/templates/deprecated/Discord.cjs +24 -0
  434. package/dist/v1/regexp/Username/templates/deprecated/Discord.d.mts +17 -0
  435. package/dist/v1/regexp/Username/templates/deprecated/Discord.d.mts.map +1 -0
  436. package/dist/v1/regexp/Username/templates/deprecated/Discord.mjs +20 -0
  437. package/dist/v1/regexp/Username/templates/index.cjs +11 -0
  438. package/dist/v1/regexp/Username/templates/index.d.mts +5 -0
  439. package/dist/v1/regexp/Username/templates/index.d.mts.map +1 -0
  440. package/dist/v1/regexp/Username/templates/index.mjs +4 -0
  441. package/dist/v1/regexp/index.cjs +41 -0
  442. package/dist/v1/regexp/index.d.mts +9 -0
  443. package/dist/v1/regexp/index.d.mts.map +1 -0
  444. package/dist/v1/regexp/index.mjs +8 -0
  445. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Browser.cjs +64 -0
  446. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Browser.d.mts +11 -0
  447. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Browser.d.mts.map +1 -0
  448. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Browser.mjs +51 -0
  449. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/FileInput.cjs +66 -0
  450. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/FileInput.d.mts +11 -0
  451. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/FileInput.d.mts.map +1 -0
  452. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/FileInput.mjs +51 -0
  453. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Node.cjs +39 -0
  454. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Node.d.mts +11 -0
  455. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Node.d.mts.map +1 -0
  456. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Node.mjs +28 -0
  457. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Template.cjs +494 -0
  458. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Template.d.mts +142 -0
  459. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Template.d.mts.map +1 -0
  460. package/dist/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters/Template.mjs +445 -0
  461. package/dist/v1/webTemplates/bootstrap/5.3/html/BootstrapDialogs.cjs +30 -4
  462. package/dist/v1/webTemplates/bootstrap/5.3/html/BootstrapDialogs.d.mts +5 -2
  463. package/dist/v1/webTemplates/bootstrap/5.3/html/BootstrapDialogs.d.mts.map +1 -1
  464. package/dist/v1/webTemplates/bootstrap/5.3/html/BootstrapDialogs.mjs +29 -5
  465. package/dist/v1/webTemplates/media/MediaValidator/v1/Browser/index.cjs +135 -0
  466. package/dist/v1/webTemplates/media/MediaValidator/v1/Browser/index.d.mts +83 -0
  467. package/dist/v1/webTemplates/media/MediaValidator/v1/Browser/index.d.mts.map +1 -0
  468. package/dist/v1/webTemplates/media/MediaValidator/v1/Browser/index.mjs +120 -0
  469. package/dist/v1/webTemplates/media/MediaValidator/v1/Node/index.cjs +127 -0
  470. package/dist/v1/webTemplates/media/MediaValidator/v1/Node/index.d.mts +95 -0
  471. package/dist/v1/webTemplates/media/MediaValidator/v1/Node/index.d.mts.map +1 -0
  472. package/dist/v1/webTemplates/media/MediaValidator/v1/Node/index.mjs +109 -0
  473. package/dist/v1/webTemplates/multiformats/14.0/IPFSHasher/index.cjs +83 -0
  474. package/dist/v1/webTemplates/multiformats/14.0/IPFSHasher/index.d.mts +46 -0
  475. package/dist/v1/webTemplates/multiformats/14.0/IPFSHasher/index.d.mts.map +1 -0
  476. package/dist/v1/webTemplates/multiformats/14.0/IPFSHasher/index.mjs +71 -0
  477. package/dist/v1/webTemplates/vite/7.3/plugins/TinyVitePwaPlugin.cjs +493 -0
  478. package/dist/v1/webTemplates/vite/7.3/plugins/TinyVitePwaPlugin.d.mts +67 -0
  479. package/dist/v1/webTemplates/vite/7.3/plugins/TinyVitePwaPlugin.d.mts.map +1 -0
  480. package/dist/v1/webTemplates/vite/7.3/plugins/TinyVitePwaPlugin.mjs +399 -0
  481. package/dist/v1/webTemplates/vite/7.3/plugins/githubUtils.cjs +35 -0
  482. package/dist/v1/webTemplates/vite/7.3/plugins/githubUtils.d.mts +6 -0
  483. package/dist/v1/webTemplates/vite/7.3/plugins/githubUtils.d.mts.map +1 -0
  484. package/dist/v1/webTemplates/vite/7.3/plugins/githubUtils.mjs +29 -0
  485. package/docs/info/RegExp.md +74 -0
  486. package/docs/v1/Exports.md +101 -0
  487. package/docs/v1/README.md +113 -15
  488. package/docs/v1/basics/asyncReplace.md +2 -0
  489. package/docs/v1/basics/browserDetector.md +28 -11
  490. package/docs/v1/basics/crypto.md +85 -0
  491. package/docs/v1/basics/deprecated/html.md +2 -0
  492. package/docs/v1/basics/deprecated/objFilter.md +2 -0
  493. package/docs/v1/basics/html.md +2 -0
  494. package/docs/v1/basics/objChecker.md +55 -0
  495. package/docs/v1/basics/objFilter.md +57 -86
  496. package/docs/v1/basics/promiseUtils.md +12 -3
  497. package/docs/v1/basics/text.md +0 -1
  498. package/docs/v1/libs/array/TinyArrayComparator.md +50 -39
  499. package/docs/v1/libs/fs/TinyFS.md +752 -0
  500. package/docs/v1/libs/fs/TinyOPFSFileSystem.md +495 -0
  501. package/docs/v1/libs/fs/TinyStorageBucketFileSystem.md +407 -0
  502. package/docs/v1/libs/plugin/TinyPlugin.md +441 -0
  503. package/docs/v1/libs/plugin/TinyVersion.md +145 -0
  504. package/docs/v1/libs/router/TinyRouter.md +216 -0
  505. package/docs/v1/libs/storage/TinyMapCache.md +219 -0
  506. package/docs/v1/libs/storage/TinySetMapDatabase.md +478 -0
  507. package/docs/v1/libs/sw/browser/TinyNotificationAdapter.md +280 -0
  508. package/docs/v1/libs/sw/browser/TinyPushManager.md +782 -0
  509. package/docs/v1/libs/sw/browser/TinyServiceWorker.md +365 -0
  510. package/docs/v1/libs/sw/browser/plugins/TabManager.md +133 -0
  511. package/docs/v1/libs/sw/service/TinyPushRouter.md +314 -0
  512. package/docs/v1/libs/sw/service/TinyServiceWorkerEngine.md +748 -0
  513. package/docs/v1/libs/sw/service/plugins/GlobBypassPlugin.md +229 -0
  514. package/docs/v1/libs/sw/service/plugins/GlobCachePlugin.md +91 -0
  515. package/docs/v1/libs/sw/service/plugins/Ping.md +36 -0
  516. package/docs/v1/libs/sw/service/plugins/TabManager.md +64 -0
  517. package/docs/v1/libs/sw/service/plugins/ViteFileDetector.md +92 -0
  518. package/docs/v1/libs/sw/service/shared/TinyPushPayload.md +316 -0
  519. package/docs/v1/libs/text/TinyI18.md +80 -56
  520. package/docs/v1/libs/tools/TinyBrowserMonitor.md +170 -0
  521. package/docs/v1/libs/tools/TinyDebugger.md +117 -1
  522. package/docs/v1/libs/tools/TinyHtmlTagRegexBuilder.md +141 -0
  523. package/docs/v1/libs/tools/TinyHttpResponseRegistry.md +129 -0
  524. package/docs/v1/libs/tools/TinyPasswordValidator.md +153 -0
  525. package/docs/v1/libs/tools/TinyPkgExportValidator.md +45 -1
  526. package/docs/v1/libs/tools/TinySiteMap.md +134 -0
  527. package/docs/v1/libs/tools/TinySiteMapStream.md +97 -0
  528. package/docs/v1/libs/tools/TinyURLSecurityVerifier.md +146 -0
  529. package/docs/v1/libs/tools/TinyUriParser/Discord.md +374 -0
  530. package/docs/v1/libs/tools/TinyUriParser/MatrixProtocol.md +54 -0
  531. package/docs/v1/libs/tools/TinyUriParser.md +128 -0
  532. package/docs/v1/libs/utils/TinyCloner.md +126 -0
  533. package/docs/v1/libs/utils/TinyPromiseQueue.md +1 -1
  534. package/docs/v1/libs/utils/TinyThrottledApi.md +219 -0
  535. package/docs/v1/libs/worker/browser/TinyWebWorker.md +331 -0
  536. package/docs/v1/libs/worker/engine/TinyWebWorkerEngine.md +137 -0
  537. package/docs/v1/regexp/Email.md +127 -0
  538. package/docs/v1/regexp/Glob.md +155 -0
  539. package/docs/v1/regexp/IPv4.md +103 -0
  540. package/docs/v1/regexp/IPv6.md +122 -0
  541. package/docs/v1/regexp/SegmentExtractor.md +120 -0
  542. package/docs/v1/regexp/UrlDetector.md +117 -0
  543. package/docs/v1/regexp/Username/Base.md +131 -0
  544. package/docs/v1/regexp/Username/Discord.md +267 -0
  545. package/docs/v1/regexp/Username/MatrixProtocol.md +131 -0
  546. package/docs/v1/webTemplates/ag-psd/31.0/ProcessSolidFilters.md +569 -0
  547. package/docs/v1/webTemplates/bootstrap/5.3/html/BootstrapDialogs.md +19 -7
  548. package/docs/v1/webTemplates/media/MediaValidator/v1/Browser.md +123 -0
  549. package/docs/v1/webTemplates/media/MediaValidator/v1/Node.md +136 -0
  550. package/docs/v1/webTemplates/multiformats/14.0/IPFSHasher.md +310 -0
  551. package/docs/v1/webTemplates/vite/7.3/plugins/TinyVitePwaPlugin.md +131 -0
  552. package/docs/v1/webTemplates/vite/7.3/plugins/githubUtils.md +50 -0
  553. package/package.json +303 -13
  554. package/types/EventEmitter.d.ts +48 -0
  555. package/dist/v1/libs/text/TinyI18.d.mts.map +0 -1
@@ -0,0 +1,752 @@
1
+ # ๐Ÿ—„๏ธ TinyFS Core
2
+
3
+ > A tiny, dependency-free, `node:fs/promises`-compatible file system core written in pure ESM JavaScript.
4
+
5
+ TinyFS Core is an **abstract base class**. It gives you a complete, promise-based file system
6
+ API surface โ€” `readFile`, `writeFile`, `readdir`, `stat`, `chmod`, `rename`, and friends โ€” while
7
+ delegating the actual byte storage to a backend you write.
8
+
9
+ The base class is **not a stub**. It ships with a working in-memory side table for permissions,
10
+ ownership and timestamps, so a backend only has to answer one question: *"where do the bytes
11
+ live?"*
12
+
13
+ ---
14
+
15
+ ## ๐Ÿ“‘ Table of Contents
16
+
17
+ 1. [Features](#-features)
18
+ 2. [Requirements](#-requirements)
19
+ 3. [Project Layout](#-project-layout)
20
+ 4. [Quick Start](#-quick-start)
21
+ 5. [Core Concepts](#-core-concepts)
22
+ - [The Metadata Side Table](#1--the-metadata-side-table)
23
+ - [Protected Hooks](#2--protected-hooks)
24
+ - [Capabilities](#3--capabilities)
25
+ - [Identity and Permissions](#4--identity-and-permissions)
26
+ 6. [API Reference](#-api-reference)
27
+ - [Constructor](#constructor)
28
+ - [Instance Getters](#instance-getters)
29
+ - [Static Members](#static-members)
30
+ - [File Operations](#-file-operations)
31
+ - [Directory Operations](#-directory-operations)
32
+ - [Metadata Operations](#-metadata-operations)
33
+ - [Path Operations](#-path-operations)
34
+ - [Handles](#-handles)
35
+ 7. [Building a Backend](#-building-a-backend)
36
+ 8. [Error Codes](#-error-codes)
37
+ 9. [Known Divergences and Gotchas](#-known-divergences-and-gotchas)
38
+ 10. [Cheatsheet](#-cheatsheet)
39
+
40
+ ---
41
+
42
+ ## โœจ Features
43
+
44
+ | Feature | Status |
45
+ | --- | --- |
46
+ | ๐Ÿงฉ Zero runtime dependencies | โœ… |
47
+ | ๐Ÿ“ฆ Pure ESM (`import` / `export`) | โœ… |
48
+ | ๐Ÿ”’ Private class fields with getters | โœ… |
49
+ | ๐Ÿงช Trivially mockable | โœ… |
50
+ | ๐ŸชŸ Windows-style path handling | โŒ POSIX only |
51
+ | ๐Ÿ”— Symbolic links | โŒ Base class only |
52
+ | ๐Ÿงต Concurrent write safety | โŒ Backend's responsibility |
53
+
54
+ ---
55
+
56
+ ## ๐Ÿ“‹ Requirements
57
+
58
+ - **Node.js** `>= 18.0.0` (native ESM, private class fields, `Object.freeze` on statics).
59
+ - A module resolver that understands the `.mjs` extension.
60
+
61
+ ---
62
+
63
+ ## ๐Ÿ“ Project Layout
64
+
65
+ The core module imports from six sibling modules. Your tree should look like this:
66
+
67
+ ```text
68
+ src/
69
+ โ”œโ”€โ”€ index.mjs # TinyFSCore โ€” the abstract class
70
+ โ”œโ”€โ”€ constants.mjs # DEFAULT_FILE_MODE, DEFAULT_DIRECTORY_MODE, DEFAULT_UMASK, ROOT_PATH, constants
71
+ โ”œโ”€โ”€ error.mjs # assertPath, assertInteger, assertMode, assertOptionsObject,
72
+ โ”‚ # assertEncoding, createFileSystemError
73
+ โ”œโ”€โ”€ encoding.mjs # decodeBytes, toUint8Array
74
+ โ”œโ”€โ”€ stats.mjs # Stats, Dirent
75
+ โ”œโ”€โ”€ handle.mjs # FileHandle
76
+ โ””โ”€โ”€ path.mjs # toSegments
77
+ ```
78
+
79
+ ---
80
+
81
+ ## ๐Ÿš€ Quick Start
82
+
83
+ ```javascript
84
+ import MemoryFileSystem from './memory-fs.mjs';
85
+
86
+ const fs = new MemoryFileSystem({ cwd: '/app' });
87
+
88
+ // Write and read text.
89
+ await fs.writeFile('/app/notes.txt', 'hello world', { encoding: 'utf8' });
90
+ const text = await fs.readFile('/app/notes.txt', { encoding: 'utf8' });
91
+
92
+ console.log(text); // "hello world"
93
+
94
+ // Inspect metadata.
95
+ const stats = await fs.stat('/app/notes.txt');
96
+ console.log(stats.size);
97
+ console.log(stats.mode.toString(8));
98
+
99
+ // Clean up.
100
+ await fs.rm('/app/notes.txt');
101
+ ```
102
+
103
+ > ๐Ÿ’ก The example above requires a backend. Jump to
104
+ > [Building a Backend](#-building-a-backend) for a complete, copy-pasteable implementation.
105
+
106
+ ---
107
+
108
+ ## ๐Ÿง  Core Concepts
109
+
110
+ ### 1. ๐Ÿ—‚๏ธ The Metadata Side Table
111
+
112
+ Every `TinyFSCore` instance owns a private `Map`:
113
+
114
+ ```javascript
115
+ #metadata = new Map(); // Map<string, FSMetadata>
116
+ ```
117
+
118
+ This map stores `mode`, `uid`, `gid`, `atimeMs`, `mtimeMs` and `birthtimeMs` for each path.
119
+ **Your backend never touches it directly.** The public methods read and write it for you.
120
+
121
+ The shape of each record is:
122
+
123
+ ```javascript
124
+ /**
125
+ * @typedef {Object} FSMetadata
126
+ * @property {number | null} mode
127
+ * @property {number | null} uid
128
+ * @property {number | null} gid
129
+ * @property {number | null} atimeMs
130
+ * @property {number | null} mtimeMs
131
+ * @property {number | null} birthtimeMs
132
+ */
133
+ ```
134
+
135
+ A `null` field means *"not set"*. When `stat()` encounters a `null`, it substitutes a sensible
136
+ default based on the entry kind.
137
+
138
+ ---
139
+
140
+ ### 2 ๐Ÿ”Œ Protected Hooks
141
+
142
+ Methods prefixed with a single underscore are **hooks**. They are the contract between the core
143
+ and your backend. Every hook receives **raw, already-validated values** โ€” no encoding, no
144
+ defaults, no metadata merging.
145
+
146
+ | Hook | Purpose |
147
+ | --- | --- |
148
+ | `_readFile(path)` | Return the raw bytes of a file. |
149
+ | `_writeFile(path, bytes, options)` | Persist bytes. Honour `options.append`. |
150
+ | `_readdir(path)` | Return `FSDirectoryEntry[]`. |
151
+ | `_mkdir(path, options)` | Create a directory. Honour `options.recursive`. |
152
+ | `_rm(path, options)` | Remove an entry. Honour `recursive` and `force`. |
153
+ | `_stat(path)` | Return an `FSStatDescriptor`, or `undefined` when missing. |
154
+ | `_rename(oldPath, newPath)` | Move an entry. |
155
+ | `_copyFile(source, destination, mode)` | Copy a file. |
156
+ | `_readMetadata(path)` | Read the side table. **Rarely overridden.** |
157
+ | `_writeMetadata(path, metadata)` | Write the side table. **Rarely overridden.** |
158
+
159
+ Every hook throws `ENOSYS` by default, so an unimplemented operation fails loudly instead of
160
+ silently corrupting data.
161
+
162
+ ---
163
+
164
+ ### 3. ๐ŸŽš๏ธ Capabilities
165
+
166
+ `capabilities` is a **static getter** that advertises what a backend supports. It is frozen, so
167
+ consumers can safely cache it.
168
+
169
+ ```javascript
170
+ import TinyFSCore from 'tiny-essentials/libs/fs/TinyFSCore';
171
+
172
+ console.log(TinyFSCore.capabilities);
173
+ // {
174
+ // permissions: false,
175
+ // ownership: false,
176
+ // symlinks: false,
177
+ // timestamps: false,
178
+ // atomicRename: false,
179
+ // seekableHandles: false
180
+ // }
181
+ ```
182
+
183
+ > โš ๏ธ Because it is `static`, read it from the **class**, not the instance:
184
+ > `MyBackend.capabilities`. Inside an instance method, use `this.constructor.capabilities`.
185
+
186
+ ---
187
+
188
+ ### 4. ๐Ÿ” Identity and Permissions
189
+
190
+ The constructor accepts an `FSIdentity`. The `access()` method uses it to decide which permission
191
+ triad applies:
192
+
193
+ | Condition | Triad | Bit shift |
194
+ | --- | --- | --- |
195
+ | `uid === identity.uid` | Owner | `>> 6` |
196
+ | `gid === identity.gid` or in `identity.groups` | Group | `>> 3` |
197
+ | Otherwise | Other | `>> 0` |
198
+
199
+ ```javascript
200
+ const fs = new MemoryFileSystem({
201
+ identity: { uid: 1000, gid: 1000, groups: [27, 100] },
202
+ });
203
+ ```
204
+
205
+ ---
206
+
207
+ ## ๐Ÿ“š API Reference
208
+
209
+ ### Constructor
210
+
211
+ ```javascript
212
+ new TinyFSCore(options?)
213
+ ```
214
+
215
+ | Option | Type | Default | Description |
216
+ | --- | --- | --- | --- |
217
+ | `options.cwd` | `string` | `ROOT_PATH` | Working directory used to resolve relative paths. |
218
+ | `options.umask` | `number` | `DEFAULT_UMASK` | Mask applied to `mode` on creation. |
219
+ | `options.identity` | `FSIdentity` | `{ uid: 0, gid: 0, groups: [] }` | Effective identity used by `access()`. |
220
+
221
+ ```javascript
222
+ const fs = new MemoryFileSystem({
223
+ cwd: '/srv/app',
224
+ umask: 0o022,
225
+ identity: { uid: 1000, gid: 1000, groups: [] },
226
+ });
227
+ ```
228
+
229
+ ---
230
+
231
+ ### Instance Getters
232
+
233
+ ```javascript
234
+ fs.cwd; // string โ€” the configured working directory
235
+ fs.umask; // number โ€” the configured umask
236
+ fs.identity; // FSIdentity โ€” the effective identity
237
+ ```
238
+
239
+ ---
240
+
241
+ ### Static Members
242
+
243
+ ```javascript
244
+ TinyFSCore.capabilities; // Readonly<FSCapabilities>
245
+ ```
246
+
247
+ ---
248
+
249
+ ### ๐Ÿ“„ File Operations
250
+
251
+ #### `readFile(path, options?)`
252
+
253
+ Reads the entire contents of a file.
254
+
255
+ | Parameter | Type | Description |
256
+ | --- | --- | --- |
257
+ | `path` | `string` | Absolute path of the file. |
258
+ | `options.encoding` | `string \| null` | When omitted or `null`, resolves to a `Uint8Array`. |
259
+
260
+ **Returns:** `Promise<string | Uint8Array>`
261
+
262
+ ```javascript
263
+ const buffer = await fs.readFile('/data/blob.bin'); // Uint8Array
264
+ const text = await fs.readFile('/data/notes.txt', { encoding: 'utf8' });
265
+ ```
266
+
267
+ ---
268
+
269
+ #### `writeFile(path, data, options?)`
270
+
271
+ Writes data to a file, replacing it when it already exists.
272
+
273
+ | Parameter | Type | Description |
274
+ | --- | --- | --- |
275
+ | `path` | `string` | Absolute path of the file. |
276
+ | `data` | `string \| Uint8Array \| ArrayBuffer` | Payload to persist. |
277
+ | `options.encoding` | `string \| null` | Used to serialise string input. |
278
+ | `options.append` | `boolean` | When `true`, appends instead of replacing. |
279
+ | `options.mode` | `number` | Permission bits applied **when the file is created**. |
280
+
281
+ **Returns:** `Promise<void>`
282
+
283
+ ```javascript
284
+ await fs.writeFile('/logs/app.log', 'boot\n', { mode: 0o640 });
285
+ ```
286
+
287
+ > โš ๏ธ Metadata is written **only when the file does not exist yet**. Overwriting an existing file
288
+ > preserves its original `mode`, `uid`, `gid` and `birthtimeMs`.
289
+
290
+ ---
291
+
292
+ #### `appendFile(path, data, options?)`
293
+
294
+ Convenience wrapper around `writeFile` with `append: true`. Creates the file when missing.
295
+
296
+ ```javascript
297
+ await fs.appendFile('/logs/app.log', 'request handled\n');
298
+ ```
299
+
300
+ ---
301
+
302
+ #### `copyFile(sourcePath, destinationPath, mode?)`
303
+
304
+ Copies a file and duplicates its metadata record.
305
+
306
+ ```javascript
307
+ await fs.copyFile('/a.txt', '/b.txt');
308
+ ```
309
+
310
+ > โš ๏ธ **Divergence:** the JSDoc advertises `number | TCopyFileOptions`, but the implementation
311
+ > only honours the `number` form. Passing an object silently resolves to `0`.
312
+
313
+ ---
314
+
315
+ #### `truncate(path, length?)`
316
+
317
+ Resizes a file to `length` bytes. Shorter files are zero-padded; longer files are cut.
318
+
319
+ ```javascript
320
+ await fs.truncate('/data.bin', 1024);
321
+ await fs.truncate('/data.bin'); // length defaults to 0
322
+ ```
323
+
324
+ ---
325
+
326
+ ### ๐Ÿ“ Directory Operations
327
+
328
+ #### `readdir(path, options?)`
329
+
330
+ Reads directory entries.
331
+
332
+ | Option | Type | Description |
333
+ | --- | --- | --- |
334
+ | `options.withFileTypes` | `boolean` | When `true`, resolves to `Dirent[]`. |
335
+ | `options.recursive` | `boolean` | When `true`, walks sub-directories depth-first. |
336
+
337
+ **Returns:** `Promise<Array<string | Dirent>>`
338
+
339
+ ```javascript
340
+ const names = await fs.readdir('/src');
341
+ const dirents = await fs.readdir('/src', { withFileTypes: true });
342
+ const tree = await fs.readdir('/src', { recursive: true });
343
+ ```
344
+
345
+ > โš ๏ธ **Divergence:** in recursive mode, nested entries are always reported with the kind
346
+ > `'file'`, even when they are directories.
347
+
348
+ ---
349
+
350
+ #### `mkdir(path, options?)`
351
+
352
+ Creates a directory.
353
+
354
+ | Option | Type | Description |
355
+ | --- | --- | --- |
356
+ | `options.recursive` | `boolean` | When `true`, missing parents are created. |
357
+ | `options.mode` | `number` | Permission bits for the new directory. |
358
+
359
+ **Returns:** `Promise<string | undefined>` โ€” the created path when `recursive` is `true`.
360
+
361
+ ```javascript
362
+ await fs.mkdir('/var/lib/app', { recursive: true, mode: 0o755 });
363
+ ```
364
+
365
+ ---
366
+
367
+ #### `rm(path, options?)`
368
+
369
+ Removes a file, or a directory tree when `recursive` is `true`.
370
+
371
+ | Option | Type | Description |
372
+ | --- | --- | --- |
373
+ | `options.recursive` | `boolean` | Removes directories and their contents. |
374
+ | `options.force` | `boolean` | When `true`, a missing path is not an error. |
375
+
376
+ ```javascript
377
+ await fs.rm('/tmp/cache', { recursive: true, force: true });
378
+ ```
379
+
380
+ ---
381
+
382
+ #### `unlink(path)`
383
+
384
+ Removes a file. Throws `EISDIR` when the path is a directory.
385
+
386
+ ```javascript
387
+ await fs.unlink('/tmp/old.log');
388
+ ```
389
+
390
+ ---
391
+
392
+ #### `rmdir(path, options?)`
393
+
394
+ Removes a directory. Forwards to `rm()`.
395
+
396
+ ```javascript
397
+ await fs.rmdir('/tmp/empty');
398
+ ```
399
+
400
+ ---
401
+
402
+ #### `rename(oldPath, newPath)`
403
+
404
+ Moves an entry and carries its metadata record across.
405
+
406
+ ```javascript
407
+ await fs.rename('/tmp/draft.md', '/docs/final.md');
408
+ ```
409
+
410
+ ---
411
+
412
+ ### ๐Ÿท๏ธ Metadata Operations
413
+
414
+ #### `stat(path, options?)`
415
+
416
+ Retrieves a `Stats` snapshot. Throws `ENOENT` when the path is missing.
417
+
418
+ ```javascript
419
+ const stats = await fs.stat('/etc/hosts');
420
+ console.log(stats.size, stats.mode.toString(8));
421
+ ```
422
+
423
+ ---
424
+
425
+ #### `lstat(path, options?)`
426
+
427
+ Alias of `stat()`. The base class has no symbolic links, so both behave identically.
428
+
429
+ ---
430
+
431
+ #### `chmod(path, mode)`
432
+
433
+ Changes the permission bits.
434
+
435
+ ```javascript
436
+ await fs.chmod('/usr/local/bin/tool', 0o755);
437
+ ```
438
+
439
+ ---
440
+
441
+ #### `chown(path, uid, gid?)`
442
+
443
+ Changes ownership. `gid` defaults to `uid`.
444
+
445
+ ```javascript
446
+ await fs.chown('/var/www', 33, 33);
447
+ ```
448
+
449
+ ---
450
+
451
+ #### `utimes(path, atimeMs, mtimeMs?)`
452
+
453
+ Updates the access and modification times. `mtimeMs` defaults to `atimeMs`.
454
+
455
+ ```javascript
456
+ await fs.utimes('/var/log/app.log', Date.now(), Date.now());
457
+ ```
458
+
459
+ ---
460
+
461
+ #### `access(path, mode?)`
462
+
463
+ Checks whether a path is reachable with the requested permission.
464
+
465
+ | Constant | Meaning |
466
+ | --- | --- |
467
+ | `constants.F_OK` | Existence only (default). |
468
+ | `constants.R_OK` | Read permission. |
469
+ | `constants.W_OK` | Write permission. |
470
+ | `constants.X_OK` | Execute permission. |
471
+
472
+ **Throws:** `Error` with `code: 'EACCES'` when the permission is missing.
473
+
474
+ ```javascript
475
+ try {
476
+ await fs.access('/etc/shadow', constants.R_OK);
477
+ } catch (error) {
478
+ console.error(error.code); // "EACCES"
479
+ }
480
+ ```
481
+
482
+ > โš ๏ธ **Divergence:** `chmod`, `chown` and `utimes` do **not** verify that the path exists.
483
+ > They will happily create an orphan metadata record. Call `stat()` first if that matters.
484
+
485
+ ---
486
+
487
+ ### ๐Ÿ›ฃ๏ธ Path Operations
488
+
489
+ #### `realpath(path)`
490
+
491
+ Resolves the canonical absolute path. Throws `ENOENT` when the path is missing.
492
+
493
+ ```javascript
494
+ await fs.realpath('/var/../var/log/./app.log');
495
+ // "/var/log/app.log"
496
+ ```
497
+
498
+ ---
499
+
500
+ #### `exists(path)`
501
+
502
+ Reports whether a path exists. Never throws for a missing path.
503
+
504
+ ```javascript
505
+ if (await fs.exists('/etc/hosts')) {
506
+ console.log('found');
507
+ }
508
+ ```
509
+
510
+ ---
511
+
512
+ ### ๐Ÿ”“ Handles
513
+
514
+ #### `open(path, flags?)`
515
+
516
+ Opens a file and returns a `FileHandle`.
517
+
518
+ | Flag | Behaviour |
519
+ | --- | --- |
520
+ | `'r'` (default) | Verifies the file exists. |
521
+ | `'w'` | Truncates the file. |
522
+ | `'a'` | Opens for appending. |
523
+
524
+ ```javascript
525
+ const handle = await fs.open('/data/report.csv', 'w');
526
+ ```
527
+
528
+ ---
529
+
530
+ ## ๐Ÿ—๏ธ Building a Backend
531
+
532
+ A complete, working in-memory backend. This is the smallest useful implementation.
533
+
534
+ ```javascript
535
+ import TinyFSCore from 'tiny-essentials/libs/fs/TinyFSCore';
536
+ import { createFileSystemError } from 'tiny-essentials/libs/fs/error.mjs';
537
+
538
+ /**
539
+ * In-memory file system used for tests and local development.
540
+ * @augments TinyFSCore
541
+ */
542
+ export class MemoryFileSystem extends TinyFSCore {
543
+ /** @type {Map<string, Uint8Array>} */
544
+ #files = new Map();
545
+
546
+ /** @type {Set<string>} */
547
+ #directories = new Set(['/']);
548
+
549
+ /**
550
+ * @returns {import('tiny-essentials/libs/fs/TinyFSCore').FSCapabilities} The capabilities of this backend.
551
+ */
552
+ static get capabilities() {
553
+ return Object.freeze({
554
+ permissions: true,
555
+ ownership: true,
556
+ symlinks: false,
557
+ timestamps: true,
558
+ atomicRename: true,
559
+ seekableHandles: false,
560
+ });
561
+ }
562
+
563
+ /**
564
+ * @param {string} targetPath Absolute path of the file.
565
+ * @returns {Promise<Uint8Array>} The raw file contents.
566
+ */
567
+ async _readFile(targetPath) {
568
+ const bytes = this.#files.get(targetPath);
569
+ if (bytes === undefined) {
570
+ throw createFileSystemError('ENOENT', 'open', targetPath);
571
+ }
572
+ return bytes;
573
+ }
574
+
575
+ /**
576
+ * @param {string} targetPath Absolute path of the file.
577
+ * @param {Uint8Array} bytes Payload to persist.
578
+ * @param {{ append: boolean, mode: number | undefined }} options Write options.
579
+ * @returns {Promise<void>} Resolves once the payload is committed.
580
+ */
581
+ async _writeFile(targetPath, bytes, options) {
582
+ const previous = options.append ? this.#files.get(targetPath) ?? new Uint8Array(0) : new Uint8Array(0);
583
+ const merged = new Uint8Array(previous.length + bytes.length);
584
+ merged.set(previous, 0);
585
+ merged.set(bytes, previous.length);
586
+ this.#files.set(targetPath, merged);
587
+ }
588
+
589
+ /**
590
+ * @param {string} targetPath Absolute path of the directory.
591
+ * @returns {Promise<import('tiny-essentials/libs/fs/stats.mjs').FSDirectoryEntry[]>} The directory entries.
592
+ */
593
+ async _readdir(targetPath) {
594
+ const prefix = targetPath.endsWith('/') ? targetPath : `${targetPath}/`;
595
+ const entries = new Map();
596
+
597
+ for (const filePath of this.#files.keys()) {
598
+ if (!filePath.startsWith(prefix)) continue;
599
+ const [name, ...rest] = filePath.slice(prefix.length).split('/');
600
+ entries.set(name, { name, kind: rest.length === 0 ? 'file' : 'directory' });
601
+ }
602
+
603
+ return [...entries.values()];
604
+ }
605
+
606
+ /**
607
+ * @param {string} targetPath Absolute path of the directory.
608
+ * @returns {Promise<void>} Resolves once the directory exists.
609
+ */
610
+ async _mkdir(targetPath) {
611
+ this.#directories.add(targetPath);
612
+ }
613
+
614
+ /**
615
+ * @param {string} targetPath Absolute path of the entry.
616
+ * @returns {Promise<void>} Resolves once the entry is gone.
617
+ */
618
+ async _rm(targetPath) {
619
+ this.#files.delete(targetPath);
620
+ this.#directories.delete(targetPath);
621
+ }
622
+
623
+ /**
624
+ * @param {string} targetPath Absolute path of the entry.
625
+ * @returns {Promise<import('tiny-essentials/libs/fs/stats.mjs').FSStatDescriptor | undefined>} The descriptor.
626
+ */
627
+ async _stat(targetPath) {
628
+ const bytes = this.#files.get(targetPath);
629
+ if (bytes !== undefined) {
630
+ return { name: targetPath.split('/').pop() ?? '', kind: 'file', size: bytes.length, mtimeMs: Date.now() };
631
+ }
632
+ if (this.#directories.has(targetPath)) {
633
+ return { name: targetPath.split('/').pop() ?? '', kind: 'directory', size: 0, mtimeMs: Date.now() };
634
+ }
635
+ return undefined;
636
+ }
637
+
638
+ /**
639
+ * @param {string} oldPath Current absolute path.
640
+ * @param {string} newPath Target absolute path.
641
+ * @returns {Promise<void>} Resolves once the move is complete.
642
+ */
643
+ async _rename(oldPath, newPath) {
644
+ const bytes = this.#files.get(oldPath);
645
+ if (bytes === undefined) {
646
+ throw createFileSystemError('ENOENT', 'rename', oldPath);
647
+ }
648
+ this.#files.set(newPath, bytes);
649
+ this.#files.delete(oldPath);
650
+ }
651
+
652
+ /**
653
+ * @param {string} sourcePath Absolute path of the source file.
654
+ * @param {string} destinationPath Absolute path of the destination file.
655
+ * @returns {Promise<void>} Resolves once the copy is complete.
656
+ */
657
+ async _copyFile(sourcePath, destinationPath) {
658
+ const bytes = await this._readFile(sourcePath);
659
+ this.#files.set(destinationPath, Uint8Array.from(bytes));
660
+ }
661
+ }
662
+ ```
663
+
664
+ ### โœ… Backend Checklist
665
+
666
+ 1. Extend `TinyFSCore`.
667
+ 2. Override `static get capabilities()` and return a frozen object.
668
+ 3. Implement only the hooks your use case needs. Everything else throws `ENOSYS`.
669
+ 4. **Never** handle encoding, validation or metadata inside a hook. That is the core's job.
670
+ 5. Throw `createFileSystemError(code, syscall, path)` instead of a bare `Error`.
671
+
672
+ ---
673
+
674
+ ## ๐Ÿšจ Error Codes
675
+
676
+ All errors are created through `createFileSystemError(code, syscall, path, message?)`.
677
+
678
+ | Code | Thrown by | Meaning |
679
+ | --- | --- | --- |
680
+ | `ENOENT` | `stat`, `access`, `realpath`, `open` | No such file or directory. |
681
+ | `EACCES` | `access` | Permission denied. |
682
+ | `EISDIR` | `unlink` | The path is a directory. |
683
+ | `ENOSYS` | Any unoverridden hook | The backend does not implement this operation. |
684
+
685
+ ```javascript
686
+ try {
687
+ await fs.readFile('/missing.txt');
688
+ } catch (error) {
689
+ console.error(error.code); // "ENOENT"
690
+ console.error(error.syscall); // "open"
691
+ console.error(error.path); // "/missing.txt"
692
+ }
693
+ ```
694
+
695
+ ---
696
+
697
+ ## โš ๏ธ Known Divergences and Gotchas
698
+
699
+ Read this section before you file a bug. These are the behaviours that differ from
700
+ `node:fs/promises` or from the JSDoc.
701
+
702
+ | # | Location | Behaviour |
703
+ | --- | --- | --- |
704
+ | 1 | `copyFile` | Accepts `TCopyFileOptions` in JSDoc but only honours the `number` form. Passing an object silently resolves to `0`. |
705
+ | 2 | `readdir` | In `recursive` mode, every nested entry is reported with the kind `'file'`. |
706
+ | 3 | `chmod` / `chown` / `utimes` | Do **not** verify that the path exists. They create orphan metadata records. |
707
+ | 4 | `writeFile` | Writes metadata only on creation. Overwriting does **not** refresh `mtimeMs`. |
708
+ | 5 | `rm` | Deletes only the exact path from the metadata map. Descendants keep their records. |
709
+ | 6 | `lstat` | Alias of `stat`. There is no symlink support in the base class. |
710
+ | 7 | `capabilities` | It is `static`. Use `this.constructor.capabilities` inside instance methods. |
711
+ | 8 | `__stat` | Public by convention only. It is the internal implementation behind `stat`. |
712
+ | 9 | `unlink` | Calls `__stat` first, so a missing file throws `ENOENT` before `rm` runs. |
713
+
714
+ ---
715
+
716
+ ## ๐Ÿงพ Cheatsheet
717
+
718
+ ```javascript
719
+ // โ”€โ”€โ”€ Setup โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
720
+ const fs = new MemoryFileSystem({ cwd: '/app', umask: 0o022 });
721
+
722
+ // โ”€โ”€โ”€ Files โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
723
+ await fs.writeFile('/a.txt', 'data', { encoding: 'utf8' });
724
+ await fs.appendFile('/a.txt', 'more');
725
+ const buffer = await fs.readFile('/a.txt'); // Uint8Array
726
+ const text = await fs.readFile('/a.txt', { encoding: 'utf8' });
727
+ await fs.copyFile('/a.txt', '/b.txt');
728
+ await fs.truncate('/a.txt', 2);
729
+ await fs.unlink('/a.txt');
730
+
731
+ // โ”€โ”€โ”€ Directories โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
732
+ await fs.mkdir('/nested/dir', { recursive: true, mode: 0o755 });
733
+ const names = await fs.readdir('/nested');
734
+ const dirents = await fs.readdir('/nested', { withFileTypes: true });
735
+ await fs.rmdir('/nested');
736
+ await fs.rm('/nested', { recursive: true, force: true });
737
+
738
+ // โ”€โ”€โ”€ Metadata โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
739
+ const stats = await fs.stat('/a.txt');
740
+ await fs.chmod('/a.txt', 0o600);
741
+ await fs.chown('/a.txt', 1000, 1000);
742
+ await fs.utimes('/a.txt', Date.now(), Date.now());
743
+ await fs.access('/a.txt', 0o4);
744
+
745
+ // โ”€โ”€โ”€ Paths โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
746
+ await fs.rename('/a.txt', '/b.txt');
747
+ const absolute = await fs.realpath('/a/../a.txt');
748
+ const found = await fs.exists('/a.txt');
749
+
750
+ // โ”€โ”€โ”€ Handles โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
751
+ const handle = await fs.open('/a.txt', 'w');
752
+ ```