@slopware/sloppy-darwin-arm64 0.1.0-alpha.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 (434) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +5 -0
  3. package/bin/sloppy +0 -0
  4. package/bin/sloppyc +0 -0
  5. package/docs/KNOWN_LIMITATIONS.md +16 -0
  6. package/docs/LICENSES.md +6 -0
  7. package/docs/NOTICE.md +8 -0
  8. package/examples/README.md +140 -0
  9. package/examples/auth-api/README.md +20 -0
  10. package/examples/auth-api/app.js +61 -0
  11. package/examples/auth-api/appsettings.json +7 -0
  12. package/examples/auth-api/sloppy.json +5 -0
  13. package/examples/cache-basic/README.md +9 -0
  14. package/examples/cache-basic/app.js +32 -0
  15. package/examples/cache-hybrid-postgres/README.md +10 -0
  16. package/examples/cache-hybrid-postgres/app.js +27 -0
  17. package/examples/cache-output-api/README.md +10 -0
  18. package/examples/cache-output-api/app.js +35 -0
  19. package/examples/codec-base64-hex/README.md +14 -0
  20. package/examples/codec-base64-hex/app.js +15 -0
  21. package/examples/codec-checksums/README.md +15 -0
  22. package/examples/codec-checksums/app.js +8 -0
  23. package/examples/codec-compression/README.md +13 -0
  24. package/examples/codec-compression/app.js +9 -0
  25. package/examples/codec-streaming-compression/README.md +19 -0
  26. package/examples/codec-streaming-compression/app.js +16 -0
  27. package/examples/codec-text-binary/README.md +16 -0
  28. package/examples/codec-text-binary/app.js +17 -0
  29. package/examples/compiler-hello/README.md +71 -0
  30. package/examples/compiler-hello/app.js +7 -0
  31. package/examples/compiler-hello/expected/app.js +8 -0
  32. package/examples/compiler-hello/expected/app.js.map +53 -0
  33. package/examples/compiler-hello/expected/app.plan.json +229 -0
  34. package/examples/compiler-hello/expected/routes.slrt +0 -0
  35. package/examples/config-basic/README.md +13 -0
  36. package/examples/config-basic/app.js +13 -0
  37. package/examples/config-basic/appsettings.json +7 -0
  38. package/examples/config-secrets-redaction/README.md +9 -0
  39. package/examples/config-secrets-redaction/app.js +9 -0
  40. package/examples/config-secrets-redaction/appsettings.json +5 -0
  41. package/examples/config-strict-mode/README.md +7 -0
  42. package/examples/config-strict-mode/app.js +10 -0
  43. package/examples/config-strict-mode/appsettings.json +7 -0
  44. package/examples/configured-api/README.md +38 -0
  45. package/examples/configured-api/app.js +12 -0
  46. package/examples/configured-api/appsettings.Development.json +5 -0
  47. package/examples/configured-api/appsettings.json +6 -0
  48. package/examples/configured-api/sloppy.json +5 -0
  49. package/examples/core-config-secrets/README.md +10 -0
  50. package/examples/core-config-secrets/app.js +15 -0
  51. package/examples/core-fs-time-codec/README.md +9 -0
  52. package/examples/core-fs-time-codec/app.js +8 -0
  53. package/examples/core-network-time-codec/README.md +11 -0
  54. package/examples/core-network-time-codec/app.js +20 -0
  55. package/examples/core-policy-audit/README.md +7 -0
  56. package/examples/core-policy-audit/app.js +22 -0
  57. package/examples/core-process-time-codec/README.md +8 -0
  58. package/examples/core-process-time-codec/app.js +28 -0
  59. package/examples/core-worker-time/README.md +8 -0
  60. package/examples/core-worker-time/app.js +17 -0
  61. package/examples/crypto-hash-hmac/README.md +17 -0
  62. package/examples/crypto-hash-hmac/app.js +29 -0
  63. package/examples/crypto-password/README.md +21 -0
  64. package/examples/crypto-password/app.js +12 -0
  65. package/examples/crypto-random-token/README.md +16 -0
  66. package/examples/crypto-random-token/app.js +12 -0
  67. package/examples/crypto-secret-constant-time/README.md +21 -0
  68. package/examples/crypto-secret-constant-time/app.js +15 -0
  69. package/examples/data-foundation/README.md +39 -0
  70. package/examples/data-foundation/app.js +63 -0
  71. package/examples/dependency-graph/README.md +19 -0
  72. package/examples/dependency-graph/fixtures/graph-helper/index.js +3 -0
  73. package/examples/dependency-graph/fixtures/graph-helper/package.json +6 -0
  74. package/examples/dependency-graph/package.json +7 -0
  75. package/examples/dependency-graph/public/message.txt +1 -0
  76. package/examples/dependency-graph/sloppy.json +9 -0
  77. package/examples/dependency-graph/src/main.ts +8 -0
  78. package/examples/dogfood/README.md +23 -0
  79. package/examples/dogfood/dogfood.json +136 -0
  80. package/examples/dynamic-module-include/README.md +20 -0
  81. package/examples/dynamic-module-include/public/readme.txt +1 -0
  82. package/examples/dynamic-module-include/sloppy.json +12 -0
  83. package/examples/dynamic-module-include/src/main.ts +6 -0
  84. package/examples/dynamic-module-include/src/plugins/alpha.js +3 -0
  85. package/examples/dynamic-module-include/src/plugins/beta.js +3 -0
  86. package/examples/ergonomics/README.md +42 -0
  87. package/examples/ergonomics/app.js +38 -0
  88. package/examples/framework-controller/README.md +12 -0
  89. package/examples/framework-controller/app.js +31 -0
  90. package/examples/framework-di-services/README.md +17 -0
  91. package/examples/framework-di-services/app.ts +40 -0
  92. package/examples/framework-explicit-binding/README.md +12 -0
  93. package/examples/framework-explicit-binding/app.ts +34 -0
  94. package/examples/framework-hello/README.md +16 -0
  95. package/examples/framework-hello/app.ts +16 -0
  96. package/examples/framework-postgres-crud/README.md +73 -0
  97. package/examples/framework-postgres-crud/app.ts +64 -0
  98. package/examples/framework-sqlite-crud/README.md +52 -0
  99. package/examples/framework-sqlite-crud/app.ts +90 -0
  100. package/examples/framework-sqlite-crud/appsettings.json +11 -0
  101. package/examples/framework-sqlserver-crud/README.md +73 -0
  102. package/examples/framework-sqlserver-crud/app.ts +64 -0
  103. package/examples/framework-validation-errors/README.md +12 -0
  104. package/examples/framework-validation-errors/app.ts +16 -0
  105. package/examples/fs-basic/README.md +24 -0
  106. package/examples/fs-basic/app.js +12 -0
  107. package/examples/fs-roots-policy/README.md +14 -0
  108. package/examples/fs-roots-policy/app.js +4 -0
  109. package/examples/fs-streams/README.md +18 -0
  110. package/examples/fs-streams/app.js +11 -0
  111. package/examples/fs-watch/README.md +19 -0
  112. package/examples/fs-watch/app.js +11 -0
  113. package/examples/hello/README.md +63 -0
  114. package/examples/hello/app.js +19 -0
  115. package/examples/hello-minimal/README.md +51 -0
  116. package/examples/hello-minimal/sloppy.json +5 -0
  117. package/examples/hello-minimal/src/main.ts +9 -0
  118. package/examples/http-client-basic/README.md +11 -0
  119. package/examples/http-client-basic/app.js +46 -0
  120. package/examples/http-client-generated/README.md +22 -0
  121. package/examples/http-client-generated/openapi.json +45 -0
  122. package/examples/http-client-resilience/README.md +4 -0
  123. package/examples/http-client-resilience/app.js +38 -0
  124. package/examples/http-client-runtime-loopback/README.md +24 -0
  125. package/examples/http-client-testhost/README.md +4 -0
  126. package/examples/http-client-testhost/app.js +27 -0
  127. package/examples/http-client-testhost-package-mock/README.md +26 -0
  128. package/examples/http-client-typed/README.md +5 -0
  129. package/examples/http-client-typed/app.js +33 -0
  130. package/examples/modules-api/README.md +30 -0
  131. package/examples/modules-api/app.js +9 -0
  132. package/examples/modules-api/modules/routes.js +16 -0
  133. package/examples/modules-api/sloppy.json +5 -0
  134. package/examples/modules-basic/README.md +32 -0
  135. package/examples/modules-basic/app.js +41 -0
  136. package/examples/net-deadline-cancel/README.md +13 -0
  137. package/examples/net-deadline-cancel/app.js +34 -0
  138. package/examples/net-local-ipc/README.md +12 -0
  139. package/examples/net-local-ipc/app.js +46 -0
  140. package/examples/net-policy-strict/README.md +12 -0
  141. package/examples/net-policy-strict/app.js +34 -0
  142. package/examples/net-tcp-client/README.md +10 -0
  143. package/examples/net-tcp-client/app.js +23 -0
  144. package/examples/net-tcp-echo/README.md +11 -0
  145. package/examples/net-tcp-echo/app.js +45 -0
  146. package/examples/net-tcp-server/README.md +10 -0
  147. package/examples/net-tcp-server/app.js +28 -0
  148. package/examples/node-compat-path-events/README.md +15 -0
  149. package/examples/node-compat-path-events/sloppy.json +6 -0
  150. package/examples/node-compat-path-events/src/main.ts +15 -0
  151. package/examples/ops-compiler/README.md +9 -0
  152. package/examples/ops-compiler/app.js +26 -0
  153. package/examples/ops-health-metrics-management/README.md +14 -0
  154. package/examples/ops-health-metrics-management/app.js +24 -0
  155. package/examples/orm-basic/README.md +17 -0
  156. package/examples/orm-basic/app.js +82 -0
  157. package/examples/orm-cursor-export/README.md +16 -0
  158. package/examples/orm-cursor-export/app.js +28 -0
  159. package/examples/orm-migrations/README.md +14 -0
  160. package/examples/orm-migrations/migrations/.gitkeep +1 -0
  161. package/examples/orm-migrations/sloppy.json +9 -0
  162. package/examples/orm-migrations/src/app.ts +34 -0
  163. package/examples/orm-relations-includes/README.md +10 -0
  164. package/examples/orm-relations-includes/app.js +47 -0
  165. package/examples/orm-testservices/README.md +37 -0
  166. package/examples/orm-testservices/test.mjs +32 -0
  167. package/examples/os-runtime-api/README.md +11 -0
  168. package/examples/os-runtime-api/app.js +44 -0
  169. package/examples/package-zod-like/README.md +28 -0
  170. package/examples/package-zod-like/fixtures/zod-like/index.js +48 -0
  171. package/examples/package-zod-like/fixtures/zod-like/package.json +12 -0
  172. package/examples/package-zod-like/package.json +7 -0
  173. package/examples/package-zod-like/sloppy.json +6 -0
  174. package/examples/package-zod-like/src/main.ts +16 -0
  175. package/examples/postgres-basic/README.md +31 -0
  176. package/examples/postgres-basic/app.js +50 -0
  177. package/examples/prealpha-control-plane/README.md +50 -0
  178. package/examples/prealpha-control-plane/appsettings.Development.json +11 -0
  179. package/examples/prealpha-control-plane/appsettings.json +15 -0
  180. package/examples/prealpha-control-plane/sloppy.json +5 -0
  181. package/examples/prealpha-control-plane/src/db/schema.js +7 -0
  182. package/examples/prealpha-control-plane/src/db/seed.js +6 -0
  183. package/examples/prealpha-control-plane/src/main.js +21 -0
  184. package/examples/prealpha-control-plane/src/routes/apps.js +34 -0
  185. package/examples/prealpha-control-plane/src/routes/builds.js +25 -0
  186. package/examples/prealpha-control-plane/src/routes/deployments.js +19 -0
  187. package/examples/prealpha-control-plane/src/routes/diagnostics.js +11 -0
  188. package/examples/prealpha-control-plane/src/routes/health.js +27 -0
  189. package/examples/prealpha-control-plane/src/routes/projects.js +38 -0
  190. package/examples/prealpha-control-plane/src/services/diagnosticsSink.js +11 -0
  191. package/examples/prealpha-control-plane/src/services/repositories.js +9 -0
  192. package/examples/prealpha-control-plane/src/validation/schemas.js +6 -0
  193. package/examples/program-fs-process/README.md +31 -0
  194. package/examples/program-fs-process/sloppy.json +9 -0
  195. package/examples/program-fs-process/src/main.ts +27 -0
  196. package/examples/program-hello/README.md +32 -0
  197. package/examples/program-hello/main.ts +8 -0
  198. package/examples/program-hello/message.ts +1 -0
  199. package/examples/program-hello/sloppy.json +5 -0
  200. package/examples/rate-limit-auth/README.md +3 -0
  201. package/examples/rate-limit-auth/app.js +14 -0
  202. package/examples/rate-limit-basic/README.md +3 -0
  203. package/examples/rate-limit-basic/app.js +13 -0
  204. package/examples/rate-limit-redis/README.md +5 -0
  205. package/examples/rate-limit-redis/app.js +20 -0
  206. package/examples/rate-limit-testhost/README.md +4 -0
  207. package/examples/rate-limit-testhost/app.js +13 -0
  208. package/examples/rate-limit-websocket/README.md +3 -0
  209. package/examples/rate-limit-websocket/app.js +16 -0
  210. package/examples/realtime-auth/README.md +8 -0
  211. package/examples/realtime-auth/app.js +25 -0
  212. package/examples/realtime-auth/test.mjs +43 -0
  213. package/examples/realtime-chat/README.md +8 -0
  214. package/examples/realtime-chat/app.js +32 -0
  215. package/examples/realtime-chat/test.mjs +52 -0
  216. package/examples/realtime-dashboard/README.md +20 -0
  217. package/examples/realtime-dashboard/app.js +37 -0
  218. package/examples/realtime-presence/README.md +8 -0
  219. package/examples/realtime-presence/app.js +32 -0
  220. package/examples/realtime-presence/test.mjs +50 -0
  221. package/examples/realtime-testhost/README.md +8 -0
  222. package/examples/realtime-testhost/test.mjs +31 -0
  223. package/examples/redis-basic/README.md +17 -0
  224. package/examples/redis-basic/app.js +39 -0
  225. package/examples/redis-cache/README.md +14 -0
  226. package/examples/redis-cache/app.js +36 -0
  227. package/examples/redis-locks/README.md +13 -0
  228. package/examples/redis-locks/app.js +49 -0
  229. package/examples/request-context/README.md +32 -0
  230. package/examples/request-context/app.js +15 -0
  231. package/examples/sqlite-basic/README.md +52 -0
  232. package/examples/sqlite-basic/app.js +56 -0
  233. package/examples/sqlserver-basic/README.md +36 -0
  234. package/examples/sqlserver-basic/app.js +59 -0
  235. package/examples/static-files-basic/README.md +11 -0
  236. package/examples/static-files-basic/app.js +12 -0
  237. package/examples/static-files-basic/public/app.js +1 -0
  238. package/examples/static-files-basic/public/site.css +3 -0
  239. package/examples/static-files-package/README.md +12 -0
  240. package/examples/static-files-package/app.js +10 -0
  241. package/examples/static-files-package/public/index.html +2 -0
  242. package/examples/static-files-precompressed/README.md +12 -0
  243. package/examples/static-files-precompressed/app.js +11 -0
  244. package/examples/static-files-precompressed/public/app.js +1 -0
  245. package/examples/static-files-precompressed/public/app.js.br +0 -0
  246. package/examples/static-files-precompressed/public/app.js.gz +0 -0
  247. package/examples/static-files-spa/README.md +12 -0
  248. package/examples/static-files-spa/app.js +16 -0
  249. package/examples/static-files-spa/dist/assets/app.js +1 -0
  250. package/examples/static-files-spa/dist/index.html +4 -0
  251. package/examples/static-files-testhost/README.md +8 -0
  252. package/examples/static-files-testhost/app.js +13 -0
  253. package/examples/static-files-testhost/public/app.js +1 -0
  254. package/examples/static-files-testhost/public/app.js.gz +0 -0
  255. package/examples/static-files-testhost/test.mjs +38 -0
  256. package/examples/testhost-basic/README.md +26 -0
  257. package/examples/testhost-db/README.md +31 -0
  258. package/examples/testservices-postgres/README.md +68 -0
  259. package/examples/testservices-redis/README.md +71 -0
  260. package/examples/testservices-sqlserver/README.md +75 -0
  261. package/examples/time-basic/README.md +18 -0
  262. package/examples/time-basic/app.js +12 -0
  263. package/examples/time-deadline-cancellation/README.md +11 -0
  264. package/examples/time-deadline-cancellation/app.js +27 -0
  265. package/examples/time-fake-clock/README.md +14 -0
  266. package/examples/time-fake-clock/app.js +25 -0
  267. package/examples/time-interval-schedule/README.md +13 -0
  268. package/examples/time-interval-schedule/app.js +60 -0
  269. package/examples/users-api-sqlite/README.md +74 -0
  270. package/examples/users-api-sqlite/app.js +11 -0
  271. package/examples/users-api-sqlite/appsettings.Development.json +11 -0
  272. package/examples/users-api-sqlite/appsettings.json +11 -0
  273. package/examples/users-api-sqlite/modules/users.js +40 -0
  274. package/examples/users-api-sqlite/sloppy.json +5 -0
  275. package/examples/validation-errors/README.md +36 -0
  276. package/examples/validation-errors/app.js +14 -0
  277. package/examples/validation-errors/invalid-user.http +6 -0
  278. package/examples/validation-errors/sloppy.json +5 -0
  279. package/examples/web-dynamic-routes/README.md +17 -0
  280. package/examples/web-dynamic-routes/app.ts +27 -0
  281. package/examples/webhooks-basic/README.md +11 -0
  282. package/examples/webhooks-basic/app.js +48 -0
  283. package/examples/websocket-auth/README.md +8 -0
  284. package/examples/websocket-auth/app.js +16 -0
  285. package/examples/websocket-echo/README.md +9 -0
  286. package/examples/websocket-echo/app.js +36 -0
  287. package/examples/websocket-json-schema/README.md +5 -0
  288. package/examples/websocket-json-schema/app.js +25 -0
  289. package/examples/websocket-testhost/README.md +11 -0
  290. package/examples/websocket-testhost/test.mjs +49 -0
  291. package/examples/workers-background-service/README.md +7 -0
  292. package/examples/workers-background-service/app.js +16 -0
  293. package/examples/workers-js-isolate/README.md +8 -0
  294. package/examples/workers-js-isolate/app.js +19 -0
  295. package/examples/workers-js-isolate/workers/parser.ts +11 -0
  296. package/examples/workers-shutdown/README.md +6 -0
  297. package/examples/workers-shutdown/app.js +26 -0
  298. package/examples/workers-workerpool/README.md +6 -0
  299. package/examples/workers-workerpool/app.js +23 -0
  300. package/examples/workers-workqueue/README.md +8 -0
  301. package/examples/workers-workqueue/app.js +24 -0
  302. package/manifest.json +59 -0
  303. package/package.json +31 -0
  304. package/stdlib/sloppy/README.md +177 -0
  305. package/stdlib/sloppy/app.js +2142 -0
  306. package/stdlib/sloppy/auth.js +1813 -0
  307. package/stdlib/sloppy/bootstrap.manifest.json +83 -0
  308. package/stdlib/sloppy/cache.js +1542 -0
  309. package/stdlib/sloppy/codec.js +1153 -0
  310. package/stdlib/sloppy/config.js +61 -0
  311. package/stdlib/sloppy/crypto.js +312 -0
  312. package/stdlib/sloppy/data.js +2945 -0
  313. package/stdlib/sloppy/ffi.js +185 -0
  314. package/stdlib/sloppy/fs.js +795 -0
  315. package/stdlib/sloppy/health.js +603 -0
  316. package/stdlib/sloppy/http.js +1595 -0
  317. package/stdlib/sloppy/index.js +59 -0
  318. package/stdlib/sloppy/internal/bytes.js +31 -0
  319. package/stdlib/sloppy/internal/capabilities.js +155 -0
  320. package/stdlib/sloppy/internal/config.js +640 -0
  321. package/stdlib/sloppy/internal/disposable.js +31 -0
  322. package/stdlib/sloppy/internal/headers.js +63 -0
  323. package/stdlib/sloppy/internal/intrinsics.js +2 -0
  324. package/stdlib/sloppy/internal/json.js +20 -0
  325. package/stdlib/sloppy/internal/logging.js +278 -0
  326. package/stdlib/sloppy/internal/modules.js +405 -0
  327. package/stdlib/sloppy/internal/redaction.js +87 -0
  328. package/stdlib/sloppy/internal/routes.js +2279 -0
  329. package/stdlib/sloppy/internal/runtime-classic.js +19837 -0
  330. package/stdlib/sloppy/internal/services.js +690 -0
  331. package/stdlib/sloppy/internal/shared.js +32 -0
  332. package/stdlib/sloppy/internal/testhost-diagnostics.js +88 -0
  333. package/stdlib/sloppy/internal/testhost-http-server.js +238 -0
  334. package/stdlib/sloppy/internal/testhost-http.js +118 -0
  335. package/stdlib/sloppy/internal/testhost-loopback.js +50 -0
  336. package/stdlib/sloppy/internal/testservices-docker.js +154 -0
  337. package/stdlib/sloppy/internal/validation.js +117 -0
  338. package/stdlib/sloppy/metrics.js +427 -0
  339. package/stdlib/sloppy/net.js +5208 -0
  340. package/stdlib/sloppy/node/assert/strict.js +39 -0
  341. package/stdlib/sloppy/node/assert.js +228 -0
  342. package/stdlib/sloppy/node/buffer.js +247 -0
  343. package/stdlib/sloppy/node/console.js +33 -0
  344. package/stdlib/sloppy/node/constants.js +9 -0
  345. package/stdlib/sloppy/node/crypto.js +89 -0
  346. package/stdlib/sloppy/node/diagnostics_channel.js +41 -0
  347. package/stdlib/sloppy/node/events.js +113 -0
  348. package/stdlib/sloppy/node/fs/promises.js +27 -0
  349. package/stdlib/sloppy/node/fs.js +280 -0
  350. package/stdlib/sloppy/node/http.js +11 -0
  351. package/stdlib/sloppy/node/https.js +11 -0
  352. package/stdlib/sloppy/node/module.js +40 -0
  353. package/stdlib/sloppy/node/os.js +22 -0
  354. package/stdlib/sloppy/node/path.js +78 -0
  355. package/stdlib/sloppy/node/perf_hooks.js +12 -0
  356. package/stdlib/sloppy/node/process.js +129 -0
  357. package/stdlib/sloppy/node/querystring.js +21 -0
  358. package/stdlib/sloppy/node/stream/promises.js +3 -0
  359. package/stdlib/sloppy/node/stream.js +132 -0
  360. package/stdlib/sloppy/node/string_decoder.js +23 -0
  361. package/stdlib/sloppy/node/timers.js +26 -0
  362. package/stdlib/sloppy/node/tty.js +18 -0
  363. package/stdlib/sloppy/node/url.js +17 -0
  364. package/stdlib/sloppy/node/util.js +95 -0
  365. package/stdlib/sloppy/node/zlib.js +72 -0
  366. package/stdlib/sloppy/orm.js +2188 -0
  367. package/stdlib/sloppy/os.js +580 -0
  368. package/stdlib/sloppy/problem-details.js +29 -0
  369. package/stdlib/sloppy/providers/sqlite.js +26 -0
  370. package/stdlib/sloppy/rate-limit.js +856 -0
  371. package/stdlib/sloppy/realtime.js +1508 -0
  372. package/stdlib/sloppy/redis.js +1272 -0
  373. package/stdlib/sloppy/request-id.js +184 -0
  374. package/stdlib/sloppy/request-logging.js +101 -0
  375. package/stdlib/sloppy/results.js +933 -0
  376. package/stdlib/sloppy/schema.js +546 -0
  377. package/stdlib/sloppy/testing.js +4081 -0
  378. package/stdlib/sloppy/testservices.js +1041 -0
  379. package/stdlib/sloppy/time.js +894 -0
  380. package/stdlib/sloppy/webhooks.js +1330 -0
  381. package/stdlib/sloppy/workers.js +986 -0
  382. package/templates/api/README.md +82 -0
  383. package/templates/api/appsettings.Development.json +14 -0
  384. package/templates/api/appsettings.json +13 -0
  385. package/templates/api/data/.gitkeep +1 -0
  386. package/templates/api/gitignore +4 -0
  387. package/templates/api/migrations/0001_create_users.sql +1 -0
  388. package/templates/api/package.json +16 -0
  389. package/templates/api/public/hello.txt +1 -0
  390. package/templates/api/sloppy.json +14 -0
  391. package/templates/api/src/config.ts +1 -0
  392. package/templates/api/src/db/migrate.ts +14 -0
  393. package/templates/api/src/db/schema.ts +4 -0
  394. package/templates/api/src/db/usersRepository.ts +23 -0
  395. package/templates/api/src/main.ts +18 -0
  396. package/templates/api/src/models/user.ts +7 -0
  397. package/templates/api/src/routes/health.ts +20 -0
  398. package/templates/api/src/routes/users.ts +40 -0
  399. package/templates/api/src/services/usersService.ts +21 -0
  400. package/templates/api/tsconfig.json +15 -0
  401. package/templates/cli/README.md +16 -0
  402. package/templates/cli/gitignore +2 -0
  403. package/templates/cli/package.json +13 -0
  404. package/templates/cli/sloppy.json +6 -0
  405. package/templates/cli/src/commands/echo.ts +9 -0
  406. package/templates/cli/src/commands/inspect.ts +20 -0
  407. package/templates/cli/src/main.ts +50 -0
  408. package/templates/cli/tsconfig.json +15 -0
  409. package/templates/minimal-api/README.md +14 -0
  410. package/templates/minimal-api/gitignore +3 -0
  411. package/templates/minimal-api/package.json +14 -0
  412. package/templates/minimal-api/sloppy.json +5 -0
  413. package/templates/minimal-api/src/main.ts +9 -0
  414. package/templates/minimal-api/tsconfig.json +15 -0
  415. package/templates/node-compat/README.md +40 -0
  416. package/templates/node-compat/gitignore +2 -0
  417. package/templates/node-compat/package.json +11 -0
  418. package/templates/node-compat/sloppy.json +6 -0
  419. package/templates/node-compat/src/main.ts +40 -0
  420. package/templates/package-api/README.md +44 -0
  421. package/templates/package-api/fixtures/validator-lite/index.js +7 -0
  422. package/templates/package-api/fixtures/validator-lite/package.json +6 -0
  423. package/templates/package-api/gitignore +3 -0
  424. package/templates/package-api/package.json +17 -0
  425. package/templates/package-api/sloppy.json +5 -0
  426. package/templates/package-api/src/main.ts +10 -0
  427. package/templates/package-api/src/routes/health.ts +5 -0
  428. package/templates/package-api/src/routes/users.ts +12 -0
  429. package/templates/package-api/tsconfig.json +15 -0
  430. package/templates/program/README.md +12 -0
  431. package/templates/program/gitignore +1 -0
  432. package/templates/program/package.json +10 -0
  433. package/templates/program/sloppy.json +6 -0
  434. package/templates/program/src/main.ts +9 -0
@@ -0,0 +1,795 @@
1
+ import { isPlainObject } from "./internal/validation.js";
2
+ import {
3
+ CancelledError,
4
+ InvalidDeadlineError,
5
+ Time,
6
+ TimeoutError,
7
+ } from "./time.js";
8
+ import { Text } from "./codec.js";
9
+
10
+ const MAX_TIMEOUT_MS = 0xffffffff;
11
+
12
+ function nativeFsBridge(operation) {
13
+ const bridge = globalThis.__sloppy?.fs ?? null;
14
+
15
+ if (bridge === null) {
16
+ throw new Error(`SLOPPY_E_UNAVAILABLE_RUNTIME_FEATURE: runtime feature stdlib.fs is inactive or unavailable
17
+
18
+ Feature:
19
+ stdlib.fs
20
+
21
+ Operation:
22
+ ${operation}
23
+
24
+ Reason:
25
+ The active Sloppy Plan did not enable the __sloppy.fs V8 intrinsic namespace.`);
26
+ }
27
+
28
+ return bridge;
29
+ }
30
+
31
+ function validatePath(path, operationLabel) {
32
+ if (typeof path !== "string" || path.length === 0 || path.includes("\0")) {
33
+ throw new TypeError(`${operationLabel} path must be a non-empty string without NUL.`);
34
+ }
35
+ return path;
36
+ }
37
+
38
+ function validateBytes(value, operation) {
39
+ if (!(value instanceof Uint8Array)) {
40
+ throw new TypeError(`Sloppy File.${operation} bytes must be a Uint8Array.`);
41
+ }
42
+ return value;
43
+ }
44
+
45
+ function validateCopyMoveOptions(options) {
46
+ if (options === undefined) {
47
+ return Object.freeze({ overwrite: false });
48
+ }
49
+ if (!isPlainObject(options)) {
50
+ throw new TypeError("Sloppy File copy/move options must be a plain object.");
51
+ }
52
+ const overwrite = options.overwrite ?? false;
53
+ if (typeof overwrite !== "boolean") {
54
+ throw new TypeError("Sloppy File overwrite option must be boolean.");
55
+ }
56
+ return Object.freeze({ overwrite });
57
+ }
58
+
59
+ function validateRecursiveOptions(options) {
60
+ if (options === undefined) {
61
+ return Object.freeze({ recursive: false });
62
+ }
63
+ if (!isPlainObject(options)) {
64
+ throw new TypeError("Sloppy Directory options must be a plain object.");
65
+ }
66
+ const recursive = options.recursive ?? false;
67
+ if (typeof recursive !== "boolean") {
68
+ throw new TypeError("Sloppy Directory recursive option must be boolean.");
69
+ }
70
+ return Object.freeze({ recursive });
71
+ }
72
+
73
+ function validateOpenOptions(options) {
74
+ if (options === undefined) {
75
+ return Object.freeze({ access: "read", create: false });
76
+ }
77
+ if (!isPlainObject(options)) {
78
+ throw new TypeError("Sloppy File.open options must be a plain object.");
79
+ }
80
+ const access = options.access ?? "read";
81
+ const create = options.create ?? access !== "read";
82
+ if (!["read", "write", "readwrite", "append"].includes(access)) {
83
+ throw new TypeError("Sloppy File.open access must be read, write, readwrite, or append.");
84
+ }
85
+ if (typeof create !== "boolean") {
86
+ throw new TypeError("Sloppy File.open create option must be boolean.");
87
+ }
88
+ return Object.freeze({ access, create });
89
+ }
90
+
91
+ function validateWatchOptions(options, directory) {
92
+ if (options === undefined) {
93
+ return Object.freeze({ recursive: false, queueCapacity: 16, snapshotCapacity: directory ? 128 : 1 });
94
+ }
95
+ if (!isPlainObject(options)) {
96
+ throw new TypeError("Sloppy filesystem watch options must be a plain object.");
97
+ }
98
+ const recursive = options.recursive ?? false;
99
+ const queueCapacity = options.queueCapacity ?? 16;
100
+ const snapshotCapacity = options.snapshotCapacity ?? (directory ? 128 : 1);
101
+ if (typeof recursive !== "boolean") {
102
+ throw new TypeError("Sloppy filesystem watch recursive option must be boolean.");
103
+ }
104
+ if (!Number.isInteger(queueCapacity) || queueCapacity < 1 || queueCapacity > 256) {
105
+ throw new TypeError("Sloppy filesystem watch queueCapacity must be 1..256.");
106
+ }
107
+ if (!Number.isInteger(snapshotCapacity) || snapshotCapacity < 1 || snapshotCapacity > 1024) {
108
+ throw new TypeError("Sloppy filesystem watch snapshotCapacity must be 1..1024.");
109
+ }
110
+ return Object.freeze({ recursive, queueCapacity, snapshotCapacity });
111
+ }
112
+
113
+ function validateTempPrefix(options, operation) {
114
+ const prefix = options?.prefix ?? "sloppy-";
115
+ if (typeof prefix !== "string" || prefix.length === 0 || prefix.includes("\0")) {
116
+ throw new TypeError(`${operation} prefix must be a non-empty string without NUL.`);
117
+ }
118
+ return prefix;
119
+ }
120
+
121
+ function stringifyJson(value, options) {
122
+ if (options === undefined) {
123
+ return JSON.stringify(value);
124
+ }
125
+ if (!isPlainObject(options)) {
126
+ throw new TypeError("Sloppy File.writeJson options must be a plain object.");
127
+ }
128
+ const indent = options.indent ?? undefined;
129
+ if (
130
+ indent !== undefined
131
+ && (!Number.isInteger(indent) || indent < 0 || indent > 10)
132
+ ) {
133
+ throw new TypeError("Sloppy File.writeJson indent must be an integer from 0 to 10.");
134
+ }
135
+ return JSON.stringify(value, null, indent);
136
+ }
137
+
138
+ function shouldAtomic(options) {
139
+ if (options === undefined) {
140
+ return false;
141
+ }
142
+ if (!isPlainObject(options)) {
143
+ throw new TypeError("Sloppy File write options must be a plain object.");
144
+ }
145
+ const atomic = options.atomic ?? false;
146
+ if (typeof atomic !== "boolean") {
147
+ throw new TypeError("Sloppy File atomic option must be boolean.");
148
+ }
149
+ return atomic;
150
+ }
151
+
152
+ function isCancellationSignal(value) {
153
+ return (
154
+ value !== null &&
155
+ typeof value === "object" &&
156
+ typeof value.aborted === "boolean" &&
157
+ ("reason" in value || typeof value.addEventListener === "function")
158
+ );
159
+ }
160
+
161
+ function subscribeCancellation(signal, listener) {
162
+ if (!isCancellationSignal(signal)) {
163
+ return () => {};
164
+ }
165
+ if (signal.aborted) {
166
+ listener(signal.reason);
167
+ return () => {};
168
+ }
169
+ if (typeof signal._subscribe === "function") {
170
+ return signal._subscribe(listener);
171
+ }
172
+ if (typeof signal.addEventListener === "function") {
173
+ const wrapped = () => listener(signal.reason);
174
+ signal.addEventListener("abort", wrapped);
175
+ return () => signal.removeEventListener?.("abort", wrapped);
176
+ }
177
+ return () => {};
178
+ }
179
+
180
+ function cancelledError(reason = undefined) {
181
+ return reason instanceof CancelledError
182
+ ? reason
183
+ : new CancelledError("Sloppy filesystem operation was cancelled.", { reason });
184
+ }
185
+
186
+ function validateTimeoutMs(value, operation) {
187
+ if (value === undefined) {
188
+ return undefined;
189
+ }
190
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0 || value > MAX_TIMEOUT_MS) {
191
+ throw new InvalidDeadlineError(
192
+ `${operation} timeoutMs must be a finite non-negative number no greater than ${MAX_TIMEOUT_MS}.`,
193
+ );
194
+ }
195
+ return Math.ceil(value);
196
+ }
197
+
198
+ function createTimeoutBudgetOptions(options, operation) {
199
+ const timeoutMs = validateTimeoutMs(options?.timeoutMs, operation);
200
+ if (timeoutMs === undefined) {
201
+ return () => options;
202
+ }
203
+ const expiresAtMs = Date.now() + timeoutMs;
204
+ return () => ({
205
+ ...options,
206
+ timeoutMs: Math.max(0, expiresAtMs - Date.now()),
207
+ });
208
+ }
209
+
210
+ function isTimeTerminalError(error) {
211
+ return (
212
+ error instanceof CancelledError ||
213
+ error instanceof TimeoutError ||
214
+ error?.name === "AbortError" ||
215
+ error?.name === "CancelledError" ||
216
+ error?.name === "TimeoutError"
217
+ );
218
+ }
219
+
220
+ function deadlineRemainingMs(deadline) {
221
+ if (deadline === undefined || deadline === null) {
222
+ return Infinity;
223
+ }
224
+ if (typeof deadline.remainingMs !== "function") {
225
+ throw new InvalidDeadlineError(
226
+ "Filesystem operation deadline must come from Deadline.after, Deadline.at, or Deadline.never.",
227
+ );
228
+ }
229
+ return deadline.remainingMs();
230
+ }
231
+
232
+ function raceFilesystemCancellation(promise, signal) {
233
+ if (!isCancellationSignal(signal)) {
234
+ return promise;
235
+ }
236
+ if (signal.aborted) {
237
+ return Promise.reject(cancelledError(signal.reason));
238
+ }
239
+ return new Promise((resolve, reject) => {
240
+ const cleanup = subscribeCancellation(signal, (reason) => {
241
+ cleanup();
242
+ reject(cancelledError(reason));
243
+ });
244
+ promise.then(
245
+ (value) => {
246
+ cleanup();
247
+ resolve(value);
248
+ },
249
+ (error) => {
250
+ cleanup();
251
+ reject(error);
252
+ },
253
+ );
254
+ });
255
+ }
256
+
257
+ function validateTimeOptions(options, operation) {
258
+ if (options !== undefined && !isPlainObject(options)) {
259
+ throw new TypeError(`${operation} options must be a plain object.`);
260
+ }
261
+ }
262
+
263
+ function applyTimeOptions(createPromise, options, operation) {
264
+ validateTimeOptions(options, operation);
265
+ const signal = options?.signal;
266
+ const timeoutMs = validateTimeoutMs(options?.timeoutMs, operation);
267
+ const deadline = options?.deadline;
268
+ if (isCancellationSignal(signal) && signal.aborted) {
269
+ return Promise.reject(cancelledError(signal.reason));
270
+ }
271
+ const deadlineMs = deadlineRemainingMs(deadline);
272
+ if (timeoutMs === 0 || deadlineMs <= 0) {
273
+ return Time.timeout(Promise.resolve(), { afterMs: timeoutMs, deadline });
274
+ }
275
+ const promise = createPromise();
276
+ if (timeoutMs !== undefined || deadlineMs !== Infinity) {
277
+ return Time.timeout(Promise.resolve(promise), {
278
+ afterMs: timeoutMs,
279
+ deadline,
280
+ signal,
281
+ });
282
+ }
283
+ return raceFilesystemCancellation(Promise.resolve(promise), signal);
284
+ }
285
+
286
+ const File = Object.freeze({
287
+ readText(path, options) {
288
+ return applyTimeOptions(
289
+ () => nativeFsBridge("readText").readText(validatePath(path, "Sloppy File.readText")),
290
+ options,
291
+ "File.readText",
292
+ );
293
+ },
294
+
295
+ readBytes(path, options) {
296
+ return applyTimeOptions(
297
+ () => nativeFsBridge("readBytes").readBytes(validatePath(path, "Sloppy File.readBytes")),
298
+ options,
299
+ "File.readBytes",
300
+ );
301
+ },
302
+
303
+ async readJson(path, options) {
304
+ return JSON.parse(await File.readText(path, options));
305
+ },
306
+
307
+ writeText(path, text, options) {
308
+ if (typeof text !== "string") {
309
+ throw new TypeError("Sloppy File.writeText text must be a string.");
310
+ }
311
+ if (shouldAtomic(options)) {
312
+ return applyTimeOptions(
313
+ () => nativeFsBridge("atomicWriteText").atomicWriteText(validatePath(path, "Sloppy File.writeText"), text),
314
+ options,
315
+ "File.writeText",
316
+ );
317
+ }
318
+ return applyTimeOptions(
319
+ () => nativeFsBridge("writeText").writeText(validatePath(path, "Sloppy File.writeText"), text),
320
+ options,
321
+ "File.writeText",
322
+ );
323
+ },
324
+
325
+ writeBytes(path, bytes, options) {
326
+ const checked = validateBytes(bytes, "writeBytes");
327
+ if (shouldAtomic(options)) {
328
+ return applyTimeOptions(
329
+ () => nativeFsBridge("atomicWriteBytes").atomicWriteBytes(validatePath(path, "Sloppy File.writeBytes"), checked),
330
+ options,
331
+ "File.writeBytes",
332
+ );
333
+ }
334
+ return applyTimeOptions(
335
+ () => nativeFsBridge("writeBytes").writeBytes(
336
+ validatePath(path, "Sloppy File.writeBytes"),
337
+ checked,
338
+ ),
339
+ options,
340
+ "File.writeBytes",
341
+ );
342
+ },
343
+
344
+ writeJson(path, value, options) {
345
+ return File.writeText(path, stringifyJson(value, options), options);
346
+ },
347
+
348
+ appendText(path, text, options) {
349
+ if (typeof text !== "string") {
350
+ throw new TypeError("Sloppy File.appendText text must be a string.");
351
+ }
352
+ return applyTimeOptions(
353
+ () => nativeFsBridge("appendText").appendText(validatePath(path, "Sloppy File.appendText"), text),
354
+ options,
355
+ "File.appendText",
356
+ );
357
+ },
358
+
359
+ appendBytes(path, bytes, options) {
360
+ return applyTimeOptions(
361
+ () => nativeFsBridge("appendBytes").appendBytes(
362
+ validatePath(path, "Sloppy File.appendBytes"),
363
+ validateBytes(bytes, "appendBytes"),
364
+ ),
365
+ options,
366
+ "File.appendBytes",
367
+ );
368
+ },
369
+
370
+ exists(path, options) {
371
+ return applyTimeOptions(
372
+ () => nativeFsBridge("exists").exists(validatePath(path, "Sloppy File.exists")),
373
+ options,
374
+ "File.exists",
375
+ );
376
+ },
377
+
378
+ stat(path, options) {
379
+ return applyTimeOptions(
380
+ () => nativeFsBridge("stat").stat(validatePath(path, "Sloppy File.stat")),
381
+ options,
382
+ "File.stat",
383
+ );
384
+ },
385
+
386
+ copy(fromPath, toPath, options) {
387
+ return applyTimeOptions(
388
+ () => nativeFsBridge("copy").copy(
389
+ validatePath(fromPath, "Sloppy File.copy"),
390
+ validatePath(toPath, "Sloppy File.copy"),
391
+ validateCopyMoveOptions(options),
392
+ ),
393
+ options,
394
+ "File.copy",
395
+ );
396
+ },
397
+
398
+ move(fromPath, toPath, options) {
399
+ return applyTimeOptions(
400
+ () => nativeFsBridge("move").move(
401
+ validatePath(fromPath, "Sloppy File.move"),
402
+ validatePath(toPath, "Sloppy File.move"),
403
+ validateCopyMoveOptions(options),
404
+ ),
405
+ options,
406
+ "File.move",
407
+ );
408
+ },
409
+
410
+ delete(path, options) {
411
+ return applyTimeOptions(
412
+ () => nativeFsBridge("delete").delete(validatePath(path, "Sloppy File.delete")),
413
+ options,
414
+ "File.delete",
415
+ );
416
+ },
417
+
418
+ async open(path, options) {
419
+ const checked = validateOpenOptions(options);
420
+ const id = await applyTimeOptions(
421
+ () => nativeFsBridge("openHandle").openHandle(
422
+ validatePath(path, "Sloppy File.open"),
423
+ checked.access,
424
+ checked.create,
425
+ ),
426
+ options,
427
+ "File.open",
428
+ );
429
+ return new FileHandle(id);
430
+ },
431
+
432
+ async watch(path, options) {
433
+ const checked = validateWatchOptions(options, false);
434
+ const id = await applyTimeOptions(
435
+ () => nativeFsBridge("watch").watch(validatePath(path, "Sloppy File.watch"), false, checked),
436
+ options,
437
+ "File.watch",
438
+ );
439
+ return new FileWatcher(id);
440
+ },
441
+
442
+ createSymlink(targetPath, linkPath, options) {
443
+ const directory = options?.directory ?? false;
444
+ if (typeof directory !== "boolean") {
445
+ throw new TypeError("Sloppy File.createSymlink directory option must be boolean.");
446
+ }
447
+ return applyTimeOptions(
448
+ () => nativeFsBridge("symlink").symlink(
449
+ validatePath(targetPath, "Sloppy File.createSymlink"),
450
+ validatePath(linkPath, "Sloppy File.createSymlink"),
451
+ directory,
452
+ ),
453
+ options,
454
+ "File.createSymlink",
455
+ );
456
+ },
457
+
458
+ readLink(path, options) {
459
+ return applyTimeOptions(
460
+ () => nativeFsBridge("readLink").readLink(validatePath(path, "Sloppy File.readLink")),
461
+ options,
462
+ "File.readLink",
463
+ );
464
+ },
465
+
466
+ createTemp(directory, options) {
467
+ const prefix = validateTempPrefix(options, "Sloppy File.createTemp");
468
+ return applyTimeOptions(
469
+ () => nativeFsBridge("tempFile").tempFile(validatePath(directory, "Sloppy File.createTemp"), prefix),
470
+ options,
471
+ "File.createTemp",
472
+ );
473
+ },
474
+ });
475
+
476
+ async function isSymlink(path, options) {
477
+ try {
478
+ await File.readLink(path, options);
479
+ return true;
480
+ }
481
+ catch (error) {
482
+ if (isTimeTerminalError(error)) {
483
+ throw error;
484
+ }
485
+ return false;
486
+ }
487
+ }
488
+
489
+ const Directory = Object.freeze({
490
+ create(path, options) {
491
+ const checked = validateRecursiveOptions(options);
492
+ return applyTimeOptions(
493
+ () => nativeFsBridge("directoryCreate").directoryCreate(
494
+ validatePath(path, "Sloppy Directory.create"),
495
+ checked.recursive,
496
+ ),
497
+ options,
498
+ "Directory.create",
499
+ );
500
+ },
501
+
502
+ list(path, options) {
503
+ return applyTimeOptions(
504
+ () => nativeFsBridge("directoryList").directoryList(validatePath(path, "Sloppy Directory.list")),
505
+ options,
506
+ "Directory.list",
507
+ );
508
+ },
509
+
510
+ async *walk(path, options) {
511
+ const followSymlinks = options?.followSymlinks ?? false;
512
+ if (typeof followSymlinks !== "boolean") {
513
+ throw new TypeError("Sloppy Directory.walk followSymlinks option must be boolean.");
514
+ }
515
+ const optionsForStep = createTimeoutBudgetOptions(options, "Directory.walk");
516
+ for (const entry of await Directory.list(path, optionsForStep())) {
517
+ yield entry;
518
+ if (entry.kind === "directory") {
519
+ const child = `${path.replace(/[\\/]$/, "")}/${entry.name}`;
520
+ if (!followSymlinks && await isSymlink(child, optionsForStep())) {
521
+ continue;
522
+ }
523
+ for await (const nested of Directory.walk(child, {
524
+ ...optionsForStep(),
525
+ followSymlinks,
526
+ })) {
527
+ yield { ...nested, name: `${entry.name}/${nested.name}` };
528
+ }
529
+ }
530
+ }
531
+ },
532
+
533
+ delete(path, options) {
534
+ const checked = validateRecursiveOptions(options);
535
+ return applyTimeOptions(
536
+ () => nativeFsBridge("directoryDelete").directoryDelete(
537
+ validatePath(path, "Sloppy Directory.delete"),
538
+ checked.recursive,
539
+ ),
540
+ options,
541
+ "Directory.delete",
542
+ );
543
+ },
544
+
545
+ async exists(path, options) {
546
+ const stat = await File.stat(path, options);
547
+ return stat.exists && stat.kind === "directory";
548
+ },
549
+
550
+ createTemp(directory, options) {
551
+ const prefix = validateTempPrefix(options, "Sloppy Directory.createTemp");
552
+ return applyTimeOptions(
553
+ () => nativeFsBridge("tempDirectory").tempDirectory(
554
+ validatePath(directory, "Sloppy Directory.createTemp"),
555
+ prefix,
556
+ ),
557
+ options,
558
+ "Directory.createTemp",
559
+ );
560
+ },
561
+
562
+ async watch(path, options) {
563
+ const checked = validateWatchOptions(options, true);
564
+ const id = await applyTimeOptions(
565
+ () => nativeFsBridge("watch").watch(validatePath(path, "Sloppy Directory.watch"), true, checked),
566
+ options,
567
+ "Directory.watch",
568
+ );
569
+ return new FileWatcher(id);
570
+ },
571
+ });
572
+
573
+ const Path = Object.freeze({
574
+ classify(path) {
575
+ validatePath(path, "Sloppy Path.classify");
576
+ if (/^\.[\\/]/.test(path)) {
577
+ return "project-relative";
578
+ }
579
+ if (/^(?:[A-Za-z]:[\\/]|[\\/])/.test(path)) {
580
+ return "absolute";
581
+ }
582
+ if (/^[A-Za-z][A-Za-z0-9_.-]*:[\\/]/.test(path)) {
583
+ return "named-root";
584
+ }
585
+ return "invalid";
586
+ },
587
+ });
588
+
589
+ class FileHandle {
590
+ constructor(id) {
591
+ this._id = Object.freeze({ slot: id.slot, generation: id.generation });
592
+ }
593
+
594
+ readBytes(maxBytes = 64 * 1024, options) {
595
+ if (!Number.isInteger(maxBytes) || maxBytes <= 0 || maxBytes > 1024 * 1024) {
596
+ throw new TypeError("Sloppy FileHandle.readBytes maxBytes must be 1..1048576.");
597
+ }
598
+ return applyTimeOptions(
599
+ () => nativeFsBridge("handleRead").handleRead(this._id, maxBytes),
600
+ options,
601
+ "FileHandle.readBytes",
602
+ );
603
+ }
604
+
605
+ async readText(maxBytes, options) {
606
+ const bytes = await this.readBytes(maxBytes, options);
607
+ return Text.utf8.decode(bytes);
608
+ }
609
+
610
+ writeBytes(bytes, options) {
611
+ return applyTimeOptions(
612
+ () => nativeFsBridge("handleWriteBytes").handleWriteBytes(
613
+ this._id,
614
+ validateBytes(bytes, "writeBytes"),
615
+ ),
616
+ options,
617
+ "FileHandle.writeBytes",
618
+ );
619
+ }
620
+
621
+ writeText(text, options) {
622
+ if (typeof text !== "string") {
623
+ throw new TypeError("Sloppy FileHandle.writeText text must be a string.");
624
+ }
625
+ return applyTimeOptions(
626
+ () => nativeFsBridge("handleWriteText").handleWriteText(this._id, text),
627
+ options,
628
+ "FileHandle.writeText",
629
+ );
630
+ }
631
+
632
+ seek(offset, origin = "start", options) {
633
+ if (!Number.isInteger(offset) || !["start", "current", "end"].includes(origin)) {
634
+ throw new TypeError("Sloppy FileHandle.seek requires an integer offset and valid origin.");
635
+ }
636
+ return applyTimeOptions(
637
+ () => nativeFsBridge("handleSeek").handleSeek(this._id, offset, origin),
638
+ options,
639
+ "FileHandle.seek",
640
+ );
641
+ }
642
+
643
+ truncate(size, options) {
644
+ if (!Number.isInteger(size) || size < 0) {
645
+ throw new TypeError("Sloppy FileHandle.truncate size must be a non-negative integer.");
646
+ }
647
+ return applyTimeOptions(
648
+ () => nativeFsBridge("handleTruncate").handleTruncate(this._id, size),
649
+ options,
650
+ "FileHandle.truncate",
651
+ );
652
+ }
653
+
654
+ flush(options) {
655
+ return applyTimeOptions(
656
+ () => nativeFsBridge("handleFlush").handleFlush(this._id),
657
+ options,
658
+ "FileHandle.flush",
659
+ );
660
+ }
661
+
662
+ sync(options) {
663
+ return applyTimeOptions(
664
+ () => nativeFsBridge("handleSync").handleSync(this._id),
665
+ options,
666
+ "FileHandle.sync",
667
+ );
668
+ }
669
+
670
+ close() {
671
+ return nativeFsBridge("handleClose").handleClose(this._id);
672
+ }
673
+
674
+ async *readChunks(options) {
675
+ const chunkSize = options?.chunkSize ?? 64 * 1024;
676
+ const optionsForRead = createTimeoutBudgetOptions(options, "FileHandle.readChunks");
677
+ for (;;) {
678
+ const chunk = await this.readBytes(chunkSize, optionsForRead());
679
+ if (chunk.byteLength === 0) {
680
+ return;
681
+ }
682
+ yield chunk;
683
+ }
684
+ }
685
+
686
+ async *readLines(options) {
687
+ const decoder = Text.utf8.decoder();
688
+ const newline = options?.newline ?? "\n";
689
+ const maxLineLength = options?.maxLineLength ?? 1024 * 1024;
690
+ let buffered = "";
691
+ const limitError = () => {
692
+ const error = new Error(
693
+ "SLOPPY_E_LIMIT_EXCEEDED: filesystem line exceeds maxLineLength.",
694
+ );
695
+ error.code = "SLOPPY_E_LIMIT_EXCEEDED";
696
+ return error;
697
+ };
698
+ const shouldNormalizeCarriageReturn = newline === "\n" || newline === "\r\n";
699
+ const normalizeLine = (line) => shouldNormalizeCarriageReturn ? line.replace(/\r$/, "") : line;
700
+ const pendingDelimiterCarryLength = () => {
701
+ const maxCarry = Math.min(buffered.length, newline.length - 1);
702
+ for (let length = maxCarry; length > 0; length -= 1) {
703
+ if (buffered.endsWith(newline.slice(0, length))) {
704
+ return length;
705
+ }
706
+ }
707
+ return 0;
708
+ };
709
+ const checkPendingLineLength = () => {
710
+ const carryLength = pendingDelimiterCarryLength();
711
+ const pendingLine = carryLength > 0
712
+ ? buffered.slice(0, buffered.length - carryLength)
713
+ : buffered;
714
+ if (normalizeLine(pendingLine).length > maxLineLength) {
715
+ throw limitError();
716
+ }
717
+ };
718
+ if (typeof newline !== "string" || newline.length === 0) {
719
+ throw new TypeError(
720
+ "Sloppy FileHandle.readLines newline must be a non-empty string.",
721
+ );
722
+ }
723
+ for await (const chunk of this.readChunks(options)) {
724
+ buffered += decoder.decode(chunk, { stream: true });
725
+ let index = buffered.indexOf(newline);
726
+ while (index !== -1) {
727
+ const line = normalizeLine(buffered.slice(0, index));
728
+ if (line.length > maxLineLength) {
729
+ throw limitError();
730
+ }
731
+ yield line;
732
+ buffered = buffered.slice(index + newline.length);
733
+ index = buffered.indexOf(newline);
734
+ }
735
+ checkPendingLineLength();
736
+ }
737
+ buffered += decoder.finish();
738
+ const trailingLine = normalizeLine(buffered);
739
+ if (trailingLine.length > maxLineLength) {
740
+ throw limitError();
741
+ }
742
+ if (buffered.length !== 0) {
743
+ yield trailingLine;
744
+ }
745
+ }
746
+ }
747
+
748
+ class FileWatcher {
749
+ constructor(id) {
750
+ this._id = Object.freeze({ slot: id.slot, generation: id.generation });
751
+ this._closed = false;
752
+ }
753
+
754
+ async nextEvent(options) {
755
+ if (this._closed) {
756
+ return null;
757
+ }
758
+ if (options !== undefined && !isPlainObject(options)) {
759
+ throw new TypeError("Sloppy FileWatcher.nextEvent options must be a plain object.");
760
+ }
761
+ return applyTimeOptions(
762
+ () => nativeFsBridge("watchNext").watchNext(this._id),
763
+ options,
764
+ "FileWatcher.nextEvent",
765
+ );
766
+ }
767
+
768
+ async close() {
769
+ if (this._closed) {
770
+ return;
771
+ }
772
+ this._closed = true;
773
+ await nativeFsBridge("watchClose").watchClose(this._id);
774
+ }
775
+
776
+ [Symbol.asyncIterator]() {
777
+ return {
778
+ next: async () => {
779
+ while (!this._closed) {
780
+ const event = await this.nextEvent();
781
+ if (event !== null) {
782
+ return { done: false, value: event };
783
+ }
784
+ }
785
+ return { done: true, value: undefined };
786
+ },
787
+ return: async () => {
788
+ await this.close();
789
+ return { done: true, value: undefined };
790
+ },
791
+ };
792
+ }
793
+ }
794
+
795
+ export { Directory, File, FileHandle, FileWatcher, Path };