diff --git a/extensions/akiflow/.gitignore b/extensions/akiflow/.gitignore new file mode 100644 index 00000000000..9ff34e3e9f3 --- /dev/null +++ b/extensions/akiflow/.gitignore @@ -0,0 +1,13 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules + +# Raycast specific files +raycast-env.d.ts +.raycast-swift-build +.swiftpm +compiled_raycast_swift + +# misc +.DS_Store diff --git a/extensions/akiflow/.prettierrc b/extensions/akiflow/.prettierrc new file mode 100644 index 00000000000..fc0f5030683 --- /dev/null +++ b/extensions/akiflow/.prettierrc @@ -0,0 +1,4 @@ +{ + "printWidth": 120, + "singleQuote": false +} diff --git a/extensions/akiflow/CHANGELOG.md b/extensions/akiflow/CHANGELOG.md new file mode 100644 index 00000000000..7be4ac75ece --- /dev/null +++ b/extensions/akiflow/CHANGELOG.md @@ -0,0 +1,3 @@ +# Akiflow Changelog + +## [Initial Version] - {PR_MERGE_DATE} \ No newline at end of file diff --git a/extensions/akiflow/README.md b/extensions/akiflow/README.md new file mode 100644 index 00000000000..0500ed756a9 --- /dev/null +++ b/extensions/akiflow/README.md @@ -0,0 +1,22 @@ +# Akiflow + +Manages your tasks in Akiflow + +## Set-Up Guide +Unfortunately, the lack of a public API for Akiflow means that setting this up is difficult and can be time-consuming (30min) + +1. Open the Akiflow desktop app, and then open the developer tools by pressing "Cmd+Shift+I". (You can also do this in the web app, but the keyboard shortcut might not work) +2. Go to the "Network" tab. This contains all of your network requests and it is where you will find the refresh token. + +**It should look something like this:** + +(It may be in a separate window rather than a side panel) +3. Wait a maximum of 30 minutes - the token used expires every 30 minutes and a new one is generated by your refresh token. +Eventually, you will see a refresh_token request in the network tab. You can do anything else while waiting, just ensure that the network tab remains open - history is not kept between sessions. + + +4. Copy the refresh token and paste it into the "Akiflow Extension" preferences in Raycast. Only copy what is inside the quotation marks. +5. You're done! You can now use the extension. + +@ me in Slack if you have any questions or need help. + \ No newline at end of file diff --git a/extensions/akiflow/assets/akiflow-icon.png b/extensions/akiflow/assets/akiflow-icon.png new file mode 100644 index 00000000000..f1c1fdc6bcb Binary files /dev/null and b/extensions/akiflow/assets/akiflow-icon.png differ diff --git a/extensions/akiflow/assets/akiflow-menu-bar-icon.png b/extensions/akiflow/assets/akiflow-menu-bar-icon.png new file mode 100644 index 00000000000..0d0962d3740 Binary files /dev/null and b/extensions/akiflow/assets/akiflow-menu-bar-icon.png differ diff --git a/extensions/akiflow/eslint.config.js b/extensions/akiflow/eslint.config.js new file mode 100644 index 00000000000..50f86489f3b --- /dev/null +++ b/extensions/akiflow/eslint.config.js @@ -0,0 +1,6 @@ +const { defineConfig } = require("eslint/config"); +const raycastConfig = require("@raycast/eslint-config"); + +module.exports = defineConfig([ + ...raycastConfig, +]); diff --git a/extensions/akiflow/media/akiflow-extension-set-up-step-1.png b/extensions/akiflow/media/akiflow-extension-set-up-step-1.png new file mode 100644 index 00000000000..a6b7e93aacd Binary files /dev/null and b/extensions/akiflow/media/akiflow-extension-set-up-step-1.png differ diff --git a/extensions/akiflow/media/akiflow-extension-set-up-step-2.png b/extensions/akiflow/media/akiflow-extension-set-up-step-2.png new file mode 100644 index 00000000000..140f2c42dab Binary files /dev/null and b/extensions/akiflow/media/akiflow-extension-set-up-step-2.png differ diff --git a/extensions/akiflow/media/slack.png b/extensions/akiflow/media/slack.png new file mode 100644 index 00000000000..4ba28d4c176 Binary files /dev/null and b/extensions/akiflow/media/slack.png differ diff --git a/extensions/akiflow/package-lock.json b/extensions/akiflow/package-lock.json new file mode 100644 index 00000000000..a57c87be8e5 --- /dev/null +++ b/extensions/akiflow/package-lock.json @@ -0,0 +1,3479 @@ +{ + "name": "akiflow", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "akiflow", + "license": "MIT", + "dependencies": { + "@raycast/api": "^1.94.0", + "@raycast/utils": "^1.17.0", + "axios": "^1.8.4", + "date-fns": "^4.1.0" + }, + "devDependencies": { + "@raycast/eslint-config": "^2.0.4", + "@types/node": "22.13.10", + "@types/react": "19.0.10", + "eslint": "^9.22.0", + "prettier": "^3.5.3", + "typescript": "^5.8.2" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz", + "integrity": "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.1.tgz", + "integrity": "sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.1.tgz", + "integrity": "sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.1.tgz", + "integrity": "sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.1.tgz", + "integrity": "sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.1.tgz", + "integrity": "sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.1.tgz", + "integrity": "sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.1.tgz", + "integrity": "sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.1.tgz", + "integrity": "sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.1.tgz", + "integrity": "sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.1.tgz", + "integrity": "sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.1.tgz", + "integrity": "sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.1.tgz", + "integrity": "sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.1.tgz", + "integrity": "sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.1.tgz", + "integrity": "sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.1.tgz", + "integrity": "sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.1.tgz", + "integrity": "sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.1.tgz", + "integrity": "sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.1.tgz", + "integrity": "sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.1.tgz", + "integrity": "sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.1.tgz", + "integrity": "sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.1.tgz", + "integrity": "sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.1.tgz", + "integrity": "sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.1.tgz", + "integrity": "sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.1.tgz", + "integrity": "sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.5.1.tgz", + "integrity": "sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", + "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.1.0.tgz", + "integrity": "sha512-kLrdPDJE1ckPo94kmPPf9Hfd0DU0Jw6oKYrhe+pwSC0iTUInmTa+w6fw8sGgcfkFJGNdWOUeOaDM4quW4a7OkA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", + "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.0.tgz", + "integrity": "sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "9.22.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.22.0.tgz", + "integrity": "sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz", + "integrity": "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.12.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz", + "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@inquirer/checkbox": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.1.4.tgz", + "integrity": "sha512-d30576EZdApjAMceijXA5jDzRQHT/MygbC+J8I7EqA6f/FRpYxlRtRJbHF8gHeWYeSdOuTEJqonn7QLB1ELezA==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.9", + "@inquirer/figures": "^1.0.11", + "@inquirer/type": "^3.0.5", + "ansi-escapes": "^4.3.2", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/confirm": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.8.tgz", + "integrity": "sha512-dNLWCYZvXDjO3rnQfk2iuJNL4Ivwz/T2+C3+WnNfJKsNGSuOs3wAo2F6e0p946gtSAk31nZMfW+MRmYaplPKsg==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.9", + "@inquirer/type": "^3.0.5" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/core": { + "version": "10.1.9", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.9.tgz", + "integrity": "sha512-sXhVB8n20NYkUBfDYgizGHlpRVaCRjtuzNZA6xpALIUbkgfd2Hjz+DfEN6+h1BRnuxw0/P4jCIMjMsEOAMwAJw==", + "license": "MIT", + "dependencies": { + "@inquirer/figures": "^1.0.11", + "@inquirer/type": "^3.0.5", + "ansi-escapes": "^4.3.2", + "cli-width": "^4.1.0", + "mute-stream": "^2.0.0", + "signal-exit": "^4.1.0", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/core/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/editor": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.9.tgz", + "integrity": "sha512-8HjOppAxO7O4wV1ETUlJFg6NDjp/W2NP5FB9ZPAcinAlNT4ZIWOLe2pUVwmmPRSV0NMdI5r/+lflN55AwZOKSw==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.9", + "@inquirer/type": "^3.0.5", + "external-editor": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/expand": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.11.tgz", + "integrity": "sha512-OZSUW4hFMW2TYvX/Sv+NnOZgO8CHT2TU1roUCUIF2T+wfw60XFRRp9MRUPCT06cRnKL+aemt2YmTWwt7rOrNEA==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.9", + "@inquirer/type": "^3.0.5", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.11.tgz", + "integrity": "sha512-eOg92lvrn/aRUqbxRyvpEWnrvRuTYRifixHkYVpJiygTgVSBIHDqLh0SrMQXkafvULg3ck11V7xvR+zcgvpHFw==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/input": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.1.8.tgz", + "integrity": "sha512-WXJI16oOZ3/LiENCAxe8joniNp8MQxF6Wi5V+EBbVA0ZIOpFcL4I9e7f7cXse0HJeIPCWO8Lcgnk98juItCi7Q==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.9", + "@inquirer/type": "^3.0.5" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/number": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.11.tgz", + "integrity": "sha512-pQK68CsKOgwvU2eA53AG/4npRTH2pvs/pZ2bFvzpBhrznh8Mcwt19c+nMO7LHRr3Vreu1KPhNBF3vQAKrjIulw==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.9", + "@inquirer/type": "^3.0.5" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/password": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.11.tgz", + "integrity": "sha512-dH6zLdv+HEv1nBs96Case6eppkRggMe8LoOTl30+Gq5Wf27AO/vHFgStTVz4aoevLdNXqwE23++IXGw4eiOXTg==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.9", + "@inquirer/type": "^3.0.5", + "ansi-escapes": "^4.3.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/prompts": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.4.0.tgz", + "integrity": "sha512-EZiJidQOT4O5PYtqnu1JbF0clv36oW2CviR66c7ma4LsupmmQlUwmdReGKRp456OWPWMz3PdrPiYg3aCk3op2w==", + "license": "MIT", + "dependencies": { + "@inquirer/checkbox": "^4.1.4", + "@inquirer/confirm": "^5.1.8", + "@inquirer/editor": "^4.2.9", + "@inquirer/expand": "^4.0.11", + "@inquirer/input": "^4.1.8", + "@inquirer/number": "^3.0.11", + "@inquirer/password": "^4.0.11", + "@inquirer/rawlist": "^4.0.11", + "@inquirer/search": "^3.0.11", + "@inquirer/select": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/rawlist": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.0.11.tgz", + "integrity": "sha512-uAYtTx0IF/PqUAvsRrF3xvnxJV516wmR6YVONOmCWJbbt87HcDHLfL9wmBQFbNJRv5kCjdYKrZcavDkH3sVJPg==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.9", + "@inquirer/type": "^3.0.5", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/search": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.0.11.tgz", + "integrity": "sha512-9CWQT0ikYcg6Ls3TOa7jljsD7PgjcsYEM0bYE+Gkz+uoW9u8eaJCRHJKkucpRE5+xKtaaDbrND+nPDoxzjYyew==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.9", + "@inquirer/figures": "^1.0.11", + "@inquirer/type": "^3.0.5", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/select": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.1.0.tgz", + "integrity": "sha512-z0a2fmgTSRN+YBuiK1ROfJ2Nvrpij5lVN3gPDkQGhavdvIVGHGW29LwYZfM/j42Ai2hUghTI/uoBuTbrJk42bA==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.9", + "@inquirer/figures": "^1.0.11", + "@inquirer/type": "^3.0.5", + "ansi-escapes": "^4.3.2", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/type": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.5.tgz", + "integrity": "sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@oclif/core": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/@oclif/core/-/core-4.2.10.tgz", + "integrity": "sha512-fAqcXgqkUm4v5FYy7qWP4w1HaOlVSVJveah+yVTo5Nm5kTiXhmD5mQQ7+knGeBaStyrtQy6WardoC2xSic9rlQ==", + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.3.2", + "ansis": "^3.17.0", + "clean-stack": "^3.0.1", + "cli-spinners": "^2.9.2", + "debug": "^4.4.0", + "ejs": "^3.1.10", + "get-package-type": "^0.1.0", + "globby": "^11.1.0", + "indent-string": "^4.0.0", + "is-wsl": "^2.2.0", + "lilconfig": "^3.1.3", + "minimatch": "^9.0.5", + "semver": "^7.6.3", + "string-width": "^4.2.3", + "supports-color": "^8", + "widest-line": "^3.1.0", + "wordwrap": "^1.0.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@oclif/plugin-autocomplete": { + "version": "3.2.26", + "resolved": "https://registry.npmjs.org/@oclif/plugin-autocomplete/-/plugin-autocomplete-3.2.26.tgz", + "integrity": "sha512-vpVByZUUd2tQ/KmjA+5ltKvO/iVYyByHiHhwaePEOFWZtC8XeZAMQ4pZHAROiLmOeBQEZydMaOweesZiTVSq5w==", + "license": "MIT", + "dependencies": { + "@oclif/core": "^4", + "ansis": "^3.16.0", + "debug": "^4.4.0", + "ejs": "^3.1.10" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@oclif/plugin-help": { + "version": "6.2.27", + "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-6.2.27.tgz", + "integrity": "sha512-RWSWtCFVObRmCwgxVOye3lsYbPHTnB7G4He5LEAg2tf600Sil5yXEOL/ULx1TqL/XOQxKqRvmLn/rLQOMT85YA==", + "license": "MIT", + "dependencies": { + "@oclif/core": "^4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@oclif/plugin-not-found": { + "version": "3.2.47", + "resolved": "https://registry.npmjs.org/@oclif/plugin-not-found/-/plugin-not-found-3.2.47.tgz", + "integrity": "sha512-7Zk10TQhPOd5kkS4wiLDBqtR2MRM8FBiSrZDmSsgME1kXt4eYQLAFc9c5WJzkpglNb6g5/iD1LvbhTNd5oLe1g==", + "license": "MIT", + "dependencies": { + "@inquirer/prompts": "^7.3.3", + "@oclif/core": "^4", + "ansis": "^3.17.0", + "fast-levenshtein": "^3.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@raycast/api": { + "version": "1.94.0", + "resolved": "https://registry.npmjs.org/@raycast/api/-/api-1.94.0.tgz", + "integrity": "sha512-FnUZXiwO00mgFUqDL4Sv9VgCSv0sCqYerLSELFz7STYIsgglXnirHWR9rygx50/h9/3l0k2k/gicJaAX0x7iyw==", + "license": "MIT", + "dependencies": { + "@oclif/core": "^4.0.33", + "@oclif/plugin-autocomplete": "^3.2.10", + "@oclif/plugin-help": "^6.2.18", + "@oclif/plugin-not-found": "^3.2.28", + "@types/node": "22.13.10", + "@types/react": "19.0.10", + "esbuild": "^0.25.1", + "react": "19.0.0" + }, + "bin": { + "ray": "bin/run.js" + }, + "engines": { + "node": ">=22.14.0" + }, + "peerDependencies": { + "@types/node": "22.13.10", + "@types/react": "19.0.10", + "react-devtools": "6.1.1" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@types/react": { + "optional": true + }, + "react-devtools": { + "optional": true + } + } + }, + "node_modules/@raycast/eslint-config": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@raycast/eslint-config/-/eslint-config-2.0.4.tgz", + "integrity": "sha512-Sz5Q0HVY8pW21Sv7CDcJw882OGubSM3zx5uiDRQMkgt7Hui3I+IZOqxDInnhLsGG52prSdU7sg3R097hMJkkQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint/js": "^9.22.0", + "@raycast/eslint-plugin": "^2.0.4", + "eslint-config-prettier": "^10.1.1", + "globals": "^16.0.0", + "typescript-eslint": "^8.26.1" + }, + "peerDependencies": { + "eslint": ">=8.23.0", + "prettier": ">=2", + "typescript": ">=4" + } + }, + "node_modules/@raycast/eslint-plugin": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@raycast/eslint-plugin/-/eslint-plugin-2.0.4.tgz", + "integrity": "sha512-XrKppNp1sW4eoIErVgU/uStIIiwB3cesp+4hc4sK3PJGBGVz+8sO70+6pkqcOwqjeTv2COAeCFVVs6sdINsMHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^8.26.1" + }, + "peerDependencies": { + "eslint": ">=8.23.0" + } + }, + "node_modules/@raycast/utils": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/@raycast/utils/-/utils-1.19.1.tgz", + "integrity": "sha512-/udUGcTZCgZZwzesmjBkqG5naQZTD/ZLHbqRwkWcF+W97vf9tr9raxKyQjKsdZ17OVllw2T3sHBQsVUdEmCm2g==", + "license": "MIT", + "dependencies": { + "cross-fetch": "^3.1.6", + "dequal": "^2.0.3", + "object-hash": "^3.0.0", + "signal-exit": "^4.0.2", + "stream-chain": "^2.2.5", + "stream-json": "^1.8.0" + }, + "peerDependencies": { + "@raycast/api": ">=1.69.0" + } + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.13.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz", + "integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.20.0" + } + }, + "node_modules/@types/react": { + "version": "19.0.10", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.10.tgz", + "integrity": "sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g==", + "license": "MIT", + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.27.0.tgz", + "integrity": "sha512-4henw4zkePi5p252c8ncBLzLce52SEUz2Ebj8faDnuUXz2UuHEONYcJ+G0oaCF+bYCWVZtrGzq3FD7YXetmnSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.27.0", + "@typescript-eslint/type-utils": "8.27.0", + "@typescript-eslint/utils": "8.27.0", + "@typescript-eslint/visitor-keys": "8.27.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.0.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.27.0.tgz", + "integrity": "sha512-XGwIabPallYipmcOk45DpsBSgLC64A0yvdAkrwEzwZ2viqGqRUJ8eEYoPz0CWnutgAFbNMPdsGGvzjSmcWVlEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.27.0", + "@typescript-eslint/types": "8.27.0", + "@typescript-eslint/typescript-estree": "8.27.0", + "@typescript-eslint/visitor-keys": "8.27.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.27.0.tgz", + "integrity": "sha512-8oI9GwPMQmBryaaxG1tOZdxXVeMDte6NyJA4i7/TWa4fBwgnAXYlIQP+uYOeqAaLJ2JRxlG9CAyL+C+YE9Xknw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.27.0", + "@typescript-eslint/visitor-keys": "8.27.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.27.0.tgz", + "integrity": "sha512-wVArTVcz1oJOIEJxui/nRhV0TXzD/zMSOYi/ggCfNq78EIszddXcJb7r4RCp/oBrjt8n9A0BSxRMKxHftpDxDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.27.0", + "@typescript-eslint/utils": "8.27.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.0.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.27.0.tgz", + "integrity": "sha512-/6cp9yL72yUHAYq9g6DsAU+vVfvQmd1a8KyA81uvfDE21O2DwQ/qxlM4AR8TSdAu+kJLBDrEHKC5/W2/nxsY0A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.27.0.tgz", + "integrity": "sha512-BnKq8cqPVoMw71O38a1tEb6iebEgGA80icSxW7g+kndx0o6ot6696HjG7NdgfuAVmVEtwXUr3L8R9ZuVjoQL6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.27.0", + "@typescript-eslint/visitor-keys": "8.27.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.0.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.27.0.tgz", + "integrity": "sha512-njkodcwH1yvmo31YWgRHNb/x1Xhhq4/m81PhtvmRngD8iHPehxffz1SNCO+kwaePhATC+kOa/ggmvPoPza5i0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.27.0", + "@typescript-eslint/types": "8.27.0", + "@typescript-eslint/typescript-estree": "8.27.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.27.0.tgz", + "integrity": "sha512-WsXQwMkILJvffP6z4U3FYJPlbf/j07HIxmDjZpbNvBJkMfvwXj5ACRkkHwBDvLBbDbtX5TdU64/rcvKJ/vuInQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.27.0", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/acorn": { + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", + "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansis": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.17.0.tgz", + "integrity": "sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==", + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", + "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "license": "MIT" + }, + "node_modules/clean-stack": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-3.0.1.tgz", + "integrity": "sha512-lR9wNiMRcVQjSB3a7xXGLuz4cr4wJuuXlaAEbRutGowQTmlp7R72/DOgN21e8jdwblMWl9UOJMJXarX94pzKdg==", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "license": "ISC", + "engines": { + "node": ">= 12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" + }, + "node_modules/cross-fetch": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", + "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/date-fns": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.1.tgz", + "integrity": "sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.1", + "@esbuild/android-arm": "0.25.1", + "@esbuild/android-arm64": "0.25.1", + "@esbuild/android-x64": "0.25.1", + "@esbuild/darwin-arm64": "0.25.1", + "@esbuild/darwin-x64": "0.25.1", + "@esbuild/freebsd-arm64": "0.25.1", + "@esbuild/freebsd-x64": "0.25.1", + "@esbuild/linux-arm": "0.25.1", + "@esbuild/linux-arm64": "0.25.1", + "@esbuild/linux-ia32": "0.25.1", + "@esbuild/linux-loong64": "0.25.1", + "@esbuild/linux-mips64el": "0.25.1", + "@esbuild/linux-ppc64": "0.25.1", + "@esbuild/linux-riscv64": "0.25.1", + "@esbuild/linux-s390x": "0.25.1", + "@esbuild/linux-x64": "0.25.1", + "@esbuild/netbsd-arm64": "0.25.1", + "@esbuild/netbsd-x64": "0.25.1", + "@esbuild/openbsd-arm64": "0.25.1", + "@esbuild/openbsd-x64": "0.25.1", + "@esbuild/sunos-x64": "0.25.1", + "@esbuild/win32-arm64": "0.25.1", + "@esbuild/win32-ia32": "0.25.1", + "@esbuild/win32-x64": "0.25.1" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.22.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.22.0.tgz", + "integrity": "sha512-9V/QURhsRN40xuHXWjV64yvrzMjcz7ZyNoF2jJFmy9j/SLk0u1OLSZgXi28MrXjymnjEGSR80WCdab3RGMDveQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.19.2", + "@eslint/config-helpers": "^0.1.0", + "@eslint/core": "^0.12.0", + "@eslint/eslintrc": "^3.3.0", + "@eslint/js": "9.22.0", + "@eslint/plugin-kit": "^0.2.7", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.3.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-prettier": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.1.tgz", + "integrity": "sha512-4EQQr6wXwS+ZJSzaR5ZCrYgLxqvUjdXctaEtBqHcbkW944B1NQyO4qpdHQbXBONfwxXdkAY81HH4+LUfrg+zPw==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", + "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.14.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "license": "MIT", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-3.0.0.tgz", + "integrity": "sha512-hKKNajm46uNmTlhHSyZkmToAc56uZJwYq7yrciZjqOxnlfQwERDQJmHPUp7m1m9wx8vgOe8IaCKZ5Kv2k1DdCQ==", + "license": "MIT", + "dependencies": { + "fastest-levenshtein": "^1.0.7" + } + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", + "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.0.0.tgz", + "integrity": "sha512-iInW14XItCXET01CQFqudPOWP2jYMl7T+QRQT+UNcR/iQncN/F0UNpgd76iFkBPgNQb4+X3LV9tLJYzwh+Gl3A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jake": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", + "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jake/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jake/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/mute-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/optionator/node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", + "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/react": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz", + "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/stream-chain": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz", + "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==", + "license": "BSD-3-Clause" + }, + "node_modules/stream-json": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.9.1.tgz", + "integrity": "sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==", + "license": "BSD-3-Clause", + "dependencies": { + "stream-chain": "^2.2.5" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "license": "MIT", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", + "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.27.0.tgz", + "integrity": "sha512-ZZ/8+Y0rRUMuW1gJaPtLWe4ryHbsPLzzibk5Sq+IFa2aOH1Vo0gPr1fbA6pOnzBke7zC2Da4w8AyCgxKXo3lqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.27.0", + "@typescript-eslint/parser": "8.27.0", + "@typescript-eslint/utils": "8.27.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "license": "MIT" + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "license": "MIT", + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", + "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/extensions/akiflow/package.json b/extensions/akiflow/package.json new file mode 100644 index 00000000000..c638bcd5441 --- /dev/null +++ b/extensions/akiflow/package.json @@ -0,0 +1,787 @@ +{ + "$schema": "https://www.raycast.com/schemas/extension.json", + "name": "akiflow", + "title": "Akiflow", + "description": "Manages your tasks in Akiflow", + "icon": "akiflow-icon.png", + "author": "andyjsiegel", + "categories": [ + "Productivity" + ], + "license": "MIT", + "commands": [ + { + "name": "search-tasks", + "title": "Search Tasks", + "description": "Search and view your tasks in Akiflow", + "mode": "view", + "preferences": [ + { + "label": "Show Completed Tasks", + "name": "showCompletedTasks", + "description": "Whether or not to show completed (done) tasks", + "type": "checkbox", + "required": false, + "title": "Show Completed Tasks", + "default": false + }, + { + "label": "Whether to use flag icons for priority or !, !!, !!!, and a bullseye.", + "name": "useFlagsForPriority", + "description": "Whether to use flags for priority or !, !!, !!!, and a bullseye.", + "type": "dropdown", + "required": false, + "title": "Use Flags for Priority", + "data": [ + { + "title": "Use Flag Icons", + "value": "useFlags" + }, + { + "title": "Use !, !!, !!!, and Bullseye Icons", + "value": "useBullseye" + } + ] + } + ] + }, + { + "name": "add-task", + "title": "Add Task", + "description": "Adds a task to Akiflow. Supports name, description, plan date, due date (deadline), tags, projects, and priority", + "mode": "view", + "preferences": [ + { + "name": "taskAddedAction", + "description": "Determine what to do when a task is added successfully", + "type": "dropdown", + "required": true, + "title": "Action When Task Added", + "data": [ + { + "title": "Do Nothing (Keep Raycast Open)", + "value": "doNothing" + }, + { + "title": "Pop To Root", + "value": "popToRoot" + }, + { + "title": "Close Raycast Window", + "value": "closeRaycastWindow" + }, + { + "title": "Open Akiflow (Also closes Raycast Window)", + "value": "openAkiflow" + }, + { + "title": "View The Task In Akiflow", + "value": "viewTaskInAkiflow" + } + ] + } + ] + } + , + { + "name": "view-projects-and-tags", + "title": "View Projects and Tags", + "description": "View Your Akiflow Folders, Projects, and Tags", + "mode": "view" + } + , + { + "name": "menu-bar-tasks", + "title": "Menu Bar Tasks", + "description": "See Your Tasks In The Menu Bar", + "mode": "menu-bar", + "preferences": [ + { + "label": "Command Shortcut", + "name": "commandShortcut", + "description": "The shortcut to use for the command", + "type": "dropdown", + "required": false, + "title": "Command Shortcut", + "default": "cmdShiftY", + "data": [ + { + "title": "⌘Y", + "value": "cmdY" + }, + { + "title": "⌘⇧Y", + "value": "cmdShiftY" + }, + { + "title": "⌘⌥Y", + "value": "cmdOptionY" + }, + { + "title": "⌘⌥⇧Y", + "value": "cmdOptionShiftY" + } + ] + }, + { + "label": "Show Inbox Tasks", + "name": "showInboxTasks", + "description": "Whether or not to show inbox tasks in the menu bar", + "type": "checkbox", + "required": false, + "title": "Show Inbox Tasks", + "default": true + }, + { + "label": "Show Today Tasks", + "name": "showTodayTasks", + "description": "Whether or not to show today tasks in the menu bar", + "type": "checkbox", + "required": false, + "title": "Show Today Tasks", + "default": true + }, + { + "label": "Show Completed Tasks", + "name": "showCompletedTasks", + "description": "Whether or not to show completed (done) tasks in the menu bar", + "type": "checkbox", + "required": false, + "title": "Show Completed Tasks", + "default": false + } + ] + } + , + { + "name": "quick-access", + "title": "Quick Access", + "description": "Quickly Access Upcoming, Daily Planning, Daily Shutdown, Weekly Planning, and Weekly Shutdown", + "mode": "view" + } + ], + "ai": { + "instructions": "When the user asks for a relative time like 'today', 'in 1 hour', 'tomorrow', or 'Monday at 9am', call the get-current-time tool. If the user asks you to get tasks, call get tasks first. If the criteria is specific, but you don't know what to do, call both get-projects and get-tags. Then call get-tasks.", + "evals": [ + { + "input" : "@akiflow what are my inbox tasks?", + "mocks" : { + "get-tasks" : [ + { + "activation_datetime" : null, + "akiflow_account_id" : "51d94e7d-4b03-471b-83b9-4c2da8b8219c", + "calendar_id" : null, + "connector_id" : "notion", + "content" : { + "aiListId" : "e05470e6-fd04-4a12-ba1c-704bde7bcace", + "aiListIdPredictedAt" : 1736961106581, + "aiMethod" : 6, + "eventLockInCalendar" : "public" + }, + "created_at" : "2025-01-15T17:11:46.678Z", + "dailyGoal" : 0, + "date" : null, + "datetime" : null, + "datetime_tz" : "America/Phoenix", + "deleted_at" : null, + "description" : null, + "doc" : { + "created_at" : "2025-01-15T17:05:00Z", + "hash" : "e22f223ead6fef9c1245775fba8de14c", + "local_url" : "notion:/Final-Project-65ed87e418f4456cb561b6100687a540", + "updated_at" : "2025-01-15T17:06:00Z", + "url" : "https://www.notion.so/Final-Project-65ed87e418f4456cb561b6100687a540", + "workspace_id" : "1106b520-933e-80bd-be59-e1129000f31c", + "workspace_name" : "Tasks" + }, + "done" : false, + "done_at" : null, + "due_date" : "2025-04-25", + "duration" : 0, + "global_created_at" : "2025-01-15T17:11:47.689Z", + "global_list_id_updated_at" : "2025-04-06T21:14:41.458Z", + "global_tags_ids_updated_at" : "2025-04-12T18:15:42.592Z", + "global_updated_at" : "2025-04-12T18:15:42.592Z", + "id" : "88fb29cb-7ffc-4e9b-a2a8-618b7d2bb4b0", + "links" : null, + "listId" : "1b416fc3-9bc9-4d0a-83fa-ee0b464f1a77", + "origin" : null, + "origin_account_id" : "6bb780e5-31af-494b-9cef-b56b225b1d42-10ed872b-594c-81e6-a90b-0002f6d646d9", + "origin_id" : "65ed87e4-18f4-456c-b561-b6100687a540", + "original_date" : null, + "original_datetime" : null, + "plan_period" : null, + "plan_unit" : null, + "priority" : 1, + "read_at" : "2025-04-07T16:33:21.000Z", + "recurrence" : null, + "recurrence_version" : null, + "recurring_calendar_lock" : false, + "recurring_id" : null, + "section_id" : null, + "sorting" : 1744171117919, + "sorting_label" : null, + "status" : 1, + "tags_ids" : [ + "4d4fd80f-1627-44d6-9f80-ed4e161e29e5" + ], + "temp_permanently_deleted" : null, + "time_slot_id" : null, + "title" : "Final Project", + "trashed_at" : null, + "unique_id" : null, + "until_datetime" : null, + "updated_at" : "2025-04-12T18:15:42.905Z", + "user_id" : 91432 + } + ] + }, + "expected" : [ + { + "callsTool" : { + "arguments" : { + "done" : false, + "status" : 1 + }, + "name" : "get-tasks" + } + } + ] + }, + { + "input" : "@akiflow list my tasks for today", + "mocks" : { + "get-tasks" : [ + { + "activation_datetime" : null, + "akiflow_account_id" : "51d94e7d-4b03-471b-83b9-4c2da8b8219c", + "calendar_id" : null, + "connector_id" : "notion", + "content" : { + "aiListId" : "e05470e6-fd04-4a12-ba1c-704bde7bcace", + "aiListIdPredictedAt" : 1736962012745, + "aiMethod" : 6 + }, + "created_at" : "2025-01-15T17:26:53.061Z", + "dailyGoal" : 0, + "date" : "2025-04-14", + "datetime" : null, + "datetime_tz" : "America/Phoenix", + "deleted_at" : null, + "description" : "<p><br></p>", + "doc" : { + "created_at" : "2025-01-15T17:20:00Z", + "hash" : "a6188f408e3b51a631e58aeb9d6d795c", + "local_url" : "notion:/Simulation-Project-5-17c6b520933e80dd982bc4335ca6bf8c", + "updated_at" : "2025-04-14T13:00:00Z", + "url" : "https://www.notion.so/Simulation-Project-5-17c6b520933e80dd982bc4335ca6bf8c", + "workspace_id" : "1106b520-933e-80bd-be59-e1129000f31c", + "workspace_name" : "Tasks" + }, + "done" : false, + "done_at" : null, + "due_date" : "2025-04-16", + "duration" : 0, + "global_created_at" : "2025-01-15T17:28:01.675Z", + "global_list_id_updated_at" : "2025-04-11T19:27:37.122Z", + "global_tags_ids_updated_at" : "2025-04-13T06:32:32.356Z", + "global_updated_at" : "2025-04-14T16:49:17.604Z", + "id" : "5c459d4a-5e8d-45bd-b5ce-8ef8250ff056", + "links" : null, + "listId" : "0461e1f6-78e3-449b-8f06-04e4646e53e3", + "origin" : null, + "origin_account_id" : "6bb780e5-31af-494b-9cef-b56b225b1d42-10ed872b-594c-81e6-a90b-0002f6d646d9", + "origin_id" : "17c6b520-933e-80dd-982b-c4335ca6bf8c", + "original_date" : null, + "original_datetime" : null, + "plan_period" : null, + "plan_unit" : null, + "priority" : 2, + "read_at" : "2025-01-15T17:28:17.000Z", + "recurrence" : null, + "recurrence_version" : null, + "recurring_calendar_lock" : false, + "recurring_id" : null, + "section_id" : null, + "sorting" : 1744635997723, + "sorting_label" : 1737059981436, + "status" : 2, + "tags_ids" : [ + "4d4fd80f-1627-44d6-9f80-ed4e161e29e5" + ], + "temp_permanently_deleted" : null, + "time_slot_id" : null, + "title" : "Simulation Project 5", + "trashed_at" : null, + "unique_id" : null, + "until_datetime" : null, + "updated_at" : "2025-04-14T16:49:19.579Z", + "user_id" : 91432 + }, + { + "activation_datetime" : null, + "akiflow_account_id" : null, + "calendar_id" : null, + "connector_id" : "gmail", + "content" : { + "aiListId" : "0461e1f6-78e3-449b-8f06-04e4646e53e3", + "aiListIdPredictedAt" : 1744314499128, + "aiMethod" : 6 + }, + "created_at" : "2025-04-10T19:43:51.988Z", + "dailyGoal" : 1, + "date" : "2025-04-14", + "datetime" : null, + "datetime_tz" : "America/Phoenix", + "deleted_at" : null, + "description" : "Task was planned for the last Saturday, Apr 12, 2025", + "doc" : { + "from" : "lotz@d2l.arizona.edu", + "hash" : "8cf2fa52fe0c4259ed4d42d6eceb9952", + "internal_date" : "1744059248000", + "message_id" : "196120c86b8f90be", + "subject" : "CSC 335 SP25 001 - Midterm 2", + "thread_id" : "196120c86b8f90be", + "url" : "https://mail.google.com/mail/u/siegela1@arizona.edu/#all/196120c86b8f90be" + }, + "done" : false, + "done_at" : null, + "due_date" : null, + "duration" : 3600, + "global_created_at" : "2025-04-10T19:46:15.893Z", + "global_list_id_updated_at" : "2025-04-10T19:48:32.226Z", + "global_tags_ids_updated_at" : "2025-04-10T19:48:28.074Z", + "global_updated_at" : "2025-04-14T16:49:17.603Z", + "id" : "a6629d15-d102-4c73-abf6-cf82142562fb", + "links" : null, + "listId" : "1b416fc3-9bc9-4d0a-83fa-ee0b464f1a77", + "origin" : null, + "origin_account_id" : "102805524244536684760", + "origin_id" : "196120c86b8f90be", + "original_date" : null, + "original_datetime" : null, + "plan_period" : null, + "plan_unit" : null, + "priority" : -1, + "read_at" : "2025-04-10T19:46:18.000Z", + "recurrence" : null, + "recurrence_version" : null, + "recurring_calendar_lock" : false, + "recurring_id" : null, + "section_id" : null, + "sorting" : 1744314231988, + "sorting_label" : null, + "status" : 2, + "tags_ids" : [ + "4d4fd80f-1627-44d6-9f80-ed4e161e29e5" + ], + "temp_permanently_deleted" : null, + "time_slot_id" : null, + "title" : "Study For Midterm 2", + "trashed_at" : null, + "unique_id" : null, + "until_datetime" : null, + "updated_at" : "2025-04-14T16:49:19.597Z", + "user_id" : 91432 + }, + { + "activation_datetime" : null, + "akiflow_account_id" : null, + "calendar_id" : null, + "connector_id" : null, + "content" : { + "aiListId" : "6b3ad0e2-12c8-46bf-941f-2cf2ef201694", + "aiListIdPredictedAt" : 1744397242418, + "aiMethod" : 6 + }, + "created_at" : "2025-04-11T18:46:54.650Z", + "dailyGoal" : 0, + "date" : "2025-04-14", + "datetime" : null, + "datetime_tz" : "America/Phoenix", + "deleted_at" : null, + "description" : "<p>Look out for emails from <a href=\"http://contactcwt.com\">statefarm.us@contactcwt.com</a> to book onboarding travel. Respond within 24 hours.</p>", + "doc" : null, + "done" : false, + "done_at" : null, + "due_date" : null, + "duration" : 0, + "global_created_at" : "2025-04-11T18:46:55.420Z", + "global_list_id_updated_at" : "2025-04-11T18:47:24.043Z", + "global_tags_ids_updated_at" : null, + "global_updated_at" : "2025-04-14T22:01:46.606Z", + "id" : "f82a2779-9b7d-4d9e-bd10-f3e9076f716d", + "links" : null, + "listId" : "6b3ad0e2-12c8-46bf-941f-2cf2ef201694", + "origin" : null, + "origin_account_id" : null, + "origin_id" : null, + "original_date" : null, + "original_datetime" : null, + "plan_period" : null, + "plan_unit" : null, + "priority" : 1, + "read_at" : null, + "recurrence" : null, + "recurrence_version" : null, + "recurring_calendar_lock" : false, + "recurring_id" : null, + "section_id" : null, + "sorting" : 1744397214649, + "sorting_label" : null, + "status" : 2, + "tags_ids" : null, + "temp_permanently_deleted" : null, + "time_slot_id" : null, + "title" : "Check for onboarding travel email from State Farm", + "trashed_at" : null, + "unique_id" : null, + "until_datetime" : null, + "updated_at" : "2025-04-14T22:01:46.980Z", + "user_id" : 91432 + } + ] + }, + "expected" : [ + { + "callsTool" : { + "arguments" : { + "date" : "2025-04-14", + "done" : false + }, + "name" : "get-tasks" + } + }, + { + "callsTool" : { + "arguments" : {}, + "name" : "get-current-time" + } + } + ] + }, + { + "input" : "@akiflow list my tasks for csc 345.", + "mocks" : { + "get-projects" : { + "1b416fc3-9bc9-4d0a-83fa-ee0b464f1a77" : { + "color" : "#FFA500", + "icon" : "📦", + "parentId" : "7c619db3-50e8-486f-b292-a7bae846a58b", + "title" : "CSC 335" + }, + "3c0a8019-647a-43dd-8354-b2f8ac553f72" : { + "color" : "#5F1C3A", + "icon" : "🧠", + "parentId" : "73926504-55ab-40cd-85d8-73e541e05d8e", + "title" : "Admin" + }, + "6b3ad0e2-12c8-46bf-941f-2cf2ef201694" : { + "color" : "#FFC0CB", + "icon" : "🚗", + "parentId" : "7ae0a871-a58e-4001-87e3-5f87ca58608e", + "title" : "StateFarm" + }, + "7ae0a871-a58e-4001-87e3-5f87ca58608e" : { + "icon" : null, + "parentId" : null, + "title" : "Professional" + }, + "7c619db3-50e8-486f-b292-a7bae846a58b" : { + "icon" : null, + "parentId" : null, + "title" : "University" + }, + "46e5659d-c1b1-4519-9174-55999a2f0f8b" : { + "color" : "#800080", + "icon" : "📆", + "parentId" : "7c619db3-50e8-486f-b292-a7bae846a58b", + "title" : "Planning" + }, + "0461e1f6-78e3-449b-8f06-04e4646e53e3" : { + "color" : "#A52A2A", + "icon" : "📁", + "parentId" : "7c619db3-50e8-486f-b292-a7bae846a58b", + "title" : "CSC 252" + }, + "424838be-4496-4e13-9c22-8f072c827bac" : { + "color" : "#00FFFF", + "icon" : "🧩", + "parentId" : "7c619db3-50e8-486f-b292-a7bae846a58b", + "title" : "CSC 345" + }, + "73926504-55ab-40cd-85d8-73e541e05d8e" : { + "icon" : null, + "parentId" : null, + "title" : "Personal" + }, + "b761f21d-45fe-41cd-846a-ecbe93ec8e09" : { + "color" : "#FF0000", + "icon" : "🎮", + "parentId" : "7ae0a871-a58e-4001-87e3-5f87ca58608e", + "title" : "eSports Arena" + }, + "efb628e7-0d81-4a00-b351-d80426152e89" : { + "color" : "#FF0000", + "icon" : "🧺", + "parentId" : "73926504-55ab-40cd-85d8-73e541e05d8e", + "title" : "Chores" + }, + "f0976dff-028f-4531-9cc6-e2719a83b94f" : { + "color" : "#31BF75", + "icon" : "🧪", + "parentId" : "7c619db3-50e8-486f-b292-a7bae846a58b", + "title" : "CHEM 151" + } + }, + "get-tags" : { + "In Progress" : "4d4fd80f-1627-44d6-9f80-ed4e161e29e5" + } + }, + "expected" : [ + { + "callsTool" : { + "arguments" : { + + }, + "name" : "get-projects" + } + }, + { + "callsTool" : { + "arguments" : { + + }, + "name" : "get-tags" + } + }, + { + "callsTool" : { + "arguments" : { + "listId" : "424838be-4496-4e13-9c22-8f072c827bac" + }, + "name" : "get-tasks" + } + }, + { + "callsTool" : { + "arguments" : { + "done" : false, + "listId" : "424838be-4496-4e13-9c22-8f072c827bac" + }, + "name" : "get-tasks" + } + } + ] + }, + { + "input" : "@akiflow Can you rename my task \"Put Laundry Away\" to \"Put Laundry In Dresser\"", + "mocks" : { + "edit-task" : { + "data" : [ + { + "activation_datetime" : null, + "akiflow_account_id" : null, + "calendar_id" : null, + "connector_id" : null, + "content" : { + "aiListId" : "efb628e7-0d81-4a00-b351-d80426152e89", + "aiListIdPredictedAt" : 1744906504446, + "aiMethod" : 6000029 + }, + "created_at" : "2025-04-17T16:15:04.472Z", + "dailyGoal" : 0, + "date" : "2025-04-17", + "datetime" : "2025-04-18T02:00:00.000Z", + "datetime_tz" : "America/Phoenix", + "deleted_at" : null, + "description" : null, + "doc" : null, + "done" : false, + "done_at" : null, + "due_date" : null, + "duration" : 1800, + "global_created_at" : "2025-04-17T16:15:04.177Z", + "global_list_id_updated_at" : "2025-04-17T16:15:04.446Z", + "global_tags_ids_updated_at" : null, + "global_updated_at" : "2025-04-17T23:15:02.255Z", + "id" : "e81158ea-13e5-4985-995b-47aaeb77b3e4", + "links" : null, + "listId" : "efb628e7-0d81-4a00-b351-d80426152e89", + "origin" : null, + "origin_account_id" : null, + "origin_id" : null, + "original_date" : null, + "original_datetime" : null, + "plan_period" : null, + "plan_unit" : null, + "priority" : 3, + "read_at" : "2025-04-17T16:15:04.000Z", + "recurrence" : null, + "recurrence_version" : null, + "recurring_calendar_lock" : false, + "recurring_id" : null, + "section_id" : null, + "sorting" : 1744906504177, + "sorting_label" : 1744906504177, + "status" : 2, + "tags_ids" : null, + "temp_permanently_deleted" : null, + "time_slot_id" : null, + "title" : "Put Laundry In Dresser", + "trashed_at" : null, + "unique_id" : null, + "until_datetime" : null, + "updated_at" : "2025-04-17T23:15:02.255Z", + "user_id" : 91432 + } + ] + }, + "get-tasks" : [ + { + "activation_datetime" : null, + "akiflow_account_id" : null, + "calendar_id" : "5caaf18a-d654-4ffb-b3da-06e9ffeec74c", + "connector_id" : null, + "content" : { + "aiListId" : "efb628e7-0d81-4a00-b351-d80426152e89", + "aiListIdPredictedAt" : 1744906504446, + "aiMethod" : 6000029 + }, + "created_at" : "2025-04-17T16:15:04.472Z", + "dailyGoal" : 0, + "date" : "2025-04-17", + "datetime" : "2025-04-18T02:00:00.000Z", + "datetime_tz" : "America/Phoenix", + "deleted_at" : null, + "description" : null, + "doc" : null, + "done" : false, + "done_at" : null, + "due_date" : null, + "duration" : 1800, + "global_created_at" : "2025-04-17T16:15:04.177Z", + "global_list_id_updated_at" : "2025-04-17T16:15:04.446Z", + "global_tags_ids_updated_at" : null, + "global_updated_at" : "2025-04-17T16:28:47.592Z", + "id" : "e81158ea-13e5-4985-995b-47aaeb77b3e4", + "links" : null, + "listId" : "efb628e7-0d81-4a00-b351-d80426152e89", + "origin" : null, + "origin_account_id" : null, + "origin_id" : null, + "original_date" : null, + "original_datetime" : null, + "plan_period" : null, + "plan_unit" : null, + "priority" : 3, + "read_at" : "2025-04-17T16:15:04.000Z", + "recurrence" : null, + "recurrence_version" : null, + "recurring_calendar_lock" : false, + "recurring_id" : null, + "section_id" : null, + "sorting" : 1744906504177, + "sorting_label" : 1744906504177, + "status" : 2, + "tags_ids" : null, + "temp_permanently_deleted" : null, + "time_slot_id" : null, + "title" : "Put Laundry Away", + "trashed_at" : null, + "unique_id" : null, + "until_datetime" : null, + "updated_at" : "2025-04-17T16:28:49.541Z", + "user_id" : 91432 + } + ] + }, + "expected" : [ + { + "callsTool" : { + "arguments" : { + "done" : false, + "title" : "Put Laundry Away" + }, + "name" : "get-tasks" + } + }, + { + "callsTool" : { + "arguments" : { + "id" : "e81158ea-13e5-4985-995b-47aaeb77b3e4", + "title" : "Put Laundry In Dresser" + }, + "name" : "edit-task" + } + } + ] + } + ] + }, + "tools": [ + { + "name": "add-task", + "title": "Add Task", + "description": "Adds a task to Akiflow" + }, + { + "name": "get-projects", + "title": "Get Projects", + "description": "Gets the user's projects from Akiflow" + }, + { + "name": "get-tags", + "title": "Get Tags", + "description": "Gets the user's tags from Akiflow" + }, + { + "name": "get-current-time", + "title": "Get Current Time", + "description": "Gets the current time" + }, + { + "name": "get-tasks", + "title": "Get Tasks", + "description": "Gets the user's tasks." + } + , + { + "name": "edit-task", + "title": "Edit Task", + "description": "Edits a task in Akiflow given its ID. Shows confirmation when properties are other than 'done' are changed." + } + ], + "preferences": [ + { + "name": "refreshToken", + "description": "Akiflow Refresh Token", + "type": "password", + "required": true, + "title": "Akiflow Refresh Token", + "placeholder": "Click 'About' for info on how to get your refresh token." + } + ], + "dependencies": { + "@raycast/api": "^1.94.0", + "@raycast/utils": "^1.17.0", + "axios": "^1.8.4", + "date-fns": "^4.1.0" + }, + "devDependencies": { + "@raycast/eslint-config": "^2.0.4", + "@types/node": "22.13.10", + "@types/react": "19.0.10", + "eslint": "^9.22.0", + "prettier": "^3.5.3", + "typescript": "^5.8.2" + }, + "scripts": { + "build": "ray build", + "dev": "ray develop", + "fix-lint": "ray lint --fix", + "lint": "ray lint", + "prepublishOnly": "echo \"\\n\\nIt seems like you are trying to publish the Raycast extension to npm.\\n\\nIf you did intend to publish it to npm, remove the \\`prepublishOnly\\` script and rerun \\`npm publish\\` again.\\nIf you wanted to publish it to the Raycast Store instead, use \\`npm run publish\\` instead.\\n\\n\" && exit 1", + "publish": "npx @raycast/api@latest publish" + } +} diff --git a/extensions/akiflow/src/add-task.tsx b/extensions/akiflow/src/add-task.tsx new file mode 100644 index 00000000000..e74097857d5 --- /dev/null +++ b/extensions/akiflow/src/add-task.tsx @@ -0,0 +1,189 @@ +import { + Form, + ActionPanel, + Action, + showToast, + getPreferenceValues, + Icon, + Toast, + closeMainWindow, + popToRoot, + PopToRootType, +} from "@raycast/api"; +import { Akiflow, openAkiflow, viewTaskInAkiflow } from "../utils/akiflow"; +import { useEffect, useState } from "react"; + +interface Task { + title: string; + description?: string; + id?: string; + date?: string; + datetime?: string; + duration?: number; + priority?: number; + listId?: string; + done?: boolean; + status?: number; + due_date?: string; + tags_ids?: string[]; +} + +interface Project { + title: string; + color: string; + icon: string; + parentId: string | null; +} + +const taskAddedAction = getPreferenceValues<Preferences.AddTask>().taskAddedAction; +type NullaryFunction = () => void; +type TaskFunction = NullaryFunction | ((taskName?: string) => void); +const taskAddedFunctions: Record<string, TaskFunction> = { + doNothing: () => {}, + popToRoot: () => { + popToRoot(); + }, + closeRaycastWindow: () => closeMainWindow({ popToRootType: PopToRootType.Immediate }), + openAkiflow: () => { + openAkiflow(); + }, + viewTaskInAkiflow: (taskName?: string) => { + viewTaskInAkiflow(taskName!); + }, +}; + +export default function Command() { + const [projects, setProjects] = useState<{ [key: string]: Project }>({}); + const [tags, setTags] = useState<{ [key: string]: string }>({}); + const refreshToken = getPreferenceValues<Preferences>().refreshToken; + + useEffect(() => { + const akiflow = new Akiflow(refreshToken); + + const fetchProjectsAndTags = async () => { + try { + await akiflow.projectsPromise; // Wait for the projects to be fetched + setProjects(akiflow.projects); // Set the projects state + await akiflow.refreshTags(); // Fetch tags + setTags(akiflow.tags); // Set the tags state + } catch (error) { + console.error("Error fetching projects or tags:", error); + showToast({ title: "Error", message: "Failed to fetch projects or tags" }); + } + }; + + fetchProjectsAndTags(); + }, [refreshToken]); + + async function addTaskWithAuthorization(taskValues: Task) { + const akiflow = new Akiflow(refreshToken); + console.log(taskValues); + const task: Task = { + title: taskValues.title, + }; + + if (taskValues.description) { + task.description = taskValues.description; + } + if (taskValues.date) { + task.status = 2; + const date = new Date(taskValues.date ? taskValues.date : ""); + if (Form.DatePicker.isFullDay(date)) { + task.date = date.toISOString().split("T")[0]; + } else { + task.datetime = date.toISOString(); + task.date = date.toISOString().split("T")[0]; + } + } + if (task.status !== 2) { + task.status = 1; + } + if (taskValues.due_date) { + task.due_date = new Date(taskValues.due_date).toISOString().split("T")[0]; + } + if (taskValues.priority !== 99) { + task.priority = Number(taskValues.priority); + } + if (taskValues.tags_ids) { + task.tags_ids = taskValues.tags_ids; // Add selected tags to the task + } + if (taskValues.listId) { + task.listId = taskValues.listId; + } + + try { + showToast({ title: "Adding task...", style: Toast.Style.Animated }); + await akiflow.addSingleTask(task); + console.log("Task added successfully"); + taskAddedFunctions[taskAddedAction](); + showToast({ title: "Task added successfully", style: Toast.Style.Success }); + } catch (error) { + const errorMessage = (error as Error).message; + showToast({ title: "Error adding task", message: errorMessage, style: Toast.Style.Failure }); + console.error("Error adding task:", error); + } + } + + function handleSubmit(taskValues: Task) { + addTaskWithAuthorization(taskValues); + } + + return ( + <Form + actions={ + <ActionPanel> + <Action.SubmitForm onSubmit={handleSubmit} /> + </ActionPanel> + } + > + <Form.TextField id="title" title="Task Title" placeholder="Enter task title" /> + <Form.TextArea id="description" title="Task Description" placeholder="Enter task description" /> + <Form.Separator /> + <Form.DatePicker id="date" title="Date (and time)" /> + <Form.DatePicker type={Form.DatePicker.Type.Date} id="due_date" title="Deadline" /> + <Form.Separator /> + <Form.Dropdown id="priority" title="Priority"> + <Form.Dropdown.Item value="99" title="None" icon={Icon.Flag} /> + <Form.Dropdown.Item + value="-1" + title="Goal" + icon={{ source: Icon.Flag, tintColor: { light: "#D46397", dark: "#D46397" } }} + /> + <Form.Dropdown.Item + value="1" + title="High" + icon={{ source: Icon.Flag, tintColor: { light: "#EA3737", dark: "#EA3737" } }} + /> + <Form.Dropdown.Item + value="2" + title="Medium" + icon={{ source: Icon.Flag, tintColor: { light: "#FFA500", dark: "#FFA500" } }} + /> + <Form.Dropdown.Item + value="3" + title="Low" + icon={{ source: Icon.Flag, tintColor: { light: "#31BF75", dark: "#31BF75" } }} + /> + </Form.Dropdown> + {Object.entries(tags).length > 0 ? ( + <Form.TagPicker id="tags_ids" title="Select Tags"> + {Object.entries(tags).map(([name, id]) => ( + <Form.TagPicker.Item key={id} value={id} title={name} icon={Icon.Tag} /> + ))} + </Form.TagPicker> + ) : ( + "" + )} + {Object.entries(projects).length > 0 ? ( + <Form.Dropdown id="listId" title="Select Project"> + <Form.Dropdown.Item key="noproject" value="" title="No Project" /> + {Object.entries(projects).map(([id, { title, icon, parentId }]) => + parentId ? <Form.Dropdown.Item key={id} value={id} title={title} icon={icon} /> : "", + )} + </Form.Dropdown> + ) : ( + "" + )} + </Form> + ); +} diff --git a/extensions/akiflow/src/menu-bar-tasks.tsx b/extensions/akiflow/src/menu-bar-tasks.tsx new file mode 100644 index 00000000000..e01bba8d9b7 --- /dev/null +++ b/extensions/akiflow/src/menu-bar-tasks.tsx @@ -0,0 +1,132 @@ +import { useEffect, useState } from "react"; +import { getPreferenceValues, Icon, MenuBarExtra } from "@raycast/api"; +import { useCachedState } from "@raycast/utils"; +import { Akiflow, viewTaskInAkiflow } from "../utils/akiflow"; + +interface Task { + id: string; + title: string; + description: string | null; + date: string | null; + datetime: string | null; + duration: number; + priority: number; + listId: string | null; + done: boolean; + status: number; + due_date: string | null; + tagsIds: string[] | null; + deleted_at?: string | null; + trashed_at?: string | null; + recurrence: string | null; + recurring_id: string | null; +} + +interface ReturnedTasks { + data: Task[]; +} + +function TaskMenuItemsSection({ + title, + tasks, + projects, +}: { + title: string; + tasks: Task[]; + projects: { [key: string]: { title: string } }; +}) { + return ( + <MenuBarExtra.Section title={title}> + {tasks.map((task) => ( + <MenuBarExtra.Item + key={task.id} + title={task.title} + subtitle={task.listId ? projects[task.listId].title : ""} + icon={task.done ? Icon.Checkmark : Icon.Circle} + onAction={() => { + viewTaskInAkiflow(task.title); + }} + /> + ))} + </MenuBarExtra.Section> + ); +} + +export default function Command() { + const [tasks, setTasks] = useState<ReturnedTasks>({ data: [] }); + const [projects, setProjects] = useCachedState<{ + [key: string]: { title: string; color: string; parentId: string | null; icon: string }; + }>("projects", {}); + // const [tags, setTags] = useCachedState<{ [key: string]: string }>("tags", {}); + const [isLoading, setIsLoading] = useState<boolean>(true); // Loading state + + useEffect(() => { + const akiflow = new Akiflow(getPreferenceValues<Preferences>().refreshToken); + const fetchTasks = async () => { + try { + const fetchedTasks = await akiflow.getTasks(); + setTasks(fetchedTasks); // Set tasks using useState + } catch (error) { + console.error("Error fetching tasks:", error); + } finally { + setIsLoading(false); // Set loading to false after fetching + } + }; + fetchTasks(); + }, []); // Empty dependency array to run only once on mount + + useEffect(() => { + const akiflow = new Akiflow(getPreferenceValues<Preferences>().refreshToken); + + const fetchProjectsAndTags = async () => { + try { + await akiflow.projectsPromise; // Wait for the projects to be fetched + setProjects(akiflow.projects); // Set the projects state + // Menu bar tasks doesn't use tags actually so its commented out + // await akiflow.refreshTags(); // Fetch tags + // setTags(akiflow.tags); // Set the tags state + } catch (error) { + console.error("Error fetching projects or tags", error); + } finally { + setIsLoading(false); + } + }; + + fetchProjectsAndTags(); + }, []); + + const notDeletedTasks = tasks.data.filter((task: Task) => task.deleted_at === null && task.trashed_at === null); + const notRecurringTasks = notDeletedTasks.filter((task) => task.recurrence === null && task.recurring_id === null); + const notWeirdBrokenTasks = notRecurringTasks.filter((task) => [1, 2, 4, 7].includes(task.status)); + + notWeirdBrokenTasks.sort((a, b) => { + const dateA = a.date + ? new Date(a.date) + : a.datetime + ? new Date(a.datetime) + : a.due_date + ? new Date(a.due_date) + : new Date(Infinity); // Far future date + + const dateB = b.date + ? new Date(b.date) + : b.datetime + ? new Date(b.datetime) + : b.due_date + ? new Date(b.due_date) + : new Date(Infinity); // Far future date + + return dateA.getTime() - dateB.getTime(); // Ascending order + }); + + const inboxTasks = notWeirdBrokenTasks.filter((task) => task.status === 1 && task.done === false); + const date = new Date(); + const formattedDate = date.toLocaleDateString("en-CA"); // 'en-CA' is for Canadian English which uses YYYY-MM-DD format + const todayTasks = notWeirdBrokenTasks.filter((task) => task.status === 2 && formattedDate === task.date); + return ( + <MenuBarExtra icon={{ source: Icon.CheckList }} isLoading={isLoading}> + <TaskMenuItemsSection title="Inbox Tasks" tasks={inboxTasks} projects={projects} /> + <TaskMenuItemsSection title="Today's Tasks" tasks={todayTasks} projects={projects} /> + </MenuBarExtra> + ); +} diff --git a/extensions/akiflow/src/quick-access.tsx b/extensions/akiflow/src/quick-access.tsx new file mode 100644 index 00000000000..410a25546dc --- /dev/null +++ b/extensions/akiflow/src/quick-access.tsx @@ -0,0 +1,43 @@ +import { ActionPanel, Action, Icon, List } from "@raycast/api"; +import { openInAkiflow } from "../utils/akiflow"; + +interface Quicklink { + title: string; + icon: Icon; +} + +// const quicklinks: Quicklink[] = ["Upcoming", "Daily Planning", "Weekly Planning", "Daily Shutdown", "Weekly Shutdown"]; +const quicklinks: Quicklink[] = [ + { title: "Upcoming", icon: Icon.Calendar }, + { title: "Daily Planning", icon: Icon.Sunrise }, + { title: "Weekly Planning", icon: Icon.Sun }, + { title: "Daily Shutdown", icon: Icon.Moonrise }, + { title: "Weekly Shutdown", icon: Icon.Moon }, + { title: "Settings", icon: Icon.Gear }, + { title: "Statistics", icon: Icon.PieChart }, +]; + +export default function QuickAccess() { + return ( + <List> + {quicklinks.map((quicklink) => ( + <List.Item + key={quicklink.title} + title={quicklink.title} + subtitle={`Open The ${quicklink.title} Page In Akiflow`} + icon={quicklink.icon} + actions={ + <ActionPanel> + <Action + title={`Open ${quicklink.title} in Akiflow`} + onAction={() => { + openInAkiflow(quicklink.title); + }} + /> + </ActionPanel> + } + /> + ))} + </List> + ); +} diff --git a/extensions/akiflow/src/search-tasks.tsx b/extensions/akiflow/src/search-tasks.tsx new file mode 100644 index 00000000000..a9c3b6c9cf7 --- /dev/null +++ b/extensions/akiflow/src/search-tasks.tsx @@ -0,0 +1,269 @@ +import { ActionPanel, Action, Icon, List, getPreferenceValues, Color, showToast, Toast } from "@raycast/api"; +import { Akiflow, viewTaskInAkiflow } from "../utils/akiflow"; +import { useState, useEffect } from "react"; +import { useCachedState } from "@raycast/utils"; + +interface ReturnedTasks { + data: Task[]; +} + +interface Task { + id: string; + title: string; + description: string | null; + date: string | null; + datetime: string | null; + duration: number; + priority: number; + listId: string | null; + done: boolean; + status: number; + due_date: string | null; + tagsIds: string[] | null; + deleted_at?: string | null; + trashed_at?: string | null; + recurrence: string | null; + recurring_id: string | null; + links: string[] | null; + done_at: string | null; +} + +interface Priority { + stringRepresentation: string; + color: Color | undefined; + icon: Icon; +} + +interface Project { + title: string; + color: string; + parentId: string | null; + icon: string; +} + +const priorityMap: Record<number, Priority> = { + 1: { stringRepresentation: "High", color: Color.Red, icon: Icon.Exclamationmark3 }, + 2: { stringRepresentation: "Medium", color: Color.Yellow, icon: Icon.Exclamationmark2 }, + 3: { stringRepresentation: "Low", color: Color.Green, icon: Icon.Exclamationmark }, + 99: { stringRepresentation: "No Priority", color: undefined, icon: Icon.Flag }, + [-1]: { stringRepresentation: "Goal", color: Color.Magenta, icon: Icon.BullsEye }, +}; + +function formatDate(task: Task): [string, boolean] { + if (task.date) { + return [new Date(task.date).toLocaleDateString("en-US", { timeZone: "UTC" }), false]; + } else if (task.datetime) { + return [new Date(task.datetime).toLocaleDateString("en-US", { timeZone: "UTC" }), false]; + } else if (task.due_date) { + return [new Date(task.due_date).toLocaleDateString("en-US", { timeZone: "UTC" }), true]; + } else { + return ["", false]; + } +} + +async function markTaskAsDone(taskId: string) { + const akiflow = new Akiflow(getPreferenceValues<Preferences>().refreshToken); + try { + showToast({ title: "Marking task as done...", style: Toast.Style.Animated }); + await akiflow.markTaskAsDone(taskId); + showToast({ title: "Task marked as done", style: Toast.Style.Success }); + } catch (error) { + const errorMessage = (error as Error).message; + showToast({ title: "Error marking task as done", message: errorMessage, style: Toast.Style.Failure }); + console.error("Error marking task as done:", error); + } +} + +export default function Command() { + const [tasks, setTasks] = useCachedState<ReturnedTasks>("tasks", { data: [] }); + const [projects, setProjects] = useCachedState<{ [key: string]: Project }>("projects", {}); + const [tags, setTags] = useCachedState<{ [key: string]: string }>("tags", {}); + const [isLoading, setIsLoading] = useState<boolean>(true); // Loading state + const refreshToken = getPreferenceValues<Preferences>().refreshToken; + + useEffect(() => { + const akiflow = new Akiflow(getPreferenceValues<Preferences>().refreshToken); + const fetchTasks = async () => { + try { + const tasks = await akiflow.getTasks(); + setTasks(tasks); + } catch (error) { + console.error("Error fetching tasks:", error); + } finally { + setIsLoading(false); // Set loading to false after fetching + } + }; + fetchTasks(); + }, []); // Empty dependency array to run only once on mount + useEffect(() => { + const akiflow = new Akiflow(refreshToken); + + const fetchProjectsAndTags = async () => { + try { + await akiflow.projectsPromise; + setProjects(akiflow.projects); + await akiflow.refreshTags(); + setTags(akiflow.tags); + } catch (error) { + console.error("Error fetching projects or tags", error); + } finally { + setIsLoading(false); + } + }; + + fetchProjectsAndTags(); + }, [refreshToken]); + + const notDeletedTasks = tasks.data.filter((task: Task) => task.deleted_at === null && task.trashed_at === null); + const notRecurringTasks = notDeletedTasks.filter((task) => task.recurrence === null && task.recurring_id === null); + const notWeirdBrokenTasks = notRecurringTasks.filter((task) => [1, 2, 4, 7].includes(task.status)); + notWeirdBrokenTasks.sort((a, b) => { + const dateA = a.date + ? new Date(a.date) + : a.datetime + ? new Date(a.datetime) + : a.due_date + ? new Date(a.due_date) + : new Date(Infinity); + + const dateB = b.date + ? new Date(b.date) + : b.datetime + ? new Date(b.datetime) + : b.due_date + ? new Date(b.due_date) + : new Date(Infinity); + + return dateA.getTime() - dateB.getTime(); + }); + const sortedTasksOnSomeday = notWeirdBrokenTasks.sort((a, b) => { + // Move tasks with status 7 to the end + if (a.status === 7 && b.status !== 7) return 1; + if (a.status !== 7 && b.status === 7) return -1; + return 0; // Keep original order for other tasks + }); + const notDoneTasks = sortedTasksOnSomeday.filter((task) => !task.done); + const doneTasks = sortedTasksOnSomeday.filter((task) => task.done); + const sortedDoneTasks = doneTasks.sort((a, b) => { + const dateA = a.done_at ? new Date(a.done_at) : new Date(Infinity); + const dateB = b.done_at ? new Date(b.done_at) : new Date(Infinity); + return dateA.getTime() - dateB.getTime(); + }); + sortedDoneTasks.reverse(); // reverse the order of done tasks so most recently done is at the top + + function TaskListSection({ title, tasks }: { title: string; tasks: Task[] }) { + return ( + <List.Section title={title}> + {tasks.map((task) => ( + <List.Item + key={task.id} + title={task.title} + // title="title" + keywords={[ + ...(task.status == 1 && task.done == false ? ["inbox"] : []), + ...(task.status == 2 ? ["planned"] : []), + ...(task.status == 4 ? ["snoozed"] : []), + ...(task.status == 7 ? ["someday"] : []), + ...(task.priority == -1 ? ["goal priority"] : []), + ...(task.priority == 1 ? ["high priority"] : []), + ...(task.priority == 2 ? ["medium priority"] : []), + ...(task.priority == 3 ? ["low priority"] : []), + ...(task.priority == 99 || task.priority == null ? ["no priority"] : []), + ...(task.tagsIds ? task.tagsIds.map((tagId) => tags[tagId]) : []), + ...(task.listId ? [projects[task.listId].title] : []), + ...(task.date ? [formatDate(task)[0]] : []), + ...(task.datetime ? [formatDate(task)[0]] : []), + ...(task.due_date ? [formatDate(task)[0]] : []), + ]} + accessories={[ + { + text: { + value: task.status == 1 ? "Inbox" : task.status == 7 ? "Someday" : "", + color: task.status == 1 ? Color.Blue : task.status == 7 ? Color.Orange : undefined, + }, + icon: { + source: task.status == 1 ? Icon.Tray : task.status == 7 ? Icon.Calendar : "", + tintColor: task.status == 1 ? Color.Blue : task.status == 7 ? Color.Orange : undefined, + }, + }, + { + text: { + value: task.listId ? projects[task.listId].icon + " " + projects[task.listId].title : "", + // value: "listId", + }, + }, + { + text: { + value: formatDate(task)[0], + color: formatDate(task)[1] ? Color.Red : undefined, + }, + icon: { + source: Icon.Calendar, + tintColor: formatDate(task)[1] ? Color.Red : undefined, + }, + tooltip: formatDate(task)[0] ? (formatDate(task)[1] ? "Deadline" : "Planned Date") : "No Date", + }, + { + icon: { + source: + priorityMap[task.priority] && + getPreferenceValues<Preferences.SearchTasks>().useFlagsForPriority == "useBullseye" + ? priorityMap[task.priority].icon + : Icon.Flag, + tintColor: priorityMap[task.priority] ? priorityMap[task.priority].color : undefined, + }, + tooltip: priorityMap[task.priority] ? priorityMap[task.priority].stringRepresentation : "No Priority", + }, + ]} + icon={task.done ? Icon.Checkmark : Icon.Circle} + actions={ + <ActionPanel title="Task Actions"> + <Action title={`Open ${task.title} in Akiflow`} onAction={() => viewTaskInAkiflow(task.title)} /> + <Action title={`Mark ${task.title} as Done`} onAction={() => markTaskAsDone(task.id)} /> + {task.links != null && task.links.length > 0 && ( + <Action.OpenInBrowser title={"Open Associated Link"} url={task.links[0]} /> + )} + {/* <Action title="Console.log the task" onAction={() => console.log(task)} /> */} + </ActionPanel> + } + /> + ))} + </List.Section> + ); + } + + return ( + <List + navigationTitle="Search Tasks" + searchBarPlaceholder={`Search for a task by title or use keywords like 'inbox', 'low priority', or '${new Date().toLocaleDateString("en-US", { month: "numeric", day: "numeric", year: "numeric" })}'`} + isLoading={isLoading} + filtering={{ keepSectionOrder: true }} + > + <TaskListSection + title="Not Done" + tasks={notDoneTasks.sort((a, b) => { + const dateA = a.date + ? new Date(a.date) + : a.datetime + ? new Date(a.datetime) + : a.due_date + ? new Date(a.due_date) + : new Date(Infinity); + + const dateB = b.date + ? new Date(b.date) + : b.datetime + ? new Date(b.datetime) + : b.due_date + ? new Date(b.due_date) + : new Date(Infinity); + + return dateA.getTime() - dateB.getTime(); + })} + /> + {getPreferenceValues<Preferences.SearchTasks>().showCompletedTasks && ( + <TaskListSection title="Done" tasks={sortedDoneTasks} /> + )} + </List> + ); +} diff --git a/extensions/akiflow/src/tools/add-task.ts b/extensions/akiflow/src/tools/add-task.ts new file mode 100644 index 00000000000..f4f8fc9b943 --- /dev/null +++ b/extensions/akiflow/src/tools/add-task.ts @@ -0,0 +1,152 @@ +import { Akiflow } from "../../utils/akiflow"; +import { getPreferenceValues } from "@raycast/api"; +import { toISO8601WithTimezoneOffset } from "../../utils/time-utils"; +import { parseISO } from "date-fns"; + +type Task = { + /** + * The title of the task (required). + * @example "Review Financials" or "Buy Groceries" + */ + title: string; + + /** + * A brief description of the task (optional). + * @example "Review the company's financial statements." or "[] Apples\n[] Chicken\n[] Salt" + * @remarks You can also use this for subtasks in the format [] which Akiflow converts to checkboxes. If you do subtasks, you should precede all of them with [] so the user can check them off later. Do not use any other list format like "- ". Each subtask should be a separate line (\n) + */ + description?: string; + + /** + * Unique identifier for the task (optional). + * @remarks This is a UUID and is irrelevant for when the user is creating a task. Only use this when the user requests to edit a task. When the user asks to edit a task, you get the UUID from the get-tasks tool. + */ + id?: string; + + /** + * The date associated with the task (optional). + * @example "2025-04-04" + * @remarks This is a string in YYYY-MM-DD format. Use this field when the user wants to schedule a task for a day WITHOUT a time, such as "Today", "Tomorrow", "Monday". + */ + date?: string; + + /** + * The date and time of the event in ISO 8601 format with timezone offset + * @example "2024-03-20T15:30:00-07:00" or "2024-03-20T15:30:00+02:00" + * @remarks For accurate timezone handling, always include the timezone offset (e.g., -07:00, +02:00) rather than using Z (UTC). + * @remarks Additionally, date must be set even when using datetime; if the user gives you a date and time, set the date field to just the date in YYYY-MM-DD format and exclude the time. + */ + datetime?: string; + + /** + * Duration of the task in minutes (optional). + * @example 60 + */ + duration?: number; + + /** + * Priority level of the task + * @remarks this is determined by a number which represents the priority. 99 = no priority, -1 = goal, 1 = high, 2 = medium, 3 = low. If the user does not specify a priority, you can leave the field blank or set it to 99. + * @example User says make buy groceries my goal of the day. You set priority to -1 + */ + priority?: number; + + /** + * Identifier for the project to which the task belongs (optional). + * @remarks This is a UUID, so you must use the get-projects tool to determine the UUID for a project the user asks for. + * @remarks When a project is returned from get-projects, it has a color field. If the color field is null, this means the project is actually a folder and you must NOT apply it to a task. Only projects with a color are real projects. + */ + listId?: string; + + /** + * Indicates if the task is completed (optional). + */ + done?: boolean; + + /** Status of the task (1: Inbox, 2: Planned, 7: Someday) + * @remarks This is set automatically dependent on whether a date or time is provided, only set this manually if the user wants to make a task planned for "someday", in which case you will set this value to 7. + */ + status?: number; + + /** + * @example "2025-04-04" + * @remarks This is a string in YYYY-MM-DD format. Use this field when the user wants to give the task a due date or deadline. + */ + due_date?: string; + + /** Array of tag identifiers associated with the task (optional). + * @remarks This is a list of UUIDs, so you must use the get-tags tool to determine the UUID for a tag the user asks for + */ + tags_ids?: string[]; +}; + +/** + * Creates a new task in the Akiflow system based on the provided input. + * This function processes the task details and adds it to Akiflow. + * + * @param {Task} input - The task object containing details such as title, description, date, etc. + * The title is mandatory, while other fields are optional. + * + * @returns {Promise<void>} A promise that resolves when the task has been added to Akiflow. + * + * @throws {Error} Throws an error if there is an issue with the task creation process. + * + * @example + * const newTask: Task = { + * title: "Complete Project Report", + * description: "Finish the report on the project status.", + * date: "2025-04-10T09:00:00Z", + * priority: 1, + * tags_ids: + * }; + * + * await createTask(newTask); + * + * Note: This function retrieves the user's refresh token from Raycast preferences + * and initializes the Akiflow instance. It processes optional fields such as + * description, date, due date, priority, and tags before adding the task. + * Ensure that the title is always provided, as it is required for task creation. + */ +export default async function (input: Task) { + const refreshToken = getPreferenceValues<Preferences>().refreshToken; + const akiflow = new Akiflow(refreshToken); + const task: Task = { + title: input.title, + }; + + if (input.description) { + task.description = input.description; + } + if (input.date) { + task.status = 2; + task.date = input.date; + } + if (input.datetime) { + const date = parseISO(input.datetime); + + task.status = 2; + task.datetime = toISO8601WithTimezoneOffset(date); + } + if (task.status !== 2 && input.status !== 7) { + task.status = 1; + } + if (input.status === 7) { + task.status = 7; + } + if (input.due_date) { + task.due_date = input.due_date; + } + if (input.priority) { + task.priority = input.priority; + } + if (input.tags_ids) { + task.tags_ids = input.tags_ids; // Add selected tags to the task + } + if (input.listId) { + task.listId = input.listId; + } + if (input.duration) { + task.duration = input.duration * 60; + } + return await akiflow.addSingleTask(task); +} diff --git a/extensions/akiflow/src/tools/edit-task.ts b/extensions/akiflow/src/tools/edit-task.ts new file mode 100644 index 00000000000..9f5e3c32c6a --- /dev/null +++ b/extensions/akiflow/src/tools/edit-task.ts @@ -0,0 +1,127 @@ +import { Tool, getPreferenceValues } from "@raycast/api"; +import { Akiflow } from "../../utils/akiflow"; + +type Task = { + /** + * The title of the task (optional). + * @example "Review Financials" or "Buy Groceries" + */ + title?: string; + + /** + * A brief description of the task (optional). + * @example "Review the company's financial statements." or "[] Apples\n[] Chicken\n[] Salt" + * @remarks You can also use this for subtasks in the format [] which Akiflow converts to checkboxes. If you do subtasks, you should precede all of them with [] so the user can check them off later. Do not use any other list format like "- ". Each subtask should be a separate line (\n) + */ + description?: string; + + /** + * Unique identifier for the task. + * @remarks This is a UUID and is for when the user is creating a task. Only use this when the user requests to edit a task. When the user asks to edit a task, you get the UUID from the get-tasks tool. + */ + id: string; + + /** + * The date associated with the task (optional). + * @example "2025-04-04" + * @remarks This is a string in YYYY-MM-DD format. Use this field when the user wants to schedule a task for a day WITHOUT a time, such as "Today", "Tomorrow", "Monday". + */ + date?: string; + + /** + * The date and time of the event in ISO 8601 format with timezone offset + * @example "2024-03-20T15:30:00-07:00" or "2024-03-20T15:30:00+02:00" + * @remarks For accurate timezone handling, always include the timezone offset (e.g., -07:00, +02:00) rather than using Z (UTC). + * @remarks Additionally, date must be set even when using datetime; if the user gives you a date and time, set the date field to just the date in YYYY-MM-DD format and exclude the time. + */ + datetime?: string; + + /** + * Duration of the task in minutes (optional). + * @example 60 + */ + duration?: number; + + /** + * Priority level of the task + * @remarks this is determined by a number which represents the priority. 99 = no priority, -1 = goal, 1 = high, 2 = medium, 3 = low. If the user does not specify a priority, you can leave the field blank or set it to 99. + * @example User says make buy groceries my goal of the day. You set priority to -1 + */ + priority?: number; + + /** + * Identifier for the project to which the task belongs (optional). + * @remarks This is a UUID, so you must use the get-projects tool to determine the UUID for a project the user asks for. + * @remarks When a project is returned from get-projects, it has a color field. If the color field is null, this means the project is actually a folder and you must NOT apply it to a task. Only projects with a color are real projects. + */ + listId?: string; + + /** + * Indicates if the task is completed + */ + done?: boolean; + + /** Status of the task (1: Inbox, 2: Planned, 7: Someday) + * @remarks This is set automatically dependent on whether a date or time is provided, only set this manually if the user wants to make a task planned for "someday", in which case you will set this value to 7. + */ + status?: number; + + /** + * @example "2025-04-04" + * @remarks This is a string in YYYY-MM-DD format. Use this field when the user wants to give the task a due date or deadline. + */ + due_date?: string; + + /** Array of tag identifiers associated with the task (optional). + * @remarks This is a list of UUIDs, so you must use the get-tags tool to determine the UUID for a tag the user asks for + */ + tags_ids?: string[]; +}; + +export const confirmation: Tool.Confirmation<Task> = async (input) => { + // if the only property being changed is done, do not show the confirmation + if (Object.keys(input).length === 2 && Object.keys(input).includes("done") && Object.keys(input).includes("id")) { + return; + } + // take every property of the input besides ID and show it to the user + return { + message: + "Are you sure you want to edit the following properties of the task?\n" + + Object.keys(input) + .filter((key) => key !== "id") + .map((key) => `New ${key}: ${input[key as keyof Task]}`) + .join("\n"), + }; +}; + +/** + * Edits a task in Akiflow based on the provided input. + * This function processes the task details and adds it to Akiflow. + * + * @param {Task} input - The task object containing details such as title, description, date, etc. + * The id is mandatory, while other fields are optional. + * + * @returns {Promise<void>} A promise that resolves when the task has been edited in Akiflow. + * + * @throws {Error} Throws an error if there is an issue with the task editing process. + * + * @example + * const newTask: Task = { + * id: "e81158ea-13e5-4985-995b-47aaeb77b3e4", + * title: "Complete Project Report", + * }; + * @remarks That example would edit the task with the ID "e81158ea-13e5-4985-995b-47aaeb77b3e4" and set its title to "Complete Project Report". + * + * @example + * const newTask: Task = { + * id: "e81158ea-13e5-4985-995b-47aaeb77b3e4", + * done: true, + * } + * + * @remarks that example would mark the task with the ID "e81158ea-13e5-4985-995b-47aaeb77b3e4" as done. + */ +export default async function tool(input: Task) { + const refreshToken = getPreferenceValues<Preferences>().refreshToken; + const akiflow = new Akiflow(refreshToken); + return await akiflow.addSingleTask(input); +} diff --git a/extensions/akiflow/src/tools/get-current-time.ts b/extensions/akiflow/src/tools/get-current-time.ts new file mode 100644 index 00000000000..4ccbc0b049f --- /dev/null +++ b/extensions/akiflow/src/tools/get-current-time.ts @@ -0,0 +1,28 @@ +// this code is entirely copied from the google calendar extension and i made absolutely none of it. +import { toHumanReadableTime, toISO8601WithTimezoneOffset } from "../../utils/time-utils"; + +/** + * Get the current time + * + * @remarks + * Use this tool only if you need to get the current time. + * Returns the current time in ISO 8601 format with timezone offset (e.g., "2024-06-15T14:30:00-07:00"), + * which is the recommended format for accurate timezone handling with LLMs. + * The timezone offset (e.g., -07:00, +02:00) is explicitly included rather than using Z (UTC) + * to ensure proper timezone interpretation. + */ +const tool = async () => { + const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone; + + const now = new Date(); + const iso8601 = toISO8601WithTimezoneOffset(now); + const humanReadableTime = toHumanReadableTime(now); + + return { + timezone, + iso8601, + humanReadableTime, + }; +}; + +export default tool; diff --git a/extensions/akiflow/src/tools/get-projects.ts b/extensions/akiflow/src/tools/get-projects.ts new file mode 100644 index 00000000000..d3169cd2a0e --- /dev/null +++ b/extensions/akiflow/src/tools/get-projects.ts @@ -0,0 +1,13 @@ +import { Akiflow } from "../../utils/akiflow"; +import { getPreferenceValues } from "@raycast/api"; + +/** + * @returns a list of projects with values title, id, color, and icon. If color is null, the project is a folder. If color is not null, it is a project. + */ +export default async function () { + const refreshToken = getPreferenceValues<Preferences>().refreshToken; + const akiflow = new Akiflow(refreshToken); + await akiflow.refreshProjects(); + await akiflow.projectsPromise; + return akiflow.projects; +} diff --git a/extensions/akiflow/src/tools/get-tags.ts b/extensions/akiflow/src/tools/get-tags.ts new file mode 100644 index 00000000000..a8ca0266870 --- /dev/null +++ b/extensions/akiflow/src/tools/get-tags.ts @@ -0,0 +1,13 @@ +import { Akiflow } from "../../utils/akiflow"; +import { getPreferenceValues } from "@raycast/api"; + +/** + * @returns a list of tags with values that are objects where the key is id and the value is title. Use the tag id when adding a task with a tag. + */ +export default async function () { + const refreshToken = getPreferenceValues<Preferences>().refreshToken; + const akiflow = new Akiflow(refreshToken); + await akiflow.refreshTags(); + await akiflow.tagsPromise; + return akiflow.tags; +} diff --git a/extensions/akiflow/src/tools/get-tasks.ts b/extensions/akiflow/src/tools/get-tasks.ts new file mode 100644 index 00000000000..e5783d9b389 --- /dev/null +++ b/extensions/akiflow/src/tools/get-tasks.ts @@ -0,0 +1,168 @@ +import { Akiflow } from "../../utils/akiflow"; +import { getPreferenceValues } from "@raycast/api"; + +// Define the expected structure of a task +interface Task { + /** + * @remarks This is the title of the task and will always be provided. + * @examples "Review Financials" or "Buy Groceries" + */ + title: string; + + /** + * @remarks This is a brief description of the task. + * @examples "Review the company's financial statements." or "Remember to buy milk." + */ + description: string; + + /** + * @remarks this is the UUID of the task and will always be provided. You can use this to edit the task. + */ + id: string; + + /** + * @remarks This is the date associated with the task in YYYY-MM-DD format. + * @examples "2025-04-12" + * @remarks This date is already in the user's timezone. Use the get-current-time tool to get the current time in the user's timezone if they ask for a relative date like today. + */ + date: string; + + /** + * @remarks This is the date and time of the event in ISO 8601 format. It is already in the user's timezone. + * @examples "2024-03-20T15:30:00" + */ + datetime: string; + + /** + * @remarks This is the duration of the task in minutes. + * @examples 60 + */ + duration: number; + + /** + * @remarks This is the priority level of the task. It is a number that represents the priority. 99 or null = no priority, -1 = goal, 1 = high, 2 = medium, 3 = low. + * @examples -1 + */ + priority: number; + + /** + * This is the project of the task. It is a UUID and will sometimes be provided. If it is null, the task is not associated with a project. + * @remarks This is a UUID, so you must use the get-projects tool to determine the title of the project. + * @remarks When a project is returned from get-projects, it has a color field. If the color field is null, this means the project is actually a folder and you must NOT apply it to a task. Only projects with a color are real projects. + */ + listId: string; + + /** + * Whether or not the task is completed. + * @examples true or false + */ + done: boolean; + + /** + * @remarks This is a number that represents the status of the task. 1 = Inbox, 2 = Planned, 7 = Someday. + * @examples 1,2,7 + */ + status: number; + + /** + * @remarks This is the due date of the task in YYYY-MM-DD format. + * @examples "2025-04-12" + * @remarks This date is already in the user's timezone. Use the get-current-time tool to get the current time in the user's timezone if they ask for a relative date like today. + */ + due_date: string; + + /** + * @remarks This is an array of tag UUIDs associated with the task. Use the get-tags tool to determine the title of the tag given its UUID. + */ + tags_ids: string[]; + + /** + * @remarks These two fields are used to filter out things the user has removed from their account. + */ + deleted_at: string | null; + trashed_at: string | null; +} + +// Define the filter parameters +interface FilterParams { + title?: string; + description?: string; + id?: string; + date?: string; + datetime?: string; + duration?: number; + priority?: number; + listId?: string; + done: false | true; + status?: number; + due_date?: string; + tags_ids?: string[]; +} + +// Function to check if a task matches the filter +function matchesFilter(task: Task, filter: FilterParams): boolean { + return Object.keys(filter).every((key) => { + if (filter[key as keyof FilterParams] === undefined) return true; // Skip undefined filters + + const taskValue = task[key as keyof Task]; + const filterValue = filter[key as keyof FilterParams]; + + // Handle default value for done if not explicitly provided + if (key === "done" && filterValue === undefined) { + return task.done === false; // Default to false if not specified + } + + // Handle array comparison for tags_ids + if (Array.isArray(filterValue) && Array.isArray(taskValue)) { + return filterValue.every((tag) => taskValue.includes(tag)); + } + + if (typeof filterValue === "string" && typeof taskValue === "string") { + return filterValue.toLowerCase() === taskValue.toLowerCase(); + } + return taskValue === filterValue; // Direct comparison for other types + }); +} + +// Main function to get filtered tasks +export default async function getFilteredTasks(filterParams: FilterParams) { + const refreshToken = getPreferenceValues<Preferences>().refreshToken; + const akiflow = new Akiflow(refreshToken); + + // Fetch all tasks + const response = await akiflow.getTasks(); + const tasks = response.data; // Access the data key to get the list of tasks + + // Filter out deleted tasks + const notDeletedTasks = tasks.filter((task: Task) => task.deleted_at === null && task.trashed_at === null); + + // Debugging: Log the number of tasks before and after filtering + // console.log(`Total tasks: ${tasks.length}`); + // console.log(`Tasks after filtering deleted: ${notDeletedTasks.length}`); + + // Filter tasks based on the provided filter parameters + const filteredTasks = notDeletedTasks.filter((task: Task) => matchesFilter(task, filterParams)); + + // Sort the filtered tasks based on date properties + filteredTasks.sort((a: Task, b: Task) => { + const dateA = a.date + ? new Date(a.date) + : a.datetime + ? new Date(a.datetime) + : a.due_date + ? new Date(a.due_date) + : new Date(Infinity); // Far future date + + const dateB = b.date + ? new Date(b.date) + : b.datetime + ? new Date(b.datetime) + : b.due_date + ? new Date(b.due_date) + : new Date(Infinity); // Far future date + + return dateA.getTime() - dateB.getTime(); // Ascending order + }); + + return filteredTasks; +} diff --git a/extensions/akiflow/src/view-projects-and-tags.tsx b/extensions/akiflow/src/view-projects-and-tags.tsx new file mode 100644 index 00000000000..025fa48f2ad --- /dev/null +++ b/extensions/akiflow/src/view-projects-and-tags.tsx @@ -0,0 +1,165 @@ +import { ActionPanel, Action, Icon, List, getPreferenceValues, showToast, Color } from "@raycast/api"; +import { Akiflow, openInAkiflow, openAkiflow } from "../utils/akiflow"; +import { useState, useEffect } from "react"; +import { useCachedState } from "@raycast/utils"; + +interface Project { + title: string; + color: string; + parentId: string | null; + icon: string; +} + +function transformAndSortProjects( + projects: Record<string, Project>, +): Array<{ key: string; title: string; color: string; parentId: string | null; icon: string }> { + // Convert the projects object into an array of entries + const entries = Object.entries(projects).map(([key, project]) => ({ + key, + title: project.title, + color: project.color, + parentId: project.parentId, + icon: project.icon, + })); + + // Create a map to hold children for each parent + const parentMap: Record< + string, + Array<{ key: string; title: string; color: string; parentId: string | null; icon: string }> + > = {}; + const parents: Array<{ key: string; title: string; color: string; parentId: string | null; icon: string }> = []; + + // Populate the parentMap and collect parents + for (const entry of entries) { + if (entry.parentId === null) { + // It's a parent project + parents.push(entry); + } else { + // It's a child project + if (!parentMap[entry.parentId]) { + parentMap[entry.parentId] = []; + } + parentMap[entry.parentId].push(entry); + } + } + + // Sort parents lexicographically by title + parents.sort((a, b) => a.title.localeCompare(b.title)); + + // Construct the final sorted list + const sortedProjects: Array<{ key: string; title: string; color: string; parentId: string | null; icon: string }> = + []; + + // Add parents and their children to the sorted list + for (const parent of parents) { + sortedProjects.push(parent); // Add the parent project + if (parentMap[parent.key]) { + // Sort children of this parent lexicographically by title + const children = parentMap[parent.key].sort((a, b) => a.title.localeCompare(b.title)); + sortedProjects.push(...children); // Add children to the sorted list + } + } + + return sortedProjects; +} + +export default function Command() { + const [projects, setProjects] = useCachedState<{ [key: string]: Project }>("projects", {}); + const [tags, setTags] = useCachedState<{ [key: string]: string }>("tags", {}); + const [isLoading, setIsLoading] = useState<boolean>(true); + const refreshToken = getPreferenceValues<Preferences>().refreshToken; + + useEffect(() => { + const akiflow = new Akiflow(refreshToken); + + const fetchProjectsAndTags = async () => { + try { + await akiflow.projectsPromise; // Wait for the projects to be fetched + setProjects(akiflow.projects); // Set the projects state + await akiflow.refreshTags(); // Fetch tags + setTags(akiflow.tags); // Set the tags state + } catch (error) { + console.error("Error fetching projects or tags", error); + showToast({ title: "Error", message: "Failed to fetch projects or tags" }); + } finally { + setIsLoading(false); + } + }; + + fetchProjectsAndTags(); + }, [refreshToken]); + const sortedProjects = transformAndSortProjects(projects); + return ( + <List isLoading={isLoading} searchBarPlaceholder="Search projects"> + <List.Section title="Projects"> + {sortedProjects.length > 0 ? ( + sortedProjects.map((project) => ( + <List.Item + key={project.key} + title={project.title} + // subtitle={project.color ? project.color : "no color provided"} + icon={project.parentId ? (project.icon ?? Icon.Hashtag) : Icon.Folder} + keywords={[...(project.parentId ? ["project", "#"] : ["folder"])]} + actions={ + project.parentId ? ( + <ActionPanel title="Project Actions"> + <Action + title={`Open ${project.icon} ${project.title} in Akiflow`} + icon={"akiflow-menu-bar-icon.png"} + onAction={() => { + openInAkiflow(project.title); + }} + /> + <Action.OpenInBrowser + title={`Open ${project.icon} ${project.title} in Akiflow Web`} + url={`https://web.akiflow.com/#/planner/list/${project.key}`} + /> + </ActionPanel> + ) : ( + <ActionPanel title="Folder Actions"> + <Action + title="Open Akiflow" + onAction={() => { + openAkiflow(); + }} + ></Action> + </ActionPanel> + ) + } + /> + )) + ) : ( + <List.Item title="No projects found" icon={{ source: Icon.QuestionMark, tintColor: Color.Red }} /> + )} + </List.Section> + <List.Section title="Tags"> + {Object.entries(tags).length > 0 ? ( + Object.entries(tags).map(([name, id]) => ( + <List.Item + key={id} + title={name} + icon={Icon.Tag} + keywords={["tag", "*"]} + actions={ + <ActionPanel title="Tag Actions"> + <Action + title={`Open 🏷️ ${name} in Akiflow Web`} + onAction={() => { + openInAkiflow(name); + }} + /> + <Action.OpenInBrowser + title={`Open 🏷️ ${name} in Akiflow Web`} + url={`https://web.akiflow.com/#/planner/tags/${id}`} + /> + </ActionPanel> + } + /> + )) + ) : ( + <List.Item title="No tags found" icon={{ source: Icon.QuestionMark, tintColor: Color.Red }} /> + )} + </List.Section> + </List> + ); +} diff --git a/extensions/akiflow/tsconfig.json b/extensions/akiflow/tsconfig.json new file mode 100644 index 00000000000..d33dd46c481 --- /dev/null +++ b/extensions/akiflow/tsconfig.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "include": ["src/**/*", "raycast-env.d.ts"], + "compilerOptions": { + "lib": ["ES2023"], + "module": "commonjs", + "target": "ES2023", + "strict": true, + "isolatedModules": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "jsx": "react-jsx", + "resolveJsonModule": true + } +} diff --git a/extensions/akiflow/utils/akiflow.tsx b/extensions/akiflow/utils/akiflow.tsx new file mode 100644 index 00000000000..fec6d306e32 --- /dev/null +++ b/extensions/akiflow/utils/akiflow.tsx @@ -0,0 +1,360 @@ +import axios from 'axios'; +import { AxiosResponse } from 'axios'; +import { exec } from 'child_process'; +import { runAppleScript } from '@raycast/utils'; +import { closeMainWindow } from '@raycast/api'; + +interface Task { + title?: string; + description?: string; + id?: string; + date?: string; + datetime?: string; + duration?: number; + priority?: number; + listId?: string; + done?: boolean; + status?: number; + due_date?: string; + tagsIds?: string[]; +} + +interface Project { + title: string; + color: string; + parentId: string | null; + icon: string; +} + +export const colorMap: { [key: string]: string } = { + "palette-blue": "#007BFF", + "palette-violet": "#8A2BE2", + "palette-orange": "#FFA500", + "palette-wildwillow": "#31BF75", + "palette-red": "#FF0000", + "palette-comet": "#A9A9A9", + "palette-grey": "#808080", + "palette-yellow": "#FFFF00", + "palette-pink": "#FFC0CB", + "palette-purple": "#800080", + "palette-mauve": "#E0B0FF", + "palette-cyan": "#00FFFF", + "palette-green": "#008000", + "palette-chico": "#D1A6A1", + "palette-brown": "#A52A2A", + "palette-finn": "#5F1C3A" +}; + +export class Akiflow { + private refreshToken: string; + private tokenPromise: Promise<string | void>; + public projectsPromise: Promise<string | void>; + public tagsPromise: Promise<string | void>; + private tasks_url = 'https://api.akiflow.com/v3/tasks'; + private projects_url = 'https://api.akiflow.com/v3/labels'; + private tags_url = 'https://api.akiflow.com/v3/tags'; + private events_url = 'https://api.akiflow.com/v3/events'; + private token: string = ''; + private headers = { + 'Akiflow-Platform': 'mac', + 'Authorization': '', // Will be set after getting the token + 'Referer': 'https://web.akiflow.com/app/stable/e89ffa149c8786fb/static/js/21.chunk.js', + 'Akiflow-Client-Id': 'b4edaac3-5dc7-4b20-bf58-de51efc2bec4', + 'Akiflow-Version': '2.45.20', + 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36', + 'Accept': 'application/json', + 'DNT': '1', + 'Content-Type': 'application/json' + }; + public projects: Record<string, Project> = {}; + public tags: Record<string, string> = {}; + + constructor(refreshToken: string) { + this.refreshToken = refreshToken; + this.tokenPromise = this.getToken(refreshToken).then(authtoken => { + this.token = authtoken + this.headers.Authorization = `Bearer ${this.token}`; + }); + this.projectsPromise = this.refreshProjects(); + this.tagsPromise = this.refreshTags(); + } + + private async getToken(refreshToken: string): Promise<string> { + const url = 'https://web.akiflow.com/oauth/refreshToken'; + // Define the headers as an object + const headers = { + 'Accept': 'application/json', + 'Accept-Language': 'en-US,en;q=0.9', + 'Akiflow-Version': '2.45.20', + 'Content-Type': 'application/json', + }; + + const data = { + client_id: "10", + refresh_token: refreshToken, + }; + + try { + // Send the POST request + const response = await axios.post(url, data, { headers }); + + // Check if the response status is 200 + if (response.status === 200) { + return response.data.access_token; + } else { + console.error(`Error: ${response.status}`); + return "null"; + } + } catch (error) { + console.error('Error during token refresh:', error); + return "null"; + } + } + + private async makeRequest(url: string, method: string, body?: any): Promise<any> { + await this.tokenPromise; + const response: AxiosResponse = await axios.request({ + url, + method, + headers: this.headers, + data: body + }); + return response.data; + } + + private validateParameters(parameterName: string, value: any): void { + const parametersTypesDict: Record<string, string> = { + title: "string", + description: "string", + id: "string", + duration: "number", + priority: "number", + listId: "string", + done: "boolean", + status: "number", + date: "string", + datetime: "string", + due_date: "string", + tags_ids: "object" + }; + + if (!(parameterName in parametersTypesDict)) { + throw new Error(`Invalid parameter: ${parameterName}`); + } + + if (typeof value !== parametersTypesDict[parameterName]) { + throw new TypeError(`Invalid type for parameter: ${parameterName}. Expected type: ${parametersTypesDict[parameterName]}. Actual type: ${typeof value}`); + } + + if (parameterName === "priority" && ![99, -1, 1, 2, 3].includes(value)) { + throw new Error(`Invalid priority value: ${value}. Valid values are: -1 (Goal), 1 (High), 2 (Medium), 3 (Low)`); + } + + if (parameterName === "status" && ![1, 2, 4, 7].includes(value)) { + throw new Error(`Invalid status value: ${value}. Valid values are: 1 (Inbox), 2 (Planned), 4 (Snoozed), 7 (Someday)`); + } + + const dateRegex = /^\d{4}-\d{2}-\d{2}$/; + const datetimeRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(Z|[+-]\d{2}:\d{2})$/; + + if (parameterName === "date" && !dateRegex.test(value)) { + throw new Error(`Invalid date format: ${value}. Expected format: YYYY-MM-DD`); + } + + if (parameterName === "datetime" && !datetimeRegex.test(value)) { + throw new Error(`Invalid datetime format: ${value}. Expected format: YYYY-MM-DDTHH:MM:SS±HH:MM`); + } + + if (parameterName === "due_date" && !dateRegex.test(value)) { + throw new Error(`Invalid due_date format: ${value}. Expected format: YYYY-MM-DD`); + } + } + + public async addSingleTask(task: Task): Promise<any> { + // await this.tokenPromise; + if (!task.title && !task.id) { + throw new Error("Title or ID is required"); + } + + const data: any = {}; + Object.entries(task).forEach(([key, value]) => { + this.validateParameters(key, value); + data[key] = value; + }); + console.log(data); + return await this.makeRequest(this.tasks_url, 'POST', data); + } + + public async markTaskAsDone(taskId: string): Promise<any> { + const data: any = { done: true }; + data.id = taskId; + return await this.makeRequest(this.tasks_url, 'POST', data) + } + + public async addTasks(tasks: Task[]): Promise<any> { + if (!Array.isArray(tasks)) { + throw new TypeError("'tasks' must be a list"); + } + if (tasks.length === 0) { + throw new Error("List of tasks is empty"); + } + if (!tasks.every(task => typeof task === 'object')) { + throw new TypeError("All items in 'tasks' must be dictionaries"); + } + + const data: Task[] = []; + for (const task of tasks) { + const taskData = await this.addSingleTask(task); + data.push(taskData); + } + + return await this.makeRequest(this.tasks_url, 'POST', data); + } + + public async getTasks(withDeleted: boolean = false): Promise<any> { + const url = `${this.tasks_url}?per_page=2500`; + return await this.makeRequest(url, 'GET'); + } + + public async getEvents(withDeleted: boolean = false): Promise<any> { + const url = `${this.events_url}?per_page=2500`; + return await this.makeRequest(url, 'GET'); + } + + public async refreshTags(): Promise<void> { + const response = await this.makeRequest(this.tags_url, 'GET'); + const tags = response.data; + for (const tag of tags) { + if (tag.deleted_at === null) { + const cleanedTag = tag.title.replace(/[^\w\s]/g, '').trim(); + this.tags[cleanedTag] = tag.id; + } + } + } + + public async refreshProjects(): Promise<void> { + const response = await this.makeRequest(this.projects_url, 'GET'); + const projects = response.data; + this.projects = {}; // Reset the projects object + for (const project of projects) { + if (project.deleted_at === null) { + this.projects[project.id] = { + title: project.title, + color: colorMap[project.color], + parentId: project.parent_id, + icon: project.icon, + }; + } + } + } + +} + +export function openInAkiflow(thingToOpen: string) { + closeMainWindow(); + exec('open -a "Akiflow.app"'); + runAppleScript(` + tell application "Akiflow" to activate + tell application "System Events" + keystroke "k" using command down + delay 0.25 + keystroke "go to" + delay 0.25 + keystroke return + delay 0.25 + keystroke "${thingToOpen}" + delay 0.25 + keystroke return + end tell` + ) +} + +export function openAkiflow() { + closeMainWindow(); + exec('open -a "Akiflow.app"'); +} + + +export function viewTaskInAkiflow(taskName: string) { + closeMainWindow(); + let cleanedTaskTitle = taskName.replace(/[\u200B\u200C\u200D\u200E\u200F\u2060]/g, ''); + for (let i = 0; i < taskName.length; i++) { + console.log(`Character at ${i}: '${taskName[i]}' (Code: ${taskName.charCodeAt(i)})`); + } + console.log(taskName.length); + console.log("first character: '" + taskName[0] + "'"); + console.log(cleanedTaskTitle == taskName ? "there was no issue" : "zero width space found!") + exec('open -a "Akiflow.app"'); + + runAppleScript( + ` + on run {theName} + tell application "Akiflow" to activate + delay 0.5 -- let the window become key + + tell application "System Events" + -- Cmd-F sent as a key code (3 = "f" on US keyboard) + key code 3 using {command down} + delay 0.35 -- let the search field appear + + -- Type the task name exactly + keystroke theName + end tell + end run + `, + [cleanedTaskTitle] // argument list for the script + ); +// } + +// export function viewTaskInAkiflow(taskName: string) { +// closeMainWindow(); +// exec('open -a "Akiflow.app"'); + +// // Raycast: second argument is options; we ask for 15-second budget +// runAppleScript( +// ` +// on run {theName} +// my ensureAppIsReady("Akiflow") +// my openSearchAndType(theName) +// end run + +// -- Wait until the application process is frontmost (maxWait seconds) +// on ensureAppIsReady(appName) +// tell application appName to activate + +// set maxWait to 5 +// set t0 to (current date) +// tell application "System Events" +// repeat until frontmost of application process appName is true +// if (current date) - t0 > maxWait then +// error "Timed out: " & appName & " never became frontmost" +// end if +// delay 0.05 +// end repeat +// end tell +// end ensureAppIsReady + +// -- Press Cmd-F and type the task name +// on openSearchAndType(theName) +// tell application "System Events" +// key code 3 using {command down} -- Cmd-F + +// -- wait until some control in Akiflow has focus (max 5 s) +// set maxWait to 5 +// set t0 to (current date) +// set targetProc to application process "Akiflow" +// repeat until (exists (first UI element of targetProc whose focused is true)) +// if (current date) - t0 > maxWait then +// error "Timed out: search field never got focus" +// end if +// delay 0.05 +// end repeat + +// -- ready → type +// keystroke theName +// end tell +// end openSearchAndType +// `, +// [taskName], { timeout: 15_000 } // 15 000 ms total budget +// ); +} \ No newline at end of file diff --git a/extensions/akiflow/utils/time-utils.tsx b/extensions/akiflow/utils/time-utils.tsx new file mode 100644 index 00000000000..337b5a4ca57 --- /dev/null +++ b/extensions/akiflow/utils/time-utils.tsx @@ -0,0 +1,32 @@ +// this code is entirely copied from the google calendar extension and i made absolutely none of it. +export function toHumanReadableTime(date = new Date()) { + return date.toLocaleString(undefined, { + year: "numeric", + month: "long", + day: "numeric", + hour: "numeric", + minute: "2-digit", + second: "2-digit", + timeZoneName: "short", + }); +} + +export function toISO8601WithTimezoneOffset(date = new Date()) { + const year = date.getFullYear(); + const month = (date.getMonth() + 1).toString().padStart(2, "0"); + const day = date.getDate().toString().padStart(2, "0"); + const hours = date.getHours().toString().padStart(2, "0"); + const minutes = date.getMinutes().toString().padStart(2, "0"); + const seconds = date.getSeconds().toString().padStart(2, "0"); + + const offset = date.getTimezoneOffset(); + const offsetHours = Math.abs(Math.floor(offset / 60)) + .toString() + .padStart(2, "0"); + const offsetMinutes = Math.abs(offset % 60) + .toString() + .padStart(2, "0"); + const offsetSign = offset <= 0 ? "+" : "-"; + + return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}${offsetSign}${offsetHours}:${offsetMinutes}`; + } \ No newline at end of file