├── .github └── workflows │ └── main.yml ├── .gitignore ├── .prettierrc ├── README.md ├── package-lock.json ├── package.json ├── src ├── 1-basic │ ├── effect.ts │ └── fp-ts.ts ├── 2-services │ ├── effect.ts │ └── fp-ts.ts ├── 3-errors │ ├── effect.ts │ └── fp-ts.ts ├── 4-http │ ├── effect.ts │ └── fp-ts.ts ├── 5-parallelism │ ├── effect.ts │ └── fp-ts.ts ├── 6-retries │ ├── effect.ts │ └── fp-ts.ts ├── 7-schema │ ├── effect.ts │ └── fp-ts.ts ├── domain │ ├── effect.ts │ └── fp-ts.ts └── utils │ ├── effect.ts │ ├── fp-ts.ts │ └── promise.ts ├── tsconfig.json └── vitest.config.ts /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - main 8 | paths-ignore: 9 | - "**.md" 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | timeout-minutes: 10 15 | steps: 16 | - name: Checkout code 17 | uses: actions/checkout@v3 18 | 19 | - name: Install node 18.x 20 | uses: actions/setup-node@v3 21 | with: 22 | node-version: "18" 23 | cache: "npm" 24 | 25 | - name: Install packages 26 | run: npm ci 27 | 28 | - name: Typecheck 29 | run: npm run typecheck 30 | 31 | - name: Test 32 | run: npm run test 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /coverage 3 | 4 | # misc 5 | .DS_Store 6 | *.pem 7 | 8 | # debug 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | .pnpm-debug.log* 13 | 14 | # env files 15 | .env* 16 | 17 | # typescript 18 | *.tsbuildinfo 19 | 20 | # ide/editors 21 | .idea/ 22 | .vscode/ 23 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "trailingComma": "all", 4 | "singleQuote": false, 5 | "printWidth": 100, 6 | "tabWidth": 4, 7 | "overrides": [ 8 | { 9 | "files": ["*.yaml", "*.yml"], 10 | "options": { 11 | "tabWidth": 2 12 | } 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # From fp-ts to EffectTS 2 | 3 | An exploration of [EffectTS](https://github.com/Effect-TS/) ecosystem from [fp-ts](https://github.com/gcanti/fp-ts) user 4 | prospective. 5 | 6 | > [!NOTE] 7 | > This repository is up-to-date with [Effect 3.0](https://effect.website/blog/effect-3.0) stable release 8 | 9 | ## Usage 10 | 11 | Node v18 or higher 12 | 13 | ```shell 14 | npm install 15 | npm typecheck 16 | ``` 17 | 18 | Run fp-ts v2 module: 19 | 20 | ```shell 21 | npx tsx src/1-basic/fp-ts.ts 22 | ``` 23 | 24 | Run EffectTS module: 25 | 26 | ```shell 27 | npx tsx src/1-basic/effect.ts 28 | ``` 29 | 30 | ## Modules 31 | 32 | 1. [Basic](./src/1-basic) - How Effect works 33 | 2. [Services](./src/2-services) - Dependency injection 34 | 3. [Errors](./src/3-errors) - Errors, Defects and Interruptions 35 | 4. [Http](./src/4-http) - From TaskEither to Effect 36 | 5. [Parallelism](./src/5-parallelism) - Parallelism of TaskEither/Effect 37 | 6. [Retries](./src/6-retries) - Retries of TaskEither/Effect 38 | 7. [Schema](./src/7-schema) - From io-ts to Schema 39 | 40 | ## EffectTS Resources 41 | 42 | - https://www.effect.website/docs/introduction (official docs, best place to start!) 43 | - [Production-Grade TypeScript by Johannes Schickling (Effect Days 2024)](https://youtu.be/PxIBWjiv3og?si=BzEcvjtv6idG6D3L) 44 | - https://cosimomatteini.com/blog/build-applications-with-effect 45 | - https://github.com/antoine-coulon/effect-introduction 46 | - https://github.com/pigoz/effect-crashcourse 47 | - [Effect for Beginners by Ethan Niser](https://youtu.be/fTN8BX5qj6s?si=fTQV4gU8Aq9bnvmY) 48 | - [Introduction to Effect, Michael Arnaldi, WorkerConf 2022 Dornbirn](https://www.youtube.com/watch?v=zrNr3JVUc8I) 49 | - [EffectTS Discord](https://discord.gg/RVZKYxWfAJ) 50 | 51 | Effect source code: 52 | 53 | - https://github.com/Effect-TS/effect 54 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "from-fp-ts-to-effect-ts", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "from-fp-ts-to-effect-ts", 9 | "version": "1.0.0", 10 | "dependencies": { 11 | "@effect/schema": "0.66.4", 12 | "effect": "3.0.3", 13 | "fp-ts": "2.16.1", 14 | "fp-ts-contrib": "0.1.29", 15 | "io-ts": "2.2.20", 16 | "node-fetch": "3.3.2", 17 | "retry-ts": "0.1.4" 18 | }, 19 | "devDependencies": { 20 | "@types/node": "16.18.12", 21 | "prettier": "3.1.0", 22 | "tsx": "4.1.2", 23 | "typescript": "5.4.5", 24 | "vitest": "0.34.6" 25 | } 26 | }, 27 | "node_modules/@effect/schema": { 28 | "version": "0.66.4", 29 | "resolved": "https://registry.npmjs.org/@effect/schema/-/schema-0.66.4.tgz", 30 | "integrity": "sha512-UQJxoqdGLgVBCkdArChNcTuofsfhXXZhRhptYQ9ZSEqyDZ0jnDGdGpNzMse4VGEkpdw+7UjXQ/nXjVv1wuFpPw==", 31 | "peerDependencies": { 32 | "effect": "^3.0.3", 33 | "fast-check": "^3.13.2" 34 | } 35 | }, 36 | "node_modules/@esbuild/android-arm": { 37 | "version": "0.18.20", 38 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", 39 | "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", 40 | "cpu": [ 41 | "arm" 42 | ], 43 | "dev": true, 44 | "optional": true, 45 | "os": [ 46 | "android" 47 | ], 48 | "engines": { 49 | "node": ">=12" 50 | } 51 | }, 52 | "node_modules/@esbuild/android-arm64": { 53 | "version": "0.18.20", 54 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", 55 | "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", 56 | "cpu": [ 57 | "arm64" 58 | ], 59 | "dev": true, 60 | "optional": true, 61 | "os": [ 62 | "android" 63 | ], 64 | "engines": { 65 | "node": ">=12" 66 | } 67 | }, 68 | "node_modules/@esbuild/android-x64": { 69 | "version": "0.18.20", 70 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", 71 | "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", 72 | "cpu": [ 73 | "x64" 74 | ], 75 | "dev": true, 76 | "optional": true, 77 | "os": [ 78 | "android" 79 | ], 80 | "engines": { 81 | "node": ">=12" 82 | } 83 | }, 84 | "node_modules/@esbuild/darwin-arm64": { 85 | "version": "0.18.20", 86 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", 87 | "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", 88 | "cpu": [ 89 | "arm64" 90 | ], 91 | "dev": true, 92 | "optional": true, 93 | "os": [ 94 | "darwin" 95 | ], 96 | "engines": { 97 | "node": ">=12" 98 | } 99 | }, 100 | "node_modules/@esbuild/darwin-x64": { 101 | "version": "0.18.20", 102 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", 103 | "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", 104 | "cpu": [ 105 | "x64" 106 | ], 107 | "dev": true, 108 | "optional": true, 109 | "os": [ 110 | "darwin" 111 | ], 112 | "engines": { 113 | "node": ">=12" 114 | } 115 | }, 116 | "node_modules/@esbuild/freebsd-arm64": { 117 | "version": "0.18.20", 118 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", 119 | "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", 120 | "cpu": [ 121 | "arm64" 122 | ], 123 | "dev": true, 124 | "optional": true, 125 | "os": [ 126 | "freebsd" 127 | ], 128 | "engines": { 129 | "node": ">=12" 130 | } 131 | }, 132 | "node_modules/@esbuild/freebsd-x64": { 133 | "version": "0.18.20", 134 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", 135 | "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", 136 | "cpu": [ 137 | "x64" 138 | ], 139 | "dev": true, 140 | "optional": true, 141 | "os": [ 142 | "freebsd" 143 | ], 144 | "engines": { 145 | "node": ">=12" 146 | } 147 | }, 148 | "node_modules/@esbuild/linux-arm": { 149 | "version": "0.18.20", 150 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", 151 | "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", 152 | "cpu": [ 153 | "arm" 154 | ], 155 | "dev": true, 156 | "optional": true, 157 | "os": [ 158 | "linux" 159 | ], 160 | "engines": { 161 | "node": ">=12" 162 | } 163 | }, 164 | "node_modules/@esbuild/linux-arm64": { 165 | "version": "0.18.20", 166 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", 167 | "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", 168 | "cpu": [ 169 | "arm64" 170 | ], 171 | "dev": true, 172 | "optional": true, 173 | "os": [ 174 | "linux" 175 | ], 176 | "engines": { 177 | "node": ">=12" 178 | } 179 | }, 180 | "node_modules/@esbuild/linux-ia32": { 181 | "version": "0.18.20", 182 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", 183 | "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", 184 | "cpu": [ 185 | "ia32" 186 | ], 187 | "dev": true, 188 | "optional": true, 189 | "os": [ 190 | "linux" 191 | ], 192 | "engines": { 193 | "node": ">=12" 194 | } 195 | }, 196 | "node_modules/@esbuild/linux-loong64": { 197 | "version": "0.18.20", 198 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", 199 | "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", 200 | "cpu": [ 201 | "loong64" 202 | ], 203 | "dev": true, 204 | "optional": true, 205 | "os": [ 206 | "linux" 207 | ], 208 | "engines": { 209 | "node": ">=12" 210 | } 211 | }, 212 | "node_modules/@esbuild/linux-mips64el": { 213 | "version": "0.18.20", 214 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", 215 | "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", 216 | "cpu": [ 217 | "mips64el" 218 | ], 219 | "dev": true, 220 | "optional": true, 221 | "os": [ 222 | "linux" 223 | ], 224 | "engines": { 225 | "node": ">=12" 226 | } 227 | }, 228 | "node_modules/@esbuild/linux-ppc64": { 229 | "version": "0.18.20", 230 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", 231 | "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", 232 | "cpu": [ 233 | "ppc64" 234 | ], 235 | "dev": true, 236 | "optional": true, 237 | "os": [ 238 | "linux" 239 | ], 240 | "engines": { 241 | "node": ">=12" 242 | } 243 | }, 244 | "node_modules/@esbuild/linux-riscv64": { 245 | "version": "0.18.20", 246 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", 247 | "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", 248 | "cpu": [ 249 | "riscv64" 250 | ], 251 | "dev": true, 252 | "optional": true, 253 | "os": [ 254 | "linux" 255 | ], 256 | "engines": { 257 | "node": ">=12" 258 | } 259 | }, 260 | "node_modules/@esbuild/linux-s390x": { 261 | "version": "0.18.20", 262 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", 263 | "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", 264 | "cpu": [ 265 | "s390x" 266 | ], 267 | "dev": true, 268 | "optional": true, 269 | "os": [ 270 | "linux" 271 | ], 272 | "engines": { 273 | "node": ">=12" 274 | } 275 | }, 276 | "node_modules/@esbuild/linux-x64": { 277 | "version": "0.18.20", 278 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", 279 | "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", 280 | "cpu": [ 281 | "x64" 282 | ], 283 | "dev": true, 284 | "optional": true, 285 | "os": [ 286 | "linux" 287 | ], 288 | "engines": { 289 | "node": ">=12" 290 | } 291 | }, 292 | "node_modules/@esbuild/netbsd-x64": { 293 | "version": "0.18.20", 294 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", 295 | "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", 296 | "cpu": [ 297 | "x64" 298 | ], 299 | "dev": true, 300 | "optional": true, 301 | "os": [ 302 | "netbsd" 303 | ], 304 | "engines": { 305 | "node": ">=12" 306 | } 307 | }, 308 | "node_modules/@esbuild/openbsd-x64": { 309 | "version": "0.18.20", 310 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", 311 | "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", 312 | "cpu": [ 313 | "x64" 314 | ], 315 | "dev": true, 316 | "optional": true, 317 | "os": [ 318 | "openbsd" 319 | ], 320 | "engines": { 321 | "node": ">=12" 322 | } 323 | }, 324 | "node_modules/@esbuild/sunos-x64": { 325 | "version": "0.18.20", 326 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", 327 | "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", 328 | "cpu": [ 329 | "x64" 330 | ], 331 | "dev": true, 332 | "optional": true, 333 | "os": [ 334 | "sunos" 335 | ], 336 | "engines": { 337 | "node": ">=12" 338 | } 339 | }, 340 | "node_modules/@esbuild/win32-arm64": { 341 | "version": "0.18.20", 342 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", 343 | "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", 344 | "cpu": [ 345 | "arm64" 346 | ], 347 | "dev": true, 348 | "optional": true, 349 | "os": [ 350 | "win32" 351 | ], 352 | "engines": { 353 | "node": ">=12" 354 | } 355 | }, 356 | "node_modules/@esbuild/win32-ia32": { 357 | "version": "0.18.20", 358 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", 359 | "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", 360 | "cpu": [ 361 | "ia32" 362 | ], 363 | "dev": true, 364 | "optional": true, 365 | "os": [ 366 | "win32" 367 | ], 368 | "engines": { 369 | "node": ">=12" 370 | } 371 | }, 372 | "node_modules/@esbuild/win32-x64": { 373 | "version": "0.18.20", 374 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", 375 | "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", 376 | "cpu": [ 377 | "x64" 378 | ], 379 | "dev": true, 380 | "optional": true, 381 | "os": [ 382 | "win32" 383 | ], 384 | "engines": { 385 | "node": ">=12" 386 | } 387 | }, 388 | "node_modules/@jest/schemas": { 389 | "version": "29.6.3", 390 | "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", 391 | "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", 392 | "dev": true, 393 | "dependencies": { 394 | "@sinclair/typebox": "^0.27.8" 395 | }, 396 | "engines": { 397 | "node": "^14.15.0 || ^16.10.0 || >=18.0.0" 398 | } 399 | }, 400 | "node_modules/@jridgewell/sourcemap-codec": { 401 | "version": "1.4.15", 402 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", 403 | "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", 404 | "dev": true 405 | }, 406 | "node_modules/@sinclair/typebox": { 407 | "version": "0.27.8", 408 | "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", 409 | "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", 410 | "dev": true 411 | }, 412 | "node_modules/@types/chai": { 413 | "version": "4.3.10", 414 | "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.10.tgz", 415 | "integrity": "sha512-of+ICnbqjmFCiixUnqRulbylyXQrPqIGf/B3Jax1wIF3DvSheysQxAWvqHhZiW3IQrycvokcLcFQlveGp+vyNg==", 416 | "dev": true 417 | }, 418 | "node_modules/@types/chai-subset": { 419 | "version": "1.3.3", 420 | "dev": true, 421 | "license": "MIT", 422 | "dependencies": { 423 | "@types/chai": "*" 424 | } 425 | }, 426 | "node_modules/@types/node": { 427 | "version": "16.18.12", 428 | "dev": true, 429 | "license": "MIT" 430 | }, 431 | "node_modules/@vitest/expect": { 432 | "version": "0.34.6", 433 | "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.6.tgz", 434 | "integrity": "sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==", 435 | "dev": true, 436 | "dependencies": { 437 | "@vitest/spy": "0.34.6", 438 | "@vitest/utils": "0.34.6", 439 | "chai": "^4.3.10" 440 | }, 441 | "funding": { 442 | "url": "https://opencollective.com/vitest" 443 | } 444 | }, 445 | "node_modules/@vitest/runner": { 446 | "version": "0.34.6", 447 | "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.6.tgz", 448 | "integrity": "sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==", 449 | "dev": true, 450 | "dependencies": { 451 | "@vitest/utils": "0.34.6", 452 | "p-limit": "^4.0.0", 453 | "pathe": "^1.1.1" 454 | }, 455 | "funding": { 456 | "url": "https://opencollective.com/vitest" 457 | } 458 | }, 459 | "node_modules/@vitest/snapshot": { 460 | "version": "0.34.6", 461 | "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.6.tgz", 462 | "integrity": "sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==", 463 | "dev": true, 464 | "dependencies": { 465 | "magic-string": "^0.30.1", 466 | "pathe": "^1.1.1", 467 | "pretty-format": "^29.5.0" 468 | }, 469 | "funding": { 470 | "url": "https://opencollective.com/vitest" 471 | } 472 | }, 473 | "node_modules/@vitest/spy": { 474 | "version": "0.34.6", 475 | "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.6.tgz", 476 | "integrity": "sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==", 477 | "dev": true, 478 | "dependencies": { 479 | "tinyspy": "^2.1.1" 480 | }, 481 | "funding": { 482 | "url": "https://opencollective.com/vitest" 483 | } 484 | }, 485 | "node_modules/@vitest/utils": { 486 | "version": "0.34.6", 487 | "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.6.tgz", 488 | "integrity": "sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==", 489 | "dev": true, 490 | "dependencies": { 491 | "diff-sequences": "^29.4.3", 492 | "loupe": "^2.3.6", 493 | "pretty-format": "^29.5.0" 494 | }, 495 | "funding": { 496 | "url": "https://opencollective.com/vitest" 497 | } 498 | }, 499 | "node_modules/acorn": { 500 | "version": "8.11.2", 501 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", 502 | "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", 503 | "dev": true, 504 | "bin": { 505 | "acorn": "bin/acorn" 506 | }, 507 | "engines": { 508 | "node": ">=0.4.0" 509 | } 510 | }, 511 | "node_modules/acorn-walk": { 512 | "version": "8.2.0", 513 | "dev": true, 514 | "license": "MIT", 515 | "engines": { 516 | "node": ">=0.4.0" 517 | } 518 | }, 519 | "node_modules/ansi-styles": { 520 | "version": "5.2.0", 521 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", 522 | "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", 523 | "dev": true, 524 | "engines": { 525 | "node": ">=10" 526 | }, 527 | "funding": { 528 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 529 | } 530 | }, 531 | "node_modules/assertion-error": { 532 | "version": "1.1.0", 533 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", 534 | "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", 535 | "dev": true, 536 | "engines": { 537 | "node": "*" 538 | } 539 | }, 540 | "node_modules/buffer-from": { 541 | "version": "1.1.2", 542 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", 543 | "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", 544 | "dev": true 545 | }, 546 | "node_modules/cac": { 547 | "version": "6.7.14", 548 | "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", 549 | "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", 550 | "dev": true, 551 | "engines": { 552 | "node": ">=8" 553 | } 554 | }, 555 | "node_modules/chai": { 556 | "version": "4.3.10", 557 | "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", 558 | "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==", 559 | "dev": true, 560 | "dependencies": { 561 | "assertion-error": "^1.1.0", 562 | "check-error": "^1.0.3", 563 | "deep-eql": "^4.1.3", 564 | "get-func-name": "^2.0.2", 565 | "loupe": "^2.3.6", 566 | "pathval": "^1.1.1", 567 | "type-detect": "^4.0.8" 568 | }, 569 | "engines": { 570 | "node": ">=4" 571 | } 572 | }, 573 | "node_modules/check-error": { 574 | "version": "1.0.3", 575 | "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", 576 | "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", 577 | "dev": true, 578 | "dependencies": { 579 | "get-func-name": "^2.0.2" 580 | }, 581 | "engines": { 582 | "node": "*" 583 | } 584 | }, 585 | "node_modules/data-uri-to-buffer": { 586 | "version": "4.0.1", 587 | "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", 588 | "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", 589 | "engines": { 590 | "node": ">= 12" 591 | } 592 | }, 593 | "node_modules/debug": { 594 | "version": "4.3.4", 595 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 596 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 597 | "dev": true, 598 | "dependencies": { 599 | "ms": "2.1.2" 600 | }, 601 | "engines": { 602 | "node": ">=6.0" 603 | }, 604 | "peerDependenciesMeta": { 605 | "supports-color": { 606 | "optional": true 607 | } 608 | } 609 | }, 610 | "node_modules/deep-eql": { 611 | "version": "4.1.3", 612 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", 613 | "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", 614 | "dev": true, 615 | "dependencies": { 616 | "type-detect": "^4.0.0" 617 | }, 618 | "engines": { 619 | "node": ">=6" 620 | } 621 | }, 622 | "node_modules/diff-sequences": { 623 | "version": "29.6.3", 624 | "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", 625 | "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", 626 | "dev": true, 627 | "engines": { 628 | "node": "^14.15.0 || ^16.10.0 || >=18.0.0" 629 | } 630 | }, 631 | "node_modules/effect": { 632 | "version": "3.0.3", 633 | "resolved": "https://registry.npmjs.org/effect/-/effect-3.0.3.tgz", 634 | "integrity": "sha512-mgG+FoWrM4sny8OxDFWCpq+6LwGf9cK/JztVhxZQeZM9ZMXY+lKbdMEQmemNYce0QVAz2+YqUKwhKzOidwbZzg==" 635 | }, 636 | "node_modules/esbuild": { 637 | "version": "0.18.20", 638 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", 639 | "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", 640 | "dev": true, 641 | "hasInstallScript": true, 642 | "bin": { 643 | "esbuild": "bin/esbuild" 644 | }, 645 | "engines": { 646 | "node": ">=12" 647 | }, 648 | "optionalDependencies": { 649 | "@esbuild/android-arm": "0.18.20", 650 | "@esbuild/android-arm64": "0.18.20", 651 | "@esbuild/android-x64": "0.18.20", 652 | "@esbuild/darwin-arm64": "0.18.20", 653 | "@esbuild/darwin-x64": "0.18.20", 654 | "@esbuild/freebsd-arm64": "0.18.20", 655 | "@esbuild/freebsd-x64": "0.18.20", 656 | "@esbuild/linux-arm": "0.18.20", 657 | "@esbuild/linux-arm64": "0.18.20", 658 | "@esbuild/linux-ia32": "0.18.20", 659 | "@esbuild/linux-loong64": "0.18.20", 660 | "@esbuild/linux-mips64el": "0.18.20", 661 | "@esbuild/linux-ppc64": "0.18.20", 662 | "@esbuild/linux-riscv64": "0.18.20", 663 | "@esbuild/linux-s390x": "0.18.20", 664 | "@esbuild/linux-x64": "0.18.20", 665 | "@esbuild/netbsd-x64": "0.18.20", 666 | "@esbuild/openbsd-x64": "0.18.20", 667 | "@esbuild/sunos-x64": "0.18.20", 668 | "@esbuild/win32-arm64": "0.18.20", 669 | "@esbuild/win32-ia32": "0.18.20", 670 | "@esbuild/win32-x64": "0.18.20" 671 | } 672 | }, 673 | "node_modules/fast-check": { 674 | "version": "3.13.2", 675 | "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.13.2.tgz", 676 | "integrity": "sha512-ouTiFyeMoqmNg253xqy4NSacr5sHxH6pZpLOaHgaAdgZxFWdtsfxExwolpveoAE9CJdV+WYjqErNGef6SqA5Mg==", 677 | "funding": [ 678 | { 679 | "type": "individual", 680 | "url": "https://github.com/sponsors/dubzzz" 681 | }, 682 | { 683 | "type": "opencollective", 684 | "url": "https://opencollective.com/fast-check" 685 | } 686 | ], 687 | "peer": true, 688 | "dependencies": { 689 | "pure-rand": "^6.0.0" 690 | }, 691 | "engines": { 692 | "node": ">=8.0.0" 693 | } 694 | }, 695 | "node_modules/fetch-blob": { 696 | "version": "3.2.0", 697 | "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", 698 | "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", 699 | "funding": [ 700 | { 701 | "type": "github", 702 | "url": "https://github.com/sponsors/jimmywarting" 703 | }, 704 | { 705 | "type": "paypal", 706 | "url": "https://paypal.me/jimmywarting" 707 | } 708 | ], 709 | "dependencies": { 710 | "node-domexception": "^1.0.0", 711 | "web-streams-polyfill": "^3.0.3" 712 | }, 713 | "engines": { 714 | "node": "^12.20 || >= 14.13" 715 | } 716 | }, 717 | "node_modules/formdata-polyfill": { 718 | "version": "4.0.10", 719 | "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", 720 | "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", 721 | "dependencies": { 722 | "fetch-blob": "^3.1.2" 723 | }, 724 | "engines": { 725 | "node": ">=12.20.0" 726 | } 727 | }, 728 | "node_modules/fp-ts": { 729 | "version": "2.16.1", 730 | "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.16.1.tgz", 731 | "integrity": "sha512-by7U5W8dkIzcvDofUcO42yl9JbnHTEDBrzu3pt5fKT+Z4Oy85I21K80EYJYdjQGC2qum4Vo55Ag57iiIK4FYuA==" 732 | }, 733 | "node_modules/fp-ts-contrib": { 734 | "version": "0.1.29", 735 | "resolved": "https://registry.npmjs.org/fp-ts-contrib/-/fp-ts-contrib-0.1.29.tgz", 736 | "integrity": "sha512-y+f+xlZqYgj2t+Alu/oat10UC491PByvH7XrT0ITc/DbDJK7LDJLShZJy2orjE7PlcJkO5niDenc1A/woyeB/Q==", 737 | "peerDependencies": { 738 | "fp-ts": "^2.1.2" 739 | } 740 | }, 741 | "node_modules/fsevents": { 742 | "version": "2.3.3", 743 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 744 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 745 | "dev": true, 746 | "hasInstallScript": true, 747 | "optional": true, 748 | "os": [ 749 | "darwin" 750 | ], 751 | "engines": { 752 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 753 | } 754 | }, 755 | "node_modules/get-func-name": { 756 | "version": "2.0.2", 757 | "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", 758 | "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", 759 | "dev": true, 760 | "engines": { 761 | "node": "*" 762 | } 763 | }, 764 | "node_modules/get-tsconfig": { 765 | "version": "4.7.2", 766 | "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", 767 | "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", 768 | "dev": true, 769 | "dependencies": { 770 | "resolve-pkg-maps": "^1.0.0" 771 | }, 772 | "funding": { 773 | "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" 774 | } 775 | }, 776 | "node_modules/io-ts": { 777 | "version": "2.2.20", 778 | "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-2.2.20.tgz", 779 | "integrity": "sha512-Rq2BsYmtwS5vVttie4rqrOCIfHCS9TgpRLFpKQCM1wZBBRY9nWVGmEvm2FnDbSE2un1UE39DvFpTR5UL47YDcA==", 780 | "peerDependencies": { 781 | "fp-ts": "^2.5.0" 782 | } 783 | }, 784 | "node_modules/jsonc-parser": { 785 | "version": "3.2.0", 786 | "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", 787 | "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", 788 | "dev": true 789 | }, 790 | "node_modules/local-pkg": { 791 | "version": "0.4.3", 792 | "dev": true, 793 | "license": "MIT", 794 | "engines": { 795 | "node": ">=14" 796 | }, 797 | "funding": { 798 | "url": "https://github.com/sponsors/antfu" 799 | } 800 | }, 801 | "node_modules/loupe": { 802 | "version": "2.3.7", 803 | "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", 804 | "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", 805 | "dev": true, 806 | "dependencies": { 807 | "get-func-name": "^2.0.1" 808 | } 809 | }, 810 | "node_modules/magic-string": { 811 | "version": "0.30.5", 812 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", 813 | "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", 814 | "dev": true, 815 | "dependencies": { 816 | "@jridgewell/sourcemap-codec": "^1.4.15" 817 | }, 818 | "engines": { 819 | "node": ">=12" 820 | } 821 | }, 822 | "node_modules/mlly": { 823 | "version": "1.4.2", 824 | "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.4.2.tgz", 825 | "integrity": "sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg==", 826 | "dev": true, 827 | "dependencies": { 828 | "acorn": "^8.10.0", 829 | "pathe": "^1.1.1", 830 | "pkg-types": "^1.0.3", 831 | "ufo": "^1.3.0" 832 | } 833 | }, 834 | "node_modules/ms": { 835 | "version": "2.1.2", 836 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 837 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 838 | "dev": true 839 | }, 840 | "node_modules/nanoid": { 841 | "version": "3.3.7", 842 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", 843 | "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", 844 | "dev": true, 845 | "funding": [ 846 | { 847 | "type": "github", 848 | "url": "https://github.com/sponsors/ai" 849 | } 850 | ], 851 | "bin": { 852 | "nanoid": "bin/nanoid.cjs" 853 | }, 854 | "engines": { 855 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 856 | } 857 | }, 858 | "node_modules/node-domexception": { 859 | "version": "1.0.0", 860 | "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", 861 | "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", 862 | "funding": [ 863 | { 864 | "type": "github", 865 | "url": "https://github.com/sponsors/jimmywarting" 866 | }, 867 | { 868 | "type": "github", 869 | "url": "https://paypal.me/jimmywarting" 870 | } 871 | ], 872 | "engines": { 873 | "node": ">=10.5.0" 874 | } 875 | }, 876 | "node_modules/node-fetch": { 877 | "version": "3.3.2", 878 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", 879 | "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", 880 | "dependencies": { 881 | "data-uri-to-buffer": "^4.0.0", 882 | "fetch-blob": "^3.1.4", 883 | "formdata-polyfill": "^4.0.10" 884 | }, 885 | "engines": { 886 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 887 | }, 888 | "funding": { 889 | "type": "opencollective", 890 | "url": "https://opencollective.com/node-fetch" 891 | } 892 | }, 893 | "node_modules/p-limit": { 894 | "version": "4.0.0", 895 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", 896 | "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", 897 | "dev": true, 898 | "dependencies": { 899 | "yocto-queue": "^1.0.0" 900 | }, 901 | "engines": { 902 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 903 | }, 904 | "funding": { 905 | "url": "https://github.com/sponsors/sindresorhus" 906 | } 907 | }, 908 | "node_modules/pathe": { 909 | "version": "1.1.1", 910 | "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.1.tgz", 911 | "integrity": "sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==", 912 | "dev": true 913 | }, 914 | "node_modules/pathval": { 915 | "version": "1.1.1", 916 | "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", 917 | "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", 918 | "dev": true, 919 | "engines": { 920 | "node": "*" 921 | } 922 | }, 923 | "node_modules/picocolors": { 924 | "version": "1.0.0", 925 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", 926 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", 927 | "dev": true 928 | }, 929 | "node_modules/pkg-types": { 930 | "version": "1.0.3", 931 | "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz", 932 | "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==", 933 | "dev": true, 934 | "dependencies": { 935 | "jsonc-parser": "^3.2.0", 936 | "mlly": "^1.2.0", 937 | "pathe": "^1.1.0" 938 | } 939 | }, 940 | "node_modules/postcss": { 941 | "version": "8.4.31", 942 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", 943 | "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", 944 | "dev": true, 945 | "funding": [ 946 | { 947 | "type": "opencollective", 948 | "url": "https://opencollective.com/postcss/" 949 | }, 950 | { 951 | "type": "tidelift", 952 | "url": "https://tidelift.com/funding/github/npm/postcss" 953 | }, 954 | { 955 | "type": "github", 956 | "url": "https://github.com/sponsors/ai" 957 | } 958 | ], 959 | "dependencies": { 960 | "nanoid": "^3.3.6", 961 | "picocolors": "^1.0.0", 962 | "source-map-js": "^1.0.2" 963 | }, 964 | "engines": { 965 | "node": "^10 || ^12 || >=14" 966 | } 967 | }, 968 | "node_modules/prettier": { 969 | "version": "3.1.0", 970 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", 971 | "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", 972 | "dev": true, 973 | "bin": { 974 | "prettier": "bin/prettier.cjs" 975 | }, 976 | "engines": { 977 | "node": ">=14" 978 | }, 979 | "funding": { 980 | "url": "https://github.com/prettier/prettier?sponsor=1" 981 | } 982 | }, 983 | "node_modules/pretty-format": { 984 | "version": "29.7.0", 985 | "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", 986 | "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", 987 | "dev": true, 988 | "dependencies": { 989 | "@jest/schemas": "^29.6.3", 990 | "ansi-styles": "^5.0.0", 991 | "react-is": "^18.0.0" 992 | }, 993 | "engines": { 994 | "node": "^14.15.0 || ^16.10.0 || >=18.0.0" 995 | } 996 | }, 997 | "node_modules/pure-rand": { 998 | "version": "6.0.4", 999 | "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", 1000 | "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", 1001 | "funding": [ 1002 | { 1003 | "type": "individual", 1004 | "url": "https://github.com/sponsors/dubzzz" 1005 | }, 1006 | { 1007 | "type": "opencollective", 1008 | "url": "https://opencollective.com/fast-check" 1009 | } 1010 | ], 1011 | "peer": true 1012 | }, 1013 | "node_modules/react-is": { 1014 | "version": "18.2.0", 1015 | "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", 1016 | "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", 1017 | "dev": true 1018 | }, 1019 | "node_modules/resolve-pkg-maps": { 1020 | "version": "1.0.0", 1021 | "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", 1022 | "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", 1023 | "dev": true, 1024 | "funding": { 1025 | "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" 1026 | } 1027 | }, 1028 | "node_modules/retry-ts": { 1029 | "version": "0.1.4", 1030 | "resolved": "https://registry.npmjs.org/retry-ts/-/retry-ts-0.1.4.tgz", 1031 | "integrity": "sha512-qUfPfEU+EjUVNU0aTDFjLtFJAh0yRD8TixwMs06WY/L8rTwUTluegfhT1k+9d4IKxa0XJ8r86+yxq/oxdx4fgg==", 1032 | "peerDependencies": { 1033 | "fp-ts": "^2.4.0" 1034 | } 1035 | }, 1036 | "node_modules/rollup": { 1037 | "version": "3.29.4", 1038 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", 1039 | "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", 1040 | "dev": true, 1041 | "bin": { 1042 | "rollup": "dist/bin/rollup" 1043 | }, 1044 | "engines": { 1045 | "node": ">=14.18.0", 1046 | "npm": ">=8.0.0" 1047 | }, 1048 | "optionalDependencies": { 1049 | "fsevents": "~2.3.2" 1050 | } 1051 | }, 1052 | "node_modules/siginfo": { 1053 | "version": "2.0.0", 1054 | "dev": true, 1055 | "license": "ISC" 1056 | }, 1057 | "node_modules/source-map": { 1058 | "version": "0.6.1", 1059 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1060 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1061 | "dev": true, 1062 | "engines": { 1063 | "node": ">=0.10.0" 1064 | } 1065 | }, 1066 | "node_modules/source-map-js": { 1067 | "version": "1.0.2", 1068 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", 1069 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", 1070 | "dev": true, 1071 | "engines": { 1072 | "node": ">=0.10.0" 1073 | } 1074 | }, 1075 | "node_modules/source-map-support": { 1076 | "version": "0.5.21", 1077 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", 1078 | "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", 1079 | "dev": true, 1080 | "dependencies": { 1081 | "buffer-from": "^1.0.0", 1082 | "source-map": "^0.6.0" 1083 | } 1084 | }, 1085 | "node_modules/stackback": { 1086 | "version": "0.0.2", 1087 | "dev": true, 1088 | "license": "MIT" 1089 | }, 1090 | "node_modules/std-env": { 1091 | "version": "3.5.0", 1092 | "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.5.0.tgz", 1093 | "integrity": "sha512-JGUEaALvL0Mf6JCfYnJOTcobY+Nc7sG/TemDRBqCA0wEr4DER7zDchaaixTlmOxAjG1uRJmX82EQcxwTQTkqVA==", 1094 | "dev": true 1095 | }, 1096 | "node_modules/strip-literal": { 1097 | "version": "1.0.1", 1098 | "dev": true, 1099 | "license": "MIT", 1100 | "dependencies": { 1101 | "acorn": "^8.8.2" 1102 | }, 1103 | "funding": { 1104 | "url": "https://github.com/sponsors/antfu" 1105 | } 1106 | }, 1107 | "node_modules/tinybench": { 1108 | "version": "2.5.1", 1109 | "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.1.tgz", 1110 | "integrity": "sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg==", 1111 | "dev": true 1112 | }, 1113 | "node_modules/tinypool": { 1114 | "version": "0.7.0", 1115 | "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.7.0.tgz", 1116 | "integrity": "sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==", 1117 | "dev": true, 1118 | "engines": { 1119 | "node": ">=14.0.0" 1120 | } 1121 | }, 1122 | "node_modules/tinyspy": { 1123 | "version": "2.2.0", 1124 | "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.0.tgz", 1125 | "integrity": "sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==", 1126 | "dev": true, 1127 | "engines": { 1128 | "node": ">=14.0.0" 1129 | } 1130 | }, 1131 | "node_modules/tsx": { 1132 | "version": "4.1.2", 1133 | "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.1.2.tgz", 1134 | "integrity": "sha512-1spM1bFV6MP2s4tO4tDC7g52fsaFdtEWdO4GfGdqi20qUgPbnAJqixOyIAvCSx1DDj3YIUB4CD06owTWUsOAuQ==", 1135 | "dev": true, 1136 | "dependencies": { 1137 | "esbuild": "~0.18.20", 1138 | "get-tsconfig": "^4.7.2", 1139 | "source-map-support": "^0.5.21" 1140 | }, 1141 | "bin": { 1142 | "tsx": "dist/cli.mjs" 1143 | }, 1144 | "engines": { 1145 | "node": ">=18.0.0" 1146 | }, 1147 | "optionalDependencies": { 1148 | "fsevents": "~2.3.3" 1149 | } 1150 | }, 1151 | "node_modules/type-detect": { 1152 | "version": "4.0.8", 1153 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", 1154 | "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", 1155 | "dev": true, 1156 | "engines": { 1157 | "node": ">=4" 1158 | } 1159 | }, 1160 | "node_modules/typescript": { 1161 | "version": "5.4.5", 1162 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", 1163 | "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", 1164 | "dev": true, 1165 | "bin": { 1166 | "tsc": "bin/tsc", 1167 | "tsserver": "bin/tsserver" 1168 | }, 1169 | "engines": { 1170 | "node": ">=14.17" 1171 | } 1172 | }, 1173 | "node_modules/ufo": { 1174 | "version": "1.3.2", 1175 | "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.2.tgz", 1176 | "integrity": "sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==", 1177 | "dev": true 1178 | }, 1179 | "node_modules/vite": { 1180 | "version": "4.5.0", 1181 | "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz", 1182 | "integrity": "sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==", 1183 | "dev": true, 1184 | "dependencies": { 1185 | "esbuild": "^0.18.10", 1186 | "postcss": "^8.4.27", 1187 | "rollup": "^3.27.1" 1188 | }, 1189 | "bin": { 1190 | "vite": "bin/vite.js" 1191 | }, 1192 | "engines": { 1193 | "node": "^14.18.0 || >=16.0.0" 1194 | }, 1195 | "funding": { 1196 | "url": "https://github.com/vitejs/vite?sponsor=1" 1197 | }, 1198 | "optionalDependencies": { 1199 | "fsevents": "~2.3.2" 1200 | }, 1201 | "peerDependencies": { 1202 | "@types/node": ">= 14", 1203 | "less": "*", 1204 | "lightningcss": "^1.21.0", 1205 | "sass": "*", 1206 | "stylus": "*", 1207 | "sugarss": "*", 1208 | "terser": "^5.4.0" 1209 | }, 1210 | "peerDependenciesMeta": { 1211 | "@types/node": { 1212 | "optional": true 1213 | }, 1214 | "less": { 1215 | "optional": true 1216 | }, 1217 | "lightningcss": { 1218 | "optional": true 1219 | }, 1220 | "sass": { 1221 | "optional": true 1222 | }, 1223 | "stylus": { 1224 | "optional": true 1225 | }, 1226 | "sugarss": { 1227 | "optional": true 1228 | }, 1229 | "terser": { 1230 | "optional": true 1231 | } 1232 | } 1233 | }, 1234 | "node_modules/vite-node": { 1235 | "version": "0.34.6", 1236 | "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.34.6.tgz", 1237 | "integrity": "sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==", 1238 | "dev": true, 1239 | "dependencies": { 1240 | "cac": "^6.7.14", 1241 | "debug": "^4.3.4", 1242 | "mlly": "^1.4.0", 1243 | "pathe": "^1.1.1", 1244 | "picocolors": "^1.0.0", 1245 | "vite": "^3.0.0 || ^4.0.0 || ^5.0.0-0" 1246 | }, 1247 | "bin": { 1248 | "vite-node": "vite-node.mjs" 1249 | }, 1250 | "engines": { 1251 | "node": ">=v14.18.0" 1252 | }, 1253 | "funding": { 1254 | "url": "https://opencollective.com/vitest" 1255 | } 1256 | }, 1257 | "node_modules/vitest": { 1258 | "version": "0.34.6", 1259 | "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.34.6.tgz", 1260 | "integrity": "sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==", 1261 | "dev": true, 1262 | "dependencies": { 1263 | "@types/chai": "^4.3.5", 1264 | "@types/chai-subset": "^1.3.3", 1265 | "@types/node": "*", 1266 | "@vitest/expect": "0.34.6", 1267 | "@vitest/runner": "0.34.6", 1268 | "@vitest/snapshot": "0.34.6", 1269 | "@vitest/spy": "0.34.6", 1270 | "@vitest/utils": "0.34.6", 1271 | "acorn": "^8.9.0", 1272 | "acorn-walk": "^8.2.0", 1273 | "cac": "^6.7.14", 1274 | "chai": "^4.3.10", 1275 | "debug": "^4.3.4", 1276 | "local-pkg": "^0.4.3", 1277 | "magic-string": "^0.30.1", 1278 | "pathe": "^1.1.1", 1279 | "picocolors": "^1.0.0", 1280 | "std-env": "^3.3.3", 1281 | "strip-literal": "^1.0.1", 1282 | "tinybench": "^2.5.0", 1283 | "tinypool": "^0.7.0", 1284 | "vite": "^3.1.0 || ^4.0.0 || ^5.0.0-0", 1285 | "vite-node": "0.34.6", 1286 | "why-is-node-running": "^2.2.2" 1287 | }, 1288 | "bin": { 1289 | "vitest": "vitest.mjs" 1290 | }, 1291 | "engines": { 1292 | "node": ">=v14.18.0" 1293 | }, 1294 | "funding": { 1295 | "url": "https://opencollective.com/vitest" 1296 | }, 1297 | "peerDependencies": { 1298 | "@edge-runtime/vm": "*", 1299 | "@vitest/browser": "*", 1300 | "@vitest/ui": "*", 1301 | "happy-dom": "*", 1302 | "jsdom": "*", 1303 | "playwright": "*", 1304 | "safaridriver": "*", 1305 | "webdriverio": "*" 1306 | }, 1307 | "peerDependenciesMeta": { 1308 | "@edge-runtime/vm": { 1309 | "optional": true 1310 | }, 1311 | "@vitest/browser": { 1312 | "optional": true 1313 | }, 1314 | "@vitest/ui": { 1315 | "optional": true 1316 | }, 1317 | "happy-dom": { 1318 | "optional": true 1319 | }, 1320 | "jsdom": { 1321 | "optional": true 1322 | }, 1323 | "playwright": { 1324 | "optional": true 1325 | }, 1326 | "safaridriver": { 1327 | "optional": true 1328 | }, 1329 | "webdriverio": { 1330 | "optional": true 1331 | } 1332 | } 1333 | }, 1334 | "node_modules/web-streams-polyfill": { 1335 | "version": "3.2.1", 1336 | "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", 1337 | "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", 1338 | "engines": { 1339 | "node": ">= 8" 1340 | } 1341 | }, 1342 | "node_modules/why-is-node-running": { 1343 | "version": "2.2.2", 1344 | "dev": true, 1345 | "license": "MIT", 1346 | "dependencies": { 1347 | "siginfo": "^2.0.0", 1348 | "stackback": "0.0.2" 1349 | }, 1350 | "bin": { 1351 | "why-is-node-running": "cli.js" 1352 | }, 1353 | "engines": { 1354 | "node": ">=8" 1355 | } 1356 | }, 1357 | "node_modules/yocto-queue": { 1358 | "version": "1.0.0", 1359 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", 1360 | "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", 1361 | "dev": true, 1362 | "engines": { 1363 | "node": ">=12.20" 1364 | }, 1365 | "funding": { 1366 | "url": "https://github.com/sponsors/sindresorhus" 1367 | } 1368 | } 1369 | }, 1370 | "dependencies": { 1371 | "@effect/schema": { 1372 | "version": "0.66.4", 1373 | "resolved": "https://registry.npmjs.org/@effect/schema/-/schema-0.66.4.tgz", 1374 | "integrity": "sha512-UQJxoqdGLgVBCkdArChNcTuofsfhXXZhRhptYQ9ZSEqyDZ0jnDGdGpNzMse4VGEkpdw+7UjXQ/nXjVv1wuFpPw==", 1375 | "requires": {} 1376 | }, 1377 | "@esbuild/android-arm": { 1378 | "version": "0.18.20", 1379 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", 1380 | "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", 1381 | "dev": true, 1382 | "optional": true 1383 | }, 1384 | "@esbuild/android-arm64": { 1385 | "version": "0.18.20", 1386 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", 1387 | "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", 1388 | "dev": true, 1389 | "optional": true 1390 | }, 1391 | "@esbuild/android-x64": { 1392 | "version": "0.18.20", 1393 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", 1394 | "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", 1395 | "dev": true, 1396 | "optional": true 1397 | }, 1398 | "@esbuild/darwin-arm64": { 1399 | "version": "0.18.20", 1400 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", 1401 | "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", 1402 | "dev": true, 1403 | "optional": true 1404 | }, 1405 | "@esbuild/darwin-x64": { 1406 | "version": "0.18.20", 1407 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", 1408 | "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", 1409 | "dev": true, 1410 | "optional": true 1411 | }, 1412 | "@esbuild/freebsd-arm64": { 1413 | "version": "0.18.20", 1414 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", 1415 | "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", 1416 | "dev": true, 1417 | "optional": true 1418 | }, 1419 | "@esbuild/freebsd-x64": { 1420 | "version": "0.18.20", 1421 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", 1422 | "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", 1423 | "dev": true, 1424 | "optional": true 1425 | }, 1426 | "@esbuild/linux-arm": { 1427 | "version": "0.18.20", 1428 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", 1429 | "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", 1430 | "dev": true, 1431 | "optional": true 1432 | }, 1433 | "@esbuild/linux-arm64": { 1434 | "version": "0.18.20", 1435 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", 1436 | "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", 1437 | "dev": true, 1438 | "optional": true 1439 | }, 1440 | "@esbuild/linux-ia32": { 1441 | "version": "0.18.20", 1442 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", 1443 | "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", 1444 | "dev": true, 1445 | "optional": true 1446 | }, 1447 | "@esbuild/linux-loong64": { 1448 | "version": "0.18.20", 1449 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", 1450 | "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", 1451 | "dev": true, 1452 | "optional": true 1453 | }, 1454 | "@esbuild/linux-mips64el": { 1455 | "version": "0.18.20", 1456 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", 1457 | "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", 1458 | "dev": true, 1459 | "optional": true 1460 | }, 1461 | "@esbuild/linux-ppc64": { 1462 | "version": "0.18.20", 1463 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", 1464 | "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", 1465 | "dev": true, 1466 | "optional": true 1467 | }, 1468 | "@esbuild/linux-riscv64": { 1469 | "version": "0.18.20", 1470 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", 1471 | "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", 1472 | "dev": true, 1473 | "optional": true 1474 | }, 1475 | "@esbuild/linux-s390x": { 1476 | "version": "0.18.20", 1477 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", 1478 | "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", 1479 | "dev": true, 1480 | "optional": true 1481 | }, 1482 | "@esbuild/linux-x64": { 1483 | "version": "0.18.20", 1484 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", 1485 | "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", 1486 | "dev": true, 1487 | "optional": true 1488 | }, 1489 | "@esbuild/netbsd-x64": { 1490 | "version": "0.18.20", 1491 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", 1492 | "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", 1493 | "dev": true, 1494 | "optional": true 1495 | }, 1496 | "@esbuild/openbsd-x64": { 1497 | "version": "0.18.20", 1498 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", 1499 | "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", 1500 | "dev": true, 1501 | "optional": true 1502 | }, 1503 | "@esbuild/sunos-x64": { 1504 | "version": "0.18.20", 1505 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", 1506 | "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", 1507 | "dev": true, 1508 | "optional": true 1509 | }, 1510 | "@esbuild/win32-arm64": { 1511 | "version": "0.18.20", 1512 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", 1513 | "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", 1514 | "dev": true, 1515 | "optional": true 1516 | }, 1517 | "@esbuild/win32-ia32": { 1518 | "version": "0.18.20", 1519 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", 1520 | "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", 1521 | "dev": true, 1522 | "optional": true 1523 | }, 1524 | "@esbuild/win32-x64": { 1525 | "version": "0.18.20", 1526 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", 1527 | "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", 1528 | "dev": true, 1529 | "optional": true 1530 | }, 1531 | "@jest/schemas": { 1532 | "version": "29.6.3", 1533 | "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", 1534 | "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", 1535 | "dev": true, 1536 | "requires": { 1537 | "@sinclair/typebox": "^0.27.8" 1538 | } 1539 | }, 1540 | "@jridgewell/sourcemap-codec": { 1541 | "version": "1.4.15", 1542 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", 1543 | "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", 1544 | "dev": true 1545 | }, 1546 | "@sinclair/typebox": { 1547 | "version": "0.27.8", 1548 | "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", 1549 | "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", 1550 | "dev": true 1551 | }, 1552 | "@types/chai": { 1553 | "version": "4.3.10", 1554 | "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.10.tgz", 1555 | "integrity": "sha512-of+ICnbqjmFCiixUnqRulbylyXQrPqIGf/B3Jax1wIF3DvSheysQxAWvqHhZiW3IQrycvokcLcFQlveGp+vyNg==", 1556 | "dev": true 1557 | }, 1558 | "@types/chai-subset": { 1559 | "version": "1.3.3", 1560 | "dev": true, 1561 | "requires": { 1562 | "@types/chai": "*" 1563 | } 1564 | }, 1565 | "@types/node": { 1566 | "version": "16.18.12", 1567 | "dev": true 1568 | }, 1569 | "@vitest/expect": { 1570 | "version": "0.34.6", 1571 | "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.6.tgz", 1572 | "integrity": "sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==", 1573 | "dev": true, 1574 | "requires": { 1575 | "@vitest/spy": "0.34.6", 1576 | "@vitest/utils": "0.34.6", 1577 | "chai": "^4.3.10" 1578 | } 1579 | }, 1580 | "@vitest/runner": { 1581 | "version": "0.34.6", 1582 | "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.6.tgz", 1583 | "integrity": "sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==", 1584 | "dev": true, 1585 | "requires": { 1586 | "@vitest/utils": "0.34.6", 1587 | "p-limit": "^4.0.0", 1588 | "pathe": "^1.1.1" 1589 | } 1590 | }, 1591 | "@vitest/snapshot": { 1592 | "version": "0.34.6", 1593 | "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.6.tgz", 1594 | "integrity": "sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==", 1595 | "dev": true, 1596 | "requires": { 1597 | "magic-string": "^0.30.1", 1598 | "pathe": "^1.1.1", 1599 | "pretty-format": "^29.5.0" 1600 | } 1601 | }, 1602 | "@vitest/spy": { 1603 | "version": "0.34.6", 1604 | "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.6.tgz", 1605 | "integrity": "sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==", 1606 | "dev": true, 1607 | "requires": { 1608 | "tinyspy": "^2.1.1" 1609 | } 1610 | }, 1611 | "@vitest/utils": { 1612 | "version": "0.34.6", 1613 | "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.6.tgz", 1614 | "integrity": "sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==", 1615 | "dev": true, 1616 | "requires": { 1617 | "diff-sequences": "^29.4.3", 1618 | "loupe": "^2.3.6", 1619 | "pretty-format": "^29.5.0" 1620 | } 1621 | }, 1622 | "acorn": { 1623 | "version": "8.11.2", 1624 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", 1625 | "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", 1626 | "dev": true 1627 | }, 1628 | "acorn-walk": { 1629 | "version": "8.2.0", 1630 | "dev": true 1631 | }, 1632 | "ansi-styles": { 1633 | "version": "5.2.0", 1634 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", 1635 | "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", 1636 | "dev": true 1637 | }, 1638 | "assertion-error": { 1639 | "version": "1.1.0", 1640 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", 1641 | "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", 1642 | "dev": true 1643 | }, 1644 | "buffer-from": { 1645 | "version": "1.1.2", 1646 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", 1647 | "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", 1648 | "dev": true 1649 | }, 1650 | "cac": { 1651 | "version": "6.7.14", 1652 | "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", 1653 | "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", 1654 | "dev": true 1655 | }, 1656 | "chai": { 1657 | "version": "4.3.10", 1658 | "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", 1659 | "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==", 1660 | "dev": true, 1661 | "requires": { 1662 | "assertion-error": "^1.1.0", 1663 | "check-error": "^1.0.3", 1664 | "deep-eql": "^4.1.3", 1665 | "get-func-name": "^2.0.2", 1666 | "loupe": "^2.3.6", 1667 | "pathval": "^1.1.1", 1668 | "type-detect": "^4.0.8" 1669 | } 1670 | }, 1671 | "check-error": { 1672 | "version": "1.0.3", 1673 | "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", 1674 | "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", 1675 | "dev": true, 1676 | "requires": { 1677 | "get-func-name": "^2.0.2" 1678 | } 1679 | }, 1680 | "data-uri-to-buffer": { 1681 | "version": "4.0.1", 1682 | "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", 1683 | "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==" 1684 | }, 1685 | "debug": { 1686 | "version": "4.3.4", 1687 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 1688 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 1689 | "dev": true, 1690 | "requires": { 1691 | "ms": "2.1.2" 1692 | } 1693 | }, 1694 | "deep-eql": { 1695 | "version": "4.1.3", 1696 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", 1697 | "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", 1698 | "dev": true, 1699 | "requires": { 1700 | "type-detect": "^4.0.0" 1701 | } 1702 | }, 1703 | "diff-sequences": { 1704 | "version": "29.6.3", 1705 | "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", 1706 | "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", 1707 | "dev": true 1708 | }, 1709 | "effect": { 1710 | "version": "3.0.3", 1711 | "resolved": "https://registry.npmjs.org/effect/-/effect-3.0.3.tgz", 1712 | "integrity": "sha512-mgG+FoWrM4sny8OxDFWCpq+6LwGf9cK/JztVhxZQeZM9ZMXY+lKbdMEQmemNYce0QVAz2+YqUKwhKzOidwbZzg==" 1713 | }, 1714 | "esbuild": { 1715 | "version": "0.18.20", 1716 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", 1717 | "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", 1718 | "dev": true, 1719 | "requires": { 1720 | "@esbuild/android-arm": "0.18.20", 1721 | "@esbuild/android-arm64": "0.18.20", 1722 | "@esbuild/android-x64": "0.18.20", 1723 | "@esbuild/darwin-arm64": "0.18.20", 1724 | "@esbuild/darwin-x64": "0.18.20", 1725 | "@esbuild/freebsd-arm64": "0.18.20", 1726 | "@esbuild/freebsd-x64": "0.18.20", 1727 | "@esbuild/linux-arm": "0.18.20", 1728 | "@esbuild/linux-arm64": "0.18.20", 1729 | "@esbuild/linux-ia32": "0.18.20", 1730 | "@esbuild/linux-loong64": "0.18.20", 1731 | "@esbuild/linux-mips64el": "0.18.20", 1732 | "@esbuild/linux-ppc64": "0.18.20", 1733 | "@esbuild/linux-riscv64": "0.18.20", 1734 | "@esbuild/linux-s390x": "0.18.20", 1735 | "@esbuild/linux-x64": "0.18.20", 1736 | "@esbuild/netbsd-x64": "0.18.20", 1737 | "@esbuild/openbsd-x64": "0.18.20", 1738 | "@esbuild/sunos-x64": "0.18.20", 1739 | "@esbuild/win32-arm64": "0.18.20", 1740 | "@esbuild/win32-ia32": "0.18.20", 1741 | "@esbuild/win32-x64": "0.18.20" 1742 | } 1743 | }, 1744 | "fast-check": { 1745 | "version": "3.13.2", 1746 | "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.13.2.tgz", 1747 | "integrity": "sha512-ouTiFyeMoqmNg253xqy4NSacr5sHxH6pZpLOaHgaAdgZxFWdtsfxExwolpveoAE9CJdV+WYjqErNGef6SqA5Mg==", 1748 | "peer": true, 1749 | "requires": { 1750 | "pure-rand": "^6.0.0" 1751 | } 1752 | }, 1753 | "fetch-blob": { 1754 | "version": "3.2.0", 1755 | "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", 1756 | "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", 1757 | "requires": { 1758 | "node-domexception": "^1.0.0", 1759 | "web-streams-polyfill": "^3.0.3" 1760 | } 1761 | }, 1762 | "formdata-polyfill": { 1763 | "version": "4.0.10", 1764 | "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", 1765 | "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", 1766 | "requires": { 1767 | "fetch-blob": "^3.1.2" 1768 | } 1769 | }, 1770 | "fp-ts": { 1771 | "version": "2.16.1", 1772 | "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.16.1.tgz", 1773 | "integrity": "sha512-by7U5W8dkIzcvDofUcO42yl9JbnHTEDBrzu3pt5fKT+Z4Oy85I21K80EYJYdjQGC2qum4Vo55Ag57iiIK4FYuA==" 1774 | }, 1775 | "fp-ts-contrib": { 1776 | "version": "0.1.29", 1777 | "resolved": "https://registry.npmjs.org/fp-ts-contrib/-/fp-ts-contrib-0.1.29.tgz", 1778 | "integrity": "sha512-y+f+xlZqYgj2t+Alu/oat10UC491PByvH7XrT0ITc/DbDJK7LDJLShZJy2orjE7PlcJkO5niDenc1A/woyeB/Q==", 1779 | "requires": {} 1780 | }, 1781 | "fsevents": { 1782 | "version": "2.3.3", 1783 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 1784 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 1785 | "dev": true, 1786 | "optional": true 1787 | }, 1788 | "get-func-name": { 1789 | "version": "2.0.2", 1790 | "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", 1791 | "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", 1792 | "dev": true 1793 | }, 1794 | "get-tsconfig": { 1795 | "version": "4.7.2", 1796 | "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", 1797 | "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", 1798 | "dev": true, 1799 | "requires": { 1800 | "resolve-pkg-maps": "^1.0.0" 1801 | } 1802 | }, 1803 | "io-ts": { 1804 | "version": "2.2.20", 1805 | "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-2.2.20.tgz", 1806 | "integrity": "sha512-Rq2BsYmtwS5vVttie4rqrOCIfHCS9TgpRLFpKQCM1wZBBRY9nWVGmEvm2FnDbSE2un1UE39DvFpTR5UL47YDcA==", 1807 | "requires": {} 1808 | }, 1809 | "jsonc-parser": { 1810 | "version": "3.2.0", 1811 | "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", 1812 | "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", 1813 | "dev": true 1814 | }, 1815 | "local-pkg": { 1816 | "version": "0.4.3", 1817 | "dev": true 1818 | }, 1819 | "loupe": { 1820 | "version": "2.3.7", 1821 | "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", 1822 | "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", 1823 | "dev": true, 1824 | "requires": { 1825 | "get-func-name": "^2.0.1" 1826 | } 1827 | }, 1828 | "magic-string": { 1829 | "version": "0.30.5", 1830 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", 1831 | "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", 1832 | "dev": true, 1833 | "requires": { 1834 | "@jridgewell/sourcemap-codec": "^1.4.15" 1835 | } 1836 | }, 1837 | "mlly": { 1838 | "version": "1.4.2", 1839 | "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.4.2.tgz", 1840 | "integrity": "sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg==", 1841 | "dev": true, 1842 | "requires": { 1843 | "acorn": "^8.10.0", 1844 | "pathe": "^1.1.1", 1845 | "pkg-types": "^1.0.3", 1846 | "ufo": "^1.3.0" 1847 | } 1848 | }, 1849 | "ms": { 1850 | "version": "2.1.2", 1851 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1852 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1853 | "dev": true 1854 | }, 1855 | "nanoid": { 1856 | "version": "3.3.7", 1857 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", 1858 | "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", 1859 | "dev": true 1860 | }, 1861 | "node-domexception": { 1862 | "version": "1.0.0", 1863 | "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", 1864 | "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" 1865 | }, 1866 | "node-fetch": { 1867 | "version": "3.3.2", 1868 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", 1869 | "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", 1870 | "requires": { 1871 | "data-uri-to-buffer": "^4.0.0", 1872 | "fetch-blob": "^3.1.4", 1873 | "formdata-polyfill": "^4.0.10" 1874 | } 1875 | }, 1876 | "p-limit": { 1877 | "version": "4.0.0", 1878 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", 1879 | "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", 1880 | "dev": true, 1881 | "requires": { 1882 | "yocto-queue": "^1.0.0" 1883 | } 1884 | }, 1885 | "pathe": { 1886 | "version": "1.1.1", 1887 | "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.1.tgz", 1888 | "integrity": "sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==", 1889 | "dev": true 1890 | }, 1891 | "pathval": { 1892 | "version": "1.1.1", 1893 | "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", 1894 | "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", 1895 | "dev": true 1896 | }, 1897 | "picocolors": { 1898 | "version": "1.0.0", 1899 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", 1900 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", 1901 | "dev": true 1902 | }, 1903 | "pkg-types": { 1904 | "version": "1.0.3", 1905 | "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz", 1906 | "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==", 1907 | "dev": true, 1908 | "requires": { 1909 | "jsonc-parser": "^3.2.0", 1910 | "mlly": "^1.2.0", 1911 | "pathe": "^1.1.0" 1912 | } 1913 | }, 1914 | "postcss": { 1915 | "version": "8.4.31", 1916 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", 1917 | "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", 1918 | "dev": true, 1919 | "requires": { 1920 | "nanoid": "^3.3.6", 1921 | "picocolors": "^1.0.0", 1922 | "source-map-js": "^1.0.2" 1923 | } 1924 | }, 1925 | "prettier": { 1926 | "version": "3.1.0", 1927 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", 1928 | "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", 1929 | "dev": true 1930 | }, 1931 | "pretty-format": { 1932 | "version": "29.7.0", 1933 | "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", 1934 | "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", 1935 | "dev": true, 1936 | "requires": { 1937 | "@jest/schemas": "^29.6.3", 1938 | "ansi-styles": "^5.0.0", 1939 | "react-is": "^18.0.0" 1940 | } 1941 | }, 1942 | "pure-rand": { 1943 | "version": "6.0.4", 1944 | "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", 1945 | "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", 1946 | "peer": true 1947 | }, 1948 | "react-is": { 1949 | "version": "18.2.0", 1950 | "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", 1951 | "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", 1952 | "dev": true 1953 | }, 1954 | "resolve-pkg-maps": { 1955 | "version": "1.0.0", 1956 | "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", 1957 | "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", 1958 | "dev": true 1959 | }, 1960 | "retry-ts": { 1961 | "version": "0.1.4", 1962 | "resolved": "https://registry.npmjs.org/retry-ts/-/retry-ts-0.1.4.tgz", 1963 | "integrity": "sha512-qUfPfEU+EjUVNU0aTDFjLtFJAh0yRD8TixwMs06WY/L8rTwUTluegfhT1k+9d4IKxa0XJ8r86+yxq/oxdx4fgg==", 1964 | "requires": {} 1965 | }, 1966 | "rollup": { 1967 | "version": "3.29.4", 1968 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", 1969 | "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", 1970 | "dev": true, 1971 | "requires": { 1972 | "fsevents": "~2.3.2" 1973 | } 1974 | }, 1975 | "siginfo": { 1976 | "version": "2.0.0", 1977 | "dev": true 1978 | }, 1979 | "source-map": { 1980 | "version": "0.6.1", 1981 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1982 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1983 | "dev": true 1984 | }, 1985 | "source-map-js": { 1986 | "version": "1.0.2", 1987 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", 1988 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", 1989 | "dev": true 1990 | }, 1991 | "source-map-support": { 1992 | "version": "0.5.21", 1993 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", 1994 | "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", 1995 | "dev": true, 1996 | "requires": { 1997 | "buffer-from": "^1.0.0", 1998 | "source-map": "^0.6.0" 1999 | } 2000 | }, 2001 | "stackback": { 2002 | "version": "0.0.2", 2003 | "dev": true 2004 | }, 2005 | "std-env": { 2006 | "version": "3.5.0", 2007 | "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.5.0.tgz", 2008 | "integrity": "sha512-JGUEaALvL0Mf6JCfYnJOTcobY+Nc7sG/TemDRBqCA0wEr4DER7zDchaaixTlmOxAjG1uRJmX82EQcxwTQTkqVA==", 2009 | "dev": true 2010 | }, 2011 | "strip-literal": { 2012 | "version": "1.0.1", 2013 | "dev": true, 2014 | "requires": { 2015 | "acorn": "^8.8.2" 2016 | } 2017 | }, 2018 | "tinybench": { 2019 | "version": "2.5.1", 2020 | "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.1.tgz", 2021 | "integrity": "sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg==", 2022 | "dev": true 2023 | }, 2024 | "tinypool": { 2025 | "version": "0.7.0", 2026 | "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.7.0.tgz", 2027 | "integrity": "sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==", 2028 | "dev": true 2029 | }, 2030 | "tinyspy": { 2031 | "version": "2.2.0", 2032 | "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.0.tgz", 2033 | "integrity": "sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==", 2034 | "dev": true 2035 | }, 2036 | "tsx": { 2037 | "version": "4.1.2", 2038 | "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.1.2.tgz", 2039 | "integrity": "sha512-1spM1bFV6MP2s4tO4tDC7g52fsaFdtEWdO4GfGdqi20qUgPbnAJqixOyIAvCSx1DDj3YIUB4CD06owTWUsOAuQ==", 2040 | "dev": true, 2041 | "requires": { 2042 | "esbuild": "~0.18.20", 2043 | "fsevents": "~2.3.3", 2044 | "get-tsconfig": "^4.7.2", 2045 | "source-map-support": "^0.5.21" 2046 | } 2047 | }, 2048 | "type-detect": { 2049 | "version": "4.0.8", 2050 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", 2051 | "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", 2052 | "dev": true 2053 | }, 2054 | "typescript": { 2055 | "version": "5.4.5", 2056 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", 2057 | "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", 2058 | "dev": true 2059 | }, 2060 | "ufo": { 2061 | "version": "1.3.2", 2062 | "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.2.tgz", 2063 | "integrity": "sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==", 2064 | "dev": true 2065 | }, 2066 | "vite": { 2067 | "version": "4.5.0", 2068 | "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz", 2069 | "integrity": "sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==", 2070 | "dev": true, 2071 | "requires": { 2072 | "esbuild": "^0.18.10", 2073 | "fsevents": "~2.3.2", 2074 | "postcss": "^8.4.27", 2075 | "rollup": "^3.27.1" 2076 | } 2077 | }, 2078 | "vite-node": { 2079 | "version": "0.34.6", 2080 | "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.34.6.tgz", 2081 | "integrity": "sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==", 2082 | "dev": true, 2083 | "requires": { 2084 | "cac": "^6.7.14", 2085 | "debug": "^4.3.4", 2086 | "mlly": "^1.4.0", 2087 | "pathe": "^1.1.1", 2088 | "picocolors": "^1.0.0", 2089 | "vite": "^3.0.0 || ^4.0.0 || ^5.0.0-0" 2090 | } 2091 | }, 2092 | "vitest": { 2093 | "version": "0.34.6", 2094 | "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.34.6.tgz", 2095 | "integrity": "sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==", 2096 | "dev": true, 2097 | "requires": { 2098 | "@types/chai": "^4.3.5", 2099 | "@types/chai-subset": "^1.3.3", 2100 | "@types/node": "*", 2101 | "@vitest/expect": "0.34.6", 2102 | "@vitest/runner": "0.34.6", 2103 | "@vitest/snapshot": "0.34.6", 2104 | "@vitest/spy": "0.34.6", 2105 | "@vitest/utils": "0.34.6", 2106 | "acorn": "^8.9.0", 2107 | "acorn-walk": "^8.2.0", 2108 | "cac": "^6.7.14", 2109 | "chai": "^4.3.10", 2110 | "debug": "^4.3.4", 2111 | "local-pkg": "^0.4.3", 2112 | "magic-string": "^0.30.1", 2113 | "pathe": "^1.1.1", 2114 | "picocolors": "^1.0.0", 2115 | "std-env": "^3.3.3", 2116 | "strip-literal": "^1.0.1", 2117 | "tinybench": "^2.5.0", 2118 | "tinypool": "^0.7.0", 2119 | "vite": "^3.1.0 || ^4.0.0 || ^5.0.0-0", 2120 | "vite-node": "0.34.6", 2121 | "why-is-node-running": "^2.2.2" 2122 | } 2123 | }, 2124 | "web-streams-polyfill": { 2125 | "version": "3.2.1", 2126 | "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", 2127 | "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==" 2128 | }, 2129 | "why-is-node-running": { 2130 | "version": "2.2.2", 2131 | "dev": true, 2132 | "requires": { 2133 | "siginfo": "^2.0.0", 2134 | "stackback": "0.0.2" 2135 | } 2136 | }, 2137 | "yocto-queue": { 2138 | "version": "1.0.0", 2139 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", 2140 | "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", 2141 | "dev": true 2142 | } 2143 | } 2144 | } 2145 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "from-fp-ts-to-effect-ts", 3 | "version": "1.0.0", 4 | "description": "An exploration of EffectTS ecosystem from fp-ts user prospective", 5 | "scripts": { 6 | "format": "prettier --write src/**/*.ts", 7 | "test": "vitest run --passWithNoTests", 8 | "test:w": "vitest watch", 9 | "typecheck": "tsc --noEmit", 10 | "typecheck:w": "tsc --noEmit --watch" 11 | }, 12 | "dependencies": { 13 | "effect": "3.0.3", 14 | "@effect/schema": "0.66.4", 15 | "fp-ts": "2.16.1", 16 | "io-ts": "2.2.20", 17 | "fp-ts-contrib": "0.1.29", 18 | "retry-ts": "0.1.4", 19 | "node-fetch": "3.3.2" 20 | }, 21 | "devDependencies": { 22 | "@types/node": "16.18.12", 23 | "typescript": "5.4.5", 24 | "vitest": "0.34.6", 25 | "prettier": "3.1.0", 26 | "tsx": "4.1.2" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/1-basic/effect.ts: -------------------------------------------------------------------------------- 1 | import * as Effect from "effect/Effect" 2 | import * as F from "effect/Function" 3 | import * as E from "effect/Either" 4 | 5 | /* 6 | Effect 7 | - A -> type in case the computation succeeds 8 | - E -> errors in case the computation fails 9 | - R -> computation requirements 10 | */ 11 | 12 | const succeed = Effect.succeed(7) // Effect.Effect 13 | 14 | const fail = Effect.fail(3) // Effect.Effect 15 | 16 | const sync = Effect.sync(() => { 17 | console.log("hello from Effect.sync") 18 | return 4 19 | }) // Effect.Effect 20 | 21 | const failSync = Effect.failSync(() => { 22 | console.log("hello from Effect.failSync") 23 | return 4 24 | }) // Effect.Effect 25 | 26 | const eitherFromRandom = (random: number): E.Either => 27 | random > 0.5 ? E.right(random) : E.left("Number is less than 0.5") 28 | 29 | // Either and Option are subtype of Effect so can be mixed together! 30 | // https://www.effect.website/docs/data-types/either#interop-with-effect 31 | // https://www.effect.website/docs/data-types/option#interop-with-effect 32 | const x = F.pipe( 33 | Effect.sync(() => Math.random()), // Effect.Effect 34 | Effect.flatMap(eitherFromRandom), // Effect.Effect 35 | ) 36 | 37 | // Run Effect 38 | // NOTE: Since you can also run async operations inside Effect, you should always use Effect.runPromise 39 | console.log(Effect.runSync(x)) 40 | -------------------------------------------------------------------------------- /src/1-basic/fp-ts.ts: -------------------------------------------------------------------------------- 1 | import * as F from "fp-ts/function" 2 | import * as E from "fp-ts/Either" 3 | 4 | const r = E.right(7) 5 | 6 | const l = E.left(3) 7 | 8 | const eitherFromRandom = (random: number): E.Either => 9 | random > 0.5 ? E.right(random) : E.left("Number is less than 0.5") 10 | 11 | const x = F.pipe( 12 | // keep new line 13 | Math.random(), 14 | eitherFromRandom, 15 | ) 16 | 17 | console.log(x) 18 | -------------------------------------------------------------------------------- /src/2-services/effect.ts: -------------------------------------------------------------------------------- 1 | import * as Effect from "effect/Effect" 2 | import * as Context from "effect/Context" 3 | import * as F from "effect/Function" 4 | import { runEffect } from "../utils/effect" 5 | import { User, Todo } from "../domain/effect" 6 | 7 | // DOCS: https://www.effect.website/docs/context-management/services 8 | 9 | interface TodoRepo { 10 | load: () => Effect.Effect 11 | save: (todo: Todo) => Effect.Effect 12 | } 13 | const TodoRepo = Context.GenericTag("@services/TodoRepo") 14 | 15 | interface UserRepo { 16 | load: () => Effect.Effect 17 | } 18 | const UserRepo = Context.GenericTag("@services/UserRepo") 19 | 20 | const makeMarkAsCompleted = F.pipe( 21 | Effect.all([TodoRepo, UserRepo]), 22 | Effect.flatMap(([todoRepo, userRepo]) => 23 | F.pipe( 24 | Effect.all( 25 | { 26 | todo: todoRepo.load(), 27 | user: userRepo.load(), 28 | }, 29 | { concurrency: "unbounded" }, // run this effects in parallel with no limits (https://www.effect.website/docs/concurrency/concurrency-options) 30 | ), 31 | Effect.let("completedTodo", ({ todo }) => markCompleted(todo)), 32 | Effect.bind("_", ({ completedTodo }) => todoRepo.save(completedTodo)), 33 | Effect.map(({ completedTodo, user }) => ({ 34 | todo: completedTodo.title, 35 | userName: user.name, 36 | })), 37 | ), 38 | ), 39 | ) 40 | 41 | /* Like C# LINQ or similar to Rust "?" operator 42 | Effect uses JavaScript generators. 43 | 44 | MDN: 45 | - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators 46 | - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function* 47 | - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield* 48 | */ 49 | const generators = Effect.gen(function* ($) { 50 | // ~~~~~~~~~ 51 | // ^ define generator function 52 | const todoRepo = yield* $(TodoRepo) 53 | // ~~~~~~ 54 | // ^ delegate to another generator 55 | const userRepo = yield* $(UserRepo) 56 | 57 | const { user, todo } = yield* $( 58 | Effect.all( 59 | { 60 | todo: todoRepo.load(), 61 | user: userRepo.load(), 62 | }, 63 | { concurrency: "unbounded" }, 64 | ), 65 | ) 66 | 67 | const completedTodo = markCompleted(todo) 68 | yield* $(todoRepo.save(completedTodo)) 69 | 70 | return { 71 | todo: completedTodo.title, 72 | userName: user.name, 73 | } 74 | }) 75 | 76 | const markCompleted = (todo: Todo) => ({ ...todo, completed: true }) 77 | 78 | const effect = F.pipe( 79 | makeMarkAsCompleted, // change this for the version using generators 80 | Effect.provideService(TodoRepo, { 81 | load: () => 82 | Effect.succeed({ id: 1, userId: 23, title: "Use more EffectTS", completed: false }), 83 | save: (todo) => 84 | Effect.sync(() => { 85 | console.log(`Saved todo #${todo.id}`) 86 | }), 87 | }), 88 | Effect.provideService(UserRepo, { 89 | load: () => Effect.succeed({ id: 23, name: "Cosimo" }), 90 | }), 91 | ) 92 | 93 | runEffect(effect).catch(() => { 94 | process.exit(1) 95 | }) 96 | -------------------------------------------------------------------------------- /src/2-services/fp-ts.ts: -------------------------------------------------------------------------------- 1 | import { TaskEither } from "fp-ts/TaskEither" 2 | import { Todo } from "../domain/effect" 3 | import * as F from "fp-ts/function" 4 | import * as TE from "fp-ts/TaskEither" 5 | import { runTaskEither } from "../utils/fp-ts" 6 | import { User } from "../domain/fp-ts" 7 | import { sequenceS } from "fp-ts/Apply" 8 | 9 | const sequenceTE = sequenceS(TE.ApplyPar) 10 | 11 | type Deps = { 12 | loadUser: () => TaskEither 13 | loadTodo: () => TaskEither 14 | saveTodo: (todo: Todo) => TaskEither 15 | } 16 | 17 | const makeMarkAsCompleted = ({ loadTodo, saveTodo, loadUser }: Deps) => 18 | F.pipe( 19 | sequenceTE({ 20 | todo: loadTodo(), 21 | user: loadUser(), 22 | }), 23 | TE.bind("completedTodo", ({ todo }) => TE.right({ ...todo, completed: true })), 24 | TE.bind("_", ({ completedTodo }) => saveTodo(completedTodo)), 25 | TE.map(({ completedTodo, user }) => ({ todo: completedTodo.title, userName: user.name })), 26 | ) 27 | 28 | const markAsCompleted = makeMarkAsCompleted({ 29 | loadTodo: () => TE.right({ id: 1, userId: 23, title: "Try EffectTS", completed: false }), 30 | saveTodo: (todo) => 31 | TE.rightIO(() => { 32 | console.log(`Saved todo #${todo.id}`) 33 | }), 34 | loadUser: () => TE.right({ id: 23, name: "Cosimo" }), 35 | }) 36 | 37 | runTaskEither(markAsCompleted).catch(() => { 38 | process.exit(1) 39 | }) 40 | -------------------------------------------------------------------------------- /src/3-errors/effect.ts: -------------------------------------------------------------------------------- 1 | import * as Effect from "effect/Effect" 2 | import * as F from "effect/Function" 3 | import * as Data from "effect/Data" 4 | import * as Equal from "effect/Equal" 5 | import * as Cause from "effect/Cause" 6 | import { runEffect } from "../utils/effect" 7 | 8 | interface TransientError { 9 | _tag: "TransientError" 10 | message: string 11 | } 12 | const TransientError = Data.tagged("TransientError") 13 | 14 | interface FatalError { 15 | _tag: "FatalError" 16 | message: string 17 | } 18 | const FatalError = Data.tagged("FatalError") 19 | 20 | // --- Failures --- 21 | // Expected and recoverable errors. This is the E type parameter in Effect 22 | 23 | const someError = F.pipe( 24 | Effect.fail(TransientError({ message: "http timeout" })), 25 | Effect.flatMap(() => Effect.fail(FatalError({ message: "malformed json" }))), 26 | Effect.map(() => "done"), 27 | ) 28 | 29 | const canCompareErrorByValue = Equal.equals( 30 | TransientError({ message: "timeout" }), 31 | TransientError({ message: "timeout" }), 32 | ) 33 | 34 | const handleError = F.pipe( 35 | someError, 36 | Effect.catchTag("TransientError", () => Effect.succeed("http ok now")), 37 | ) 38 | /* 39 | Other alternatives: 40 | - Effect.catchTags -> like catchTag but can specify N errors 41 | - Effect.catch -> if your error tagged union has key different from _tag 42 | - Effect.catchAll -> handle all errors at once 43 | */ 44 | 45 | // --- Defects --- 46 | // Unexpected and unrecoverable errors. This are not part of Effect 47 | // The Effect runtime keeps track of this errors in structure called Cause that you can inspect 48 | // --- Interruption --- 49 | // Interrupt the execution of a Fiber 50 | 51 | Cause.empty // Cause of an Effect that succeeds 52 | Cause.fail // Cause of an Effect that errors with fail (failure) 53 | Cause.die // Cause of an Effect that errors with die (defect) 54 | Cause.interrupt // Cause of an Effect that errors with interrupt 55 | 56 | const defect = F.pipe( 57 | Effect.succeed("Everything fine here"), 58 | Effect.flatMap(() => Effect.die("Houston, we have a problem")), 59 | ) 60 | 61 | const catchAllCauseLog = Effect.catchAllCause(defect, (cause) => 62 | Effect.logError("Something went wrong", cause), 63 | ) 64 | 65 | runEffect(catchAllCauseLog) 66 | -------------------------------------------------------------------------------- /src/3-errors/fp-ts.ts: -------------------------------------------------------------------------------- 1 | console.log(`Empty module! 2 | There are no out-of-the-box fp-ts equivalents for Effect's error`) 3 | -------------------------------------------------------------------------------- /src/4-http/effect.ts: -------------------------------------------------------------------------------- 1 | import * as F from "effect/Function" 2 | import * as Effect from "effect/Effect" 3 | import fetch from "node-fetch" 4 | import { Todos } from "../domain/effect" 5 | import { decode, runEffect } from "../utils/effect" 6 | 7 | const getTodos = F.pipe( 8 | Effect.tryPromise({ 9 | try: () => fetch("https://jsonplaceholder.typicode.com/users/1/todos"), 10 | catch: (e) => `Error fetching todos: ${e}`, 11 | }), 12 | Effect.flatMap((response) => 13 | response.ok 14 | ? Effect.succeed(response) 15 | : Effect.fail(`Error fetch with status code ${response.status}`), 16 | ), 17 | Effect.flatMap((response) => 18 | Effect.tryPromise({ 19 | try: () => response.json(), 20 | catch: (e) => `Error parsing todos as json: ${e}`, 21 | }), 22 | ), 23 | Effect.flatMap(F.flow(decode(Todos))), 24 | ) 25 | 26 | runEffect(getTodos).catch(() => { 27 | process.exit(1) 28 | }) 29 | -------------------------------------------------------------------------------- /src/4-http/fp-ts.ts: -------------------------------------------------------------------------------- 1 | import * as F from "fp-ts/function" 2 | import * as TE from "fp-ts/TaskEither" 3 | import fetch from "node-fetch" 4 | import { Todos } from "../domain/fp-ts" 5 | import { decode, runTaskEither } from "../utils/fp-ts" 6 | 7 | const getTodos = () => 8 | F.pipe( 9 | TE.tryCatch( 10 | () => fetch("https://jsonplaceholder.typicode.com/users/1/todos"), 11 | (e) => `Error fetching todos: ${e}`, 12 | ), 13 | TE.chain( 14 | TE.fromPredicate( 15 | (response) => response.ok, 16 | (response) => `Error fetch with status code ${response.status}`, 17 | ), 18 | ), 19 | TE.chain((response) => 20 | TE.tryCatch( 21 | () => response.json(), 22 | (e) => `Error parsing todos as json: ${e}`, 23 | ), 24 | ), 25 | TE.chainEitherK(F.flow(decode(Todos))), 26 | ) 27 | 28 | runTaskEither(getTodos()).catch((e) => { 29 | process.exit(1) 30 | }) 31 | -------------------------------------------------------------------------------- /src/5-parallelism/effect.ts: -------------------------------------------------------------------------------- 1 | import * as F from "effect/Function" 2 | import * as ROA from "effect/Array" 3 | import * as Effect from "effect/Effect" 4 | import * as Duration from "effect/Duration" 5 | import { Todo } from "../domain/effect" 6 | import { runEffect } from "../utils/effect" 7 | 8 | const getTodos = (url: string) => 9 | F.pipe( 10 | Effect.logInfo(`Fetching ${url}`), 11 | Effect.flatMap(() => Effect.delay(Duration.seconds(3))(Effect.succeed("delay done"))), 12 | Effect.map((): Todo[] => [{ id: 999, title: url, completed: false, userId: 999 }]), 13 | ) 14 | 15 | const getUsersTodos = F.pipe( 16 | [ 17 | "https://jsonplaceholder.typicode.com/users/1/todos", 18 | "https://jsonplaceholder.typicode.com/users/2/todos", 19 | "https://jsonplaceholder.typicode.com/users/3/todos", 20 | "https://jsonplaceholder.typicode.com/users/4/todos", 21 | "https://jsonplaceholder.typicode.com/users/5/todos", 22 | "https://jsonplaceholder.typicode.com/users/6/todos", 23 | ], 24 | ROA.map(getTodos), 25 | // Effect.allWith is data-last variant of `Effect.all` 26 | Effect.allWith({ concurrency: "inherit" }), 27 | // With concurrency "inherit" you can control how much concurrency you want from the top level program 28 | Effect.map(ROA.flatten), 29 | Effect.withConcurrency(2), 30 | // NOTE: If you don't call `withConcurrency`, by default it will be "unbounded" 31 | ) 32 | 33 | runEffect(getUsersTodos).catch(() => { 34 | process.exit(1) 35 | }) 36 | -------------------------------------------------------------------------------- /src/5-parallelism/fp-ts.ts: -------------------------------------------------------------------------------- 1 | import * as F from "fp-ts/function" 2 | import * as TE from "fp-ts/TaskEither" 3 | import * as A from "fp-ts/Array" 4 | import { runTaskEither } from "../utils/fp-ts" 5 | import { batchTraverse } from "fp-ts-contrib/batchTraverse" 6 | import { Todo } from "../domain/fp-ts" 7 | import { delay } from "../utils/promise" 8 | 9 | // https://gcanti.github.io/fp-ts-contrib/modules/batchTraverse.ts.html 10 | const arrayTraverseTE = A.traverse(TE.ApplicativePar) 11 | type TraverseTE = typeof arrayTraverseTE 12 | const batchTraverseTE = batchTraverse(TE.Monad) 13 | 14 | const batchTE = 15 | (batchSize: number): TraverseTE => 16 | (f) => 17 | (array) => 18 | F.pipe(array, A.chunksOf(batchSize), (chunks) => batchTraverseTE(chunks, f)) 19 | 20 | const getTodos = (url: string) => { 21 | console.log(`Fetching ${url} at ${new Date().toLocaleTimeString()}`) 22 | return F.pipe( 23 | TE.tryCatch( 24 | () => delay(3_000), 25 | () => `delay error`, 26 | ), 27 | TE.map((): Todo[] => [{ id: 999, title: url, completed: false, userId: 999 }]), 28 | ) 29 | } 30 | 31 | const batch2 = batchTE(2) 32 | 33 | const getUsersTodos = () => 34 | F.pipe( 35 | [ 36 | "https://jsonplaceholder.typicode.com/users/1/todos", 37 | "https://jsonplaceholder.typicode.com/users/2/todos", 38 | "https://jsonplaceholder.typicode.com/users/3/todos", 39 | "https://jsonplaceholder.typicode.com/users/4/todos", 40 | "https://jsonplaceholder.typicode.com/users/5/todos", 41 | "https://jsonplaceholder.typicode.com/users/6/todos", 42 | ], 43 | batch2(getTodos), 44 | TE.map(A.flatten), 45 | ) 46 | 47 | runTaskEither(getUsersTodos()).catch(() => { 48 | process.exit(1) 49 | }) 50 | -------------------------------------------------------------------------------- /src/6-retries/effect.ts: -------------------------------------------------------------------------------- 1 | import * as F from "effect/Function" 2 | import * as Effect from "effect/Effect" 3 | import * as Duration from "effect/Duration" 4 | import * as Schedule from "effect/Schedule" 5 | import { runEffect } from "../utils/effect" 6 | 7 | const retryPolicy = F.pipe( 8 | // keep new line 9 | Schedule.recurs(4), 10 | Schedule.compose(Schedule.exponential(Duration.millis(200), 2.0)), 11 | Schedule.mapEffect((x) => Effect.log(`Retrying in ${Duration.toMillis(x)} milliseconds...`)), 12 | ) 13 | 14 | const getTodos = F.pipe( 15 | // keep new line 16 | Effect.fail("getTodos failed"), 17 | Effect.delay(Duration.seconds(1)), 18 | ) 19 | 20 | const withRetry = F.pipe( 21 | // keep new line 22 | getTodos, 23 | Effect.retry(retryPolicy), 24 | ) 25 | 26 | runEffect(withRetry).catch(() => { 27 | process.exit(1) 28 | }) 29 | -------------------------------------------------------------------------------- /src/6-retries/fp-ts.ts: -------------------------------------------------------------------------------- 1 | import * as F from "fp-ts/function" 2 | import * as TE from "fp-ts/TaskEither" 3 | import { TaskEither } from "fp-ts/TaskEither" 4 | import * as O from "fp-ts/Option" 5 | import * as E from "fp-ts/Either" 6 | import { capDelay, exponentialBackoff, limitRetries, Monoid, RetryStatus } from "retry-ts" 7 | import { retrying } from "retry-ts/Task" 8 | import { delayTE, runTaskEither } from "../utils/fp-ts" 9 | 10 | const max2sec = 2000 11 | 12 | const policy = capDelay( 13 | // keep new line 14 | max2sec, 15 | Monoid.concat(exponentialBackoff(200), limitRetries(5)), 16 | ) 17 | 18 | const getTodos = delayTE(1000, { fail: true }) 19 | const logRetry = (status: RetryStatus) => 20 | TE.rightIO(() => { 21 | const message = F.pipe( 22 | status.previousDelay, 23 | O.map((delay) => `Retrying in ${delay} milliseconds...`), 24 | O.getOrElse(() => "First run..."), 25 | ) 26 | console.log(message) 27 | }) 28 | 29 | const withRetry = (te: TaskEither) => 30 | retrying( 31 | // keep new line 32 | policy, 33 | (status) => F.pipe(logRetry(status), TE.apSecond(te)), 34 | E.isLeft, 35 | ) 36 | 37 | const getTodosWithRetry = withRetry(getTodos) 38 | 39 | runTaskEither(getTodosWithRetry).catch(() => { 40 | process.exit(1) 41 | }) 42 | -------------------------------------------------------------------------------- /src/7-schema/effect.ts: -------------------------------------------------------------------------------- 1 | import * as F from "effect/Function" 2 | import * as E from "effect/Either" 3 | import * as S from "@effect/schema/Schema" 4 | import { formatErrorSync } from "@effect/schema/TreeFormatter" 5 | import * as PR from "@effect/schema/ParseResult" 6 | 7 | // ********** Branded types ********** 8 | // https://github.com/Effect-TS/schema#branded-types 9 | 10 | const UserId = F.pipe(S.Number, S.brand("UserId")) 11 | type UserId = S.Schema.Type 12 | 13 | // @ts-expect-error 14 | const notAUserId: UserId = 10 15 | 16 | const userId = F.pipe( 17 | S.decodeUnknownEither(UserId)(10), 18 | E.getOrElse((x) => { 19 | throw new Error(`Not a UserID: ${formatErrorSync(x)}`) 20 | }), 21 | ) 22 | console.log("UserId from decode: ", userId) 23 | 24 | // ********** Custom Types ********** 25 | // https://github.com/Effect-TS/schema#transformations 26 | 27 | // NOTE: this type is already available in schema: S.Date 28 | const DateFromString = S.transformOrFail(S.String, S.ValidDateFromSelf, { 29 | decode: (input) => { 30 | const result = Date.parse(input) 31 | return Number.isNaN(result) 32 | ? PR.fail(new PR.Type(S.ValidDateFromSelf.ast, input)) // PR.type means: an error that occurs when the actual value is not of the expected type, in this case is not 'S.DateFromSelf' 33 | : PR.succeed(new Date(result)) 34 | }, 35 | encode: (date) => PR.succeed(date.toISOString()), 36 | }) 37 | type DateFromString = S.Schema.Type 38 | 39 | // NOTE: without branded types you can directly create the underlying type, but it might not be valid 40 | const ctor: DateFromString = new Date("2023-04-32") 41 | console.log("DateFromString constructed manually: ", ctor) 42 | 43 | // Always decode DateFromString to ensure it's actually valid 44 | const dateFromString = F.pipe( 45 | S.decodeUnknownEither(DateFromString)("2023-04-07"), 46 | E.getOrElse((x) => { 47 | throw new Error(`Not a DateFromString: ${formatErrorSync(x)}`) 48 | }), 49 | ) 50 | console.log("DateFromString from decode: ", dateFromString) 51 | 52 | // ********** Annotations ********** 53 | // https://github.com/Effect-TS/schema#annotations 54 | 55 | // https://www.emailregex.com/ 56 | const emailRegex = 57 | /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ 58 | 59 | const Email = F.pipe( 60 | S.String, 61 | S.nonEmpty(), 62 | S.pattern(emailRegex), 63 | S.annotations({ 64 | identifier: "Email", 65 | message: (x) => `Invalid email pattern '${x.actual}'`, 66 | examples: ["info@example.com", "foo.bar@example.co.uk"], 67 | }), 68 | ) 69 | 70 | const invalidEmail = F.pipe( 71 | S.decodeUnknownEither(Email)("any@email"), 72 | E.getOrElse((x) => { 73 | // TODO: make sure identifier and examples are logged 74 | throw new Error(`Parse Error: ${formatErrorSync(x)}`) 75 | }), 76 | ) 77 | console.log("Email decode with annotation: ", invalidEmail) 78 | -------------------------------------------------------------------------------- /src/7-schema/fp-ts.ts: -------------------------------------------------------------------------------- 1 | import * as t from "io-ts" 2 | import { PathReporter } from "io-ts/PathReporter" 3 | import * as F from "fp-ts/function" 4 | import * as E from "fp-ts/Either" 5 | 6 | // ********** Branded types ********** 7 | 8 | interface UserIdBrand { 9 | readonly UserId: unique symbol 10 | } 11 | 12 | const UserId = t.brand(t.number, (x): x is t.Branded => t.Int.is(x), "UserId") 13 | type UserId = t.TypeOf 14 | 15 | // @ts-expect-error 16 | const notAUserId: UserId = 10 17 | 18 | const userId = F.pipe( 19 | UserId.decode(10), 20 | E.getOrElseW((x) => { 21 | const errors = PathReporter.report(E.left(x)).join("\n ") 22 | throw new Error(`Not a UserID: ${errors}`) 23 | }), 24 | ) 25 | console.log("UserId from decode: ", userId) 26 | 27 | // ********** Custom Types ********** 28 | 29 | const DateFromString = new t.Type( 30 | "DateFromString", 31 | (input): input is Date => input instanceof Date, 32 | (input, ctx) => 33 | F.pipe( 34 | t.string.validate(input, ctx), 35 | E.chain((s) => { 36 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse 37 | const result = Date.parse(s) 38 | return Number.isNaN(result) 39 | ? t.failure(input, ctx, `Invalid ISO 8601 datetime: ${s}`) 40 | : t.success(new Date(s)) 41 | }), 42 | ), 43 | (date) => date.toISOString(), 44 | ) 45 | type DateFromString = t.TypeOf 46 | 47 | // NOTE: without branded types you can directly create the underlying type, but it might not be valid 48 | const ctor: DateFromString = new Date("2023-04-32") 49 | console.log("DateFromString constructed manually: ", ctor) 50 | 51 | // Always use DateFromString.decode to ensure it's actually valid 52 | const dateFromString = F.pipe( 53 | DateFromString.decode("2023-04-07"), 54 | E.getOrElseW((x) => { 55 | const errors = PathReporter.report(E.left(x)).join("\n ") 56 | throw new Error(`Not a DateFromString: ${errors}`) 57 | }), 58 | ) 59 | console.log("DateFromString from decode: ", dateFromString) 60 | -------------------------------------------------------------------------------- /src/domain/effect.ts: -------------------------------------------------------------------------------- 1 | import * as S from "@effect/schema/Schema" 2 | 3 | export const Todo = S.Struct({ 4 | userId: S.Number, 5 | id: S.Number, 6 | title: S.String, 7 | completed: S.Boolean, 8 | }) 9 | export interface Todo extends S.Schema.Type {} 10 | 11 | export const Todos = S.Array(Todo) 12 | export interface Todos extends S.Schema.Type {} 13 | 14 | export const User = S.Struct({ 15 | id: S.Number, 16 | name: S.String, 17 | }) 18 | export interface User extends S.Schema.Type {} 19 | -------------------------------------------------------------------------------- /src/domain/fp-ts.ts: -------------------------------------------------------------------------------- 1 | import * as t from "io-ts" 2 | 3 | export const Todo = t.type( 4 | { 5 | userId: t.number, 6 | id: t.number, 7 | title: t.string, 8 | completed: t.boolean, 9 | }, 10 | "Todo", 11 | ) 12 | export type Todo = t.TypeOf 13 | 14 | export const Todos = t.array(Todo, "Todos") 15 | export type Todos = t.TypeOf 16 | 17 | export const User = t.type( 18 | { 19 | id: t.number, 20 | name: t.string, 21 | }, 22 | "User", 23 | ) 24 | export type User = t.TypeOf 25 | -------------------------------------------------------------------------------- /src/utils/effect.ts: -------------------------------------------------------------------------------- 1 | import * as E from "effect/Either" 2 | import * as F from "effect/Function" 3 | import { Either } from "effect/Either" 4 | import * as Effect from "effect/Effect" 5 | import * as S from "@effect/schema/Schema" 6 | import { formatErrorSync } from "@effect/schema/TreeFormatter" 7 | 8 | type Decoder = (a: unknown) => Either 9 | export const decode = 10 | (schema: S.Schema): Decoder => 11 | (input) => { 12 | const parser = S.decodeUnknownEither(schema) 13 | const parsed = parser(input, { 14 | errors: "all", 15 | onExcessProperty: "ignore", 16 | }) 17 | return F.pipe( 18 | parsed, 19 | E.mapLeft((x) => formatErrorSync(x)), 20 | ) 21 | } 22 | 23 | export const runEffect = (e: Effect.Effect) => 24 | Effect.runPromise(e) 25 | .then((x) => { 26 | if (x === null || x === undefined) return 27 | if (typeof x === "object") { 28 | console.log(JSON.stringify(x, null, 2)) 29 | return 30 | } 31 | console.log(x) 32 | }) 33 | .catch((e) => { 34 | console.error("Error!!!\n", e) 35 | throw e 36 | }) 37 | -------------------------------------------------------------------------------- /src/utils/fp-ts.ts: -------------------------------------------------------------------------------- 1 | import * as E from "fp-ts/Either" 2 | import { Either } from "fp-ts/Either" 3 | import * as F from "fp-ts/function" 4 | import { TaskEither } from "fp-ts/TaskEither" 5 | import * as TE from "fp-ts/TaskEither" 6 | import * as t from "io-ts" 7 | import { PathReporter } from "io-ts/PathReporter" 8 | import { delay } from "./promise" 9 | 10 | type Decoder = (a: unknown) => Either 11 | export const decode = (type: t.Type): Decoder => 12 | F.flow( 13 | // keep new line 14 | type.decode, 15 | E.mapLeft((x) => { 16 | const errors = PathReporter.report(E.left(x)).join("\n ") 17 | return `Unable to decode ${type.name}:\n ${errors}` 18 | }), 19 | ) 20 | 21 | type DelayOptions = { 22 | fail?: boolean 23 | } 24 | export const delayTE = (timeout: number, options?: DelayOptions) => 25 | TE.tryCatch( 26 | () => delay(timeout, options?.fail), 27 | (e) => `Failed delayTE: ${e}`, 28 | ) 29 | 30 | export const runTaskEither = async (te: TaskEither) => { 31 | const result = await te() 32 | 33 | if (E.isRight(result)) { 34 | const x = result.right 35 | 36 | if (x === null || x === undefined) return 37 | if (typeof x === "object") { 38 | console.log(JSON.stringify(x, null, 2)) 39 | return 40 | } 41 | console.log(x) 42 | } else { 43 | console.error("Error!!!\n", result.left) 44 | throw result.left 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/utils/promise.ts: -------------------------------------------------------------------------------- 1 | export const delay = (timeout: number, shouldReject?: boolean) => 2 | new Promise((resolve, reject) => { 3 | setTimeout(() => { 4 | if (shouldReject) reject("delay promise is rejected") 5 | resolve(timeout) 6 | }, timeout) 7 | }) 8 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Node 16", 4 | "compilerOptions": { 5 | "lib": [ 6 | "es2022" 7 | ], 8 | "module": "commonjs", 9 | "target": "es2022", 10 | "strict": true, 11 | "esModuleInterop": true, 12 | "skipLibCheck": true, 13 | "forceConsistentCasingInFileNames": true, 14 | "moduleResolution": "node" 15 | }, 16 | "include": ["src/**/*"] 17 | } 18 | -------------------------------------------------------------------------------- /vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitest/config" 2 | 3 | export default defineConfig({ 4 | test: { 5 | // https://vitest.dev/config/ 6 | }, 7 | }) 8 | --------------------------------------------------------------------------------