├── .envrc ├── .gitignore ├── .prettierrc.json ├── .vscode └── settings.json ├── flake.lock ├── flake.nix ├── package.json ├── pnpm-lock.yaml ├── src ├── Accounts.ts ├── Accounts │ ├── AccountsRepo.ts │ ├── Api.ts │ ├── Http.ts │ ├── Policy.ts │ └── UsersRepo.ts ├── Api.ts ├── Domain │ ├── AccessToken.ts │ ├── Account.ts │ ├── Email.ts │ ├── Group.ts │ ├── Person.ts │ ├── Policy.ts │ └── User.ts ├── Groups.ts ├── Groups │ ├── Api.ts │ ├── Http.ts │ ├── Policy.ts │ └── Repo.ts ├── Http.ts ├── People.ts ├── People │ ├── Api.ts │ ├── Http.ts │ ├── Policy.ts │ └── Repo.ts ├── Sql.ts ├── Tracing.ts ├── Uuid.ts ├── client.ts ├── lib │ └── Layer.ts ├── main.ts └── migrations │ ├── 00001_create users.ts │ ├── 00002_create groups.ts │ └── 00003_create_people.ts ├── test └── Accounts.test.ts ├── tsconfig.base.json ├── tsconfig.json ├── tsconfig.src.json ├── tsconfig.test.json └── vitest.config.ts /.envrc: -------------------------------------------------------------------------------- 1 | use flake 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .direnv/ 2 | node_modules/ 3 | dist/ 4 | /data/ 5 | .env 6 | *.tsbuildinfo 7 | .DS_Store 8 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib", 3 | "explorer.sortOrderLexicographicOptions": "upper", 4 | } -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-parts": { 4 | "inputs": { 5 | "nixpkgs-lib": "nixpkgs-lib" 6 | }, 7 | "locked": { 8 | "lastModified": 1727826117, 9 | "narHash": "sha256-K5ZLCyfO/Zj9mPFldf3iwS6oZStJcU4tSpiXTMYaaL0=", 10 | "owner": "hercules-ci", 11 | "repo": "flake-parts", 12 | "rev": "3d04084d54bedc3d6b8b736c70ef449225c361b1", 13 | "type": "github" 14 | }, 15 | "original": { 16 | "owner": "hercules-ci", 17 | "repo": "flake-parts", 18 | "type": "github" 19 | } 20 | }, 21 | "nixpkgs": { 22 | "locked": { 23 | "lastModified": 1729265718, 24 | "narHash": "sha256-4HQI+6LsO3kpWTYuVGIzhJs1cetFcwT7quWCk/6rqeo=", 25 | "owner": "nixos", 26 | "repo": "nixpkgs", 27 | "rev": "ccc0c2126893dd20963580b6478d1a10a4512185", 28 | "type": "github" 29 | }, 30 | "original": { 31 | "owner": "nixos", 32 | "ref": "nixpkgs-unstable", 33 | "repo": "nixpkgs", 34 | "type": "github" 35 | } 36 | }, 37 | "nixpkgs-lib": { 38 | "locked": { 39 | "lastModified": 1727825735, 40 | "narHash": "sha256-0xHYkMkeLVQAMa7gvkddbPqpxph+hDzdu1XdGPJR+Os=", 41 | "type": "tarball", 42 | "url": "https://github.com/NixOS/nixpkgs/archive/fb192fec7cc7a4c26d51779e9bab07ce6fa5597a.tar.gz" 43 | }, 44 | "original": { 45 | "type": "tarball", 46 | "url": "https://github.com/NixOS/nixpkgs/archive/fb192fec7cc7a4c26d51779e9bab07ce6fa5597a.tar.gz" 47 | } 48 | }, 49 | "process-compose-flake": { 50 | "locked": { 51 | "lastModified": 1729544733, 52 | "narHash": "sha256-ir7WTVpG999N07wkOCs1kwZsQKitOv3CNDqNalCMK3c=", 53 | "owner": "Platonic-Systems", 54 | "repo": "process-compose-flake", 55 | "rev": "7241e6b247b65cfa579d6f838a8efc18e5401924", 56 | "type": "github" 57 | }, 58 | "original": { 59 | "owner": "Platonic-Systems", 60 | "repo": "process-compose-flake", 61 | "type": "github" 62 | } 63 | }, 64 | "root": { 65 | "inputs": { 66 | "flake-parts": "flake-parts", 67 | "nixpkgs": "nixpkgs", 68 | "process-compose-flake": "process-compose-flake", 69 | "services-flake": "services-flake" 70 | } 71 | }, 72 | "services-flake": { 73 | "locked": { 74 | "lastModified": 1729545021, 75 | "narHash": "sha256-kiiLawNVU363Ax6LaTutZXFQ+FCdrHMQNmhAZ0nBl7k=", 76 | "owner": "juspay", 77 | "repo": "services-flake", 78 | "rev": "93aa84c4ad56566c5777c07079d49d440b41e9e1", 79 | "type": "github" 80 | }, 81 | "original": { 82 | "owner": "juspay", 83 | "repo": "services-flake", 84 | "type": "github" 85 | } 86 | } 87 | }, 88 | "root": "root", 89 | "version": 7 90 | } 91 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; 4 | flake-parts.url = "github:hercules-ci/flake-parts"; 5 | process-compose-flake.url = "github:Platonic-Systems/process-compose-flake"; 6 | services-flake.url = "github:juspay/services-flake"; 7 | }; 8 | outputs = inputs @ {flake-parts, ...}: 9 | flake-parts.lib.mkFlake {inherit inputs;} { 10 | systems = inputs.nixpkgs.lib.systems.flakeExposed; 11 | imports = [ 12 | inputs.process-compose-flake.flakeModule 13 | ]; 14 | perSystem = {pkgs, ...}: { 15 | devShells.default = pkgs.mkShell { 16 | nativeBuildInputs = with pkgs; [ 17 | corepack 18 | nodejs_22 19 | ]; 20 | }; 21 | 22 | process-compose."default" = {config, ...}: { 23 | imports = [ 24 | inputs.services-flake.processComposeModules.default 25 | ]; 26 | 27 | services.tempo.tempo.enable = true; 28 | services.grafana.grafana = { 29 | enable = true; 30 | http_port = 4000; 31 | extraConf = { 32 | "auth.anonymous" = { 33 | enabled = true; 34 | org_role = "Editor"; 35 | }; 36 | }; 37 | datasources = with config.services.tempo.tempo; [ 38 | { 39 | name = "Tempo"; 40 | type = "tempo"; 41 | access = "proxy"; 42 | url = "http://${httpAddress}:${builtins.toString httpPort}"; 43 | } 44 | ]; 45 | }; 46 | settings.processes.tsx = { 47 | command = "pnpm dev"; 48 | }; 49 | }; 50 | }; 51 | }; 52 | } 53 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "groups-api", 3 | "version": "1.0.0", 4 | "type": "module", 5 | "description": "", 6 | "scripts": { 7 | "dev": "tsx --env-file=.env --watch src/main.ts", 8 | "test": "vitest" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "packageManager": "pnpm@9.12.2", 13 | "devDependencies": { 14 | "@effect/language-service": "^0.2.0", 15 | "@effect/vitest": "^0.13.19", 16 | "@types/node": "^22.10.1", 17 | "@types/uuid": "^10.0.0", 18 | "prettier": "^3.4.1", 19 | "tsup": "^8.3.5", 20 | "tsx": "^4.19.2", 21 | "typescript": "^5.7.2", 22 | "vitest": "^2.1.6" 23 | }, 24 | "dependencies": { 25 | "@effect/experimental": "^0.32.16", 26 | "@effect/opentelemetry": "^0.39.19", 27 | "@effect/platform": "^0.69.31", 28 | "@effect/platform-node": "^0.64.33", 29 | "@effect/sql": "^0.21.3", 30 | "@effect/sql-sqlite-node": "^0.22.3", 31 | "@opentelemetry/exporter-trace-otlp-http": "^0.55.0", 32 | "@opentelemetry/sdk-trace-base": "^1.28.0", 33 | "@opentelemetry/sdk-trace-node": "^1.28.0", 34 | "effect": "^3.10.19", 35 | "uuid": "^11.0.3" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | dependencies: 11 | '@effect/experimental': 12 | specifier: ^0.32.16 13 | version: 0.32.16(@effect/platform-node@0.64.33(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19))(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19)(ws@8.18.0) 14 | '@effect/opentelemetry': 15 | specifier: ^0.39.19 16 | version: 0.39.19(@opentelemetry/api@1.9.0)(@opentelemetry/resources@1.28.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-metrics@1.28.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.28.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-node@1.28.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.28.0)(effect@3.10.19) 17 | '@effect/platform': 18 | specifier: ^0.69.31 19 | version: 0.69.31(effect@3.10.19) 20 | '@effect/platform-node': 21 | specifier: ^0.64.33 22 | version: 0.64.33(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19) 23 | '@effect/sql': 24 | specifier: ^0.21.3 25 | version: 0.21.3(@effect/experimental@0.32.16(@effect/platform-node@0.64.33(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19))(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19)(ws@8.18.0))(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19) 26 | '@effect/sql-sqlite-node': 27 | specifier: ^0.22.3 28 | version: 0.22.3(@effect/platform@0.69.31(effect@3.10.19))(@effect/sql@0.21.3(@effect/experimental@0.32.16(@effect/platform-node@0.64.33(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19))(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19)(ws@8.18.0))(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19))(effect@3.10.19) 29 | '@opentelemetry/exporter-trace-otlp-http': 30 | specifier: ^0.55.0 31 | version: 0.55.0(@opentelemetry/api@1.9.0) 32 | '@opentelemetry/sdk-trace-base': 33 | specifier: ^1.28.0 34 | version: 1.28.0(@opentelemetry/api@1.9.0) 35 | '@opentelemetry/sdk-trace-node': 36 | specifier: ^1.28.0 37 | version: 1.28.0(@opentelemetry/api@1.9.0) 38 | effect: 39 | specifier: ^3.10.19 40 | version: 3.10.19 41 | uuid: 42 | specifier: ^11.0.3 43 | version: 11.0.3 44 | devDependencies: 45 | '@effect/language-service': 46 | specifier: ^0.2.0 47 | version: 0.2.0 48 | '@effect/vitest': 49 | specifier: ^0.13.19 50 | version: 0.13.19(effect@3.10.19)(vitest@2.1.6(@types/node@22.10.1)(tsx@4.19.2)) 51 | '@types/node': 52 | specifier: ^22.10.1 53 | version: 22.10.1 54 | '@types/uuid': 55 | specifier: ^10.0.0 56 | version: 10.0.0 57 | prettier: 58 | specifier: ^3.4.1 59 | version: 3.4.1 60 | tsup: 61 | specifier: ^8.3.5 62 | version: 8.3.5(postcss@8.4.49)(tsx@4.19.2)(typescript@5.7.2) 63 | tsx: 64 | specifier: ^4.19.2 65 | version: 4.19.2 66 | typescript: 67 | specifier: ^5.7.2 68 | version: 5.7.2 69 | vitest: 70 | specifier: ^2.1.6 71 | version: 2.1.6(@types/node@22.10.1)(tsx@4.19.2) 72 | 73 | packages: 74 | 75 | '@effect/experimental@0.32.16': 76 | resolution: {integrity: sha512-uLW88LoN1cqdrlFWYj0NMR/6rMJ1i2SxwfgULJXfnURGaoQzHfkVYU3zccx6+BCyoi6SB1Yr8BSeNNgE5NNqng==} 77 | peerDependencies: 78 | '@effect/platform': ^0.69.31 79 | '@effect/platform-node': ^0.64.33 80 | effect: ^3.10.19 81 | ioredis: ^5 82 | lmdb: ^3 83 | ws: ^8 84 | peerDependenciesMeta: 85 | '@effect/platform-node': 86 | optional: true 87 | ioredis: 88 | optional: true 89 | lmdb: 90 | optional: true 91 | ws: 92 | optional: true 93 | 94 | '@effect/language-service@0.2.0': 95 | resolution: {integrity: sha512-DoK41yKGyQv79o0ca8gxEogMlt+IphXkdCXwgenbQjH1BXKD7tJAr0+VsDhblycQcvQ39f1l9NZN9CBqjM9ALA==} 96 | 97 | '@effect/opentelemetry@0.39.19': 98 | resolution: {integrity: sha512-648f/JCZ0iuYSl6Qxa8i40RX3W9TcT3agDgESVkBLMr8JesQeI+zfc5KReyIMouXOyuuKhNXEBr40s6S3FmLgw==} 99 | peerDependencies: 100 | '@opentelemetry/api': ^1.6 101 | '@opentelemetry/resources': ^1.22 102 | '@opentelemetry/sdk-metrics': ^1.22 103 | '@opentelemetry/sdk-trace-base': ^1.22 104 | '@opentelemetry/sdk-trace-node': ^1.22 105 | '@opentelemetry/sdk-trace-web': ^1.22 106 | '@opentelemetry/semantic-conventions': ^1.24.1 107 | effect: ^3.10.19 108 | peerDependenciesMeta: 109 | '@opentelemetry/sdk-metrics': 110 | optional: true 111 | '@opentelemetry/sdk-trace-base': 112 | optional: true 113 | '@opentelemetry/sdk-trace-node': 114 | optional: true 115 | '@opentelemetry/sdk-trace-web': 116 | optional: true 117 | 118 | '@effect/platform-node-shared@0.19.32': 119 | resolution: {integrity: sha512-qYimZLE2r3sqV8nCOVlOO8zVYozClpOeWbmZ9wtJ7gerEcYP/MRFaPVJ3YKuXvthVm8J/58HM5AE1IrT4VGgGg==} 120 | peerDependencies: 121 | '@effect/platform': ^0.69.31 122 | effect: ^3.10.19 123 | 124 | '@effect/platform-node@0.64.33': 125 | resolution: {integrity: sha512-75f3EwzQzLn4VSNAJnraRXveO2/v5vM/gzIDyYZqXQlhWokpsZt1Avm8ei3tE0r4bOxgRJXYvmNuvkvbuIxpeA==} 126 | peerDependencies: 127 | '@effect/platform': ^0.69.31 128 | effect: ^3.10.19 129 | 130 | '@effect/platform@0.69.31': 131 | resolution: {integrity: sha512-a4JQHieGF/kxH8ZSfEpVrxbdX9haAKFyoOQT5tXiiWoXSgvm+iQ/41FhXqwkWeMddh0hbYJmvmkEljcXUuxWcQ==} 132 | peerDependencies: 133 | effect: ^3.10.19 134 | 135 | '@effect/sql-sqlite-node@0.22.3': 136 | resolution: {integrity: sha512-ZHDbSzo39as0CQdfcHyf7shNuReJf4uise67tDGhxTpPQ1CV4VYSap5BW/Kt8JMX21VrgatVZ98HMx5n5LZjWw==} 137 | peerDependencies: 138 | '@effect/platform': ^0.69.31 139 | '@effect/sql': ^0.21.3 140 | effect: ^3.10.19 141 | 142 | '@effect/sql@0.21.3': 143 | resolution: {integrity: sha512-BqgxpeH1JtGfwe59ejsI9p5bxs165MOymhO7FcpIPj5Q7iS3UD/iNJi3KX992RrwOIgEnMm1AsEy9Bs1gQenpw==} 144 | peerDependencies: 145 | '@effect/experimental': ^0.32.16 146 | '@effect/platform': ^0.69.31 147 | effect: ^3.10.19 148 | 149 | '@effect/vitest@0.13.19': 150 | resolution: {integrity: sha512-5Tixz44IuH+TgXk2WJFEXhdz2IlhrUfxdSagzqKr7qVERZceYvCYka2W+JCgf8pgajNX91fu24vjB0YjTFKNOQ==} 151 | peerDependencies: 152 | effect: ^3.10.19 153 | vitest: ^2.0.5 154 | 155 | '@esbuild/aix-ppc64@0.23.1': 156 | resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==} 157 | engines: {node: '>=18'} 158 | cpu: [ppc64] 159 | os: [aix] 160 | 161 | '@esbuild/aix-ppc64@0.24.0': 162 | resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==} 163 | engines: {node: '>=18'} 164 | cpu: [ppc64] 165 | os: [aix] 166 | 167 | '@esbuild/android-arm64@0.23.1': 168 | resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==} 169 | engines: {node: '>=18'} 170 | cpu: [arm64] 171 | os: [android] 172 | 173 | '@esbuild/android-arm64@0.24.0': 174 | resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==} 175 | engines: {node: '>=18'} 176 | cpu: [arm64] 177 | os: [android] 178 | 179 | '@esbuild/android-arm@0.23.1': 180 | resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==} 181 | engines: {node: '>=18'} 182 | cpu: [arm] 183 | os: [android] 184 | 185 | '@esbuild/android-arm@0.24.0': 186 | resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==} 187 | engines: {node: '>=18'} 188 | cpu: [arm] 189 | os: [android] 190 | 191 | '@esbuild/android-x64@0.23.1': 192 | resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==} 193 | engines: {node: '>=18'} 194 | cpu: [x64] 195 | os: [android] 196 | 197 | '@esbuild/android-x64@0.24.0': 198 | resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==} 199 | engines: {node: '>=18'} 200 | cpu: [x64] 201 | os: [android] 202 | 203 | '@esbuild/darwin-arm64@0.23.1': 204 | resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==} 205 | engines: {node: '>=18'} 206 | cpu: [arm64] 207 | os: [darwin] 208 | 209 | '@esbuild/darwin-arm64@0.24.0': 210 | resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==} 211 | engines: {node: '>=18'} 212 | cpu: [arm64] 213 | os: [darwin] 214 | 215 | '@esbuild/darwin-x64@0.23.1': 216 | resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==} 217 | engines: {node: '>=18'} 218 | cpu: [x64] 219 | os: [darwin] 220 | 221 | '@esbuild/darwin-x64@0.24.0': 222 | resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==} 223 | engines: {node: '>=18'} 224 | cpu: [x64] 225 | os: [darwin] 226 | 227 | '@esbuild/freebsd-arm64@0.23.1': 228 | resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==} 229 | engines: {node: '>=18'} 230 | cpu: [arm64] 231 | os: [freebsd] 232 | 233 | '@esbuild/freebsd-arm64@0.24.0': 234 | resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==} 235 | engines: {node: '>=18'} 236 | cpu: [arm64] 237 | os: [freebsd] 238 | 239 | '@esbuild/freebsd-x64@0.23.1': 240 | resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==} 241 | engines: {node: '>=18'} 242 | cpu: [x64] 243 | os: [freebsd] 244 | 245 | '@esbuild/freebsd-x64@0.24.0': 246 | resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==} 247 | engines: {node: '>=18'} 248 | cpu: [x64] 249 | os: [freebsd] 250 | 251 | '@esbuild/linux-arm64@0.23.1': 252 | resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==} 253 | engines: {node: '>=18'} 254 | cpu: [arm64] 255 | os: [linux] 256 | 257 | '@esbuild/linux-arm64@0.24.0': 258 | resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==} 259 | engines: {node: '>=18'} 260 | cpu: [arm64] 261 | os: [linux] 262 | 263 | '@esbuild/linux-arm@0.23.1': 264 | resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==} 265 | engines: {node: '>=18'} 266 | cpu: [arm] 267 | os: [linux] 268 | 269 | '@esbuild/linux-arm@0.24.0': 270 | resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==} 271 | engines: {node: '>=18'} 272 | cpu: [arm] 273 | os: [linux] 274 | 275 | '@esbuild/linux-ia32@0.23.1': 276 | resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==} 277 | engines: {node: '>=18'} 278 | cpu: [ia32] 279 | os: [linux] 280 | 281 | '@esbuild/linux-ia32@0.24.0': 282 | resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==} 283 | engines: {node: '>=18'} 284 | cpu: [ia32] 285 | os: [linux] 286 | 287 | '@esbuild/linux-loong64@0.23.1': 288 | resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==} 289 | engines: {node: '>=18'} 290 | cpu: [loong64] 291 | os: [linux] 292 | 293 | '@esbuild/linux-loong64@0.24.0': 294 | resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==} 295 | engines: {node: '>=18'} 296 | cpu: [loong64] 297 | os: [linux] 298 | 299 | '@esbuild/linux-mips64el@0.23.1': 300 | resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==} 301 | engines: {node: '>=18'} 302 | cpu: [mips64el] 303 | os: [linux] 304 | 305 | '@esbuild/linux-mips64el@0.24.0': 306 | resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==} 307 | engines: {node: '>=18'} 308 | cpu: [mips64el] 309 | os: [linux] 310 | 311 | '@esbuild/linux-ppc64@0.23.1': 312 | resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==} 313 | engines: {node: '>=18'} 314 | cpu: [ppc64] 315 | os: [linux] 316 | 317 | '@esbuild/linux-ppc64@0.24.0': 318 | resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==} 319 | engines: {node: '>=18'} 320 | cpu: [ppc64] 321 | os: [linux] 322 | 323 | '@esbuild/linux-riscv64@0.23.1': 324 | resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==} 325 | engines: {node: '>=18'} 326 | cpu: [riscv64] 327 | os: [linux] 328 | 329 | '@esbuild/linux-riscv64@0.24.0': 330 | resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==} 331 | engines: {node: '>=18'} 332 | cpu: [riscv64] 333 | os: [linux] 334 | 335 | '@esbuild/linux-s390x@0.23.1': 336 | resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==} 337 | engines: {node: '>=18'} 338 | cpu: [s390x] 339 | os: [linux] 340 | 341 | '@esbuild/linux-s390x@0.24.0': 342 | resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==} 343 | engines: {node: '>=18'} 344 | cpu: [s390x] 345 | os: [linux] 346 | 347 | '@esbuild/linux-x64@0.23.1': 348 | resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==} 349 | engines: {node: '>=18'} 350 | cpu: [x64] 351 | os: [linux] 352 | 353 | '@esbuild/linux-x64@0.24.0': 354 | resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==} 355 | engines: {node: '>=18'} 356 | cpu: [x64] 357 | os: [linux] 358 | 359 | '@esbuild/netbsd-x64@0.23.1': 360 | resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==} 361 | engines: {node: '>=18'} 362 | cpu: [x64] 363 | os: [netbsd] 364 | 365 | '@esbuild/netbsd-x64@0.24.0': 366 | resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==} 367 | engines: {node: '>=18'} 368 | cpu: [x64] 369 | os: [netbsd] 370 | 371 | '@esbuild/openbsd-arm64@0.23.1': 372 | resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==} 373 | engines: {node: '>=18'} 374 | cpu: [arm64] 375 | os: [openbsd] 376 | 377 | '@esbuild/openbsd-arm64@0.24.0': 378 | resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==} 379 | engines: {node: '>=18'} 380 | cpu: [arm64] 381 | os: [openbsd] 382 | 383 | '@esbuild/openbsd-x64@0.23.1': 384 | resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==} 385 | engines: {node: '>=18'} 386 | cpu: [x64] 387 | os: [openbsd] 388 | 389 | '@esbuild/openbsd-x64@0.24.0': 390 | resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==} 391 | engines: {node: '>=18'} 392 | cpu: [x64] 393 | os: [openbsd] 394 | 395 | '@esbuild/sunos-x64@0.23.1': 396 | resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==} 397 | engines: {node: '>=18'} 398 | cpu: [x64] 399 | os: [sunos] 400 | 401 | '@esbuild/sunos-x64@0.24.0': 402 | resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==} 403 | engines: {node: '>=18'} 404 | cpu: [x64] 405 | os: [sunos] 406 | 407 | '@esbuild/win32-arm64@0.23.1': 408 | resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==} 409 | engines: {node: '>=18'} 410 | cpu: [arm64] 411 | os: [win32] 412 | 413 | '@esbuild/win32-arm64@0.24.0': 414 | resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==} 415 | engines: {node: '>=18'} 416 | cpu: [arm64] 417 | os: [win32] 418 | 419 | '@esbuild/win32-ia32@0.23.1': 420 | resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==} 421 | engines: {node: '>=18'} 422 | cpu: [ia32] 423 | os: [win32] 424 | 425 | '@esbuild/win32-ia32@0.24.0': 426 | resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==} 427 | engines: {node: '>=18'} 428 | cpu: [ia32] 429 | os: [win32] 430 | 431 | '@esbuild/win32-x64@0.23.1': 432 | resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==} 433 | engines: {node: '>=18'} 434 | cpu: [x64] 435 | os: [win32] 436 | 437 | '@esbuild/win32-x64@0.24.0': 438 | resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==} 439 | engines: {node: '>=18'} 440 | cpu: [x64] 441 | os: [win32] 442 | 443 | '@isaacs/cliui@8.0.2': 444 | resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} 445 | engines: {node: '>=12'} 446 | 447 | '@jridgewell/gen-mapping@0.3.5': 448 | resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} 449 | engines: {node: '>=6.0.0'} 450 | 451 | '@jridgewell/resolve-uri@3.1.2': 452 | resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} 453 | engines: {node: '>=6.0.0'} 454 | 455 | '@jridgewell/set-array@1.2.1': 456 | resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} 457 | engines: {node: '>=6.0.0'} 458 | 459 | '@jridgewell/sourcemap-codec@1.5.0': 460 | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} 461 | 462 | '@jridgewell/trace-mapping@0.3.25': 463 | resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} 464 | 465 | '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': 466 | resolution: {integrity: sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==} 467 | cpu: [arm64] 468 | os: [darwin] 469 | 470 | '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3': 471 | resolution: {integrity: sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==} 472 | cpu: [x64] 473 | os: [darwin] 474 | 475 | '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3': 476 | resolution: {integrity: sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==} 477 | cpu: [arm64] 478 | os: [linux] 479 | 480 | '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3': 481 | resolution: {integrity: sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==} 482 | cpu: [arm] 483 | os: [linux] 484 | 485 | '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3': 486 | resolution: {integrity: sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==} 487 | cpu: [x64] 488 | os: [linux] 489 | 490 | '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': 491 | resolution: {integrity: sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==} 492 | cpu: [x64] 493 | os: [win32] 494 | 495 | '@opentelemetry/api-logs@0.55.0': 496 | resolution: {integrity: sha512-3cpa+qI45VHYcA5c0bHM6VHo9gicv3p5mlLHNG3rLyjQU8b7e0st1rWtrUn3JbZ3DwwCfhKop4eQ9UuYlC6Pkg==} 497 | engines: {node: '>=14'} 498 | 499 | '@opentelemetry/api@1.9.0': 500 | resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} 501 | engines: {node: '>=8.0.0'} 502 | 503 | '@opentelemetry/context-async-hooks@1.28.0': 504 | resolution: {integrity: sha512-igcl4Ve+F1N2063PJUkesk/GkYyuGIWinYkSyAFTnIj3gzrOgvOA4k747XNdL47HRRL1w/qh7UW8NDuxOLvKFA==} 505 | engines: {node: '>=14'} 506 | peerDependencies: 507 | '@opentelemetry/api': '>=1.0.0 <1.10.0' 508 | 509 | '@opentelemetry/core@1.28.0': 510 | resolution: {integrity: sha512-ZLwRMV+fNDpVmF2WYUdBHlq0eOWtEaUJSusrzjGnBt7iSRvfjFE3RXYUZJrqou/wIDWV0DwQ5KIfYe9WXg9Xqw==} 511 | engines: {node: '>=14'} 512 | peerDependencies: 513 | '@opentelemetry/api': '>=1.0.0 <1.10.0' 514 | 515 | '@opentelemetry/exporter-trace-otlp-http@0.55.0': 516 | resolution: {integrity: sha512-lMiNic63EVHpW+eChmLD2CieDmwQBFi72+LFbh8+5hY0ShrDGrsGP/zuT5MRh7M/vM/UZYO/2A/FYd7CMQGR7A==} 517 | engines: {node: '>=14'} 518 | peerDependencies: 519 | '@opentelemetry/api': ^1.3.0 520 | 521 | '@opentelemetry/otlp-exporter-base@0.55.0': 522 | resolution: {integrity: sha512-iHQI0Zzq3h1T6xUJTVFwmFl5Dt5y1es+fl4kM+k5T/3YvmVyeYkSiF+wHCg6oKrlUAJfk+t55kaAu3sYmt7ZYA==} 523 | engines: {node: '>=14'} 524 | peerDependencies: 525 | '@opentelemetry/api': ^1.3.0 526 | 527 | '@opentelemetry/otlp-transformer@0.55.0': 528 | resolution: {integrity: sha512-kVqEfxtp6mSN2Dhpy0REo1ghP4PYhC1kMHQJ2qVlO99Pc+aigELjZDfg7/YKmL71gR6wVGIeJfiql/eXL7sQPA==} 529 | engines: {node: '>=14'} 530 | peerDependencies: 531 | '@opentelemetry/api': ^1.3.0 532 | 533 | '@opentelemetry/propagator-b3@1.28.0': 534 | resolution: {integrity: sha512-Q7HVDIMwhN5RxL4bECMT4BdbyYSAKkC6U/RGn4NpO/cbqP6ZRg+BS7fPo/pGZi2w8AHfpIGQFXQmE8d2PC5xxQ==} 535 | engines: {node: '>=14'} 536 | peerDependencies: 537 | '@opentelemetry/api': '>=1.0.0 <1.10.0' 538 | 539 | '@opentelemetry/propagator-jaeger@1.28.0': 540 | resolution: {integrity: sha512-wKJ94+s8467CnIRgoSRh0yXm/te0QMOwTq9J01PfG/RzYZvlvN8aRisN2oZ9SznB45dDGnMj3BhUlchSA9cEKA==} 541 | engines: {node: '>=14'} 542 | peerDependencies: 543 | '@opentelemetry/api': '>=1.0.0 <1.10.0' 544 | 545 | '@opentelemetry/resources@1.28.0': 546 | resolution: {integrity: sha512-cIyXSVJjGeTICENN40YSvLDAq4Y2502hGK3iN7tfdynQLKWb3XWZQEkPc+eSx47kiy11YeFAlYkEfXwR1w8kfw==} 547 | engines: {node: '>=14'} 548 | peerDependencies: 549 | '@opentelemetry/api': '>=1.0.0 <1.10.0' 550 | 551 | '@opentelemetry/sdk-logs@0.55.0': 552 | resolution: {integrity: sha512-TSx+Yg/d48uWW6HtjS1AD5x6WPfLhDWLl/WxC7I2fMevaiBuKCuraxTB8MDXieCNnBI24bw9ytyXrDCswFfWgA==} 553 | engines: {node: '>=14'} 554 | peerDependencies: 555 | '@opentelemetry/api': '>=1.4.0 <1.10.0' 556 | 557 | '@opentelemetry/sdk-metrics@1.28.0': 558 | resolution: {integrity: sha512-43tqMK/0BcKTyOvm15/WQ3HLr0Vu/ucAl/D84NO7iSlv6O4eOprxSHa3sUtmYkaZWHqdDJV0AHVz/R6u4JALVQ==} 559 | engines: {node: '>=14'} 560 | peerDependencies: 561 | '@opentelemetry/api': '>=1.3.0 <1.10.0' 562 | 563 | '@opentelemetry/sdk-trace-base@1.28.0': 564 | resolution: {integrity: sha512-ceUVWuCpIao7Y5xE02Xs3nQi0tOGmMea17ecBdwtCvdo9ekmO+ijc9RFDgfifMl7XCBf41zne/1POM3LqSTZDA==} 565 | engines: {node: '>=14'} 566 | peerDependencies: 567 | '@opentelemetry/api': '>=1.0.0 <1.10.0' 568 | 569 | '@opentelemetry/sdk-trace-node@1.28.0': 570 | resolution: {integrity: sha512-N0sYfYXvHpP0FNIyc+UfhLnLSTOuZLytV0qQVrDWIlABeD/DWJIGttS7nYeR14gQLXch0M1DW8zm3VeN6Opwtg==} 571 | engines: {node: '>=14'} 572 | peerDependencies: 573 | '@opentelemetry/api': '>=1.0.0 <1.10.0' 574 | 575 | '@opentelemetry/semantic-conventions@1.27.0': 576 | resolution: {integrity: sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg==} 577 | engines: {node: '>=14'} 578 | 579 | '@opentelemetry/semantic-conventions@1.28.0': 580 | resolution: {integrity: sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==} 581 | engines: {node: '>=14'} 582 | 583 | '@parcel/watcher-android-arm64@2.5.0': 584 | resolution: {integrity: sha512-qlX4eS28bUcQCdribHkg/herLe+0A9RyYC+mm2PXpncit8z5b3nSqGVzMNR3CmtAOgRutiZ02eIJJgP/b1iEFQ==} 585 | engines: {node: '>= 10.0.0'} 586 | cpu: [arm64] 587 | os: [android] 588 | 589 | '@parcel/watcher-darwin-arm64@2.5.0': 590 | resolution: {integrity: sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw==} 591 | engines: {node: '>= 10.0.0'} 592 | cpu: [arm64] 593 | os: [darwin] 594 | 595 | '@parcel/watcher-darwin-x64@2.5.0': 596 | resolution: {integrity: sha512-9rhlwd78saKf18fT869/poydQK8YqlU26TMiNg7AIu7eBp9adqbJZqmdFOsbZ5cnLp5XvRo9wcFmNHgHdWaGYA==} 597 | engines: {node: '>= 10.0.0'} 598 | cpu: [x64] 599 | os: [darwin] 600 | 601 | '@parcel/watcher-freebsd-x64@2.5.0': 602 | resolution: {integrity: sha512-syvfhZzyM8kErg3VF0xpV8dixJ+RzbUaaGaeb7uDuz0D3FK97/mZ5AJQ3XNnDsXX7KkFNtyQyFrXZzQIcN49Tw==} 603 | engines: {node: '>= 10.0.0'} 604 | cpu: [x64] 605 | os: [freebsd] 606 | 607 | '@parcel/watcher-linux-arm-glibc@2.5.0': 608 | resolution: {integrity: sha512-0VQY1K35DQET3dVYWpOaPFecqOT9dbuCfzjxoQyif1Wc574t3kOSkKevULddcR9znz1TcklCE7Ht6NIxjvTqLA==} 609 | engines: {node: '>= 10.0.0'} 610 | cpu: [arm] 611 | os: [linux] 612 | 613 | '@parcel/watcher-linux-arm-musl@2.5.0': 614 | resolution: {integrity: sha512-6uHywSIzz8+vi2lAzFeltnYbdHsDm3iIB57d4g5oaB9vKwjb6N6dRIgZMujw4nm5r6v9/BQH0noq6DzHrqr2pA==} 615 | engines: {node: '>= 10.0.0'} 616 | cpu: [arm] 617 | os: [linux] 618 | 619 | '@parcel/watcher-linux-arm64-glibc@2.5.0': 620 | resolution: {integrity: sha512-BfNjXwZKxBy4WibDb/LDCriWSKLz+jJRL3cM/DllnHH5QUyoiUNEp3GmL80ZqxeumoADfCCP19+qiYiC8gUBjA==} 621 | engines: {node: '>= 10.0.0'} 622 | cpu: [arm64] 623 | os: [linux] 624 | 625 | '@parcel/watcher-linux-arm64-musl@2.5.0': 626 | resolution: {integrity: sha512-S1qARKOphxfiBEkwLUbHjCY9BWPdWnW9j7f7Hb2jPplu8UZ3nes7zpPOW9bkLbHRvWM0WDTsjdOTUgW0xLBN1Q==} 627 | engines: {node: '>= 10.0.0'} 628 | cpu: [arm64] 629 | os: [linux] 630 | 631 | '@parcel/watcher-linux-x64-glibc@2.5.0': 632 | resolution: {integrity: sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw==} 633 | engines: {node: '>= 10.0.0'} 634 | cpu: [x64] 635 | os: [linux] 636 | 637 | '@parcel/watcher-linux-x64-musl@2.5.0': 638 | resolution: {integrity: sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA==} 639 | engines: {node: '>= 10.0.0'} 640 | cpu: [x64] 641 | os: [linux] 642 | 643 | '@parcel/watcher-win32-arm64@2.5.0': 644 | resolution: {integrity: sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig==} 645 | engines: {node: '>= 10.0.0'} 646 | cpu: [arm64] 647 | os: [win32] 648 | 649 | '@parcel/watcher-win32-ia32@2.5.0': 650 | resolution: {integrity: sha512-+rgpsNRKwo8A53elqbbHXdOMtY/tAtTzManTWShB5Kk54N8Q9mzNWV7tV+IbGueCbcj826MfWGU3mprWtuf1TA==} 651 | engines: {node: '>= 10.0.0'} 652 | cpu: [ia32] 653 | os: [win32] 654 | 655 | '@parcel/watcher-win32-x64@2.5.0': 656 | resolution: {integrity: sha512-lPrxve92zEHdgeff3aiu4gDOIt4u7sJYha6wbdEZDCDUhtjTsOMiaJzG5lMY4GkWH8p0fMmO2Ppq5G5XXG+DQw==} 657 | engines: {node: '>= 10.0.0'} 658 | cpu: [x64] 659 | os: [win32] 660 | 661 | '@parcel/watcher@2.5.0': 662 | resolution: {integrity: sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ==} 663 | engines: {node: '>= 10.0.0'} 664 | 665 | '@pkgjs/parseargs@0.11.0': 666 | resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} 667 | engines: {node: '>=14'} 668 | 669 | '@protobufjs/aspromise@1.1.2': 670 | resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} 671 | 672 | '@protobufjs/base64@1.1.2': 673 | resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} 674 | 675 | '@protobufjs/codegen@2.0.4': 676 | resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} 677 | 678 | '@protobufjs/eventemitter@1.1.0': 679 | resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} 680 | 681 | '@protobufjs/fetch@1.1.0': 682 | resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} 683 | 684 | '@protobufjs/float@1.0.2': 685 | resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} 686 | 687 | '@protobufjs/inquire@1.1.0': 688 | resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} 689 | 690 | '@protobufjs/path@1.1.2': 691 | resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} 692 | 693 | '@protobufjs/pool@1.1.0': 694 | resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} 695 | 696 | '@protobufjs/utf8@1.1.0': 697 | resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} 698 | 699 | '@rollup/rollup-android-arm-eabi@4.24.4': 700 | resolution: {integrity: sha512-jfUJrFct/hTA0XDM5p/htWKoNNTbDLY0KRwEt6pyOA6k2fmk0WVwl65PdUdJZgzGEHWx+49LilkcSaumQRyNQw==} 701 | cpu: [arm] 702 | os: [android] 703 | 704 | '@rollup/rollup-android-arm-eabi@4.28.0': 705 | resolution: {integrity: sha512-wLJuPLT6grGZsy34g4N1yRfYeouklTgPhH1gWXCYspenKYD0s3cR99ZevOGw5BexMNywkbV3UkjADisozBmpPQ==} 706 | cpu: [arm] 707 | os: [android] 708 | 709 | '@rollup/rollup-android-arm64@4.24.4': 710 | resolution: {integrity: sha512-j4nrEO6nHU1nZUuCfRKoCcvh7PIywQPUCBa2UsootTHvTHIoIu2BzueInGJhhvQO/2FTRdNYpf63xsgEqH9IhA==} 711 | cpu: [arm64] 712 | os: [android] 713 | 714 | '@rollup/rollup-android-arm64@4.28.0': 715 | resolution: {integrity: sha512-eiNkznlo0dLmVG/6wf+Ifi/v78G4d4QxRhuUl+s8EWZpDewgk7PX3ZyECUXU0Zq/Ca+8nU8cQpNC4Xgn2gFNDA==} 716 | cpu: [arm64] 717 | os: [android] 718 | 719 | '@rollup/rollup-darwin-arm64@4.24.4': 720 | resolution: {integrity: sha512-GmU/QgGtBTeraKyldC7cDVVvAJEOr3dFLKneez/n7BvX57UdhOqDsVwzU7UOnYA7AAOt+Xb26lk79PldDHgMIQ==} 721 | cpu: [arm64] 722 | os: [darwin] 723 | 724 | '@rollup/rollup-darwin-arm64@4.28.0': 725 | resolution: {integrity: sha512-lmKx9yHsppblnLQZOGxdO66gT77bvdBtr/0P+TPOseowE7D9AJoBw8ZDULRasXRWf1Z86/gcOdpBrV6VDUY36Q==} 726 | cpu: [arm64] 727 | os: [darwin] 728 | 729 | '@rollup/rollup-darwin-x64@4.24.4': 730 | resolution: {integrity: sha512-N6oDBiZCBKlwYcsEPXGDE4g9RoxZLK6vT98M8111cW7VsVJFpNEqvJeIPfsCzbf0XEakPslh72X0gnlMi4Ddgg==} 731 | cpu: [x64] 732 | os: [darwin] 733 | 734 | '@rollup/rollup-darwin-x64@4.28.0': 735 | resolution: {integrity: sha512-8hxgfReVs7k9Js1uAIhS6zq3I+wKQETInnWQtgzt8JfGx51R1N6DRVy3F4o0lQwumbErRz52YqwjfvuwRxGv1w==} 736 | cpu: [x64] 737 | os: [darwin] 738 | 739 | '@rollup/rollup-freebsd-arm64@4.24.4': 740 | resolution: {integrity: sha512-py5oNShCCjCyjWXCZNrRGRpjWsF0ic8f4ieBNra5buQz0O/U6mMXCpC1LvrHuhJsNPgRt36tSYMidGzZiJF6mw==} 741 | cpu: [arm64] 742 | os: [freebsd] 743 | 744 | '@rollup/rollup-freebsd-arm64@4.28.0': 745 | resolution: {integrity: sha512-lA1zZB3bFx5oxu9fYud4+g1mt+lYXCoch0M0V/xhqLoGatbzVse0wlSQ1UYOWKpuSu3gyN4qEc0Dxf/DII1bhQ==} 746 | cpu: [arm64] 747 | os: [freebsd] 748 | 749 | '@rollup/rollup-freebsd-x64@4.24.4': 750 | resolution: {integrity: sha512-L7VVVW9FCnTTp4i7KrmHeDsDvjB4++KOBENYtNYAiYl96jeBThFfhP6HVxL74v4SiZEVDH/1ILscR5U9S4ms4g==} 751 | cpu: [x64] 752 | os: [freebsd] 753 | 754 | '@rollup/rollup-freebsd-x64@4.28.0': 755 | resolution: {integrity: sha512-aI2plavbUDjCQB/sRbeUZWX9qp12GfYkYSJOrdYTL/C5D53bsE2/nBPuoiJKoWp5SN78v2Vr8ZPnB+/VbQ2pFA==} 756 | cpu: [x64] 757 | os: [freebsd] 758 | 759 | '@rollup/rollup-linux-arm-gnueabihf@4.24.4': 760 | resolution: {integrity: sha512-10ICosOwYChROdQoQo589N5idQIisxjaFE/PAnX2i0Zr84mY0k9zul1ArH0rnJ/fpgiqfu13TFZR5A5YJLOYZA==} 761 | cpu: [arm] 762 | os: [linux] 763 | 764 | '@rollup/rollup-linux-arm-gnueabihf@4.28.0': 765 | resolution: {integrity: sha512-WXveUPKtfqtaNvpf0iOb0M6xC64GzUX/OowbqfiCSXTdi/jLlOmH0Ba94/OkiY2yTGTwteo4/dsHRfh5bDCZ+w==} 766 | cpu: [arm] 767 | os: [linux] 768 | 769 | '@rollup/rollup-linux-arm-musleabihf@4.24.4': 770 | resolution: {integrity: sha512-ySAfWs69LYC7QhRDZNKqNhz2UKN8LDfbKSMAEtoEI0jitwfAG2iZwVqGACJT+kfYvvz3/JgsLlcBP+WWoKCLcw==} 771 | cpu: [arm] 772 | os: [linux] 773 | 774 | '@rollup/rollup-linux-arm-musleabihf@4.28.0': 775 | resolution: {integrity: sha512-yLc3O2NtOQR67lI79zsSc7lk31xjwcaocvdD1twL64PK1yNaIqCeWI9L5B4MFPAVGEVjH5k1oWSGuYX1Wutxpg==} 776 | cpu: [arm] 777 | os: [linux] 778 | 779 | '@rollup/rollup-linux-arm64-gnu@4.24.4': 780 | resolution: {integrity: sha512-uHYJ0HNOI6pGEeZ/5mgm5arNVTI0nLlmrbdph+pGXpC9tFHFDQmDMOEqkmUObRfosJqpU8RliYoGz06qSdtcjg==} 781 | cpu: [arm64] 782 | os: [linux] 783 | 784 | '@rollup/rollup-linux-arm64-gnu@4.28.0': 785 | resolution: {integrity: sha512-+P9G9hjEpHucHRXqesY+3X9hD2wh0iNnJXX/QhS/J5vTdG6VhNYMxJ2rJkQOxRUd17u5mbMLHM7yWGZdAASfcg==} 786 | cpu: [arm64] 787 | os: [linux] 788 | 789 | '@rollup/rollup-linux-arm64-musl@4.24.4': 790 | resolution: {integrity: sha512-38yiWLemQf7aLHDgTg85fh3hW9stJ0Muk7+s6tIkSUOMmi4Xbv5pH/5Bofnsb6spIwD5FJiR+jg71f0CH5OzoA==} 791 | cpu: [arm64] 792 | os: [linux] 793 | 794 | '@rollup/rollup-linux-arm64-musl@4.28.0': 795 | resolution: {integrity: sha512-1xsm2rCKSTpKzi5/ypT5wfc+4bOGa/9yI/eaOLW0oMs7qpC542APWhl4A37AENGZ6St6GBMWhCCMM6tXgTIplw==} 796 | cpu: [arm64] 797 | os: [linux] 798 | 799 | '@rollup/rollup-linux-powerpc64le-gnu@4.24.4': 800 | resolution: {integrity: sha512-q73XUPnkwt9ZNF2xRS4fvneSuaHw2BXuV5rI4cw0fWYVIWIBeDZX7c7FWhFQPNTnE24172K30I+dViWRVD9TwA==} 801 | cpu: [ppc64] 802 | os: [linux] 803 | 804 | '@rollup/rollup-linux-powerpc64le-gnu@4.28.0': 805 | resolution: {integrity: sha512-zgWxMq8neVQeXL+ouSf6S7DoNeo6EPgi1eeqHXVKQxqPy1B2NvTbaOUWPn/7CfMKL7xvhV0/+fq/Z/J69g1WAQ==} 806 | cpu: [ppc64] 807 | os: [linux] 808 | 809 | '@rollup/rollup-linux-riscv64-gnu@4.24.4': 810 | resolution: {integrity: sha512-Aie/TbmQi6UXokJqDZdmTJuZBCU3QBDA8oTKRGtd4ABi/nHgXICulfg1KI6n9/koDsiDbvHAiQO3YAUNa/7BCw==} 811 | cpu: [riscv64] 812 | os: [linux] 813 | 814 | '@rollup/rollup-linux-riscv64-gnu@4.28.0': 815 | resolution: {integrity: sha512-VEdVYacLniRxbRJLNtzwGt5vwS0ycYshofI7cWAfj7Vg5asqj+pt+Q6x4n+AONSZW/kVm+5nklde0qs2EUwU2g==} 816 | cpu: [riscv64] 817 | os: [linux] 818 | 819 | '@rollup/rollup-linux-s390x-gnu@4.24.4': 820 | resolution: {integrity: sha512-P8MPErVO/y8ohWSP9JY7lLQ8+YMHfTI4bAdtCi3pC2hTeqFJco2jYspzOzTUB8hwUWIIu1xwOrJE11nP+0JFAQ==} 821 | cpu: [s390x] 822 | os: [linux] 823 | 824 | '@rollup/rollup-linux-s390x-gnu@4.28.0': 825 | resolution: {integrity: sha512-LQlP5t2hcDJh8HV8RELD9/xlYtEzJkm/aWGsauvdO2ulfl3QYRjqrKW+mGAIWP5kdNCBheqqqYIGElSRCaXfpw==} 826 | cpu: [s390x] 827 | os: [linux] 828 | 829 | '@rollup/rollup-linux-x64-gnu@4.24.4': 830 | resolution: {integrity: sha512-K03TljaaoPK5FOyNMZAAEmhlyO49LaE4qCsr0lYHUKyb6QacTNF9pnfPpXnFlFD3TXuFbFbz7tJ51FujUXkXYA==} 831 | cpu: [x64] 832 | os: [linux] 833 | 834 | '@rollup/rollup-linux-x64-gnu@4.28.0': 835 | resolution: {integrity: sha512-Nl4KIzteVEKE9BdAvYoTkW19pa7LR/RBrT6F1dJCV/3pbjwDcaOq+edkP0LXuJ9kflW/xOK414X78r+K84+msw==} 836 | cpu: [x64] 837 | os: [linux] 838 | 839 | '@rollup/rollup-linux-x64-musl@4.24.4': 840 | resolution: {integrity: sha512-VJYl4xSl/wqG2D5xTYncVWW+26ICV4wubwN9Gs5NrqhJtayikwCXzPL8GDsLnaLU3WwhQ8W02IinYSFJfyo34Q==} 841 | cpu: [x64] 842 | os: [linux] 843 | 844 | '@rollup/rollup-linux-x64-musl@4.28.0': 845 | resolution: {integrity: sha512-eKpJr4vBDOi4goT75MvW+0dXcNUqisK4jvibY9vDdlgLx+yekxSm55StsHbxUsRxSTt3JEQvlr3cGDkzcSP8bw==} 846 | cpu: [x64] 847 | os: [linux] 848 | 849 | '@rollup/rollup-win32-arm64-msvc@4.24.4': 850 | resolution: {integrity: sha512-ku2GvtPwQfCqoPFIJCqZ8o7bJcj+Y54cZSr43hHca6jLwAiCbZdBUOrqE6y29QFajNAzzpIOwsckaTFmN6/8TA==} 851 | cpu: [arm64] 852 | os: [win32] 853 | 854 | '@rollup/rollup-win32-arm64-msvc@4.28.0': 855 | resolution: {integrity: sha512-Vi+WR62xWGsE/Oj+mD0FNAPY2MEox3cfyG0zLpotZdehPFXwz6lypkGs5y38Jd/NVSbOD02aVad6q6QYF7i8Bg==} 856 | cpu: [arm64] 857 | os: [win32] 858 | 859 | '@rollup/rollup-win32-ia32-msvc@4.24.4': 860 | resolution: {integrity: sha512-V3nCe+eTt/W6UYNr/wGvO1fLpHUrnlirlypZfKCT1fG6hWfqhPgQV/K/mRBXBpxc0eKLIF18pIOFVPh0mqHjlg==} 861 | cpu: [ia32] 862 | os: [win32] 863 | 864 | '@rollup/rollup-win32-ia32-msvc@4.28.0': 865 | resolution: {integrity: sha512-kN/Vpip8emMLn/eOza+4JwqDZBL6MPNpkdaEsgUtW1NYN3DZvZqSQrbKzJcTL6hd8YNmFTn7XGWMwccOcJBL0A==} 866 | cpu: [ia32] 867 | os: [win32] 868 | 869 | '@rollup/rollup-win32-x64-msvc@4.24.4': 870 | resolution: {integrity: sha512-LTw1Dfd0mBIEqUVCxbvTE/LLo+9ZxVC9k99v1v4ahg9Aak6FpqOfNu5kRkeTAn0wphoC4JU7No1/rL+bBCEwhg==} 871 | cpu: [x64] 872 | os: [win32] 873 | 874 | '@rollup/rollup-win32-x64-msvc@4.28.0': 875 | resolution: {integrity: sha512-Bvno2/aZT6usSa7lRDL2+hMjVAGjuqaymF1ApZm31JXzniR/hvr14jpU+/z4X6Gt5BPlzosscyJZGUvguXIqeQ==} 876 | cpu: [x64] 877 | os: [win32] 878 | 879 | '@types/estree@1.0.6': 880 | resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} 881 | 882 | '@types/node@22.10.1': 883 | resolution: {integrity: sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==} 884 | 885 | '@types/uuid@10.0.0': 886 | resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==} 887 | 888 | '@vitest/expect@2.1.6': 889 | resolution: {integrity: sha512-9M1UR9CAmrhJOMoSwVnPh2rELPKhYo0m/CSgqw9PyStpxtkwhmdM6XYlXGKeYyERY1N6EIuzkQ7e3Lm1WKCoUg==} 890 | 891 | '@vitest/mocker@2.1.6': 892 | resolution: {integrity: sha512-MHZp2Z+Q/A3am5oD4WSH04f9B0T7UvwEb+v5W0kCYMhtXGYbdyl2NUk1wdSMqGthmhpiThPDp/hEoVwu16+u1A==} 893 | peerDependencies: 894 | msw: ^2.4.9 895 | vite: ^5.0.0 || ^6.0.0 896 | peerDependenciesMeta: 897 | msw: 898 | optional: true 899 | vite: 900 | optional: true 901 | 902 | '@vitest/pretty-format@2.1.6': 903 | resolution: {integrity: sha512-exZyLcEnHgDMKc54TtHca4McV4sKT+NKAe9ix/yhd/qkYb/TP8HTyXRFDijV19qKqTZM0hPL4753zU/U8L/gAA==} 904 | 905 | '@vitest/runner@2.1.6': 906 | resolution: {integrity: sha512-SjkRGSFyrA82m5nz7To4CkRSEVWn/rwQISHoia/DB8c6IHIhaE/UNAo+7UfeaeJRE979XceGl00LNkIz09RFsA==} 907 | 908 | '@vitest/snapshot@2.1.6': 909 | resolution: {integrity: sha512-5JTWHw8iS9l3v4/VSuthCndw1lN/hpPB+mlgn1BUhFbobeIUj1J1V/Bj2t2ovGEmkXLTckFjQddsxS5T6LuVWw==} 910 | 911 | '@vitest/spy@2.1.6': 912 | resolution: {integrity: sha512-oTFObV8bd4SDdRka5O+mSh5w9irgx5IetrD5i+OsUUsk/shsBoHifwCzy45SAORzAhtNiprUVaK3hSCCzZh1jQ==} 913 | 914 | '@vitest/utils@2.1.6': 915 | resolution: {integrity: sha512-ixNkFy3k4vokOUTU2blIUvOgKq/N2PW8vKIjZZYsGJCMX69MRa9J2sKqX5hY/k5O5Gty3YJChepkqZ3KM9LyIQ==} 916 | 917 | ansi-regex@5.0.1: 918 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 919 | engines: {node: '>=8'} 920 | 921 | ansi-regex@6.1.0: 922 | resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} 923 | engines: {node: '>=12'} 924 | 925 | ansi-styles@4.3.0: 926 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 927 | engines: {node: '>=8'} 928 | 929 | ansi-styles@6.2.1: 930 | resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} 931 | engines: {node: '>=12'} 932 | 933 | any-promise@1.3.0: 934 | resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} 935 | 936 | assertion-error@2.0.1: 937 | resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} 938 | engines: {node: '>=12'} 939 | 940 | balanced-match@1.0.2: 941 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 942 | 943 | base64-js@1.5.1: 944 | resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} 945 | 946 | better-sqlite3@11.6.0: 947 | resolution: {integrity: sha512-2J6k/eVxcFYY2SsTxsXrj6XylzHWPxveCn4fKPKZFv/Vqn/Cd7lOuX4d7rGQXT5zL+97MkNL3nSbCrIoe3LkgA==} 948 | 949 | bindings@1.5.0: 950 | resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} 951 | 952 | bl@4.1.0: 953 | resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} 954 | 955 | brace-expansion@2.0.1: 956 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} 957 | 958 | braces@3.0.3: 959 | resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} 960 | engines: {node: '>=8'} 961 | 962 | buffer@5.7.1: 963 | resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} 964 | 965 | bundle-require@5.0.0: 966 | resolution: {integrity: sha512-GuziW3fSSmopcx4KRymQEJVbZUfqlCqcq7dvs6TYwKRZiegK/2buMxQTPs6MGlNv50wms1699qYO54R8XfRX4w==} 967 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 968 | peerDependencies: 969 | esbuild: '>=0.18' 970 | 971 | cac@6.7.14: 972 | resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} 973 | engines: {node: '>=8'} 974 | 975 | chai@5.1.2: 976 | resolution: {integrity: sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==} 977 | engines: {node: '>=12'} 978 | 979 | check-error@2.1.1: 980 | resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} 981 | engines: {node: '>= 16'} 982 | 983 | chokidar@4.0.1: 984 | resolution: {integrity: sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==} 985 | engines: {node: '>= 14.16.0'} 986 | 987 | chownr@1.1.4: 988 | resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} 989 | 990 | color-convert@2.0.1: 991 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 992 | engines: {node: '>=7.0.0'} 993 | 994 | color-name@1.1.4: 995 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 996 | 997 | commander@4.1.1: 998 | resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} 999 | engines: {node: '>= 6'} 1000 | 1001 | consola@3.2.3: 1002 | resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==} 1003 | engines: {node: ^14.18.0 || >=16.10.0} 1004 | 1005 | cross-spawn@7.0.3: 1006 | resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} 1007 | engines: {node: '>= 8'} 1008 | 1009 | debug@4.3.7: 1010 | resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} 1011 | engines: {node: '>=6.0'} 1012 | peerDependencies: 1013 | supports-color: '*' 1014 | peerDependenciesMeta: 1015 | supports-color: 1016 | optional: true 1017 | 1018 | decompress-response@6.0.0: 1019 | resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} 1020 | engines: {node: '>=10'} 1021 | 1022 | deep-eql@5.0.2: 1023 | resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} 1024 | engines: {node: '>=6'} 1025 | 1026 | deep-extend@0.6.0: 1027 | resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} 1028 | engines: {node: '>=4.0.0'} 1029 | 1030 | detect-libc@1.0.3: 1031 | resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} 1032 | engines: {node: '>=0.10'} 1033 | hasBin: true 1034 | 1035 | detect-libc@2.0.3: 1036 | resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} 1037 | engines: {node: '>=8'} 1038 | 1039 | eastasianwidth@0.2.0: 1040 | resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} 1041 | 1042 | effect@3.10.19: 1043 | resolution: {integrity: sha512-Bc+unZVpHQ/0QkydshNk97OjDXT17Y1M4rBjDZaEPjD6YmlcZxhadEo325OfdPQKWCKEHTdRGtX8/bfQ0RLTIw==} 1044 | 1045 | emoji-regex@8.0.0: 1046 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 1047 | 1048 | emoji-regex@9.2.2: 1049 | resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} 1050 | 1051 | end-of-stream@1.4.4: 1052 | resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} 1053 | 1054 | es-module-lexer@1.5.4: 1055 | resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} 1056 | 1057 | esbuild@0.23.1: 1058 | resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==} 1059 | engines: {node: '>=18'} 1060 | hasBin: true 1061 | 1062 | esbuild@0.24.0: 1063 | resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==} 1064 | engines: {node: '>=18'} 1065 | hasBin: true 1066 | 1067 | estree-walker@3.0.3: 1068 | resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} 1069 | 1070 | expand-template@2.0.3: 1071 | resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} 1072 | engines: {node: '>=6'} 1073 | 1074 | expect-type@1.1.0: 1075 | resolution: {integrity: sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==} 1076 | engines: {node: '>=12.0.0'} 1077 | 1078 | fast-check@3.23.1: 1079 | resolution: {integrity: sha512-u/MudsoQEgBUZgR5N1v87vEgybeVYus9VnDVaIkxkkGP2jt54naghQ3PCQHJiogS8U/GavZCUPFfx3Xkp+NaHw==} 1080 | engines: {node: '>=8.0.0'} 1081 | 1082 | fdir@6.4.2: 1083 | resolution: {integrity: sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==} 1084 | peerDependencies: 1085 | picomatch: ^3 || ^4 1086 | peerDependenciesMeta: 1087 | picomatch: 1088 | optional: true 1089 | 1090 | file-uri-to-path@1.0.0: 1091 | resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} 1092 | 1093 | fill-range@7.1.1: 1094 | resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} 1095 | engines: {node: '>=8'} 1096 | 1097 | find-my-way-ts@0.1.5: 1098 | resolution: {integrity: sha512-4GOTMrpGQVzsCH2ruUn2vmwzV/02zF4q+ybhCIrw/Rkt3L8KWcycdC6aJMctJzwN4fXD4SD5F/4B9Sksh5rE0A==} 1099 | 1100 | foreground-child@3.3.0: 1101 | resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} 1102 | engines: {node: '>=14'} 1103 | 1104 | fs-constants@1.0.0: 1105 | resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} 1106 | 1107 | fsevents@2.3.3: 1108 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 1109 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 1110 | os: [darwin] 1111 | 1112 | get-tsconfig@4.8.1: 1113 | resolution: {integrity: sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==} 1114 | 1115 | github-from-package@0.0.0: 1116 | resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} 1117 | 1118 | glob@10.4.5: 1119 | resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} 1120 | hasBin: true 1121 | 1122 | ieee754@1.2.1: 1123 | resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} 1124 | 1125 | inherits@2.0.4: 1126 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 1127 | 1128 | ini@1.3.8: 1129 | resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} 1130 | 1131 | is-extglob@2.1.1: 1132 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 1133 | engines: {node: '>=0.10.0'} 1134 | 1135 | is-fullwidth-code-point@3.0.0: 1136 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 1137 | engines: {node: '>=8'} 1138 | 1139 | is-glob@4.0.3: 1140 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 1141 | engines: {node: '>=0.10.0'} 1142 | 1143 | is-number@7.0.0: 1144 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 1145 | engines: {node: '>=0.12.0'} 1146 | 1147 | isexe@2.0.0: 1148 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 1149 | 1150 | jackspeak@3.4.3: 1151 | resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} 1152 | 1153 | joycon@3.1.1: 1154 | resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} 1155 | engines: {node: '>=10'} 1156 | 1157 | lilconfig@3.1.2: 1158 | resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} 1159 | engines: {node: '>=14'} 1160 | 1161 | lines-and-columns@1.2.4: 1162 | resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} 1163 | 1164 | load-tsconfig@0.2.5: 1165 | resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} 1166 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 1167 | 1168 | lodash.sortby@4.7.0: 1169 | resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} 1170 | 1171 | long@5.2.3: 1172 | resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} 1173 | 1174 | loupe@3.1.2: 1175 | resolution: {integrity: sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==} 1176 | 1177 | lru-cache@10.4.3: 1178 | resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} 1179 | 1180 | magic-string@0.30.14: 1181 | resolution: {integrity: sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==} 1182 | 1183 | micromatch@4.0.8: 1184 | resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} 1185 | engines: {node: '>=8.6'} 1186 | 1187 | mime@3.0.0: 1188 | resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} 1189 | engines: {node: '>=10.0.0'} 1190 | hasBin: true 1191 | 1192 | mimic-response@3.1.0: 1193 | resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} 1194 | engines: {node: '>=10'} 1195 | 1196 | minimatch@9.0.5: 1197 | resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} 1198 | engines: {node: '>=16 || 14 >=14.17'} 1199 | 1200 | minimist@1.2.8: 1201 | resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} 1202 | 1203 | minipass@7.1.2: 1204 | resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} 1205 | engines: {node: '>=16 || 14 >=14.17'} 1206 | 1207 | mkdirp-classic@0.5.3: 1208 | resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} 1209 | 1210 | ms@2.1.3: 1211 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 1212 | 1213 | msgpackr-extract@3.0.3: 1214 | resolution: {integrity: sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==} 1215 | hasBin: true 1216 | 1217 | msgpackr@1.11.2: 1218 | resolution: {integrity: sha512-F9UngXRlPyWCDEASDpTf6c9uNhGPTqnTeLVt7bN+bU1eajoR/8V9ys2BRaV5C/e5ihE6sJ9uPIKaYt6bFuO32g==} 1219 | 1220 | multipasta@0.2.5: 1221 | resolution: {integrity: sha512-c8eMDb1WwZcE02WVjHoOmUVk7fnKU/RmUcosHACglrWAuPQsEJv+E8430sXj6jNc1jHw0zrS16aCjQh4BcEb4A==} 1222 | 1223 | mz@2.7.0: 1224 | resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} 1225 | 1226 | nanoid@3.3.8: 1227 | resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} 1228 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 1229 | hasBin: true 1230 | 1231 | napi-build-utils@1.0.2: 1232 | resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} 1233 | 1234 | node-abi@3.71.0: 1235 | resolution: {integrity: sha512-SZ40vRiy/+wRTf21hxkkEjPJZpARzUMVcJoQse2EF8qkUWbbO2z7vd5oA/H6bVH6SZQ5STGcu0KRDS7biNRfxw==} 1236 | engines: {node: '>=10'} 1237 | 1238 | node-addon-api@7.1.1: 1239 | resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} 1240 | 1241 | node-gyp-build-optional-packages@5.2.2: 1242 | resolution: {integrity: sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==} 1243 | hasBin: true 1244 | 1245 | object-assign@4.1.1: 1246 | resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} 1247 | engines: {node: '>=0.10.0'} 1248 | 1249 | once@1.4.0: 1250 | resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} 1251 | 1252 | package-json-from-dist@1.0.1: 1253 | resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} 1254 | 1255 | path-key@3.1.1: 1256 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 1257 | engines: {node: '>=8'} 1258 | 1259 | path-scurry@1.11.1: 1260 | resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} 1261 | engines: {node: '>=16 || 14 >=14.18'} 1262 | 1263 | pathe@1.1.2: 1264 | resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} 1265 | 1266 | pathval@2.0.0: 1267 | resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} 1268 | engines: {node: '>= 14.16'} 1269 | 1270 | picocolors@1.1.1: 1271 | resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} 1272 | 1273 | picomatch@2.3.1: 1274 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 1275 | engines: {node: '>=8.6'} 1276 | 1277 | picomatch@4.0.2: 1278 | resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} 1279 | engines: {node: '>=12'} 1280 | 1281 | pirates@4.0.6: 1282 | resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} 1283 | engines: {node: '>= 6'} 1284 | 1285 | postcss-load-config@6.0.1: 1286 | resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} 1287 | engines: {node: '>= 18'} 1288 | peerDependencies: 1289 | jiti: '>=1.21.0' 1290 | postcss: '>=8.0.9' 1291 | tsx: ^4.8.1 1292 | yaml: ^2.4.2 1293 | peerDependenciesMeta: 1294 | jiti: 1295 | optional: true 1296 | postcss: 1297 | optional: true 1298 | tsx: 1299 | optional: true 1300 | yaml: 1301 | optional: true 1302 | 1303 | postcss@8.4.49: 1304 | resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} 1305 | engines: {node: ^10 || ^12 || >=14} 1306 | 1307 | prebuild-install@7.1.2: 1308 | resolution: {integrity: sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==} 1309 | engines: {node: '>=10'} 1310 | hasBin: true 1311 | 1312 | prettier@3.4.1: 1313 | resolution: {integrity: sha512-G+YdqtITVZmOJje6QkXQWzl3fSfMxFwm1tjTyo9exhkmWSqC4Yhd1+lug++IlR2mvRVAxEDDWYkQdeSztajqgg==} 1314 | engines: {node: '>=14'} 1315 | hasBin: true 1316 | 1317 | protobufjs@7.4.0: 1318 | resolution: {integrity: sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==} 1319 | engines: {node: '>=12.0.0'} 1320 | 1321 | pump@3.0.2: 1322 | resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} 1323 | 1324 | punycode@2.3.1: 1325 | resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} 1326 | engines: {node: '>=6'} 1327 | 1328 | pure-rand@6.1.0: 1329 | resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} 1330 | 1331 | rc@1.2.8: 1332 | resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} 1333 | hasBin: true 1334 | 1335 | readable-stream@3.6.2: 1336 | resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} 1337 | engines: {node: '>= 6'} 1338 | 1339 | readdirp@4.0.2: 1340 | resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==} 1341 | engines: {node: '>= 14.16.0'} 1342 | 1343 | resolve-from@5.0.0: 1344 | resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} 1345 | engines: {node: '>=8'} 1346 | 1347 | resolve-pkg-maps@1.0.0: 1348 | resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} 1349 | 1350 | rollup@4.24.4: 1351 | resolution: {integrity: sha512-vGorVWIsWfX3xbcyAS+I047kFKapHYivmkaT63Smj77XwvLSJos6M1xGqZnBPFQFBRZDOcG1QnYEIxAvTr/HjA==} 1352 | engines: {node: '>=18.0.0', npm: '>=8.0.0'} 1353 | hasBin: true 1354 | 1355 | rollup@4.28.0: 1356 | resolution: {integrity: sha512-G9GOrmgWHBma4YfCcX8PjH0qhXSdH8B4HDE2o4/jaxj93S4DPCIDoLcXz99eWMji4hB29UFCEd7B2gwGJDR9cQ==} 1357 | engines: {node: '>=18.0.0', npm: '>=8.0.0'} 1358 | hasBin: true 1359 | 1360 | safe-buffer@5.2.1: 1361 | resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} 1362 | 1363 | semver@7.6.3: 1364 | resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} 1365 | engines: {node: '>=10'} 1366 | hasBin: true 1367 | 1368 | shebang-command@2.0.0: 1369 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 1370 | engines: {node: '>=8'} 1371 | 1372 | shebang-regex@3.0.0: 1373 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 1374 | engines: {node: '>=8'} 1375 | 1376 | siginfo@2.0.0: 1377 | resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} 1378 | 1379 | signal-exit@4.1.0: 1380 | resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} 1381 | engines: {node: '>=14'} 1382 | 1383 | simple-concat@1.0.1: 1384 | resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} 1385 | 1386 | simple-get@4.0.1: 1387 | resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} 1388 | 1389 | source-map-js@1.2.1: 1390 | resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} 1391 | engines: {node: '>=0.10.0'} 1392 | 1393 | source-map@0.8.0-beta.0: 1394 | resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} 1395 | engines: {node: '>= 8'} 1396 | 1397 | stackback@0.0.2: 1398 | resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} 1399 | 1400 | std-env@3.8.0: 1401 | resolution: {integrity: sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==} 1402 | 1403 | string-width@4.2.3: 1404 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 1405 | engines: {node: '>=8'} 1406 | 1407 | string-width@5.1.2: 1408 | resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} 1409 | engines: {node: '>=12'} 1410 | 1411 | string_decoder@1.3.0: 1412 | resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} 1413 | 1414 | strip-ansi@6.0.1: 1415 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 1416 | engines: {node: '>=8'} 1417 | 1418 | strip-ansi@7.1.0: 1419 | resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} 1420 | engines: {node: '>=12'} 1421 | 1422 | strip-json-comments@2.0.1: 1423 | resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} 1424 | engines: {node: '>=0.10.0'} 1425 | 1426 | sucrase@3.35.0: 1427 | resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} 1428 | engines: {node: '>=16 || 14 >=14.17'} 1429 | hasBin: true 1430 | 1431 | tar-fs@2.1.1: 1432 | resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} 1433 | 1434 | tar-stream@2.2.0: 1435 | resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} 1436 | engines: {node: '>=6'} 1437 | 1438 | thenify-all@1.6.0: 1439 | resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} 1440 | engines: {node: '>=0.8'} 1441 | 1442 | thenify@3.3.1: 1443 | resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} 1444 | 1445 | tinybench@2.9.0: 1446 | resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} 1447 | 1448 | tinyexec@0.3.1: 1449 | resolution: {integrity: sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==} 1450 | 1451 | tinyglobby@0.2.10: 1452 | resolution: {integrity: sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==} 1453 | engines: {node: '>=12.0.0'} 1454 | 1455 | tinypool@1.0.2: 1456 | resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} 1457 | engines: {node: ^18.0.0 || >=20.0.0} 1458 | 1459 | tinyrainbow@1.2.0: 1460 | resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} 1461 | engines: {node: '>=14.0.0'} 1462 | 1463 | tinyspy@3.0.2: 1464 | resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} 1465 | engines: {node: '>=14.0.0'} 1466 | 1467 | to-regex-range@5.0.1: 1468 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1469 | engines: {node: '>=8.0'} 1470 | 1471 | tr46@1.0.1: 1472 | resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} 1473 | 1474 | tree-kill@1.2.2: 1475 | resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} 1476 | hasBin: true 1477 | 1478 | ts-interface-checker@0.1.13: 1479 | resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} 1480 | 1481 | tsup@8.3.5: 1482 | resolution: {integrity: sha512-Tunf6r6m6tnZsG9GYWndg0z8dEV7fD733VBFzFJ5Vcm1FtlXB8xBD/rtrBi2a3YKEV7hHtxiZtW5EAVADoe1pA==} 1483 | engines: {node: '>=18'} 1484 | hasBin: true 1485 | peerDependencies: 1486 | '@microsoft/api-extractor': ^7.36.0 1487 | '@swc/core': ^1 1488 | postcss: ^8.4.12 1489 | typescript: '>=4.5.0' 1490 | peerDependenciesMeta: 1491 | '@microsoft/api-extractor': 1492 | optional: true 1493 | '@swc/core': 1494 | optional: true 1495 | postcss: 1496 | optional: true 1497 | typescript: 1498 | optional: true 1499 | 1500 | tsx@4.19.2: 1501 | resolution: {integrity: sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==} 1502 | engines: {node: '>=18.0.0'} 1503 | hasBin: true 1504 | 1505 | tunnel-agent@0.6.0: 1506 | resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} 1507 | 1508 | typescript@5.7.2: 1509 | resolution: {integrity: sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==} 1510 | engines: {node: '>=14.17'} 1511 | hasBin: true 1512 | 1513 | undici-types@6.20.0: 1514 | resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} 1515 | 1516 | undici@6.21.0: 1517 | resolution: {integrity: sha512-BUgJXc752Kou3oOIuU1i+yZZypyZRqNPW0vqoMPl8VaoalSfeR0D8/t4iAS3yirs79SSMTxTag+ZC86uswv+Cw==} 1518 | engines: {node: '>=18.17'} 1519 | 1520 | util-deprecate@1.0.2: 1521 | resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} 1522 | 1523 | uuid@11.0.3: 1524 | resolution: {integrity: sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==} 1525 | hasBin: true 1526 | 1527 | vite-node@2.1.6: 1528 | resolution: {integrity: sha512-DBfJY0n9JUwnyLxPSSUmEePT21j8JZp/sR9n+/gBwQU6DcQOioPdb8/pibWfXForbirSagZCilseYIwaL3f95A==} 1529 | engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} 1530 | hasBin: true 1531 | 1532 | vite@6.0.1: 1533 | resolution: {integrity: sha512-Ldn6gorLGr4mCdFnmeAOLweJxZ34HjKnDm4HGo6P66IEqTxQb36VEdFJQENKxWjupNfoIjvRUnswjn1hpYEpjQ==} 1534 | engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} 1535 | hasBin: true 1536 | peerDependencies: 1537 | '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 1538 | jiti: '>=1.21.0' 1539 | less: '*' 1540 | lightningcss: ^1.21.0 1541 | sass: '*' 1542 | sass-embedded: '*' 1543 | stylus: '*' 1544 | sugarss: '*' 1545 | terser: ^5.16.0 1546 | tsx: ^4.8.1 1547 | yaml: ^2.4.2 1548 | peerDependenciesMeta: 1549 | '@types/node': 1550 | optional: true 1551 | jiti: 1552 | optional: true 1553 | less: 1554 | optional: true 1555 | lightningcss: 1556 | optional: true 1557 | sass: 1558 | optional: true 1559 | sass-embedded: 1560 | optional: true 1561 | stylus: 1562 | optional: true 1563 | sugarss: 1564 | optional: true 1565 | terser: 1566 | optional: true 1567 | tsx: 1568 | optional: true 1569 | yaml: 1570 | optional: true 1571 | 1572 | vitest@2.1.6: 1573 | resolution: {integrity: sha512-isUCkvPL30J4c5O5hgONeFRsDmlw6kzFEdLQHLezmDdKQHy8Ke/B/dgdTMEgU0vm+iZ0TjW8GuK83DiahBoKWQ==} 1574 | engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} 1575 | hasBin: true 1576 | peerDependencies: 1577 | '@edge-runtime/vm': '*' 1578 | '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 1579 | '@vitest/browser': 2.1.6 1580 | '@vitest/ui': 2.1.6 1581 | happy-dom: '*' 1582 | jsdom: '*' 1583 | peerDependenciesMeta: 1584 | '@edge-runtime/vm': 1585 | optional: true 1586 | '@types/node': 1587 | optional: true 1588 | '@vitest/browser': 1589 | optional: true 1590 | '@vitest/ui': 1591 | optional: true 1592 | happy-dom: 1593 | optional: true 1594 | jsdom: 1595 | optional: true 1596 | 1597 | webidl-conversions@4.0.2: 1598 | resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} 1599 | 1600 | whatwg-url@7.1.0: 1601 | resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} 1602 | 1603 | which@2.0.2: 1604 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 1605 | engines: {node: '>= 8'} 1606 | hasBin: true 1607 | 1608 | why-is-node-running@2.3.0: 1609 | resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} 1610 | engines: {node: '>=8'} 1611 | hasBin: true 1612 | 1613 | wrap-ansi@7.0.0: 1614 | resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} 1615 | engines: {node: '>=10'} 1616 | 1617 | wrap-ansi@8.1.0: 1618 | resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} 1619 | engines: {node: '>=12'} 1620 | 1621 | wrappy@1.0.2: 1622 | resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} 1623 | 1624 | ws@8.18.0: 1625 | resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} 1626 | engines: {node: '>=10.0.0'} 1627 | peerDependencies: 1628 | bufferutil: ^4.0.1 1629 | utf-8-validate: '>=5.0.2' 1630 | peerDependenciesMeta: 1631 | bufferutil: 1632 | optional: true 1633 | utf-8-validate: 1634 | optional: true 1635 | 1636 | snapshots: 1637 | 1638 | '@effect/experimental@0.32.16(@effect/platform-node@0.64.33(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19))(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19)(ws@8.18.0)': 1639 | dependencies: 1640 | '@effect/platform': 0.69.31(effect@3.10.19) 1641 | effect: 3.10.19 1642 | msgpackr: 1.11.2 1643 | optionalDependencies: 1644 | '@effect/platform-node': 0.64.33(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19) 1645 | ws: 8.18.0 1646 | 1647 | '@effect/language-service@0.2.0': {} 1648 | 1649 | '@effect/opentelemetry@0.39.19(@opentelemetry/api@1.9.0)(@opentelemetry/resources@1.28.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-metrics@1.28.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.28.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-node@1.28.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.28.0)(effect@3.10.19)': 1650 | dependencies: 1651 | '@opentelemetry/api': 1.9.0 1652 | '@opentelemetry/resources': 1.28.0(@opentelemetry/api@1.9.0) 1653 | '@opentelemetry/semantic-conventions': 1.28.0 1654 | effect: 3.10.19 1655 | optionalDependencies: 1656 | '@opentelemetry/sdk-metrics': 1.28.0(@opentelemetry/api@1.9.0) 1657 | '@opentelemetry/sdk-trace-base': 1.28.0(@opentelemetry/api@1.9.0) 1658 | '@opentelemetry/sdk-trace-node': 1.28.0(@opentelemetry/api@1.9.0) 1659 | 1660 | '@effect/platform-node-shared@0.19.32(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19)': 1661 | dependencies: 1662 | '@effect/platform': 0.69.31(effect@3.10.19) 1663 | '@parcel/watcher': 2.5.0 1664 | effect: 3.10.19 1665 | multipasta: 0.2.5 1666 | 1667 | '@effect/platform-node@0.64.33(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19)': 1668 | dependencies: 1669 | '@effect/platform': 0.69.31(effect@3.10.19) 1670 | '@effect/platform-node-shared': 0.19.32(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19) 1671 | effect: 3.10.19 1672 | mime: 3.0.0 1673 | undici: 6.21.0 1674 | ws: 8.18.0 1675 | transitivePeerDependencies: 1676 | - bufferutil 1677 | - utf-8-validate 1678 | 1679 | '@effect/platform@0.69.31(effect@3.10.19)': 1680 | dependencies: 1681 | effect: 3.10.19 1682 | find-my-way-ts: 0.1.5 1683 | multipasta: 0.2.5 1684 | 1685 | '@effect/sql-sqlite-node@0.22.3(@effect/platform@0.69.31(effect@3.10.19))(@effect/sql@0.21.3(@effect/experimental@0.32.16(@effect/platform-node@0.64.33(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19))(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19)(ws@8.18.0))(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19))(effect@3.10.19)': 1686 | dependencies: 1687 | '@effect/platform': 0.69.31(effect@3.10.19) 1688 | '@effect/sql': 0.21.3(@effect/experimental@0.32.16(@effect/platform-node@0.64.33(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19))(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19)(ws@8.18.0))(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19) 1689 | '@opentelemetry/semantic-conventions': 1.28.0 1690 | better-sqlite3: 11.6.0 1691 | effect: 3.10.19 1692 | 1693 | '@effect/sql@0.21.3(@effect/experimental@0.32.16(@effect/platform-node@0.64.33(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19))(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19)(ws@8.18.0))(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19)': 1694 | dependencies: 1695 | '@effect/experimental': 0.32.16(@effect/platform-node@0.64.33(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19))(@effect/platform@0.69.31(effect@3.10.19))(effect@3.10.19)(ws@8.18.0) 1696 | '@effect/platform': 0.69.31(effect@3.10.19) 1697 | '@opentelemetry/semantic-conventions': 1.28.0 1698 | effect: 3.10.19 1699 | 1700 | '@effect/vitest@0.13.19(effect@3.10.19)(vitest@2.1.6(@types/node@22.10.1)(tsx@4.19.2))': 1701 | dependencies: 1702 | effect: 3.10.19 1703 | vitest: 2.1.6(@types/node@22.10.1)(tsx@4.19.2) 1704 | 1705 | '@esbuild/aix-ppc64@0.23.1': 1706 | optional: true 1707 | 1708 | '@esbuild/aix-ppc64@0.24.0': 1709 | optional: true 1710 | 1711 | '@esbuild/android-arm64@0.23.1': 1712 | optional: true 1713 | 1714 | '@esbuild/android-arm64@0.24.0': 1715 | optional: true 1716 | 1717 | '@esbuild/android-arm@0.23.1': 1718 | optional: true 1719 | 1720 | '@esbuild/android-arm@0.24.0': 1721 | optional: true 1722 | 1723 | '@esbuild/android-x64@0.23.1': 1724 | optional: true 1725 | 1726 | '@esbuild/android-x64@0.24.0': 1727 | optional: true 1728 | 1729 | '@esbuild/darwin-arm64@0.23.1': 1730 | optional: true 1731 | 1732 | '@esbuild/darwin-arm64@0.24.0': 1733 | optional: true 1734 | 1735 | '@esbuild/darwin-x64@0.23.1': 1736 | optional: true 1737 | 1738 | '@esbuild/darwin-x64@0.24.0': 1739 | optional: true 1740 | 1741 | '@esbuild/freebsd-arm64@0.23.1': 1742 | optional: true 1743 | 1744 | '@esbuild/freebsd-arm64@0.24.0': 1745 | optional: true 1746 | 1747 | '@esbuild/freebsd-x64@0.23.1': 1748 | optional: true 1749 | 1750 | '@esbuild/freebsd-x64@0.24.0': 1751 | optional: true 1752 | 1753 | '@esbuild/linux-arm64@0.23.1': 1754 | optional: true 1755 | 1756 | '@esbuild/linux-arm64@0.24.0': 1757 | optional: true 1758 | 1759 | '@esbuild/linux-arm@0.23.1': 1760 | optional: true 1761 | 1762 | '@esbuild/linux-arm@0.24.0': 1763 | optional: true 1764 | 1765 | '@esbuild/linux-ia32@0.23.1': 1766 | optional: true 1767 | 1768 | '@esbuild/linux-ia32@0.24.0': 1769 | optional: true 1770 | 1771 | '@esbuild/linux-loong64@0.23.1': 1772 | optional: true 1773 | 1774 | '@esbuild/linux-loong64@0.24.0': 1775 | optional: true 1776 | 1777 | '@esbuild/linux-mips64el@0.23.1': 1778 | optional: true 1779 | 1780 | '@esbuild/linux-mips64el@0.24.0': 1781 | optional: true 1782 | 1783 | '@esbuild/linux-ppc64@0.23.1': 1784 | optional: true 1785 | 1786 | '@esbuild/linux-ppc64@0.24.0': 1787 | optional: true 1788 | 1789 | '@esbuild/linux-riscv64@0.23.1': 1790 | optional: true 1791 | 1792 | '@esbuild/linux-riscv64@0.24.0': 1793 | optional: true 1794 | 1795 | '@esbuild/linux-s390x@0.23.1': 1796 | optional: true 1797 | 1798 | '@esbuild/linux-s390x@0.24.0': 1799 | optional: true 1800 | 1801 | '@esbuild/linux-x64@0.23.1': 1802 | optional: true 1803 | 1804 | '@esbuild/linux-x64@0.24.0': 1805 | optional: true 1806 | 1807 | '@esbuild/netbsd-x64@0.23.1': 1808 | optional: true 1809 | 1810 | '@esbuild/netbsd-x64@0.24.0': 1811 | optional: true 1812 | 1813 | '@esbuild/openbsd-arm64@0.23.1': 1814 | optional: true 1815 | 1816 | '@esbuild/openbsd-arm64@0.24.0': 1817 | optional: true 1818 | 1819 | '@esbuild/openbsd-x64@0.23.1': 1820 | optional: true 1821 | 1822 | '@esbuild/openbsd-x64@0.24.0': 1823 | optional: true 1824 | 1825 | '@esbuild/sunos-x64@0.23.1': 1826 | optional: true 1827 | 1828 | '@esbuild/sunos-x64@0.24.0': 1829 | optional: true 1830 | 1831 | '@esbuild/win32-arm64@0.23.1': 1832 | optional: true 1833 | 1834 | '@esbuild/win32-arm64@0.24.0': 1835 | optional: true 1836 | 1837 | '@esbuild/win32-ia32@0.23.1': 1838 | optional: true 1839 | 1840 | '@esbuild/win32-ia32@0.24.0': 1841 | optional: true 1842 | 1843 | '@esbuild/win32-x64@0.23.1': 1844 | optional: true 1845 | 1846 | '@esbuild/win32-x64@0.24.0': 1847 | optional: true 1848 | 1849 | '@isaacs/cliui@8.0.2': 1850 | dependencies: 1851 | string-width: 5.1.2 1852 | string-width-cjs: string-width@4.2.3 1853 | strip-ansi: 7.1.0 1854 | strip-ansi-cjs: strip-ansi@6.0.1 1855 | wrap-ansi: 8.1.0 1856 | wrap-ansi-cjs: wrap-ansi@7.0.0 1857 | 1858 | '@jridgewell/gen-mapping@0.3.5': 1859 | dependencies: 1860 | '@jridgewell/set-array': 1.2.1 1861 | '@jridgewell/sourcemap-codec': 1.5.0 1862 | '@jridgewell/trace-mapping': 0.3.25 1863 | 1864 | '@jridgewell/resolve-uri@3.1.2': {} 1865 | 1866 | '@jridgewell/set-array@1.2.1': {} 1867 | 1868 | '@jridgewell/sourcemap-codec@1.5.0': {} 1869 | 1870 | '@jridgewell/trace-mapping@0.3.25': 1871 | dependencies: 1872 | '@jridgewell/resolve-uri': 3.1.2 1873 | '@jridgewell/sourcemap-codec': 1.5.0 1874 | 1875 | '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': 1876 | optional: true 1877 | 1878 | '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3': 1879 | optional: true 1880 | 1881 | '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3': 1882 | optional: true 1883 | 1884 | '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3': 1885 | optional: true 1886 | 1887 | '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3': 1888 | optional: true 1889 | 1890 | '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': 1891 | optional: true 1892 | 1893 | '@opentelemetry/api-logs@0.55.0': 1894 | dependencies: 1895 | '@opentelemetry/api': 1.9.0 1896 | 1897 | '@opentelemetry/api@1.9.0': {} 1898 | 1899 | '@opentelemetry/context-async-hooks@1.28.0(@opentelemetry/api@1.9.0)': 1900 | dependencies: 1901 | '@opentelemetry/api': 1.9.0 1902 | 1903 | '@opentelemetry/core@1.28.0(@opentelemetry/api@1.9.0)': 1904 | dependencies: 1905 | '@opentelemetry/api': 1.9.0 1906 | '@opentelemetry/semantic-conventions': 1.27.0 1907 | 1908 | '@opentelemetry/exporter-trace-otlp-http@0.55.0(@opentelemetry/api@1.9.0)': 1909 | dependencies: 1910 | '@opentelemetry/api': 1.9.0 1911 | '@opentelemetry/core': 1.28.0(@opentelemetry/api@1.9.0) 1912 | '@opentelemetry/otlp-exporter-base': 0.55.0(@opentelemetry/api@1.9.0) 1913 | '@opentelemetry/otlp-transformer': 0.55.0(@opentelemetry/api@1.9.0) 1914 | '@opentelemetry/resources': 1.28.0(@opentelemetry/api@1.9.0) 1915 | '@opentelemetry/sdk-trace-base': 1.28.0(@opentelemetry/api@1.9.0) 1916 | 1917 | '@opentelemetry/otlp-exporter-base@0.55.0(@opentelemetry/api@1.9.0)': 1918 | dependencies: 1919 | '@opentelemetry/api': 1.9.0 1920 | '@opentelemetry/core': 1.28.0(@opentelemetry/api@1.9.0) 1921 | '@opentelemetry/otlp-transformer': 0.55.0(@opentelemetry/api@1.9.0) 1922 | 1923 | '@opentelemetry/otlp-transformer@0.55.0(@opentelemetry/api@1.9.0)': 1924 | dependencies: 1925 | '@opentelemetry/api': 1.9.0 1926 | '@opentelemetry/api-logs': 0.55.0 1927 | '@opentelemetry/core': 1.28.0(@opentelemetry/api@1.9.0) 1928 | '@opentelemetry/resources': 1.28.0(@opentelemetry/api@1.9.0) 1929 | '@opentelemetry/sdk-logs': 0.55.0(@opentelemetry/api@1.9.0) 1930 | '@opentelemetry/sdk-metrics': 1.28.0(@opentelemetry/api@1.9.0) 1931 | '@opentelemetry/sdk-trace-base': 1.28.0(@opentelemetry/api@1.9.0) 1932 | protobufjs: 7.4.0 1933 | 1934 | '@opentelemetry/propagator-b3@1.28.0(@opentelemetry/api@1.9.0)': 1935 | dependencies: 1936 | '@opentelemetry/api': 1.9.0 1937 | '@opentelemetry/core': 1.28.0(@opentelemetry/api@1.9.0) 1938 | 1939 | '@opentelemetry/propagator-jaeger@1.28.0(@opentelemetry/api@1.9.0)': 1940 | dependencies: 1941 | '@opentelemetry/api': 1.9.0 1942 | '@opentelemetry/core': 1.28.0(@opentelemetry/api@1.9.0) 1943 | 1944 | '@opentelemetry/resources@1.28.0(@opentelemetry/api@1.9.0)': 1945 | dependencies: 1946 | '@opentelemetry/api': 1.9.0 1947 | '@opentelemetry/core': 1.28.0(@opentelemetry/api@1.9.0) 1948 | '@opentelemetry/semantic-conventions': 1.27.0 1949 | 1950 | '@opentelemetry/sdk-logs@0.55.0(@opentelemetry/api@1.9.0)': 1951 | dependencies: 1952 | '@opentelemetry/api': 1.9.0 1953 | '@opentelemetry/api-logs': 0.55.0 1954 | '@opentelemetry/core': 1.28.0(@opentelemetry/api@1.9.0) 1955 | '@opentelemetry/resources': 1.28.0(@opentelemetry/api@1.9.0) 1956 | 1957 | '@opentelemetry/sdk-metrics@1.28.0(@opentelemetry/api@1.9.0)': 1958 | dependencies: 1959 | '@opentelemetry/api': 1.9.0 1960 | '@opentelemetry/core': 1.28.0(@opentelemetry/api@1.9.0) 1961 | '@opentelemetry/resources': 1.28.0(@opentelemetry/api@1.9.0) 1962 | 1963 | '@opentelemetry/sdk-trace-base@1.28.0(@opentelemetry/api@1.9.0)': 1964 | dependencies: 1965 | '@opentelemetry/api': 1.9.0 1966 | '@opentelemetry/core': 1.28.0(@opentelemetry/api@1.9.0) 1967 | '@opentelemetry/resources': 1.28.0(@opentelemetry/api@1.9.0) 1968 | '@opentelemetry/semantic-conventions': 1.27.0 1969 | 1970 | '@opentelemetry/sdk-trace-node@1.28.0(@opentelemetry/api@1.9.0)': 1971 | dependencies: 1972 | '@opentelemetry/api': 1.9.0 1973 | '@opentelemetry/context-async-hooks': 1.28.0(@opentelemetry/api@1.9.0) 1974 | '@opentelemetry/core': 1.28.0(@opentelemetry/api@1.9.0) 1975 | '@opentelemetry/propagator-b3': 1.28.0(@opentelemetry/api@1.9.0) 1976 | '@opentelemetry/propagator-jaeger': 1.28.0(@opentelemetry/api@1.9.0) 1977 | '@opentelemetry/sdk-trace-base': 1.28.0(@opentelemetry/api@1.9.0) 1978 | semver: 7.6.3 1979 | 1980 | '@opentelemetry/semantic-conventions@1.27.0': {} 1981 | 1982 | '@opentelemetry/semantic-conventions@1.28.0': {} 1983 | 1984 | '@parcel/watcher-android-arm64@2.5.0': 1985 | optional: true 1986 | 1987 | '@parcel/watcher-darwin-arm64@2.5.0': 1988 | optional: true 1989 | 1990 | '@parcel/watcher-darwin-x64@2.5.0': 1991 | optional: true 1992 | 1993 | '@parcel/watcher-freebsd-x64@2.5.0': 1994 | optional: true 1995 | 1996 | '@parcel/watcher-linux-arm-glibc@2.5.0': 1997 | optional: true 1998 | 1999 | '@parcel/watcher-linux-arm-musl@2.5.0': 2000 | optional: true 2001 | 2002 | '@parcel/watcher-linux-arm64-glibc@2.5.0': 2003 | optional: true 2004 | 2005 | '@parcel/watcher-linux-arm64-musl@2.5.0': 2006 | optional: true 2007 | 2008 | '@parcel/watcher-linux-x64-glibc@2.5.0': 2009 | optional: true 2010 | 2011 | '@parcel/watcher-linux-x64-musl@2.5.0': 2012 | optional: true 2013 | 2014 | '@parcel/watcher-win32-arm64@2.5.0': 2015 | optional: true 2016 | 2017 | '@parcel/watcher-win32-ia32@2.5.0': 2018 | optional: true 2019 | 2020 | '@parcel/watcher-win32-x64@2.5.0': 2021 | optional: true 2022 | 2023 | '@parcel/watcher@2.5.0': 2024 | dependencies: 2025 | detect-libc: 1.0.3 2026 | is-glob: 4.0.3 2027 | micromatch: 4.0.8 2028 | node-addon-api: 7.1.1 2029 | optionalDependencies: 2030 | '@parcel/watcher-android-arm64': 2.5.0 2031 | '@parcel/watcher-darwin-arm64': 2.5.0 2032 | '@parcel/watcher-darwin-x64': 2.5.0 2033 | '@parcel/watcher-freebsd-x64': 2.5.0 2034 | '@parcel/watcher-linux-arm-glibc': 2.5.0 2035 | '@parcel/watcher-linux-arm-musl': 2.5.0 2036 | '@parcel/watcher-linux-arm64-glibc': 2.5.0 2037 | '@parcel/watcher-linux-arm64-musl': 2.5.0 2038 | '@parcel/watcher-linux-x64-glibc': 2.5.0 2039 | '@parcel/watcher-linux-x64-musl': 2.5.0 2040 | '@parcel/watcher-win32-arm64': 2.5.0 2041 | '@parcel/watcher-win32-ia32': 2.5.0 2042 | '@parcel/watcher-win32-x64': 2.5.0 2043 | 2044 | '@pkgjs/parseargs@0.11.0': 2045 | optional: true 2046 | 2047 | '@protobufjs/aspromise@1.1.2': {} 2048 | 2049 | '@protobufjs/base64@1.1.2': {} 2050 | 2051 | '@protobufjs/codegen@2.0.4': {} 2052 | 2053 | '@protobufjs/eventemitter@1.1.0': {} 2054 | 2055 | '@protobufjs/fetch@1.1.0': 2056 | dependencies: 2057 | '@protobufjs/aspromise': 1.1.2 2058 | '@protobufjs/inquire': 1.1.0 2059 | 2060 | '@protobufjs/float@1.0.2': {} 2061 | 2062 | '@protobufjs/inquire@1.1.0': {} 2063 | 2064 | '@protobufjs/path@1.1.2': {} 2065 | 2066 | '@protobufjs/pool@1.1.0': {} 2067 | 2068 | '@protobufjs/utf8@1.1.0': {} 2069 | 2070 | '@rollup/rollup-android-arm-eabi@4.24.4': 2071 | optional: true 2072 | 2073 | '@rollup/rollup-android-arm-eabi@4.28.0': 2074 | optional: true 2075 | 2076 | '@rollup/rollup-android-arm64@4.24.4': 2077 | optional: true 2078 | 2079 | '@rollup/rollup-android-arm64@4.28.0': 2080 | optional: true 2081 | 2082 | '@rollup/rollup-darwin-arm64@4.24.4': 2083 | optional: true 2084 | 2085 | '@rollup/rollup-darwin-arm64@4.28.0': 2086 | optional: true 2087 | 2088 | '@rollup/rollup-darwin-x64@4.24.4': 2089 | optional: true 2090 | 2091 | '@rollup/rollup-darwin-x64@4.28.0': 2092 | optional: true 2093 | 2094 | '@rollup/rollup-freebsd-arm64@4.24.4': 2095 | optional: true 2096 | 2097 | '@rollup/rollup-freebsd-arm64@4.28.0': 2098 | optional: true 2099 | 2100 | '@rollup/rollup-freebsd-x64@4.24.4': 2101 | optional: true 2102 | 2103 | '@rollup/rollup-freebsd-x64@4.28.0': 2104 | optional: true 2105 | 2106 | '@rollup/rollup-linux-arm-gnueabihf@4.24.4': 2107 | optional: true 2108 | 2109 | '@rollup/rollup-linux-arm-gnueabihf@4.28.0': 2110 | optional: true 2111 | 2112 | '@rollup/rollup-linux-arm-musleabihf@4.24.4': 2113 | optional: true 2114 | 2115 | '@rollup/rollup-linux-arm-musleabihf@4.28.0': 2116 | optional: true 2117 | 2118 | '@rollup/rollup-linux-arm64-gnu@4.24.4': 2119 | optional: true 2120 | 2121 | '@rollup/rollup-linux-arm64-gnu@4.28.0': 2122 | optional: true 2123 | 2124 | '@rollup/rollup-linux-arm64-musl@4.24.4': 2125 | optional: true 2126 | 2127 | '@rollup/rollup-linux-arm64-musl@4.28.0': 2128 | optional: true 2129 | 2130 | '@rollup/rollup-linux-powerpc64le-gnu@4.24.4': 2131 | optional: true 2132 | 2133 | '@rollup/rollup-linux-powerpc64le-gnu@4.28.0': 2134 | optional: true 2135 | 2136 | '@rollup/rollup-linux-riscv64-gnu@4.24.4': 2137 | optional: true 2138 | 2139 | '@rollup/rollup-linux-riscv64-gnu@4.28.0': 2140 | optional: true 2141 | 2142 | '@rollup/rollup-linux-s390x-gnu@4.24.4': 2143 | optional: true 2144 | 2145 | '@rollup/rollup-linux-s390x-gnu@4.28.0': 2146 | optional: true 2147 | 2148 | '@rollup/rollup-linux-x64-gnu@4.24.4': 2149 | optional: true 2150 | 2151 | '@rollup/rollup-linux-x64-gnu@4.28.0': 2152 | optional: true 2153 | 2154 | '@rollup/rollup-linux-x64-musl@4.24.4': 2155 | optional: true 2156 | 2157 | '@rollup/rollup-linux-x64-musl@4.28.0': 2158 | optional: true 2159 | 2160 | '@rollup/rollup-win32-arm64-msvc@4.24.4': 2161 | optional: true 2162 | 2163 | '@rollup/rollup-win32-arm64-msvc@4.28.0': 2164 | optional: true 2165 | 2166 | '@rollup/rollup-win32-ia32-msvc@4.24.4': 2167 | optional: true 2168 | 2169 | '@rollup/rollup-win32-ia32-msvc@4.28.0': 2170 | optional: true 2171 | 2172 | '@rollup/rollup-win32-x64-msvc@4.24.4': 2173 | optional: true 2174 | 2175 | '@rollup/rollup-win32-x64-msvc@4.28.0': 2176 | optional: true 2177 | 2178 | '@types/estree@1.0.6': {} 2179 | 2180 | '@types/node@22.10.1': 2181 | dependencies: 2182 | undici-types: 6.20.0 2183 | 2184 | '@types/uuid@10.0.0': {} 2185 | 2186 | '@vitest/expect@2.1.6': 2187 | dependencies: 2188 | '@vitest/spy': 2.1.6 2189 | '@vitest/utils': 2.1.6 2190 | chai: 5.1.2 2191 | tinyrainbow: 1.2.0 2192 | 2193 | '@vitest/mocker@2.1.6(vite@6.0.1(@types/node@22.10.1)(tsx@4.19.2))': 2194 | dependencies: 2195 | '@vitest/spy': 2.1.6 2196 | estree-walker: 3.0.3 2197 | magic-string: 0.30.14 2198 | optionalDependencies: 2199 | vite: 6.0.1(@types/node@22.10.1)(tsx@4.19.2) 2200 | 2201 | '@vitest/pretty-format@2.1.6': 2202 | dependencies: 2203 | tinyrainbow: 1.2.0 2204 | 2205 | '@vitest/runner@2.1.6': 2206 | dependencies: 2207 | '@vitest/utils': 2.1.6 2208 | pathe: 1.1.2 2209 | 2210 | '@vitest/snapshot@2.1.6': 2211 | dependencies: 2212 | '@vitest/pretty-format': 2.1.6 2213 | magic-string: 0.30.14 2214 | pathe: 1.1.2 2215 | 2216 | '@vitest/spy@2.1.6': 2217 | dependencies: 2218 | tinyspy: 3.0.2 2219 | 2220 | '@vitest/utils@2.1.6': 2221 | dependencies: 2222 | '@vitest/pretty-format': 2.1.6 2223 | loupe: 3.1.2 2224 | tinyrainbow: 1.2.0 2225 | 2226 | ansi-regex@5.0.1: {} 2227 | 2228 | ansi-regex@6.1.0: {} 2229 | 2230 | ansi-styles@4.3.0: 2231 | dependencies: 2232 | color-convert: 2.0.1 2233 | 2234 | ansi-styles@6.2.1: {} 2235 | 2236 | any-promise@1.3.0: {} 2237 | 2238 | assertion-error@2.0.1: {} 2239 | 2240 | balanced-match@1.0.2: {} 2241 | 2242 | base64-js@1.5.1: {} 2243 | 2244 | better-sqlite3@11.6.0: 2245 | dependencies: 2246 | bindings: 1.5.0 2247 | prebuild-install: 7.1.2 2248 | 2249 | bindings@1.5.0: 2250 | dependencies: 2251 | file-uri-to-path: 1.0.0 2252 | 2253 | bl@4.1.0: 2254 | dependencies: 2255 | buffer: 5.7.1 2256 | inherits: 2.0.4 2257 | readable-stream: 3.6.2 2258 | 2259 | brace-expansion@2.0.1: 2260 | dependencies: 2261 | balanced-match: 1.0.2 2262 | 2263 | braces@3.0.3: 2264 | dependencies: 2265 | fill-range: 7.1.1 2266 | 2267 | buffer@5.7.1: 2268 | dependencies: 2269 | base64-js: 1.5.1 2270 | ieee754: 1.2.1 2271 | 2272 | bundle-require@5.0.0(esbuild@0.24.0): 2273 | dependencies: 2274 | esbuild: 0.24.0 2275 | load-tsconfig: 0.2.5 2276 | 2277 | cac@6.7.14: {} 2278 | 2279 | chai@5.1.2: 2280 | dependencies: 2281 | assertion-error: 2.0.1 2282 | check-error: 2.1.1 2283 | deep-eql: 5.0.2 2284 | loupe: 3.1.2 2285 | pathval: 2.0.0 2286 | 2287 | check-error@2.1.1: {} 2288 | 2289 | chokidar@4.0.1: 2290 | dependencies: 2291 | readdirp: 4.0.2 2292 | 2293 | chownr@1.1.4: {} 2294 | 2295 | color-convert@2.0.1: 2296 | dependencies: 2297 | color-name: 1.1.4 2298 | 2299 | color-name@1.1.4: {} 2300 | 2301 | commander@4.1.1: {} 2302 | 2303 | consola@3.2.3: {} 2304 | 2305 | cross-spawn@7.0.3: 2306 | dependencies: 2307 | path-key: 3.1.1 2308 | shebang-command: 2.0.0 2309 | which: 2.0.2 2310 | 2311 | debug@4.3.7: 2312 | dependencies: 2313 | ms: 2.1.3 2314 | 2315 | decompress-response@6.0.0: 2316 | dependencies: 2317 | mimic-response: 3.1.0 2318 | 2319 | deep-eql@5.0.2: {} 2320 | 2321 | deep-extend@0.6.0: {} 2322 | 2323 | detect-libc@1.0.3: {} 2324 | 2325 | detect-libc@2.0.3: {} 2326 | 2327 | eastasianwidth@0.2.0: {} 2328 | 2329 | effect@3.10.19: 2330 | dependencies: 2331 | fast-check: 3.23.1 2332 | 2333 | emoji-regex@8.0.0: {} 2334 | 2335 | emoji-regex@9.2.2: {} 2336 | 2337 | end-of-stream@1.4.4: 2338 | dependencies: 2339 | once: 1.4.0 2340 | 2341 | es-module-lexer@1.5.4: {} 2342 | 2343 | esbuild@0.23.1: 2344 | optionalDependencies: 2345 | '@esbuild/aix-ppc64': 0.23.1 2346 | '@esbuild/android-arm': 0.23.1 2347 | '@esbuild/android-arm64': 0.23.1 2348 | '@esbuild/android-x64': 0.23.1 2349 | '@esbuild/darwin-arm64': 0.23.1 2350 | '@esbuild/darwin-x64': 0.23.1 2351 | '@esbuild/freebsd-arm64': 0.23.1 2352 | '@esbuild/freebsd-x64': 0.23.1 2353 | '@esbuild/linux-arm': 0.23.1 2354 | '@esbuild/linux-arm64': 0.23.1 2355 | '@esbuild/linux-ia32': 0.23.1 2356 | '@esbuild/linux-loong64': 0.23.1 2357 | '@esbuild/linux-mips64el': 0.23.1 2358 | '@esbuild/linux-ppc64': 0.23.1 2359 | '@esbuild/linux-riscv64': 0.23.1 2360 | '@esbuild/linux-s390x': 0.23.1 2361 | '@esbuild/linux-x64': 0.23.1 2362 | '@esbuild/netbsd-x64': 0.23.1 2363 | '@esbuild/openbsd-arm64': 0.23.1 2364 | '@esbuild/openbsd-x64': 0.23.1 2365 | '@esbuild/sunos-x64': 0.23.1 2366 | '@esbuild/win32-arm64': 0.23.1 2367 | '@esbuild/win32-ia32': 0.23.1 2368 | '@esbuild/win32-x64': 0.23.1 2369 | 2370 | esbuild@0.24.0: 2371 | optionalDependencies: 2372 | '@esbuild/aix-ppc64': 0.24.0 2373 | '@esbuild/android-arm': 0.24.0 2374 | '@esbuild/android-arm64': 0.24.0 2375 | '@esbuild/android-x64': 0.24.0 2376 | '@esbuild/darwin-arm64': 0.24.0 2377 | '@esbuild/darwin-x64': 0.24.0 2378 | '@esbuild/freebsd-arm64': 0.24.0 2379 | '@esbuild/freebsd-x64': 0.24.0 2380 | '@esbuild/linux-arm': 0.24.0 2381 | '@esbuild/linux-arm64': 0.24.0 2382 | '@esbuild/linux-ia32': 0.24.0 2383 | '@esbuild/linux-loong64': 0.24.0 2384 | '@esbuild/linux-mips64el': 0.24.0 2385 | '@esbuild/linux-ppc64': 0.24.0 2386 | '@esbuild/linux-riscv64': 0.24.0 2387 | '@esbuild/linux-s390x': 0.24.0 2388 | '@esbuild/linux-x64': 0.24.0 2389 | '@esbuild/netbsd-x64': 0.24.0 2390 | '@esbuild/openbsd-arm64': 0.24.0 2391 | '@esbuild/openbsd-x64': 0.24.0 2392 | '@esbuild/sunos-x64': 0.24.0 2393 | '@esbuild/win32-arm64': 0.24.0 2394 | '@esbuild/win32-ia32': 0.24.0 2395 | '@esbuild/win32-x64': 0.24.0 2396 | 2397 | estree-walker@3.0.3: 2398 | dependencies: 2399 | '@types/estree': 1.0.6 2400 | 2401 | expand-template@2.0.3: {} 2402 | 2403 | expect-type@1.1.0: {} 2404 | 2405 | fast-check@3.23.1: 2406 | dependencies: 2407 | pure-rand: 6.1.0 2408 | 2409 | fdir@6.4.2(picomatch@4.0.2): 2410 | optionalDependencies: 2411 | picomatch: 4.0.2 2412 | 2413 | file-uri-to-path@1.0.0: {} 2414 | 2415 | fill-range@7.1.1: 2416 | dependencies: 2417 | to-regex-range: 5.0.1 2418 | 2419 | find-my-way-ts@0.1.5: {} 2420 | 2421 | foreground-child@3.3.0: 2422 | dependencies: 2423 | cross-spawn: 7.0.3 2424 | signal-exit: 4.1.0 2425 | 2426 | fs-constants@1.0.0: {} 2427 | 2428 | fsevents@2.3.3: 2429 | optional: true 2430 | 2431 | get-tsconfig@4.8.1: 2432 | dependencies: 2433 | resolve-pkg-maps: 1.0.0 2434 | 2435 | github-from-package@0.0.0: {} 2436 | 2437 | glob@10.4.5: 2438 | dependencies: 2439 | foreground-child: 3.3.0 2440 | jackspeak: 3.4.3 2441 | minimatch: 9.0.5 2442 | minipass: 7.1.2 2443 | package-json-from-dist: 1.0.1 2444 | path-scurry: 1.11.1 2445 | 2446 | ieee754@1.2.1: {} 2447 | 2448 | inherits@2.0.4: {} 2449 | 2450 | ini@1.3.8: {} 2451 | 2452 | is-extglob@2.1.1: {} 2453 | 2454 | is-fullwidth-code-point@3.0.0: {} 2455 | 2456 | is-glob@4.0.3: 2457 | dependencies: 2458 | is-extglob: 2.1.1 2459 | 2460 | is-number@7.0.0: {} 2461 | 2462 | isexe@2.0.0: {} 2463 | 2464 | jackspeak@3.4.3: 2465 | dependencies: 2466 | '@isaacs/cliui': 8.0.2 2467 | optionalDependencies: 2468 | '@pkgjs/parseargs': 0.11.0 2469 | 2470 | joycon@3.1.1: {} 2471 | 2472 | lilconfig@3.1.2: {} 2473 | 2474 | lines-and-columns@1.2.4: {} 2475 | 2476 | load-tsconfig@0.2.5: {} 2477 | 2478 | lodash.sortby@4.7.0: {} 2479 | 2480 | long@5.2.3: {} 2481 | 2482 | loupe@3.1.2: {} 2483 | 2484 | lru-cache@10.4.3: {} 2485 | 2486 | magic-string@0.30.14: 2487 | dependencies: 2488 | '@jridgewell/sourcemap-codec': 1.5.0 2489 | 2490 | micromatch@4.0.8: 2491 | dependencies: 2492 | braces: 3.0.3 2493 | picomatch: 2.3.1 2494 | 2495 | mime@3.0.0: {} 2496 | 2497 | mimic-response@3.1.0: {} 2498 | 2499 | minimatch@9.0.5: 2500 | dependencies: 2501 | brace-expansion: 2.0.1 2502 | 2503 | minimist@1.2.8: {} 2504 | 2505 | minipass@7.1.2: {} 2506 | 2507 | mkdirp-classic@0.5.3: {} 2508 | 2509 | ms@2.1.3: {} 2510 | 2511 | msgpackr-extract@3.0.3: 2512 | dependencies: 2513 | node-gyp-build-optional-packages: 5.2.2 2514 | optionalDependencies: 2515 | '@msgpackr-extract/msgpackr-extract-darwin-arm64': 3.0.3 2516 | '@msgpackr-extract/msgpackr-extract-darwin-x64': 3.0.3 2517 | '@msgpackr-extract/msgpackr-extract-linux-arm': 3.0.3 2518 | '@msgpackr-extract/msgpackr-extract-linux-arm64': 3.0.3 2519 | '@msgpackr-extract/msgpackr-extract-linux-x64': 3.0.3 2520 | '@msgpackr-extract/msgpackr-extract-win32-x64': 3.0.3 2521 | optional: true 2522 | 2523 | msgpackr@1.11.2: 2524 | optionalDependencies: 2525 | msgpackr-extract: 3.0.3 2526 | 2527 | multipasta@0.2.5: {} 2528 | 2529 | mz@2.7.0: 2530 | dependencies: 2531 | any-promise: 1.3.0 2532 | object-assign: 4.1.1 2533 | thenify-all: 1.6.0 2534 | 2535 | nanoid@3.3.8: {} 2536 | 2537 | napi-build-utils@1.0.2: {} 2538 | 2539 | node-abi@3.71.0: 2540 | dependencies: 2541 | semver: 7.6.3 2542 | 2543 | node-addon-api@7.1.1: {} 2544 | 2545 | node-gyp-build-optional-packages@5.2.2: 2546 | dependencies: 2547 | detect-libc: 2.0.3 2548 | optional: true 2549 | 2550 | object-assign@4.1.1: {} 2551 | 2552 | once@1.4.0: 2553 | dependencies: 2554 | wrappy: 1.0.2 2555 | 2556 | package-json-from-dist@1.0.1: {} 2557 | 2558 | path-key@3.1.1: {} 2559 | 2560 | path-scurry@1.11.1: 2561 | dependencies: 2562 | lru-cache: 10.4.3 2563 | minipass: 7.1.2 2564 | 2565 | pathe@1.1.2: {} 2566 | 2567 | pathval@2.0.0: {} 2568 | 2569 | picocolors@1.1.1: {} 2570 | 2571 | picomatch@2.3.1: {} 2572 | 2573 | picomatch@4.0.2: {} 2574 | 2575 | pirates@4.0.6: {} 2576 | 2577 | postcss-load-config@6.0.1(postcss@8.4.49)(tsx@4.19.2): 2578 | dependencies: 2579 | lilconfig: 3.1.2 2580 | optionalDependencies: 2581 | postcss: 8.4.49 2582 | tsx: 4.19.2 2583 | 2584 | postcss@8.4.49: 2585 | dependencies: 2586 | nanoid: 3.3.8 2587 | picocolors: 1.1.1 2588 | source-map-js: 1.2.1 2589 | 2590 | prebuild-install@7.1.2: 2591 | dependencies: 2592 | detect-libc: 2.0.3 2593 | expand-template: 2.0.3 2594 | github-from-package: 0.0.0 2595 | minimist: 1.2.8 2596 | mkdirp-classic: 0.5.3 2597 | napi-build-utils: 1.0.2 2598 | node-abi: 3.71.0 2599 | pump: 3.0.2 2600 | rc: 1.2.8 2601 | simple-get: 4.0.1 2602 | tar-fs: 2.1.1 2603 | tunnel-agent: 0.6.0 2604 | 2605 | prettier@3.4.1: {} 2606 | 2607 | protobufjs@7.4.0: 2608 | dependencies: 2609 | '@protobufjs/aspromise': 1.1.2 2610 | '@protobufjs/base64': 1.1.2 2611 | '@protobufjs/codegen': 2.0.4 2612 | '@protobufjs/eventemitter': 1.1.0 2613 | '@protobufjs/fetch': 1.1.0 2614 | '@protobufjs/float': 1.0.2 2615 | '@protobufjs/inquire': 1.1.0 2616 | '@protobufjs/path': 1.1.2 2617 | '@protobufjs/pool': 1.1.0 2618 | '@protobufjs/utf8': 1.1.0 2619 | '@types/node': 22.10.1 2620 | long: 5.2.3 2621 | 2622 | pump@3.0.2: 2623 | dependencies: 2624 | end-of-stream: 1.4.4 2625 | once: 1.4.0 2626 | 2627 | punycode@2.3.1: {} 2628 | 2629 | pure-rand@6.1.0: {} 2630 | 2631 | rc@1.2.8: 2632 | dependencies: 2633 | deep-extend: 0.6.0 2634 | ini: 1.3.8 2635 | minimist: 1.2.8 2636 | strip-json-comments: 2.0.1 2637 | 2638 | readable-stream@3.6.2: 2639 | dependencies: 2640 | inherits: 2.0.4 2641 | string_decoder: 1.3.0 2642 | util-deprecate: 1.0.2 2643 | 2644 | readdirp@4.0.2: {} 2645 | 2646 | resolve-from@5.0.0: {} 2647 | 2648 | resolve-pkg-maps@1.0.0: {} 2649 | 2650 | rollup@4.24.4: 2651 | dependencies: 2652 | '@types/estree': 1.0.6 2653 | optionalDependencies: 2654 | '@rollup/rollup-android-arm-eabi': 4.24.4 2655 | '@rollup/rollup-android-arm64': 4.24.4 2656 | '@rollup/rollup-darwin-arm64': 4.24.4 2657 | '@rollup/rollup-darwin-x64': 4.24.4 2658 | '@rollup/rollup-freebsd-arm64': 4.24.4 2659 | '@rollup/rollup-freebsd-x64': 4.24.4 2660 | '@rollup/rollup-linux-arm-gnueabihf': 4.24.4 2661 | '@rollup/rollup-linux-arm-musleabihf': 4.24.4 2662 | '@rollup/rollup-linux-arm64-gnu': 4.24.4 2663 | '@rollup/rollup-linux-arm64-musl': 4.24.4 2664 | '@rollup/rollup-linux-powerpc64le-gnu': 4.24.4 2665 | '@rollup/rollup-linux-riscv64-gnu': 4.24.4 2666 | '@rollup/rollup-linux-s390x-gnu': 4.24.4 2667 | '@rollup/rollup-linux-x64-gnu': 4.24.4 2668 | '@rollup/rollup-linux-x64-musl': 4.24.4 2669 | '@rollup/rollup-win32-arm64-msvc': 4.24.4 2670 | '@rollup/rollup-win32-ia32-msvc': 4.24.4 2671 | '@rollup/rollup-win32-x64-msvc': 4.24.4 2672 | fsevents: 2.3.3 2673 | 2674 | rollup@4.28.0: 2675 | dependencies: 2676 | '@types/estree': 1.0.6 2677 | optionalDependencies: 2678 | '@rollup/rollup-android-arm-eabi': 4.28.0 2679 | '@rollup/rollup-android-arm64': 4.28.0 2680 | '@rollup/rollup-darwin-arm64': 4.28.0 2681 | '@rollup/rollup-darwin-x64': 4.28.0 2682 | '@rollup/rollup-freebsd-arm64': 4.28.0 2683 | '@rollup/rollup-freebsd-x64': 4.28.0 2684 | '@rollup/rollup-linux-arm-gnueabihf': 4.28.0 2685 | '@rollup/rollup-linux-arm-musleabihf': 4.28.0 2686 | '@rollup/rollup-linux-arm64-gnu': 4.28.0 2687 | '@rollup/rollup-linux-arm64-musl': 4.28.0 2688 | '@rollup/rollup-linux-powerpc64le-gnu': 4.28.0 2689 | '@rollup/rollup-linux-riscv64-gnu': 4.28.0 2690 | '@rollup/rollup-linux-s390x-gnu': 4.28.0 2691 | '@rollup/rollup-linux-x64-gnu': 4.28.0 2692 | '@rollup/rollup-linux-x64-musl': 4.28.0 2693 | '@rollup/rollup-win32-arm64-msvc': 4.28.0 2694 | '@rollup/rollup-win32-ia32-msvc': 4.28.0 2695 | '@rollup/rollup-win32-x64-msvc': 4.28.0 2696 | fsevents: 2.3.3 2697 | 2698 | safe-buffer@5.2.1: {} 2699 | 2700 | semver@7.6.3: {} 2701 | 2702 | shebang-command@2.0.0: 2703 | dependencies: 2704 | shebang-regex: 3.0.0 2705 | 2706 | shebang-regex@3.0.0: {} 2707 | 2708 | siginfo@2.0.0: {} 2709 | 2710 | signal-exit@4.1.0: {} 2711 | 2712 | simple-concat@1.0.1: {} 2713 | 2714 | simple-get@4.0.1: 2715 | dependencies: 2716 | decompress-response: 6.0.0 2717 | once: 1.4.0 2718 | simple-concat: 1.0.1 2719 | 2720 | source-map-js@1.2.1: {} 2721 | 2722 | source-map@0.8.0-beta.0: 2723 | dependencies: 2724 | whatwg-url: 7.1.0 2725 | 2726 | stackback@0.0.2: {} 2727 | 2728 | std-env@3.8.0: {} 2729 | 2730 | string-width@4.2.3: 2731 | dependencies: 2732 | emoji-regex: 8.0.0 2733 | is-fullwidth-code-point: 3.0.0 2734 | strip-ansi: 6.0.1 2735 | 2736 | string-width@5.1.2: 2737 | dependencies: 2738 | eastasianwidth: 0.2.0 2739 | emoji-regex: 9.2.2 2740 | strip-ansi: 7.1.0 2741 | 2742 | string_decoder@1.3.0: 2743 | dependencies: 2744 | safe-buffer: 5.2.1 2745 | 2746 | strip-ansi@6.0.1: 2747 | dependencies: 2748 | ansi-regex: 5.0.1 2749 | 2750 | strip-ansi@7.1.0: 2751 | dependencies: 2752 | ansi-regex: 6.1.0 2753 | 2754 | strip-json-comments@2.0.1: {} 2755 | 2756 | sucrase@3.35.0: 2757 | dependencies: 2758 | '@jridgewell/gen-mapping': 0.3.5 2759 | commander: 4.1.1 2760 | glob: 10.4.5 2761 | lines-and-columns: 1.2.4 2762 | mz: 2.7.0 2763 | pirates: 4.0.6 2764 | ts-interface-checker: 0.1.13 2765 | 2766 | tar-fs@2.1.1: 2767 | dependencies: 2768 | chownr: 1.1.4 2769 | mkdirp-classic: 0.5.3 2770 | pump: 3.0.2 2771 | tar-stream: 2.2.0 2772 | 2773 | tar-stream@2.2.0: 2774 | dependencies: 2775 | bl: 4.1.0 2776 | end-of-stream: 1.4.4 2777 | fs-constants: 1.0.0 2778 | inherits: 2.0.4 2779 | readable-stream: 3.6.2 2780 | 2781 | thenify-all@1.6.0: 2782 | dependencies: 2783 | thenify: 3.3.1 2784 | 2785 | thenify@3.3.1: 2786 | dependencies: 2787 | any-promise: 1.3.0 2788 | 2789 | tinybench@2.9.0: {} 2790 | 2791 | tinyexec@0.3.1: {} 2792 | 2793 | tinyglobby@0.2.10: 2794 | dependencies: 2795 | fdir: 6.4.2(picomatch@4.0.2) 2796 | picomatch: 4.0.2 2797 | 2798 | tinypool@1.0.2: {} 2799 | 2800 | tinyrainbow@1.2.0: {} 2801 | 2802 | tinyspy@3.0.2: {} 2803 | 2804 | to-regex-range@5.0.1: 2805 | dependencies: 2806 | is-number: 7.0.0 2807 | 2808 | tr46@1.0.1: 2809 | dependencies: 2810 | punycode: 2.3.1 2811 | 2812 | tree-kill@1.2.2: {} 2813 | 2814 | ts-interface-checker@0.1.13: {} 2815 | 2816 | tsup@8.3.5(postcss@8.4.49)(tsx@4.19.2)(typescript@5.7.2): 2817 | dependencies: 2818 | bundle-require: 5.0.0(esbuild@0.24.0) 2819 | cac: 6.7.14 2820 | chokidar: 4.0.1 2821 | consola: 3.2.3 2822 | debug: 4.3.7 2823 | esbuild: 0.24.0 2824 | joycon: 3.1.1 2825 | picocolors: 1.1.1 2826 | postcss-load-config: 6.0.1(postcss@8.4.49)(tsx@4.19.2) 2827 | resolve-from: 5.0.0 2828 | rollup: 4.24.4 2829 | source-map: 0.8.0-beta.0 2830 | sucrase: 3.35.0 2831 | tinyexec: 0.3.1 2832 | tinyglobby: 0.2.10 2833 | tree-kill: 1.2.2 2834 | optionalDependencies: 2835 | postcss: 8.4.49 2836 | typescript: 5.7.2 2837 | transitivePeerDependencies: 2838 | - jiti 2839 | - supports-color 2840 | - tsx 2841 | - yaml 2842 | 2843 | tsx@4.19.2: 2844 | dependencies: 2845 | esbuild: 0.23.1 2846 | get-tsconfig: 4.8.1 2847 | optionalDependencies: 2848 | fsevents: 2.3.3 2849 | 2850 | tunnel-agent@0.6.0: 2851 | dependencies: 2852 | safe-buffer: 5.2.1 2853 | 2854 | typescript@5.7.2: {} 2855 | 2856 | undici-types@6.20.0: {} 2857 | 2858 | undici@6.21.0: {} 2859 | 2860 | util-deprecate@1.0.2: {} 2861 | 2862 | uuid@11.0.3: {} 2863 | 2864 | vite-node@2.1.6(@types/node@22.10.1)(tsx@4.19.2): 2865 | dependencies: 2866 | cac: 6.7.14 2867 | debug: 4.3.7 2868 | es-module-lexer: 1.5.4 2869 | pathe: 1.1.2 2870 | vite: 6.0.1(@types/node@22.10.1)(tsx@4.19.2) 2871 | transitivePeerDependencies: 2872 | - '@types/node' 2873 | - jiti 2874 | - less 2875 | - lightningcss 2876 | - sass 2877 | - sass-embedded 2878 | - stylus 2879 | - sugarss 2880 | - supports-color 2881 | - terser 2882 | - tsx 2883 | - yaml 2884 | 2885 | vite@6.0.1(@types/node@22.10.1)(tsx@4.19.2): 2886 | dependencies: 2887 | esbuild: 0.24.0 2888 | postcss: 8.4.49 2889 | rollup: 4.28.0 2890 | optionalDependencies: 2891 | '@types/node': 22.10.1 2892 | fsevents: 2.3.3 2893 | tsx: 4.19.2 2894 | 2895 | vitest@2.1.6(@types/node@22.10.1)(tsx@4.19.2): 2896 | dependencies: 2897 | '@vitest/expect': 2.1.6 2898 | '@vitest/mocker': 2.1.6(vite@6.0.1(@types/node@22.10.1)(tsx@4.19.2)) 2899 | '@vitest/pretty-format': 2.1.6 2900 | '@vitest/runner': 2.1.6 2901 | '@vitest/snapshot': 2.1.6 2902 | '@vitest/spy': 2.1.6 2903 | '@vitest/utils': 2.1.6 2904 | chai: 5.1.2 2905 | debug: 4.3.7 2906 | expect-type: 1.1.0 2907 | magic-string: 0.30.14 2908 | pathe: 1.1.2 2909 | std-env: 3.8.0 2910 | tinybench: 2.9.0 2911 | tinyexec: 0.3.1 2912 | tinypool: 1.0.2 2913 | tinyrainbow: 1.2.0 2914 | vite: 6.0.1(@types/node@22.10.1)(tsx@4.19.2) 2915 | vite-node: 2.1.6(@types/node@22.10.1)(tsx@4.19.2) 2916 | why-is-node-running: 2.3.0 2917 | optionalDependencies: 2918 | '@types/node': 22.10.1 2919 | transitivePeerDependencies: 2920 | - jiti 2921 | - less 2922 | - lightningcss 2923 | - msw 2924 | - sass 2925 | - sass-embedded 2926 | - stylus 2927 | - sugarss 2928 | - supports-color 2929 | - terser 2930 | - tsx 2931 | - yaml 2932 | 2933 | webidl-conversions@4.0.2: {} 2934 | 2935 | whatwg-url@7.1.0: 2936 | dependencies: 2937 | lodash.sortby: 4.7.0 2938 | tr46: 1.0.1 2939 | webidl-conversions: 4.0.2 2940 | 2941 | which@2.0.2: 2942 | dependencies: 2943 | isexe: 2.0.0 2944 | 2945 | why-is-node-running@2.3.0: 2946 | dependencies: 2947 | siginfo: 2.0.0 2948 | stackback: 0.0.2 2949 | 2950 | wrap-ansi@7.0.0: 2951 | dependencies: 2952 | ansi-styles: 4.3.0 2953 | string-width: 4.2.3 2954 | strip-ansi: 6.0.1 2955 | 2956 | wrap-ansi@8.1.0: 2957 | dependencies: 2958 | ansi-styles: 6.2.1 2959 | string-width: 5.1.2 2960 | strip-ansi: 7.1.0 2961 | 2962 | wrappy@1.0.2: {} 2963 | 2964 | ws@8.18.0: {} 2965 | -------------------------------------------------------------------------------- /src/Accounts.ts: -------------------------------------------------------------------------------- 1 | import { SqlClient } from "@effect/sql" 2 | import { Effect, Layer, Option, pipe } from "effect" 3 | import { AccountsRepo } from "./Accounts/AccountsRepo.js" 4 | import { UsersRepo } from "./Accounts/UsersRepo.js" 5 | import { AccessToken, accessTokenFromString } from "./Domain/AccessToken.js" 6 | import { Account } from "./Domain/Account.js" 7 | import { policyRequire } from "./Domain/Policy.js" 8 | import { User, UserId, UserNotFound, UserWithSensitive } from "./Domain/User.js" 9 | import { SqlLive, SqlTest } from "./Sql.js" 10 | import { Uuid } from "./Uuid.js" 11 | 12 | export class Accounts extends Effect.Service()("Accounts", { 13 | effect: Effect.gen(function* () { 14 | const sql = yield* SqlClient.SqlClient 15 | const accountRepo = yield* AccountsRepo 16 | const userRepo = yield* UsersRepo 17 | const uuid = yield* Uuid 18 | 19 | const createUser = (user: typeof User.jsonCreate.Type) => 20 | accountRepo.insert(Account.insert.make({})).pipe( 21 | Effect.tap((account) => Effect.annotateCurrentSpan("account", account)), 22 | Effect.bindTo("account"), 23 | Effect.bind("accessToken", () => 24 | uuid.generate.pipe(Effect.map(accessTokenFromString)), 25 | ), 26 | Effect.bind("user", ({ account, accessToken }) => 27 | userRepo.insert( 28 | User.insert.make({ 29 | ...user, 30 | accountId: account.id, 31 | accessToken, 32 | }), 33 | ), 34 | ), 35 | Effect.map( 36 | ({ user, account }) => 37 | new UserWithSensitive({ 38 | ...user, 39 | account, 40 | }), 41 | ), 42 | sql.withTransaction, 43 | Effect.orDie, 44 | Effect.withSpan("Accounts.createUser", { attributes: { user } }), 45 | policyRequire("User", "create"), 46 | ) 47 | 48 | const updateUser = ( 49 | id: UserId, 50 | user: Partial, 51 | ) => 52 | userRepo.findById(id).pipe( 53 | Effect.flatMap( 54 | Option.match({ 55 | onNone: () => new UserNotFound({ id }), 56 | onSome: Effect.succeed, 57 | }), 58 | ), 59 | Effect.andThen((previous) => 60 | userRepo.update({ 61 | ...previous, 62 | ...user, 63 | id, 64 | updatedAt: undefined, 65 | }), 66 | ), 67 | sql.withTransaction, 68 | Effect.catchTag("SqlError", (err) => Effect.die(err)), 69 | Effect.withSpan("Accounts.updateUser", { attributes: { id, user } }), 70 | policyRequire("User", "update"), 71 | ) 72 | 73 | const findUserByAccessToken = (apiKey: AccessToken) => 74 | pipe( 75 | userRepo.findByAccessToken(apiKey), 76 | Effect.withSpan("Accounts.findUserByAccessToken"), 77 | policyRequire("User", "read"), 78 | ) 79 | 80 | const findUserById = (id: UserId) => 81 | pipe( 82 | userRepo.findById(id), 83 | Effect.withSpan("Accounts.findUserById", { 84 | attributes: { id }, 85 | }), 86 | policyRequire("User", "read"), 87 | ) 88 | 89 | const embellishUser = (user: User) => 90 | pipe( 91 | accountRepo.findById(user.accountId), 92 | Effect.flatten, 93 | Effect.map((account) => new UserWithSensitive({ ...user, account })), 94 | Effect.orDie, 95 | Effect.withSpan("Accounts.embellishUser", { 96 | attributes: { id: user.id }, 97 | }), 98 | policyRequire("User", "readSensitive"), 99 | ) 100 | 101 | return { 102 | createUser, 103 | updateUser, 104 | findUserByAccessToken, 105 | findUserById, 106 | embellishUser, 107 | } as const 108 | }), 109 | dependencies: [ 110 | SqlLive, 111 | AccountsRepo.Default, 112 | UsersRepo.Default, 113 | Uuid.Default, 114 | ], 115 | }) { 116 | static Test = this.DefaultWithoutDependencies.pipe( 117 | Layer.provideMerge(SqlTest), 118 | Layer.provideMerge(Uuid.Test), 119 | ) 120 | } 121 | -------------------------------------------------------------------------------- /src/Accounts/AccountsRepo.ts: -------------------------------------------------------------------------------- 1 | import { Model } from "@effect/sql" 2 | import { Effect } from "effect" 3 | import { Account } from "../Domain/Account.js" 4 | import { SqlLive } from "../Sql.js" 5 | import { makeTestLayer } from "../lib/Layer.js" 6 | 7 | export const make = Model.makeRepository(Account, { 8 | tableName: "accounts", 9 | spanPrefix: "AccountsRepo", 10 | idColumn: "id", 11 | }) 12 | 13 | export class AccountsRepo extends Effect.Service()( 14 | "Accounts/AccountsRepo", 15 | { 16 | effect: Model.makeRepository(Account, { 17 | tableName: "accounts", 18 | spanPrefix: "AccountsRepo", 19 | idColumn: "id", 20 | }), 21 | dependencies: [SqlLive], 22 | }, 23 | ) { 24 | static Test = makeTestLayer(AccountsRepo)({}) 25 | } 26 | -------------------------------------------------------------------------------- /src/Accounts/Api.ts: -------------------------------------------------------------------------------- 1 | import { 2 | HttpApiEndpoint, 3 | HttpApiGroup, 4 | HttpApiMiddleware, 5 | HttpApiSchema, 6 | HttpApiSecurity, 7 | OpenApi, 8 | } from "@effect/platform" 9 | import { 10 | CurrentUser, 11 | User, 12 | UserIdFromString, 13 | UserNotFound, 14 | UserWithSensitive, 15 | } from "../Domain/User.js" 16 | import { Schema } from "effect" 17 | import { Unauthorized } from "../Domain/Policy.js" 18 | 19 | export class Authentication extends HttpApiMiddleware.Tag()( 20 | "Accounts/Api/Authentication", 21 | { 22 | provides: CurrentUser, 23 | failure: Unauthorized, 24 | security: { 25 | cookie: HttpApiSecurity.apiKey({ 26 | in: "cookie", 27 | key: "token", 28 | }), 29 | }, 30 | }, 31 | ) {} 32 | 33 | export class AccountsApi extends HttpApiGroup.make("accounts") 34 | .add( 35 | HttpApiEndpoint.patch( 36 | "updateUser", 37 | )`/users/${HttpApiSchema.param("id", UserIdFromString)}` 38 | .addSuccess(User.json) 39 | .addError(UserNotFound) 40 | .setPayload(Schema.partialWith(User.jsonUpdate, { exact: true })), 41 | ) 42 | .add( 43 | HttpApiEndpoint.get("getUserMe", "/users/me").addSuccess( 44 | UserWithSensitive.json, 45 | ), 46 | ) 47 | .add( 48 | HttpApiEndpoint.get( 49 | "getUser", 50 | )`/users/${HttpApiSchema.param("id", UserIdFromString)}` 51 | .addSuccess(User.json) 52 | .addError(UserNotFound), 53 | ) 54 | .middlewareEndpoints(Authentication) 55 | // unauthenticated 56 | .add( 57 | HttpApiEndpoint.post("createUser", "/users") 58 | .addSuccess(UserWithSensitive.json) 59 | .setPayload(User.jsonCreate), 60 | ) 61 | .annotate(OpenApi.Title, "Accounts") 62 | .annotate(OpenApi.Description, "Manage user accounts") {} 63 | -------------------------------------------------------------------------------- /src/Accounts/Http.ts: -------------------------------------------------------------------------------- 1 | import { HttpApiBuilder } from "@effect/platform" 2 | import { Effect, Layer, Option, pipe } from "effect" 3 | import { Accounts } from "../Accounts.js" 4 | import { Api } from "../Api.js" 5 | import { policyUse, Unauthorized, withSystemActor } from "../Domain/Policy.js" 6 | import { CurrentUser, UserId, UserNotFound } from "../Domain/User.js" 7 | import { AccountsPolicy } from "./Policy.js" 8 | import { Authentication } from "./Api.js" 9 | import { accessTokenFromRedacted } from "../Domain/AccessToken.js" 10 | import { UsersRepo } from "./UsersRepo.js" 11 | 12 | export const AuthenticationLive = Layer.effect( 13 | Authentication, 14 | Effect.gen(function* () { 15 | const userRepo = yield* UsersRepo 16 | 17 | return Authentication.of({ 18 | cookie: (token) => 19 | userRepo.findByAccessToken(accessTokenFromRedacted(token)).pipe( 20 | Effect.flatMap( 21 | Option.match({ 22 | onNone: () => 23 | new Unauthorized({ 24 | actorId: UserId.make(-1), 25 | entity: "User", 26 | action: "read", 27 | }), 28 | onSome: Effect.succeed, 29 | }), 30 | ), 31 | Effect.withSpan("Authentication.cookie"), 32 | ), 33 | }) 34 | }), 35 | ).pipe(Layer.provide(UsersRepo.Default)) 36 | 37 | export const HttpAccountsLive = HttpApiBuilder.group( 38 | Api, 39 | "accounts", 40 | (handlers) => 41 | Effect.gen(function* () { 42 | const accounts = yield* Accounts 43 | const policy = yield* AccountsPolicy 44 | 45 | return handlers 46 | .handle("updateUser", ({ payload, path }) => 47 | pipe( 48 | accounts.updateUser(path.id, payload), 49 | policyUse(policy.canUpdate(path.id)), 50 | ), 51 | ) 52 | .handle("getUserMe", () => 53 | CurrentUser.pipe( 54 | Effect.flatMap(accounts.embellishUser), 55 | withSystemActor, 56 | ), 57 | ) 58 | .handle("getUser", ({ path }) => 59 | pipe( 60 | accounts.findUserById(path.id), 61 | Effect.flatMap( 62 | Option.match({ 63 | onNone: () => new UserNotFound({ id: path.id }), 64 | onSome: Effect.succeed, 65 | }), 66 | ), 67 | policyUse(policy.canRead(path.id)), 68 | ), 69 | ) 70 | .handle("createUser", ({ payload }) => 71 | accounts.createUser(payload).pipe( 72 | withSystemActor, 73 | Effect.tap((user) => 74 | HttpApiBuilder.securitySetCookie( 75 | Authentication.security.cookie, 76 | user.accessToken, 77 | ), 78 | ), 79 | ), 80 | ) 81 | }), 82 | ).pipe( 83 | Layer.provide([Accounts.Default, AccountsPolicy.Default, AuthenticationLive]), 84 | ) 85 | -------------------------------------------------------------------------------- /src/Accounts/Policy.ts: -------------------------------------------------------------------------------- 1 | import { Effect } from "effect" 2 | import { UserId } from "../Domain/User.js" 3 | import { policy } from "../Domain/Policy.js" 4 | 5 | export class AccountsPolicy extends Effect.Service()( 6 | "Accounts/Policy", 7 | { 8 | effect: Effect.gen(function* () { 9 | const canUpdate = (toUpdate: UserId) => 10 | policy("User", "update", (actor) => 11 | Effect.succeed(actor.id === toUpdate), 12 | ) 13 | 14 | const canRead = (toRead: UserId) => 15 | policy("User", "read", (actor) => Effect.succeed(actor.id === toRead)) 16 | 17 | const canReadSensitive = (toRead: UserId) => 18 | policy("User", "readSensitive", (actor) => 19 | Effect.succeed(actor.id === toRead), 20 | ) 21 | 22 | return { canUpdate, canRead, canReadSensitive } as const 23 | }), 24 | }, 25 | ) {} 26 | -------------------------------------------------------------------------------- /src/Accounts/UsersRepo.ts: -------------------------------------------------------------------------------- 1 | import { Model, SqlClient, SqlSchema } from "@effect/sql" 2 | import { Effect, pipe } from "effect" 3 | import { User } from "../Domain/User.js" 4 | import { SqlLive } from "../Sql.js" 5 | import { AccessToken } from "../Domain/AccessToken.js" 6 | import { makeTestLayer } from "../lib/Layer.js" 7 | 8 | export class UsersRepo extends Effect.Service()( 9 | "Accounts/UsersRepo", 10 | { 11 | effect: Effect.gen(function* () { 12 | const sql = yield* SqlClient.SqlClient 13 | const repo = yield* Model.makeRepository(User, { 14 | tableName: "users", 15 | spanPrefix: "UsersRepo", 16 | idColumn: "id", 17 | }) 18 | 19 | const findByAccessTokenSchema = SqlSchema.findOne({ 20 | Request: AccessToken, 21 | Result: User, 22 | execute: (key) => sql`select * from users where accessToken = ${key}`, 23 | }) 24 | const findByAccessToken = (apiKey: AccessToken) => 25 | pipe( 26 | findByAccessTokenSchema(apiKey), 27 | Effect.orDie, 28 | Effect.withSpan("UsersRepo.findByAccessToken"), 29 | ) 30 | 31 | return { ...repo, findByAccessToken } as const 32 | }), 33 | dependencies: [SqlLive], 34 | }, 35 | ) { 36 | static Test = makeTestLayer(UsersRepo)({}) 37 | } 38 | -------------------------------------------------------------------------------- /src/Api.ts: -------------------------------------------------------------------------------- 1 | import { HttpApi, OpenApi } from "@effect/platform" 2 | import { AccountsApi } from "./Accounts/Api.js" 3 | import { GroupsApi } from "./Groups/Api.js" 4 | import { PeopleApi } from "./People/Api.js" 5 | 6 | export class Api extends HttpApi.empty 7 | .add(AccountsApi) 8 | .add(GroupsApi) 9 | .add(PeopleApi) 10 | .annotate(OpenApi.Title, "Groups API") 11 | .annotate(OpenApi.Servers, [{ url: "http://localhost:3000" }]) {} 12 | -------------------------------------------------------------------------------- /src/Domain/AccessToken.ts: -------------------------------------------------------------------------------- 1 | import { Redacted, Schema } from "effect" 2 | 3 | export const AccessTokenString = Schema.String.pipe(Schema.brand("AccessToken")) 4 | export const AccessToken = Schema.Redacted(AccessTokenString) 5 | export type AccessToken = typeof AccessToken.Type 6 | 7 | export const accessTokenFromString = (token: string): AccessToken => 8 | Redacted.make(AccessTokenString.make(token)) 9 | 10 | export const accessTokenFromRedacted = ( 11 | token: Redacted.Redacted, 12 | ): AccessToken => token as AccessToken 13 | -------------------------------------------------------------------------------- /src/Domain/Account.ts: -------------------------------------------------------------------------------- 1 | import { Model } from "@effect/sql" 2 | import { Schema } from "effect" 3 | 4 | export const AccountId = Schema.Number.pipe(Schema.brand("AccountId")) 5 | export type AccountId = typeof AccountId.Type 6 | 7 | export class Account extends Model.Class("Account")({ 8 | id: Model.Generated(AccountId), 9 | createdAt: Model.DateTimeInsert, 10 | updatedAt: Model.DateTimeUpdate, 11 | }) {} 12 | -------------------------------------------------------------------------------- /src/Domain/Email.ts: -------------------------------------------------------------------------------- 1 | import { Schema } from "effect" 2 | 3 | export const Email = Schema.String.pipe( 4 | Schema.pattern(/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/), 5 | Schema.annotations({ 6 | title: "Email", 7 | description: "An email address", 8 | }), 9 | Schema.brand("Email"), 10 | Schema.annotations({ title: "Email" }), 11 | ) 12 | 13 | export type Email = typeof Email.Type 14 | -------------------------------------------------------------------------------- /src/Domain/Group.ts: -------------------------------------------------------------------------------- 1 | import { Schema } from "effect" 2 | import { Model } from "@effect/sql" 3 | import { AccountId } from "./Account.js" 4 | import { HttpApiSchema } from "@effect/platform" 5 | 6 | export const GroupId = Schema.Number.pipe(Schema.brand("GroupId")) 7 | export type GroupId = typeof GroupId.Type 8 | 9 | export const GroupIdFromString = Schema.NumberFromString.pipe( 10 | Schema.compose(GroupId), 11 | ) 12 | 13 | export class Group extends Model.Class("Group")({ 14 | id: Model.Generated(GroupId), 15 | ownerId: Model.GeneratedByApp(AccountId), 16 | name: Schema.NonEmptyTrimmedString, 17 | createdAt: Model.DateTimeInsert, 18 | updatedAt: Model.DateTimeUpdate, 19 | }) {} 20 | 21 | export class GroupNotFound extends Schema.TaggedError()( 22 | "GroupNotFound", 23 | { id: GroupId }, 24 | HttpApiSchema.annotations({ status: 404 }), 25 | ) {} 26 | -------------------------------------------------------------------------------- /src/Domain/Person.ts: -------------------------------------------------------------------------------- 1 | import { Schema } from "effect" 2 | import { Model } from "@effect/sql" 3 | import { GroupId } from "./Group.js" 4 | 5 | export const PersonId = Schema.Number.pipe(Schema.brand("PersonId")) 6 | export type PersonId = typeof PersonId.Type 7 | 8 | export const PersonIdFromString = Schema.NumberFromString.pipe( 9 | Schema.compose(PersonId), 10 | ) 11 | 12 | export class Person extends Model.Class("Person")({ 13 | id: Model.Generated(PersonId), 14 | groupId: Model.GeneratedByApp(GroupId), 15 | firstName: Schema.NonEmptyTrimmedString, 16 | lastName: Schema.NonEmptyTrimmedString, 17 | dateOfBirth: Model.FieldOption(Model.Date), 18 | createdAt: Model.DateTimeInsert, 19 | updatedAt: Model.DateTimeUpdate, 20 | }) {} 21 | 22 | export class PersonNotFound extends Schema.TaggedError()( 23 | "PersonNotFound", 24 | { 25 | id: PersonId, 26 | }, 27 | ) {} 28 | -------------------------------------------------------------------------------- /src/Domain/Policy.ts: -------------------------------------------------------------------------------- 1 | import { HttpApiSchema } from "@effect/platform" 2 | import { Effect, Predicate, Schema } from "effect" 3 | import { CurrentUser, User, UserId } from "../Domain/User.js" 4 | 5 | export class Unauthorized extends Schema.TaggedError()( 6 | "Unauthorized", 7 | { 8 | actorId: UserId, 9 | entity: Schema.String, 10 | action: Schema.String, 11 | }, 12 | HttpApiSchema.annotations({ status: 403 }), 13 | ) { 14 | get message() { 15 | return `Actor (${this.actorId}) is not authorized to perform action "${this.action}" on entity "${this.entity}"` 16 | } 17 | 18 | static is(u: unknown): u is Unauthorized { 19 | return Predicate.isTagged(u, "Unauthorized") 20 | } 21 | 22 | static refail(entity: string, action: string) { 23 | return ( 24 | effect: Effect.Effect, 25 | ): Effect.Effect => 26 | Effect.catchIf( 27 | effect, 28 | (e) => !Unauthorized.is(e), 29 | () => 30 | Effect.flatMap( 31 | CurrentUser, 32 | (actor) => 33 | new Unauthorized({ 34 | actorId: actor.id, 35 | entity, 36 | action, 37 | }), 38 | ), 39 | ) as any 40 | } 41 | } 42 | 43 | export const TypeId: unique symbol = Symbol.for("Domain/Policy/AuthorizedActor") 44 | export type TypeId = typeof TypeId 45 | 46 | export interface AuthorizedActor 47 | extends User { 48 | readonly [TypeId]: { 49 | readonly _Entity: Entity 50 | readonly _Action: Action 51 | } 52 | } 53 | 54 | export const authorizedActor = (user: User): AuthorizedActor => 55 | user as any 56 | 57 | export const policy = ( 58 | entity: Entity, 59 | action: Action, 60 | f: (actor: User) => Effect.Effect, 61 | ): Effect.Effect< 62 | AuthorizedActor, 63 | E | Unauthorized, 64 | R | CurrentUser 65 | > => 66 | Effect.flatMap(CurrentUser, (actor) => 67 | Effect.flatMap(f(actor), (can) => 68 | can 69 | ? Effect.succeed(authorizedActor(actor)) 70 | : Effect.fail( 71 | new Unauthorized({ 72 | actorId: actor.id, 73 | entity, 74 | action, 75 | }), 76 | ), 77 | ), 78 | ) 79 | 80 | export const policyCompose = 81 | , E, R>( 82 | that: Effect.Effect, 83 | ) => 84 | , E2, R2>( 85 | self: Effect.Effect, 86 | ): Effect.Effect => 87 | Effect.zipRight(self, that) as any 88 | 89 | export const policyUse = 90 | , E, R>( 91 | policy: Effect.Effect, 92 | ) => 93 | ( 94 | effect: Effect.Effect, 95 | ): Effect.Effect | R> => 96 | policy.pipe(Effect.zipRight(effect)) as any 97 | 98 | export const policyRequire = 99 | ( 100 | _entity: Entity, 101 | _action: Action, 102 | ) => 103 | ( 104 | effect: Effect.Effect, 105 | ): Effect.Effect> => 106 | effect 107 | 108 | export const withSystemActor = ( 109 | effect: Effect.Effect, 110 | ): Effect.Effect>> => effect as any 111 | -------------------------------------------------------------------------------- /src/Domain/User.ts: -------------------------------------------------------------------------------- 1 | import { HttpApiSchema } from "@effect/platform" 2 | import { Model } from "@effect/sql" 3 | import { Context, Schema } from "effect" 4 | import { AccessToken } from "./AccessToken.js" 5 | import { Account, AccountId } from "./Account.js" 6 | import { Email } from "./Email.js" 7 | 8 | export const UserId = Schema.Number.pipe(Schema.brand("UserId")) 9 | export type UserId = typeof UserId.Type 10 | 11 | export const UserIdFromString = Schema.NumberFromString.pipe( 12 | Schema.compose(UserId), 13 | ) 14 | 15 | export class User extends Model.Class("User")({ 16 | id: Model.Generated(UserId), 17 | accountId: Model.GeneratedByApp(AccountId), 18 | email: Email, 19 | accessToken: Model.Sensitive(AccessToken), 20 | createdAt: Model.DateTimeInsert, 21 | updatedAt: Model.DateTimeUpdate, 22 | }) {} 23 | 24 | export class UserWithSensitive extends Model.Class( 25 | "UserWithSensitive", 26 | )({ 27 | ...Model.fields(User), 28 | accessToken: AccessToken, 29 | account: Account, 30 | }) {} 31 | 32 | export class CurrentUser extends Context.Tag("Domain/User/CurrentUser")< 33 | CurrentUser, 34 | User 35 | >() {} 36 | 37 | export class UserNotFound extends Schema.TaggedError()( 38 | "UserNotFound", 39 | { id: UserId }, 40 | HttpApiSchema.annotations({ status: 404 }), 41 | ) {} 42 | -------------------------------------------------------------------------------- /src/Groups.ts: -------------------------------------------------------------------------------- 1 | import { Effect, Option, pipe } from "effect" 2 | import { GroupsRepo } from "./Groups/Repo.js" 3 | import { AccountId } from "./Domain/Account.js" 4 | import { Group, GroupId, GroupNotFound } from "./Domain/Group.js" 5 | import { policyRequire } from "./Domain/Policy.js" 6 | import { SqlClient } from "@effect/sql" 7 | import { SqlLive } from "./Sql.js" 8 | 9 | export class Groups extends Effect.Service()("Groups", { 10 | effect: Effect.gen(function* () { 11 | const repo = yield* GroupsRepo 12 | const sql = yield* SqlClient.SqlClient 13 | 14 | const create = (ownerId: AccountId, group: typeof Group.jsonCreate.Type) => 15 | pipe( 16 | repo.insert( 17 | Group.insert.make({ 18 | ...group, 19 | ownerId, 20 | }), 21 | ), 22 | Effect.withSpan("Groups.create", { attributes: { group } }), 23 | policyRequire("Group", "create"), 24 | ) 25 | 26 | const update = ( 27 | group: Group, 28 | update: Partial, 29 | ) => 30 | pipe( 31 | repo.update({ 32 | ...group, 33 | ...update, 34 | updatedAt: undefined, 35 | }), 36 | Effect.withSpan("Groups.update", { 37 | attributes: { id: group.id, update }, 38 | }), 39 | policyRequire("Group", "update"), 40 | ) 41 | 42 | const findById = (id: GroupId) => 43 | pipe( 44 | repo.findById(id), 45 | Effect.withSpan("Groups.findById", { attributes: { id } }), 46 | policyRequire("Group", "read"), 47 | ) 48 | 49 | const with_ = ( 50 | id: GroupId, 51 | f: (group: Group) => Effect.Effect, 52 | ): Effect.Effect => 53 | pipe( 54 | repo.findById(id), 55 | Effect.flatMap( 56 | Option.match({ 57 | onNone: () => new GroupNotFound({ id }), 58 | onSome: Effect.succeed, 59 | }), 60 | ), 61 | Effect.flatMap(f), 62 | sql.withTransaction, 63 | Effect.catchTag("SqlError", (err) => Effect.die(err)), 64 | Effect.withSpan("Groups.with", { attributes: { id } }), 65 | ) 66 | 67 | return { create, update, findById, with: with_ } as const 68 | }), 69 | dependencies: [SqlLive, GroupsRepo.Default], 70 | }) {} 71 | -------------------------------------------------------------------------------- /src/Groups/Api.ts: -------------------------------------------------------------------------------- 1 | import { Group, GroupIdFromString, GroupNotFound } from "../Domain/Group.js" 2 | import { 3 | HttpApiEndpoint, 4 | HttpApiGroup, 5 | HttpApiSchema, 6 | OpenApi, 7 | } from "@effect/platform" 8 | import { Authentication } from "../Accounts/Api.js" 9 | 10 | export class GroupsApi extends HttpApiGroup.make("groups") 11 | .add( 12 | HttpApiEndpoint.post("create", "/") 13 | .addSuccess(Group.json) 14 | .setPayload(Group.jsonCreate), 15 | ) 16 | .add( 17 | HttpApiEndpoint.patch( 18 | "update", 19 | )`/${HttpApiSchema.param("id", GroupIdFromString)}` 20 | .addSuccess(Group.json) 21 | .setPayload(Group.jsonUpdate) 22 | .addError(GroupNotFound), 23 | ) 24 | .middleware(Authentication) 25 | .prefix("/groups") 26 | .annotate(OpenApi.Title, "Groups") 27 | .annotate(OpenApi.Description, "Manage groups") {} 28 | -------------------------------------------------------------------------------- /src/Groups/Http.ts: -------------------------------------------------------------------------------- 1 | import { HttpApiBuilder } from "@effect/platform" 2 | import { Effect, Layer, pipe } from "effect" 3 | import { Api } from "../Api.js" 4 | import { policyUse } from "../Domain/Policy.js" 5 | import { CurrentUser } from "../Domain/User.js" 6 | import { Groups } from "../Groups.js" 7 | import { GroupsPolicy } from "./Policy.js" 8 | import { AuthenticationLive } from "../Accounts/Http.js" 9 | 10 | export const HttpGroupsLive = HttpApiBuilder.group(Api, "groups", (handlers) => 11 | Effect.gen(function* () { 12 | const groups = yield* Groups 13 | const policy = yield* GroupsPolicy 14 | 15 | return handlers 16 | .handle("create", ({ payload }) => 17 | CurrentUser.pipe( 18 | Effect.flatMap((user) => groups.create(user.accountId, payload)), 19 | policyUse(policy.canCreate(payload)), 20 | ), 21 | ) 22 | .handle("update", ({ payload, path }) => 23 | groups.with(path.id, (group) => 24 | pipe( 25 | groups.update(group, payload), 26 | policyUse(policy.canUpdate(group)), 27 | ), 28 | ), 29 | ) 30 | }), 31 | ).pipe( 32 | Layer.provide([AuthenticationLive, Groups.Default, GroupsPolicy.Default]), 33 | ) 34 | -------------------------------------------------------------------------------- /src/Groups/Policy.ts: -------------------------------------------------------------------------------- 1 | import { Effect } from "effect" 2 | import { policy } from "../Domain/Policy.js" 3 | import { Group } from "../Domain/Group.js" 4 | 5 | export class GroupsPolicy extends Effect.Service()( 6 | "Groups/Policy", 7 | { 8 | effect: Effect.gen(function* () { 9 | const canCreate = (_group: typeof Group.jsonCreate.Type) => 10 | policy("Group", "create", (_actor) => Effect.succeed(true)) 11 | 12 | const canUpdate = (group: Group) => 13 | policy("Group", "update", (actor) => 14 | Effect.succeed(group.ownerId === actor.accountId), 15 | ) 16 | 17 | return { canCreate, canUpdate } as const 18 | }), 19 | }, 20 | ) {} 21 | -------------------------------------------------------------------------------- /src/Groups/Repo.ts: -------------------------------------------------------------------------------- 1 | import { Model } from "@effect/sql" 2 | import { Effect } from "effect" 3 | import { Group } from "../Domain/Group.js" 4 | import { SqlLive } from "../Sql.js" 5 | 6 | export class GroupsRepo extends Effect.Service()("Groups/Repo", { 7 | effect: Model.makeRepository(Group, { 8 | tableName: "groups", 9 | spanPrefix: "GroupsRepo", 10 | idColumn: "id", 11 | }), 12 | dependencies: [SqlLive], 13 | }) {} 14 | -------------------------------------------------------------------------------- /src/Http.ts: -------------------------------------------------------------------------------- 1 | import { 2 | HttpApiBuilder, 3 | HttpApiScalar, 4 | HttpMiddleware, 5 | HttpServer, 6 | } from "@effect/platform" 7 | import { Layer } from "effect" 8 | import { NodeHttpServer } from "@effect/platform-node" 9 | import { createServer } from "http" 10 | import { Api } from "./Api.js" 11 | import { HttpAccountsLive } from "./Accounts/Http.js" 12 | import { HttpGroupsLive } from "./Groups/Http.js" 13 | import { HttpPeopleLive } from "./People/Http.js" 14 | 15 | const ApiLive = Layer.provide(HttpApiBuilder.api(Api), [ 16 | HttpAccountsLive, 17 | HttpGroupsLive, 18 | HttpPeopleLive, 19 | ]) 20 | 21 | export const HttpLive = HttpApiBuilder.serve(HttpMiddleware.logger).pipe( 22 | Layer.provide(HttpApiScalar.layer()), 23 | Layer.provide(HttpApiBuilder.middlewareOpenApi()), 24 | Layer.provide(HttpApiBuilder.middlewareCors()), 25 | Layer.provide(ApiLive), 26 | HttpServer.withLogAddress, 27 | Layer.provide(NodeHttpServer.layer(createServer, { port: 3000 })), 28 | ) 29 | -------------------------------------------------------------------------------- /src/People.ts: -------------------------------------------------------------------------------- 1 | import { Effect, Option, pipe } from "effect" 2 | import { PeopleRepo } from "./People/Repo.js" 3 | import { Person, PersonId, PersonNotFound } from "./Domain/Person.js" 4 | import { policyRequire } from "./Domain/Policy.js" 5 | import { GroupId } from "./Domain/Group.js" 6 | import { SqlClient } from "@effect/sql" 7 | import { SqlLive } from "./Sql.js" 8 | 9 | export class People extends Effect.Service()("People", { 10 | effect: Effect.gen(function* () { 11 | const repo = yield* PeopleRepo 12 | const sql = yield* SqlClient.SqlClient 13 | 14 | const create = (groupId: GroupId, person: typeof Person.jsonCreate.Type) => 15 | pipe( 16 | repo.insert( 17 | Person.insert.make({ 18 | ...person, 19 | groupId, 20 | }), 21 | ), 22 | Effect.withSpan("People.create", { attributes: { person, groupId } }), 23 | policyRequire("Person", "create"), 24 | ) 25 | 26 | const findById = (id: PersonId) => 27 | pipe( 28 | repo.findById(id), 29 | Effect.withSpan("People.findById", { attributes: { id } }), 30 | policyRequire("Person", "read"), 31 | ) 32 | 33 | const with_ = ( 34 | id: PersonId, 35 | f: (person: Person) => Effect.Effect, 36 | ): Effect.Effect => 37 | pipe( 38 | repo.findById(id), 39 | Effect.flatMap( 40 | Option.match({ 41 | onNone: () => Effect.fail(new PersonNotFound({ id })), 42 | onSome: Effect.succeed, 43 | }), 44 | ), 45 | Effect.flatMap(f), 46 | sql.withTransaction, 47 | Effect.catchTag("SqlError", (e) => Effect.die(e)), 48 | Effect.withSpan("People.with", { attributes: { id } }), 49 | ) 50 | 51 | return { create, findById, with: with_ } as const 52 | }), 53 | dependencies: [SqlLive, PeopleRepo.Default], 54 | }) {} 55 | -------------------------------------------------------------------------------- /src/People/Api.ts: -------------------------------------------------------------------------------- 1 | import { GroupIdFromString, GroupNotFound } from "../Domain/Group.js" 2 | import { Person, PersonIdFromString, PersonNotFound } from "../Domain/Person.js" 3 | import { 4 | HttpApiEndpoint, 5 | HttpApiGroup, 6 | HttpApiSchema, 7 | OpenApi, 8 | } from "@effect/platform" 9 | import { Authentication } from "../Accounts/Api.js" 10 | 11 | export class PeopleApi extends HttpApiGroup.make("people") 12 | .add( 13 | HttpApiEndpoint.get( 14 | "findById", 15 | )`/${HttpApiSchema.param("id", PersonIdFromString)}` 16 | .addSuccess(Person.json) 17 | .addError(PersonNotFound), 18 | ) 19 | .prefix("/people") 20 | .add( 21 | HttpApiEndpoint.post( 22 | "create", 23 | )`/groups/${HttpApiSchema.param("groupId", GroupIdFromString)}/people` 24 | .addSuccess(Person.json) 25 | .setPayload(Person.jsonCreate) 26 | .addError(GroupNotFound), 27 | ) 28 | .middleware(Authentication) 29 | .annotate(OpenApi.Title, "People") 30 | .annotate(OpenApi.Description, "Manage people") {} 31 | -------------------------------------------------------------------------------- /src/People/Http.ts: -------------------------------------------------------------------------------- 1 | import { HttpApiBuilder } from "@effect/platform" 2 | import { Effect, Layer, pipe } from "effect" 3 | import { Api } from "../Api.js" 4 | import { policyUse } from "../Domain/Policy.js" 5 | import { Groups } from "../Groups.js" 6 | import { People } from "../People.js" 7 | import { PeoplePolicy } from "./Policy.js" 8 | import { PersonNotFound } from "../Domain/Person.js" 9 | import { AuthenticationLive } from "../Accounts/Http.js" 10 | 11 | export const HttpPeopleLive = HttpApiBuilder.group(Api, "people", (handlers) => 12 | Effect.gen(function* () { 13 | const groups = yield* Groups 14 | const people = yield* People 15 | const policy = yield* PeoplePolicy 16 | 17 | return handlers 18 | .handle("create", ({ payload, path }) => 19 | groups.with(path.groupId, (group) => 20 | pipe( 21 | people.create(group.id, payload), 22 | policyUse(policy.canCreate(group.id, payload)), 23 | ), 24 | ), 25 | ) 26 | .handle("findById", ({ path }) => 27 | pipe( 28 | people.findById(path.id), 29 | Effect.flatten, 30 | Effect.mapError(() => new PersonNotFound({ id: path.id })), 31 | policyUse(policy.canRead(path.id)), 32 | ), 33 | ) 34 | }), 35 | ).pipe( 36 | Layer.provide([ 37 | Groups.Default, 38 | People.Default, 39 | PeoplePolicy.Default, 40 | AuthenticationLive, 41 | ]), 42 | ) 43 | -------------------------------------------------------------------------------- /src/People/Policy.ts: -------------------------------------------------------------------------------- 1 | import { Effect, pipe } from "effect" 2 | import { policy, policyCompose, Unauthorized } from "../Domain/Policy.js" 3 | import { Person, PersonId } from "../Domain/Person.js" 4 | import { GroupId } from "../Domain/Group.js" 5 | import { GroupsPolicy } from "../Groups/Policy.js" 6 | import { Groups } from "../Groups.js" 7 | import { People } from "../People.js" 8 | 9 | export class PeoplePolicy extends Effect.Service()( 10 | "People/Policy", 11 | { 12 | effect: Effect.gen(function* () { 13 | const groupsPolicy = yield* GroupsPolicy 14 | const groups = yield* Groups 15 | const people = yield* People 16 | 17 | const canCreate = ( 18 | groupId: GroupId, 19 | _person: typeof Person.jsonCreate.Type, 20 | ) => 21 | Unauthorized.refail( 22 | "Person", 23 | "create", 24 | )( 25 | groups.with(groupId, (group) => 26 | pipe( 27 | groupsPolicy.canUpdate(group), 28 | policyCompose( 29 | policy("Person", "create", (_actor) => Effect.succeed(true)), 30 | ), 31 | ), 32 | ), 33 | ) 34 | 35 | const canRead = (id: PersonId) => 36 | Unauthorized.refail( 37 | "Person", 38 | "read", 39 | )( 40 | people.with(id, (person) => 41 | groups.with(person.groupId, (group) => 42 | pipe( 43 | groupsPolicy.canUpdate(group), 44 | policyCompose( 45 | policy("Person", "read", (_actor) => Effect.succeed(true)), 46 | ), 47 | ), 48 | ), 49 | ), 50 | ) 51 | 52 | return { canCreate, canRead } as const 53 | }), 54 | dependencies: [GroupsPolicy.Default, Groups.Default, People.Default], 55 | }, 56 | ) {} 57 | -------------------------------------------------------------------------------- /src/People/Repo.ts: -------------------------------------------------------------------------------- 1 | import { Model } from "@effect/sql" 2 | import { Effect } from "effect" 3 | import { Person } from "../Domain/Person.js" 4 | import { SqlLive } from "../Sql.js" 5 | 6 | export class PeopleRepo extends Effect.Service()("People/Repo", { 7 | effect: Model.makeRepository(Person, { 8 | tableName: "people", 9 | spanPrefix: "PeopleRepo", 10 | idColumn: "id", 11 | }), 12 | dependencies: [SqlLive], 13 | }) {} 14 | -------------------------------------------------------------------------------- /src/Sql.ts: -------------------------------------------------------------------------------- 1 | import { NodeContext } from "@effect/platform-node" 2 | import { SqliteClient, SqliteMigrator } from "@effect/sql-sqlite-node" 3 | import { identity, Layer } from "effect" 4 | import { fileURLToPath } from "url" 5 | import { makeTestLayer } from "./lib/Layer.js" 6 | import { SqlClient } from "@effect/sql" 7 | 8 | const ClientLive = SqliteClient.layer({ 9 | filename: "data/db.sqlite", 10 | }) 11 | 12 | const MigratorLive = SqliteMigrator.layer({ 13 | loader: SqliteMigrator.fromFileSystem( 14 | fileURLToPath(new URL("./migrations", import.meta.url)), 15 | ), 16 | }).pipe(Layer.provide(NodeContext.layer)) 17 | 18 | export const SqlLive = MigratorLive.pipe(Layer.provideMerge(ClientLive)) 19 | 20 | export const SqlTest = makeTestLayer(SqlClient.SqlClient)({ 21 | withTransaction: identity, 22 | }) 23 | -------------------------------------------------------------------------------- /src/Tracing.ts: -------------------------------------------------------------------------------- 1 | import * as NodeSdk from "@effect/opentelemetry/NodeSdk" 2 | import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http" 3 | import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base" 4 | import { Config, Effect, Layer, Redacted } from "effect" 5 | 6 | export const TracingLive = Layer.unwrapEffect( 7 | Effect.gen(function* () { 8 | const apiKey = yield* Config.option(Config.redacted("HONEYCOMB_API_KEY")) 9 | const dataset = yield* Config.withDefault( 10 | Config.string("HONEYCOMB_DATASET"), 11 | "effect-http-play", 12 | ) 13 | if (apiKey._tag === "None") { 14 | const endpoint = yield* Config.option( 15 | Config.string("OTEL_EXPORTER_OTLP_ENDPOINT"), 16 | ) 17 | if (endpoint._tag === "None") { 18 | return Layer.empty 19 | } 20 | return NodeSdk.layer(() => ({ 21 | resource: { 22 | serviceName: dataset, 23 | }, 24 | spanProcessor: new BatchSpanProcessor( 25 | new OTLPTraceExporter({ url: `${endpoint.value}/v1/traces` }), 26 | ), 27 | })) 28 | } 29 | 30 | const headers = { 31 | "X-Honeycomb-Team": Redacted.value(apiKey.value), 32 | "X-Honeycomb-Dataset": dataset, 33 | } 34 | 35 | return NodeSdk.layer(() => ({ 36 | resource: { 37 | serviceName: dataset, 38 | }, 39 | spanProcessor: new BatchSpanProcessor( 40 | new OTLPTraceExporter({ 41 | url: "https://api.honeycomb.io/v1/traces", 42 | headers, 43 | }), 44 | ), 45 | })) 46 | }), 47 | ) 48 | -------------------------------------------------------------------------------- /src/Uuid.ts: -------------------------------------------------------------------------------- 1 | import { Effect, Layer } from "effect" 2 | import * as Api from "uuid" 3 | 4 | export class Uuid extends Effect.Service()("Uuid", { 5 | succeed: { 6 | generate: Effect.sync(() => Api.v7()), 7 | }, 8 | }) { 9 | static Test = Layer.succeed( 10 | Uuid, 11 | new Uuid({ 12 | generate: Effect.succeed("test-uuid"), 13 | }), 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /src/client.ts: -------------------------------------------------------------------------------- 1 | import { Cookies, HttpApiClient, HttpClient } from "@effect/platform" 2 | import { NodeHttpClient, NodeRuntime } from "@effect/platform-node" 3 | import { Effect, Ref } from "effect" 4 | import { Api } from "./Api.js" 5 | import { Email } from "./Domain/Email.js" 6 | 7 | Effect.gen(function* () { 8 | const cookies = yield* Ref.make(Cookies.empty) 9 | const client = yield* HttpApiClient.make(Api, { 10 | baseUrl: "http://localhost:3000", 11 | transformClient: HttpClient.withCookiesRef(cookies), 12 | }) 13 | const user = yield* client.accounts.createUser({ 14 | payload: { 15 | email: Email.make("joe2.bloggs@example.com"), 16 | }, 17 | }) 18 | console.log(user) 19 | const me = yield* client.accounts.getUserMe() 20 | console.log(me) 21 | }).pipe(Effect.provide(NodeHttpClient.layerUndici), NodeRuntime.runMain) 22 | -------------------------------------------------------------------------------- /src/lib/Layer.ts: -------------------------------------------------------------------------------- 1 | import { Context, Effect, Layer } from "effect" 2 | 3 | const makeUnimplemented = (id: string, prop: PropertyKey) => { 4 | const dead = Effect.die(`${id}: Unimplemented method "${prop.toString()}"`) 5 | function unimplemented() { 6 | return dead 7 | } 8 | Object.assign(unimplemented, dead) 9 | Object.setPrototypeOf(unimplemented, Object.getPrototypeOf(dead)) 10 | return unimplemented 11 | } 12 | 13 | const makeUnimplementedProxy = ( 14 | service: string, 15 | impl: Partial, 16 | ): A => 17 | new Proxy({ ...impl } as A, { 18 | get(target, prop, _receiver) { 19 | if (prop in target) { 20 | return target[prop as keyof A] 21 | } 22 | return ((target as any)[prop] = makeUnimplemented(service, prop)) 23 | }, 24 | has: () => true, 25 | }) 26 | 27 | export const makeTestLayer = 28 | (tag: Context.Tag) => 29 | (service: Partial): Layer.Layer => 30 | Layer.succeed(tag, makeUnimplementedProxy(tag.key, service)) 31 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { NodeRuntime } from "@effect/platform-node" 2 | import { Layer } from "effect" 3 | import { HttpLive } from "./Http.js" 4 | import { TracingLive } from "./Tracing.js" 5 | 6 | HttpLive.pipe(Layer.provide(TracingLive), Layer.launch, NodeRuntime.runMain) 7 | -------------------------------------------------------------------------------- /src/migrations/00001_create users.ts: -------------------------------------------------------------------------------- 1 | import { SqlClient } from "@effect/sql" 2 | import { Effect } from "effect" 3 | 4 | export default Effect.gen(function* () { 5 | const sql = yield* SqlClient.SqlClient 6 | yield* sql.onDialectOrElse({ 7 | pg: () => sql` 8 | CREATE TABLE accounts ( 9 | id SERIAL PRIMARY KEY, 10 | createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, 11 | updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL 12 | ) 13 | `, 14 | orElse: () => sql` 15 | CREATE TABLE accounts ( 16 | id INTEGER PRIMARY KEY AUTOINCREMENT, 17 | createdAt DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, 18 | updatedAt DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL 19 | ) 20 | `, 21 | }) 22 | yield* sql.onDialectOrElse({ 23 | pg: () => sql` 24 | CREATE TABLE users ( 25 | id SERIAL PRIMARY KEY, 26 | accountId INTEGER NOT NULL, 27 | email TEXT UNIQUE NOT NULL, 28 | accessToken VARCHAR(255) UNIQUE NOT NULL, 29 | createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, 30 | updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, 31 | FOREIGN KEY (accountId) REFERENCES accounts(id) 32 | ) 33 | `, 34 | orElse: () => sql` 35 | CREATE TABLE users ( 36 | id INTEGER PRIMARY KEY AUTOINCREMENT, 37 | accountId INTEGER NOT NULL, 38 | email TEXT UNIQUE NOT NULL, 39 | accessToken VARCHAR(255) UNIQUE NOT NULL, 40 | createdAt DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, 41 | updatedAt DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, 42 | FOREIGN KEY (accountId) REFERENCES accounts(id) 43 | ) 44 | `, 45 | }) 46 | }) 47 | -------------------------------------------------------------------------------- /src/migrations/00002_create groups.ts: -------------------------------------------------------------------------------- 1 | import { SqlClient } from "@effect/sql" 2 | import { Effect } from "effect" 3 | 4 | export default Effect.gen(function* () { 5 | const sql = yield* SqlClient.SqlClient 6 | yield* sql.onDialectOrElse({ 7 | pg: () => sql` 8 | CREATE TABLE groups ( 9 | id SERIAL PRIMARY KEY, 10 | ownerId INTEGER NOT NULL, 11 | name VARCHAR(255) NOT NULL, 12 | createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, 13 | updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, 14 | FOREIGN KEY (ownerId) REFERENCES accounts(id) 15 | ) 16 | `, 17 | orElse: () => sql` 18 | CREATE TABLE groups ( 19 | id INTEGER PRIMARY KEY AUTOINCREMENT, 20 | ownerId INTEGER NOT NULL, 21 | name TEXT NOT NULL, 22 | createdAt DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, 23 | updatedAt DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, 24 | FOREIGN KEY (ownerId) REFERENCES accounts(id) 25 | ) 26 | `, 27 | }) 28 | }) 29 | -------------------------------------------------------------------------------- /src/migrations/00003_create_people.ts: -------------------------------------------------------------------------------- 1 | import { SqlClient } from "@effect/sql" 2 | import { Effect } from "effect" 3 | 4 | export default Effect.gen(function* () { 5 | const sql = yield* SqlClient.SqlClient 6 | yield* sql.onDialectOrElse({ 7 | pg: () => sql` 8 | CREATE TABLE people ( 9 | id SERIAL PRIMARY KEY, 10 | groupId INTEGER NOT NULL, 11 | firstName VARCHAR(255) NOT NULL, 12 | lastName VARCHAR(255) NOT NULL, 13 | dateOfBirth DATE, 14 | createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, 15 | updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, 16 | FOREIGN KEY (ownerId) REFERENCES groups(id) 17 | ) 18 | `, 19 | orElse: () => sql` 20 | CREATE TABLE people ( 21 | id INTEGER PRIMARY KEY AUTOINCREMENT, 22 | groupId INTEGER NOT NULL, 23 | firstName TEXT NOT NULL, 24 | lastName TEXT NOT NULL, 25 | dateOfBirth DATE, 26 | createdAt DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, 27 | updatedAt DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, 28 | FOREIGN KEY (groupId) REFERENCES groups(id) 29 | ) 30 | `, 31 | }) 32 | }) 33 | -------------------------------------------------------------------------------- /test/Accounts.test.ts: -------------------------------------------------------------------------------- 1 | import { assert, describe, it } from "@effect/vitest" 2 | import { Accounts } from "app/Accounts" 3 | import { AccountsRepo } from "app/Accounts/AccountsRepo" 4 | import { UsersRepo } from "app/Accounts/UsersRepo" 5 | import { Account, AccountId } from "app/Domain/Account" 6 | import { Email } from "app/Domain/Email" 7 | import { withSystemActor } from "app/Domain/Policy" 8 | import { User, UserId } from "app/Domain/User" 9 | import { makeTestLayer } from "app/lib/Layer" 10 | import { DateTime, Effect, Layer, pipe, Redacted } from "effect" 11 | 12 | describe("Accounts", () => { 13 | it.effect("createUser", () => 14 | Effect.gen(function* () { 15 | const accounts = yield* Accounts 16 | const user = yield* pipe( 17 | accounts.createUser({ email: Email.make("test@example.com") }), 18 | withSystemActor, 19 | ) 20 | assert.strictEqual(user.id, 1) 21 | assert.strictEqual(user.accountId, 123) 22 | assert.strictEqual(user.account.id, 123) 23 | assert.strictEqual(Redacted.value(user.accessToken), "test-uuid") 24 | }).pipe( 25 | Effect.provide( 26 | Accounts.Test.pipe( 27 | Layer.provide( 28 | makeTestLayer(AccountsRepo)({ 29 | insert: (account) => 30 | Effect.map( 31 | DateTime.now, 32 | (now) => 33 | new Account({ 34 | ...account, 35 | id: AccountId.make(123), 36 | createdAt: now, 37 | updatedAt: now, 38 | }), 39 | ), 40 | }), 41 | ), 42 | Layer.provide( 43 | makeTestLayer(UsersRepo)({ 44 | insert: (user) => 45 | Effect.map( 46 | DateTime.now, 47 | (now) => 48 | new User({ 49 | ...user, 50 | id: UserId.make(1), 51 | createdAt: now, 52 | updatedAt: now, 53 | }), 54 | ), 55 | }), 56 | ), 57 | ), 58 | ), 59 | ), 60 | ) 61 | }) 62 | -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "incremental": true, 5 | "outDir": "dist", 6 | "resolveJsonModule": true, 7 | "skipLibCheck": true, 8 | "moduleResolution": "NodeNext", 9 | "module": "NodeNext", 10 | "allowSyntheticDefaultImports": true, 11 | "exactOptionalPropertyTypes": true, 12 | "noErrorTruncation": true, 13 | "lib": ["ESNext", "DOM"], 14 | "sourceMap": true, 15 | "strict": true, 16 | "strictNullChecks": true, 17 | "target": "ESNext", 18 | "plugins": [{ "name": "@effect/language-service" }] 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "incremental": true 5 | }, 6 | "files": [], 7 | "references": [ 8 | { "path": "./tsconfig.src.json" }, 9 | { "path": "./tsconfig.test.json" } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /tsconfig.src.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src", 6 | "tsBuildInfoFile": "./tsconfig.src.tsbuildinfo" 7 | }, 8 | "include": ["src/**/*"] 9 | } 10 | -------------------------------------------------------------------------------- /tsconfig.test.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "test", 6 | "baseUrl": "./", 7 | "tsBuildInfoFile": "./tsconfig.test.tsbuildinfo", 8 | "paths": { 9 | "app/*": ["src/*.js"] 10 | } 11 | }, 12 | "include": ["test/**/*"], 13 | "references": [{ "path": "./tsconfig.src.json" }] 14 | } 15 | -------------------------------------------------------------------------------- /vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitest/config" 2 | import * as Path from "node:path" 3 | 4 | export default defineConfig({ 5 | test: { 6 | alias: { 7 | app: Path.join(__dirname, "src"), 8 | }, 9 | }, 10 | }) 11 | --------------------------------------------------------------------------------