Update from main
14
.github/workflows/update-e2e-branch.yml
vendored
@ -14,10 +14,19 @@ permissions:
|
||||
jobs:
|
||||
update-branch:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/create-github-app-token@v1
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ secrets.MODELING_APP_GH_APP_ID }}
|
||||
private-key: ${{ secrets.MODELING_APP_GH_APP_PRIVATE_KEY }}
|
||||
owner: ${{ github.repository_owner }}
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
- shell: bash
|
||||
with:
|
||||
token: ${{ steps.app-token.outputs.token }}
|
||||
|
||||
- name: Sync with main
|
||||
run: |
|
||||
# checkout our branch
|
||||
git checkout all-e2e || git checkout -b all-e2e
|
||||
@ -26,4 +35,5 @@ jobs:
|
||||
# reset to main
|
||||
git reset --hard origin/main
|
||||
# force push it
|
||||
git remote set-url origin https://x-access-token:${{ steps.app-token.outputs.token }}@github.com/${{ github.repository }}.git
|
||||
git push --force origin all-e2e
|
||||
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 75 KiB |
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
3
interface.d.ts
vendored
@ -44,6 +44,9 @@ export interface IElectronAPI {
|
||||
rm: typeof fs.rm
|
||||
stat: (path: string) => ReturnType<fs.stat>
|
||||
statIsDirectory: (path: string) => Promise<boolean>
|
||||
canReadWriteDirectory: (
|
||||
path: string
|
||||
) => Promise<{ value: boolean; error: unknown }>
|
||||
path: typeof path
|
||||
mkdir: typeof fs.mkdir
|
||||
join: typeof path.join
|
||||
|
@ -18,7 +18,9 @@ const config = defineConfig({
|
||||
environment: 'node',
|
||||
reporters: process.env.GITHUB_ACTIONS
|
||||
? ['dot', 'github-actions']
|
||||
: ['verbose', 'hanging-process'],
|
||||
: // Gotcha: 'hanging-process' is very noisey, turn off by default on localhost
|
||||
// : ['verbose', 'hanging-process'],
|
||||
['verbose'],
|
||||
testTimeout: 1000,
|
||||
hookTimeout: 1000,
|
||||
teardownTimeout: 1000,
|
||||
|
@ -135,13 +135,13 @@
|
||||
"@types/mocha": "^10.0.10",
|
||||
"@types/node": "^22.13.10",
|
||||
"@types/vscode": "^1.97.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.6.0",
|
||||
"@typescript-eslint/parser": "^6.6.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.27.0",
|
||||
"@typescript-eslint/parser": "^8.27.0",
|
||||
"@vscode/test-electron": "^2.4.1",
|
||||
"@vscode/vsce": "^2.30.0",
|
||||
"@vscode/vsce": "^3.3.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"esbuild": "^0.25.1",
|
||||
"glob": "^10.4.3",
|
||||
"glob": "^11.0.1",
|
||||
"mocha": "^11.1.0",
|
||||
"typescript": "^5.8.2"
|
||||
},
|
||||
|
@ -252,7 +252,7 @@
|
||||
dependencies:
|
||||
eslint-visitor-keys "^3.4.3"
|
||||
|
||||
"@eslint-community/regexpp@^4.5.1":
|
||||
"@eslint-community/regexpp@^4.10.0":
|
||||
version "4.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0"
|
||||
integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==
|
||||
@ -308,11 +308,6 @@
|
||||
"@types/minimatch" "^5.1.2"
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/json-schema@^7.0.12":
|
||||
version "7.0.15"
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
|
||||
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
|
||||
|
||||
"@types/minimatch@^5.1.2":
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca"
|
||||
@ -330,101 +325,91 @@
|
||||
dependencies:
|
||||
undici-types "~6.20.0"
|
||||
|
||||
"@types/semver@^7.5.0":
|
||||
version "7.5.8"
|
||||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e"
|
||||
integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==
|
||||
|
||||
"@types/vscode@^1.97.0":
|
||||
version "1.97.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/vscode/-/vscode-1.97.0.tgz#62ce3a32243019aaa4fc20cee2a3de06bc71af4f"
|
||||
integrity sha512-ueE73loeOTe7olaVyqP9mrRI54kVPJifUPjblZo9fYcv1CuVLPOEKEkqW0GkqPC454+nCEoigLWnC2Pp7prZ9w==
|
||||
|
||||
"@typescript-eslint/eslint-plugin@^6.6.0":
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz#30830c1ca81fd5f3c2714e524c4303e0194f9cd3"
|
||||
integrity sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==
|
||||
"@typescript-eslint/eslint-plugin@^8.27.0":
|
||||
version "8.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.27.0.tgz#fbef10802365832ee1d1bd5d2117dcec82727a72"
|
||||
integrity sha512-4henw4zkePi5p252c8ncBLzLce52SEUz2Ebj8faDnuUXz2UuHEONYcJ+G0oaCF+bYCWVZtrGzq3FD7YXetmnSA==
|
||||
dependencies:
|
||||
"@eslint-community/regexpp" "^4.5.1"
|
||||
"@typescript-eslint/scope-manager" "6.21.0"
|
||||
"@typescript-eslint/type-utils" "6.21.0"
|
||||
"@typescript-eslint/utils" "6.21.0"
|
||||
"@typescript-eslint/visitor-keys" "6.21.0"
|
||||
debug "^4.3.4"
|
||||
"@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.2.4"
|
||||
ignore "^5.3.1"
|
||||
natural-compare "^1.4.0"
|
||||
semver "^7.5.4"
|
||||
ts-api-utils "^1.0.1"
|
||||
ts-api-utils "^2.0.1"
|
||||
|
||||
"@typescript-eslint/parser@^6.6.0":
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.21.0.tgz#af8fcf66feee2edc86bc5d1cf45e33b0630bf35b"
|
||||
integrity sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==
|
||||
"@typescript-eslint/parser@^8.27.0":
|
||||
version "8.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.27.0.tgz#3f6beaa83934467eda34ae82ef04090014df8227"
|
||||
integrity sha512-XGwIabPallYipmcOk45DpsBSgLC64A0yvdAkrwEzwZ2viqGqRUJ8eEYoPz0CWnutgAFbNMPdsGGvzjSmcWVlEA==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "6.21.0"
|
||||
"@typescript-eslint/types" "6.21.0"
|
||||
"@typescript-eslint/typescript-estree" "6.21.0"
|
||||
"@typescript-eslint/visitor-keys" "6.21.0"
|
||||
"@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"
|
||||
|
||||
"@typescript-eslint/scope-manager@6.21.0":
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz#ea8a9bfc8f1504a6ac5d59a6df308d3a0630a2b1"
|
||||
integrity sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==
|
||||
"@typescript-eslint/scope-manager@8.27.0":
|
||||
version "8.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.27.0.tgz#b51042927067d677fbfc471605cf40d1ffaee482"
|
||||
integrity sha512-8oI9GwPMQmBryaaxG1tOZdxXVeMDte6NyJA4i7/TWa4fBwgnAXYlIQP+uYOeqAaLJ2JRxlG9CAyL+C+YE9Xknw==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "6.21.0"
|
||||
"@typescript-eslint/visitor-keys" "6.21.0"
|
||||
"@typescript-eslint/types" "8.27.0"
|
||||
"@typescript-eslint/visitor-keys" "8.27.0"
|
||||
|
||||
"@typescript-eslint/type-utils@6.21.0":
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz#6473281cfed4dacabe8004e8521cee0bd9d4c01e"
|
||||
integrity sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==
|
||||
"@typescript-eslint/type-utils@8.27.0":
|
||||
version "8.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.27.0.tgz#af3c4eefcb64455ee50aae2d7069918467af085c"
|
||||
integrity sha512-wVArTVcz1oJOIEJxui/nRhV0TXzD/zMSOYi/ggCfNq78EIszddXcJb7r4RCp/oBrjt8n9A0BSxRMKxHftpDxDA==
|
||||
dependencies:
|
||||
"@typescript-eslint/typescript-estree" "6.21.0"
|
||||
"@typescript-eslint/utils" "6.21.0"
|
||||
"@typescript-eslint/typescript-estree" "8.27.0"
|
||||
"@typescript-eslint/utils" "8.27.0"
|
||||
debug "^4.3.4"
|
||||
ts-api-utils "^1.0.1"
|
||||
ts-api-utils "^2.0.1"
|
||||
|
||||
"@typescript-eslint/types@6.21.0":
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d"
|
||||
integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==
|
||||
"@typescript-eslint/types@8.27.0":
|
||||
version "8.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.27.0.tgz#3dd01ced4c81e798d1106fda0904f8d5c91051aa"
|
||||
integrity sha512-/6cp9yL72yUHAYq9g6DsAU+vVfvQmd1a8KyA81uvfDE21O2DwQ/qxlM4AR8TSdAu+kJLBDrEHKC5/W2/nxsY0A==
|
||||
|
||||
"@typescript-eslint/typescript-estree@6.21.0":
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz#c47ae7901db3b8bddc3ecd73daff2d0895688c46"
|
||||
integrity sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==
|
||||
"@typescript-eslint/typescript-estree@8.27.0":
|
||||
version "8.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.27.0.tgz#4e02a1056454a84418cc9bce7c00b1c08b03567a"
|
||||
integrity sha512-BnKq8cqPVoMw71O38a1tEb6iebEgGA80icSxW7g+kndx0o6ot6696HjG7NdgfuAVmVEtwXUr3L8R9ZuVjoQL6A==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "6.21.0"
|
||||
"@typescript-eslint/visitor-keys" "6.21.0"
|
||||
"@typescript-eslint/types" "8.27.0"
|
||||
"@typescript-eslint/visitor-keys" "8.27.0"
|
||||
debug "^4.3.4"
|
||||
globby "^11.1.0"
|
||||
fast-glob "^3.3.2"
|
||||
is-glob "^4.0.3"
|
||||
minimatch "9.0.3"
|
||||
semver "^7.5.4"
|
||||
ts-api-utils "^1.0.1"
|
||||
minimatch "^9.0.4"
|
||||
semver "^7.6.0"
|
||||
ts-api-utils "^2.0.1"
|
||||
|
||||
"@typescript-eslint/utils@6.21.0":
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.21.0.tgz#4714e7a6b39e773c1c8e97ec587f520840cd8134"
|
||||
integrity sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==
|
||||
"@typescript-eslint/utils@8.27.0":
|
||||
version "8.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.27.0.tgz#d9c2a4891c6a85b952a9d5f9656c379ab111cf6d"
|
||||
integrity sha512-njkodcwH1yvmo31YWgRHNb/x1Xhhq4/m81PhtvmRngD8iHPehxffz1SNCO+kwaePhATC+kOa/ggmvPoPza5i0Q==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.4.0"
|
||||
"@types/json-schema" "^7.0.12"
|
||||
"@types/semver" "^7.5.0"
|
||||
"@typescript-eslint/scope-manager" "6.21.0"
|
||||
"@typescript-eslint/types" "6.21.0"
|
||||
"@typescript-eslint/typescript-estree" "6.21.0"
|
||||
semver "^7.5.4"
|
||||
"@typescript-eslint/scope-manager" "8.27.0"
|
||||
"@typescript-eslint/types" "8.27.0"
|
||||
"@typescript-eslint/typescript-estree" "8.27.0"
|
||||
|
||||
"@typescript-eslint/visitor-keys@6.21.0":
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz#87a99d077aa507e20e238b11d56cc26ade45fe47"
|
||||
integrity sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==
|
||||
"@typescript-eslint/visitor-keys@8.27.0":
|
||||
version "8.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.27.0.tgz#4a13e9d7ad7e311a07ea1b178b4c9f848ce11334"
|
||||
integrity sha512-WsXQwMkILJvffP6z4U3FYJPlbf/j07HIxmDjZpbNvBJkMfvwXj5ACRkkHwBDvLBbDbtX5TdU64/rcvKJ/vuInQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "6.21.0"
|
||||
eslint-visitor-keys "^3.4.1"
|
||||
"@typescript-eslint/types" "8.27.0"
|
||||
eslint-visitor-keys "^4.2.0"
|
||||
|
||||
"@vscode/test-electron@^2.4.1":
|
||||
version "2.4.1"
|
||||
@ -497,10 +482,10 @@
|
||||
"@vscode/vsce-sign-win32-arm64" "2.0.2"
|
||||
"@vscode/vsce-sign-win32-x64" "2.0.2"
|
||||
|
||||
"@vscode/vsce@^2.30.0":
|
||||
version "2.30.0"
|
||||
resolved "https://registry.yarnpkg.com/@vscode/vsce/-/vsce-2.30.0.tgz#7a0c16b20ef529fa291fe9d3c7fe51a2a613f773"
|
||||
integrity sha512-MBYpXdCY1SCdc2u/y11kmJuSODKFyZRpeRTQq5p4rSg05QSjSy5pz6h/BGLNdSahgXfKRBATEkjAcJFdJuDz8Q==
|
||||
"@vscode/vsce@^3.3.0":
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@vscode/vsce/-/vsce-3.3.0.tgz#803e41368a95d35693ce049076503f34f89fde09"
|
||||
integrity sha512-HA/pUyvh/TQWkc4wG7AudPIWUvsR8i4jiWZZgM/a69ncPi9Nm5FDogf/wVEk4EWJs4/UdxU7J6X18dfAwfPbxA==
|
||||
dependencies:
|
||||
"@azure/identity" "^4.1.0"
|
||||
"@vscode/vsce-sign" "^2.0.0"
|
||||
@ -508,19 +493,19 @@
|
||||
chalk "^2.4.2"
|
||||
cheerio "^1.0.0-rc.9"
|
||||
cockatiel "^3.1.2"
|
||||
commander "^6.2.1"
|
||||
commander "^12.1.0"
|
||||
form-data "^4.0.0"
|
||||
glob "^7.0.6"
|
||||
glob "^11.0.0"
|
||||
hosted-git-info "^4.0.2"
|
||||
jsonc-parser "^3.2.0"
|
||||
leven "^3.1.0"
|
||||
markdown-it "^12.3.2"
|
||||
markdown-it "^14.1.0"
|
||||
mime "^1.3.4"
|
||||
minimatch "^3.0.3"
|
||||
parse-semver "^1.1.1"
|
||||
read "^1.0.7"
|
||||
semver "^7.5.2"
|
||||
tmp "^0.2.1"
|
||||
tmp "^0.2.3"
|
||||
typed-rest-client "^1.8.4"
|
||||
url-join "^4.0.1"
|
||||
xml2js "^0.5.0"
|
||||
@ -583,11 +568,6 @@ argparse@^2.0.1:
|
||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
|
||||
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
|
||||
|
||||
array-union@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
|
||||
integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
|
||||
|
||||
asynckit@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||
@ -832,10 +812,10 @@ combined-stream@^1.0.8:
|
||||
dependencies:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
commander@^6.2.1:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
|
||||
integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
|
||||
commander@^12.1.0:
|
||||
version "12.1.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3"
|
||||
integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
@ -932,13 +912,6 @@ diff@^5.2.0:
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531"
|
||||
integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==
|
||||
|
||||
dir-glob@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
|
||||
integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==
|
||||
dependencies:
|
||||
path-type "^4.0.0"
|
||||
|
||||
dom-serializer@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53"
|
||||
@ -1008,11 +981,6 @@ entities@^4.2.0, entities@^4.4.0:
|
||||
resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
|
||||
integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
|
||||
|
||||
entities@~2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5"
|
||||
integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==
|
||||
|
||||
es-define-property@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845"
|
||||
@ -1071,11 +1039,16 @@ escape-string-regexp@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
|
||||
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
|
||||
|
||||
eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3:
|
||||
eslint-visitor-keys@^3.4.3:
|
||||
version "3.4.3"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
|
||||
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
||||
|
||||
eslint-visitor-keys@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45"
|
||||
integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==
|
||||
|
||||
events@^3.0.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
|
||||
@ -1086,7 +1059,7 @@ expand-template@^2.0.3:
|
||||
resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c"
|
||||
integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==
|
||||
|
||||
fast-glob@^3.2.9:
|
||||
fast-glob@^3.3.2:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818"
|
||||
integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==
|
||||
@ -1153,11 +1126,6 @@ fs-constants@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
|
||||
integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
|
||||
|
||||
fsevents@~2.3.2:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
|
||||
@ -1196,7 +1164,7 @@ glob-parent@^5.1.2, glob-parent@~5.1.2:
|
||||
dependencies:
|
||||
is-glob "^4.0.1"
|
||||
|
||||
glob@^10.4.3, glob@^10.4.5:
|
||||
glob@^10.4.5:
|
||||
version "10.4.5"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956"
|
||||
integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==
|
||||
@ -1208,29 +1176,17 @@ glob@^10.4.3, glob@^10.4.5:
|
||||
package-json-from-dist "^1.0.0"
|
||||
path-scurry "^1.11.1"
|
||||
|
||||
glob@^7.0.6:
|
||||
version "7.2.3"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
|
||||
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
|
||||
glob@^11.0.0, glob@^11.0.1:
|
||||
version "11.0.1"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-11.0.1.tgz#1c3aef9a59d680e611b53dcd24bb8639cef064d9"
|
||||
integrity sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.1.1"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
globby@^11.1.0:
|
||||
version "11.1.0"
|
||||
resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
|
||||
integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==
|
||||
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"
|
||||
foreground-child "^3.1.0"
|
||||
jackspeak "^4.0.1"
|
||||
minimatch "^10.0.0"
|
||||
minipass "^7.1.2"
|
||||
package-json-from-dist "^1.0.0"
|
||||
path-scurry "^2.0.0"
|
||||
|
||||
gopd@^1.0.1:
|
||||
version "1.0.1"
|
||||
@ -1321,7 +1277,7 @@ ieee754@^1.1.13, ieee754@^1.2.1:
|
||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
|
||||
|
||||
ignore@^5.2.0, ignore@^5.2.4:
|
||||
ignore@^5.3.1:
|
||||
version "5.3.2"
|
||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5"
|
||||
integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==
|
||||
@ -1331,15 +1287,7 @@ immediate@~3.0.5:
|
||||
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
|
||||
integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==
|
||||
|
||||
inflight@^1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||
integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
|
||||
dependencies:
|
||||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3:
|
||||
inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
@ -1429,6 +1377,13 @@ jackspeak@^3.1.2:
|
||||
optionalDependencies:
|
||||
"@pkgjs/parseargs" "^0.11.0"
|
||||
|
||||
jackspeak@^4.0.1:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-4.1.0.tgz#c489c079f2b636dc4cbe9b0312a13ff1282e561b"
|
||||
integrity sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw==
|
||||
dependencies:
|
||||
"@isaacs/cliui" "^8.0.2"
|
||||
|
||||
js-yaml@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
|
||||
@ -1521,12 +1476,12 @@ lie@~3.3.0:
|
||||
dependencies:
|
||||
immediate "~3.0.5"
|
||||
|
||||
linkify-it@^3.0.1:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.3.tgz#a98baf44ce45a550efb4d49c769d07524cc2fa2e"
|
||||
integrity sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==
|
||||
linkify-it@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-5.0.0.tgz#9ef238bfa6dc70bd8e7f9572b52d369af569b421"
|
||||
integrity sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==
|
||||
dependencies:
|
||||
uc.micro "^1.0.1"
|
||||
uc.micro "^2.0.0"
|
||||
|
||||
locate-path@^6.0.0:
|
||||
version "6.0.0"
|
||||
@ -1591,6 +1546,11 @@ lru-cache@^10.2.0:
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.2.tgz#48206bc114c1252940c41b25b41af5b545aca878"
|
||||
integrity sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==
|
||||
|
||||
lru-cache@^11.0.0:
|
||||
version "11.0.2"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.0.2.tgz#fbd8e7cf8211f5e7e5d91905c415a3f55755ca39"
|
||||
integrity sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==
|
||||
|
||||
lru-cache@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
|
||||
@ -1598,23 +1558,24 @@ lru-cache@^6.0.0:
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
markdown-it@^12.3.2:
|
||||
version "12.3.2"
|
||||
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.3.2.tgz#bf92ac92283fe983fe4de8ff8abfb5ad72cd0c90"
|
||||
integrity sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==
|
||||
markdown-it@^14.1.0:
|
||||
version "14.1.0"
|
||||
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-14.1.0.tgz#3c3c5992883c633db4714ccb4d7b5935d98b7d45"
|
||||
integrity sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==
|
||||
dependencies:
|
||||
argparse "^2.0.1"
|
||||
entities "~2.1.0"
|
||||
linkify-it "^3.0.1"
|
||||
mdurl "^1.0.1"
|
||||
uc.micro "^1.0.5"
|
||||
entities "^4.4.0"
|
||||
linkify-it "^5.0.0"
|
||||
mdurl "^2.0.0"
|
||||
punycode.js "^2.3.1"
|
||||
uc.micro "^2.1.0"
|
||||
|
||||
mdurl@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
|
||||
integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==
|
||||
mdurl@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-2.0.0.tgz#80676ec0433025dd3e17ee983d0fe8de5a2237e0"
|
||||
integrity sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==
|
||||
|
||||
merge2@^1.3.0, merge2@^1.4.1:
|
||||
merge2@^1.3.0:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
|
||||
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
|
||||
@ -1654,14 +1615,14 @@ mimic-response@^3.1.0:
|
||||
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9"
|
||||
integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==
|
||||
|
||||
minimatch@9.0.3:
|
||||
version "9.0.3"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825"
|
||||
integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==
|
||||
minimatch@^10.0.0:
|
||||
version "10.0.1"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.0.1.tgz#ce0521856b453c86e25f2c4c0d03e6ff7ddc440b"
|
||||
integrity sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimatch@^3.0.3, minimatch@^3.1.1:
|
||||
minimatch@^3.0.3:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
@ -1777,7 +1738,7 @@ object-inspect@^1.13.1:
|
||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2"
|
||||
integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==
|
||||
|
||||
once@^1.3.0, once@^1.3.1, once@^1.4.0:
|
||||
once@^1.3.1, once@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||
integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
|
||||
@ -1866,11 +1827,6 @@ path-exists@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
|
||||
integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
|
||||
|
||||
path-is-absolute@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||
integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
|
||||
|
||||
path-key@^3.1.0:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
|
||||
@ -1884,10 +1840,13 @@ path-scurry@^1.11.1:
|
||||
lru-cache "^10.2.0"
|
||||
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
|
||||
|
||||
path-type@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
|
||||
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
|
||||
path-scurry@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-2.0.0.tgz#9f052289f23ad8bf9397a2a0425e7b8615c58580"
|
||||
integrity sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==
|
||||
dependencies:
|
||||
lru-cache "^11.0.0"
|
||||
minipass "^7.1.2"
|
||||
|
||||
pend@~1.2.0:
|
||||
version "1.2.0"
|
||||
@ -1930,6 +1889,11 @@ pump@^3.0.0:
|
||||
end-of-stream "^1.1.0"
|
||||
once "^1.3.1"
|
||||
|
||||
punycode.js@^2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/punycode.js/-/punycode.js-2.3.1.tgz#6b53e56ad75588234e79f4affa90972c7dd8cdb7"
|
||||
integrity sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==
|
||||
|
||||
qs@^6.9.1:
|
||||
version "6.12.1"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.12.1.tgz#39422111ca7cbdb70425541cba20c7d7b216599a"
|
||||
@ -2040,10 +2004,10 @@ semver@^5.1.0:
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
|
||||
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
|
||||
|
||||
semver@^7.3.5, semver@^7.3.7, semver@^7.5.2, semver@^7.5.4, semver@^7.6.2:
|
||||
version "7.6.2"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13"
|
||||
integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==
|
||||
semver@^7.3.5, semver@^7.3.7, semver@^7.5.2, semver@^7.5.4, semver@^7.6.0, semver@^7.6.2:
|
||||
version "7.7.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f"
|
||||
integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==
|
||||
|
||||
serialize-javascript@^6.0.2:
|
||||
version "6.0.2"
|
||||
@ -2115,11 +2079,6 @@ simple-get@^4.0.0:
|
||||
once "^1.3.1"
|
||||
simple-concat "^1.0.0"
|
||||
|
||||
slash@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
|
||||
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
|
||||
|
||||
stdin-discarder@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/stdin-discarder/-/stdin-discarder-0.1.0.tgz#22b3e400393a8e28ebf53f9958f3880622efde21"
|
||||
@ -2255,7 +2214,7 @@ tar-stream@^2.1.4:
|
||||
inherits "^2.0.3"
|
||||
readable-stream "^3.1.1"
|
||||
|
||||
tmp@^0.2.1:
|
||||
tmp@^0.2.3:
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae"
|
||||
integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==
|
||||
@ -2267,10 +2226,10 @@ to-regex-range@^5.0.1:
|
||||
dependencies:
|
||||
is-number "^7.0.0"
|
||||
|
||||
ts-api-utils@^1.0.1:
|
||||
version "1.4.3"
|
||||
resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.4.3.tgz#bfc2215fe6528fecab2b0fba570a2e8a4263b064"
|
||||
integrity sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==
|
||||
ts-api-utils@^2.0.1:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.1.0.tgz#595f7094e46eed364c13fd23e75f9513d29baf91"
|
||||
integrity sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==
|
||||
|
||||
tslib@^2.2.0, tslib@^2.6.2:
|
||||
version "2.6.2"
|
||||
@ -2303,10 +2262,10 @@ typescript@^5.8.2:
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.2.tgz#8170b3702f74b79db2e5a96207c15e65807999e4"
|
||||
integrity sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==
|
||||
|
||||
uc.micro@^1.0.1, uc.micro@^1.0.5:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac"
|
||||
integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==
|
||||
uc.micro@^2.0.0, uc.micro@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-2.1.0.tgz#f8d3f7d0ec4c3dea35a7e3c8efa4cb8b45c9e7ee"
|
||||
integrity sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==
|
||||
|
||||
underscore@^1.12.1:
|
||||
version "1.13.6"
|
||||
|
@ -86,8 +86,16 @@ function ProjectCard({
|
||||
>
|
||||
<Link
|
||||
data-testid="project-link"
|
||||
to={`${PATHS.FILE}/${encodeURIComponent(project.default_file)}`}
|
||||
className="flex flex-col flex-1 !no-underline !text-chalkboard-110 dark:!text-chalkboard-10 group-hover:!hue-rotate-0 min-h-[5em] divide-y divide-primary/40 dark:divide-chalkboard-80 group-hover:!divide-primary"
|
||||
to={
|
||||
project.readWriteAccess
|
||||
? `${PATHS.FILE}/${encodeURIComponent(project.default_file)}`
|
||||
: ''
|
||||
}
|
||||
className={`flex flex-col flex-1 !no-underline !text-chalkboard-110 dark:!text-chalkboard-10 min-h-[5em] divide-y divide-primary/40 dark:divide-chalkboard-80 ${
|
||||
project.readWriteAccess
|
||||
? 'group-hover:!divide-primary group-hover:!hue-rotate-0'
|
||||
: 'cursor-not-allowed'
|
||||
}`}
|
||||
>
|
||||
<div className="h-36 relative overflow-hidden bg-gradient-to-b from-transparent to-primary/10 rounded-t-sm">
|
||||
{imageUrl && (
|
||||
@ -116,19 +124,21 @@ function ProjectCard({
|
||||
{project.name?.replace(FILE_EXT, '')}
|
||||
</h3>
|
||||
)}
|
||||
<span className="px-2 text-chalkboard-60 text-xs">
|
||||
<span data-testid="project-file-count">{numberOfFiles}</span> file
|
||||
{numberOfFiles === 1 ? '' : 's'}{' '}
|
||||
{numberOfFolders > 0 && (
|
||||
<>
|
||||
{'/ '}
|
||||
<span data-testid="project-folder-count">
|
||||
{numberOfFolders}
|
||||
</span>{' '}
|
||||
folder{numberOfFolders === 1 ? '' : 's'}
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
{project.readWriteAccess && (
|
||||
<span className="px-2 text-chalkboard-60 text-xs">
|
||||
<span data-testid="project-file-count">{numberOfFiles}</span> file
|
||||
{numberOfFiles === 1 ? '' : 's'}{' '}
|
||||
{numberOfFolders > 0 && (
|
||||
<>
|
||||
{'/ '}
|
||||
<span data-testid="project-folder-count">
|
||||
{numberOfFolders}
|
||||
</span>{' '}
|
||||
folder{numberOfFolders === 1 ? '' : 's'}
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
<span className="px-2 text-chalkboard-60 text-xs">
|
||||
Edited{' '}
|
||||
<span data-testid="project-edit-date">
|
||||
@ -145,6 +155,7 @@ function ProjectCard({
|
||||
data-edit-buttons-for={project.name?.replace(FILE_EXT, '')}
|
||||
>
|
||||
<ActionButton
|
||||
disabled={!project.readWriteAccess}
|
||||
Element="button"
|
||||
iconStart={{
|
||||
icon: 'sketch',
|
||||
@ -163,6 +174,7 @@ function ProjectCard({
|
||||
</Tooltip>
|
||||
</ActionButton>
|
||||
<ActionButton
|
||||
disabled={!project.readWriteAccess}
|
||||
Element="button"
|
||||
iconStart={{
|
||||
icon: 'trash',
|
||||
|
@ -14,6 +14,7 @@ const projectWellFormed = {
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
readWriteAccess: true,
|
||||
metadata: {
|
||||
created: now.toISOString(),
|
||||
modified: now.toISOString(),
|
||||
|
@ -137,6 +137,7 @@ const ProjectsContextWeb = ({ children }: { children: React.ReactNode }) => {
|
||||
projects: [],
|
||||
defaultProjectName: settings.projects.defaultProjectName.current,
|
||||
defaultDirectory: settings.app.projectDirectory.current,
|
||||
hasListedProjects: false,
|
||||
},
|
||||
}
|
||||
)
|
||||
@ -182,20 +183,11 @@ const ProjectsContextDesktop = ({
|
||||
}, [searchParams, setSearchParams])
|
||||
const { onProjectOpen } = useLspContext()
|
||||
const settings = useSettings()
|
||||
|
||||
const [projectsLoaderTrigger, setProjectsLoaderTrigger] = useState(0)
|
||||
const { projectPaths, projectsDir } = useProjectsLoader([
|
||||
projectsLoaderTrigger,
|
||||
])
|
||||
|
||||
// Re-read projects listing if the projectDir has any updates.
|
||||
useFileSystemWatcher(
|
||||
async () => {
|
||||
return setProjectsLoaderTrigger(projectsLoaderTrigger + 1)
|
||||
},
|
||||
projectsDir ? [projectsDir] : []
|
||||
)
|
||||
|
||||
const [state, send, actor] = useMachine(
|
||||
projectsMachine.provide({
|
||||
actions: {
|
||||
@ -313,7 +305,9 @@ const ProjectsContextDesktop = ({
|
||||
),
|
||||
},
|
||||
actors: {
|
||||
readProjects: fromPromise(() => listProjects()),
|
||||
readProjects: fromPromise(() => {
|
||||
return listProjects()
|
||||
}),
|
||||
createProject: fromPromise(async ({ input }) => {
|
||||
let name = (
|
||||
input && 'name' in input && input.name
|
||||
@ -427,13 +421,33 @@ const ProjectsContextDesktop = ({
|
||||
projects: projectPaths,
|
||||
defaultProjectName: settings.projects.defaultProjectName.current,
|
||||
defaultDirectory: settings.app.projectDirectory.current,
|
||||
hasListedProjects: false,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
useFileSystemWatcher(
|
||||
async () => {
|
||||
// Gotcha: Chokidar is buggy. It will emit addDir or add on files that did not get created.
|
||||
// This means while the application initialize and Chokidar initializes you cannot tell if
|
||||
// a directory or file is actually created or they are buggy signals. This means you must
|
||||
// ignore all signals during initialization because it is ambiguous. Once those signals settle
|
||||
// you can actually start listening to real signals.
|
||||
// If someone creates folders or files during initialization we ignore those events!
|
||||
if (!actor.getSnapshot().context.hasListedProjects) {
|
||||
return
|
||||
}
|
||||
return setProjectsLoaderTrigger(projectsLoaderTrigger + 1)
|
||||
},
|
||||
projectsDir ? [projectsDir] : []
|
||||
)
|
||||
|
||||
// Gotcha: Triggers listProjects() on chokidar changes
|
||||
// Gotcha: Load the projects when the projectDirectory changes.
|
||||
const projectDirectory = settings.app.projectDirectory.current
|
||||
useEffect(() => {
|
||||
send({ type: 'Read projects', data: {} })
|
||||
}, [projectPaths])
|
||||
}, [projectPaths, projectDirectory])
|
||||
|
||||
// register all project-related command palette commands
|
||||
useStateMachineCommands({
|
||||
|
@ -5,6 +5,8 @@ import { loadAndValidateSettings } from 'lib/settings/settingsUtils'
|
||||
import { Project } from 'lib/project'
|
||||
import { isDesktop } from 'lib/isDesktop'
|
||||
|
||||
// Gotcha: This should be ported to the ProjectMachine and keep track of
|
||||
// projectDirs and projectPaths in the context when it internally calls listProjects
|
||||
// Hook uses [number] to give users familiarity. It is meant to mimic a
|
||||
// dependency array, but is intended to only ever be used with 1 value.
|
||||
export const useProjectsLoader = (deps?: [number]) => {
|
||||
|
@ -25,6 +25,7 @@ const mockElectron = {
|
||||
},
|
||||
getPath: vi.fn(),
|
||||
kittycad: vi.fn(),
|
||||
canReadWriteDirectory: vi.fn(),
|
||||
}
|
||||
|
||||
vi.stubGlobal('window', { electron: mockElectron })
|
||||
@ -87,6 +88,12 @@ describe('desktop utilities', () => {
|
||||
return path in mockFileSystem
|
||||
})
|
||||
|
||||
mockElectron.canReadWriteDirectory.mockImplementation(
|
||||
async (path: string) => {
|
||||
return { value: path in mockFileSystem, error: undefined }
|
||||
}
|
||||
)
|
||||
|
||||
// Mock stat to always resolve with dummy metadata
|
||||
mockElectron.stat.mockResolvedValue({
|
||||
mtimeMs: 123,
|
||||
|
@ -126,6 +126,8 @@ export async function createNewProjectDirectory(
|
||||
metadata,
|
||||
kcl_file_count: 1,
|
||||
directory_count: 0,
|
||||
// If the mkdir did not crash you have readWriteAccess
|
||||
readWriteAccess: true,
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,7 +152,12 @@ export async function listProjects(
|
||||
const projects = []
|
||||
if (!projectDir) return Promise.reject(new Error('projectDir was falsey'))
|
||||
|
||||
// Gotcha: readdir will list all folders at this project directory even if you do not have readwrite access on the directory path
|
||||
const entries = await window.electron.readdir(projectDir)
|
||||
|
||||
const { value: canReadWriteProjectDirectory } =
|
||||
await window.electron.canReadWriteDirectory(projectDir)
|
||||
|
||||
for (let entry of entries) {
|
||||
// Skip directories that start with a dot
|
||||
if (entry.startsWith('.')) {
|
||||
@ -158,19 +165,28 @@ export async function listProjects(
|
||||
}
|
||||
|
||||
const projectPath = window.electron.path.join(projectDir, entry)
|
||||
|
||||
// if it's not a directory ignore.
|
||||
// Gotcha: statIsDirectory will work even if you do not have read write permissions on the project path
|
||||
const isDirectory = await window.electron.statIsDirectory(projectPath)
|
||||
if (!isDirectory) {
|
||||
continue
|
||||
}
|
||||
|
||||
const project = await getProjectInfo(projectPath)
|
||||
// Needs at least one file to be added to the projects list
|
||||
if (project.kcl_file_count === 0) {
|
||||
|
||||
if (
|
||||
project.kcl_file_count === 0 &&
|
||||
project.readWriteAccess &&
|
||||
canReadWriteProjectDirectory
|
||||
) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Push folders you cannot readWrite to show users the issue
|
||||
projects.push(project)
|
||||
}
|
||||
|
||||
return projects
|
||||
}
|
||||
|
||||
@ -185,7 +201,10 @@ const IMPORT_FILE_EXTENSIONS = [
|
||||
const isRelevantFile = (filename: string): boolean =>
|
||||
IMPORT_FILE_EXTENSIONS.some((ext) => filename.endsWith('.' + ext))
|
||||
|
||||
const collectAllFilesRecursiveFrom = async (path: string) => {
|
||||
const collectAllFilesRecursiveFrom = async (
|
||||
path: string,
|
||||
canReadWritePath: boolean
|
||||
) => {
|
||||
// Make sure the filesystem object exists.
|
||||
try {
|
||||
await window.electron.stat(path)
|
||||
@ -202,12 +221,18 @@ const collectAllFilesRecursiveFrom = async (path: string) => {
|
||||
}
|
||||
|
||||
const name = window.electron.path.basename(path)
|
||||
|
||||
let entry: FileEntry = {
|
||||
name: name,
|
||||
path,
|
||||
children: [],
|
||||
}
|
||||
|
||||
// If you cannot read/write this project path do not collect the files
|
||||
if (!canReadWritePath) {
|
||||
return entry
|
||||
}
|
||||
|
||||
const children = []
|
||||
|
||||
const entries = await window.electron.readdir(path)
|
||||
@ -234,7 +259,10 @@ const collectAllFilesRecursiveFrom = async (path: string) => {
|
||||
const isEDir = await window.electron.statIsDirectory(ePath)
|
||||
|
||||
if (isEDir) {
|
||||
const subChildren = await collectAllFilesRecursiveFrom(ePath)
|
||||
const subChildren = await collectAllFilesRecursiveFrom(
|
||||
ePath,
|
||||
canReadWritePath
|
||||
)
|
||||
children.push(subChildren)
|
||||
} else {
|
||||
if (!isRelevantFile(ePath)) {
|
||||
@ -343,15 +371,31 @@ export async function getProjectInfo(projectPath: string): Promise<Project> {
|
||||
|
||||
// Make sure it is a directory.
|
||||
const projectPathIsDir = await window.electron.statIsDirectory(projectPath)
|
||||
|
||||
if (!projectPathIsDir) {
|
||||
return Promise.reject(
|
||||
new Error(`Project path is not a directory: ${projectPath}`)
|
||||
)
|
||||
}
|
||||
let walked = await collectAllFilesRecursiveFrom(projectPath)
|
||||
let default_file = await getDefaultKclFileForDir(projectPath, walked)
|
||||
|
||||
// Detect the projectPath has read write permission
|
||||
const { value: canReadWriteProjectPath } =
|
||||
await window.electron.canReadWriteDirectory(projectPath)
|
||||
const metadata = await window.electron.stat(projectPath)
|
||||
|
||||
// Return walked early if canReadWriteProjectPath is false
|
||||
let walked = await collectAllFilesRecursiveFrom(
|
||||
projectPath,
|
||||
canReadWriteProjectPath
|
||||
)
|
||||
|
||||
// If the projectPath does not have read write permissions, the default_file is empty string
|
||||
let default_file = ''
|
||||
if (canReadWriteProjectPath) {
|
||||
// Create the default main.kcl file only if the project path has read write permissions
|
||||
default_file = await getDefaultKclFileForDir(projectPath, walked)
|
||||
}
|
||||
|
||||
let project = {
|
||||
...walked,
|
||||
// We need to map from node fs.Stats to FileMetadata
|
||||
@ -368,6 +412,7 @@ export async function getProjectInfo(projectPath: string): Promise<Project> {
|
||||
kcl_file_count: 0,
|
||||
directory_count: 0,
|
||||
default_file,
|
||||
readWriteAccess: canReadWriteProjectPath,
|
||||
}
|
||||
|
||||
// Populate the number of KCL files in the project.
|
||||
|
1
src/lib/project.d.ts
vendored
@ -43,4 +43,5 @@ export type Project = {
|
||||
path: string
|
||||
name: string
|
||||
children: Array<FileEntry> | null
|
||||
readWriteAccess: boolean
|
||||
}
|
||||
|
@ -98,6 +98,7 @@ export const fileLoader: LoaderFunction = async (
|
||||
directory_count: 0,
|
||||
metadata: null,
|
||||
default_file: projectPath,
|
||||
readWriteAccess: true,
|
||||
}
|
||||
|
||||
const maybeProjectInfo = isDesktop()
|
||||
@ -143,6 +144,7 @@ export const fileLoader: LoaderFunction = async (
|
||||
directory_count: 0,
|
||||
kcl_file_count: 1,
|
||||
metadata: null,
|
||||
readWriteAccess: true,
|
||||
}
|
||||
|
||||
// Fire off the event to load the project settings
|
||||
|
@ -9,6 +9,7 @@ export const projectsMachine = setup({
|
||||
projects: Project[]
|
||||
defaultProjectName: string
|
||||
defaultDirectory: string
|
||||
hasListedProjects: boolean
|
||||
},
|
||||
events: {} as
|
||||
| { type: 'Read projects'; data: {} }
|
||||
@ -55,6 +56,7 @@ export const projectsMachine = setup({
|
||||
projects: Project[]
|
||||
defaultProjectName: string
|
||||
defaultDirectory: string
|
||||
hasListedProjects: boolean
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
@ -64,6 +66,9 @@ export const projectsMachine = setup({
|
||||
? event.output
|
||||
: context.projects,
|
||||
}),
|
||||
setHasListedProjects: assign({
|
||||
hasListedProjects: () => true,
|
||||
}),
|
||||
toastSuccess: () => {},
|
||||
toastError: () => {},
|
||||
navigateToProject: () => {},
|
||||
@ -128,7 +133,6 @@ export const projectsMachine = setup({
|
||||
actions: assign(({ event }) => ({
|
||||
...event.data,
|
||||
})),
|
||||
target: '.Reading projects',
|
||||
},
|
||||
|
||||
'Import file from URL': '.Creating file',
|
||||
@ -281,11 +285,11 @@ export const projectsMachine = setup({
|
||||
{
|
||||
guard: 'Has at least 1 project',
|
||||
target: 'Has projects',
|
||||
actions: ['setProjects'],
|
||||
actions: ['setProjects', 'setHasListedProjects'],
|
||||
},
|
||||
{
|
||||
target: 'Has no projects',
|
||||
actions: ['setProjects'],
|
||||
actions: ['setProjects', 'setHasListedProjects'],
|
||||
},
|
||||
],
|
||||
onError: [
|
||||
|
@ -98,14 +98,40 @@ const rename = (prev: string, next: string) => fs.rename(prev, next)
|
||||
const writeFile = (path: string, data: string | Uint8Array) =>
|
||||
fs.writeFile(path, data, 'utf-8')
|
||||
const readdir = (path: string) => fs.readdir(path, 'utf-8')
|
||||
const stat = (path: string) =>
|
||||
fs.stat(path).catch((e) => Promise.reject(e.code))
|
||||
const stat = (path: string) => {
|
||||
return fs.stat(path).catch((e) => Promise.reject(e.code))
|
||||
}
|
||||
|
||||
// Electron has behavior where it doesn't clone the prototype chain over.
|
||||
// So we need to call stat.isDirectory on this side.
|
||||
const statIsDirectory = (path: string) =>
|
||||
stat(path).then((res) => res.isDirectory())
|
||||
const getPath = async (name: string) => ipcRenderer.invoke('app.getPath', name)
|
||||
|
||||
const canReadWriteDirectory = async (
|
||||
path: string
|
||||
): Promise<{ value: boolean; error: unknown } | Error> => {
|
||||
const isDirectory = await statIsDirectory(path)
|
||||
if (!isDirectory) {
|
||||
return new Error('path is not a directory. Do not send a file path.')
|
||||
}
|
||||
|
||||
// bitwise OR to check read and write permissions
|
||||
try {
|
||||
const canReadWrite = await fs.access(
|
||||
path,
|
||||
fs.constants.R_OK | fs.constants.W_OK
|
||||
)
|
||||
// This function returns undefined. If it cannot access the path it will throw an error
|
||||
return canReadWrite === undefined
|
||||
? { value: true, error: undefined }
|
||||
: { value: false, error: undefined }
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
return { value: false, error: e }
|
||||
}
|
||||
}
|
||||
|
||||
const exposeProcessEnvs = (varNames: Array<string>) => {
|
||||
const envs: Record<string, string> = {}
|
||||
varNames.forEach((varName) => {
|
||||
@ -211,4 +237,5 @@ contextBridge.exposeInMainWorld('electron', {
|
||||
appCheckForUpdates,
|
||||
getArgvParsed,
|
||||
resizeWindow,
|
||||
canReadWriteDirectory,
|
||||
})
|
||||
|
@ -19,19 +19,23 @@ import { LowerRightControls } from 'components/LowerRightControls'
|
||||
import { ProjectSearchBar, useProjectSearch } from 'components/ProjectSearchBar'
|
||||
import { Project } from 'lib/project'
|
||||
import { markOnce } from 'lib/performance'
|
||||
import { useFileSystemWatcher } from 'hooks/useFileSystemWatcher'
|
||||
import { useProjectsLoader } from 'hooks/useProjectsLoader'
|
||||
import { useProjectsContext } from 'hooks/useProjectsContext'
|
||||
import { commandBarActor } from 'machines/commandBarMachine'
|
||||
import { useCreateFileLinkQuery } from 'hooks/useCreateFileLinkQueryWatcher'
|
||||
import { useSettings } from 'machines/appMachine'
|
||||
import { reportRejection } from 'lib/trap'
|
||||
|
||||
// This route only opens in the desktop context for now,
|
||||
// as defined in Router.tsx, so we can use the desktop APIs and types.
|
||||
const Home = () => {
|
||||
const { state, send } = useProjectsContext()
|
||||
const [projectsLoaderTrigger, setProjectsLoaderTrigger] = useState(0)
|
||||
const { projectsDir } = useProjectsLoader([projectsLoaderTrigger])
|
||||
const [readWriteProjectDir, setReadWriteProjectDir] = useState<{
|
||||
value: boolean
|
||||
error: unknown
|
||||
}>({
|
||||
value: true,
|
||||
error: undefined,
|
||||
})
|
||||
|
||||
// Keep a lookout for a URL query string that invokes the 'import file from URL' command
|
||||
useCreateFileLinkQuery((argDefaultValues) => {
|
||||
@ -66,14 +70,6 @@ const Home = () => {
|
||||
)
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
|
||||
// Re-read projects listing if the projectDir has any updates.
|
||||
useFileSystemWatcher(
|
||||
async () => {
|
||||
setProjectsLoaderTrigger(projectsLoaderTrigger + 1)
|
||||
},
|
||||
projectsDir ? [projectsDir] : []
|
||||
)
|
||||
|
||||
const projects = state?.context.projects ?? []
|
||||
const [searchParams, setSearchParams] = useSearchParams()
|
||||
const { searchResults, query, setQuery } = useProjectSearch(projects)
|
||||
@ -91,6 +87,16 @@ const Home = () => {
|
||||
defaultDirectory: settings.app.projectDirectory.current,
|
||||
},
|
||||
})
|
||||
|
||||
// Must be a truthy string, not '' or null or undefined
|
||||
if (settings.app.projectDirectory.current) {
|
||||
window.electron
|
||||
.canReadWriteDirectory(settings.app.projectDirectory.current)
|
||||
.then((res) => {
|
||||
setReadWriteProjectDir(res)
|
||||
})
|
||||
.catch(reportRejection)
|
||||
}
|
||||
}, [
|
||||
settings.app.projectDirectory.current,
|
||||
settings.projects.defaultProjectName.current,
|
||||
@ -124,6 +130,18 @@ const Home = () => {
|
||||
data: { name: project.name || '' },
|
||||
})
|
||||
}
|
||||
/** Type narrowing function of unknown error to a string */
|
||||
function errorMessage(error: unknown): string {
|
||||
if (error != undefined && error instanceof Error) {
|
||||
return error.message
|
||||
} else if (error && typeof error === 'object') {
|
||||
return JSON.stringify(error)
|
||||
} else if (typeof error === 'string') {
|
||||
return error
|
||||
} else {
|
||||
return 'Unknown error'
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="relative flex flex-col h-screen overflow-hidden" ref={ref}>
|
||||
@ -219,6 +237,22 @@ const Home = () => {
|
||||
</Link>
|
||||
.
|
||||
</p>
|
||||
{!readWriteProjectDir.value && (
|
||||
<section>
|
||||
<div className="flex items-center select-none">
|
||||
<div className="flex gap-8 items-center justify-between grow bg-destroy-80 text-white py-1 px-4 my-2 rounded-sm grow">
|
||||
<p className="">{errorMessage(readWriteProjectDir.error)}</p>
|
||||
<Link
|
||||
data-testid="project-directory-settings-link"
|
||||
to={`${PATHS.HOME + PATHS.SETTINGS_USER}#projectDirectory`}
|
||||
className="py-1 text-white underline underline-offset-2 text-sm"
|
||||
>
|
||||
Change Project Directory
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
</section>
|
||||
<section
|
||||
data-testid="home-section"
|
||||
|
@ -48,7 +48,9 @@ const config = defineConfig({
|
||||
mockReset: true,
|
||||
reporters: process.env.GITHUB_ACTIONS
|
||||
? ['dot', 'github-actions']
|
||||
: ['verbose', 'hanging-process'],
|
||||
: // Gotcha: 'hanging-process' is very noisey, turn off by default on localhost
|
||||
// : ['verbose', 'hanging-process'],
|
||||
['verbose'],
|
||||
testTimeout: 1000,
|
||||
hookTimeout: 1000,
|
||||
teardownTimeout: 1000,
|
||||
|