diff --git a/.lintstagedrc.json b/.lintstagedrc.json index be59f95..c1a949e 100644 --- a/.lintstagedrc.json +++ b/.lintstagedrc.json @@ -1,4 +1,4 @@ { - "*": ["deno fmt"], - "*.ts": ["deno lint"] + "*": ["deno fmt --check"], + "*.ts": ["deno lint --fix"] } diff --git a/.vscode/extensions.json b/.vscode/extensions.json index ce29cb6..9430c79 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -2,8 +2,6 @@ "recommendations": [ "bierner.github-markdown-preview", "bradlc.vscode-tailwindcss", - "dbaeumer.vscode-eslint", - "esbenp.prettier-vscode", "streetsidesoftware.code-spell-checker", "streetsidesoftware.code-spell-checker-spanish", "usernamehw.errorlens", diff --git a/deno.json b/deno.json deleted file mode 100644 index af67ff1..0000000 --- a/deno.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "tasks": { - "dev": "deno run --watch main.ts", - "test": "deno test --watch", - "hook": "deno run --allow-read --allow-run --allow-write https://deno.land/x/deno_hooks@0.1.1/mod.ts" - }, - "workspace": [ - "packages/fabric/core", - "packages/fabric/domain", - "packages/fabric/sqlite-store" - ], - "imports": { - "@std/assert": "jsr:@std/assert@1" - }, - "compilerOptions": { - "strict": true - } -} diff --git a/deno.jsonc b/deno.jsonc new file mode 100644 index 0000000..fd3cfc7 --- /dev/null +++ b/deno.jsonc @@ -0,0 +1,34 @@ +{ + "tasks": { + "test": "deno test --allow-all --unstable-ffi", + "test:dev": "deno test --allow-all --unstable-ffi --watch", + "hook": "deno run --allow-read --allow-run --allow-write https://deno.land/x/deno_hooks@0.1.1/mod.ts" + }, + "workspace": [ + "packages/fabric/core", + "packages/fabric/domain", + "packages/fabric/sqlite-store", + "packages/fabric/testing" + ], + "imports": { + "@db/sqlite": "jsr:@db/sqlite@^0.12.0", + "@quentinadam/decimal": "jsr:@quentinadam/decimal@^0.1.6", + "@std/expect": "jsr:@std/expect@^1.0.5", + "@std/testing": "jsr:@std/testing@^1.0.3", + "expect-type": "npm:expect-type@^1.1.0" + }, + "compilerOptions": { + "strict": true, + "exactOptionalPropertyTypes": true, + "useUnknownInCatchVariables": true, + "noImplicitOverride": true, + "noUncheckedIndexedAccess": true + }, + "lint": { + "include": ["src/"], + "rules": { + "tags": ["recommended"], + "exclude": ["no-namespace"] + } + } +} diff --git a/deno.lock b/deno.lock index 3ca6077..10894f5 100644 --- a/deno.lock +++ b/deno.lock @@ -1,980 +1,138 @@ { "version": "4", "specifiers": { - "jsr:@std/assert@1": "1.0.6", + "jsr:@db/sqlite@*": "0.12.0", + "jsr:@db/sqlite@0.12": "0.12.0", + "jsr:@denosaurs/plug@1": "1.0.6", + "jsr:@quentinadam/assert@~0.1.7": "0.1.7", + "jsr:@quentinadam/decimal@*": "0.1.6", + "jsr:@quentinadam/decimal@~0.1.6": "0.1.6", + "jsr:@std/assert@0.217": "0.217.0", + "jsr:@std/assert@0.221": "0.221.0", + "jsr:@std/assert@^1.0.6": "1.0.6", + "jsr:@std/data-structures@^1.0.4": "1.0.4", + "jsr:@std/encoding@0.221": "0.221.0", + "jsr:@std/expect@*": "1.0.5", + "jsr:@std/expect@^1.0.5": "1.0.5", + "jsr:@std/fmt@0.221": "0.221.0", + "jsr:@std/fs@0.221": "0.221.0", + "jsr:@std/fs@^1.0.4": "1.0.4", "jsr:@std/internal@^1.0.4": "1.0.4", - "npm:@vitest/coverage-v8@^2.1.2": "2.1.3_vitest@2.1.3__@vitest+spy@2.1.3__vite@5.4.9", - "npm:lint-staged@*": "15.2.10", - "npm:typescript@^5.6.3": "5.6.3", - "npm:vitest@*": "2.1.3_@vitest+spy@2.1.3_vite@5.4.9", - "npm:vitest@^2.1.2": "2.1.3_@vitest+spy@2.1.3_vite@5.4.9" + "jsr:@std/path@0.217": "0.217.0", + "jsr:@std/path@0.221": "0.221.0", + "jsr:@std/path@^1.0.6": "1.0.6", + "jsr:@std/testing@^1.0.3": "1.0.3", + "npm:expect-type@*": "1.1.0", + "npm:expect-type@^1.1.0": "1.1.0" }, "jsr": { + "@db/sqlite@0.12.0": { + "integrity": "dd1ef7f621ad50fc1e073a1c3609c4470bd51edc0994139c5bf9851de7a6d85f", + "dependencies": [ + "jsr:@denosaurs/plug", + "jsr:@std/path@0.217" + ] + }, + "@denosaurs/plug@1.0.6": { + "integrity": "6cf5b9daba7799837b9ffbe89f3450510f588fafef8115ddab1ff0be9cb7c1a7", + "dependencies": [ + "jsr:@std/encoding", + "jsr:@std/fmt", + "jsr:@std/fs@0.221", + "jsr:@std/path@0.221" + ] + }, + "@quentinadam/assert@0.1.7": { + "integrity": "0246fb7fd3aa7b286535db40feefdafc588272d3f287b4eb995c96263ab6dfca" + }, + "@quentinadam/decimal@0.1.6": { + "integrity": "fd3e2684614355db8a6ef94a839cbe115f040e8dcc843a17a0c5afa23e3db408", + "dependencies": [ + "jsr:@quentinadam/assert" + ] + }, + "@std/assert@0.217.0": { + "integrity": "c98e279362ca6982d5285c3b89517b757c1e3477ee9f14eb2fdf80a45aaa9642" + }, + "@std/assert@0.221.0": { + "integrity": "a5f1aa6e7909dbea271754fd4ab3f4e687aeff4873b4cef9a320af813adb489a" + }, "@std/assert@1.0.6": { "integrity": "1904c05806a25d94fe791d6d883b685c9e2dcd60e4f9fc30f4fc5cf010c72207", "dependencies": [ "jsr:@std/internal" ] }, + "@std/data-structures@1.0.4": { + "integrity": "fa0e20c11eb9ba673417450915c750a0001405a784e2a4e0c3725031681684a0" + }, + "@std/encoding@0.221.0": { + "integrity": "d1dd76ef0dc5d14088411e6dc1dede53bf8308c95d1537df1214c97137208e45" + }, + "@std/expect@1.0.5": { + "integrity": "8c7ac797e2ffe57becc6399c0f2fd06230cb9ef124d45229c6e592c563824af1", + "dependencies": [ + "jsr:@std/assert@^1.0.6", + "jsr:@std/internal" + ] + }, + "@std/fmt@0.221.0": { + "integrity": "379fed69bdd9731110f26b9085aeb740606b20428ce6af31ef6bd45ef8efa62a" + }, + "@std/fs@0.221.0": { + "integrity": "028044450299de8ed5a716ade4e6d524399f035513b85913794f4e81f07da286", + "dependencies": [ + "jsr:@std/assert@0.221", + "jsr:@std/path@0.221" + ] + }, + "@std/fs@1.0.4": { + "integrity": "2907d32d8d1d9e540588fd5fe0ec21ee638134bd51df327ad4e443aaef07123c", + "dependencies": [ + "jsr:@std/path@^1.0.6" + ] + }, "@std/internal@1.0.4": { "integrity": "62e8e4911527e5e4f307741a795c0b0a9e6958d0b3790716ae71ce085f755422" + }, + "@std/path@0.217.0": { + "integrity": "1217cc25534bca9a2f672d7fe7c6f356e4027df400c0e85c0ef3e4343bc67d11", + "dependencies": [ + "jsr:@std/assert@0.217" + ] + }, + "@std/path@0.221.0": { + "integrity": "0a36f6b17314ef653a3a1649740cc8db51b25a133ecfe838f20b79a56ebe0095", + "dependencies": [ + "jsr:@std/assert@0.221" + ] + }, + "@std/path@1.0.6": { + "integrity": "ab2c55f902b380cf28e0eec501b4906e4c1960d13f00e11cfbcd21de15f18fed" + }, + "@std/testing@1.0.3": { + "integrity": "f98c2bee53860a5916727d7e7d3abe920dd6f9edace022e2d059f00d05c2cf42", + "dependencies": [ + "jsr:@std/assert@^1.0.6", + "jsr:@std/data-structures", + "jsr:@std/fs@^1.0.4", + "jsr:@std/internal", + "jsr:@std/path@^1.0.6" + ] } }, "npm": { - "@ampproject/remapping@2.3.0": { - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dependencies": [ - "@jridgewell/gen-mapping", - "@jridgewell/trace-mapping" - ] - }, - "@babel/helper-string-parser@7.25.7": { - "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==" - }, - "@babel/helper-validator-identifier@7.25.7": { - "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==" - }, - "@babel/parser@7.25.8": { - "integrity": "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==", - "dependencies": [ - "@babel/types" - ] - }, - "@babel/types@7.25.8": { - "integrity": "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==", - "dependencies": [ - "@babel/helper-string-parser", - "@babel/helper-validator-identifier", - "to-fast-properties" - ] - }, - "@bcoe/v8-coverage@0.2.3": { - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" - }, - "@esbuild/aix-ppc64@0.21.5": { - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==" - }, - "@esbuild/android-arm64@0.21.5": { - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==" - }, - "@esbuild/android-arm@0.21.5": { - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==" - }, - "@esbuild/android-x64@0.21.5": { - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==" - }, - "@esbuild/darwin-arm64@0.21.5": { - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==" - }, - "@esbuild/darwin-x64@0.21.5": { - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==" - }, - "@esbuild/freebsd-arm64@0.21.5": { - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==" - }, - "@esbuild/freebsd-x64@0.21.5": { - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==" - }, - "@esbuild/linux-arm64@0.21.5": { - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==" - }, - "@esbuild/linux-arm@0.21.5": { - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==" - }, - "@esbuild/linux-ia32@0.21.5": { - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==" - }, - "@esbuild/linux-loong64@0.21.5": { - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==" - }, - "@esbuild/linux-mips64el@0.21.5": { - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==" - }, - "@esbuild/linux-ppc64@0.21.5": { - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==" - }, - "@esbuild/linux-riscv64@0.21.5": { - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==" - }, - "@esbuild/linux-s390x@0.21.5": { - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==" - }, - "@esbuild/linux-x64@0.21.5": { - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==" - }, - "@esbuild/netbsd-x64@0.21.5": { - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==" - }, - "@esbuild/openbsd-x64@0.21.5": { - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==" - }, - "@esbuild/sunos-x64@0.21.5": { - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==" - }, - "@esbuild/win32-arm64@0.21.5": { - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==" - }, - "@esbuild/win32-ia32@0.21.5": { - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==" - }, - "@esbuild/win32-x64@0.21.5": { - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==" - }, - "@isaacs/cliui@8.0.2": { - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dependencies": [ - "string-width@5.1.2", - "string-width-cjs@npm:string-width@4.2.3", - "strip-ansi@7.1.0", - "strip-ansi-cjs@npm:strip-ansi@6.0.1", - "wrap-ansi@8.1.0", - "wrap-ansi-cjs@npm:wrap-ansi@7.0.0" - ] - }, - "@istanbuljs/schema@0.1.3": { - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==" - }, - "@jridgewell/gen-mapping@0.3.5": { - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dependencies": [ - "@jridgewell/set-array", - "@jridgewell/sourcemap-codec", - "@jridgewell/trace-mapping" - ] - }, - "@jridgewell/resolve-uri@3.1.2": { - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==" - }, - "@jridgewell/set-array@1.2.1": { - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==" - }, - "@jridgewell/sourcemap-codec@1.5.0": { - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" - }, - "@jridgewell/trace-mapping@0.3.25": { - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dependencies": [ - "@jridgewell/resolve-uri", - "@jridgewell/sourcemap-codec" - ] - }, - "@pkgjs/parseargs@0.11.0": { - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==" - }, - "@rollup/rollup-android-arm-eabi@4.24.0": { - "integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==" - }, - "@rollup/rollup-android-arm64@4.24.0": { - "integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==" - }, - "@rollup/rollup-darwin-arm64@4.24.0": { - "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==" - }, - "@rollup/rollup-darwin-x64@4.24.0": { - "integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==" - }, - "@rollup/rollup-linux-arm-gnueabihf@4.24.0": { - "integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==" - }, - "@rollup/rollup-linux-arm-musleabihf@4.24.0": { - "integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==" - }, - "@rollup/rollup-linux-arm64-gnu@4.24.0": { - "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==" - }, - "@rollup/rollup-linux-arm64-musl@4.24.0": { - "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==" - }, - "@rollup/rollup-linux-powerpc64le-gnu@4.24.0": { - "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==" - }, - "@rollup/rollup-linux-riscv64-gnu@4.24.0": { - "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==" - }, - "@rollup/rollup-linux-s390x-gnu@4.24.0": { - "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==" - }, - "@rollup/rollup-linux-x64-gnu@4.24.0": { - "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==" - }, - "@rollup/rollup-linux-x64-musl@4.24.0": { - "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==" - }, - "@rollup/rollup-win32-arm64-msvc@4.24.0": { - "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==" - }, - "@rollup/rollup-win32-ia32-msvc@4.24.0": { - "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==" - }, - "@rollup/rollup-win32-x64-msvc@4.24.0": { - "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==" - }, - "@types/estree@1.0.6": { - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==" - }, - "@vitest/coverage-v8@2.1.3_vitest@2.1.3__@vitest+spy@2.1.3__vite@5.4.9": { - "integrity": "sha512-2OJ3c7UPoFSmBZwqD2VEkUw6A/tzPF0LmW0ZZhhB8PFxuc+9IBG/FaSM+RLEenc7ljzFvGN+G0nGQoZnh7sy2A==", - "dependencies": [ - "@ampproject/remapping", - "@bcoe/v8-coverage", - "debug", - "istanbul-lib-coverage", - "istanbul-lib-report", - "istanbul-lib-source-maps", - "istanbul-reports", - "magic-string", - "magicast", - "std-env", - "test-exclude", - "tinyrainbow", - "vitest" - ] - }, - "@vitest/expect@2.1.3": { - "integrity": "sha512-SNBoPubeCJhZ48agjXruCI57DvxcsivVDdWz+SSsmjTT4QN/DfHk3zB/xKsJqMs26bLZ/pNRLnCf0j679i0uWQ==", - "dependencies": [ - "@vitest/spy", - "@vitest/utils", - "chai", - "tinyrainbow" - ] - }, - "@vitest/mocker@2.1.3_@vitest+spy@2.1.3_vite@5.4.9": { - "integrity": "sha512-eSpdY/eJDuOvuTA3ASzCjdithHa+GIF1L4PqtEELl6Qa3XafdMLBpBlZCIUCX2J+Q6sNmjmxtosAG62fK4BlqQ==", - "dependencies": [ - "@vitest/spy", - "estree-walker", - "magic-string", - "vite" - ] - }, - "@vitest/pretty-format@2.1.3": { - "integrity": "sha512-XH1XdtoLZCpqV59KRbPrIhFCOO0hErxrQCMcvnQete3Vibb9UeIOX02uFPfVn3Z9ZXsq78etlfyhnkmIZSzIwQ==", - "dependencies": [ - "tinyrainbow" - ] - }, - "@vitest/runner@2.1.3": { - "integrity": "sha512-JGzpWqmFJ4fq5ZKHtVO3Xuy1iF2rHGV4d/pdzgkYHm1+gOzNZtqjvyiaDGJytRyMU54qkxpNzCx+PErzJ1/JqQ==", - "dependencies": [ - "@vitest/utils", - "pathe" - ] - }, - "@vitest/snapshot@2.1.3": { - "integrity": "sha512-qWC2mWc7VAXmjAkEKxrScWHWFyCQx/cmiZtuGqMi+WwqQJ2iURsVY4ZfAK6dVo6K2smKRU6l3BPwqEBvhnpQGg==", - "dependencies": [ - "@vitest/pretty-format", - "magic-string", - "pathe" - ] - }, - "@vitest/spy@2.1.3": { - "integrity": "sha512-Nb2UzbcUswzeSP7JksMDaqsI43Sj5+Kry6ry6jQJT4b5gAK+NS9NED6mDb8FlMRCX8m5guaHCDZmqYMMWRy5nQ==", - "dependencies": [ - "tinyspy" - ] - }, - "@vitest/utils@2.1.3": { - "integrity": "sha512-xpiVfDSg1RrYT0tX6czgerkpcKFmFOF/gCr30+Mve5V2kewCy4Prn1/NDMSRwaSmT7PRaOF83wu+bEtsY1wrvA==", - "dependencies": [ - "@vitest/pretty-format", - "loupe", - "tinyrainbow" - ] - }, - "ansi-escapes@7.0.0": { - "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", - "dependencies": [ - "environment" - ] - }, - "ansi-regex@5.0.1": { - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-regex@6.1.0": { - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==" - }, - "ansi-styles@4.3.0": { - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": [ - "color-convert" - ] - }, - "ansi-styles@6.2.1": { - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" - }, - "assertion-error@2.0.1": { - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==" - }, - "balanced-match@1.0.2": { - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "brace-expansion@2.0.1": { - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": [ - "balanced-match" - ] - }, - "braces@3.0.3": { - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dependencies": [ - "fill-range" - ] - }, - "cac@6.7.14": { - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==" - }, - "chai@5.1.1": { - "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==", - "dependencies": [ - "assertion-error", - "check-error", - "deep-eql", - "loupe", - "pathval" - ] - }, - "chalk@5.3.0": { - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==" - }, - "check-error@2.1.1": { - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==" - }, - "cli-cursor@5.0.0": { - "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", - "dependencies": [ - "restore-cursor" - ] - }, - "cli-truncate@4.0.0": { - "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", - "dependencies": [ - "slice-ansi@5.0.0", - "string-width@7.2.0" - ] - }, - "color-convert@2.0.1": { - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": [ - "color-name" - ] - }, - "color-name@1.1.4": { - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "colorette@2.0.20": { - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" - }, - "commander@12.1.0": { - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==" - }, - "cross-spawn@7.0.3": { - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dependencies": [ - "path-key@3.1.1", - "shebang-command", - "which" - ] - }, - "debug@4.3.7": { - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dependencies": [ - "ms" - ] - }, - "deep-eql@5.0.2": { - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==" - }, - "eastasianwidth@0.2.0": { - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" - }, - "emoji-regex@10.4.0": { - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==" - }, - "emoji-regex@8.0.0": { - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "emoji-regex@9.2.2": { - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "environment@1.1.0": { - "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==" - }, - "esbuild@0.21.5": { - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dependencies": [ - "@esbuild/aix-ppc64", - "@esbuild/android-arm", - "@esbuild/android-arm64", - "@esbuild/android-x64", - "@esbuild/darwin-arm64", - "@esbuild/darwin-x64", - "@esbuild/freebsd-arm64", - "@esbuild/freebsd-x64", - "@esbuild/linux-arm", - "@esbuild/linux-arm64", - "@esbuild/linux-ia32", - "@esbuild/linux-loong64", - "@esbuild/linux-mips64el", - "@esbuild/linux-ppc64", - "@esbuild/linux-riscv64", - "@esbuild/linux-s390x", - "@esbuild/linux-x64", - "@esbuild/netbsd-x64", - "@esbuild/openbsd-x64", - "@esbuild/sunos-x64", - "@esbuild/win32-arm64", - "@esbuild/win32-ia32", - "@esbuild/win32-x64" - ] - }, - "estree-walker@3.0.3": { - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dependencies": [ - "@types/estree" - ] - }, - "eventemitter3@5.0.1": { - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" - }, - "execa@8.0.1": { - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dependencies": [ - "cross-spawn", - "get-stream", - "human-signals", - "is-stream", - "merge-stream", - "npm-run-path", - "onetime@6.0.0", - "signal-exit", - "strip-final-newline" - ] - }, - "fill-range@7.1.1": { - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dependencies": [ - "to-regex-range" - ] - }, - "foreground-child@3.3.0": { - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", - "dependencies": [ - "cross-spawn", - "signal-exit" - ] - }, - "fsevents@2.3.3": { - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==" - }, - "get-east-asian-width@1.3.0": { - "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==" - }, - "get-stream@8.0.1": { - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==" - }, - "glob@10.4.5": { - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dependencies": [ - "foreground-child", - "jackspeak", - "minimatch", - "minipass", - "package-json-from-dist", - "path-scurry" - ] - }, - "has-flag@4.0.0": { - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "html-escaper@2.0.2": { - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==" - }, - "human-signals@5.0.0": { - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==" - }, - "is-fullwidth-code-point@3.0.0": { - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "is-fullwidth-code-point@4.0.0": { - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==" - }, - "is-fullwidth-code-point@5.0.0": { - "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", - "dependencies": [ - "get-east-asian-width" - ] - }, - "is-number@7.0.0": { - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "is-stream@3.0.0": { - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==" - }, - "isexe@2.0.0": { - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "istanbul-lib-coverage@3.2.2": { - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==" - }, - "istanbul-lib-report@3.0.1": { - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dependencies": [ - "istanbul-lib-coverage", - "make-dir", - "supports-color" - ] - }, - "istanbul-lib-source-maps@5.0.6": { - "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", - "dependencies": [ - "@jridgewell/trace-mapping", - "debug", - "istanbul-lib-coverage" - ] - }, - "istanbul-reports@3.1.7": { - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", - "dependencies": [ - "html-escaper", - "istanbul-lib-report" - ] - }, - "jackspeak@3.4.3": { - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dependencies": [ - "@isaacs/cliui", - "@pkgjs/parseargs" - ] - }, - "lilconfig@3.1.2": { - "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==" - }, - "lint-staged@15.2.10": { - "integrity": "sha512-5dY5t743e1byO19P9I4b3x8HJwalIznL5E1FWYnU6OWw33KxNBSLAc6Cy7F2PsFEO8FKnLwjwm5hx7aMF0jzZg==", - "dependencies": [ - "chalk", - "commander", - "debug", - "execa", - "lilconfig", - "listr2", - "micromatch", - "pidtree", - "string-argv", - "yaml" - ] - }, - "listr2@8.2.5": { - "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", - "dependencies": [ - "cli-truncate", - "colorette", - "eventemitter3", - "log-update", - "rfdc", - "wrap-ansi@9.0.0" - ] - }, - "log-update@6.1.0": { - "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", - "dependencies": [ - "ansi-escapes", - "cli-cursor", - "slice-ansi@7.1.0", - "strip-ansi@7.1.0", - "wrap-ansi@9.0.0" - ] - }, - "loupe@3.1.2": { - "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==" - }, - "lru-cache@10.4.3": { - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" - }, - "magic-string@0.30.12": { - "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", - "dependencies": [ - "@jridgewell/sourcemap-codec" - ] - }, - "magicast@0.3.5": { - "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", - "dependencies": [ - "@babel/parser", - "@babel/types", - "source-map-js" - ] - }, - "make-dir@4.0.0": { - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dependencies": [ - "semver" - ] - }, - "merge-stream@2.0.0": { - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" - }, - "micromatch@4.0.8": { - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dependencies": [ - "braces", - "picomatch" - ] - }, - "mimic-fn@4.0.0": { - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==" - }, - "mimic-function@5.0.1": { - "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==" - }, - "minimatch@9.0.5": { - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dependencies": [ - "brace-expansion" - ] - }, - "minipass@7.1.2": { - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==" - }, - "ms@2.1.3": { - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "nanoid@3.3.7": { - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==" - }, - "npm-run-path@5.3.0": { - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dependencies": [ - "path-key@4.0.0" - ] - }, - "onetime@6.0.0": { - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dependencies": [ - "mimic-fn" - ] - }, - "onetime@7.0.0": { - "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", - "dependencies": [ - "mimic-function" - ] - }, - "package-json-from-dist@1.0.1": { - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" - }, - "path-key@3.1.1": { - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" - }, - "path-key@4.0.0": { - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==" - }, - "path-scurry@1.11.1": { - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dependencies": [ - "lru-cache", - "minipass" - ] - }, - "pathe@1.1.2": { - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==" - }, - "pathval@2.0.0": { - "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==" - }, - "picocolors@1.1.0": { - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" - }, - "picomatch@2.3.1": { - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" - }, - "pidtree@0.6.0": { - "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==" - }, - "postcss@8.4.47": { - "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", - "dependencies": [ - "nanoid", - "picocolors", - "source-map-js" - ] - }, - "restore-cursor@5.1.0": { - "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", - "dependencies": [ - "onetime@7.0.0", - "signal-exit" - ] - }, - "rfdc@1.4.1": { - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==" - }, - "rollup@4.24.0": { - "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==", - "dependencies": [ - "@rollup/rollup-android-arm-eabi", - "@rollup/rollup-android-arm64", - "@rollup/rollup-darwin-arm64", - "@rollup/rollup-darwin-x64", - "@rollup/rollup-linux-arm-gnueabihf", - "@rollup/rollup-linux-arm-musleabihf", - "@rollup/rollup-linux-arm64-gnu", - "@rollup/rollup-linux-arm64-musl", - "@rollup/rollup-linux-powerpc64le-gnu", - "@rollup/rollup-linux-riscv64-gnu", - "@rollup/rollup-linux-s390x-gnu", - "@rollup/rollup-linux-x64-gnu", - "@rollup/rollup-linux-x64-musl", - "@rollup/rollup-win32-arm64-msvc", - "@rollup/rollup-win32-ia32-msvc", - "@rollup/rollup-win32-x64-msvc", - "@types/estree", - "fsevents" - ] - }, - "semver@7.6.3": { - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==" - }, - "shebang-command@2.0.0": { - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dependencies": [ - "shebang-regex" - ] - }, - "shebang-regex@3.0.0": { - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - }, - "siginfo@2.0.0": { - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==" - }, - "signal-exit@4.1.0": { - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" - }, - "slice-ansi@5.0.0": { - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dependencies": [ - "ansi-styles@6.2.1", - "is-fullwidth-code-point@4.0.0" - ] - }, - "slice-ansi@7.1.0": { - "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", - "dependencies": [ - "ansi-styles@6.2.1", - "is-fullwidth-code-point@5.0.0" - ] - }, - "source-map-js@1.2.1": { - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==" - }, - "stackback@0.0.2": { - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==" - }, - "std-env@3.7.0": { - "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==" - }, - "string-argv@0.3.2": { - "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==" - }, - "string-width@4.2.3": { - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": [ - "emoji-regex@8.0.0", - "is-fullwidth-code-point@3.0.0", - "strip-ansi@6.0.1" - ] - }, - "string-width@5.1.2": { - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dependencies": [ - "eastasianwidth", - "emoji-regex@9.2.2", - "strip-ansi@7.1.0" - ] - }, - "string-width@7.2.0": { - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dependencies": [ - "emoji-regex@10.4.0", - "get-east-asian-width", - "strip-ansi@7.1.0" - ] - }, - "strip-ansi@6.0.1": { - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": [ - "ansi-regex@5.0.1" - ] - }, - "strip-ansi@7.1.0": { - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dependencies": [ - "ansi-regex@6.1.0" - ] - }, - "strip-final-newline@3.0.0": { - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==" - }, - "supports-color@7.2.0": { - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": [ - "has-flag" - ] - }, - "test-exclude@7.0.1": { - "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", - "dependencies": [ - "@istanbuljs/schema", - "glob", - "minimatch" - ] - }, - "tinybench@2.9.0": { - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==" - }, - "tinyexec@0.3.0": { - "integrity": "sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==" - }, - "tinypool@1.0.1": { - "integrity": "sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==" - }, - "tinyrainbow@1.2.0": { - "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==" - }, - "tinyspy@3.0.2": { - "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==" - }, - "to-fast-properties@2.0.0": { - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==" - }, - "to-regex-range@5.0.1": { - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dependencies": [ - "is-number" - ] - }, - "typescript@5.6.3": { - "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==" - }, - "vite-node@2.1.3": { - "integrity": "sha512-I1JadzO+xYX887S39Do+paRePCKoiDrWRRjp9kkG5he0t7RXNvPAJPCQSJqbGN4uCrFFeS3Kj3sLqY8NMYBEdA==", - "dependencies": [ - "cac", - "debug", - "pathe", - "vite" - ] - }, - "vite@5.4.9": { - "integrity": "sha512-20OVpJHh0PAM0oSOELa5GaZNWeDjcAvQjGXy2Uyr+Tp+/D2/Hdz6NLgpJLsarPTA2QJ6v8mX2P1ZfbsSKvdMkg==", - "dependencies": [ - "esbuild", - "fsevents", - "postcss", - "rollup" - ] - }, - "vitest@2.1.3_@vitest+spy@2.1.3_vite@5.4.9": { - "integrity": "sha512-Zrxbg/WiIvUP2uEzelDNTXmEMJXuzJ1kCpbDvaKByFA9MNeO95V+7r/3ti0qzJzrxdyuUw5VduN7k+D3VmVOSA==", - "dependencies": [ - "@vitest/expect", - "@vitest/mocker", - "@vitest/pretty-format", - "@vitest/runner", - "@vitest/snapshot", - "@vitest/spy", - "@vitest/utils", - "chai", - "debug", - "magic-string", - "pathe", - "std-env", - "tinybench", - "tinyexec", - "tinypool", - "tinyrainbow", - "vite", - "vite-node", - "why-is-node-running" - ] - }, - "which@2.0.2": { - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dependencies": [ - "isexe" - ] - }, - "why-is-node-running@2.3.0": { - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", - "dependencies": [ - "siginfo", - "stackback" - ] - }, - "wrap-ansi@7.0.0": { - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": [ - "ansi-styles@4.3.0", - "string-width@4.2.3", - "strip-ansi@6.0.1" - ] - }, - "wrap-ansi@8.1.0": { - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dependencies": [ - "ansi-styles@6.2.1", - "string-width@5.1.2", - "strip-ansi@7.1.0" - ] - }, - "wrap-ansi@9.0.0": { - "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", - "dependencies": [ - "ansi-styles@6.2.1", - "string-width@7.2.0", - "strip-ansi@7.1.0" - ] - }, - "yaml@2.5.1": { - "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==" + "expect-type@1.1.0": { + "integrity": "sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==" } }, "workspace": { "dependencies": [ - "jsr:@std/assert@1" - ], - "members": { - "packages/fabric/core": { - "packageJson": { - "dependencies": [ - "npm:@vitest/coverage-v8@^2.1.2", - "npm:typescript@^5.6.3", - "npm:vitest@^2.1.2" - ] - } - }, - "packages/fabric/domain": { - "packageJson": { - "dependencies": [ - "npm:@vitest/coverage-v8@^2.1.2", - "npm:decimal.js@^10.4.3", - "npm:typescript@^5.6.3", - "npm:vitest@^2.1.2" - ] - } - }, - "packages/fabric/sqlite-store": { - "packageJson": { - "dependencies": [ - "npm:@vitest/coverage-v8@^2.1.2", - "npm:sqlite3@^5.1.7", - "npm:typescript@^5.6.3", - "npm:vitest@^2.1.2" - ] - } - } - } + "jsr:@db/sqlite@0.12", + "jsr:@quentinadam/decimal@~0.1.6", + "jsr:@std/expect@^1.0.5", + "jsr:@std/testing@^1.0.3", + "npm:expect-type@^1.1.0" + ] } } diff --git a/eslint.config.js b/eslint.config.js deleted file mode 100644 index 7acab71..0000000 --- a/eslint.config.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check - -import eslint from "@eslint/js"; -import tseslint from "typescript-eslint"; - -export default tseslint.config( - eslint.configs.recommended, - ...tseslint.configs.strict, - ...tseslint.configs.stylistic, - { - rules: { - "@typescript-eslint/no-namespace": "off", - }, - }, -); diff --git a/packages/fabric/core/deno.jsonc b/packages/fabric/core/deno.jsonc new file mode 100644 index 0000000..97e3b90 --- /dev/null +++ b/packages/fabric/core/deno.jsonc @@ -0,0 +1,6 @@ +{ + "name": "@fabric/core", + "exports": { + ".": "./src/index.ts" + } +} diff --git a/packages/fabric/core/package.json b/packages/fabric/core/package.json deleted file mode 100644 index 4c1e33b..0000000 --- a/packages/fabric/core/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@fabric/core", - "private": true, - "sideEffects": false, - "type": "module", - "main": "./dist/index.js", - "types": "./dist/index.d.ts", - "exports": { - ".": "./dist/index.js" - }, - "files": [ - "dist" - ], - "packageManager": "yarn@4.1.1", - "devDependencies": { - "@vitest/coverage-v8": "^2.1.2", - "typescript": "^5.6.3", - "vitest": "^2.1.2" - }, - "scripts": { - "test": "vitest", - "coverage": "vitest run --coverage", - "build": "tsc -p tsconfig.build.json" - } -} diff --git a/packages/fabric/core/src/array/array-element.spec.ts b/packages/fabric/core/src/array/array-element.test.ts similarity index 50% rename from packages/fabric/core/src/array/array-element.spec.ts rename to packages/fabric/core/src/array/array-element.test.ts index d345bd4..ef4fc1b 100644 --- a/packages/fabric/core/src/array/array-element.spec.ts +++ b/packages/fabric/core/src/array/array-element.test.ts @@ -1,10 +1,8 @@ -import { describe, expectTypeOf, test } from "vitest"; +import { describe, expectTypeOf, test } from "@fabric/testing"; +import type { ArrayElement } from "./array-element.ts"; -describe("ArrayElement utils", () => { +describe("ArrayElement", () => { test("Given an array, it should return the element type of the array", () => { - type ArrayElement = - T extends readonly (infer U)[] ? U : never; - type result = ArrayElement<["a", "b", "c"]>; expectTypeOf().toEqualTypeOf<"a" | "b" | "c">(); diff --git a/packages/fabric/core/src/array/index.ts b/packages/fabric/core/src/array/index.ts index 9062f34..d4037d3 100644 --- a/packages/fabric/core/src/array/index.ts +++ b/packages/fabric/core/src/array/index.ts @@ -1 +1 @@ -export * from "./array-element.js"; +export * from "./array-element.ts"; diff --git a/packages/fabric/core/src/error/index.ts b/packages/fabric/core/src/error/index.ts index 5d2ab53..141de8a 100644 --- a/packages/fabric/core/src/error/index.ts +++ b/packages/fabric/core/src/error/index.ts @@ -1,3 +1,3 @@ -export * from "./is-error.js"; -export * from "./tagged-error.js"; -export * from "./unexpected-error.js"; +export * from "./is-error.ts"; +export * from "./tagged-error.ts"; +export * from "./unexpected-error.ts"; diff --git a/packages/fabric/core/src/error/is-error.spec.ts b/packages/fabric/core/src/error/is-error.spec.ts deleted file mode 100644 index 63af83d..0000000 --- a/packages/fabric/core/src/error/is-error.spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { describe, expect, expectTypeOf, it } from "vitest"; -import { Result } from "../result/result.js"; -import { isError } from "./is-error.js"; -import { TaggedError } from "./tagged-error.js"; - -describe("is-error", () => { - it("should determine if a value is an error", () => { - type DemoResult = Result>; - - //Ok should not be an error - const ok: DemoResult = 42; - expect(isError(ok)).toBe(false); - - //Error should be an error - const error: DemoResult = new TaggedError("DemoError"); - expect(isError(error)).toBe(true); - - //After a check, typescript should be able to infer the type - if (isError(error)) { - expectTypeOf(error).toEqualTypeOf>(); - } - }); -}); diff --git a/packages/fabric/core/src/error/is-error.test.ts b/packages/fabric/core/src/error/is-error.test.ts new file mode 100644 index 0000000..9fd68cd --- /dev/null +++ b/packages/fabric/core/src/error/is-error.test.ts @@ -0,0 +1,16 @@ +import { describe, expect, expectTypeOf, test } from "@fabric/testing"; +import { isError } from "./is-error.ts"; +import { UnexpectedError } from "./unexpected-error.ts"; + +describe("is-error", () => { + test("Given a value that is an error, it should return true", () => { + const error = new UnexpectedError(); + + expect(isError(error)).toBe(true); + + //After a check, typescript should be able to infer the type + if (isError(error)) { + expectTypeOf(error).toEqualTypeOf(); + } + }); +}); diff --git a/packages/fabric/core/src/error/is-error.ts b/packages/fabric/core/src/error/is-error.ts index 1dda468..cad8735 100644 --- a/packages/fabric/core/src/error/is-error.ts +++ b/packages/fabric/core/src/error/is-error.ts @@ -1,4 +1,4 @@ -import { TaggedError } from "./tagged-error.js"; +import { TaggedError } from "./tagged-error.ts"; /** * Indicates if a value is an error. diff --git a/packages/fabric/core/src/error/tagged-error.ts b/packages/fabric/core/src/error/tagged-error.ts index c01f0bf..5c26f9e 100644 --- a/packages/fabric/core/src/error/tagged-error.ts +++ b/packages/fabric/core/src/error/tagged-error.ts @@ -1,4 +1,4 @@ -import { TaggedVariant, VariantTag } from "../variant/index.js"; +import { type TaggedVariant, VariantTag } from "../variant/index.ts"; /** * A TaggedError is a tagged variant with an error message. diff --git a/packages/fabric/core/src/error/unexpected-error.ts b/packages/fabric/core/src/error/unexpected-error.ts index a9ee30f..a05ee44 100644 --- a/packages/fabric/core/src/error/unexpected-error.ts +++ b/packages/fabric/core/src/error/unexpected-error.ts @@ -1,4 +1,4 @@ -import { TaggedError } from "./tagged-error.js"; +import { TaggedError } from "./tagged-error.ts"; /** * `UnexpectedError` represents any type of unexpected error. diff --git a/packages/fabric/core/src/index.ts b/packages/fabric/core/src/index.ts index 8baf34e..ad77c14 100644 --- a/packages/fabric/core/src/index.ts +++ b/packages/fabric/core/src/index.ts @@ -1,9 +1,9 @@ -export * from "./array/index.js"; -export * from "./error/index.js"; -export * from "./record/index.js"; -export * from "./result/index.js"; -export * from "./run/index.js"; -export * from "./time/index.js"; -export * from "./types/index.js"; -export * from "./utils/index.js"; -export * from "./variant/index.js"; +export * from "./array/index.ts"; +export * from "./error/index.ts"; +export * from "./record/index.ts"; +export * from "./result/index.ts"; +export * from "./run/index.ts"; +export * from "./time/index.ts"; +export * from "./types/index.ts"; +export * from "./utils/index.ts"; +export * from "./variant/index.ts"; diff --git a/packages/fabric/core/src/record/index.ts b/packages/fabric/core/src/record/index.ts index 5a27eb7..06c2d32 100644 --- a/packages/fabric/core/src/record/index.ts +++ b/packages/fabric/core/src/record/index.ts @@ -1,2 +1,2 @@ -export * from "./is-record-empty.js"; -export * from "./is-record.js"; +export * from "./is-record-empty.ts"; +export * from "./is-record.ts"; diff --git a/packages/fabric/core/src/record/is-record-empty.spec.ts b/packages/fabric/core/src/record/is-record-empty.spec.ts deleted file mode 100644 index 02bb488..0000000 --- a/packages/fabric/core/src/record/is-record-empty.spec.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { isRecordEmpty } from "./is-record-empty.js"; - -describe("Record - Is Record Empty", () => { - it("should return true for an empty record", () => { - const result = isRecordEmpty({}); - expect(result).toBe(true); - }); - - it("should return false for a non-empty record", () => { - const result = isRecordEmpty({ key: "value" }); - expect(result).toBe(false); - }); - - it("should return false for a record with multiple keys", () => { - const result = isRecordEmpty({ key1: "value1", key2: "value2" }); - expect(result).toBe(false); - }); -}); diff --git a/packages/fabric/core/src/record/is-record-empty.test.ts b/packages/fabric/core/src/record/is-record-empty.test.ts new file mode 100644 index 0000000..dd15207 --- /dev/null +++ b/packages/fabric/core/src/record/is-record-empty.test.ts @@ -0,0 +1,19 @@ +import { describe, expect, test } from "@fabric/testing"; +import { isRecordEmpty } from "./is-record-empty.ts"; + +describe("Record - Is Record Empty", () => { + test("Given an empty record, it should return true", () => { + const result = isRecordEmpty({}); + expect(result).toBe(true); + }); + + test("Given a record with a single key, it should return false", () => { + const result = isRecordEmpty({ key: "value" }); + expect(result).toBe(false); + }); + + test("Given a record with multiple keys, it should return false", () => { + const result = isRecordEmpty({ key1: "value1", key2: "value2" }); + expect(result).toBe(false); + }); +}); diff --git a/packages/fabric/core/src/record/is-record.spec.ts b/packages/fabric/core/src/record/is-record.test.ts similarity index 50% rename from packages/fabric/core/src/record/is-record.spec.ts rename to packages/fabric/core/src/record/is-record.test.ts index 8b84a95..b37fba2 100644 --- a/packages/fabric/core/src/record/is-record.spec.ts +++ b/packages/fabric/core/src/record/is-record.test.ts @@ -1,23 +1,23 @@ -import { describe, expect, it } from "vitest"; -import { isRecord } from "./is-record.js"; +import { describe, expect, test } from "@fabric/testing"; +import { isRecord } from "./is-record.ts"; describe("isRecord", () => { - it("should return true for an object", () => { + test("Given an empty object, it should return true", () => { const obj = { name: "John", age: 30 }; expect(isRecord(obj)).toBe(true); }); - it("should return false for an array", () => { + test("Given an array, it should return false", () => { const arr = [1, 2, 3]; expect(isRecord(arr)).toBe(false); }); - it("should return false for null", () => { + test("Given a number, it should return false", () => { const value = null; expect(isRecord(value)).toBe(false); }); - it("should return false for a string", () => { + test("Given a string, it should return false", () => { const value = "Hello"; expect(isRecord(value)).toBe(false); }); diff --git a/packages/fabric/core/src/result/async-result.ts b/packages/fabric/core/src/result/async-result.ts index 266bedf..82b35da 100644 --- a/packages/fabric/core/src/result/async-result.ts +++ b/packages/fabric/core/src/result/async-result.ts @@ -1,8 +1,8 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { TaggedError } from "../error/tagged-error.js"; -import { UnexpectedError } from "../error/unexpected-error.js"; -import { MaybePromise } from "../types/maybe-promise.js"; -import { Result } from "./result.js"; +// deno-lint-ignore-file no-namespace no-explicit-any +import type { TaggedError } from "../error/tagged-error.ts"; +import { UnexpectedError } from "../error/unexpected-error.ts"; +import type { MaybePromise } from "../types/maybe-promise.ts"; +import { Result } from "./result.ts"; /** * An AsyncResult represents the result of an asynchronous operation that can @@ -10,13 +10,13 @@ import { Result } from "./result.js"; */ export type AsyncResult< TValue = any, - TError extends TaggedError = never, + TError extends TaggedError = never > = Promise>; export namespace AsyncResult { export async function tryFrom( fn: () => MaybePromise, - errorMapper: (error: any) => TError, + errorMapper: (error: any) => TError ): AsyncResult { try { return Result.succeedWith(await fn()); @@ -25,9 +25,7 @@ export namespace AsyncResult { } } - export async function from( - fn: () => MaybePromise, - ): AsyncResult { + export function from(fn: () => MaybePromise): AsyncResult { return tryFrom(fn, (error) => new UnexpectedError(error) as never); } } diff --git a/packages/fabric/core/src/result/index.ts b/packages/fabric/core/src/result/index.ts index fed60c7..d7ad8f3 100644 --- a/packages/fabric/core/src/result/index.ts +++ b/packages/fabric/core/src/result/index.ts @@ -1,2 +1,2 @@ -export * from "./async-result.js"; -export * from "./result.js"; +export * from "./async-result.ts"; +export * from "./result.ts"; diff --git a/packages/fabric/core/src/result/result.spec.ts b/packages/fabric/core/src/result/result.test.ts similarity index 67% rename from packages/fabric/core/src/result/result.spec.ts rename to packages/fabric/core/src/result/result.test.ts index 5628f2c..b9dc0e7 100644 --- a/packages/fabric/core/src/result/result.spec.ts +++ b/packages/fabric/core/src/result/result.test.ts @@ -1,10 +1,10 @@ -import { describe, expect, expectTypeOf, it, vitest } from "vitest"; -import { UnexpectedError } from "../error/unexpected-error.js"; -import { Result } from "./result.js"; +import { describe, expect, expectTypeOf, fn, test } from "@fabric/testing"; +import { UnexpectedError } from "../error/unexpected-error.ts"; +import { Result } from "./result.ts"; describe("Result", () => { describe("isOk", () => { - it("should return true if the result is ok", () => { + test("should return true if the result is ok", () => { const result = Result.succeedWith(1) as Result; expect(result.isOk()).toBe(true); @@ -18,7 +18,7 @@ describe("Result", () => { }); describe("isError", () => { - it("should return true if the result is an error", () => { + test("should return true if the result is an error", () => { const result = Result.failWith(new UnexpectedError()) as Result< number, UnexpectedError @@ -35,7 +35,7 @@ describe("Result", () => { }); describe("Map", () => { - it("should return the result of the last function", () => { + test("should return the result of the last function", () => { const x = 0; const result = Result.succeedWith(x + 1).map((x) => x * 2); @@ -45,13 +45,13 @@ describe("Result", () => { expectTypeOf(result).toEqualTypeOf>(); }); - it("should not execute the function if the result is an error", () => { - const fn = vitest.fn(); - const result = Result.failWith(new UnexpectedError()).map(fn); + test("should not execute the function if the result is an error", () => { + const mock = fn() as () => number; + const result = Result.failWith(new UnexpectedError()).map(mock); expect(result.isError()).toBe(true); - expect(fn).not.toHaveBeenCalled(); + expect(mock).not.toHaveBeenCalled(); }); }); }); diff --git a/packages/fabric/core/src/result/result.ts b/packages/fabric/core/src/result/result.ts index 72e25a2..da51cca 100644 --- a/packages/fabric/core/src/result/result.ts +++ b/packages/fabric/core/src/result/result.ts @@ -1,7 +1,7 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ +// deno-lint-ignore-file no-explicit-any -import { isError } from "../error/is-error.js"; -import { TaggedError } from "../error/tagged-error.js"; +import { isError } from "../error/is-error.ts"; +import type { TaggedError } from "../error/tagged-error.ts"; /** * A Result represents the outcome of an operation @@ -24,7 +24,7 @@ export class Result { static tryFrom( fn: () => T, - errorMapper: (error: any) => TError, + errorMapper: (error: any) => TError ): Result { try { return Result.succeedWith(fn()); @@ -83,7 +83,7 @@ export class Result { * Map a function over the value of the result. */ map( - fn: (value: TValue) => TMappedValue, + fn: (value: TValue) => TMappedValue ): Result { if (!isError(this.value)) { return Result.succeedWith(fn(this.value as TValue)); @@ -96,7 +96,7 @@ export class Result { * Maps a function over the value of the result and flattens the result. */ flatMap( - fn: (value: TValue) => Result, + fn: (value: TValue) => Result ): Result { if (!isError(this.value)) { return fn(this.value as TValue) as any; @@ -111,7 +111,7 @@ export class Result { */ tryMap( fn: (value: TValue) => TMappedValue, - errMapper: (error: any) => TError, + errMapper: (error: any) => TError ): Result { if (!isError(this.value)) { try { @@ -128,7 +128,7 @@ export class Result { * Map a function over the error of the result. */ mapError( - fn: (error: TError) => TMappedError, + fn: (error: TError) => TMappedError ): Result { if (isError(this.value)) { return Result.failWith(fn(this.value as TError)); diff --git a/packages/fabric/core/src/run/index.ts b/packages/fabric/core/src/run/index.ts index 2392331..02f2ab7 100644 --- a/packages/fabric/core/src/run/index.ts +++ b/packages/fabric/core/src/run/index.ts @@ -1 +1 @@ -export * from "./run.js"; +export * from "./run.ts"; diff --git a/packages/fabric/core/src/run/run.spec.ts b/packages/fabric/core/src/run/run.spec.ts deleted file mode 100644 index a573da7..0000000 --- a/packages/fabric/core/src/run/run.spec.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { UnexpectedError } from "../error/unexpected-error.js"; -import { Result } from "../result/result.js"; -import { Run } from "./run.js"; - -describe("Run", () => { - describe("In Sequence", () => { - it("should pipe the results of multiple async functions", async () => { - const result = await Run.seq( - async () => Result.succeedWith(1), - async (x) => Result.succeedWith(x + 1), - async (x) => Result.succeedWith(x * 2), - ); - - expect(result.unwrapOrThrow()).toEqual(4); - }); - - it("should return the first error if one of the functions fails", async () => { - const result = await Run.seq( - async () => Result.succeedWith(1), - async () => Result.failWith(new UnexpectedError()), - async (x) => Result.succeedWith(x * 2), - ); - - expect(result.isError()).toBe(true); - }); - }); -}); diff --git a/packages/fabric/core/src/run/run.test.ts b/packages/fabric/core/src/run/run.test.ts new file mode 100644 index 0000000..fc03d1e --- /dev/null +++ b/packages/fabric/core/src/run/run.test.ts @@ -0,0 +1,29 @@ +// deno-lint-ignore-file require-await +import { describe, expect, test } from "@fabric/testing"; +import { UnexpectedError } from "../error/unexpected-error.ts"; +import { Result } from "../result/result.ts"; +import { Run } from "./run.ts"; + +describe("Run", () => { + describe("In Sequence", () => { + test("should pipe the results of multiple async functions", async () => { + const result = await Run.seq( + async () => Result.succeedWith(1), + async (x) => Result.succeedWith(x + 1), + async (x) => Result.succeedWith(x * 2) + ); + + expect(result.unwrapOrThrow()).toEqual(4); + }); + + test("should return the first error if one of the functions fails", async () => { + const result = await Run.seq( + async () => Result.succeedWith(1), + async () => Result.failWith(new UnexpectedError()), + async (x) => Result.succeedWith(x * 2) + ); + + expect(result.isError()).toBe(true); + }); + }); +}); diff --git a/packages/fabric/core/src/run/run.ts b/packages/fabric/core/src/run/run.ts index 6935632..462332f 100644 --- a/packages/fabric/core/src/run/run.ts +++ b/packages/fabric/core/src/run/run.ts @@ -1,6 +1,6 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { TaggedError } from "../error/tagged-error.js"; -import { AsyncResult } from "../result/async-result.js"; +// deno-lint-ignore-file no-namespace no-explicit-any +import type { TaggedError } from "../error/tagged-error.ts"; +import type { AsyncResult } from "../result/async-result.ts"; export namespace Run { // prettier-ignore @@ -36,14 +36,14 @@ export namespace Run { export async function seq( ...fns: ((...args: any[]) => AsyncResult)[] ): AsyncResult { - let result = await fns[0](); + let result = await fns[0]!(); for (let i = 1; i < fns.length; i++) { if (result.isError()) { return result; } - result = await fns[i](result.unwrapOrThrow()); + result = await fns[i]!(result.unwrapOrThrow()); } return result; @@ -80,7 +80,7 @@ export namespace Run { } export async function UNSAFE( - fn: () => AsyncResult, + fn: () => AsyncResult ): Promise { return (await fn()).unwrapOrThrow(); } diff --git a/packages/fabric/core/src/time/index.ts b/packages/fabric/core/src/time/index.ts index 420f025..e567ae5 100644 --- a/packages/fabric/core/src/time/index.ts +++ b/packages/fabric/core/src/time/index.ts @@ -1,3 +1,2 @@ -export * from "./posix-date.js"; -export * from "./time-constants.js"; -export * from "./timeout.js"; +export * from "./posix-date.ts"; +export * from "./time-constants.ts"; diff --git a/packages/fabric/core/src/time/posix-date.ts b/packages/fabric/core/src/time/posix-date.ts index 6c6245e..6b39054 100644 --- a/packages/fabric/core/src/time/posix-date.ts +++ b/packages/fabric/core/src/time/posix-date.ts @@ -1,5 +1,5 @@ -import { isRecord } from "../record/is-record.js"; -import { TaggedVariant } from "../variant/variant.js"; +import { isRecord } from "../record/is-record.ts"; +import type { TaggedVariant } from "../variant/variant.ts"; export class PosixDate { constructor(public readonly timestamp: number = Date.now()) {} diff --git a/packages/fabric/core/src/time/timeout.spec.ts b/packages/fabric/core/src/time/timeout.spec.ts deleted file mode 100644 index 8d9c3f9..0000000 --- a/packages/fabric/core/src/time/timeout.spec.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { describe, expect, test } from "vitest"; -import { timeout } from "./timeout.js"; - -const HEAVY_TESTS = - process.env.HEAVY_TESTS === "true" || process.env.RUN_ALL_TESTS === "true"; - -describe("timeout", () => { - test.runIf(HEAVY_TESTS)( - "timeout never triggers *before* the input time", - async () => { - const count = 10000; - const maxTimeInMs = 1000; - - const result = await Promise.all( - new Array(count).fill(0).map(async (e, i) => { - const start = Date.now(); - const ms = i % maxTimeInMs; - await timeout(ms); - const end = Date.now(); - return end - start; - }), - ); - expect( - result - .map((t, i) => { - return [t, i % maxTimeInMs]; //Actual time and expected time - }) - .filter((e) => { - return e[0] < e[1]; //Actual time is less than the expected time - }), - ).toEqual([]); - }, - ); - - test("using timeout we can define a timeout in milliseconds", async () => { - const start = Date.now(); - await timeout(100); - const end = Date.now(); - - const time = end - start; - - expect(time).toBeGreaterThanOrEqual(100); - }); -}); diff --git a/packages/fabric/core/src/time/timeout.ts b/packages/fabric/core/src/time/timeout.ts deleted file mode 100644 index fb91ba0..0000000 --- a/packages/fabric/core/src/time/timeout.ts +++ /dev/null @@ -1,14 +0,0 @@ -export function timeout(ms: number) { - return new Promise((resolve) => { - const start = Date.now(); - setTimeout(() => { - const end = Date.now(); - const remaining = ms - (end - start); - if (remaining > 0) { - timeout(remaining).then(resolve); - } else { - resolve(); - } - }, ms); - }); -} diff --git a/packages/fabric/core/src/types/fn.ts b/packages/fabric/core/src/types/fn.ts index 7dada92..88ce795 100644 --- a/packages/fabric/core/src/types/fn.ts +++ b/packages/fabric/core/src/types/fn.ts @@ -1,7 +1,7 @@ +// deno-lint-ignore-file no-explicit-any /** * A function that takes an argument of type `T` and returns a value of type `R`. */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any export type Fn = (arg: T) => R; /** diff --git a/packages/fabric/core/src/types/index.ts b/packages/fabric/core/src/types/index.ts index 5112de5..ea1cb5f 100644 --- a/packages/fabric/core/src/types/index.ts +++ b/packages/fabric/core/src/types/index.ts @@ -1,6 +1,6 @@ -export * from "./enum.js"; -export * from "./fn.js"; -export * from "./keyof.js"; -export * from "./maybe-promise.js"; -export * from "./optional.js"; -export * from "./record.js"; +export * from "./enum.ts"; +export * from "./fn.ts"; +export * from "./keyof.ts"; +export * from "./maybe-promise.ts"; +export * from "./optional.ts"; +export * from "./record.ts"; diff --git a/packages/fabric/core/src/utils/ensure-value.ts b/packages/fabric/core/src/utils/ensure-value.ts index 11bb5e8..9ad9f6b 100644 --- a/packages/fabric/core/src/utils/ensure-value.ts +++ b/packages/fabric/core/src/utils/ensure-value.ts @@ -1,8 +1,8 @@ -import { UnexpectedError } from "../error/unexpected-error.js"; +import { UnexpectedError } from "../error/unexpected-error.ts"; export function ensureValue(value?: T): T { if (!value) { - throw new UnexpectedError("Value is undefined"); + throw new UnexpectedError("Value is nullish."); } return value; } diff --git a/packages/fabric/core/src/utils/index.ts b/packages/fabric/core/src/utils/index.ts index 2a01b7e..2f5dc32 100644 --- a/packages/fabric/core/src/utils/index.ts +++ b/packages/fabric/core/src/utils/index.ts @@ -1 +1 @@ -export * from "./ensure-value.js"; +export * from "./ensure-value.ts"; diff --git a/packages/fabric/core/src/variant/index.ts b/packages/fabric/core/src/variant/index.ts index c0edbd9..dd17902 100644 --- a/packages/fabric/core/src/variant/index.ts +++ b/packages/fabric/core/src/variant/index.ts @@ -1,2 +1,2 @@ -export * from "./match.js"; -export * from "./variant.js"; +export * from "./match.ts"; +export * from "./variant.ts"; diff --git a/packages/fabric/core/src/variant/match.spec.ts b/packages/fabric/core/src/variant/match.spec.ts deleted file mode 100644 index 983c8fa..0000000 --- a/packages/fabric/core/src/variant/match.spec.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { match } from "./match.js"; -import { TaggedVariant, VariantTag } from "./variant.js"; - -interface V1 extends TaggedVariant<"V1"> { - a: number; -} -interface V2 extends TaggedVariant<"V2"> { - b: string; -} - -type Variant = V1 | V2; - -describe("Pattern matching", () => { - it("Should match a pattern", () => { - const v = { [VariantTag]: "V1", a: 42 } as Variant; - - const result = match(v).case({ - V1: (v) => v.a, - V2: (v) => v.b, - }); - - expect(result).toBe(42); - }); - - it("Should alert that a pattern is not exhaustive", () => { - const v = { [VariantTag]: "V1", a: 42 } as Variant; - - expect(() => - // @ts-expect-error Testing non-exhaustive pattern matching - match(v).case({ - V2: (v) => v.b, - }), - ).toThrowError("Non-exhaustive pattern match"); - }); -}); diff --git a/packages/fabric/core/src/variant/match.test.ts b/packages/fabric/core/src/variant/match.test.ts new file mode 100644 index 0000000..62c2f4f --- /dev/null +++ b/packages/fabric/core/src/variant/match.test.ts @@ -0,0 +1,35 @@ +import { expect } from "jsr:@std/expect"; +import { match } from "./match.ts"; +import { type TaggedVariant, VariantTag } from "./variant.ts"; + +interface V1 extends TaggedVariant<"V1"> { + a: number; +} +interface V2 extends TaggedVariant<"V2"> { + b: string; +} + +type Variant = V1 | V2; + +const v = { [VariantTag]: "V1", a: 42 } as Variant; + +Deno.test("match().case() calls the correct function", () => { + const result = match(v).case({ + V1: (v) => v.a, + V2: (v) => v.b, + }); + + expect(result).toBe(42); +}); + +Deno.test( + "match().case() throws an error for non-exhaustive pattern matching", + () => { + expect(() => + // @ts-expect-error Testing non-exhaustive pattern matching + match(v).case({ + V2: (v) => v.b, + }) + ).toThrow("Non-exhaustive pattern match"); + } +); diff --git a/packages/fabric/core/src/variant/match.ts b/packages/fabric/core/src/variant/match.ts index 5d14799..a6d29b1 100644 --- a/packages/fabric/core/src/variant/match.ts +++ b/packages/fabric/core/src/variant/match.ts @@ -1,12 +1,12 @@ -import { Fn } from "../types/fn.js"; -import { TaggedVariant, VariantFromTag, VariantTag } from "./variant.js"; +import type { Fn } from "../types/fn.ts"; +import { type TaggedVariant, type VariantFromTag, VariantTag } from "./variant.ts"; export type VariantMatcher, T> = { [K in TVariant[VariantTag]]: Fn, T>; }; export function match>( - v: TVariant, + v: TVariant ) { return { case< @@ -14,14 +14,14 @@ export function match>( const TMatcher extends VariantMatcher< TVariant, TReturnType - > = VariantMatcher, + > = VariantMatcher >(cases: TMatcher): TReturnType { if (!(v[VariantTag] in cases)) { throw new Error("Non-exhaustive pattern match"); } return cases[v[VariantTag] as TVariant[VariantTag]]( - v as Extract, + v as Extract ); }, }; diff --git a/packages/fabric/core/src/variant/variant.spec.ts b/packages/fabric/core/src/variant/variant.spec.ts deleted file mode 100644 index f976a0a..0000000 --- a/packages/fabric/core/src/variant/variant.spec.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { describe, expect, expectTypeOf, it } from "vitest"; -import { TaggedVariant, Variant, VariantTag } from "./variant.js"; - -interface SuccessVariant extends TaggedVariant<"success"> { - [VariantTag]: "success"; - data: string; -} - -interface ErrorVariant extends TaggedVariant<"error"> { - [VariantTag]: "error"; - message: string; -} - -describe("Variant", () => { - describe("isVariant", () => { - const successVariant = { - [VariantTag]: "success", - data: "Operation successful", - } as SuccessVariant | ErrorVariant; - - const errorVariant = { - [VariantTag]: "error", - message: "Operation failed", - } as SuccessVariant | ErrorVariant; - - it("should return true for a matching tag and correctly infer it", () => { - if (Variant.is(successVariant, "success")) { - expectTypeOf(successVariant).toEqualTypeOf(); - } - - if (Variant.is(errorVariant, "error")) { - expectTypeOf(errorVariant).toEqualTypeOf(); - } - }); - - it("should return false for a non-matching tag", () => { - expect(Variant.is(successVariant, "error")).toBe(false); - expect(Variant.is(errorVariant, "success")).toBe(false); - }); - }); -}); diff --git a/packages/fabric/core/src/variant/variant.test.ts b/packages/fabric/core/src/variant/variant.test.ts new file mode 100644 index 0000000..919bdd0 --- /dev/null +++ b/packages/fabric/core/src/variant/variant.test.ts @@ -0,0 +1,32 @@ +import { expect } from "jsr:@std/expect"; +import { type TaggedVariant, Variant, VariantTag } from "./variant.ts"; + +interface SuccessVariant extends TaggedVariant<"success"> { + [VariantTag]: "success"; + data: string; +} + +interface ErrorVariant extends TaggedVariant<"error"> { + [VariantTag]: "error"; + message: string; +} + +const successVariant = { + [VariantTag]: "success", + data: "Operation successful", +} as SuccessVariant | ErrorVariant; + +const errorVariant = { + [VariantTag]: "error", + message: "Operation failed", +} as SuccessVariant | ErrorVariant; + +Deno.test("is() should return true for a matching tag", () => { + expect(Variant.is(successVariant, "success")).toBe(true); + expect(Variant.is(errorVariant, "error")).toBe(true); +}); + +Deno.test("is() should return false for a non-matching tag", () => { + expect(Variant.is(successVariant, "error")).toBe(false); + expect(Variant.is(errorVariant, "success")).toBe(false); +}); diff --git a/packages/fabric/core/tsconfig.build.json b/packages/fabric/core/tsconfig.build.json deleted file mode 100644 index 7706c0e..0000000 --- a/packages/fabric/core/tsconfig.build.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "noEmit": false, - "allowImportingTsExtensions": false, - "outDir": "dist" - }, - "exclude": [ - "src/**/*.spec.ts", - "dist", - "node_modules", - "coverage", - "vitest.config.ts" - ] -} diff --git a/packages/fabric/core/tsconfig.json b/packages/fabric/core/tsconfig.json deleted file mode 100644 index 7a7fde8..0000000 --- a/packages/fabric/core/tsconfig.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": "../../../tsconfig.json", - "exclude": ["dist", "node_modules"] -} diff --git a/packages/fabric/core/vitest.config.ts b/packages/fabric/core/vitest.config.ts deleted file mode 100644 index 820dbd6..0000000 --- a/packages/fabric/core/vitest.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { defineConfig } from "vitest/config"; - -export default defineConfig({ - test: { - coverage: { - exclude: ["dist/**", "vitest.config.ts", "**/index.ts", "**/*.spec.ts"], - }, - passWithNoTests: true, - }, -}); diff --git a/packages/fabric/domain/deno.jsonc b/packages/fabric/domain/deno.jsonc new file mode 100644 index 0000000..801737d --- /dev/null +++ b/packages/fabric/domain/deno.jsonc @@ -0,0 +1,7 @@ +{ + "name": "@fabric/domain", + "exports": { + ".": "./src/index.ts", + "./mocks": "./src/mocks.ts" + } +} diff --git a/packages/fabric/domain/package.json b/packages/fabric/domain/package.json deleted file mode 100644 index 0c0e6df..0000000 --- a/packages/fabric/domain/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "@fabric/domain", - "private": true, - "sideEffects": false, - "type": "module", - "main": "./dist/index.js", - "types": "./dist/index.d.ts", - "exports": { - ".": "./dist/index.js", - "./mocks": "./dist/mocks.js" - }, - "files": [ - "dist" - ], - "packageManager": "yarn@4.1.1", - "devDependencies": { - "@vitest/coverage-v8": "^2.1.2", - "typescript": "^5.6.3", - "vitest": "^2.1.2" - }, - "dependencies": { - "@fabric/core": "workspace:^", - "decimal.js": "^10.4.3" - }, - "scripts": { - "test": "vitest", - "coverage": "vitest run --coverage", - "build": "tsc -p tsconfig.build.json" - } -} diff --git a/packages/fabric/domain/src/errors/index.ts b/packages/fabric/domain/src/errors/index.ts index ad34939..f063335 100644 --- a/packages/fabric/domain/src/errors/index.ts +++ b/packages/fabric/domain/src/errors/index.ts @@ -1,2 +1,2 @@ -export * from "./circular-dependency-error.js"; -export * from "./query-error.js"; +export * from "./circular-dependency-error.ts"; +export * from "./query-error.ts"; diff --git a/packages/fabric/domain/src/errors/query-error.ts b/packages/fabric/domain/src/errors/query-error.ts index ca36ae8..4b2da34 100644 --- a/packages/fabric/domain/src/errors/query-error.ts +++ b/packages/fabric/domain/src/errors/query-error.ts @@ -1,7 +1,7 @@ import { TaggedError } from "@fabric/core"; export class StoreQueryError extends TaggedError<"StoreQueryError"> { - constructor(public message: string) { + constructor(message: string) { super("StoreQueryError", message); } } diff --git a/packages/fabric/domain/src/events/event-store.ts b/packages/fabric/domain/src/events/event-store.ts index 62e09ee..e50c715 100644 --- a/packages/fabric/domain/src/events/event-store.ts +++ b/packages/fabric/domain/src/events/event-store.ts @@ -1,35 +1,35 @@ -import { +import type { AsyncResult, MaybePromise, PosixDate, VariantFromTag, VariantTag, } from "@fabric/core"; -import { StoreQueryError } from "../errors/query-error.js"; -import { UUID } from "../types/uuid.js"; -import { Event } from "./event.js"; -import { StoredEvent } from "./stored-event.js"; +import type { StoreQueryError } from "../errors/query-error.ts"; +import type { UUID } from "../types/uuid.ts"; +import type { Event } from "./event.ts"; +import type { StoredEvent } from "./stored-event.ts"; export interface EventStore { /** * Store a new event in the event store. */ append( - event: T, + event: T ): AsyncResult, StoreQueryError>; getEventsFromStream( - streamId: UUID, + streamId: UUID ): AsyncResult[], StoreQueryError>; subscribe( events: TEventKey[], - subscriber: EventSubscriber>, + subscriber: EventSubscriber> ): void; } export type EventSubscriber = ( - event: StoredEvent, + event: StoredEvent ) => MaybePromise; export interface EventFilterOptions { diff --git a/packages/fabric/domain/src/events/event.ts b/packages/fabric/domain/src/events/event.ts index 8b8a417..4e2894d 100644 --- a/packages/fabric/domain/src/events/event.ts +++ b/packages/fabric/domain/src/events/event.ts @@ -1,6 +1,6 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { VariantTag } from "@fabric/core"; -import { UUID } from "../types/uuid.js"; +// deno-lint-ignore-file no-explicit-any +import type { VariantTag } from "@fabric/core"; +import type { UUID } from "../types/uuid.ts"; /** * An event is a tagged variant with a payload and a timestamp. @@ -14,5 +14,5 @@ export interface Event { export type EventFromKey< TEvents extends Event, - TKey extends TEvents[VariantTag], + TKey extends TEvents[VariantTag] > = Extract; diff --git a/packages/fabric/domain/src/events/index.ts b/packages/fabric/domain/src/events/index.ts index a6fc9bd..905a051 100644 --- a/packages/fabric/domain/src/events/index.ts +++ b/packages/fabric/domain/src/events/index.ts @@ -1,3 +1,3 @@ -export * from "./event-store.js"; -export * from "./event.js"; -export * from "./stored-event.js"; +export * from "./event-store.ts"; +export * from "./event.ts"; +export * from "./stored-event.ts"; diff --git a/packages/fabric/domain/src/events/stored-event.ts b/packages/fabric/domain/src/events/stored-event.ts index e0a33eb..2a279a0 100644 --- a/packages/fabric/domain/src/events/stored-event.ts +++ b/packages/fabric/domain/src/events/stored-event.ts @@ -1,5 +1,5 @@ -import { PosixDate } from "@fabric/core"; -import { Event } from "./event.js"; +import type { PosixDate } from "@fabric/core"; +import type { Event } from "./event.ts"; /** * A stored event is an inmutable event, already stored, with it's version in the stream and timestamp. diff --git a/packages/fabric/domain/src/files/base-file.ts b/packages/fabric/domain/src/files/base-file.ts index 7a3ce27..a1a082c 100644 --- a/packages/fabric/domain/src/files/base-file.ts +++ b/packages/fabric/domain/src/files/base-file.ts @@ -1,4 +1,4 @@ -import { MimeType } from "./mime-type.js"; +import type { MimeType } from "./mime-type.ts"; /** * Represents a file. Its the base type for all files. diff --git a/packages/fabric/domain/src/files/image-file.ts b/packages/fabric/domain/src/files/image-file.ts index 76d772c..d3228b7 100644 --- a/packages/fabric/domain/src/files/image-file.ts +++ b/packages/fabric/domain/src/files/image-file.ts @@ -1,5 +1,5 @@ -import { ImageMimeType } from "./mime-type.js"; -import { StoredFile } from "./stored-file.js"; +import type { ImageMimeType } from "./mime-type.ts"; +import type { StoredFile } from "./stored-file.ts"; /** * Represents an image file. diff --git a/packages/fabric/domain/src/files/in-memory-file.ts b/packages/fabric/domain/src/files/in-memory-file.ts index 4ec31ed..32c8ecb 100644 --- a/packages/fabric/domain/src/files/in-memory-file.ts +++ b/packages/fabric/domain/src/files/in-memory-file.ts @@ -1,5 +1,5 @@ -import { Base64String } from "../types/base-64.js"; -import { BaseFile } from "./base-file.js"; +import type { Base64String } from "../types/base-64.ts"; +import type { BaseFile } from "./base-file.ts"; /** * Represents a file with its contents in memory. diff --git a/packages/fabric/domain/src/files/index.ts b/packages/fabric/domain/src/files/index.ts index 381360a..60dc15a 100644 --- a/packages/fabric/domain/src/files/index.ts +++ b/packages/fabric/domain/src/files/index.ts @@ -1,10 +1,10 @@ -export * from "./base-file.js"; -export * from "./bytes.js"; -export * from "./image-file.js"; -export * from "./in-memory-file.js"; -export * from "./invalid-file-type-error.js"; -export * from "./is-in-memory-file.js"; -export * from "./is-mime-type.js"; -export * from "./media-file.js"; -export * from "./mime-type.js"; -export * from "./stored-file.js"; +export * from "./base-file.ts"; +export * from "./bytes.ts"; +export * from "./image-file.ts"; +export * from "./in-memory-file.ts"; +export * from "./invalid-file-type-error.ts"; +export * from "./is-in-memory-file.ts"; +export * from "./is-mime-type.ts"; +export * from "./media-file.ts"; +export * from "./mime-type.ts"; +export * from "./stored-file.ts"; diff --git a/packages/fabric/domain/src/files/is-in-memory-file.ts b/packages/fabric/domain/src/files/is-in-memory-file.ts index 09c4049..a9bcf49 100644 --- a/packages/fabric/domain/src/files/is-in-memory-file.ts +++ b/packages/fabric/domain/src/files/is-in-memory-file.ts @@ -1,5 +1,5 @@ import { isRecord } from "@fabric/core"; -import { InMemoryFile } from "./in-memory-file.js"; +import type { InMemoryFile } from "./in-memory-file.ts"; export function isInMemoryFile(value: unknown): value is InMemoryFile { try { diff --git a/packages/fabric/domain/src/files/is-mime-type.spec.ts b/packages/fabric/domain/src/files/is-mime-type.test.ts similarity index 62% rename from packages/fabric/domain/src/files/is-mime-type.spec.ts rename to packages/fabric/domain/src/files/is-mime-type.test.ts index 02fb339..9759a4a 100644 --- a/packages/fabric/domain/src/files/is-mime-type.spec.ts +++ b/packages/fabric/domain/src/files/is-mime-type.test.ts @@ -1,8 +1,8 @@ -import { describe, expect, expectTypeOf, it } from "vitest"; -import { isMimeType } from "./is-mime-type.js"; +import { describe, expect, expectTypeOf, test } from "@fabric/testing"; +import { isMimeType } from "./is-mime-type.ts"; describe("isMimeType", () => { - it("should return true if the file type is the same as the mime type", () => { + test("should return true if the file type is the same as the mime type", () => { const fileType = "image/png" as string; const result = isMimeType("image/.*", fileType); expect(result).toBe(true); @@ -11,7 +11,7 @@ describe("isMimeType", () => { } }); - it("should return false if the file type is not the same as the mime type", () => { + test("should return false if the file type is not the same as the mime type", () => { const fileType = "image/png" as string; expect(isMimeType("image/jpeg", fileType)).toBe(false); diff --git a/packages/fabric/domain/src/files/is-mime-type.ts b/packages/fabric/domain/src/files/is-mime-type.ts index 418aa4e..67cd1d6 100644 --- a/packages/fabric/domain/src/files/is-mime-type.ts +++ b/packages/fabric/domain/src/files/is-mime-type.ts @@ -1,11 +1,11 @@ -import { MimeType } from "./mime-type.js"; +import type { MimeType } from "./mime-type.ts"; /** * Checks if the actual file type is the same as the expected mime type. */ export function isMimeType( expectedMimeType: T, - actualMimeType: string, + actualMimeType: string ): actualMimeType is T { return actualMimeType.match("^" + expectedMimeType + "$") !== null; } diff --git a/packages/fabric/domain/src/files/media-file.ts b/packages/fabric/domain/src/files/media-file.ts index 9f1e4ce..10d077e 100644 --- a/packages/fabric/domain/src/files/media-file.ts +++ b/packages/fabric/domain/src/files/media-file.ts @@ -1,4 +1,4 @@ -import { StoredFile } from "./stored-file.js"; +import type { StoredFile } from "./stored-file.ts"; /** * Represents a media file, either an image, a video or an audio file. diff --git a/packages/fabric/domain/src/files/stored-file.ts b/packages/fabric/domain/src/files/stored-file.ts index dbc71da..5c9122c 100644 --- a/packages/fabric/domain/src/files/stored-file.ts +++ b/packages/fabric/domain/src/files/stored-file.ts @@ -1,5 +1,5 @@ -import { Entity } from "../types/entity.js"; -import { BaseFile } from "./base-file.js"; +import type { Entity } from "../types/entity.ts"; +import type { BaseFile } from "./base-file.ts"; /** * Represents a file as managed by the domain. diff --git a/packages/fabric/domain/src/index.ts b/packages/fabric/domain/src/index.ts index 97addcc..73ee54f 100644 --- a/packages/fabric/domain/src/index.ts +++ b/packages/fabric/domain/src/index.ts @@ -1,9 +1,9 @@ -export * from "./errors/index.js"; -export * from "./events/index.js"; -export * from "./files/index.js"; -export * from "./models/index.js"; -export * from "./security/index.js"; -export * from "./services/index.js"; -export * from "./types/index.js"; -export * from "./use-case/index.js"; -export * from "./utils/index.js"; +export * from "./errors/index.ts"; +export * from "./events/index.ts"; +export * from "./files/index.ts"; +export * from "./models/index.ts"; +export * from "./security/index.ts"; +export * from "./services/index.ts"; +export * from "./types/index.ts"; +export * from "./use-case/index.ts"; +export * from "./utils/index.ts"; diff --git a/packages/fabric/domain/src/mocks.ts b/packages/fabric/domain/src/mocks.ts index ff20c22..3e75d9d 100644 --- a/packages/fabric/domain/src/mocks.ts +++ b/packages/fabric/domain/src/mocks.ts @@ -1 +1 @@ -export * from "./services/mocks.js"; +export * from "./services/mocks.ts"; diff --git a/packages/fabric/domain/src/models/fields/decimal.ts b/packages/fabric/domain/src/models/fields/decimal.ts index 568feff..42eb3fd 100644 --- a/packages/fabric/domain/src/models/fields/decimal.ts +++ b/packages/fabric/domain/src/models/fields/decimal.ts @@ -1,5 +1,5 @@ -import { TaggedVariant, VariantTag } from "@fabric/core"; -import { BaseField } from "./base-field.js"; +import { type TaggedVariant, VariantTag } from "@fabric/core"; +import type { BaseField } from "./base-field.ts"; export interface DecimalFieldOptions extends BaseField { isUnsigned?: boolean; @@ -12,7 +12,7 @@ export interface DecimalField DecimalFieldOptions {} export function createDecimalField( - opts: T = {} as T, + opts: T = {} as T ): DecimalField & T { return { [VariantTag]: "DecimalField", diff --git a/packages/fabric/domain/src/models/fields/embedded.ts b/packages/fabric/domain/src/models/fields/embedded.ts index 59b83c4..22ae2f4 100644 --- a/packages/fabric/domain/src/models/fields/embedded.ts +++ b/packages/fabric/domain/src/models/fields/embedded.ts @@ -1,8 +1,7 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { TaggedVariant, VariantTag } from "@fabric/core"; -import { BaseField } from "./base-field.js"; +// deno-lint-ignore-file no-explicit-any +import { type TaggedVariant, VariantTag } from "@fabric/core"; +import type { BaseField } from "./base-field.ts"; -// eslint-disable-next-line @typescript-eslint/no-empty-object-type, @typescript-eslint/no-unused-vars export interface EmbeddedFieldOptions extends BaseField {} export interface EmbeddedField @@ -11,7 +10,7 @@ export interface EmbeddedField export function createEmbeddedField< K = any, - T extends EmbeddedFieldOptions = EmbeddedFieldOptions, + T extends EmbeddedFieldOptions = EmbeddedFieldOptions >(opts: T = {} as T): EmbeddedField & T { return { [VariantTag]: "EmbeddedField", diff --git a/packages/fabric/domain/src/models/fields/field-to-type.spec.ts b/packages/fabric/domain/src/models/fields/field-to-type.spec.ts deleted file mode 100644 index e69de29..0000000 diff --git a/packages/fabric/domain/src/models/fields/field-to-type.ts b/packages/fabric/domain/src/models/fields/field-to-type.ts index 76e1ee8..823b938 100644 --- a/packages/fabric/domain/src/models/fields/field-to-type.ts +++ b/packages/fabric/domain/src/models/fields/field-to-type.ts @@ -1,14 +1,14 @@ -import { PosixDate } from "@fabric/core"; -import { Decimal } from "decimal.js"; -import { UUID } from "../../types/uuid.js"; -import { DecimalField } from "./decimal.js"; -import { EmbeddedField } from "./embedded.js"; -import { FloatField } from "./float.js"; -import { IntegerField } from "./integer.js"; -import { ReferenceField } from "./reference-field.js"; -import { StringField } from "./string-field.js"; -import { TimestampField } from "./timestamp.js"; -import { UUIDField } from "./uuid-field.js"; +import type { PosixDate } from "@fabric/core"; +import type Decimal from "jsr:@quentinadam/decimal"; +import type { UUID } from "../../types/uuid.ts"; +import type { DecimalField } from "./decimal.ts"; +import type { EmbeddedField } from "./embedded.ts"; +import type { FloatField } from "./float.ts"; +import type { IntegerField } from "./integer.ts"; +import type { ReferenceField } from "./reference-field.ts"; +import type { StringField } from "./string-field.ts"; +import type { TimestampField } from "./timestamp.ts"; +import type { UUIDField } from "./uuid-field.ts"; /** * Converts a field definition to its corresponding TypeScript type. diff --git a/packages/fabric/domain/src/models/fields/float.ts b/packages/fabric/domain/src/models/fields/float.ts index fd67bcc..f80ed06 100644 --- a/packages/fabric/domain/src/models/fields/float.ts +++ b/packages/fabric/domain/src/models/fields/float.ts @@ -1,7 +1,6 @@ -import { TaggedVariant, VariantTag } from "@fabric/core"; -import { BaseField } from "./base-field.js"; +import { type TaggedVariant, VariantTag } from "@fabric/core"; +import type { BaseField } from "./base-field.ts"; -// eslint-disable-next-line @typescript-eslint/no-empty-object-type export interface FloatFieldOptions extends BaseField {} export interface FloatField @@ -9,7 +8,7 @@ export interface FloatField FloatFieldOptions {} export function createFloatField( - opts: T = {} as T, + opts: T = {} as T ): FloatField & T { return { [VariantTag]: "FloatField", diff --git a/packages/fabric/domain/src/models/fields/index.ts b/packages/fabric/domain/src/models/fields/index.ts index cde17d4..a7f4226 100644 --- a/packages/fabric/domain/src/models/fields/index.ts +++ b/packages/fabric/domain/src/models/fields/index.ts @@ -1,14 +1,17 @@ -import { createDecimalField, DecimalField } from "./decimal.js"; -import { createEmbeddedField, EmbeddedField } from "./embedded.js"; -import { createFloatField, FloatField } from "./float.js"; -import { createIntegerField, IntegerField } from "./integer.js"; -import { createReferenceField, ReferenceField } from "./reference-field.js"; -import { createStringField, StringField } from "./string-field.js"; -import { createTimestampField, TimestampField } from "./timestamp.js"; -import { createUUIDField, UUIDField } from "./uuid-field.js"; -export * from "./base-field.js"; -export * from "./field-to-type.js"; -export * from "./reference-field.js"; +import { createDecimalField, type DecimalField } from "./decimal.ts"; +import { createEmbeddedField, type EmbeddedField } from "./embedded.ts"; +import { createFloatField, type FloatField } from "./float.ts"; +import { createIntegerField, type IntegerField } from "./integer.ts"; +import { + createReferenceField, + type ReferenceField, +} from "./reference-field.ts"; +import { createStringField, type StringField } from "./string-field.ts"; +import { createTimestampField, type TimestampField } from "./timestamp.ts"; +import { createUUIDField, type UUIDField } from "./uuid-field.ts"; +export * from "./base-field.ts"; +export * from "./field-to-type.ts"; +export * from "./reference-field.ts"; export type FieldDefinition = | StringField diff --git a/packages/fabric/domain/src/models/fields/integer.ts b/packages/fabric/domain/src/models/fields/integer.ts index 48b9a69..c5e0aeb 100644 --- a/packages/fabric/domain/src/models/fields/integer.ts +++ b/packages/fabric/domain/src/models/fields/integer.ts @@ -1,5 +1,5 @@ -import { TaggedVariant, VariantTag } from "@fabric/core"; -import { BaseField } from "./base-field.js"; +import { type TaggedVariant, VariantTag } from "@fabric/core"; +import type { BaseField } from "./base-field.ts"; export interface IntegerFieldOptions extends BaseField { isUnsigned?: boolean; @@ -11,7 +11,7 @@ export interface IntegerField IntegerFieldOptions {} export function createIntegerField( - opts: T = {} as T, + opts: T = {} as T ): IntegerField & T { return { [VariantTag]: "IntegerField", diff --git a/packages/fabric/domain/src/models/fields/reference-field.spec.ts b/packages/fabric/domain/src/models/fields/reference-field.test.ts similarity index 70% rename from packages/fabric/domain/src/models/fields/reference-field.spec.ts rename to packages/fabric/domain/src/models/fields/reference-field.test.ts index 2adfb93..4b1ccf6 100644 --- a/packages/fabric/domain/src/models/fields/reference-field.spec.ts +++ b/packages/fabric/domain/src/models/fields/reference-field.test.ts @@ -1,11 +1,11 @@ import { isError } from "@fabric/core"; -import { describe, expect, it } from "vitest"; -import { defineModel } from "../model.js"; -import { Field } from "./index.js"; +import { describe, expect, test } from "@fabric/testing"; +import { defineModel } from "../model.ts"; +import { Field } from "./index.ts"; import { InvalidReferenceFieldError, validateReferenceField, -} from "./reference-field.js"; +} from "./reference-field.ts"; describe("Validate Reference Field", () => { const schema = { @@ -20,57 +20,57 @@ describe("Validate Reference Field", () => { }), }; - it("should return an error when the target model is not in the schema", () => { + test("should return an error when the target model is not in the schema", () => { const result = validateReferenceField( schema, Field.reference({ targetModel: "foo", - }), + }) ).unwrapErrorOrThrow(); expect(result).toBeInstanceOf(InvalidReferenceFieldError); }); - it("should not return an error if the target model is in the schema", () => { + test("should not return an error if the target model is in the schema", () => { validateReferenceField( schema, Field.reference({ targetModel: "User", - }), + }) ).unwrapOrThrow(); }); - it("should return an error if the target key is not in the target model", () => { + test("should return an error if the target key is not in the target model", () => { const result = validateReferenceField( schema, Field.reference({ targetModel: "User", targetKey: "foo", - }), + }) ).unwrapErrorOrThrow(); expect(result).toBeInstanceOf(InvalidReferenceFieldError); }); - it("should return error if the target key is not unique", () => { + test("should return error if the target key is not unique", () => { const result = validateReferenceField( schema, Field.reference({ targetModel: "User", targetKey: "otherNotUnique", - }), + }) ).unwrapErrorOrThrow(); expect(result).toBeInstanceOf(InvalidReferenceFieldError); }); - it("should not return an error if the target key is in the target model and is unique", () => { + test("should not return an error if the target key is in the target model and is unique", () => { const result = validateReferenceField( schema, Field.reference({ targetModel: "User", targetKey: "otherUnique", - }), + }) ); if (isError(result)) { diff --git a/packages/fabric/domain/src/models/fields/reference-field.ts b/packages/fabric/domain/src/models/fields/reference-field.ts index a2180de..9b8f4ce 100644 --- a/packages/fabric/domain/src/models/fields/reference-field.ts +++ b/packages/fabric/domain/src/models/fields/reference-field.ts @@ -1,6 +1,11 @@ -import { Result, TaggedError, TaggedVariant, VariantTag } from "@fabric/core"; -import { ModelSchema } from "../model-schema.js"; -import { BaseField } from "./base-field.js"; +import { + Result, + TaggedError, + type TaggedVariant, + VariantTag, +} from "@fabric/core"; +import type { ModelSchema } from "../model-schema.ts"; +import type { BaseField } from "./base-field.ts"; export interface ReferenceFieldOptions extends BaseField { targetModel: string; @@ -12,7 +17,7 @@ export interface ReferenceField ReferenceFieldOptions {} export function createReferenceField( - opts: T = {} as T, + opts: T = {} as T ): ReferenceField & T { return { [VariantTag]: "ReferenceField", @@ -26,32 +31,32 @@ export function getTargetKey(field: ReferenceField): string { export function validateReferenceField( schema: ModelSchema, - field: ReferenceField, + field: ReferenceField ): Result { if (!schema[field.targetModel]) { return Result.failWith( new InvalidReferenceFieldError( - `The target model '${field.targetModel}' is not in the schema.`, - ), + `The target model '${field.targetModel}' is not in the schema.` + ) ); } - if (field.targetKey && !schema[field.targetModel].fields[field.targetKey]) { + if (field.targetKey && !schema[field.targetModel]!.fields[field.targetKey]) { return Result.failWith( new InvalidReferenceFieldError( - `The target key '${field.targetKey}' is not in the target model '${field.targetModel}'.`, - ), + `The target key '${field.targetKey}' is not in the target model '${field.targetModel}'.` + ) ); } if ( field.targetKey && - !schema[field.targetModel].fields[field.targetKey].isUnique + !schema[field.targetModel]!.fields[field.targetKey]!.isUnique ) { return Result.failWith( new InvalidReferenceFieldError( - `The target key '${field.targetModel}'.'${field.targetKey}' is not unique.`, - ), + `The target key '${field.targetModel}'.'${field.targetKey}' is not unique.` + ) ); } diff --git a/packages/fabric/domain/src/models/fields/string-field.ts b/packages/fabric/domain/src/models/fields/string-field.ts index 2df7b35..959ed77 100644 --- a/packages/fabric/domain/src/models/fields/string-field.ts +++ b/packages/fabric/domain/src/models/fields/string-field.ts @@ -1,5 +1,5 @@ -import { TaggedVariant, VariantTag } from "@fabric/core"; -import { BaseField } from "./base-field.js"; +import { type TaggedVariant, VariantTag } from "@fabric/core"; +import type { BaseField } from "./base-field.ts"; export interface StringFieldOptions extends BaseField { maxLength?: number; @@ -11,7 +11,7 @@ export interface StringField StringFieldOptions {} export function createStringField( - opts: T = {} as T, + opts: T = {} as T ): StringField & T { return { [VariantTag]: "StringField", diff --git a/packages/fabric/domain/src/models/fields/timestamp.ts b/packages/fabric/domain/src/models/fields/timestamp.ts index 41b1eab..e55e2cb 100644 --- a/packages/fabric/domain/src/models/fields/timestamp.ts +++ b/packages/fabric/domain/src/models/fields/timestamp.ts @@ -1,7 +1,6 @@ -import { TaggedVariant, VariantTag } from "@fabric/core"; -import { BaseField } from "./base-field.js"; +import { type TaggedVariant, VariantTag } from "@fabric/core"; +import type { BaseField } from "./base-field.ts"; -// eslint-disable-next-line @typescript-eslint/no-empty-object-type export interface TimestampFieldOptions extends BaseField {} export interface TimestampField @@ -9,7 +8,7 @@ export interface TimestampField TimestampFieldOptions {} export function createTimestampField( - opts: T = {} as T, + opts: T = {} as T ): TimestampField & T { return { [VariantTag]: "TimestampField", diff --git a/packages/fabric/domain/src/models/fields/uuid-field.ts b/packages/fabric/domain/src/models/fields/uuid-field.ts index f4bcafc..2df4850 100644 --- a/packages/fabric/domain/src/models/fields/uuid-field.ts +++ b/packages/fabric/domain/src/models/fields/uuid-field.ts @@ -1,5 +1,5 @@ -import { TaggedVariant, VariantTag } from "@fabric/core"; -import { BaseField } from "./base-field.js"; +import { type TaggedVariant, VariantTag } from "@fabric/core"; +import type { BaseField } from "./base-field.ts"; export interface UUIDFieldOptions extends BaseField { isPrimaryKey?: boolean; @@ -10,7 +10,7 @@ export interface UUIDField UUIDFieldOptions {} export function createUUIDField( - opts: T = {} as T, + opts: T = {} as T ): UUIDField & T { return { [VariantTag]: "UUIDField", diff --git a/packages/fabric/domain/src/models/index.ts b/packages/fabric/domain/src/models/index.ts index bb4c9d7..576733f 100644 --- a/packages/fabric/domain/src/models/index.ts +++ b/packages/fabric/domain/src/models/index.ts @@ -1,5 +1,5 @@ -export * from "./fields/index.js"; -export * from "./model-schema.js"; -export * from "./model.js"; -export * from "./query/index.js"; -export * from "./state-store.js"; +export * from "./fields/index.ts"; +export * from "./model-schema.ts"; +export * from "./model.ts"; +export * from "./query/index.ts"; +export * from "./state-store.ts"; diff --git a/packages/fabric/domain/src/models/model-schema.ts b/packages/fabric/domain/src/models/model-schema.ts index 8150980..8a49167 100644 --- a/packages/fabric/domain/src/models/model-schema.ts +++ b/packages/fabric/domain/src/models/model-schema.ts @@ -1,4 +1,4 @@ -import { Model } from "./model.js"; +import type { Model } from "./model.ts"; export type ModelSchema = Record; diff --git a/packages/fabric/domain/src/models/model.spec.ts b/packages/fabric/domain/src/models/model.test.ts similarity index 54% rename from packages/fabric/domain/src/models/model.spec.ts rename to packages/fabric/domain/src/models/model.test.ts index f3b2dd2..272a7d4 100644 --- a/packages/fabric/domain/src/models/model.spec.ts +++ b/packages/fabric/domain/src/models/model.test.ts @@ -1,10 +1,11 @@ -import { describe, expectTypeOf, it } from "vitest"; -import { UUID } from "../types/uuid.js"; -import { Field } from "./fields/index.js"; -import { defineModel, ModelToType } from "./model.js"; +import type { PosixDate } from "@fabric/core"; +import { describe, expectTypeOf, test } from "@fabric/testing"; +import type { UUID } from "../types/uuid.ts"; +import { Field } from "./fields/index.ts"; +import { defineModel, type ModelToType } from "./model.ts"; describe("CreateModel", () => { - it("should create a model and it's interface type", () => { + test("should create a model and it's interface type", () => { const User = defineModel("User", { name: Field.string(), password: Field.string(), @@ -19,6 +20,7 @@ describe("CreateModel", () => { name: string; password: string; phone: string | null; + deletedAt: PosixDate | null; }>(); }); }); diff --git a/packages/fabric/domain/src/models/model.ts b/packages/fabric/domain/src/models/model.ts index 61a7893..ac03c7c 100644 --- a/packages/fabric/domain/src/models/model.ts +++ b/packages/fabric/domain/src/models/model.ts @@ -1,12 +1,12 @@ -import { Keyof } from "@fabric/core"; -import { FieldToType } from "./fields/field-to-type.js"; -import { Field, FieldDefinition } from "./fields/index.js"; +import type { Keyof } from "@fabric/core"; +import type { FieldToType } from "./fields/field-to-type.ts"; +import { Field, type FieldDefinition } from "./fields/index.ts"; export type CustomModelFields = Record; export interface Collection< TName extends string = string, - TFields extends CustomModelFields = CustomModelFields, + TFields extends CustomModelFields = CustomModelFields > { name: TName; fields: TFields; @@ -24,14 +24,14 @@ export const DefaultModelFields = { export interface Model< TName extends string = string, - TFields extends CustomModelFields = CustomModelFields, + TFields extends CustomModelFields = CustomModelFields > extends Collection { fields: typeof DefaultModelFields & TFields; } export function defineModel< TName extends string, - TFields extends CustomModelFields, + TFields extends CustomModelFields >(name: TName, fields: TFields): Model { return { name, @@ -41,7 +41,7 @@ export function defineModel< export function defineCollection< TName extends string, - TFields extends CustomModelFields, + TFields extends CustomModelFields >(name: TName, fields: TFields): Collection { return { name, diff --git a/packages/fabric/domain/src/models/query/aggregate-options.ts b/packages/fabric/domain/src/models/query/aggregate-options.ts index 361d650..3439df6 100644 --- a/packages/fabric/domain/src/models/query/aggregate-options.ts +++ b/packages/fabric/domain/src/models/query/aggregate-options.ts @@ -1,6 +1,5 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ - -import { Keyof, TaggedVariant } from "@fabric/core"; +// deno-lint-ignore-file no-explicit-any +import type { Keyof, TaggedVariant } from "@fabric/core"; export type AggregateOptions = Record>; diff --git a/packages/fabric/domain/src/models/query/filter-options.ts b/packages/fabric/domain/src/models/query/filter-options.ts index 98a5ed1..efe0c86 100644 --- a/packages/fabric/domain/src/models/query/filter-options.ts +++ b/packages/fabric/domain/src/models/query/filter-options.ts @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ +// deno-lint-ignore-file no-explicit-any export type FilterOptions = | SingleFilterOption diff --git a/packages/fabric/domain/src/models/query/index.ts b/packages/fabric/domain/src/models/query/index.ts index ff7581f..cd0f265 100644 --- a/packages/fabric/domain/src/models/query/index.ts +++ b/packages/fabric/domain/src/models/query/index.ts @@ -1,3 +1,3 @@ -export * from "./filter-options.js"; -export * from "./order-by-options.js"; -export * from "./query.js"; +export * from "./filter-options.ts"; +export * from "./order-by-options.ts"; +export * from "./query.ts"; diff --git a/packages/fabric/domain/src/models/query/query.ts b/packages/fabric/domain/src/models/query/query.ts index 8f25a4d..e5a01a9 100644 --- a/packages/fabric/domain/src/models/query/query.ts +++ b/packages/fabric/domain/src/models/query/query.ts @@ -1,8 +1,8 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { AsyncResult, Keyof, Optional } from "@fabric/core"; -import { StoreQueryError } from "../../errors/query-error.js"; -import { FilterOptions } from "./filter-options.js"; -import { OrderByOptions } from "./order-by-options.js"; +// deno-lint-ignore-file no-explicit-any +import type { AsyncResult, Keyof, Optional } from "@fabric/core"; +import type { StoreQueryError } from "../../errors/query-error.ts"; +import type { FilterOptions } from "./filter-options.ts"; +import type { OrderByOptions } from "./order-by-options.ts"; export interface StoreQuery { where(where: FilterOptions): StoreSortableQuery; @@ -11,12 +11,12 @@ export interface StoreQuery { select(): AsyncResult; select>( - keys: K[], + keys: K[] ): AsyncResult[], StoreQueryError>; selectOne(): AsyncResult, StoreQueryError>; selectOne>( - keys: K[], + keys: K[] ): AsyncResult>, StoreQueryError>; } @@ -26,12 +26,12 @@ export interface StoreSortableQuery { select(): AsyncResult; select>( - keys: K[], + keys: K[] ): AsyncResult[], StoreQueryError>; selectOne(): AsyncResult, StoreQueryError>; selectOne>( - keys: K[], + keys: K[] ): AsyncResult>, StoreQueryError>; } @@ -40,24 +40,24 @@ export interface StoreLimitableQuery { select(): AsyncResult; select>( - keys: K[], + keys: K[] ): AsyncResult[], StoreQueryError>; selectOne(): AsyncResult, StoreQueryError>; selectOne>( - keys: K[], + keys: K[] ): AsyncResult>, StoreQueryError>; } export interface SelectableQuery { select(): AsyncResult; select>( - keys: K[], + keys: K[] ): AsyncResult[], StoreQueryError>; selectOne(): AsyncResult, StoreQueryError>; selectOne>( - keys: K[], + keys: K[] ): AsyncResult>, StoreQueryError>; } diff --git a/packages/fabric/domain/src/models/state-store.ts b/packages/fabric/domain/src/models/state-store.ts index c94359a..0c38278 100644 --- a/packages/fabric/domain/src/models/state-store.ts +++ b/packages/fabric/domain/src/models/state-store.ts @@ -1,12 +1,12 @@ -import { AsyncResult } from "@fabric/core"; -import { StoreQueryError } from "../errors/query-error.js"; -import { ModelSchemaFromModels } from "./model-schema.js"; -import { Model, ModelToType } from "./model.js"; -import { StoreQuery } from "./query/query.js"; +import type { AsyncResult } from "@fabric/core"; +import type { StoreQueryError } from "../errors/query-error.ts"; +import type { ModelSchemaFromModels } from "./model-schema.ts"; +import type { Model, ModelToType } from "./model.ts"; +import type { StoreQuery } from "./query/query.ts"; export interface ReadonlyStateStore { from>( - collection: T, + collection: T ): StoreQuery[T]>>; } @@ -14,6 +14,6 @@ export interface WritableStateStore extends ReadonlyStateStore { insertInto>( collection: T, - record: ModelToType[T]>, + record: ModelToType[T]> ): AsyncResult; } diff --git a/packages/fabric/domain/src/projections/projection.ts b/packages/fabric/domain/src/projections/projection.ts index 801b963..cfc03bf 100644 --- a/packages/fabric/domain/src/projections/projection.ts +++ b/packages/fabric/domain/src/projections/projection.ts @@ -1,13 +1,13 @@ -import { VariantTag } from "@fabric/core"; -import { Event } from "../events/event.js"; -import { StoredEvent } from "../events/stored-event.js"; -import { Model, ModelToType } from "../models/model.js"; +import type { VariantTag } from "@fabric/core"; +import type { Event } from "../events/event.ts"; +import type { StoredEvent } from "../events/stored-event.ts"; +import type { Model, ModelToType } from "../models/model.ts"; export interface Projection { model: TModel; events: TEvents[VariantTag][]; projection: ( event: StoredEvent, - model?: ModelToType, + model?: ModelToType ) => ModelToType; } diff --git a/packages/fabric/domain/src/security/index.ts b/packages/fabric/domain/src/security/index.ts index 9856aaf..3e2369e 100644 --- a/packages/fabric/domain/src/security/index.ts +++ b/packages/fabric/domain/src/security/index.ts @@ -1 +1 @@ -export * from "./policy.js"; +export * from "./policy.ts"; diff --git a/packages/fabric/domain/src/services/index.ts b/packages/fabric/domain/src/services/index.ts index 62534e8..8c74787 100644 --- a/packages/fabric/domain/src/services/index.ts +++ b/packages/fabric/domain/src/services/index.ts @@ -1 +1 @@ -export * from "./uuid-generator.js"; +export * from "./uuid-generator.ts"; diff --git a/packages/fabric/domain/src/services/mocks.ts b/packages/fabric/domain/src/services/mocks.ts index 478d835..8ec2b89 100644 --- a/packages/fabric/domain/src/services/mocks.ts +++ b/packages/fabric/domain/src/services/mocks.ts @@ -1 +1 @@ -export * from "./uuid-generator.mock.js"; +export * from "./uuid-generator.mock.ts"; diff --git a/packages/fabric/domain/src/services/uuid-generator.mock.ts b/packages/fabric/domain/src/services/uuid-generator.mock.ts index 3b9674d..ad4cd5d 100644 --- a/packages/fabric/domain/src/services/uuid-generator.mock.ts +++ b/packages/fabric/domain/src/services/uuid-generator.mock.ts @@ -1,5 +1,5 @@ -import { UUID } from "../types/uuid.js"; -import { UUIDGenerator } from "./uuid-generator.js"; +import type { UUID } from "../types/uuid.ts"; +import type { UUIDGenerator } from "./uuid-generator.ts"; export const UUIDGeneratorMock: UUIDGenerator = { generate(): UUID { diff --git a/packages/fabric/domain/src/services/uuid-generator.ts b/packages/fabric/domain/src/services/uuid-generator.ts index 34c145e..ce187ef 100644 --- a/packages/fabric/domain/src/services/uuid-generator.ts +++ b/packages/fabric/domain/src/services/uuid-generator.ts @@ -1,4 +1,4 @@ -import { UUID } from "../types/uuid.js"; +import type { UUID } from "../types/uuid.ts"; export interface UUIDGenerator { generate(): UUID; diff --git a/packages/fabric/domain/src/types/decimal.ts b/packages/fabric/domain/src/types/decimal.ts deleted file mode 100644 index a760328..0000000 --- a/packages/fabric/domain/src/types/decimal.ts +++ /dev/null @@ -1 +0,0 @@ -export { Decimal } from "decimal.js"; diff --git a/packages/fabric/domain/src/types/entity.ts b/packages/fabric/domain/src/types/entity.ts index 7b2ffab..bd002cd 100644 --- a/packages/fabric/domain/src/types/entity.ts +++ b/packages/fabric/domain/src/types/entity.ts @@ -1,4 +1,4 @@ -import { UUID } from "./uuid.js"; +import type { UUID } from "./uuid.ts"; /** * An entity is a domain object that is defined by its identity. diff --git a/packages/fabric/domain/src/types/index.ts b/packages/fabric/domain/src/types/index.ts index 72d810d..92ad57a 100644 --- a/packages/fabric/domain/src/types/index.ts +++ b/packages/fabric/domain/src/types/index.ts @@ -1,6 +1,5 @@ -export * from "./base-64.js"; -export * from "./decimal.js"; -export * from "./email.js"; -export * from "./entity.js"; -export * from "./semver.js"; -export * from "./uuid.js"; +export * from "./base-64.ts"; +export * from "./email.ts"; +export * from "./entity.ts"; +export * from "./semver.ts"; +export * from "./uuid.ts"; diff --git a/packages/fabric/domain/src/use-case/index.ts b/packages/fabric/domain/src/use-case/index.ts index ef6a8a0..b2be5af 100644 --- a/packages/fabric/domain/src/use-case/index.ts +++ b/packages/fabric/domain/src/use-case/index.ts @@ -1,2 +1,2 @@ -export * from "./use-case-definition.js"; -export * from "./use-case.js"; +export * from "./use-case-definition.ts"; +export * from "./use-case.ts"; diff --git a/packages/fabric/domain/src/use-case/use-case-definition.ts b/packages/fabric/domain/src/use-case/use-case-definition.ts index b7e9768..f3f76c2 100644 --- a/packages/fabric/domain/src/use-case/use-case-definition.ts +++ b/packages/fabric/domain/src/use-case/use-case-definition.ts @@ -1,19 +1,19 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { TaggedError } from "@fabric/core"; -import { UseCase } from "./use-case.js"; +// deno-lint-ignore-file no-explicit-any +import type { TaggedError } from "@fabric/core"; +import type { UseCase } from "./use-case.ts"; export type UseCaseDefinition< TDependencies = any, TPayload = any, TOutput = any, - TErrors extends TaggedError = any, + TErrors extends TaggedError = any > = BasicUseCaseDefinition; interface BasicUseCaseDefinition< TDependencies, TPayload, TOutput, - TErrors extends TaggedError, + TErrors extends TaggedError > { /** * The use case name. diff --git a/packages/fabric/domain/src/use-case/use-case.ts b/packages/fabric/domain/src/use-case/use-case.ts index de67136..330be6b 100644 --- a/packages/fabric/domain/src/use-case/use-case.ts +++ b/packages/fabric/domain/src/use-case/use-case.ts @@ -1,4 +1,4 @@ -import { AsyncResult, TaggedError } from "@fabric/core"; +import type { AsyncResult, TaggedError } from "@fabric/core"; /** * A use case is a piece of domain logic that can be executed. diff --git a/packages/fabric/domain/src/utils/index.ts b/packages/fabric/domain/src/utils/index.ts index 7bca11f..385247d 100644 --- a/packages/fabric/domain/src/utils/index.ts +++ b/packages/fabric/domain/src/utils/index.ts @@ -1,2 +1,2 @@ -export * from "./json-utils.js"; -export * from "./sort-by-dependencies.js"; +export * from "./json-utils.ts"; +export * from "./sort-by-dependencies.ts"; diff --git a/packages/fabric/domain/src/utils/sort-by-dependencies.spec.ts b/packages/fabric/domain/src/utils/sort-by-dependencies.test.ts similarity index 86% rename from packages/fabric/domain/src/utils/sort-by-dependencies.spec.ts rename to packages/fabric/domain/src/utils/sort-by-dependencies.test.ts index 5b122f5..a0edd87 100644 --- a/packages/fabric/domain/src/utils/sort-by-dependencies.spec.ts +++ b/packages/fabric/domain/src/utils/sort-by-dependencies.test.ts @@ -1,7 +1,7 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { describe, expect, it } from "vitest"; -import { CircularDependencyError } from "../errors/circular-dependency-error.js"; -import { sortByDependencies } from "./sort-by-dependencies.js"; +import { expect } from "@std/expect"; +import { describe, it } from "@std/testing/bdd"; +import { CircularDependencyError } from "../errors/circular-dependency-error.ts"; +import { sortByDependencies } from "./sort-by-dependencies.ts"; describe("sortByDependencies", () => { it("should sort an array of objects by their dependencies", () => { @@ -35,11 +35,12 @@ describe("sortByDependencies", () => { sortByDependencies(array, { keyGetter: (element) => element.name, depGetter: (element) => element.dependencies, - }).unwrapErrorOrThrow(), + }).unwrapErrorOrThrow() ).toBeInstanceOf(CircularDependencyError); }); it("should return an empty array when the input array is empty", () => { + // deno-lint-ignore no-explicit-any const array: any[] = []; const result = sortByDependencies(array, { diff --git a/packages/fabric/domain/src/utils/sort-by-dependencies.ts b/packages/fabric/domain/src/utils/sort-by-dependencies.ts index 78c0a00..9a45f3e 100644 --- a/packages/fabric/domain/src/utils/sort-by-dependencies.ts +++ b/packages/fabric/domain/src/utils/sort-by-dependencies.ts @@ -1,5 +1,5 @@ import { Result } from "@fabric/core"; -import { CircularDependencyError } from "../errors/circular-dependency-error.js"; +import { CircularDependencyError } from "../errors/circular-dependency-error.ts"; export function sortByDependencies( array: T[], @@ -9,7 +9,7 @@ export function sortByDependencies( }: { keyGetter: (element: T) => string; depGetter: (element: T) => string[]; - }, + } ): Result { const graph = new Map(); const visited = new Set(); @@ -36,13 +36,13 @@ export function sortByDependencies( }; return Result.tryFrom( () => { - graph.forEach((deps, key) => { + graph.forEach((_, key) => { visit(key, []); }); return sorted.map( - (key) => array.find((element) => keyGetter(element) === key) as T, + (key) => array.find((element) => keyGetter(element) === key) as T ); }, - (e) => e as CircularDependencyError, + (e) => e as CircularDependencyError ); } diff --git a/packages/fabric/domain/tsconfig.build.json b/packages/fabric/domain/tsconfig.build.json deleted file mode 100644 index 7706c0e..0000000 --- a/packages/fabric/domain/tsconfig.build.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "noEmit": false, - "allowImportingTsExtensions": false, - "outDir": "dist" - }, - "exclude": [ - "src/**/*.spec.ts", - "dist", - "node_modules", - "coverage", - "vitest.config.ts" - ] -} diff --git a/packages/fabric/domain/tsconfig.json b/packages/fabric/domain/tsconfig.json deleted file mode 100644 index 7a7fde8..0000000 --- a/packages/fabric/domain/tsconfig.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": "../../../tsconfig.json", - "exclude": ["dist", "node_modules"] -} diff --git a/packages/fabric/domain/vitest.config.ts b/packages/fabric/domain/vitest.config.ts deleted file mode 100644 index 820dbd6..0000000 --- a/packages/fabric/domain/vitest.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { defineConfig } from "vitest/config"; - -export default defineConfig({ - test: { - coverage: { - exclude: ["dist/**", "vitest.config.ts", "**/index.ts", "**/*.spec.ts"], - }, - passWithNoTests: true, - }, -}); diff --git a/packages/fabric/sqlite-store/deno.jsonc b/packages/fabric/sqlite-store/deno.jsonc new file mode 100644 index 0000000..d511a2c --- /dev/null +++ b/packages/fabric/sqlite-store/deno.jsonc @@ -0,0 +1,6 @@ +{ + "name": "@fabric/sqlite-store", + "exports": { + ".": "./src/index.ts" + } +} diff --git a/packages/fabric/sqlite-store/package.json b/packages/fabric/sqlite-store/package.json deleted file mode 100644 index e75e379..0000000 --- a/packages/fabric/sqlite-store/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "@fabric/sqlite-store", - "private": true, - "sideEffects": false, - "type": "module", - "main": "./dist/index.js", - "types": "./dist/index.d.ts", - "exports": { - ".": "./dist/index.js" - }, - "files": [ - "dist" - ], - "packageManager": "yarn@4.1.1", - "devDependencies": { - "@vitest/coverage-v8": "^2.1.2", - "typescript": "^5.6.3", - "vitest": "^2.1.2" - }, - "dependencies": { - "@fabric/core": "workspace:^", - "@fabric/domain": "workspace:^", - "sqlite3": "^5.1.7" - }, - "scripts": { - "test": "vitest", - "coverage": "vitest run --coverage", - "build": "tsc -p tsconfig.build.json" - } -} diff --git a/packages/fabric/sqlite-store/src/events/event-store.spec.ts b/packages/fabric/sqlite-store/src/events/event-store.test.ts similarity index 85% rename from packages/fabric/sqlite-store/src/events/event-store.spec.ts rename to packages/fabric/sqlite-store/src/events/event-store.test.ts index 4093c78..ec797aa 100644 --- a/packages/fabric/sqlite-store/src/events/event-store.spec.ts +++ b/packages/fabric/sqlite-store/src/events/event-store.test.ts @@ -1,8 +1,15 @@ import { PosixDate, Run } from "@fabric/core"; import { Event } from "@fabric/domain"; import { UUIDGeneratorMock } from "@fabric/domain/mocks"; -import { afterEach, beforeEach, describe, expect, it, vitest } from "vitest"; -import { SQLiteEventStore } from "./event-store.js"; +import { + afterEach, + beforeEach, + describe, + expect, + fn, + test, +} from "@fabric/testing"; +import { SQLiteEventStore } from "./event-store.ts"; describe("Event Store", () => { type UserCreated = Event<"UserCreated", { name: string }>; @@ -22,7 +29,7 @@ describe("Event Store", () => { await Run.UNSAFE(() => store.close()); }); - it("Should append an event", async () => { + test("Should append an event", async () => { const newUUID = UUIDGeneratorMock.generate(); const userCreated: UserCreated = { @@ -48,7 +55,7 @@ describe("Event Store", () => { }); }); - it("should notify subscribers on append", async () => { + test("should notify subscribers on append", async () => { const newUUID = UUIDGeneratorMock.generate(); const userCreated: UserCreated = { @@ -58,7 +65,7 @@ describe("Event Store", () => { payload: { name: "test" }, }; - const subscriber = vitest.fn(); + const subscriber = fn() as () => void; store.subscribe(["UserCreated"], subscriber); diff --git a/packages/fabric/sqlite-store/src/events/event-store.ts b/packages/fabric/sqlite-store/src/events/event-store.ts index b54e659..752a05a 100644 --- a/packages/fabric/sqlite-store/src/events/event-store.ts +++ b/packages/fabric/sqlite-store/src/events/event-store.ts @@ -15,7 +15,7 @@ import { StoreQueryError, UUID, } from "@fabric/domain"; -import { SQLiteDatabase } from "../sqlite/sqlite-database.js"; +import { SQLiteDatabase } from "../sqlite/sqlite-database.ts"; export class SQLiteEventStore implements EventStore @@ -33,11 +33,11 @@ export class SQLiteEventStore this.db = new SQLiteDatabase(dbPath); } - async migrate(): AsyncResult { + migrate(): AsyncResult { return AsyncResult.tryFrom( - async () => { - await this.db.init(); - await this.db.run( + () => { + this.db.init(); + this.db.run( `CREATE TABLE IF NOT EXISTS events ( id TEXT PRIMARY KEY, _tag TEXT NOT NULL, @@ -46,19 +46,19 @@ export class SQLiteEventStore timestamp NUMERIC NOT NULL, payload TEXT NOT NULL, UNIQUE(streamId, version) - )`, + )` ); }, - (error) => new StoreQueryError(error.message), + (error) => new StoreQueryError(error.message) ); } - async getEventsFromStream( - streamId: UUID, + getEventsFromStream( + streamId: UUID ): AsyncResult[], StoreQueryError> { return AsyncResult.tryFrom( - async () => { - const events = await this.db.allPrepared( + () => { + const events = this.db.allPrepared( `SELECT * FROM events WHERE streamId = $id`, { $id: streamId, @@ -70,16 +70,16 @@ export class SQLiteEventStore version: BigInt(e.version), timestamp: new PosixDate(e.timestamp), payload: JSONUtils.parse(e.payload), - }), + }) ); return events; }, - (error) => new StoreQueryError(error.message), + (error) => new StoreQueryError(error.message) ); } - async append( - event: T, + append( + event: T ): AsyncResult, StoreQueryError> { return Run.seq( () => this.getLastVersion(event.streamId), @@ -93,42 +93,38 @@ export class SQLiteEventStore AsyncResult.from(async () => { await this.notifySubscribers(storedEvent); return storedEvent; - }), + }) ); } - private async notifySubscribers( - event: StoredEvent, - ): AsyncResult { + private notifySubscribers(event: StoredEvent): AsyncResult { return AsyncResult.from(async () => { const subscribers = this.eventSubscribers.get(event[VariantTag]) || []; await Promise.all(subscribers.map((subscriber) => subscriber(event))); }); } - private async getLastVersion( - streamId: UUID, - ): AsyncResult { + private getLastVersion(streamId: UUID): AsyncResult { return AsyncResult.tryFrom( - async () => { - const { lastVersion } = await this.db.onePrepared( + () => { + const { lastVersion } = this.db.onePrepared( `SELECT max(version) as lastVersion FROM events WHERE streamId = $id`, { $id: streamId, - }, + } ); return !lastVersion ? 0n : BigInt(lastVersion); }, - (error) => new StoreQueryError(error.message), + (error) => new StoreQueryError(error.message) ); } subscribe( eventNames: TEventKey[], subscriber: ( - event: StoredEvent>, - ) => MaybePromise, + event: StoredEvent> + ) => MaybePromise ): void { eventNames.forEach((event) => { const subscribers = this.eventSubscribers.get(event) || []; @@ -143,23 +139,23 @@ export class SQLiteEventStore close(): AsyncResult { return AsyncResult.tryFrom( () => this.db.close(), - (error) => new StoreQueryError(error.message), + (error) => new StoreQueryError(error.message) ); } private storeEvent( streamId: UUID, version: bigint, - event: T, + event: T ): AsyncResult, StoreQueryError> { return AsyncResult.tryFrom( - async () => { + () => { const storedEvent: StoredEvent = { ...event, version: version, timestamp: new PosixDate(), }; - await this.db.runPrepared( + this.db.runPrepared( `INSERT INTO events (id, streamId, _tag, version, timestamp, payload) VALUES ($id, $streamId, $_tag, $version, $timestamp, $payload)`, { @@ -169,11 +165,11 @@ export class SQLiteEventStore $version: storedEvent.version.toString(), $timestamp: storedEvent.timestamp.timestamp, $payload: JSON.stringify(storedEvent.payload), - }, + } ); return storedEvent; }, - (error) => new StoreQueryError(error.message), + (error) => new StoreQueryError(error.message) ); } } diff --git a/packages/fabric/sqlite-store/src/events/index.ts b/packages/fabric/sqlite-store/src/events/index.ts index 84a156c..75db876 100644 --- a/packages/fabric/sqlite-store/src/events/index.ts +++ b/packages/fabric/sqlite-store/src/events/index.ts @@ -1 +1 @@ -export * from "./event-store.js"; +export * from "./event-store.ts"; diff --git a/packages/fabric/sqlite-store/src/index.ts b/packages/fabric/sqlite-store/src/index.ts index 5dae270..e500278 100644 --- a/packages/fabric/sqlite-store/src/index.ts +++ b/packages/fabric/sqlite-store/src/index.ts @@ -1 +1 @@ -export * from "./state/index.js"; +export * from "./state/index.ts"; diff --git a/packages/fabric/sqlite-store/src/sqlite/filter-to-sql.spec.ts b/packages/fabric/sqlite-store/src/sqlite/filter-to-sql.test.ts similarity index 80% rename from packages/fabric/sqlite-store/src/sqlite/filter-to-sql.spec.ts rename to packages/fabric/sqlite-store/src/sqlite/filter-to-sql.test.ts index ccef5a3..ed2d951 100644 --- a/packages/fabric/sqlite-store/src/sqlite/filter-to-sql.spec.ts +++ b/packages/fabric/sqlite-store/src/sqlite/filter-to-sql.test.ts @@ -9,8 +9,8 @@ import { isLike, isNotEqualTo, } from "@fabric/domain"; -import { describe, expect, it } from "vitest"; -import { filterToParams, filterToSQL } from "./filter-to-sql.js"; +import { describe, expect, test } from "@fabric/testing"; +import { filterToParams, filterToSQL } from "./filter-to-sql.ts"; describe("SQL where clause from filter options", () => { const col = defineCollection("users", { @@ -25,7 +25,7 @@ describe("SQL where clause from filter options", () => { price: Field.decimal(), }); - it("should create a where clause from options with IN option", () => { + test("should create a where clause from options with IN option", () => { const opts = { name: isIn(["John", "Jane"]), }; @@ -37,7 +37,7 @@ describe("SQL where clause from filter options", () => { expect(params).toEqual({ $where_name_0: "John", $where_name_1: "Jane" }); }); - it("should create a where clause from options with LIKE option", () => { + test("should create a where clause from options with LIKE option", () => { const opts = { name: isLike("%John%"), }; @@ -47,7 +47,7 @@ describe("SQL where clause from filter options", () => { expect(params).toEqual({ $where_name: "%John%" }); }); - it("should create a where clause from options with EQUALS option", () => { + test("should create a where clause from options with EQUALS option", () => { const opts = { age: 25, }; @@ -57,7 +57,7 @@ describe("SQL where clause from filter options", () => { expect(params).toEqual({ $where_age: 25 }); }); - it("should create a where clause from options with NOT EQUALS option", () => { + test("should create a where clause from options with NOT EQUALS option", () => { const opts = { status: isNotEqualTo("inactive"), }; @@ -67,7 +67,7 @@ describe("SQL where clause from filter options", () => { expect(params).toEqual({ $where_status: "inactive" }); }); - it("should create a where clause from options with GREATER THAN option", () => { + test("should create a where clause from options with GREATER THAN option", () => { const opts = { salary: isGreaterThan(50000), }; @@ -77,7 +77,7 @@ describe("SQL where clause from filter options", () => { expect(params).toEqual({ $where_salary: 50000 }); }); - it("should create a where clause from options with LESS THAN option", () => { + test("should create a where clause from options with LESS THAN option", () => { const opts = { rating: isLessThan(4.5), }; @@ -87,7 +87,7 @@ describe("SQL where clause from filter options", () => { expect(params).toEqual({ $where_rating: 4.5 }); }); - it("should create a where clause from options with GREATER THAN OR EQUALS option", () => { + test("should create a where clause from options with GREATER THAN OR EQUALS option", () => { const opts = { quantity: isGreaterOrEqualTo(10), }; @@ -97,7 +97,7 @@ describe("SQL where clause from filter options", () => { expect(params).toEqual({ $where_quantity: 10 }); }); - it("should create a where clause from options with LESS THAN OR EQUALS option", () => { + test("should create a where clause from options with LESS THAN OR EQUALS option", () => { const opts = { price: isLessOrEqualTo(100), }; @@ -107,7 +107,7 @@ describe("SQL where clause from filter options", () => { expect(params).toEqual({ $where_price: 100 }); }); - it("should create a where clause from options with IS NULL option", () => { + test("should create a where clause from options with IS NULL option", () => { const opts = { price: undefined, }; @@ -117,7 +117,7 @@ describe("SQL where clause from filter options", () => { expect(params).toEqual({}); }); - it("should create a where clause from options with OR combination", () => { + test("should create a where clause from options with OR combination", () => { const opts = [ { name: isIn(["John", "Jane"]), @@ -135,7 +135,7 @@ describe("SQL where clause from filter options", () => { const result = filterToSQL(opts); const params = filterToParams(col, opts); expect(result).toEqual( - "WHERE (name IN ($where_name_0_0,$where_name_0_1) AND age > $where_age_0) OR (status <> $where_status_1 AND salary > $where_salary_1) OR (rating < $where_rating_2 AND quantity >= $where_quantity_2)", + "WHERE (name IN ($where_name_0_0,$where_name_0_1) AND age > $where_age_0) OR (status <> $where_status_1 AND salary > $where_salary_1) OR (rating < $where_rating_2 AND quantity >= $where_quantity_2)" ); expect(params).toEqual({ $where_name_0_0: "John", diff --git a/packages/fabric/sqlite-store/src/sqlite/filter-to-sql.ts b/packages/fabric/sqlite-store/src/sqlite/filter-to-sql.ts index da4f3b4..a43f971 100644 --- a/packages/fabric/sqlite-store/src/sqlite/filter-to-sql.ts +++ b/packages/fabric/sqlite-store/src/sqlite/filter-to-sql.ts @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ +// deno-lint-ignore-file no-explicit-any import { Collection, FieldDefinition, @@ -10,8 +10,8 @@ import { MultiFilterOption, SingleFilterOption, } from "@fabric/domain"; -import { keyToParam } from "./record-utils.js"; -import { fieldValueToSQL } from "./value-to-sql.js"; +import { keyToParam } from "./record-utils.ts"; +import { fieldValueToSQL } from "./value-to-sql.ts"; export function filterToSQL(filterOptions?: FilterOptions) { if (!filterOptions) return ""; @@ -24,7 +24,7 @@ export function filterToSQL(filterOptions?: FilterOptions) { export function filterToParams( collection: Collection, - filterOptions?: FilterOptions, + filterOptions?: FilterOptions ) { if (!filterOptions) return {}; @@ -38,14 +38,14 @@ function getWhereFromMultiOption(filterOptions: MultiFilterOption) { return filterOptions .map( (option, i) => - `(${getWhereFromSingleOption(option, { postfix: `_${i}` })})`, + `(${getWhereFromSingleOption(option, { postfix: `_${i}` })})` ) .join(" OR "); } function getWhereFromSingleOption( filterOptions: SingleFilterOption, - opts: { postfix?: string } = {}, + opts: { postfix?: string } = {} ) { return Object.entries(filterOptions) .map(([key, value]) => getWhereFromKeyValue(key, value, opts)) @@ -61,7 +61,7 @@ function getWhereParamKey(key: string, opts: { postfix?: string } = {}) { function getWhereFromKeyValue( key: string, value: FilterValue, - opts: { postfix?: string } = {}, + opts: { postfix?: string } = {} ) { if (value == undefined) { return `${key} IS NULL`; @@ -74,17 +74,17 @@ function getWhereFromKeyValue( if (value[FILTER_OPTION_TYPE_SYMBOL] === "in") { return `${key} IN (${value[FILTER_OPTION_VALUE_SYMBOL].map( - (v: any, i: number) => + (_v: any, i: number) => `${getWhereParamKey(key, { postfix: opts.postfix ? `${opts.postfix}_${i}` : `_${i}`, - })}`, + })}` ).join(",")})`; } if (value[FILTER_OPTION_TYPE_SYMBOL] === "comparison") { return `${key} ${value[FILTER_OPTION_OPERATOR_SYMBOL]} ${getWhereParamKey( key, - opts, + opts )}`; } } @@ -93,7 +93,7 @@ function getWhereFromKeyValue( function getParamsFromMultiFilterOption( collection: Collection, - filterOptions: MultiFilterOption, + filterOptions: MultiFilterOption ) { return filterOptions.reduce( (acc, filterOption, i) => ({ @@ -102,14 +102,14 @@ function getParamsFromMultiFilterOption( postfix: `_${i}`, }), }), - {}, + {} ); } function getParamsFromSingleFilterOption( collection: Collection, filterOptions: SingleFilterOption, - opts: { postfix?: string } = {}, + opts: { postfix?: string } = {} ) { return Object.entries(filterOptions) .filter(([, value]) => { @@ -118,9 +118,14 @@ function getParamsFromSingleFilterOption( .reduce( (acc, [key, value]) => ({ ...acc, - ...getParamsForFilterKeyValue(collection.fields[key], key, value, opts), + ...getParamsForFilterKeyValue( + collection.fields[key]!, + key, + value, + opts + ), }), - {}, + {} ); } @@ -142,12 +147,12 @@ function getParamsForFilterKeyValue( field: FieldDefinition, key: string, value: FilterValue, - opts: { postfix?: string } = {}, + opts: { postfix?: string } = {} ) { if (typeof value === "object") { if (value[FILTER_OPTION_TYPE_SYMBOL] === "in") { return value[FILTER_OPTION_VALUE_SYMBOL].reduce( - (acc: Record, v: any, i: number) => { + (acc: Record, _: any, i: number) => { return { ...acc, [getWhereParamKey(key, { @@ -155,7 +160,7 @@ function getParamsForFilterKeyValue( })]: value[FILTER_OPTION_VALUE_SYMBOL][i], }; }, - {}, + {} ); } } diff --git a/packages/fabric/sqlite-store/src/sqlite/model-to-sql.spec.ts b/packages/fabric/sqlite-store/src/sqlite/model-to-sql.test.ts similarity index 74% rename from packages/fabric/sqlite-store/src/sqlite/model-to-sql.spec.ts rename to packages/fabric/sqlite-store/src/sqlite/model-to-sql.test.ts index 8038dec..2749655 100644 --- a/packages/fabric/sqlite-store/src/sqlite/model-to-sql.spec.ts +++ b/packages/fabric/sqlite-store/src/sqlite/model-to-sql.test.ts @@ -1,6 +1,6 @@ import { defineCollection, Field } from "@fabric/domain"; -import { describe, expect, it } from "vitest"; -import { modelToSql } from "./model-to-sql.js"; +import { describe, expect, test } from "@fabric/testing"; +import { modelToSql } from "./model-to-sql.ts"; describe("ModelToSQL", () => { const model = defineCollection("something", { @@ -12,11 +12,11 @@ describe("ModelToSQL", () => { reference: Field.reference({ targetModel: "somethingElse" }), }); - it("should generate SQL for a model", () => { + test("should generate SQL for a model", () => { const result = modelToSql(model); expect(result).toEqual( - `CREATE TABLE something (id TEXT PRIMARY KEY, name TEXT NOT NULL, age INTEGER NOT NULL, date NUMERIC NOT NULL, reference TEXT NOT NULL REFERENCES somethingElse(id))`, + `CREATE TABLE something (id TEXT PRIMARY KEY, name TEXT NOT NULL, age INTEGER NOT NULL, date NUMERIC NOT NULL, reference TEXT NOT NULL REFERENCES somethingElse(id))` ); }); }); diff --git a/packages/fabric/sqlite-store/src/sqlite/model-to-sql.ts b/packages/fabric/sqlite-store/src/sqlite/model-to-sql.ts index 5b5129d..724d582 100644 --- a/packages/fabric/sqlite-store/src/sqlite/model-to-sql.ts +++ b/packages/fabric/sqlite-store/src/sqlite/model-to-sql.ts @@ -1,11 +1,11 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ +// deno-lint-ignore-file no-explicit-any import { Variant, VariantTag } from "@fabric/core"; import { Collection, FieldDefinition, getTargetKey } from "@fabric/domain"; type FieldSQLDefinitionMap = { [K in FieldDefinition[VariantTag]]: ( name: string, - field: Extract, + field: Extract ) => string; }; @@ -61,7 +61,7 @@ function modifiersFromOpts(field: FieldDefinition) { } export function modelToSql( - model: Collection>, + model: Collection> ) { const fields = Object.entries(model.fields) .map(([name, type]) => fieldDefinitionToSQL(name, type)) diff --git a/packages/fabric/sqlite-store/src/sqlite/record-utils.ts b/packages/fabric/sqlite-store/src/sqlite/record-utils.ts index 50dfd7c..1c6ab9c 100644 --- a/packages/fabric/sqlite-store/src/sqlite/record-utils.ts +++ b/packages/fabric/sqlite-store/src/sqlite/record-utils.ts @@ -1,7 +1,7 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ +// deno-lint-ignore-file no-explicit-any import { Model } from "@fabric/domain"; -import { fieldValueToSQL } from "./value-to-sql.js"; +import { fieldValueToSQL } from "./value-to-sql.ts"; /** * Unfold a record into a string of it's keys separated by commas. @@ -27,9 +27,9 @@ export function recordToSQLParams(model: Model, record: Record) { return Object.keys(record).reduce( (acc, key) => ({ ...acc, - [keyToParam(key)]: fieldValueToSQL(model.fields[key], record[key]), + [keyToParam(key)]: fieldValueToSQL(model.fields[key]!, record[key]), }), - {}, + {} ); } diff --git a/packages/fabric/sqlite-store/src/sqlite/sql-to-value.ts b/packages/fabric/sqlite-store/src/sqlite/sql-to-value.ts index ce8d123..96b20f6 100644 --- a/packages/fabric/sqlite-store/src/sqlite/sql-to-value.ts +++ b/packages/fabric/sqlite-store/src/sqlite/sql-to-value.ts @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ +// deno-lint-ignore-file no-explicit-any import { PosixDate, VariantTag } from "@fabric/core"; import { Collection, FieldDefinition, FieldToType } from "@fabric/domain"; @@ -6,7 +6,7 @@ export function transformRow(model: Collection) { return (row: Record) => { const result: Record = {}; for (const key in row) { - const field = model.fields[key]; + const field = model.fields[key]!; result[key] = valueFromSQL(field, row[key]); } return result; @@ -24,21 +24,21 @@ function valueFromSQL(field: FieldDefinition, value: any): any { type FieldSQLInsertMap = { [K in FieldDefinition[VariantTag]]: ( field: Extract, - value: any, + value: any ) => FieldToType>; }; const FieldSQLInsertMap: FieldSQLInsertMap = { - StringField: (f, v) => v, - UUIDField: (f, v) => v, + StringField: (_, v) => v, + UUIDField: (_, v) => v, IntegerField: (f, v) => { if (f.hasArbitraryPrecision) { return BigInt(v); } return v; }, - ReferenceField: (f, v) => v, - FloatField: (f, v) => v, - DecimalField: (f, v) => v, - TimestampField: (f, v) => new PosixDate(v), - EmbeddedField: (f, v: string) => JSON.parse(v), + ReferenceField: (_, v) => v, + FloatField: (_, v) => v, + DecimalField: (_, v) => v, + TimestampField: (_, v) => new PosixDate(v), + EmbeddedField: (_, v: string) => JSON.parse(v), }; diff --git a/packages/fabric/sqlite-store/src/sqlite/sqlite-database.ts b/packages/fabric/sqlite-store/src/sqlite/sqlite-database.ts index 7daecb7..a9a9b01 100644 --- a/packages/fabric/sqlite-store/src/sqlite/sqlite-database.ts +++ b/packages/fabric/sqlite-store/src/sqlite/sqlite-database.ts @@ -1,118 +1,72 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ +// deno-lint-ignore-file no-explicit-any import { MaybePromise } from "@fabric/core"; -import SQLite from "sqlite3"; +import { Database, Statement } from "jsr:@db/sqlite"; export class SQLiteDatabase { - db: SQLite.Database; + db: Database; - private cachedStatements = new Map(); + private cachedStatements = new Map(); constructor(private readonly path: string) { - this.db = new SQLite.Database(path); + this.db = new Database(path); } - async init() { - await this.run("PRAGMA journal_mode = WAL"); - await this.run("PRAGMA foreign_keys = ON"); + init() { + this.run("PRAGMA journal_mode = WAL"); + this.run("PRAGMA foreign_keys = ON"); } - async close() { - await this.finalizeStatements(); - await new Promise((resolve, reject) => { - this.db.close((err: Error | null) => { - if (err) { - reject(err); - } else { - resolve(); - } - }); - }); + close() { + this.finalizeStatements(); + this.db.close(); } async withTransaction(fn: () => MaybePromise) { try { - await this.run("BEGIN TRANSACTION"); + this.run("BEGIN TRANSACTION"); await fn(); - await this.run("COMMIT"); + this.run("COMMIT"); } catch { - await this.run("ROLLBACK"); + this.run("ROLLBACK"); } } run(sql: string, params?: Record) { - return new Promise((resolve, reject) => { - this.db.run(sql, params, (err: Error | null) => { - if (err) { - reject(err); - } else { - resolve(); - } - }); - }); + this.db.run(sql, params); } runPrepared(sql: string, params?: Record) { const cachedStmt = this.getCachedStatement(sql); - return new Promise((resolve, reject) => { - cachedStmt.run(params, (err: Error | null) => { - if (err) { - reject(err); - } else { - resolve(); - } - }); - }); + cachedStmt.run(params); } allPrepared( sql: string, params?: Record, - transformer?: (row: any) => any, + transformer?: (row: any) => any ) { const cachedStmt = this.getCachedStatement(sql); - return new Promise((resolve, reject) => { - cachedStmt.all( - params, - (err: Error | null, rows: Record[]) => { - if (err) { - reject(err); - } else { - try { - resolve(transformer ? rows.map(transformer) : rows); - } catch (e) { - reject(e); - } - } - }, - ); - }); + const result = cachedStmt.all(params); + + return transformer ? result.map(transformer) : result; } onePrepared( sql: string, params?: Record, - transformer?: (row: any) => any, + transformer?: (row: any) => any ) { const cachedStmt = this.getCachedStatement(sql); - return new Promise((resolve, reject) => { - cachedStmt.all( - params, - (err: Error | null, rows: Record[]) => { - if (err) { - reject(err); - } else { - try { - resolve(transformer ? rows.map(transformer)[0] : rows[0]); - } catch (e) { - reject(e); - } - } - }, - ); - }); + const result = cachedStmt.all(params); + + if (result.length === 0) { + return; + } + + return transformer ? transformer(result[0]) : result[0]; } private getCachedStatement(sql: string) { @@ -126,17 +80,9 @@ export class SQLiteDatabase { return cached; } - private async finalizeStatements() { + private finalizeStatements() { for (const stmt of this.cachedStatements.values()) { - await new Promise((resolve, reject) => { - stmt.finalize((err: Error | null) => { - if (err) { - reject(err); - } else { - resolve(); - } - }); - }); + stmt.finalize(); } } } diff --git a/packages/fabric/sqlite-store/src/sqlite/value-to-sql.ts b/packages/fabric/sqlite-store/src/sqlite/value-to-sql.ts index c5feeae..fb507dc 100644 --- a/packages/fabric/sqlite-store/src/sqlite/value-to-sql.ts +++ b/packages/fabric/sqlite-store/src/sqlite/value-to-sql.ts @@ -1,27 +1,27 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ +// deno-lint-ignore-file no-explicit-any import { VariantTag } from "@fabric/core"; import { FieldDefinition, FieldToType } from "@fabric/domain"; type FieldSQLInsertMap = { [K in FieldDefinition[VariantTag]]: ( field: Extract, - value: FieldToType>, + value: FieldToType> ) => any; }; const FieldSQLInsertMap: FieldSQLInsertMap = { - StringField: (f, v) => v, - UUIDField: (f, v) => v, + StringField: (_, v) => v, + UUIDField: (_, v) => v, IntegerField: (f, v: number | bigint) => { if (f.hasArbitraryPrecision) { return String(v); } return v as number; }, - ReferenceField: (f, v) => v, - FloatField: (f, v) => v, - DecimalField: (f, v) => v, - TimestampField: (f, v) => v.timestamp, - EmbeddedField: (f, v: string) => JSON.stringify(v), + ReferenceField: (_, v) => v, + FloatField: (_, v) => v, + DecimalField: (_, v) => v, + TimestampField: (_, v) => v.timestamp, + EmbeddedField: (_, v: string) => JSON.stringify(v), }; export function fieldValueToSQL(field: FieldDefinition, value: any) { diff --git a/packages/fabric/sqlite-store/src/state/index.ts b/packages/fabric/sqlite-store/src/state/index.ts index 381f7cc..b8cc439 100644 --- a/packages/fabric/sqlite-store/src/state/index.ts +++ b/packages/fabric/sqlite-store/src/state/index.ts @@ -1 +1 @@ -export * from "./state-store.js"; +export * from "./state-store.ts"; diff --git a/packages/fabric/sqlite-store/src/state/query-builder.ts b/packages/fabric/sqlite-store/src/state/query-builder.ts index 858f725..555e4fc 100644 --- a/packages/fabric/sqlite-store/src/state/query-builder.ts +++ b/packages/fabric/sqlite-store/src/state/query-builder.ts @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ +// deno-lint-ignore-file no-explicit-any import { AsyncResult, Keyof, Optional } from "@fabric/core"; import { Collection, @@ -12,15 +12,15 @@ import { StoreQueryError, StoreSortableQuery, } from "@fabric/domain"; -import { filterToParams, filterToSQL } from "../sqlite/filter-to-sql.js"; -import { transformRow } from "../sqlite/sql-to-value.js"; -import { SQLiteDatabase } from "../sqlite/sqlite-database.js"; +import { filterToParams, filterToSQL } from "../sqlite/filter-to-sql.ts"; +import { transformRow } from "../sqlite/sql-to-value.ts"; +import { SQLiteDatabase } from "../sqlite/sqlite-database.ts"; export class QueryBuilder implements StoreQuery { constructor( private db: SQLiteDatabase, private schema: ModelSchema, - private query: QueryDefinition, + private query: QueryDefinition ) {} where(where: FilterOptions): StoreSortableQuery { @@ -41,60 +41,63 @@ export class QueryBuilder implements StoreQuery { return new QueryBuilder(this.db, this.schema, { ...this.query, limit, - offset, + offset: offset ?? 0, }); } select(): AsyncResult; select>( - keys: K[], + keys: K[] ): AsyncResult[], StoreQueryError>; select>(keys?: K[]): AsyncResult { return AsyncResult.tryFrom( - async () => { - const [sql, params] = getSelectStatement(this.schema[this.query.from], { - ...this.query, - keys, - }); + () => { + const [sql, params] = getSelectStatement( + this.schema[this.query.from]!, + { + ...this.query, + keys: keys!, + } + ); return this.db.allPrepared( sql, params, - transformRow(this.schema[this.query.from]), + transformRow(this.schema[this.query.from]!) ); }, - (err) => new StoreQueryError(err.message), + (err) => new StoreQueryError(err.message) ); } selectOne(): AsyncResult, StoreQueryError>; selectOne>( - keys: K, + keys: K[] ): AsyncResult>, StoreQueryError>; selectOne>(keys?: K[]): AsyncResult { return AsyncResult.tryFrom( async () => { const [stmt, params] = getSelectStatement( - this.schema[this.query.from], + this.schema[this.query.from]!, { ...this.query, - keys, + keys: keys!, limit: 1, - }, + } ); return await this.db.onePrepared( stmt, params, - transformRow(this.schema[this.query.from]), + transformRow(this.schema[this.query.from]!) ); }, - (err) => new StoreQueryError(err.message), + (err) => new StoreQueryError(err.message) ); } } export function getSelectStatement( collection: Collection, - query: QueryDefinition, + query: QueryDefinition ): [string, Record] { const selectFields = query.keys ? query.keys.join(", ") : "*"; diff --git a/packages/fabric/sqlite-store/src/state/state-store.spec.ts b/packages/fabric/sqlite-store/src/state/state-store.test.ts similarity index 87% rename from packages/fabric/sqlite-store/src/state/state-store.spec.ts rename to packages/fabric/sqlite-store/src/state/state-store.test.ts index bd1b298..96ed741 100644 --- a/packages/fabric/sqlite-store/src/state/state-store.spec.ts +++ b/packages/fabric/sqlite-store/src/state/state-store.test.ts @@ -7,9 +7,9 @@ import { describe, expect, expectTypeOf, - it, -} from "vitest"; -import { SQLiteStateStore } from "./state-store.js"; + test, +} from "@fabric/testing"; +import { SQLiteStateStore } from "./state-store.ts"; describe("State Store", () => { const models = [ @@ -33,7 +33,7 @@ describe("State Store", () => { await Run.UNSAFE(() => store.close()); }); - it("should insert a record", async () => { + test("should insert a record", async () => { const newUUID = UUIDGeneratorMock.generate(); await Run.UNSAFE(() => @@ -43,11 +43,11 @@ describe("State Store", () => { streamId: newUUID, streamVersion: 1n, deletedAt: null, - }), + }) ); }); - it("should select all records", async () => { + test("should select all records", async () => { const newUUID = UUIDGeneratorMock.generate(); await Run.UNSAFE(() => @@ -57,7 +57,7 @@ describe("State Store", () => { streamId: newUUID, streamVersion: 1n, deletedAt: null, - }), + }) ); const result = await Run.UNSAFE(() => store.from("users").select()); @@ -83,7 +83,7 @@ describe("State Store", () => { ]); }); - it("should select records with a filter", async () => { + test("should select records with a filter", async () => { const newUUID = UUIDGeneratorMock.generate(); await Run.seqUNSAFE( @@ -110,7 +110,7 @@ describe("State Store", () => { streamId: UUIDGeneratorMock.generate(), streamVersion: 1n, deletedAt: null, - }), + }) ); const result = await Run.UNSAFE(() => @@ -119,7 +119,7 @@ describe("State Store", () => { .where({ name: isLike("te%"), }) - .select(), + .select() ); expectTypeOf(result).toEqualTypeOf< @@ -143,7 +143,7 @@ describe("State Store", () => { ]); }); - it("should update a record", async () => { + test("should update a record", async () => { const newUUID = UUIDGeneratorMock.generate(); await Run.UNSAFE(() => @@ -153,17 +153,17 @@ describe("State Store", () => { streamId: newUUID, streamVersion: 1n, deletedAt: null, - }), + }) ); await Run.UNSAFE(() => store.update("users", newUUID, { name: "updated", - }), + }) ); const result = await Run.UNSAFE(() => - store.from("users").where({ id: newUUID }).selectOne(), + store.from("users").where({ id: newUUID }).selectOne() ); expect(result).toEqual({ @@ -175,7 +175,7 @@ describe("State Store", () => { }); }); - it("should delete a record", async () => { + test("should delete a record", async () => { const newUUID = UUIDGeneratorMock.generate(); await Run.UNSAFE(() => @@ -185,13 +185,13 @@ describe("State Store", () => { streamId: newUUID, streamVersion: 1n, deletedAt: null, - }), + }) ); await Run.UNSAFE(() => store.delete("users", newUUID)); const result = await Run.UNSAFE(() => - store.from("users").where({ id: newUUID }).selectOne(), + store.from("users").where({ id: newUUID }).selectOne() ); expect(result).toBeUndefined(); @@ -199,7 +199,7 @@ describe("State Store", () => { //test for inserting into a collection with a reference - it("should insert a record with a reference", async () => { + test("should insert a record with a reference", async () => { const newUUID = UUIDGeneratorMock.generate(); const ownerUUID = UUIDGeneratorMock.generate(); @@ -210,7 +210,7 @@ describe("State Store", () => { streamId: ownerUUID, streamVersion: 1n, deletedAt: null, - }), + }) ); await Run.UNSAFE(() => @@ -221,7 +221,7 @@ describe("State Store", () => { streamId: newUUID, streamVersion: 1n, deletedAt: null, - }), + }) ); }); }); diff --git a/packages/fabric/sqlite-store/src/state/state-store.ts b/packages/fabric/sqlite-store/src/state/state-store.ts index ccb02cc..12d1843 100644 --- a/packages/fabric/sqlite-store/src/state/state-store.ts +++ b/packages/fabric/sqlite-store/src/state/state-store.ts @@ -8,16 +8,16 @@ import { UUID, WritableStateStore, } from "@fabric/domain"; -import { modelToSql } from "../sqlite/model-to-sql.js"; +import { modelToSql } from "../sqlite/model-to-sql.ts"; import { keyToParam, recordToSQLKeyParams, recordToSQLKeys, recordToSQLParams, recordToSQLSet, -} from "../sqlite/record-utils.js"; -import { SQLiteDatabase } from "../sqlite/sqlite-database.js"; -import { QueryBuilder } from "./query-builder.js"; +} from "../sqlite/record-utils.ts"; +import { SQLiteDatabase } from "../sqlite/sqlite-database.ts"; +import { QueryBuilder } from "./query-builder.ts"; export class SQLiteStateStore implements WritableStateStore @@ -25,10 +25,7 @@ export class SQLiteStateStore private schema: ModelSchemaFromModels; private db: SQLiteDatabase; - constructor( - private readonly dbPath: string, - models: TModel[], - ) { + constructor(private readonly dbPath: string, models: TModel[]) { this.schema = models.reduce((acc, model: TModel) => { return { ...acc, @@ -39,25 +36,27 @@ export class SQLiteStateStore this.db = new SQLiteDatabase(dbPath); } - async insertInto>( + insertInto>( collection: T, - record: ModelToType[T]>, + record: ModelToType[T]> ): AsyncResult { const model = this.schema[collection]; return AsyncResult.tryFrom( - async () => { - await this.db.runPrepared( - `INSERT INTO ${model.name} (${recordToSQLKeys(record)}) VALUES (${recordToSQLKeyParams(record)})`, - recordToSQLParams(model, record), + () => { + this.db.runPrepared( + `INSERT INTO ${model.name} (${recordToSQLKeys( + record + )}) VALUES (${recordToSQLKeyParams(record)})`, + recordToSQLParams(model, record) ); }, - (error) => new StoreQueryError(error.message), + (error) => new StoreQueryError(error.message) ); } from>( - collection: T, + collection: T ): StoreQuery[T]>> { return new QueryBuilder(this.db, this.schema, { from: collection, @@ -67,39 +66,41 @@ export class SQLiteStateStore update>( collection: T, id: UUID, - record: Partial[T]>>, + record: Partial[T]>> ): AsyncResult { const model = this.schema[collection]; return AsyncResult.tryFrom( - async () => { + () => { const params = recordToSQLParams(model, { ...record, id, }); - await this.db.runPrepared( - `UPDATE ${model.name} SET ${recordToSQLSet(record)} WHERE id = ${keyToParam("id")}`, - params, + this.db.runPrepared( + `UPDATE ${model.name} SET ${recordToSQLSet( + record + )} WHERE id = ${keyToParam("id")}`, + params ); }, - (error) => new StoreQueryError(error.message), + (error) => new StoreQueryError(error.message) ); } delete>( collection: T, - id: UUID, + id: UUID ): AsyncResult { const model = this.schema[collection]; return AsyncResult.tryFrom( - async () => { - await this.db.runPrepared( + () => { + this.db.runPrepared( `DELETE FROM ${model.name} WHERE id = ${keyToParam("id")}`, - { $id: id }, + { $id: id } ); }, - (error) => new StoreQueryError(error.message), + (error) => new StoreQueryError(error.message) ); } @@ -107,19 +108,19 @@ export class SQLiteStateStore return AsyncResult.tryFrom( async () => { await this.db.init(); - await this.db.withTransaction(async () => { + await this.db.withTransaction(() => { for (const modelKey in this.schema) { const model = this.schema[modelKey as keyof ModelSchemaFromModels]; - await this.db.runPrepared(modelToSql(model)); + this.db.runPrepared(modelToSql(model)); } }); }, - (error) => new StoreQueryError(error.message), + (error) => new StoreQueryError(error.message) ); } - async close(): AsyncResult { + close(): AsyncResult { return AsyncResult.from(() => this.db.close()); } } diff --git a/packages/fabric/sqlite-store/tsconfig.build.json b/packages/fabric/sqlite-store/tsconfig.build.json deleted file mode 100644 index 7706c0e..0000000 --- a/packages/fabric/sqlite-store/tsconfig.build.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "noEmit": false, - "allowImportingTsExtensions": false, - "outDir": "dist" - }, - "exclude": [ - "src/**/*.spec.ts", - "dist", - "node_modules", - "coverage", - "vitest.config.ts" - ] -} diff --git a/packages/fabric/sqlite-store/tsconfig.json b/packages/fabric/sqlite-store/tsconfig.json deleted file mode 100644 index 7a7fde8..0000000 --- a/packages/fabric/sqlite-store/tsconfig.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": "../../../tsconfig.json", - "exclude": ["dist", "node_modules"] -} diff --git a/packages/fabric/sqlite-store/vitest.config.ts b/packages/fabric/sqlite-store/vitest.config.ts deleted file mode 100644 index 820dbd6..0000000 --- a/packages/fabric/sqlite-store/vitest.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { defineConfig } from "vitest/config"; - -export default defineConfig({ - test: { - coverage: { - exclude: ["dist/**", "vitest.config.ts", "**/index.ts", "**/*.spec.ts"], - }, - passWithNoTests: true, - }, -}); diff --git a/packages/fabric/testing/deno.jsonc b/packages/fabric/testing/deno.jsonc new file mode 100644 index 0000000..b32f679 --- /dev/null +++ b/packages/fabric/testing/deno.jsonc @@ -0,0 +1,6 @@ +{ + "name": "@fabric/testing", + "exports": { + ".": "./src/index.ts" + } +} diff --git a/packages/fabric/testing/src/index.ts b/packages/fabric/testing/src/index.ts new file mode 100644 index 0000000..9774d9f --- /dev/null +++ b/packages/fabric/testing/src/index.ts @@ -0,0 +1,4 @@ +export { expect, fn } from "@std/expect"; +export { afterEach, beforeEach, describe, test } from "@std/testing/bdd"; +export { spy, stub } from "@std/testing/mock"; +export { expectTypeOf } from "npm:expect-type"; diff --git a/packages/templates/domain/package.json b/packages/templates/domain/package.json index a4f22df..3d29c7d 100644 --- a/packages/templates/domain/package.json +++ b/packages/templates/domain/package.json @@ -12,14 +12,14 @@ "devDependencies": { "@vitest/coverage-v8": "^2.1.2", "typescript": "^5.6.3", - "vitest": "^2.1.2" + "@fabric/testing": "^2.1.2" }, "dependencies": { "@fabric/core": "workspace:^", "@fabric/domain": "workspace:^" }, "scripts": { - "test": "vitest", + "test": "@fabric/testing", "coverage": "vitest run --coverage", "build": "tsc -p tsconfig.build.json" } diff --git a/packages/templates/lib/package.json b/packages/templates/lib/package.json index b75d100..5b206d3 100644 --- a/packages/templates/lib/package.json +++ b/packages/templates/lib/package.json @@ -15,13 +15,13 @@ "devDependencies": { "@vitest/coverage-v8": "^2.1.2", "typescript": "^5.6.3", - "vitest": "^2.1.2" + "@fabric/testing": "^2.1.2" }, "dependencies": { "@fabric/core": "workspace:^" }, "scripts": { - "test": "vitest", + "test": "@fabric/testing", "coverage": "vitest run --coverage", "build": "tsc -p tsconfig.build.json" }