diff --git a/.vscode-test.js b/.vscode-test.js new file mode 100644 index 0000000..76a1b16 --- /dev/null +++ b/.vscode-test.js @@ -0,0 +1,4 @@ +// https://code.visualstudio.com/api/working-with-extensions/testing-extension +const { defineConfig } = require('@vscode/test-cli'); + +module.exports = defineConfig({ files: 'out/test/**/*.test.js' }); \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 198d0dc..c8bb013 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -15,7 +15,7 @@ "editor.formatOnType": true, // tell the ESLint plugin to run on save "editor.codeActionsOnSave": { - "source.fixAll": true + "source.fixAll": "explicit" }, }, "cSpell.words": ["cedarentities", "cedarlanguage", "cedarschema", "vsix"], diff --git a/CHANGELOG.md b/CHANGELOG.md index e719dae..38d50fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## v0.5.4 (Preview) 2023-12-18 + +- Update to Cedar 2.4.2 +- Add JSON export of Cedar policies +- Require Visual Studio Code version [1.82](https://code.visualstudio.com/updates/v1_82) or later + ## v0.5.3 (Preview) 2023-10-16 - Update to Cedar 2.4.1 diff --git a/Dockerfile b/Dockerfile index 8afcfce..a0fd754 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:16 +FROM node:18 RUN apt-get -y update RUN apt-get -y install --fix-missing xvfb RUN apt-get -y install libnss3 libatk1.0-0 libatk-bridge2.0-0 libgtk-3-0 libgbm-dev libasound2 diff --git a/README.md b/README.md index 2ca8d48..8ca2502 100644 --- a/README.md +++ b/README.md @@ -8,22 +8,26 @@ Cedar is a language for writing authorization policies and making authorization ### Cedar policy language -Files matching `*.cedar` are detected as a Cedar policy language and receive syntax highlighting. Validation is performed on document open, document save, during formatting, and via context menu. Formatting can disabled per file using a leading comment line of `// @formatter:off`. Policy navigation using Outline or Breadcrumb. +Files matching `*.cedar` are detected as a Cedar policy language and receive syntax highlighting. Validation is performed on document open, document save, during formatting, and via context menu. Formatting can disabled per file using a leading comment line of `// @formatter:off`. Policy navigation using Outline or Breadcrumb. "Go to Definition" on Cedar entity types and action names. Policies exportable to their JSON representation. ![Cedar policy validation and navigation](https://raw.githubusercontent.com/cedar-policy/vscode-cedar/main/docs/marketplace/cedar_policy.gif) ### Cedar schema -Files named `cedarschema.json` or matching `*.cedarschema.json` are detected as a Cedar schema and receive additional syntax highlighting. Validation is performed on document open, document save, and via context menu. When a Cedar schema file is detected or configured in [Settings](#settings), additional validation of Cedar files uses that schema. Entity type navigation using Outline or Breadcrumb. +Files named `cedarschema.json` or matching `*.cedarschema.json` are detected as a Cedar schema and receive additional syntax highlighting. Validation is performed on document open, document save, and via context menu. When a Cedar schema file is detected or configured in [Settings](#settings), additional validation of Cedar files uses that schema. Entity type navigation using Outline or Breadcrumb. "Go to Definition" on Cedar entity types and action names. ![Cedar schema validation and navigation](https://raw.githubusercontent.com/cedar-policy/vscode-cedar/main/docs/marketplace/cedar_schema.gif) ### Cedar entities -Files named `cedarentities.json` or matching `*.cedarentities.json` are detected as Cedar entities and receive additional syntax highlighting. Validation is performed against a Cedar schema on document open, document save, and via context menu. Entity navigation using Outline or Breadcrumb. +Files named `cedarentities.json` or matching `*.cedarentities.json` are detected as Cedar entities and receive additional syntax highlighting. Validation is performed against a Cedar schema on document open, document save, and via context menu. Entity navigation using Outline or Breadcrumb. "Go to Definition" on Cedar entity types. ![Cedar entities validation and navigation](https://raw.githubusercontent.com/cedar-policy/vscode-cedar/main/docs/marketplace/cedar_entities.gif) +### Cedar CLI + +Various commands of the `cedar` CLI take JSON formatted file inputs. Files named `cedarauth.json` or matching `*.cedarauth.json` are detected as input to the `--request-json` option for the `authorize` command. Files named `cedartemplatelinks.json` or matching `*.cedartemplatelinks.json` are detected as input to the `--template-linked` option for the `authorize` command. These files receive additional syntax highlighting. + ### Markdown Syntax highlighting of `cedar` code fence blocks within markdown (`*.md`) files. diff --git a/development.md b/development.md index e923a4f..65b5c04 100644 --- a/development.md +++ b/development.md @@ -73,9 +73,9 @@ Then run the `package` command to create the .vsix file. npm run package ``` -### Docker +### Container Testing -To build and run tests in a clean environment, first build the container, then open a bash shell in the container. +To build and run tests in a clean environment, first build the container, then open a bash shell in the container. The CLI commands below use `docker`, but are compatible with the [`Finch`](https://github.com/runfinch/finch) open source client for container development. ```bash docker build . -t cedar-policy/vscode-cedar @@ -93,7 +93,7 @@ Then build and test the extension inside the container. This will take several This extension can locally be installed to `~/.vscode/extensions` using the command palette and selecting **Extensions: Install from VSIX...** or running the following [Visual Studio Code command-line interface](https://code.visualstudio.com/docs/editor/command-line) command (see link if `code` is not in your PATH): ```bash -code --install-extension vscode-cedar-0.5.3.vsix +code --install-extension vscode-cedar-0.5.4.vsix ``` Note: Preview install may see a `[DEP0005] DeprecationWarning` tracked in GitHub issue [install-extension command throws Buffer deprecated warning #82524](https://github.com/microsoft/vscode/issues/82524) diff --git a/package-lock.json b/package-lock.json index bf9fdab..5ff5cf0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,34 +1,33 @@ { "name": "vscode-cedar", - "version": "0.5.3", + "version": "0.5.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "vscode-cedar", - "version": "0.5.3", + "version": "0.5.4", "license": "Apache-2.0", "dependencies": { "jsonc-parser": "^3.2.0", "vscode-cedar-wasm": "file:vscode-cedar-wasm/pkg" }, "devDependencies": { - "@types/glob": "^8.1.0", - "@types/mocha": "^10.0.2", - "@types/node": "^16.18.58", - "@types/vscode": "=1.77.0", + "@types/mocha": "^10.0.6", + "@types/node": "^18.19.3", + "@types/vscode": "=1.82.0", "@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/parser": "^5.62.0", - "@vscode/test-electron": "^2.3.5", - "@vscode/vsce": "^2.21.1", - "eslint": "^8.51.0", - "glob": "^8.1.0", + "@vscode/test-cli": "^0.0.4", + "@vscode/test-electron": "^2.3.8", + "@vscode/vsce": "^2.22.0", + "eslint": "^8.56.0", "js-yaml": "^4.1.0", "mocha": "^10.2.0", "typescript": "^4.9.5" }, "engines": { - "vscode": "^1.77.0" + "vscode": "^1.82.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -56,18 +55,18 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.1.tgz", - "integrity": "sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -87,22 +86,44 @@ "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, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "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, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@eslint/js": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz", - "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", - "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", + "@humanwhocodes/object-schema": "^2.0.1", "debug": "^4.1.1", "minimatch": "^3.0.5" }, @@ -110,6 +131,28 @@ "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/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, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/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, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -124,11 +167,55 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -164,6 +251,16 @@ "node": ">= 8" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -173,50 +270,37 @@ "node": ">= 6" } }, - "node_modules/@types/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==", - "dev": true, - "dependencies": { - "@types/minimatch": "^5.1.2", - "@types/node": "*" - } - }, "node_modules/@types/json-schema": { - "version": "7.0.13", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz", - "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==", - "dev": true - }, - "node_modules/@types/minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "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 }, "node_modules/@types/mocha": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.2.tgz", - "integrity": "sha512-NaHL0+0lLNhX6d9rs+NSt97WH/gIlRHmszXbQ/8/MV/eVcFNdeJ/GYhrFuUc8K7WuPhRhTSdMkCp8VMzhUq85w==", + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", + "integrity": "sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==", "dev": true }, "node_modules/@types/node": { - "version": "16.18.58", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.58.tgz", - "integrity": "sha512-YGncyA25/MaVtQkjWW9r0EFBukZ+JulsLcVZBlGUfIb96OBMjkoRWwQo5IEWJ8Fj06Go3GHw+bjYDitv6BaGsA==", - "dev": true + "version": "18.19.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.3.tgz", + "integrity": "sha512-k5fggr14DwAytoA/t8rPrIz++lXK7/DqckthCmoZOKNsEbJkId4Z//BqgApXBUGrGddrigYa1oqheo/7YmW4rg==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==", + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", "dev": true }, "node_modules/@types/vscode": { - "version": "1.77.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.77.0.tgz", - "integrity": "sha512-MWFN5R7a33n8eJZJmdVlifjig3LWUNRrPeO1xemIcZ0ae0TEQuRc7G2xV0LUX78RZFECY1plYBn+dP/Acc3L0Q==", + "version": "1.82.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.82.0.tgz", + "integrity": "sha512-VSHV+VnpF8DEm8LNrn8OJ8VuUNcBzN3tMvKrNpbhhfuVjFm82+6v44AbDhLvVFgCzn6vs94EJNTp7w8S6+Q1Rw==", "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { @@ -407,10 +491,34 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/@vscode/test-cli": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@vscode/test-cli/-/test-cli-0.0.4.tgz", + "integrity": "sha512-Tx0tfbxeSb2Xlo+jpd+GJrNLgKQHobhRHrYvOipZRZQYWZ82sKiK02VY09UjU1Czc/YnZnqyAnjUfaVGl3h09w==", + "dev": true, + "dependencies": { + "@types/mocha": "^10.0.2", + "chokidar": "^3.5.3", + "glob": "^10.3.10", + "minimatch": "^9.0.3", + "mocha": "^10.2.0", + "supports-color": "^9.4.0", + "yargs": "^17.7.2" + }, + "bin": { + "vscode-test": "out/bin.mjs" + } + }, "node_modules/@vscode/test-electron": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.5.tgz", - "integrity": "sha512-lAW7nQ0HuPqJnGJrtCzEKZCICtRizeP6qNanyCrjmdCOAAWjX3ixiG8RVPwqsYPQBWLPgYuE12qQlwXsOR/2fQ==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.8.tgz", + "integrity": "sha512-b4aZZsBKtMGdDljAsOPObnAi7+VWIaYl3ylCz1jTs+oV6BZ4TNHcVNC3xUn0azPeszBmwSBDQYfFESIaUQnrOg==", "dev": true, "dependencies": { "http-proxy-agent": "^4.0.1", @@ -423,9 +531,9 @@ } }, "node_modules/@vscode/vsce": { - "version": "2.21.1", - "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.21.1.tgz", - "integrity": "sha512-f45/aT+HTubfCU2oC7IaWnH9NjOWp668ML002QiFObFRVUCoLtcwepp9mmql/ArFUy+HCHp54Xrq4koTcOD6TA==", + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.22.0.tgz", + "integrity": "sha512-8df4uJiM3C6GZ2Sx/KilSKVxsetrTBBIUb3c0W4B1EWHcddioVs5mkyDKtMNP0khP/xBILVSzlXxhV+nm2rC9A==", "dev": true, "dependencies": { "azure-devops-node-api": "^11.0.1", @@ -459,6 +567,16 @@ "keytar": "^7.7.0" } }, + "node_modules/@vscode/vsce/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, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/@vscode/vsce/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -479,10 +597,22 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@vscode/vsce/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, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -666,13 +796,12 @@ "dev": true }, "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==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "node_modules/braces": { @@ -728,13 +857,14 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -775,6 +905,18 @@ "node": ">=4" } }, + "node_modules/chalk/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/cheerio": { "version": "1.0.0-rc.12", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", @@ -840,18 +982,6 @@ "fsevents": "~2.3.2" } }, - "node_modules/chokidar/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==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", @@ -860,14 +990,87 @@ "optional": true }, "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/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==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/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==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/cliui/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==", + "dev": true + }, + "node_modules/cliui/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==", + "dev": true + }, + "node_modules/cliui/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==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/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==", + "dev": true, + "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/color-convert": { @@ -1009,6 +1212,20 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/detect-libc": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", @@ -1107,10 +1324,16 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "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==", + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, "node_modules/end-of-stream": { @@ -1154,18 +1377,19 @@ } }, "node_modules/eslint": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz", - "integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.51.0", - "@humanwhocodes/config-array": "^0.11.11", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.56.0", + "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -1247,6 +1471,16 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "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, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/eslint/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -1318,13 +1552,37 @@ "node": ">=4.0" } }, - "node_modules/eslint/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==", + "node_modules/eslint/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, - "engines": { - "node": ">=8" + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/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==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "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, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, "node_modules/eslint/node_modules/supports-color": { @@ -1433,9 +1691,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -1448,18 +1706,6 @@ "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==", - "dev": true, - "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", @@ -1540,9 +1786,9 @@ } }, "node_modules/flat-cache": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", - "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "dependencies": { "flatted": "^3.2.9", @@ -1550,7 +1796,7 @@ "rimraf": "^3.0.2" }, "engines": { - "node": ">=12.0.0" + "node": "^10.12.0 || >=12.0.0" } }, "node_modules/flatted": { @@ -1559,6 +1805,22 @@ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -1605,15 +1867,15 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1627,61 +1889,43 @@ "optional": true }, "node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=12" + "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "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, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob/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==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=10" + "node": ">= 6" } }, "node_modules/globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -1713,21 +1957,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "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 }, - "node_modules/has": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", - "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -1737,6 +1984,18 @@ "node": ">=4" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", @@ -1761,6 +2020,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -1850,9 +2121,9 @@ "optional": true }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", "dev": true, "engines": { "node": ">= 4" @@ -2005,6 +2276,24 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -2311,15 +2600,18 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minimist": { @@ -2332,6 +2624,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", @@ -2379,6 +2680,56 @@ "url": "https://opencollective.com/mochajs" } }, + "node_modules/mocha/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==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/mocha/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/mocha/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==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/mocha/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==", + "dev": true + }, + "node_modules/mocha/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==", + "dev": true + }, "node_modules/mocha/node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -2411,6 +2762,16 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/mocha/node_modules/glob/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, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/mocha/node_modules/glob/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -2444,21 +2805,26 @@ "node": ">=10" } }, - "node_modules/mocha/node_modules/minimatch/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==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/mocha/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==", "dev": true }, + "node_modules/mocha/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==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -2474,6 +2840,41 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/mocha/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==", + "dev": true, + "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/mocha/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -2518,9 +2919,9 @@ "dev": true }, "node_modules/node-abi": { - "version": "3.50.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.50.0.tgz", - "integrity": "sha512-2Gxu7Eq7vnBIRfYSmqPruEllMM14FjOQFJSoqdGWthVn+tmwEXzmdPpya6cvvwf0uZA3F5N1fMFr9mijZBplFA==", + "version": "3.52.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.52.0.tgz", + "integrity": "sha512-JJ98b02z16ILv7859irtXn4oUaFWADtvkzy2c0IAatNVX2Mc9Yoh8z6hZInn3QwvMEYhHuQloYi+TTQy67SIdQ==", "dev": true, "optional": true, "dependencies": { @@ -2559,9 +2960,9 @@ } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2711,6 +3112,31 @@ "node": ">=8" } }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", + "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -2792,9 +3218,9 @@ } }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "engines": { "node": ">=6" @@ -2952,6 +3378,16 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rimraf/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, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/rimraf/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -2972,6 +3408,18 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rimraf/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, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -3031,6 +3479,21 @@ "randombytes": "^2.1.0" } }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -3072,6 +3535,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "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==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/simple-concat": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", @@ -3138,6 +3613,24 @@ } }, "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "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==", @@ -3151,6 +3644,39 @@ "node": ">=8" } }, + "node_modules/string-width-cjs/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==", + "dev": true + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -3163,6 +3689,19 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "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", @@ -3176,15 +3715,15 @@ } }, "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", + "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, "engines": { - "node": ">=4" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/tar-fs": { @@ -3365,6 +3904,12 @@ "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", "dev": true }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -3412,6 +3957,24 @@ "dev": true }, "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "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==", @@ -3428,7 +3991,7 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { + "node_modules/wrap-ansi-cjs/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==", @@ -3443,7 +4006,7 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/color-convert": { + "node_modules/wrap-ansi-cjs/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==", @@ -3455,12 +4018,71 @@ "node": ">=7.0.0" } }, - "node_modules/wrap-ansi/node_modules/color-name": { + "node_modules/wrap-ansi-cjs/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==", "dev": true }, + "node_modules/wrap-ansi-cjs/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==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/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==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -3505,21 +4127,21 @@ "dev": true }, "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "dependencies": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/yargs-parser": { @@ -3546,6 +4168,35 @@ "node": ">=10" } }, + "node_modules/yargs/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==", + "dev": true + }, + "node_modules/yargs/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==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", @@ -3578,7 +4229,8 @@ } }, "vscode-cedar-wasm/pkg": { - "version": "0.5.3", + "name": "vscode-cedar-wasm", + "version": "0.5.4", "license": "SEE LICENSE IN LICENSE" } } diff --git a/package.json b/package.json index 93293ce..241fbca 100644 --- a/package.json +++ b/package.json @@ -12,11 +12,11 @@ "url": "https://github.com/cedar-policy/vscode-cedar/issues" }, "qna": "https://github.com/cedar-policy/vscode-cedar/issues", - "version": "0.5.3", + "version": "0.5.4", "preview": true, "icon": "icons/cedar-policy.png", "engines": { - "vscode": "^1.77.0" + "vscode": "^1.82.0" }, "categories": [ "Programming Languages", @@ -54,6 +54,17 @@ }, { "id": "cedar-injection" + }, + { + "id": "cedarschema", + "aliases": [ + "Cedar Schema", + "cedar schema" + ], + "extensions": [ + ".cedarschema" + ], + "configuration": "./language-configuration.json" } ], "commands": [ @@ -62,6 +73,11 @@ "category": "Cedar", "title": "Validate Cedar policy" }, + { + "command": "cedar.export", + "category": "Cedar", + "title": "Export Cedar policy as JSON" + }, { "command": "cedar.schemavalidate", "category": "Cedar", @@ -95,6 +111,11 @@ "command": "cedar.validate", "group": "1_modification" }, + { + "when": "editorLangId == cedar", + "command": "cedar.export", + "group": "y_commands" + }, { "when": "editorLangId == cedar || resourceFilename == cedarentities.json || resourceFilename =~ /\\.cedarentities\\.json$/", "command": "cedar.schemaopen", @@ -121,6 +142,10 @@ "command": "cedar.validate", "when": "editorLangId == cedar" }, + { + "command": "cedar.export", + "when": "editorLangId == cedar" + }, { "command": "cedar.schemavalidate", "when": "resourceFilename == cedarschema.json || resourceFilename =~ /\\.cedarschema\\.json$/" @@ -151,6 +176,11 @@ "embeddedLanguages": { "meta.embedded.block.cedar": "cedar" } + }, + { + "language": "cedarschema", + "scopeName": "source.cedarschema", + "path": "./syntaxes/cedarschema.tmLanguage.json" } ], "snippets": [ @@ -181,7 +211,7 @@ "watch": "tsc -watch -p ./", "pretest": "npm run compile && npm run lint", "lint": "eslint src --ext ts", - "test": "node ./out/test/runTest.js", + "test": "vscode-test", "package": "vsce package", "wasm-build": "cd vscode-cedar-wasm && wasm-pack build --target nodejs", "wasm-pkg": "cd vscode-cedar-wasm/pkg && npm pack && mv *.tgz ../.." @@ -191,16 +221,15 @@ "vscode-cedar-wasm": "file:vscode-cedar-wasm/pkg" }, "devDependencies": { - "@types/glob": "^8.1.0", - "@types/mocha": "^10.0.2", - "@types/node": "^16.18.58", - "@types/vscode": "=1.77.0", + "@types/mocha": "^10.0.6", + "@types/node": "^18.19.3", + "@types/vscode": "=1.82.0", "@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/parser": "^5.62.0", - "@vscode/test-electron": "^2.3.5", - "@vscode/vsce": "^2.21.1", - "eslint": "^8.51.0", - "glob": "^8.1.0", + "@vscode/test-cli": "^0.0.4", + "@vscode/test-electron": "^2.3.8", + "@vscode/vsce": "^2.22.0", + "eslint": "^8.56.0", "js-yaml": "^4.1.0", "mocha": "^10.2.0", "typescript": "^4.9.5" diff --git a/schemas/README.md b/schemas/README.md index 0080ed0..beb52e8 100644 --- a/schemas/README.md +++ b/schemas/README.md @@ -1,23 +1,33 @@ # JSON Schemas -The [JSON Schema](https://json-schema.org/) files in this folder are **experimental** and **not enabled** in the Cedar policy language extension for Visual Studio Code. The extension already validates Cedar schema and entities files using Cedar APIs. These JSON Schemas perform a base level of validation, but also can enable a base level of auto-completion. +The [JSON Schema](https://json-schema.org/) files in this folder are **experimental** and **not enabled** in the Cedar policy language extension for Visual Studio Code. The extension already validates Cedar schema and entities files using Cedar APIs. These JSON Schemas perform a base level of validation, but also can enable simple auto-completion. They include VS Code-specific schema extensions including `defaultSnippets` and `markdownDescription`. -The Visual Studio Code documentation for [JSON schemas and settings](https://code.visualstudio.com/docs/languages/json#_json-schemas-and-settings) explains how to associate a JSON file with a JSON Schema. For example, if you download `cedarschema.schema.json` and `cedarentities.schema.json` into your workspace, you can edit your `.vscode/settings.json` to reference them: +The Visual Studio Code documentation for [JSON schemas and settings](https://code.visualstudio.com/docs/languages/json#_json-schemas-and-settings) explains how to associate a JSON file with a JSON Schema. You can edit your `.vscode/settings.json` to reference the GitHub hosted files: ```json "json.schemas": [ { "fileMatch": ["*.cedarschema.json", "cedarschema.json"], - "url": "./cedarschema.schema.json" + "url": "https://raw.githubusercontent.com/cedar-policy/vscode-cedar/main/schemas/cedarschema.schema.json" }, { "fileMatch": ["*.cedarentities.json", "cedarentities.json"], - "url": "./cedarentities.schema.json" + "url": "https://raw.githubusercontent.com/cedar-policy/vscode-cedar/main/schemas/cedarentities.schema.json" + }, + { + "fileMatch": ["*.cedartemplatelinks.json", "cedartemplatelinks.json"], + "url": "https://raw.githubusercontent.com/cedar-policy/vscode-cedar/main/schemas/cedartemplatelinks.schema.json" + }, + { + "fileMatch": ["*.cedarauth.json", "cedarauth.json"], + "url": "https://raw.githubusercontent.com/cedar-policy/vscode-cedar/main/schemas/cedarauth.schema.json" } ], ``` -These schema files include VS Code-specific schema extensions including `defaultSnippets` and `markdownDescription`. +You can also download these schema files and change the `url` values to reference your local copies. + +## Development If you are building the Cedar policy language extension for Visual Studio from source and creating a custom `.vsix` file, you can update `package.json` with the `jsonValidation` section below to enable this for all extension users. @@ -36,6 +46,20 @@ If you are building the Cedar policy language extension for Visual Studio from s "cedarentities.json" ], "url": "./schemas/cedarentities.schema.json" + }, + { + "fileMatch": [ + "*.cedartemplatelinks.json", + "cedartemplatelinks.json" + ], + "url": "./schemas/cedartemplatelinks.schema.json" + }, + { + "fileMatch": [ + "*.cedarauth.json", + "cedarauth.json" + ], + "url": "./schemas/cedarauth.schema.json" } ], ``` diff --git a/schemas/cedarauth.schema.json b/schemas/cedarauth.schema.json new file mode 100644 index 0000000..3bb3b50 --- /dev/null +++ b/schemas/cedarauth.schema.json @@ -0,0 +1,40 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "$comment": "https://docs.cedarpolicy.com/auth/authorization.html", + "type": "object", + "description": "Declaration of the structure of the authorization request used by the Cedar CLI.", + "properties": { + "principal": { + "type": "string", + "description": "Can this principal take this action on this resource in this context?", + "markdownDescription": "Can this `principal` take this `action` on this `resource` in this `context`?" + }, + "action": { + "type": "string", + "description": "Can this principal take this action on this resource in this context?", + "markdownDescription": "Can this `principal` take this `action` on this `resource` in this `context`?" + }, + "resource": { + "type": "string", + "description": "Can this principal take this action on this resource in this context?", + "markdownDescription": "Can this `principal` take this `action` on this `resource` in this `context`?" + }, + "context": { + "type": "object", + "description": "Can this principal take this action on this resource in this context?", + "markdownDescription": "Can this `principal` take this `action` on this `resource` in this `context`?" + } + }, + "required": ["principal", "action", "resource", "context"], + "defaultSnippets": [ + { + "label": "New authorization request", + "body": { + "principal": "$1::\"$2\"", + "action": "$3Action::\"$4\"", + "resource": "$5::\"$6\"", + "context": "^{$7}" + } + } + ] +} diff --git a/schemas/cedartemplatelinks.schema.json b/schemas/cedartemplatelinks.schema.json new file mode 100644 index 0000000..01b333d --- /dev/null +++ b/schemas/cedartemplatelinks.schema.json @@ -0,0 +1,53 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "$comment": "https://docs.cedarpolicy.com/policies/templates.html", + "type": "array", + "description": "Each object in this list represents a single template link, and should have three attributes: template_id, link_id, args", + "markdownDescription": "Each object in this list represents a single template link, and should have three attributes: `template_id`, `link_id`, `args`", + "items": { + "type": "object", + "properties": { + "template_id": { + "type": "string", + "description": "The id of policy template to link with" + }, + "link_id": { + "type": "string", + "description": "The id of this template-linked policy" + }, + "args": { + "type": "object", + "description": "One or both of ?principal and ?resource is required", + "markdownDescription": "One or both of `?principal` and `?resource` is required", + "properties": { + "?principal": { + "type": "string", + "description": "Exact principal to use for this template-linked policy" + }, + "?resource": { + "type": "string", + "description": "Exact resource to use for this template-linked policy" + } + }, + "anyOf": [ + {"required": ["?principal"]}, + {"required": ["?resource"]} + ] + } + }, + "required": ["template_id", "link_id", "args"], + "defaultSnippets": [ + { + "label": "New template link", + "body": { + "template_id": "$1", + "link_id": "$2", + "args": { + "?principal": "$3::\"$4\"", + "?resource": "$5::\"$6\"" + } + } + } + ] + } +} diff --git a/src/commands.ts b/src/commands.ts index 4ba0359..6547b66 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -3,6 +3,7 @@ // strings need to match commands in package.json export const COMMAND_CEDAR_VALIDATE = 'cedar.validate'; +export const COMMAND_CEDAR_EXPORT = 'cedar.export'; export const COMMAND_CEDAR_SCHEMAVALIDATE = 'cedar.schemavalidate'; export const COMMAND_CEDAR_SCHEMAEXPORT = 'cedar.schemaexport'; export const COMMAND_CEDAR_SCHEMAOPEN = 'cedar.schemaopen'; diff --git a/src/definition.ts b/src/definition.ts index b15fa33..49db6d3 100644 --- a/src/definition.ts +++ b/src/definition.ts @@ -3,9 +3,12 @@ import * as vscode from 'vscode'; import { - parseCedarDocEntities, - parseCedarDocPolicies, - parseCedarDocSchema, + parseCedarEntitiesDoc, + parseCedarPoliciesDoc, + parseCedarAuthDoc, + parseCedarSchemaDoc, + parseCedarTemplateLinksDoc, + parseCedarJsonPolicyDoc, } from './parser'; import { getSchemaTextDocument } from './fileutil'; @@ -17,7 +20,7 @@ const findSchemaDefinition = async ( schemaDoc: vscode.TextDocument ): Promise => { // TODO: update from O(n^2) to something more efficient - const schemaItem = parseCedarDocSchema(schemaDoc); + const schemaItem = parseCedarSchemaDoc(schemaDoc); const schemaEntityTypeRanges = schemaItem.entities; for (let entityTypeRange of entityTypeRanges) { if (entityTypeRange.contains(position)) { @@ -64,7 +67,7 @@ export class CedarEntitiesDefinitionProvider const schemaDoc = await getSchemaTextDocument(undefined, cedarEntitiesDoc); if (schemaDoc) { const entityTypeRanges = - parseCedarDocEntities(cedarEntitiesDoc).entityTypes; + parseCedarEntitiesDoc(cedarEntitiesDoc).entityTypes; return findSchemaDefinition( cedarEntitiesDoc, position, @@ -78,6 +81,83 @@ export class CedarEntitiesDefinitionProvider } } +export class CedarTemplateLinksDefinitionProvider + implements vscode.DefinitionProvider +{ + async provideDefinition( + cedarTemplateLinksDoc: vscode.TextDocument, + position: vscode.Position, + token: vscode.CancellationToken + ): Promise { + const schemaDoc = await getSchemaTextDocument( + undefined, + cedarTemplateLinksDoc + ); + if (schemaDoc) { + const entityTypeRanges = parseCedarTemplateLinksDoc( + cedarTemplateLinksDoc + ).entityTypes; + return findSchemaDefinition( + cedarTemplateLinksDoc, + position, + entityTypeRanges, + [], + schemaDoc + ); + } + + return null; + } +} + +export class CedarAuthDefinitionProvider implements vscode.DefinitionProvider { + async provideDefinition( + cedarAuthDoc: vscode.TextDocument, + position: vscode.Position, + token: vscode.CancellationToken + ): Promise { + const schemaDoc = await getSchemaTextDocument(undefined, cedarAuthDoc); + if (schemaDoc) { + const authItem = parseCedarAuthDoc(cedarAuthDoc); + const entityTypeRanges = authItem.entityTypes; + const actionRanges = authItem.actions; + return findSchemaDefinition( + cedarAuthDoc, + position, + entityTypeRanges, + actionRanges, + schemaDoc + ); + } + + return null; + } +} + +export class CedarJsonDefinitionProvider implements vscode.DefinitionProvider { + async provideDefinition( + cedarJsonDoc: vscode.TextDocument, + position: vscode.Position, + token: vscode.CancellationToken + ): Promise { + const schemaDoc = await getSchemaTextDocument(undefined, cedarJsonDoc); + if (schemaDoc) { + const authItem = parseCedarJsonPolicyDoc(cedarJsonDoc); + const entityTypeRanges = authItem.entityTypes; + const actionRanges = authItem.actions; + return findSchemaDefinition( + cedarJsonDoc, + position, + entityTypeRanges, + actionRanges, + schemaDoc + ); + } + + return null; + } +} + export class CedarSchemaDefinitionProvider implements vscode.DefinitionProvider { @@ -86,7 +166,7 @@ export class CedarSchemaDefinitionProvider position: vscode.Position, token: vscode.CancellationToken ): Promise { - const schemaItem = parseCedarDocSchema(schemaDoc); + const schemaItem = parseCedarSchemaDoc(schemaDoc); const entityTypeRanges = schemaItem.entityTypes; const actionRanges = schemaItem.actions; return findSchemaDefinition( @@ -107,7 +187,7 @@ export class CedarDefinitionProvider implements vscode.DefinitionProvider { ): Promise { const schemaDoc = await getSchemaTextDocument(undefined, cedarDoc); if (schemaDoc) { - const policyItem = parseCedarDocPolicies(cedarDoc); + const policyItem = parseCedarPoliciesDoc(cedarDoc); const entityTypeRanges = policyItem.entityTypes; const actionRanges = policyItem.actions; return findSchemaDefinition( diff --git a/src/diagnostics.ts b/src/diagnostics.ts index c7151c7..24786e4 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -3,7 +3,7 @@ import * as vscode from 'vscode'; import * as jsonc from 'jsonc-parser'; -import { parseCedarDocEntities, parseCedarDocSchema } from './parser'; +import { parseCedarEntitiesDoc, parseCedarSchemaDoc } from './parser'; const SOURCE_CEDAR = 'Cedar'; export const DEFAULT_RANGE = new vscode.Range( new vscode.Position(0, 0), @@ -126,7 +126,7 @@ const determineRangeFromError = ( } else if ( error === 'Entity type `Action` declared in `entityTypes` list.' ) { - const entityRanges = parseCedarDocSchema(document).entities; + const entityRanges = parseCedarSchemaDoc(document).entities; for (let entityRange of entityRanges) { if (entityRange.etype === 'Action') { range = entityRange.etypeRange; @@ -335,7 +335,7 @@ const handleEntitiesDiagnosticError = ( } if (uid) { - const entityRanges = parseCedarDocEntities(document).entities; + const entityRanges = parseCedarEntitiesDoc(document).entities; entityRanges.forEach((entityRange, index) => { if (entityRange.uid === uid) { const attributeRange = entityRange.attrsNameRanges.hasOwnProperty( diff --git a/src/documentsymbols.ts b/src/documentsymbols.ts index 0f771af..6f99408 100644 --- a/src/documentsymbols.ts +++ b/src/documentsymbols.ts @@ -3,9 +3,10 @@ import * as vscode from 'vscode'; import { - parseCedarDocEntities, - parseCedarDocPolicies, - parseCedarDocSchema, + parseCedarEntitiesDoc, + parseCedarPoliciesDoc, + parseCedarSchemaDoc, + parseCedarTemplateLinksDoc, } from './parser'; export class CedarDocumentSymbolProvider @@ -17,7 +18,7 @@ export class CedarDocumentSymbolProvider ): Promise { try { const symbols: vscode.DocumentSymbol[] = []; - const policyRanges = parseCedarDocPolicies(document).policies; + const policyRanges = parseCedarPoliciesDoc(document).policies; policyRanges.forEach((policyRange, index) => { symbols.push( new vscode.DocumentSymbol( @@ -44,7 +45,7 @@ export class CedarFoldingRangeProvider implements vscode.FoldingRangeProvider { token: vscode.CancellationToken ): vscode.FoldingRange[] { const ranges: vscode.FoldingRange[] = []; - const policyRanges = parseCedarDocPolicies(document).policies; + const policyRanges = parseCedarPoliciesDoc(document).policies; policyRanges.forEach((policyRange, index) => { ranges.push( new vscode.FoldingRange( @@ -78,7 +79,7 @@ export class CedarEntitiesDocumentSymbolProvider try { const symbols: vscode.DocumentSymbol[] = []; - const entityRanges = parseCedarDocEntities(document).entities; + const entityRanges = parseCedarEntitiesDoc(document).entities; entityRanges.forEach((entityRange, index) => { const symbol = new vscode.DocumentSymbol( entityRange.uid, @@ -119,6 +120,38 @@ export class CedarEntitiesDocumentSymbolProvider } } +export class CedarTemplateLinksDocumentSymbolProvider + implements vscode.DocumentSymbolProvider +{ + async provideDocumentSymbols( + cedarTemplateLinksDoc: vscode.TextDocument, + token: vscode.CancellationToken + ): Promise { + try { + const symbols: vscode.DocumentSymbol[] = []; + + const templateLinkRanges = parseCedarTemplateLinksDoc( + cedarTemplateLinksDoc + ).links; + templateLinkRanges.forEach((templateLinkRange, index) => { + symbols.push( + new vscode.DocumentSymbol( + templateLinkRange.id, + '', + vscode.SymbolKind.Object, + templateLinkRange.range, + templateLinkRange.linkIdRange + ) + ); + }); + + return Promise.resolve(symbols); + } catch (error) { + return Promise.resolve([]); + } + } +} + export class CedarSchemaDocumentSymbolProvider implements vscode.DocumentSymbolProvider { @@ -129,7 +162,7 @@ export class CedarSchemaDocumentSymbolProvider try { const symbols: vscode.DocumentSymbol[] = []; - const entityRanges = parseCedarDocSchema(cedarSchemaDoc).entities; + const entityRanges = parseCedarSchemaDoc(cedarSchemaDoc).entities; entityRanges.forEach((entityRange, index) => { symbols.push( new vscode.DocumentSymbol( diff --git a/src/extension.ts b/src/extension.ts index cb58b70..6b676ca 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -3,7 +3,11 @@ import * as vscode from 'vscode'; import * as path from 'node:path'; -import { ExportType, generateDiagram } from './generate'; +import { + SchemaExportType, + generateDiagram, + schemaExportTypeExtension, +} from './generate'; import { HOVER_HELP_DEFINITIONS } from './help'; import { handleWillDeleteFiles, @@ -12,9 +16,9 @@ import { getSchemaUri, CEDAR_SCHEMA_GLOB, CEDAR_ENTITIES_GLOB, - CEDAR_SCHEMA_FILE, - CEDAR_SCHEMA_FILE_GLOB, - CEDAR_ENTITIES_FILE_GLOB, + CEDAR_TEMPLATELINKS_GLOB, + CEDAR_AUTH_GLOB, + CEDAR_JSON_GLOB, } from './fileutil'; import { createDiagnosticCollection } from './diagnostics'; import { formatCedarDoc } from './format'; @@ -29,6 +33,7 @@ import { CedarSchemaJSONQuickFix, CedarQuickFix } from './quickfix'; import { COMMAND_CEDAR_CLEARPROBLEMS, COMMAND_CEDAR_ENTITIESVALIDATE, + COMMAND_CEDAR_EXPORT, COMMAND_CEDAR_SCHEMAEXPORT, COMMAND_CEDAR_SCHEMAOPEN, COMMAND_CEDAR_SCHEMAVALIDATE, @@ -39,18 +44,26 @@ import { CedarEntitiesDocumentSymbolProvider, CedarFoldingRangeProvider, CedarSchemaDocumentSymbolProvider, + CedarTemplateLinksDocumentSymbolProvider, } from './documentsymbols'; import { CedarDefinitionProvider, CedarEntitiesDefinitionProvider, + CedarAuthDefinitionProvider, CedarSchemaDefinitionProvider, + CedarTemplateLinksDefinitionProvider, + CedarJsonDefinitionProvider, } from './definition'; import { semanticTokensLegend, cedarTokensProvider, entitiesTokensProvider, schemaTokensProvider, + templateLinksTokensProvider, + authTokensProvider, + cedarJsonTokensProvider, } from './parser'; +import { exportCedarDocPolicyById, getPolicyQuickPickItems } from './policy'; // This method is called when your extension is activated export async function activate(context: vscode.ExtensionContext) { @@ -127,27 +140,6 @@ export async function activate(context: vscode.ExtensionContext) { } ) ); - context.subscriptions.push( - vscode.languages.registerCodeActionsProvider( - { pattern: CEDAR_SCHEMA_FILE_GLOB, scheme: 'file' }, - new CedarSchemaJSONQuickFix(), - { - providedCodeActionKinds: - CedarSchemaJSONQuickFix.providedCodeActionKinds, - } - ) - ); - - // context.subscriptions.push( - // vscode.languages.registerTypeDefinitionProvider( - // { pattern: CEDAR_SCHEMA_GLOB, scheme: "file" }, - // { - // provideTypeDefinition: (document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken) => { - // return null; - // }, - // } - // ) - // ); context.subscriptions.push( vscode.workspace.onDidChangeConfiguration( @@ -210,6 +202,49 @@ export async function activate(context: vscode.ExtensionContext) { } ) ); + context.subscriptions.push( + vscode.commands.registerTextEditorCommand( + COMMAND_CEDAR_EXPORT, + async ( + textEditor: vscode.TextEditor, + edit: vscode.TextEditorEdit, + args: any[] + ) => { + const results = await vscode.window.showQuickPick( + getPolicyQuickPickItems(textEditor.document, textEditor.selection), + { + title: 'Export Cedar policy as JSON', + canPickMany: true, + } + ); + if (results) { + const cedarDoc = textEditor.document; + results.forEach(async (result) => { + const exportFilename = cedarDoc.uri.fsPath.replace( + /\.cedar$/, + `(${result.label}).cedar.json` + ); + const exportJson = await exportCedarDocPolicyById( + cedarDoc, + result.label, + exportFilename + ); + + if (!exportJson) { + vscode.window.showErrorMessage( + `Unable to export Cedar policy: ${result.label}` + ); + } else if (results.length === 1) { + vscode.commands.executeCommand( + 'vscode.open', + vscode.Uri.file(exportFilename) + ); + } + }); + } + } + ) + ); context.subscriptions.push( vscode.commands.registerTextEditorCommand( COMMAND_CEDAR_SCHEMAVALIDATE, @@ -247,32 +282,45 @@ export async function activate(context: vscode.ExtensionContext) { return; } - const result = await vscode.window.showQuickPick([ - ExportType.PlantUML, - ExportType.Mermaid, - ]); + const result = await vscode.window.showQuickPick( + [ + { + label: SchemaExportType.PlantUML, + description: 'Class Diagram', + }, + { + label: SchemaExportType.Mermaid, + description: 'Class Diagram', + }, + ], + { + title: 'Export Cedar schema (experimental)', + } + ); if (result) { - const cedarschema = JSON.parse(textEditor.document.getText()); - const exportFilename = - uri.fsPath + (result === ExportType.PlantUML ? '.puml' : '.mmd'); - let diagramName = uri.fsPath.substring( - uri.fsPath.lastIndexOf(path.sep) + 1 - ); - diagramName = diagramName.substring(0, diagramName.indexOf('.')); + const saveUri = await vscode.window.showSaveDialog({ + defaultUri: uri.with({ + path: uri.path + schemaExportTypeExtension[result.label], + }), + }); + if (saveUri) { + const cedarschema = JSON.parse(textEditor.document.getText()); + let diagramName = uri.fsPath.substring( + uri.fsPath.lastIndexOf(path.sep) + 1 + ); + diagramName = diagramName.substring(0, diagramName.indexOf('.')); - const dsl = generateDiagram( - diagramName, - cedarschema, - result as ExportType - ); - vscode.workspace.fs.writeFile( - vscode.Uri.file(exportFilename), - new Uint8Array(Buffer.from(dsl)) - ); - vscode.commands.executeCommand( - 'vscode.open', - vscode.Uri.file(exportFilename) - ); + const dsl = generateDiagram( + diagramName, + cedarschema, + result.label as SchemaExportType + ); + vscode.workspace.fs.writeFile( + saveUri, + new Uint8Array(Buffer.from(dsl)) + ); + vscode.commands.executeCommand('vscode.open', saveUri); + } } } ) @@ -362,23 +410,14 @@ export async function activate(context: vscode.ExtensionContext) { baseUri: vscode.workspace.workspaceFolders[0].uri, pattern: CEDAR_SCHEMA_GLOB, }; - const schemaSelector = { pattern: schemaPattern, scheme: 'file' }; - - context.subscriptions.push( - vscode.languages.registerDocumentSemanticTokensProvider( - schemaSelector, - schemaTokensProvider, - semanticTokensLegend - ) - ); - - const schemaFileSelector = { + const schemaSelector = { language: 'json', - pattern: CEDAR_SCHEMA_FILE_GLOB, + pattern: schemaPattern, }; + context.subscriptions.push( vscode.languages.registerDocumentSemanticTokensProvider( - schemaFileSelector, + schemaSelector, schemaTokensProvider, semanticTokensLegend ) @@ -392,12 +431,6 @@ export async function activate(context: vscode.ExtensionContext) { schemaSymbolProvider ) ); - context.subscriptions.push( - vscode.languages.registerDocumentSymbolProvider( - schemaFileSelector, - schemaSymbolProvider - ) - ); const schemaDefinitionProvider = new CedarSchemaDefinitionProvider(); context.subscriptions.push( @@ -406,19 +439,16 @@ export async function activate(context: vscode.ExtensionContext) { schemaDefinitionProvider ) ); - context.subscriptions.push( - vscode.languages.registerDefinitionProvider( - schemaFileSelector, - schemaDefinitionProvider - ) - ); // @ts-ignore const entitiesPattern: vscode.RelativePattern = { baseUri: vscode.workspace.workspaceFolders[0].uri, pattern: CEDAR_ENTITIES_GLOB, }; - const entitiesSelector = { pattern: entitiesPattern, scheme: 'file' }; + const entitiesSelector = { + language: 'json', + pattern: entitiesPattern, + }; context.subscriptions.push( vscode.languages.registerDocumentSemanticTokensProvider( @@ -428,44 +458,109 @@ export async function activate(context: vscode.ExtensionContext) { ) ); - const entitiesFileSelector = { + // display uid strings in outline and breadcrumb + const entitiesSymbolProvider = new CedarEntitiesDocumentSymbolProvider(); + context.subscriptions.push( + vscode.languages.registerDocumentSymbolProvider( + entitiesSelector, + entitiesSymbolProvider + ) + ); + + const entitiesDefinitionProvider = new CedarEntitiesDefinitionProvider(); + context.subscriptions.push( + vscode.languages.registerDefinitionProvider( + entitiesSelector, + entitiesDefinitionProvider + ) + ); + + // @ts-ignore + const templateLinksPattern: vscode.RelativePattern = { + baseUri: vscode.workspace.workspaceFolders[0].uri, + pattern: CEDAR_TEMPLATELINKS_GLOB, + }; + const templateLinksSelector = { language: 'json', - pattern: CEDAR_ENTITIES_FILE_GLOB, + pattern: templateLinksPattern, }; + context.subscriptions.push( vscode.languages.registerDocumentSemanticTokensProvider( - entitiesFileSelector, - entitiesTokensProvider, + templateLinksSelector, + templateLinksTokensProvider, semanticTokensLegend ) ); - // display uid strings in outline and breadcrumb - const entitiesSymbolProvider = new CedarEntitiesDocumentSymbolProvider(); + // display template link id strings in outline and breadcrumb + const templateLinksSymbolProvider = + new CedarTemplateLinksDocumentSymbolProvider(); context.subscriptions.push( vscode.languages.registerDocumentSymbolProvider( - entitiesSelector, - entitiesSymbolProvider + templateLinksSelector, + templateLinksSymbolProvider ) ); + + const templateLinksDefinitionProvider = + new CedarTemplateLinksDefinitionProvider(); context.subscriptions.push( - vscode.languages.registerDocumentSymbolProvider( - entitiesFileSelector, - entitiesSymbolProvider + vscode.languages.registerDefinitionProvider( + templateLinksSelector, + templateLinksDefinitionProvider ) ); - const entitiesDefinitionProvider = new CedarEntitiesDefinitionProvider(); + // @ts-ignore + const authPattern: vscode.RelativePattern = { + baseUri: vscode.workspace.workspaceFolders[0].uri, + pattern: CEDAR_AUTH_GLOB, + }; + const authSelector = { + language: 'json', + pattern: authPattern, + }; + + context.subscriptions.push( + vscode.languages.registerDocumentSemanticTokensProvider( + authSelector, + authTokensProvider, + semanticTokensLegend + ) + ); + + const authDefinitionProvider = new CedarAuthDefinitionProvider(); context.subscriptions.push( vscode.languages.registerDefinitionProvider( - entitiesSelector, - entitiesDefinitionProvider + authSelector, + authDefinitionProvider ) ); + + // @ts-ignore + const cedarJsonPattern: vscode.RelativePattern = { + baseUri: vscode.workspace.workspaceFolders[0].uri, + pattern: CEDAR_JSON_GLOB, + }; + const cedarJsonSelector = { + language: 'json', + pattern: cedarJsonPattern, + }; + + context.subscriptions.push( + vscode.languages.registerDocumentSemanticTokensProvider( + cedarJsonSelector, + cedarJsonTokensProvider, + semanticTokensLegend + ) + ); + + const cedarJsonDefinitionProvider = new CedarJsonDefinitionProvider(); context.subscriptions.push( vscode.languages.registerDefinitionProvider( - entitiesFileSelector, - entitiesDefinitionProvider + cedarJsonSelector, + cedarJsonDefinitionProvider ) ); } diff --git a/src/fileutil.ts b/src/fileutil.ts index a50aa44..17dd34c 100644 --- a/src/fileutil.ts +++ b/src/fileutil.ts @@ -5,15 +5,34 @@ import * as vscode from 'vscode'; import * as path from 'node:path'; import { addValidationDiagnosticInfo } from './diagnostics'; -export const CEDAR_SCHEMA_FILE = `cedarschema.json`; -export const CEDAR_SCHEMA_FILE_GLOB = `**/cedarschema.json`; -/*export*/ const CEDAR_SCHEMA_EXTENSION = `.cedarschema`; // https://github.com/cedar-policy/rfcs/blob/schema-syntax/text/0024-schema-syntax.md -export const CEDAR_SCHEMA_EXTENSION_JSON = `.cedarschema.json`; -export const CEDAR_SCHEMA_GLOB = `**/*.cedarschema.json`; -export const CEDAR_ENTITIES_FILE = `cedarentities.json`; -export const CEDAR_ENTITIES_FILE_GLOB = `**/cedarentities.json`; -export const CEDAR_ENTITIES_EXTENSION_JSON = `.cedarentities.json`; -export const CEDAR_ENTITIES_GLOB = `**/*.cedarentities.json`; +const CEDAR_SCHEMA_FILE = `cedarschema.json`; +const CEDAR_SCHEMA_EXTENSION_JSON = `.cedarschema.json`; +const CEDAR_SCHEMA_EXTENSION = `.cedarschema`; // https://github.com/cedar-policy/rfcs/blob/schema-syntax/text/0024-schema-syntax.md +export const CEDAR_SCHEMA_GLOB = `{**/cedarschema.json,**/*.cedarschema.json}`; + +const CEDAR_ENTITIES_FILE = `cedarentities.json`; +const CEDAR_ENTITIES_EXTENSION_JSON = `.cedarentities.json`; +export const CEDAR_ENTITIES_GLOB = `{**/cedarentities.json,**/*.cedarentities.json,**/avpentities.json,**/*.avpentities.json}`; + +export const CEDAR_TEMPLATELINKS_GLOB = `{**/cedartemplatelinks.json,**/*.cedartemplatelinks.json,**/cedarlinks.json,**/*.cedarlinks.json}`; +export const CEDAR_AUTH_GLOB = `{**/cedarauth.json,**/*.cedarauth.json,**/cedarparc.json,**/*.cedarparc.json}`; +export const CEDAR_JSON_GLOB = `**/*.cedar.json`; + +export const detectSchemaDoc = (doc: vscode.TextDocument): boolean => { + const result = + doc.fileName.endsWith(path.sep + CEDAR_SCHEMA_FILE) || + doc.fileName.endsWith(CEDAR_SCHEMA_EXTENSION_JSON); + + return result; +}; + +export const detectEntitiesDoc = (doc: vscode.TextDocument): boolean => { + const result = + doc.fileName.endsWith(path.sep + CEDAR_ENTITIES_FILE) || + doc.fileName.endsWith(CEDAR_ENTITIES_EXTENSION_JSON); + + return result; +}; export const findSchemaFilesInFolder = async (filepath: string) => { const schemaFiles = []; diff --git a/src/generate.ts b/src/generate.ts index 1c4d041..d04600c 100644 --- a/src/generate.ts +++ b/src/generate.ts @@ -3,16 +3,25 @@ import { Attributes, CedarSchemaDefinition, Shape } from './cedarschema'; -export enum ExportType { - // eslint-disable-next-line +export enum SchemaExportType { + // eslint-disable-next-line @typescript-eslint/naming-convention PlantUML = 'PlantUML', - // eslint-disable-next-line + // eslint-disable-next-line @typescript-eslint/naming-convention Mermaid = 'Mermaid', } +export const schemaExportTypeExtension: Record< + keyof typeof SchemaExportType, + string +> = { + // eslint-disable-next-line @typescript-eslint/naming-convention + PlantUML: '.puml', + // eslint-disable-next-line @typescript-eslint/naming-convention + Mermaid: '.mmd', +}; const buildProperties = ( attributes: Attributes, - diagramType: ExportType, + diagramType: SchemaExportType, prefix: string = '' ): string => { let properties = ''; @@ -28,13 +37,13 @@ const buildProperties = ( } else if (attributeType === 'Set') { const shapeType = attributes[k].element?.type as String; if (shapeType === 'Entity') { - if (diagramType === ExportType.Mermaid) { + if (diagramType === SchemaExportType.Mermaid) { attributeType = `Set~${attributes[k].element?.name}~`; } else { attributeType = `Set<${attributes[k].element?.name}>`; } } else { - if (diagramType === ExportType.Mermaid) { + if (diagramType === SchemaExportType.Mermaid) { attributeType = `Set~${shapeType}~`; } else { attributeType = `Set<${shapeType}>`; @@ -63,7 +72,7 @@ const buildProperties = ( export const generateDiagram = ( diagramFilename: string, cedarschema: CedarSchemaDefinition, - diagramType: ExportType + diagramType: SchemaExportType ): string => { let dsl = ''; @@ -89,7 +98,7 @@ export const generateDiagram = ( ' ' ); } - if (diagramType === ExportType.Mermaid) { + if (diagramType === SchemaExportType.Mermaid) { commonTypesDSL += `class ${name} {\n <>${properties}\n}\n\n`; } else { commonTypesDSL += `struct ${name} <> {${properties}\n}\n\n`; @@ -110,13 +119,13 @@ export const generateDiagram = ( properties = buildProperties(attributes, diagramType); } entityTypesDSLTmp[name] = - diagramType === ExportType.Mermaid + diagramType === SchemaExportType.Mermaid ? ` class ${name} {\n <>${properties}` : ` class ${name} <> {${properties}`; if (e?.memberOfTypes) { e?.memberOfTypes.forEach((m) => { - if (diagramType === ExportType.Mermaid) { + if (diagramType === SchemaExportType.Mermaid) { membersDSL += `${name} ..> ${m} : memberOf\n`; } else { membersDSL += `${name} - ${m} : > memberOf\n`; @@ -124,7 +133,7 @@ export const generateDiagram = ( }); } if (commonTypes.includes(e?.shape?.type as string)) { - if (diagramType === ExportType.Mermaid) { + if (diagramType === SchemaExportType.Mermaid) { parentsDSL += `${name} ..> ${e?.shape?.type} : shape\n`; } else { parentsDSL += `${name} -U- ${e?.shape?.type} : > shape\n`; @@ -138,14 +147,14 @@ export const generateDiagram = ( Object.keys(cedarschema[namespace].actions).forEach((name) => { const a = cedarschema[namespace].actions[name]; let tmp = - diagramType === ExportType.Mermaid + diagramType === SchemaExportType.Mermaid ? ` class ${name} {\n <>` : ` class ${name} <> {`; if (a.appliesTo?.context?.attributes) { const attributes = a.appliesTo.context.attributes; let properties = buildProperties(attributes, diagramType); - if (diagramType === ExportType.PlantUML) { + if (diagramType === SchemaExportType.PlantUML) { tmp += '\n --context--'; } tmp += properties + '\n'; @@ -157,7 +166,7 @@ export const generateDiagram = ( } //tmp += diagramType === ExportType.Mermaid ? `\n }\n` : `}\n`; if (commonTypes.includes(a.appliesTo?.context?.type as string)) { - if (diagramType === ExportType.Mermaid) { + if (diagramType === SchemaExportType.Mermaid) { parentsDSL += `${name} ..> ${a.appliesTo?.context?.type} : context\n`; } else { parentsDSL += `${name} -U- ${a.appliesTo?.context?.type} : > context\n`; @@ -167,7 +176,7 @@ export const generateDiagram = ( if (a?.memberOf) { a.memberOf.forEach((m) => { - if (diagramType === ExportType.Mermaid) { + if (diagramType === SchemaExportType.Mermaid) { membersDSL += `${name} ..> ${m.id} : memberOf\n`; } else { membersDSL += `${name} - ${m.id} : > memberOf\n`; @@ -203,7 +212,7 @@ export const generateDiagram = ( entityTypesDSL += '}\n\n'; }); - if (diagramType === ExportType.Mermaid) { + if (diagramType === SchemaExportType.Mermaid) { dsl += formatMermaid( diagramFilename, title, diff --git a/src/parser.ts b/src/parser.ts index 37600cd..de903af 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -15,7 +15,15 @@ import { * see https://github.com/microsoft/node-jsonc-parser */ -const tokenTypes = ['namespace', 'type', 'property', 'macro', 'function']; +const tokenTypes = [ + 'namespace', + 'type', + 'property', + 'macro', + 'function', + 'variable', + 'keyword', +]; const tokenModifiers = ['declaration', 'deprecated']; export const semanticTokensLegend = new vscode.SemanticTokensLegend( tokenTypes, @@ -58,7 +66,7 @@ const policyCache: Record = {}; const ID_ATTR = /@id\("(?(.+))"\)/; -export const parseCedarDocPolicies = ( +export const parseCedarPoliciesDoc = ( cedarDoc: vscode.TextDocument, visitPolicy?: | undefined @@ -68,7 +76,7 @@ export const parseCedarDocPolicies = ( if (visitPolicy === undefined) { const cachedItem = policyCache[cedarDoc.uri.toString()]; if (cachedItem && cachedItem.version === cedarDoc.version) { - // console.log("parseCedarDocPolicies (cached)"); + // console.log("parseCedarPoliciesDoc (cached)"); return cachedItem; } } @@ -183,7 +191,123 @@ export const cedarTokensProvider: vscode.DocumentSemanticTokensProvider = { provideDocumentSemanticTokens( cedarDoc: vscode.TextDocument ): vscode.ProviderResult { - return parseCedarDocPolicies(cedarDoc).tokens; + return parseCedarPoliciesDoc(cedarDoc).tokens; + }, +}; + +// Cedar policy (JSON) + +type PolicyJsonCacheItem = { + version: number; + tokens: vscode.SemanticTokens; + entityTypes: vscode.Range[]; + actions: vscode.Range[]; +}; + +const policyJsonCache: Record = {}; + +export const parseCedarJsonPolicyDoc = ( + cedarJsonDoc: vscode.TextDocument +): PolicyJsonCacheItem => { + let cachedItem = policyJsonCache[cedarJsonDoc.uri.toString()]; + if (cachedItem && cachedItem.version === cedarJsonDoc.version) { + // console.log("parseCedarJsonPolicyDoc (cached)"); + return cachedItem; + } + + const tokensBuilder = new vscode.SemanticTokensBuilder(semanticTokensLegend); + + const entityTypes: vscode.Range[] = []; + const actions: vscode.Range[] = []; + + jsonc.visit(cedarJsonDoc.getText(), { + onObjectProperty( + property, + offset, + length, + startLine, + startCharacter, + pathSupplier + ) { + const range = new vscode.Range( + new vscode.Position(startLine, startCharacter), + new vscode.Position(startLine, startCharacter + length) + ); + const jsonPathLen = pathSupplier().length; + if (jsonPathLen === 0) { + if (['principal', 'action', 'resource'].includes(property)) { + tokensBuilder.push(range, 'variable', []); + } + } + }, + onLiteralValue( + value, + offset, + length, + startLine, + startCharacter, + pathSupplier + ) { + const range = new vscode.Range( + new vscode.Position(startLine, startCharacter), + new vscode.Position(startLine, startCharacter + length) + ); + const jsonPathLen = pathSupplier().length; + const property = pathSupplier()[0] as string; + if (jsonPathLen === 1 && pathSupplier()[0] === 'effect') { + tokensBuilder.push(range, 'keyword', []); + } + + if ( + jsonPathLen === 3 && + pathSupplier()[0] === 'conditions' && + pathSupplier()[jsonPathLen - 1] === 'kind' + ) { + // most things directly under "kind" are a keyword + tokensBuilder.push(range, 'keyword', []); + } else if ( + jsonPathLen > 2 && + pathSupplier()[0] === 'action' && + pathSupplier()[jsonPathLen - 1] === 'id' + ) { + const innerRange = new vscode.Range( + new vscode.Position(startLine, startCharacter + 1), + new vscode.Position(startLine, startCharacter + length - 1) + ); + actions.push(innerRange); + } else if ( + jsonPathLen > 2 && + pathSupplier()[jsonPathLen - 1] === 'type' + ) { + // most things directly under "type" are a type + tokensBuilder.push(range, 'type', []); + + entityTypes.push( + determineDefinitionRange(value, startLine, startCharacter, length - 1) + ); + } else if (jsonPathLen > 2 && pathSupplier()[jsonPathLen - 1] === 'Var') { + // most things directly under "Var" are a variable + tokensBuilder.push(range, 'variable', []); + } + }, + }); + + cachedItem = { + version: cedarJsonDoc.version, + tokens: tokensBuilder.build(), + entityTypes: entityTypes, + actions: actions, + }; + policyJsonCache[cedarJsonDoc.uri.toString()] = cachedItem; + + return cachedItem; +}; + +export const cedarJsonTokensProvider: vscode.DocumentSemanticTokensProvider = { + provideDocumentSemanticTokens( + cedarJsonDoc: vscode.TextDocument + ): vscode.ProviderResult { + return parseCedarJsonPolicyDoc(cedarJsonDoc).tokens; }, }; @@ -210,7 +334,7 @@ export type EntityCacheItem = { const entityCache: Record = {}; -export const parseCedarDocEntities = ( +export const parseCedarEntitiesDoc = ( entitiesDoc: vscode.TextDocument, visitEntity?: | undefined @@ -220,11 +344,27 @@ export const parseCedarDocEntities = ( if (visitEntity === undefined) { const cachedItem = entityCache[entitiesDoc.uri.toString()]; if (cachedItem && cachedItem.version === entitiesDoc.version) { - // console.log("parseCedarDocEntities (cached)"); + // console.log("parseCedarEntitiesDoc (cached)"); return cachedItem; } } + let UID = 'uid'; + let TYPE = 'type'; + let ID = 'id'; + let ENTITY = '__entity'; + let ATTRS = 'attrs'; + let PARENTS = 'parents'; + + // Amazon Verified Permissions entities format has a similar structure but different property names + if (entitiesDoc.uri.toString().endsWith('.avpentities.json')) { + UID = 'identifier'; + TYPE = 'entityType'; + ID = 'entityId'; + ENTITY = 'entityIdentifier'; + ATTRS = 'attributes'; + } + const entities: EntityRange[] = []; const entityTypes: vscode.Range[] = []; @@ -278,7 +418,7 @@ export const parseCedarDocEntities = ( parentsCount = 0; } else if ( depth === 1 && - depth1Property === 'attrs' && + depth1Property === ATTRS && attrsKeyRange && Object.keys(attrsNameRanges).length > 0 ) { @@ -287,18 +427,14 @@ export const parseCedarDocEntities = ( attrsKeyRange?.start, new vscode.Position(startLine, startCharacter + length) ); - } else if ( - depth === 1 && - depth1Property === 'parents' && - parentsKeyRange - ) { + } else if (depth === 1 && depth1Property === PARENTS && parentsKeyRange) { parentsCount++; } }, onArrayEnd(offset, length, startLine, startCharacter) { if ( depth === 1 && - depth1Property === 'parents' && + depth1Property === PARENTS && parentsKeyRange && parentsCount > 0 ) { @@ -328,14 +464,14 @@ export const parseCedarDocEntities = ( const jsonPathLen = pathSupplier().length; if (jsonPathLen === 1) { depth1Property = property; - if (property === 'uid') { + if (property === UID) { uidKeyRange = innerRange; - } else if (property === 'attrs') { + } else if (property === ATTRS) { attrsKeyRange = innerRange; - } else if (property === 'parents') { + } else if (property === PARENTS) { parentsKeyRange = innerRange; } - } else if (jsonPathLen === 2 && pathSupplier()[1] === 'attrs') { + } else if (jsonPathLen === 2 && pathSupplier()[1] === ATTRS) { // anything directly under "attrs" is an property tokensBuilder.push(range, 'property', []); attrsNameRanges[property] = innerRange; @@ -343,7 +479,7 @@ export const parseCedarDocEntities = ( // treat "__expr" as a deprecated macro tokensBuilder.push(range, 'macro', ['deprecated']); } else if (property === '__entity' || property === '__extn') { - // treat "__entity" and "__extn as a macro + // treat "__entity" and "__extn" as a macro tokensBuilder.push(range, 'macro', []); } }, @@ -360,8 +496,8 @@ export const parseCedarDocEntities = ( new vscode.Position(startLine, startCharacter + length) ); const jsonPathLen = pathSupplier().length; - if (pathSupplier()[1] === 'uid') { - if (pathSupplier()[jsonPathLen - 1] === 'type') { + if (pathSupplier()[1] === UID) { + if (pathSupplier()[jsonPathLen - 1] === TYPE) { uidType = value; uid = `${uidType}::"${uidId}"`; uidTypeRange = new vscode.Range( @@ -369,11 +505,11 @@ export const parseCedarDocEntities = ( new vscode.Position(startLine, startCharacter + length - 1) ); } - if (pathSupplier()[jsonPathLen - 1] === 'id') { + if (pathSupplier()[jsonPathLen - 1] === ID) { uidId = value; uid = `${uidType}::"${uidId}"`; } - if (pathSupplier()[jsonPathLen - 1] === 'uid') { + if (pathSupplier()[jsonPathLen - 1] === UID) { uid = value; let found = uid.match(ENTITY_REGEX); if (found?.groups) { @@ -382,7 +518,7 @@ export const parseCedarDocEntities = ( new vscode.Position(startLine, startCharacter + 1), new vscode.Position(startLine, startCharacter + type.length + 1) ); - tokensBuilder.push(typeRange, 'type', []); + tokensBuilder.push(typeRange, TYPE, []); entityTypes.push( determineDefinitionRange( @@ -398,10 +534,10 @@ export const parseCedarDocEntities = ( if ( jsonPathLen > 2 && - pathSupplier()[jsonPathLen - 1] === 'type' && - (pathSupplier()[1] === 'uid' || - pathSupplier()[1] === 'parents' || - pathSupplier()[jsonPathLen - 2] === '__entity') + pathSupplier()[jsonPathLen - 1] === TYPE && + (pathSupplier()[1] === UID || + pathSupplier()[1] === PARENTS || + pathSupplier()[jsonPathLen - 2] === ENTITY) ) { // most things directly under "type" are a type tokensBuilder.push(range, 'type', []); @@ -436,7 +572,261 @@ export const entitiesTokensProvider: vscode.DocumentSemanticTokensProvider = { provideDocumentSemanticTokens( cedarEntitiesDoc: vscode.TextDocument ): vscode.ProviderResult { - return parseCedarDocEntities(cedarEntitiesDoc).tokens; + return parseCedarEntitiesDoc(cedarEntitiesDoc).tokens; + }, +}; + +// Cedar template links + +export type TemplateLinkRange = { + id: string; + range: vscode.Range; + linkIdRange: vscode.Range; +}; + +export type TemplateLinksCacheItem = { + version: number; + links: TemplateLinkRange[]; + tokens: vscode.SemanticTokens; + entityTypes: vscode.Range[]; +}; + +const templateLinksCache: Record = {}; + +export const parseCedarTemplateLinksDoc = ( + cedarTemplateLinksDoc: vscode.TextDocument +): TemplateLinksCacheItem => { + let cachedItem = templateLinksCache[cedarTemplateLinksDoc.uri.toString()]; + if (cachedItem && cachedItem.version === cedarTemplateLinksDoc.version) { + // console.log("parseCedarTemplateLinksDoc (cached)"); + return cachedItem; + } + + const tokensBuilder = new vscode.SemanticTokensBuilder(semanticTokensLegend); + + let linkId: string = ''; + let linkStart: vscode.Position | null = null; + let linkEnd: vscode.Position | null = null; + let linkIdRange: vscode.Range | null = null; + let depth = 0; + const links: TemplateLinkRange[] = []; + const entityTypes: vscode.Range[] = []; + + jsonc.visit(cedarTemplateLinksDoc.getText(), { + onObjectBegin(offset, length, startLine, startCharacter, pathSupplier) { + depth++; + if (pathSupplier().length === 1) { + linkStart = new vscode.Position(startLine, startCharacter); + } + }, + onObjectEnd(offset, length, startLine, startCharacter) { + depth--; + if (depth === 0) { + linkEnd = new vscode.Position(startLine, startCharacter + length); + if (linkStart && linkEnd && linkIdRange) { + const templateLinkRange: TemplateLinkRange = { + id: linkId, + range: new vscode.Range(linkStart, linkEnd), + linkIdRange: linkIdRange, + }; + links.push(templateLinkRange); + } + } + }, + onLiteralValue( + value, + offset, + length, + startLine, + startCharacter, + pathSupplier + ) { + const jsonPathLen = pathSupplier().length; + if (pathSupplier()[1] === 'link_id') { + linkId = value; + } else if (pathSupplier()[1] === 'args' && jsonPathLen === 3) { + let found = value.match(ENTITY_REGEX); + if (found?.groups) { + const type = found?.groups.type; + const typeRange = new vscode.Range( + new vscode.Position(startLine, startCharacter + 1), + new vscode.Position(startLine, startCharacter + type.length + 1) + ); + tokensBuilder.push(typeRange, 'type', []); + + entityTypes.push( + determineDefinitionRange( + type, + startLine, + startCharacter, + type.length + 1 + ) + ); + } + } + }, + onObjectProperty( + property, + offset, + length, + startLine, + startCharacter, + pathSupplier + ) { + const range = new vscode.Range( + new vscode.Position(startLine, startCharacter), + new vscode.Position(startLine, startCharacter + length) + ); + const jsonPathLen = pathSupplier().length; + if (jsonPathLen === 1) { + if (property === 'link_id') { + linkIdRange = new vscode.Range( + new vscode.Position(startLine, startCharacter + 1), + new vscode.Position(startLine, startCharacter + length - 1) + ); + } + } else if (jsonPathLen === 2) { + if (['?principal', '?resource'].includes(property)) { + tokensBuilder.push(range, 'variable', []); + } + } + }, + }); + + cachedItem = { + version: cedarTemplateLinksDoc.version, + links: links, + tokens: tokensBuilder.build(), + entityTypes: entityTypes, + }; + templateLinksCache[cedarTemplateLinksDoc.uri.toString()] = cachedItem; + + return cachedItem; +}; + +// analyze the Cedar template links JSON documents and return semantic tokens +export const templateLinksTokensProvider: vscode.DocumentSemanticTokensProvider = + { + provideDocumentSemanticTokens( + cedarTemplateLinksDoc: vscode.TextDocument + ): vscode.ProviderResult { + return parseCedarTemplateLinksDoc(cedarTemplateLinksDoc).tokens; + }, + }; + +// Cedar authorization requests (PARC) + +export type AuthCacheItem = { + version: number; + tokens: vscode.SemanticTokens; + entityTypes: vscode.Range[]; + actions: vscode.Range[]; +}; + +const authCache: Record = {}; + +export const parseCedarAuthDoc = ( + cedarAuthDoc: vscode.TextDocument +): AuthCacheItem => { + let cachedItem = authCache[cedarAuthDoc.uri.toString()]; + if (cachedItem && cachedItem.version === cedarAuthDoc.version) { + // console.log("parseCedarAuthDoc (cached)"); + return cachedItem; + } + + const tokensBuilder = new vscode.SemanticTokensBuilder(semanticTokensLegend); + const entityTypes: vscode.Range[] = []; + const actions: vscode.Range[] = []; + + jsonc.visit(cedarAuthDoc.getText(), { + onLiteralValue( + value, + offset, + length, + startLine, + startCharacter, + pathSupplier + ) { + const jsonPathLen = pathSupplier().length; + const property = pathSupplier()[0] as string; + if ( + ['principal', 'action', 'resource'].includes(property) && + jsonPathLen === 1 + ) { + let found = value.match(ENTITY_REGEX); + if (found?.groups) { + const type = found?.groups.type; + const typeRange = new vscode.Range( + new vscode.Position(startLine, startCharacter + 1), + new vscode.Position(startLine, startCharacter + type.length + 1) + ); + tokensBuilder.push(typeRange, 'type', []); + + if (property === 'action') { + const actionId = found?.groups.id; + const pos = value.lastIndexOf(actionId); + if (pos > -1) { + actions.push( + new vscode.Range( + new vscode.Position(startLine, startCharacter + pos + 2), + new vscode.Position( + startLine, + startCharacter + pos + 2 + actionId.length + ) + ) + ); + } + } else { + entityTypes.push( + determineDefinitionRange( + type, + startLine, + startCharacter, + type.length + 1 + ) + ); + } + } + } + }, + onObjectProperty( + property, + offset, + length, + startLine, + startCharacter, + pathSupplier + ) { + const range = new vscode.Range( + new vscode.Position(startLine, startCharacter), + new vscode.Position(startLine, startCharacter + length) + ); + const jsonPathLen = pathSupplier().length; + if (jsonPathLen === 0) { + if (['principal', 'action', 'resource', 'context'].includes(property)) { + tokensBuilder.push(range, 'variable', []); + } + } + }, + }); + + cachedItem = { + version: cedarAuthDoc.version, + tokens: tokensBuilder.build(), + entityTypes: entityTypes, + actions: actions, + }; + authCache[cedarAuthDoc.uri.toString()] = cachedItem; + + return cachedItem; +}; + +// analyze the Cedar request JSON documents and return semantic tokens +export const authTokensProvider: vscode.DocumentSemanticTokensProvider = { + provideDocumentSemanticTokens( + cedarAuthDoc: vscode.TextDocument + ): vscode.ProviderResult { + return parseCedarAuthDoc(cedarAuthDoc).tokens; }, }; @@ -461,7 +851,7 @@ type SchemaCacheItem = { const schemaCache: Record = {}; -export const parseCedarDocSchema = ( +export const parseCedarSchemaDoc = ( schemaDoc: vscode.TextDocument, visitSchema?: | undefined @@ -649,6 +1039,6 @@ export const schemaTokensProvider: vscode.DocumentSemanticTokensProvider = { provideDocumentSemanticTokens( cedarSchemaDoc: vscode.TextDocument ): vscode.ProviderResult { - return parseCedarDocSchema(cedarSchemaDoc).tokens; + return parseCedarSchemaDoc(cedarSchemaDoc).tokens; }, }; diff --git a/src/policy.ts b/src/policy.ts new file mode 100644 index 0000000..6420521 --- /dev/null +++ b/src/policy.ts @@ -0,0 +1,59 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +import * as vscode from 'vscode'; +import * as cedar from 'vscode-cedar-wasm'; +import { parseCedarPoliciesDoc } from './parser'; + +export const getPolicyQuickPickItems = ( + cedarDoc: vscode.TextDocument, + selection: vscode.Range +): vscode.QuickPickItem[] => { + const items: vscode.QuickPickItem[] = []; + const policyRanges = parseCedarPoliciesDoc(cedarDoc).policies; + policyRanges.forEach((policyRange, index) => { + const item: vscode.QuickPickItem = { + label: policyRange.id, + detail: cedarDoc.uri.path + .substring(cedarDoc.uri.path.lastIndexOf('/') + 1) + .replace(/\.cedar$/, `(${policyRange.id}).cedar.json`), + }; + if (policyRange.range.intersection(selection)) { + // if selection range intersects with policy, pre-select in pick list + item.picked = true; + } + items.push(item); + }); + return items; +}; + +export const exportCedarDocPolicyById = async ( + cedarDoc: vscode.TextDocument, + policyId: string, + exportFilename: string +): Promise => { + let exportJson = ''; + const policyRanges = parseCedarPoliciesDoc(cedarDoc).policies; + policyRanges.forEach((policyRange, index) => { + if (policyRange.id === policyId) { + const rawPolicy = cedarDoc.getText(policyRange.range); + const exportResult: cedar.ExportPolicyResult = + cedar.exportPolicy(rawPolicy); + + let success = exportResult.success; + if (success && exportResult.json) { + exportJson = JSON.stringify(JSON.parse(exportResult.json), null, 2); + + vscode.workspace.fs.writeFile( + vscode.Uri.file(exportFilename), + new Uint8Array(Buffer.from(exportJson)) + ); + } + + exportResult.free(); + return Promise.resolve(exportJson); + } + }); + + return Promise.resolve(exportJson); +}; diff --git a/src/test/runTest.ts b/src/test/runTest.ts deleted file mode 100644 index 014c3a2..0000000 --- a/src/test/runTest.ts +++ /dev/null @@ -1,23 +0,0 @@ -import * as path from 'path'; - -import { runTests } from '@vscode/test-electron'; - -async function main() { - try { - // The folder containing the Extension Manifest package.json - // Passed to `--extensionDevelopmentPath` - const extensionDevelopmentPath = path.resolve(__dirname, '../../'); - - // The path to test runner - // Passed to --extensionTestsPath - const extensionTestsPath = path.resolve(__dirname, './suite/index'); - - // Download VS Code, unzip it and run the integration test - await runTests({ extensionDevelopmentPath, extensionTestsPath }); - } catch (err) { - console.error('Failed to run tests'); - process.exit(1); - } -} - -main(); diff --git a/src/test/suite/cedar-wasm.test.ts b/src/test/suite/cedar-wasm.test.ts index a0d7b7c..2e2385f 100644 --- a/src/test/suite/cedar-wasm.test.ts +++ b/src/test/suite/cedar-wasm.test.ts @@ -106,6 +106,20 @@ when }); }); +suite('Cedar WASM export Suite', () => { + test('exportPolicies', async () => { + const rawPolicy = `permit ( + principal == User::"bob", + action == Action::"view", + resource == Album::"trip" +) +when { principal.age > 18 };`; + const result: cedar.ExportPolicyResult = cedar.exportPolicy(rawPolicy); + assert.equal(result.success, true); + result.free(); + }); +}); + suite('Cedar WASM validate Suite', () => { test('validate_syntax_passes_1_policy', async () => { const policy = 'permit(principal, action, resource);'; diff --git a/src/test/suite/index.ts b/src/test/suite/index.ts deleted file mode 100644 index 8ced9b1..0000000 --- a/src/test/suite/index.ts +++ /dev/null @@ -1,38 +0,0 @@ -import * as path from 'path'; -import * as Mocha from 'mocha'; -import * as glob from 'glob'; - -export function run(): Promise { - // Create the mocha test - const mocha = new Mocha({ - ui: 'tdd', - color: true, - }); - - const testsRoot = path.resolve(__dirname, '..'); - - return new Promise((c, e) => { - glob('**/**.test.js', { cwd: testsRoot }, (err, files) => { - if (err) { - return e(err); - } - - // Add files to the test suite - files.forEach((f) => mocha.addFile(path.resolve(testsRoot, f))); - - try { - // Run the mocha test - mocha.run((failures) => { - if (failures > 0) { - e(new Error(`${failures} tests failed.`)); - } else { - c(); - } - }); - } catch (err) { - console.error(err); - e(err); - } - }); - }); -} diff --git a/src/test/suite/validation.test.ts b/src/test/suite/validation.test.ts index acd9379..d987313 100644 --- a/src/test/suite/validation.test.ts +++ b/src/test/suite/validation.test.ts @@ -167,10 +167,9 @@ suite('Validation RegEx Test Suite', () => { assert(found?.groups); if (found?.groups) { assert.equal(found?.groups.type, 'actions'); - assert.equal( - found?.groups.undeclared, - '"Action::\\"test1\\"", "Action::\\"test2\\""' - ); + const actions = found?.groups.undeclared.split(', '); + assert.equal(actions.includes('"Action::\\"test1\\""'), true); + assert.equal(actions.includes('"Action::\\"test2\\""'), true); } } diff --git a/src/validate.ts b/src/validate.ts index 9f658a6..bd95b84 100644 --- a/src/validate.ts +++ b/src/validate.ts @@ -3,20 +3,17 @@ import * as vscode from 'vscode'; import * as cedar from 'vscode-cedar-wasm'; -import * as path from 'node:path'; import { addPolicyResultErrors, addSyntaxDiagnosticErrors, reportFormatterOff, } from './diagnostics'; import { - CEDAR_ENTITIES_EXTENSION_JSON, - CEDAR_ENTITIES_FILE, - CEDAR_SCHEMA_EXTENSION_JSON, - CEDAR_SCHEMA_FILE, getSchemaTextDocument, + detectEntitiesDoc, + detectSchemaDoc, } from './fileutil'; -import { parseCedarDocPolicies } from './parser'; +import { parseCedarPoliciesDoc } from './parser'; type ValidationCacheItem = { version: number; @@ -92,15 +89,9 @@ export const validateTextDocument = ( } if (doc.languageId === 'cedar') { validateCedarDoc(doc, diagnosticCollection); - } else if ( - doc.fileName.endsWith(path.sep + CEDAR_SCHEMA_FILE) || - doc.fileName.endsWith(CEDAR_SCHEMA_EXTENSION_JSON) - ) { + } else if (detectSchemaDoc(doc)) { validateSchemaDoc(doc, diagnosticCollection); - } else if ( - doc.fileName.endsWith(path.sep + CEDAR_ENTITIES_FILE) || - doc.fileName.endsWith(CEDAR_ENTITIES_EXTENSION_JSON) - ) { + } else if (detectEntitiesDoc(doc)) { validateEntitiesDoc(doc, diagnosticCollection); } }; @@ -117,7 +108,6 @@ export const validateCedarDoc = async ( return Promise.resolve(cachedItem.valid); } } - // console.log(`validateCedarDoc ${cedarDoc.uri.toString()}`); const diagnostics: vscode.Diagnostic[] = []; reportFormatterOff(cedarDoc, diagnostics); @@ -133,7 +123,7 @@ export const validateCedarDoc = async ( if (validateSchemaDoc(schemaDoc, diagnosticCollection, userInitiated)) { validationCache.associateSchemaWithDoc(schemaDoc, cedarDoc); - parseCedarDocPolicies(cedarDoc, (policyRange, policyText) => { + parseCedarPoliciesDoc(cedarDoc, (policyRange, policyText) => { const policyResult: cedar.ValidatePolicyResult = cedar.validatePolicy( schemaDoc.getText(), policyText diff --git a/syntaxes/cedarschema.tmLanguage.json b/syntaxes/cedarschema.tmLanguage.json new file mode 100644 index 0000000..e5c32d2 --- /dev/null +++ b/syntaxes/cedarschema.tmLanguage.json @@ -0,0 +1,66 @@ +{ + "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", + "name": "Cedar Schema", + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#keywords" + }, + { + "include": "#sections" + }, + { + "include": "#constants" + }, + { + "include": "#types" + }, + { + "include": "#strings" + } + ], + "repository": { + "comment": { + "name": "comment.line.double-slash.cedarschema", + "match": "//.*(?=$)" + }, + "sections": { + "patterns": [{ + "name": "keyword.cedarschema", + "match": "^\\s*(namespace|type|entity|action)\\b" + }] + }, + "keywords": { + "patterns": [{ + "name": "keyword.cedarschema", + "match": "\\b(in|appliesTo)\\b" + }] + }, + "types": { + "patterns": [{ + "name": "entity.name.type.cedarschema", + "match": "(Boolean|String|Set)" + }] + }, + "constants": { + "patterns": [{ + "name": "variable.other.constant.cedarschema", + "match": "\\b(principal|resource)\\b" + }] + }, + "strings": { + "name": "string.quoted.double.cedarschema", + "begin": "\"", + "end": "\"", + "patterns": [ + { + "name": "constant.character.escape.cedarschema", + "match": "\\\\." + } + ] + } + }, + "scopeName": "source.cedarschema" +} \ No newline at end of file diff --git a/vscode-cedar-wasm/Cargo.lock b/vscode-cedar-wasm/Cargo.lock index ff7dc01..a864504 100644 --- a/vscode-cedar-wasm/Cargo.lock +++ b/vscode-cedar-wasm/Cargo.lock @@ -49,9 +49,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" -version = "0.21.4" +version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" [[package]] name = "beef" @@ -82,9 +82,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "bumpalo" @@ -103,9 +103,9 @@ dependencies = [ [[package]] name = "cedar-policy" -version = "2.4.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78feec9b7820c34adc75e873c1fc0edb74921d8e519aa638290f212b2d04cb4a" +checksum = "3d91e3b10a0f7f2911774d5e49713c4d25753466f9e11d1cd2ec627f8a2dc857" dependencies = [ "cedar-policy-core", "cedar-policy-validator", @@ -120,9 +120,9 @@ dependencies = [ [[package]] name = "cedar-policy-core" -version = "2.4.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488935107bb2a3db66fcbbb83952c838e5b0b48efe9de72c1e9fdc5ecac31d6e" +checksum = "cd2315591c6b7e18f8038f0a0529f254235fd902b6c217aabc04f2459b0d9995" dependencies = [ "either", "ipnet", @@ -143,9 +143,9 @@ dependencies = [ [[package]] name = "cedar-policy-formatter" -version = "2.4.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88cf638841ad9d318c7e9d747fd4e050b2fb38fbe26590ef359c7e90b0d29b4a" +checksum = "4ec0e42563572fa293bd371dc42a5f0c2778ed07e12285d22795381ba4e1e0d1" dependencies = [ "cedar-policy-core", "itertools", @@ -158,9 +158,9 @@ dependencies = [ [[package]] name = "cedar-policy-validator" -version = "2.4.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2751580a3b9297906e8f685ce5a46f391f5bf0a0b09e8a7ef801056b9c68748c" +checksum = "e756e1b2a5da742ed97e65199ad6d0893e9aa4bd6b34be1de9e70bd1e6adc7df" dependencies = [ "cedar-policy-core", "itertools", @@ -189,7 +189,7 @@ dependencies = [ "iana-time-zone", "num-traits", "serde", - "windows-targets", + "windows-targets 0.48.5", ] [[package]] @@ -204,9 +204,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "crunchy" @@ -251,9 +251,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +checksum = "8eb30d70a07a3b04884d2677f06bec33509dc67ca60d92949e5535352d3191dc" dependencies = [ "powerfmt", "serde", @@ -309,12 +309,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -331,9 +331,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if", "libc", @@ -348,9 +348,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.1" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" [[package]] name = "hermit-abi" @@ -366,16 +366,16 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] @@ -406,20 +406,20 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", - "hashbrown 0.14.1", + "hashbrown 0.14.3", "serde", ] [[package]] name = "ipnet" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "is-terminal" @@ -429,7 +429,7 @@ checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi", "rustix", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -443,15 +443,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" dependencies = [ "wasm-bindgen", ] @@ -496,21 +496,32 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.149" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" + +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.4.1", + "libc", + "redox_syscall", +] [[package]] name = "linux-raw-sys" -version = "0.4.10" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -600,9 +611,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "parking_lot" @@ -616,15 +627,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", + "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.48.5", ] [[package]] @@ -634,7 +645,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", - "indexmap 2.0.2", + "indexmap 2.1.0", ] [[package]] @@ -677,9 +688,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" dependencies = [ "unicode-ident", ] @@ -704,47 +715,38 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ "getrandom", - "redox_syscall 0.2.16", + "libredox", "thiserror", ] [[package]] name = "ref-cast" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acde58d073e9c79da00f2b5b84eed919c8326832648a5b109b3fce1bb1175280" +checksum = "53313ec9f12686aeeffb43462c3ac77aa25f590a5f630eb2cde0de59417b29c7" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7473c2cfcf90008193dd0e3e16599455cb601a9fce322b5bb55de799664925" +checksum = "2566c4bf6845f2c2e83b27043c3f5dfcd5ba8f2937d6c00dc009bfb51a079dc4" dependencies = [ "proc-macro2", "quote", @@ -753,9 +755,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.1" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaac441002f822bc9705a681810a4dd2963094b9ca0ddc41cb963a4c189189ea" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", @@ -765,9 +767,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5011c7e263a695dc8ca064cddb722af1be54e517a280b12a5356f98366899e5d" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", @@ -803,15 +805,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.19" +version = "0.38.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "745ecfa778e66b2b63c88a61cb36e0eea109e803b0b86bf9879fbc77c70e86ed" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -822,9 +824,9 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "scoped-tls" @@ -840,18 +842,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.189" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.189" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", @@ -860,11 +862,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.107" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ - "indexmap 2.0.2", + "indexmap 2.1.0", "itoa", "ryu", "serde", @@ -872,15 +874,15 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ca3b16a3d82c4088f343b7480a93550b3eabe1a358569c2dfe38bbcead07237" +checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23" dependencies = [ "base64", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.0.2", + "indexmap 2.1.0", "serde", "serde_json", "serde_with_macros", @@ -889,9 +891,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e6be15c453eb305019bfa438b1593c731f36a289a7853f7707ee29e870b3b3c" +checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788" dependencies = [ "darling", "proc-macro2", @@ -907,9 +909,9 @@ checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "smallvec" -version = "1.11.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "smol_str" @@ -954,9 +956,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "2.0.38" +version = "2.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" dependencies = [ "proc-macro2", "quote", @@ -976,18 +978,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.49" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" +checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.49" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" +checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df" dependencies = [ "proc-macro2", "quote", @@ -1098,7 +1100,7 @@ checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "vscode-cedar-wasm" -version = "0.5.3" +version = "0.5.4" dependencies = [ "cedar-policy", "cedar-policy-core", @@ -1122,9 +1124,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1132,9 +1134,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" dependencies = [ "bumpalo", "log", @@ -1147,9 +1149,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" dependencies = [ "cfg-if", "js-sys", @@ -1159,9 +1161,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1169,9 +1171,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", @@ -1182,15 +1184,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" [[package]] name = "wasm-bindgen-test" -version = "0.3.37" +version = "0.3.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e6e302a7ea94f83a6d09e78e7dc7d9ca7b186bc2829c24a22d0753efd680671" +checksum = "2cf9242c0d27999b831eae4767b2a146feb0b27d332d553e605864acd2afd403" dependencies = [ "console_error_panic_hook", "js-sys", @@ -1202,19 +1204,20 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.37" +version = "0.3.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecb993dd8c836930ed130e020e77d9b2e65dd0fbab1b67c790b0f5d80b11a575" +checksum = "794645f5408c9a039fd09f4d113cdfb2e7eba5ff1956b07bcf701cf4b394fe89" dependencies = [ "proc-macro2", "quote", + "syn", ] [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" dependencies = [ "js-sys", "wasm-bindgen", @@ -1243,12 +1246,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows" -version = "0.48.0" +name = "windows-core" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", ] [[package]] @@ -1257,7 +1260,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -1266,13 +1278,28 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] @@ -1281,38 +1308,80 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" diff --git a/vscode-cedar-wasm/Cargo.toml b/vscode-cedar-wasm/Cargo.toml index 58880dd..2c522f5 100644 --- a/vscode-cedar-wasm/Cargo.toml +++ b/vscode-cedar-wasm/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "vscode-cedar-wasm" -version = "0.5.3" +version = "0.5.4" edition = "2021" -description = "WASM bindgen bindings for cedar-policy 2.4.1" +description = "WASM bindgen bindings for cedar-policy 2.4.2" license-file = "LICENSE" homepage = "https://cedarpolicy.com" repository = "https://github.com/cedar-policy/vscode-cedar" @@ -29,10 +29,10 @@ serde_json = "1.0.96" console_error_panic_hook = { version = "0.1.6", optional = true } # cedar -cedar-policy = { version = "=2.4.1" } -cedar-policy-core = { version = "=2.4.1" } -cedar-policy-formatter = { version = "=2.4.1" } -cedar-policy-validator = { version = "=2.4.1" } +cedar-policy = { version = "=2.4.2" } +cedar-policy-core = { version = "=2.4.2" } +cedar-policy-formatter = { version = "=2.4.2" } +cedar-policy-validator = { version = "=2.4.2" } miette = "5.10.0" [dev-dependencies] diff --git a/vscode-cedar-wasm/src/lib.rs b/vscode-cedar-wasm/src/lib.rs index 3b48476..35abdc9 100644 --- a/vscode-cedar-wasm/src/lib.rs +++ b/vscode-cedar-wasm/src/lib.rs @@ -7,6 +7,7 @@ mod syntax_validator; mod policy_validator; mod schema_validator; mod entities_validator; +mod policy; // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global // allocator. diff --git a/vscode-cedar-wasm/src/policy.rs b/vscode-cedar-wasm/src/policy.rs new file mode 100644 index 0000000..35133f2 --- /dev/null +++ b/vscode-cedar-wasm/src/policy.rs @@ -0,0 +1,44 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +use cedar_policy::{Policy}; +use serde::{Deserialize, Serialize}; +use wasm_bindgen::prelude::*; + +#[wasm_bindgen(typescript_custom_section)] +const EXPORT_POLICY_RESULT: &'static str = r#" +export class ExportPolicyResult { + free(): void; + readonly success: boolean; + readonly json: string | undefined; +}"#; + +#[wasm_bindgen(getter_with_clone, skip_typescript)] +#[derive(Debug, Serialize, Deserialize)] +pub struct ExportPolicyResult { + #[wasm_bindgen(readonly)] + pub success: bool, + pub json: Option, +} + +#[wasm_bindgen(js_name = exportPolicy)] +pub fn export_policy(input_policy_str: &str) -> ExportPolicyResult { + let Ok(policy) = Policy::parse(None, input_policy_str) else { + return ExportPolicyResult { + success: false, + json: None, + }; + }; + + let Ok(json) = policy.to_json() else { + return ExportPolicyResult { + success: false, + json: None, + }; + }; + + ExportPolicyResult { + success: true, + json: Some(json.to_string()), + } +} \ No newline at end of file