From e34e5294fae0623a46c409abbd2f98ab52b08684 Mon Sep 17 00:00:00 2001 From: jafaircl Date: Thu, 26 Sep 2024 21:20:00 -0400 Subject: [PATCH 01/34] feat(cel): initial commit --- .npmrc | 2 + .verdaccio/config.yml | 28 + nx.json | 19 +- package-lock.json | 24491 ++++++++++------ package.json | 27 +- packages/cel/.eslintrc.json | 23 + packages/cel/README.md | 11 + packages/cel/package.json | 10 + packages/cel/project.json | 55 + packages/cel/src/index.ts | 1 + packages/cel/src/lib/balancer.ts | 61 + packages/cel/src/lib/cel.spec.ts | 7 + packages/cel/src/lib/cel.ts | 3 + packages/cel/src/lib/conformance/go.mod | 13 + packages/cel/src/lib/conformance/go.sum | 10 + .../src/lib/conformance/testdata/README.md | 66 + .../src/lib/conformance/testdata/basic.json | 436 + .../lib/conformance/testdata/basic.textproto | 290 + .../conformance/testdata/bindings_ext.json | 46 + .../testdata/bindings_ext.textproto | 41 + .../lib/conformance/testdata/block_ext.json | 956 + .../conformance/testdata/block_ext.textproto | 1011 + .../lib/conformance/testdata/comparisons.json | 3279 +++ .../testdata/comparisons.textproto | 2373 ++ .../lib/conformance/testdata/conversions.json | 881 + .../testdata/conversions.textproto | 619 + .../src/lib/conformance/testdata/dynamic.json | 2876 ++ .../conformance/testdata/dynamic.textproto | 2288 ++ .../conformance/testdata/encoders_ext.json | 49 + .../testdata/encoders_ext.textproto | 42 + .../src/lib/conformance/testdata/enums.json | 936 + .../lib/conformance/testdata/enums.textproto | 844 + .../src/lib/conformance/testdata/fields.json | 654 + .../lib/conformance/testdata/fields.textproto | 462 + .../src/lib/conformance/testdata/fp_math.json | 230 + .../conformance/testdata/fp_math.textproto | 164 + .../conformance/testdata/integer_math.json | 557 + .../testdata/integer_math.textproto | 383 + .../src/lib/conformance/testdata/lists.json | 275 + .../lib/conformance/testdata/lists.textproto | 187 + .../src/lib/conformance/testdata/logic.json | 285 + .../lib/conformance/testdata/logic.textproto | 195 + .../src/lib/conformance/testdata/macros.json | 430 + .../lib/conformance/testdata/macros.textproto | 286 + .../lib/conformance/testdata/math_ext.json | 1323 + .../conformance/testdata/math_ext.textproto | 1263 + .../lib/conformance/testdata/namespace.json | 119 + .../conformance/testdata/namespace.textproto | 68 + .../lib/conformance/testdata/optionals.json | 585 + .../conformance/testdata/optionals.textproto | 433 + .../src/lib/conformance/testdata/parse.json | 192 + .../lib/conformance/testdata/parse.textproto | 129 + .../lib/conformance/testdata/plumbing.json | 110 + .../conformance/testdata/plumbing.textproto | 71 + .../src/lib/conformance/testdata/proto2.json | 902 + .../lib/conformance/testdata/proto2.textproto | 844 + .../lib/conformance/testdata/proto2_ext.json | 476 + .../conformance/testdata/proto2_ext.textproto | 370 + .../src/lib/conformance/testdata/proto3.json | 782 + .../lib/conformance/testdata/proto3.textproto | 746 + .../src/lib/conformance/testdata/string.json | 405 + .../lib/conformance/testdata/string.textproto | 285 + .../lib/conformance/testdata/string_ext.json | 1591 + .../conformance/testdata/string_ext.textproto | 1391 + .../lib/conformance/testdata/timestamps.json | 667 + .../conformance/testdata/timestamps.textproto | 466 + .../lib/conformance/testdata/unknowns.json | 4 + .../conformance/testdata/unknowns.textproto | 2 + .../lib/conformance/testdata/wrappers.json | 374 + .../conformance/testdata/wrappers.textproto | 371 + .../src/lib/conformance/textproto-to-json.go | 82 + packages/cel/src/lib/constants.spec.ts | 402 + packages/cel/src/lib/constants.ts | 744 + packages/cel/src/lib/environment.ts | 69 + packages/cel/src/lib/exceptions.ts | 17 + packages/cel/src/lib/gen/CEL.g4 | 191 + packages/cel/src/lib/gen/CEL.interp | 99 + packages/cel/src/lib/gen/CEL.tokens | 64 + packages/cel/src/lib/gen/CELLexer.interp | 136 + packages/cel/src/lib/gen/CELLexer.tokens | 64 + packages/cel/src/lib/gen/CELLexer.ts | 285 + packages/cel/src/lib/gen/CELListener.ts | 419 + packages/cel/src/lib/gen/CELParser.ts | 2774 ++ packages/cel/src/lib/gen/CELVisitor.ts | 269 + packages/cel/src/lib/logic-manager.ts | 83 + packages/cel/src/lib/macros.ts | 257 + packages/cel/src/lib/operators.ts | 91 + packages/cel/src/lib/program.ts | 15 + packages/cel/src/lib/standard.ts | 46 + packages/cel/src/lib/to-native.spec.ts | 122 + packages/cel/src/lib/to-native.ts | 91 + packages/cel/src/lib/utils.ts | 284 + packages/cel/src/lib/visitor.spec.ts | 1464 + packages/cel/src/lib/visitor.ts | 915 + packages/cel/tsconfig.json | 22 + packages/cel/tsconfig.lib.json | 10 + packages/cel/tsconfig.spec.json | 26 + packages/cel/vite.config.ts | 62 + project.json | 14 + tsconfig.base.json | 1 + vitest.workspace.ts | 1 + 101 files changed, 60217 insertions(+), 8773 deletions(-) create mode 100644 .npmrc create mode 100644 .verdaccio/config.yml create mode 100644 packages/cel/.eslintrc.json create mode 100644 packages/cel/README.md create mode 100644 packages/cel/package.json create mode 100644 packages/cel/project.json create mode 100644 packages/cel/src/index.ts create mode 100644 packages/cel/src/lib/balancer.ts create mode 100644 packages/cel/src/lib/cel.spec.ts create mode 100644 packages/cel/src/lib/cel.ts create mode 100644 packages/cel/src/lib/conformance/go.mod create mode 100644 packages/cel/src/lib/conformance/go.sum create mode 100644 packages/cel/src/lib/conformance/testdata/README.md create mode 100755 packages/cel/src/lib/conformance/testdata/basic.json create mode 100644 packages/cel/src/lib/conformance/testdata/basic.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/bindings_ext.json create mode 100644 packages/cel/src/lib/conformance/testdata/bindings_ext.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/block_ext.json create mode 100644 packages/cel/src/lib/conformance/testdata/block_ext.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/comparisons.json create mode 100644 packages/cel/src/lib/conformance/testdata/comparisons.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/conversions.json create mode 100644 packages/cel/src/lib/conformance/testdata/conversions.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/dynamic.json create mode 100644 packages/cel/src/lib/conformance/testdata/dynamic.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/encoders_ext.json create mode 100644 packages/cel/src/lib/conformance/testdata/encoders_ext.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/enums.json create mode 100644 packages/cel/src/lib/conformance/testdata/enums.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/fields.json create mode 100644 packages/cel/src/lib/conformance/testdata/fields.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/fp_math.json create mode 100644 packages/cel/src/lib/conformance/testdata/fp_math.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/integer_math.json create mode 100644 packages/cel/src/lib/conformance/testdata/integer_math.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/lists.json create mode 100644 packages/cel/src/lib/conformance/testdata/lists.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/logic.json create mode 100644 packages/cel/src/lib/conformance/testdata/logic.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/macros.json create mode 100644 packages/cel/src/lib/conformance/testdata/macros.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/math_ext.json create mode 100644 packages/cel/src/lib/conformance/testdata/math_ext.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/namespace.json create mode 100644 packages/cel/src/lib/conformance/testdata/namespace.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/optionals.json create mode 100644 packages/cel/src/lib/conformance/testdata/optionals.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/parse.json create mode 100644 packages/cel/src/lib/conformance/testdata/parse.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/plumbing.json create mode 100644 packages/cel/src/lib/conformance/testdata/plumbing.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/proto2.json create mode 100644 packages/cel/src/lib/conformance/testdata/proto2.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/proto2_ext.json create mode 100644 packages/cel/src/lib/conformance/testdata/proto2_ext.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/proto3.json create mode 100644 packages/cel/src/lib/conformance/testdata/proto3.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/string.json create mode 100644 packages/cel/src/lib/conformance/testdata/string.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/string_ext.json create mode 100644 packages/cel/src/lib/conformance/testdata/string_ext.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/timestamps.json create mode 100644 packages/cel/src/lib/conformance/testdata/timestamps.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/unknowns.json create mode 100644 packages/cel/src/lib/conformance/testdata/unknowns.textproto create mode 100755 packages/cel/src/lib/conformance/testdata/wrappers.json create mode 100644 packages/cel/src/lib/conformance/testdata/wrappers.textproto create mode 100644 packages/cel/src/lib/conformance/textproto-to-json.go create mode 100644 packages/cel/src/lib/constants.spec.ts create mode 100644 packages/cel/src/lib/constants.ts create mode 100644 packages/cel/src/lib/environment.ts create mode 100644 packages/cel/src/lib/exceptions.ts create mode 100644 packages/cel/src/lib/gen/CEL.g4 create mode 100644 packages/cel/src/lib/gen/CEL.interp create mode 100644 packages/cel/src/lib/gen/CEL.tokens create mode 100644 packages/cel/src/lib/gen/CELLexer.interp create mode 100644 packages/cel/src/lib/gen/CELLexer.tokens create mode 100644 packages/cel/src/lib/gen/CELLexer.ts create mode 100644 packages/cel/src/lib/gen/CELListener.ts create mode 100644 packages/cel/src/lib/gen/CELParser.ts create mode 100644 packages/cel/src/lib/gen/CELVisitor.ts create mode 100644 packages/cel/src/lib/logic-manager.ts create mode 100644 packages/cel/src/lib/macros.ts create mode 100644 packages/cel/src/lib/operators.ts create mode 100644 packages/cel/src/lib/program.ts create mode 100644 packages/cel/src/lib/standard.ts create mode 100644 packages/cel/src/lib/to-native.spec.ts create mode 100644 packages/cel/src/lib/to-native.ts create mode 100644 packages/cel/src/lib/utils.ts create mode 100644 packages/cel/src/lib/visitor.spec.ts create mode 100644 packages/cel/src/lib/visitor.ts create mode 100644 packages/cel/tsconfig.json create mode 100644 packages/cel/tsconfig.lib.json create mode 100644 packages/cel/tsconfig.spec.json create mode 100644 packages/cel/vite.config.ts create mode 100644 project.json create mode 100644 vitest.workspace.ts diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..4e5c44e --- /dev/null +++ b/.npmrc @@ -0,0 +1,2 @@ +@buf:registry=https://buf.build/gen/npm/v1/ +script-shell=zsh diff --git a/.verdaccio/config.yml b/.verdaccio/config.yml new file mode 100644 index 0000000..a007fe8 --- /dev/null +++ b/.verdaccio/config.yml @@ -0,0 +1,28 @@ +# path to a directory with all packages +storage: ../tmp/local-registry/storage + +# a list of other known repositories we can talk to +uplinks: + npmjs: + url: https://registry.npmjs.org/ + maxage: 60m + +packages: + '**': + # give all users (including non-authenticated users) full access + # because it is a local registry + access: $all + publish: $all + unpublish: $all + + # if package is not available locally, proxy requests to npm registry + proxy: npmjs + +# log settings +logs: + type: stdout + format: pretty + level: warn + +publish: + allow_offline: true # set offline to true to allow publish offline diff --git a/nx.json b/nx.json index 3d19d69..2e0c8dd 100644 --- a/nx.json +++ b/nx.json @@ -2,6 +2,9 @@ "pluginsConfig": { "@nrwl/js": { "analyzeSourceFiles": true + }, + "@nx/js": { + "analyzeSourceFiles": true } }, "extends": "nx/presets/npm.json", @@ -33,9 +36,23 @@ }, "e2e": { "cache": true + }, + "@nx/vite:build": { + "cache": true, + "dependsOn": ["^build"], + "inputs": ["production", "^production"] + }, + "@nx/vite:test": { + "cache": true, + "inputs": ["default", "^production"] } }, "parallel": 3, "useInferencePlugins": false, - "defaultBase": "main" + "defaultBase": "main", + "release": { + "version": { + "preVersionCommand": "npx nx run-many -t build" + } + } } diff --git a/package-lock.json b/package-lock.json index f762a13..d639812 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,9 @@ "version": "0.0.1", "license": "MIT", "dependencies": { + "@buf/google_cel-spec.bufbuild_es": "^2.1.0-20240829202630-b69910e4e9bc.1", + "@bufbuild/protobuf": "^2.1.0", + "antlr4": "^4.13.2", "class-transformer": "^0.5.1", "deep-freeze-strict": "^1.1.1", "fast-json-stable-stringify": "^2.1.0", @@ -20,7 +23,7 @@ "@commitlint/cli": "^14.1.0", "@commitlint/config-angular": "^14.1.0", "@commitlint/config-conventional": "^14.1.0", - "@jscutlery/semver": "^2.27.1", + "@jscutlery/semver": "^5.3.1", "@nrwl/cli": "15.0.0", "@nrwl/eslint-plugin-nx": "19.8.0", "@nrwl/jest": "19.8.0", @@ -28,11 +31,19 @@ "@nrwl/linter": "19.8.0", "@nrwl/node": "19.8.0", "@nrwl/workspace": "19.8.0", + "@nx/js": "19.8.0", + "@nx/vite": "19.8.0", + "@nx/web": "19.8.0", + "@swc-node/register": "~1.9.1", + "@swc/core": "~1.5.7", + "@swc/helpers": "~0.5.11", "@types/deep-freeze-strict": "^1.1.0", "@types/jest": "29.5.13", "@types/node": "18.19.9", "@typescript-eslint/eslint-plugin": "7.18.0", "@typescript-eslint/parser": "7.18.0", + "@vitest/coverage-v8": "^1.0.4", + "@vitest/ui": "^1.3.1", "commitizen": "^4.2.4", "cz-conventional-changelog": "^3.3.0", "eslint": "8.57.1", @@ -42,9 +53,13 @@ "nx": "19.8.0", "prettier": "2.7.1", "reflect-metadata": "^0.1.13", - "ts-jest": "28.0.8", + "ts-jest": "^29.2.5", "ts-node": "10.9.1", - "typescript": "4.8.4" + "typescript": "~5.5.2", + "verdaccio": "^5.0.4", + "vite": "^5.0.0", + "vite-plugin-dts": "~3.8.1", + "vitest": "^1.3.1" } }, "node_modules/@ampproject/remapping": { @@ -2013,6 +2028,28 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "node_modules/@buf/google_cel-spec.bufbuild_es": { + "version": "2.1.0-20240829202630-b69910e4e9bc.1", + "resolved": "https://buf.build/gen/npm/v1/@buf/google_cel-spec.bufbuild_es/-/google_cel-spec.bufbuild_es-2.1.0-20240829202630-b69910e4e9bc.1.tgz", + "dependencies": { + "@buf/googleapis_googleapis.bufbuild_es": "2.1.0-20240827201746-e7f8d366f526.1" + }, + "peerDependencies": { + "@bufbuild/protobuf": "^2.1.0" + } + }, + "node_modules/@buf/googleapis_googleapis.bufbuild_es": { + "version": "2.1.0-20240827201746-e7f8d366f526.1", + "resolved": "https://buf.build/gen/npm/v1/@buf/googleapis_googleapis.bufbuild_es/-/googleapis_googleapis.bufbuild_es-2.1.0-20240827201746-e7f8d366f526.1.tgz", + "peerDependencies": { + "@bufbuild/protobuf": "^2.1.0" + } + }, + "node_modules/@bufbuild/protobuf": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.1.0.tgz", + "integrity": "sha512-+2Mx67Y3skJ4NCD/qNSdBJNWtu6x6Qr53jeNg+QcwiL6mt0wK+3jwHH2x1p7xaYH6Ve2JKOVn0OxU35WsmqI9A==" + }, "node_modules/@commitlint/cli": { "version": "14.1.0", "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-14.1.0.tgz", @@ -2167,6 +2204,19 @@ "node": ">=v12" } }, + "node_modules/@commitlint/load/node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/@commitlint/message": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-14.0.0.tgz", @@ -2352,6 +2402,64 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@cypress/request": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.1.tgz", + "integrity": "sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==", + "dev": true, + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "http-signature": "~1.3.6", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "performance-now": "^2.1.0", + "qs": "6.10.4", + "safe-buffer": "^5.1.2", + "tough-cookie": "^4.1.3", + "tunnel-agent": "^0.6.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@cypress/request/node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/@cypress/request/node_modules/qs": { + "version": "6.10.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz", + "integrity": "sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/@emnapi/core": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.2.0.tgz", @@ -2424,589 +2532,616 @@ "typescript": ">=2.7" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=12" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", - "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], "dev": true, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=12" } }, - "node_modules/@eslint/compat": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.1.tgz", - "integrity": "sha512-lpHyRyplhGPL5mGEh6M9O5nnKk0Gz4bFI+Zu6tKlPpDUN7XshWvH9C/px4UVm87IAANE0W81CEsNGbS1KlzXpA==", + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], "dev": true, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=12" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=12" } }, - "node_modules/@eslint/eslintrc/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12" } }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" } }, - "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==", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": "*" + "node": ">=12" } }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], "dev": true, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12" } }, - "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=12" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10.10.0" + "node": ">=12" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "node": ">=12" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true - }, - "node_modules/@hutson/parse-repository-url": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", - "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/@jest/console/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/@jest/console/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/@jest/console/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/@jest/console/node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": ">=12" } }, - "node_modules/@jest/core/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/@jest/core/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/@jest/core/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/@jest/core/node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/@jest/environment/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.27.8" + "eslint-visitor-keys": "^3.3.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@jest/environment/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/@eslint-community/regexpp": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", + "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/compat": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.1.tgz", + "integrity": "sha512-lpHyRyplhGPL5mGEh6M9O5nnKk0Gz4bFI+Zu6tKlPpDUN7XshWvH9C/px4UVm87IAANE0W81CEsNGbS1KlzXpA==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "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", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@jest/environment/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "node_modules/@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" + "type-fest": "^0.20.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "dependencies": { - "jest-get-type": "^29.6.3" + "argparse": "^2.0.1" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "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": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "*" } }, - "node_modules/@jest/fake-timers/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" + "engines": { + "node": ">=10" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@jest/fake-timers/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", "dev": true, "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10.10.0" } }, - "node_modules/@jest/fake-timers/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", "dev": true }, - "node_modules/@jest/fake-timers/node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "node_modules/@hutson/parse-repository-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-5.0.0.tgz", + "integrity": "sha512-e5+YUKENATs1JgYHMzTr2MW/NDcXGfYFAuOQU8gJgF/kEh4EqKgfGrfLI67bMD4tbhZVlkigz/9YYwWcbOFthg==", "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10.13.0" } }, - "node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/@jest/globals/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/@jest/globals/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/globals/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/@jest/reporters": { + "node_modules/@jest/core": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", "dev": true, "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", "@jest/test-result": "^29.7.0", "@jest/transform": "^29.7.0", "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", + "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", + "ci-info": "^3.2.0", "exit": "^0.1.2", - "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" + "strip-ansi": "^6.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3020,100 +3155,122 @@ } } }, - "node_modules/@jest/reporters/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.27.8" + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/reporters/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dev": true, "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/reporters/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/@jest/reporters/node_modules/jest-util": { + "node_modules/@jest/expect-utils": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "jest-get-type": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/schemas": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", - "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.24.1" + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/test-result": { + "node_modules/@jest/reporters": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", "dev": true, "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/@jest/test-result/node_modules/@jest/schemas": { + "node_modules/@jest/schemas": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", @@ -3125,28 +3282,34 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/test-result/node_modules/@jest/types": { + "node_modules/@jest/source-map": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/test-result/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, "node_modules/@jest/test-sequencer": { "version": "29.7.0", @@ -3189,19 +3352,7 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/transform/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/transform/node_modules/@jest/types": { + "node_modules/@jest/types": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", @@ -3218,46 +3369,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/transform/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/@jest/transform/node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/types": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", - "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^28.1.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", @@ -3291,9 +3402,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "dev": true }, "node_modules/@jridgewell/trace-mapping": { @@ -3307,88 +3418,295 @@ } }, "node_modules/@jscutlery/semver": { - "version": "2.27.1", - "resolved": "https://registry.npmjs.org/@jscutlery/semver/-/semver-2.27.1.tgz", - "integrity": "sha512-uApRqj8Pc2CG9BbN/ZiWFz9xNq14XDueJZQnhsdO0B9CYoAZqCEoKLbToM7yRXkQ/ZRg7uV3xkrFYEWXVl1K8Q==", - "dev": true, - "dependencies": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@jscutlery/semver/-/semver-5.3.1.tgz", + "integrity": "sha512-LJk85tsYnISmRBQid4fjavBYUN8W5QwVQrcZ9KuTv+/D8Qy1A3wbMcc0kfBnnsGwFcKjYTwr4/eGJ/i1HgVk2Q==", + "dev": true, + "dependencies": { + "chalk": "4.1.2", + "conventional-changelog": "^5.1.0", + "conventional-changelog-angular": "^7.0.0", + "conventional-changelog-atom": "^4.0.0", + "conventional-changelog-codemirror": "^4.0.0", + "conventional-changelog-conventionalcommits": "^7.0.2", + "conventional-changelog-ember": "^4.0.0", + "conventional-changelog-eslint": "^5.0.0", + "conventional-changelog-express": "^4.0.0", + "conventional-changelog-jquery": "^5.0.0", + "conventional-changelog-jshint": "^4.0.0", + "conventional-commits-parser": "^5.0.0", + "conventional-recommended-bump": "^9.0.0", "detect-indent": "6.1.0", - "inquirer": "8.2.4", - "rxjs": "7.5.6", - "standard-version": "9.5.0" - }, - "engines": { - "node": ">=12.0.0" + "git-semver-tags": "^7.0.1", + "inquirer": "8.2.6", + "rxjs": "7.8.1" }, "peerDependencies": { - "@nrwl/devkit": "^14.0.0" + "@nx/devkit": "^18.0.0 || ^19.0.0" } }, - "node_modules/@jscutlery/semver/node_modules/rxjs": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.6.tgz", - "integrity": "sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw==", + "node_modules/@jscutlery/semver/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "tslib": "^2.1.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz", - "integrity": "sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==", + "node_modules/@jscutlery/semver/node_modules/conventional-changelog-angular": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", + "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==", "dev": true, "dependencies": { - "@emnapi/core": "^1.1.0", - "@emnapi/runtime": "^1.1.0", - "@tybys/wasm-util": "^0.9.0" + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=16" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@jscutlery/semver/node_modules/conventional-changelog-conventionalcommits": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-7.0.2.tgz", + "integrity": "sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==", "dev": true, "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "compare-func": "^2.0.0" }, "engines": { - "node": ">= 8" + "node": ">=16" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@jscutlery/semver/node_modules/conventional-commits-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", + "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", "dev": true, + "dependencies": { + "is-text-path": "^2.0.0", + "JSONStream": "^1.3.5", + "meow": "^12.0.1", + "split2": "^4.0.0" + }, + "bin": { + "conventional-commits-parser": "cli.mjs" + }, "engines": { - "node": ">= 8" + "node": ">=16" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@jscutlery/semver/node_modules/is-text-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", + "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", "dev": true, "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "text-extensions": "^2.0.0" }, "engines": { - "node": ">= 8" + "node": ">=8" } }, - "node_modules/@nrwl/cli": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/@nrwl/cli/-/cli-15.0.0.tgz", - "integrity": "sha512-D0zAhZ375bQnoUM2HLifMzAa75A3/lC9OkkewsiVVbqaznjEIry8ezHZepgfjFRVzLr3ue7FIpDEH3iJIYzvVw==", + "node_modules/@jscutlery/semver/node_modules/meow": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", + "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", "dev": true, - "dependencies": { - "nx": "15.0.0" + "engines": { + "node": ">=16.10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@nrwl/cli/node_modules/@nrwl/tao": { + "node_modules/@jscutlery/semver/node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@jscutlery/semver/node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dev": true, + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/@jscutlery/semver/node_modules/text-extensions": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", + "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@microsoft/api-extractor": { + "version": "7.43.0", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.43.0.tgz", + "integrity": "sha512-GFhTcJpB+MI6FhvXEI9b2K0snulNLWHqC/BbcJtyNYcKUiw7l3Lgis5ApsYncJ0leALX7/of4XfmXk+maT111w==", + "dev": true, + "dependencies": { + "@microsoft/api-extractor-model": "7.28.13", + "@microsoft/tsdoc": "0.14.2", + "@microsoft/tsdoc-config": "~0.16.1", + "@rushstack/node-core-library": "4.0.2", + "@rushstack/rig-package": "0.5.2", + "@rushstack/terminal": "0.10.0", + "@rushstack/ts-command-line": "4.19.1", + "lodash": "~4.17.15", + "minimatch": "~3.0.3", + "resolve": "~1.22.1", + "semver": "~7.5.4", + "source-map": "~0.6.1", + "typescript": "5.4.2" + }, + "bin": { + "api-extractor": "bin/api-extractor" + } + }, + "node_modules/@microsoft/api-extractor-model": { + "version": "7.28.13", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.28.13.tgz", + "integrity": "sha512-39v/JyldX4MS9uzHcdfmjjfS6cYGAoXV+io8B5a338pkHiSt+gy2eXQ0Q7cGFJ7quSa1VqqlMdlPrB6sLR/cAw==", + "dev": true, + "dependencies": { + "@microsoft/tsdoc": "0.14.2", + "@microsoft/tsdoc-config": "~0.16.1", + "@rushstack/node-core-library": "4.0.2" + } + }, + "node_modules/@microsoft/api-extractor/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@microsoft/api-extractor/node_modules/typescript": { + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", + "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/@microsoft/tsdoc": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz", + "integrity": "sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==", + "dev": true + }, + "node_modules/@microsoft/tsdoc-config": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz", + "integrity": "sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==", + "dev": true, + "dependencies": { + "@microsoft/tsdoc": "0.14.2", + "ajv": "~6.12.6", + "jju": "~1.4.0", + "resolve": "~1.19.0" + } + }, + "node_modules/@microsoft/tsdoc-config/node_modules/resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz", + "integrity": "sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==", + "dev": true, + "dependencies": { + "@emnapi/core": "^1.1.0", + "@emnapi/runtime": "^1.1.0", + "@tybys/wasm-util": "^0.9.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nrwl/cli": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/@nrwl/cli/-/cli-15.0.0.tgz", + "integrity": "sha512-D0zAhZ375bQnoUM2HLifMzAa75A3/lC9OkkewsiVVbqaznjEIry8ezHZepgfjFRVzLr3ue7FIpDEH3iJIYzvVw==", + "dev": true, + "dependencies": { + "nx": "15.0.0" + } + }, + "node_modules/@nrwl/cli/node_modules/@nrwl/tao": { "version": "15.0.0", "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-15.0.0.tgz", "integrity": "sha512-qup1eSWYwp/KVrw/wxeWBvYttQ9dcbQnqpXb5NQMD31SpXEZSpJB1i3GV/o6CF5qQQSNLwICXZx25rNTTQAqpg==", @@ -3400,6 +3718,18 @@ "tao": "index.js" } }, + "node_modules/@nrwl/cli/node_modules/@zkochan/js-yaml": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.6.tgz", + "integrity": "sha512-nzvgl3VfhcELQ8LyVrYOru+UtAy1nrygk2+AGbTm8a5YcO6o8lSjAT+pfg3vJWxIoZKOUhrK6UU7xW/+00kQrg==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/@nrwl/cli/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -3595,6 +3925,24 @@ "tao": "index.js" } }, + "node_modules/@nrwl/vite": { + "version": "19.8.0", + "resolved": "https://registry.npmjs.org/@nrwl/vite/-/vite-19.8.0.tgz", + "integrity": "sha512-Nux7PN5HYFnSbVj0lVIhgMRkfJ7AYRBr8lXDsJBFboxUtmnPGpG5aV6o/9Fu2XD/eiLBsHCmMcusqkD0+jCvMA==", + "dev": true, + "dependencies": { + "@nx/vite": "19.8.0" + } + }, + "node_modules/@nrwl/web": { + "version": "19.8.0", + "resolved": "https://registry.npmjs.org/@nrwl/web/-/web-19.8.0.tgz", + "integrity": "sha512-rYADRAx2x88iiQdqRBbFN1m9pjBwBhT7v9XCKnZRjt/vRbjszBA73WlYpiZ41FqLwpJ9BgKITDYgQ9L0V4DpGw==", + "dev": true, + "dependencies": { + "@nx/web": "19.8.0" + } + }, "node_modules/@nrwl/workspace": { "version": "19.8.0", "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.8.0.tgz", @@ -3782,41 +4130,6 @@ "yargs-parser": "21.1.1" } }, - "node_modules/@nx/jest/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@nx/jest/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@nx/jest/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, "node_modules/@nx/jest/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -3826,23 +4139,6 @@ "balanced-match": "^1.0.0" } }, - "node_modules/@nx/jest/node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/@nx/jest/node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", @@ -4175,6 +4471,65 @@ "node": ">= 10" } }, + "node_modules/@nx/vite": { + "version": "19.8.0", + "resolved": "https://registry.npmjs.org/@nx/vite/-/vite-19.8.0.tgz", + "integrity": "sha512-Krok+zalc6as1w+V+D/mmY+vh5qKdkvz4omMds2k3d+RQNxIb7Mh78ueGVQr5zRtR9CKSSPvDMtUklnjDlp1SQ==", + "dev": true, + "dependencies": { + "@nrwl/vite": "19.8.0", + "@nx/devkit": "19.8.0", + "@nx/js": "19.8.0", + "@phenomnomnominal/tsquery": "~5.0.1", + "@swc/helpers": "~0.5.0", + "enquirer": "~2.3.6", + "minimatch": "9.0.3", + "tsconfig-paths": "^4.1.2" + }, + "peerDependencies": { + "vite": "^5.0.0", + "vitest": "^1.3.1 || ^2.0.0" + } + }, + "node_modules/@nx/vite/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/@nx/vite/node_modules/minimatch": { + "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": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@nx/web": { + "version": "19.8.0", + "resolved": "https://registry.npmjs.org/@nx/web/-/web-19.8.0.tgz", + "integrity": "sha512-eP+NsnVlUAil35B6MuE5AGLPrruhlKNbkjYgExEwMEMVqFykvXY7drsxy2nhkmHJoO0IAG7emIQj+ZuFdUdKMw==", + "dev": true, + "dependencies": { + "@nrwl/web": "19.8.0", + "@nx/devkit": "19.8.0", + "@nx/js": "19.8.0", + "chalk": "^4.1.0", + "detect-port": "^1.5.1", + "http-server": "^14.1.0", + "tslib": "^2.3.0" + } + }, "node_modules/@nx/workspace": { "version": "19.8.0", "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.8.0.tgz", @@ -4229,1213 +4584,4540 @@ "typescript": "^3 || ^4 || ^5" } }, - "node_modules/@sinclair/typebox": { - "version": "0.24.46", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.46.tgz", - "integrity": "sha512-ng4ut1z2MCBhK/NwDVwIQp3pAUOCs/KNaW3cBxdFB2xTDrOuo1xuNmpr/9HHFhxqIvHrs1NTH3KJg6q+JSy1Kw==", + "node_modules/@polka/url": { + "version": "1.0.0-next.28", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz", + "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==", "dev": true }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "node_modules/@rollup/pluginutils": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.2.tgz", + "integrity": "sha512-/FIdS3PyZ39bjZlwqFnWqCOVnW7o963LtKMwQOD0NhQqw22gSr2YY1afu3FxRip4ZCZNsD5jq6Aaz6QV3D/Njw==", "dev": true, "dependencies": { - "type-detect": "4.0.8" + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } + "node_modules/@rollup/pluginutils/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz", + "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz", + "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz", + "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz", + "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz", + "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz", + "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz", + "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz", + "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz", + "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz", + "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz", + "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz", + "integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz", + "integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz", + "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz", + "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz", + "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rushstack/node-core-library": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-4.0.2.tgz", + "integrity": "sha512-hyES82QVpkfQMeBMteQUnrhASL/KHPhd7iJ8euduwNJG4mu2GSOKybf0rOEjOm1Wz7CwJEUm9y0yD7jg2C1bfg==", + "dev": true, + "dependencies": { + "fs-extra": "~7.0.1", + "import-lazy": "~4.0.0", + "jju": "~1.4.0", + "resolve": "~1.22.1", + "semver": "~7.5.4", + "z-schema": "~5.0.2" + }, + "peerDependencies": { + "@types/node": "*" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@rushstack/node-core-library/node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/@rushstack/node-core-library/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@rushstack/node-core-library/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@rushstack/node-core-library/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/@rushstack/rig-package": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.5.2.tgz", + "integrity": "sha512-mUDecIJeH3yYGZs2a48k+pbhM6JYwWlgjs2Ca5f2n1G2/kgdgP9D/07oglEGf6mRyXEnazhEENeYTSNDRCwdqA==", + "dev": true, + "dependencies": { + "resolve": "~1.22.1", + "strip-json-comments": "~3.1.1" + } + }, + "node_modules/@rushstack/terminal": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.10.0.tgz", + "integrity": "sha512-UbELbXnUdc7EKwfH2sb8ChqNgapUOdqcCIdQP4NGxBpTZV2sQyeekuK3zmfQSa/MN+/7b4kBogl2wq0vpkpYGw==", + "dev": true, + "dependencies": { + "@rushstack/node-core-library": "4.0.2", + "supports-color": "~8.1.1" + }, + "peerDependencies": { + "@types/node": "*" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@rushstack/terminal/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@rushstack/ts-command-line": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.19.1.tgz", + "integrity": "sha512-J7H768dgcpG60d7skZ5uSSwyCZs/S2HrWP1Ds8d1qYAyaaeJmpmmLr9BVw97RjFzmQPOYnoXcKA4GkqDCkduQg==", + "dev": true, + "dependencies": { + "@rushstack/terminal": "0.10.0", + "@types/argparse": "1.0.38", + "argparse": "~1.0.9", + "string-argv": "~0.3.1" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@swc-node/core": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/@swc-node/core/-/core-1.13.3.tgz", + "integrity": "sha512-OGsvXIid2Go21kiNqeTIn79jcaX4l0G93X2rAnas4LFoDyA9wAwVK7xZdm+QsKoMn5Mus2yFLCc4OtX2dD/PWA==", + "dev": true, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@swc/core": ">= 1.4.13", + "@swc/types": ">= 0.1" + } + }, + "node_modules/@swc-node/register": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@swc-node/register/-/register-1.9.2.tgz", + "integrity": "sha512-BBjg0QNuEEmJSoU/++JOXhrjWdu3PTyYeJWsvchsI0Aqtj8ICkz/DqlwtXbmZVZ5vuDPpTfFlwDBZe81zgShMA==", + "dev": true, + "dependencies": { + "@swc-node/core": "^1.13.1", + "@swc-node/sourcemap-support": "^0.5.0", + "colorette": "^2.0.20", + "debug": "^4.3.4", + "pirates": "^4.0.6", + "tslib": "^2.6.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@swc/core": ">= 1.4.13", + "typescript": ">= 4.3" + } + }, + "node_modules/@swc-node/sourcemap-support": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@swc-node/sourcemap-support/-/sourcemap-support-0.5.1.tgz", + "integrity": "sha512-JxIvIo/Hrpv0JCHSyRpetAdQ6lB27oFYhv0PKCNf1g2gUXOjpeR1exrXccRxLMuAV5WAmGFBwRnNOJqN38+qtg==", + "dev": true, + "dependencies": { + "source-map-support": "^0.5.21", + "tslib": "^2.6.3" + } + }, + "node_modules/@swc/core": { + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.5.29.tgz", + "integrity": "sha512-nvTtHJI43DUSOAf3h9XsqYg8YXKc0/N4il9y4j0xAkO0ekgDNo+3+jbw6MInawjKJF9uulyr+f5bAutTsOKVlw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.8" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.5.29", + "@swc/core-darwin-x64": "1.5.29", + "@swc/core-linux-arm-gnueabihf": "1.5.29", + "@swc/core-linux-arm64-gnu": "1.5.29", + "@swc/core-linux-arm64-musl": "1.5.29", + "@swc/core-linux-x64-gnu": "1.5.29", + "@swc/core-linux-x64-musl": "1.5.29", + "@swc/core-win32-arm64-msvc": "1.5.29", + "@swc/core-win32-ia32-msvc": "1.5.29", + "@swc/core-win32-x64-msvc": "1.5.29" + }, + "peerDependencies": { + "@swc/helpers": "*" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.5.29.tgz", + "integrity": "sha512-6F/sSxpHaq3nzg2ADv9FHLi4Fu2A8w8vP8Ich8gIl16D2htStlwnaPmCLjRswO+cFkzgVqy/l01gzNGWd4DFqA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.5.29.tgz", + "integrity": "sha512-rF/rXkvUOTdTIfoYbmszbSUGsCyvqACqy1VeP3nXONS+LxFl4bRmRcUTRrblL7IE5RTMCKUuPbqbQSE2hK7bqg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.5.29.tgz", + "integrity": "sha512-2OAPL8iWBsmmwkjGXqvuUhbmmoLxS1xNXiMq87EsnCNMAKohGc7wJkdAOUL6J/YFpean/vwMWg64rJD4pycBeg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.5.29.tgz", + "integrity": "sha512-eH/Q9+8O5qhSxMestZnhuS1xqQMr6M7SolZYxiXJqxArXYILLCF+nq2R9SxuMl0CfjHSpb6+hHPk/HXy54eIRA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.5.29.tgz", + "integrity": "sha512-TERh2OICAJz+SdDIK9+0GyTUwF6r4xDlFmpoiHKHrrD/Hh3u+6Zue0d7jQ/he/i80GDn4tJQkHlZys+RZL5UZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.5.29.tgz", + "integrity": "sha512-WMDPqU7Ji9dJpA+Llek2p9t7pcy7Bob8ggPUvgsIlv3R/eesF9DIzSbrgl6j3EAEPB9LFdSafsgf6kT/qnvqFg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.5.29.tgz", + "integrity": "sha512-DO14glwpdKY4POSN0201OnGg1+ziaSVr6/RFzuSLggshwXeeyVORiHv3baj7NENhJhWhUy3NZlDsXLnRFkmhHQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.5.29.tgz", + "integrity": "sha512-V3Y1+a1zG1zpYXUMqPIHEMEOd+rHoVnIpO/KTyFwAmKVu8v+/xPEVx/AGoYE67x4vDAAvPQrKI3Aokilqa5yVg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.5.29.tgz", + "integrity": "sha512-OrM6yfXw4wXhnVFosOJzarw0Fdz5Y0okgHfn9oFbTPJhoqxV5Rdmd6kXxWu2RiVKs6kGSJFZXHDeUq2w5rTIMg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.5.29.tgz", + "integrity": "sha512-eD/gnxqKyZQQR0hR7TMkIlJ+nCF9dzYmVVNbYZWuA1Xy94aBPUsEk3Uw3oG7q6R3ErrEUPP0FNf2ztEnv+I+dw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "dev": true + }, + "node_modules/@swc/helpers": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.13.tgz", + "integrity": "sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==", + "dev": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@swc/types": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.12.tgz", + "integrity": "sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==", + "dev": true, + "dependencies": { + "@swc/counter": "^0.1.3" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "dev": true + }, + "node_modules/@tybys/wasm-util": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", + "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", + "dev": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/argparse": { + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz", + "integrity": "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==", + "dev": true + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/deep-freeze-strict": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@types/deep-freeze-strict/-/deep-freeze-strict-1.1.0.tgz", + "integrity": "sha1-RHpqJXYZE0SqQjEBMd099cQUksQ=", + "dev": true + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.13", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.13.tgz", + "integrity": "sha512-wd+MVEZCHt23V0/L642O5APvspWply/rGY5BcW4SUETo2UzPU3Z26qr8jC2qxpimI2jjx9h7+2cj2FwIr01bXg==", + "dev": true, + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/minimist": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.19.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.9.tgz", + "integrity": "sha512-oZFKlC8l5YtzGQNT4zC2PiSSKzQVZ8bAwwd+EYdPLtyk0nSEq6O16SkK+rkkT2eflDAbormJgEF3QnH3oDrTSw==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true + }, + "node_modules/@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", + "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/type-utils": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", + "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", + "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", + "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", + "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.6.0.tgz", + "integrity": "sha512-dtePl4gsuenXVwC7dVNlb4mGDcKjDT/Ropsk4za/ouMBPplCLyznIaR+W65mvCvsyS97dymoBRrioEXI7k0XIg==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "8.6.0", + "@typescript-eslint/utils": "8.6.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.6.0.tgz", + "integrity": "sha512-rojqFZGd4MQxw33SrOy09qIDS8WEldM8JWtKQLAjf/X5mGSeEFh5ixQlxssMNyPslVIk9yzWqXCsV2eFhYrYUw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.6.0.tgz", + "integrity": "sha512-MOVAzsKJIPIlLK239l5s06YXjNqpKTVhBVDnqUumQJja5+Y94V3+4VUFRA0G60y2jNnTVwRCkhyGQpavfsbq/g==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/visitor-keys": "8.6.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.6.0.tgz", + "integrity": "sha512-wapVFfZg9H0qOYh4grNVQiMklJGluQrOUiOhYRrQWhx7BY/+I1IYb8BczWNbbUpO+pqy0rDciv3lQH5E1bCLrg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.6.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/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/@typescript-eslint/type-utils/node_modules/fast-glob": { + "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", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", + "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", + "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/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/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.6.0.tgz", + "integrity": "sha512-eNp9cWnYf36NaOVjkEUznf6fEgVy1TWpE0o52e4wtojjBx7D1UV2WAWGzR+8Y5lVFtpMLPwNbC67T83DWSph4A==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.6.0", + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/typescript-estree": "8.6.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.6.0.tgz", + "integrity": "sha512-ZuoutoS5y9UOxKvpc/GkvF4cuEmpokda4wRg64JEia27wX+PysIE9q+lzDtlHHgblwUWwo5/Qn+/WyTUvDwBHw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/visitor-keys": "8.6.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.6.0.tgz", + "integrity": "sha512-rojqFZGd4MQxw33SrOy09qIDS8WEldM8JWtKQLAjf/X5mGSeEFh5ixQlxssMNyPslVIk9yzWqXCsV2eFhYrYUw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.6.0.tgz", + "integrity": "sha512-MOVAzsKJIPIlLK239l5s06YXjNqpKTVhBVDnqUumQJja5+Y94V3+4VUFRA0G60y2jNnTVwRCkhyGQpavfsbq/g==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/visitor-keys": "8.6.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.6.0.tgz", + "integrity": "sha512-wapVFfZg9H0qOYh4grNVQiMklJGluQrOUiOhYRrQWhx7BY/+I1IYb8BczWNbbUpO+pqy0rDciv3lQH5E1bCLrg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.6.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/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/@typescript-eslint/utils/node_modules/fast-glob": { + "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", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", + "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "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/@verdaccio/auth": { + "version": "8.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/@verdaccio/auth/-/auth-8.0.0-next-8.1.tgz", + "integrity": "sha512-sPmHdnYuRSMgABCsTJEfz8tb/smONsWVg0g4KK2QycyYZ/A+RwZLV1JLiQb4wzu9zvS0HSloqWqkWlyNHW3mtw==", + "dev": true, + "dependencies": { + "@verdaccio/config": "8.0.0-next-8.1", + "@verdaccio/core": "8.0.0-next-8.1", + "@verdaccio/loaders": "8.0.0-next-8.1", + "@verdaccio/logger": "8.0.0-next-8.1", + "@verdaccio/signature": "8.0.0-next-8.0", + "@verdaccio/utils": "7.0.1-next-8.1", + "debug": "4.3.7", + "lodash": "4.17.21", + "verdaccio-htpasswd": "13.0.0-next-8.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/commons-api": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@verdaccio/commons-api/-/commons-api-10.2.0.tgz", + "integrity": "sha512-F/YZANu4DmpcEV0jronzI7v2fGVWkQ5Mwi+bVmV+ACJ+EzR0c9Jbhtbe5QyLUuzR97t8R5E/Xe53O0cc2LukdQ==", + "dev": true, + "dependencies": { + "http-errors": "2.0.0", + "http-status-codes": "2.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/commons-api/node_modules/http-status-codes": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-2.2.0.tgz", + "integrity": "sha512-feERVo9iWxvnejp3SEfm/+oNG517npqL2/PIA8ORjyOZjGC7TwCRQsZylciLS64i6pJ0wRYz3rkXLRwbtFa8Ng==", + "dev": true + }, + "node_modules/@verdaccio/config": { + "version": "8.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/@verdaccio/config/-/config-8.0.0-next-8.1.tgz", + "integrity": "sha512-goDVOH4e8xMUxjHybJpi5HwIecVFqzJ9jeNFrRUgtUUn0PtFuNMHgxOeqDKRVboZhc5HK90yed8URK/1O6VsUw==", + "dev": true, + "dependencies": { + "@verdaccio/core": "8.0.0-next-8.1", + "@verdaccio/utils": "7.0.1-next-8.1", + "debug": "4.3.7", + "js-yaml": "4.1.0", + "lodash": "4.17.21", + "minimatch": "7.4.6" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/config/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/@verdaccio/config/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/@verdaccio/config/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@verdaccio/config/node_modules/minimatch": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz", + "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@verdaccio/core": { + "version": "8.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/@verdaccio/core/-/core-8.0.0-next-8.1.tgz", + "integrity": "sha512-kQRCB2wgXEh8H88G51eQgAFK9IxmnBtkQ8sY5FbmB6PbBkyHrbGcCp+2mtRqqo36j0W1VAlfM3XzoknMy6qQnw==", + "dev": true, + "dependencies": { + "ajv": "8.17.1", + "core-js": "3.37.1", + "http-errors": "2.0.0", + "http-status-codes": "2.3.0", + "process-warning": "1.0.0", + "semver": "7.6.3" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/core/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@verdaccio/core/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/@verdaccio/core/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@verdaccio/file-locking": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/@verdaccio/file-locking/-/file-locking-10.3.1.tgz", + "integrity": "sha512-oqYLfv3Yg3mAgw9qhASBpjD50osj2AX4IwbkUtyuhhKGyoFU9eZdrbeW6tpnqUnj6yBMtAPm2eGD4BwQuX400g==", + "dev": true, + "dependencies": { + "lockfile": "1.0.4" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/loaders": { + "version": "8.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/@verdaccio/loaders/-/loaders-8.0.0-next-8.1.tgz", + "integrity": "sha512-mqGCUBs862g8mICZwX8CG92p1EZ1Un0DJ2DB7+iVu2TYaEeKoHoIdafabVdiYrbOjLcAOOBrMKE1Wnn14eLxpA==", + "dev": true, + "dependencies": { + "@verdaccio/logger": "8.0.0-next-8.1", + "debug": "4.3.7", + "lodash": "4.17.21" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/local-storage-legacy": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/@verdaccio/local-storage-legacy/-/local-storage-legacy-11.0.2.tgz", + "integrity": "sha512-7AXG7qlcVFmF+Nue2oKaraprGRtaBvrQIOvc/E89+7hAe399V01KnZI6E/ET56u7U9fq0MSlp92HBcdotlpUXg==", + "dev": true, + "dependencies": { + "@verdaccio/commons-api": "10.2.0", + "@verdaccio/file-locking": "10.3.1", + "@verdaccio/streams": "10.2.1", + "async": "3.2.4", + "debug": "4.3.4", + "lodash": "4.17.21", + "lowdb": "1.0.0", + "mkdirp": "1.0.4" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/local-storage-legacy/node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "node_modules/@verdaccio/local-storage-legacy/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@verdaccio/local-storage-legacy/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@verdaccio/local-storage-legacy/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@verdaccio/logger": { + "version": "8.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/@verdaccio/logger/-/logger-8.0.0-next-8.1.tgz", + "integrity": "sha512-w5kR0/umQkfH2F4PK5Fz9T6z3xz+twewawKLPTUfAgrVAOiWxcikGhhcHWhSGiJ0lPqIa+T0VYuLWMeVeDirGw==", + "dev": true, + "dependencies": { + "@verdaccio/logger-commons": "8.0.0-next-8.1", + "pino": "8.17.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/logger-7": { + "version": "8.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/@verdaccio/logger-7/-/logger-7-8.0.0-next-8.1.tgz", + "integrity": "sha512-V+/B1Wnct3IZ90q6HkI1a3dqbS0ds7s/5WPrS5cmBeLEw78/OGgF76XkhI2+lett7Un1CjVow7mcebOWcZ/Sqw==", + "dev": true, + "dependencies": { + "@verdaccio/logger-commons": "8.0.0-next-8.1", + "pino": "7.11.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/logger-7/node_modules/duplexify": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz", + "integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.2" + } + }, + "node_modules/@verdaccio/logger-7/node_modules/on-exit-leak-free": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz", + "integrity": "sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg==", + "dev": true + }, + "node_modules/@verdaccio/logger-7/node_modules/pino": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-7.11.0.tgz", + "integrity": "sha512-dMACeu63HtRLmCG8VKdy4cShCPKaYDR4youZqoSWLxl5Gu99HUw8bw75thbPv9Nip+H+QYX8o3ZJbTdVZZ2TVg==", + "dev": true, + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.0.0", + "on-exit-leak-free": "^0.2.0", + "pino-abstract-transport": "v0.5.0", + "pino-std-serializers": "^4.0.0", + "process-warning": "^1.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.1.0", + "safe-stable-stringify": "^2.1.0", + "sonic-boom": "^2.2.1", + "thread-stream": "^0.15.1" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/@verdaccio/logger-7/node_modules/pino-abstract-transport": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-0.5.0.tgz", + "integrity": "sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ==", + "dev": true, + "dependencies": { + "duplexify": "^4.1.2", + "split2": "^4.0.0" + } + }, + "node_modules/@verdaccio/logger-7/node_modules/pino-std-serializers": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz", + "integrity": "sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q==", + "dev": true + }, + "node_modules/@verdaccio/logger-7/node_modules/real-require": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.1.0.tgz", + "integrity": "sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/@verdaccio/logger-7/node_modules/sonic-boom": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.8.0.tgz", + "integrity": "sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg==", + "dev": true, + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, + "node_modules/@verdaccio/logger-7/node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dev": true, + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/@verdaccio/logger-7/node_modules/thread-stream": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-0.15.2.tgz", + "integrity": "sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA==", + "dev": true, + "dependencies": { + "real-require": "^0.1.0" + } + }, + "node_modules/@verdaccio/logger-commons": { + "version": "8.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/@verdaccio/logger-commons/-/logger-commons-8.0.0-next-8.1.tgz", + "integrity": "sha512-jCge//RT4uaK7MarhpzcJeJ5Uvtu/DbJ1wvJQyGiFe+9AvxDGm3EUFXvawLFZ0lzYhmLt1nvm7kevcc3vOm2ZQ==", + "dev": true, + "dependencies": { + "@verdaccio/core": "8.0.0-next-8.1", + "@verdaccio/logger-prettify": "8.0.0-next-8.0", + "colorette": "2.0.20", + "debug": "4.3.7" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/logger-prettify": { + "version": "8.0.0-next-8.0", + "resolved": "https://registry.npmjs.org/@verdaccio/logger-prettify/-/logger-prettify-8.0.0-next-8.0.tgz", + "integrity": "sha512-7mAFHZF2NPTubrOXYp2+fbMjRW5MMWXMeS3LcpupMAn5uPp6jkKEM8NC4IVJEevC5Ph4vPVZqpoPDpgXHEaV3Q==", + "dev": true, + "dependencies": { + "colorette": "2.0.20", + "dayjs": "1.11.13", + "lodash": "4.17.21", + "pino-abstract-transport": "1.1.0", + "sonic-boom": "3.8.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/middleware": { + "version": "8.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/@verdaccio/middleware/-/middleware-8.0.0-next-8.1.tgz", + "integrity": "sha512-GpAdJYky1WmOERpxPoCkVSwTTJIsVAjqf2a2uQNvi7R3UZhs059JKhWcZjJMVCGV0uz9xgQvtb3DEuYGHqyaOg==", + "dev": true, + "dependencies": { + "@verdaccio/config": "8.0.0-next-8.1", + "@verdaccio/core": "8.0.0-next-8.1", + "@verdaccio/url": "13.0.0-next-8.1", + "@verdaccio/utils": "7.0.1-next-8.1", + "debug": "4.3.7", + "express": "4.21.0", + "express-rate-limit": "5.5.1", + "lodash": "4.17.21", + "lru-cache": "7.18.3", + "mime": "2.6.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/middleware/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@verdaccio/middleware/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@verdaccio/search-indexer": { + "version": "8.0.0-next-8.0", + "resolved": "https://registry.npmjs.org/@verdaccio/search-indexer/-/search-indexer-8.0.0-next-8.0.tgz", + "integrity": "sha512-VS9axVt8XAueiPceVCgaj9nlvYj5s/T4MkAILSf2rVZeFFOMUyxU3mddUCajSHzL+YpqCuzLLL9865sRRzOJ9w==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/signature": { + "version": "8.0.0-next-8.0", + "resolved": "https://registry.npmjs.org/@verdaccio/signature/-/signature-8.0.0-next-8.0.tgz", + "integrity": "sha512-klcc2UlCvQxXDV65Qewo2rZOfv7S1y8NekS/8uurSaCTjU35T+fz+Pbqz1S9XK9oQlMp4vCQ7w3iMPWQbvphEQ==", + "dev": true, + "dependencies": { + "debug": "4.3.7", + "jsonwebtoken": "9.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/streams": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/@verdaccio/streams/-/streams-10.2.1.tgz", + "integrity": "sha512-OojIG/f7UYKxC4dYX8x5ax8QhRx1b8OYUAMz82rUottCuzrssX/4nn5QE7Ank0DUSX3C9l/HPthc4d9uKRJqJQ==", + "dev": true, + "engines": { + "node": ">=12", + "npm": ">=5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/tarball": { + "version": "13.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/@verdaccio/tarball/-/tarball-13.0.0-next-8.1.tgz", + "integrity": "sha512-58uimU2Bqt9+s+9ixy7wK/nPCqbOXhhhr/MQjl+otIlsUhSeATndhFzEctz/W+4MhUDg0tUnE9HC2yeNHHAo1Q==", + "dev": true, + "dependencies": { + "@verdaccio/core": "8.0.0-next-8.1", + "@verdaccio/url": "13.0.0-next-8.1", + "@verdaccio/utils": "7.0.1-next-8.1", + "debug": "4.3.7", + "gunzip-maybe": "^1.4.2", + "lodash": "4.17.21", + "tar-stream": "^3.1.7" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/tarball/node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "dev": true, + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/@verdaccio/ui-theme": { + "version": "8.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/@verdaccio/ui-theme/-/ui-theme-8.0.0-next-8.1.tgz", + "integrity": "sha512-9PxV8+jE2Tr+iy9DQW/bzny4YqOlW0mCZ9ct6jhcUW4GdfzU//gY2fBN/DDtQVmfbTy8smuj4Enyv5f0wCsnYg==", + "dev": true + }, + "node_modules/@verdaccio/url": { + "version": "13.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/@verdaccio/url/-/url-13.0.0-next-8.1.tgz", + "integrity": "sha512-h6pkJf+YtogImKgOrmPP9UVG3p3gtb67gqkQU0bZnK+SEKQt6Rkek/QvtJ8MbmciagYS18bDhpI8DxqLHjDfZQ==", + "dev": true, + "dependencies": { + "@verdaccio/core": "8.0.0-next-8.1", + "debug": "4.3.7", + "lodash": "4.17.21", + "validator": "13.12.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/utils": { + "version": "7.0.1-next-8.1", + "resolved": "https://registry.npmjs.org/@verdaccio/utils/-/utils-7.0.1-next-8.1.tgz", + "integrity": "sha512-cyJdRrVa+8CS7UuIQb3K3IJFjMe64v38tYiBnohSmhRbX7dX9IT3jWbjrwkqWh4KeS1CS6BYENrGG1evJ2ggrQ==", + "dev": true, + "dependencies": { + "@verdaccio/core": "8.0.0-next-8.1", + "lodash": "4.17.21", + "minimatch": "7.4.6", + "semver": "7.6.3" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/utils/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/@verdaccio/utils/node_modules/minimatch": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz", + "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@verdaccio/utils/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@vitest/coverage-v8": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-1.6.0.tgz", + "integrity": "sha512-KvapcbMY/8GYIG0rlwwOKCVNRc0OL20rrhFkg/CHNzncV03TE2XWvO5w9uZYoxNiMEBacAJt3unSOiZ7svePew==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.1", + "@bcoe/v8-coverage": "^0.2.3", + "debug": "^4.3.4", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-lib-source-maps": "^5.0.4", + "istanbul-reports": "^3.1.6", + "magic-string": "^0.30.5", + "magicast": "^0.3.3", + "picocolors": "^1.0.0", + "std-env": "^3.5.0", + "strip-literal": "^2.0.0", + "test-exclude": "^6.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "vitest": "1.6.0" + } + }, + "node_modules/@vitest/coverage-v8/node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@vitest/expect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.0.tgz", + "integrity": "sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==", + "dev": true, + "dependencies": { + "@vitest/spy": "1.6.0", + "@vitest/utils": "1.6.0", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.6.0.tgz", + "integrity": "sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==", + "dev": true, + "dependencies": { + "@vitest/utils": "1.6.0", + "p-limit": "^5.0.0", + "pathe": "^1.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner/node_modules/p-limit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@vitest/runner/node_modules/yocto-queue": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", + "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@vitest/snapshot": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.6.0.tgz", + "integrity": "sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==", + "dev": true, + "dependencies": { + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.0.tgz", + "integrity": "sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==", + "dev": true, + "dependencies": { + "tinyspy": "^2.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/ui": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-1.6.0.tgz", + "integrity": "sha512-k3Lyo+ONLOgylctiGovRKy7V4+dIN2yxstX3eY5cWFXH6WP+ooVX79YSyi0GagdTQzLmT43BF27T0s6dOIPBXA==", + "dev": true, + "dependencies": { + "@vitest/utils": "1.6.0", + "fast-glob": "^3.3.2", + "fflate": "^0.8.1", + "flatted": "^3.2.9", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "sirv": "^2.0.4" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "vitest": "1.6.0" + } + }, + "node_modules/@vitest/ui/node_modules/fast-glob": { + "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", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/@vitest/utils": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.0.tgz", + "integrity": "sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==", + "dev": true, + "dependencies": { + "diff-sequences": "^29.6.3", + "estree-walker": "^3.0.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@volar/language-core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-1.11.1.tgz", + "integrity": "sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==", + "dev": true, + "dependencies": { + "@volar/source-map": "1.11.1" + } + }, + "node_modules/@volar/source-map": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-1.11.1.tgz", + "integrity": "sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg==", + "dev": true, + "dependencies": { + "muggle-string": "^0.3.1" + } + }, + "node_modules/@volar/typescript": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-1.11.1.tgz", + "integrity": "sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ==", + "dev": true, + "dependencies": { + "@volar/language-core": "1.11.1", + "path-browserify": "^1.0.1" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.8", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.8.tgz", + "integrity": "sha512-Uzlxp91EPjfbpeO5KtC0KnXPkuTfGsNDeaKQJxQN718uz+RqDYarEf7UhQJGK+ZYloD2taUbHTI2J4WrUaZQNA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.25.3", + "@vue/shared": "3.5.8", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-core/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.8", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.8.tgz", + "integrity": "sha512-GUNHWvoDSbSa5ZSHT9SnV5WkStWfzJwwTd6NMGzilOE/HM5j+9EB9zGXdtu/fCNEmctBqMs6C9SvVPpVPuk1Eg==", + "dev": true, + "dependencies": { + "@vue/compiler-core": "3.5.8", + "@vue/shared": "3.5.8" + } + }, + "node_modules/@vue/language-core": { + "version": "1.8.27", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.27.tgz", + "integrity": "sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==", + "dev": true, + "dependencies": { + "@volar/language-core": "~1.11.1", + "@volar/source-map": "~1.11.1", + "@vue/compiler-dom": "^3.3.0", + "@vue/shared": "^3.3.0", + "computeds": "^0.0.1", + "minimatch": "^9.0.3", + "muggle-string": "^0.3.1", + "path-browserify": "^1.0.1", + "vue-template-compiler": "^2.7.14" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/language-core/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/@vue/language-core/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.8", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.8.tgz", + "integrity": "sha512-mJleSWbAGySd2RJdX1RBtcrUBX6snyOc0qHpgk3lGi4l9/P/3ny3ELqFWqYdkXIwwNN/kdm8nD9ky8o6l/Lx2A==", + "dev": true + }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, + "node_modules/@yarnpkg/parsers": { + "version": "3.0.0-rc.46", + "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.0-rc.46.tgz", + "integrity": "sha512-aiATs7pSutzda/rq8fnuPwTglyVwjM22bNnK2ZgjrpAjQHSSl3lztd2f9evst1W/qnC58DRz7T7QndUDumAR4Q==", + "dev": true, + "dependencies": { + "js-yaml": "^3.10.0", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=14.15.0" + } + }, + "node_modules/@zkochan/js-yaml": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.7.tgz", + "integrity": "sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@zkochan/js-yaml/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/add-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", + "integrity": "sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==", + "dev": true + }, + "node_modules/address": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/antlr4": { + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.13.2.tgz", + "integrity": "sha512-QiVbZhyy4xAZ17UPEuG3YTOt8ZaoeOR1CvEAqrEsDBsOqINslaB147i9xqljZqoyf5S+EUlGStaj+t22LT9MOg==", + "engines": { + "node": ">=16" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/apache-md5": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/apache-md5/-/apache-md5-1.1.8.tgz", + "integrity": "sha512-FCAJojipPn0bXjuEpjOOOMN8FZDkxfWWp4JGN9mifU2IhxvKyXZYqpzPHdnTSUpmPDy+tsslB6Z1g+Vg6nVbYA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, + "node_modules/array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dev": true, + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", + "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", + "dev": true + }, + "node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "dev": true, + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/b4a": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", + "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==", + "dev": true + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-const-enum": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-const-enum/-/babel-plugin-const-enum-1.2.0.tgz", + "integrity": "sha512-o1m/6iyyFnp9MRsK1dHF3bneqyf3AlM2q3A/YbgQr2pCat6B6XJVDv2TXqzfY2RYUi4mak6WAksSBPlyYGx9dg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-typescript": "^7.3.3", + "@babel/traverse": "^7.16.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-plugin-macros": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz", + "integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.7.2", + "cosmiconfig": "^6.0.0", + "resolve": "^1.12.0" + } + }, + "node_modules/babel-plugin-macros/node_modules/cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-macros/node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/babel-plugin-macros/node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-transform-typescript-metadata": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-typescript-metadata/-/babel-plugin-transform-typescript-metadata-0.3.2.tgz", + "integrity": "sha512-mWEvCQTgXQf48yDqgN7CH50waTyYBeP2Lpqx4nNWab9sxEpdXVeKgfj1qYI2/TgUPQtNFZ85i3PemRtnXVYYJg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/bare-events": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.4.2.tgz", + "integrity": "sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==", + "dev": true, + "optional": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dev": true, + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dev": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "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==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==", + "dev": true, + "dependencies": { + "pako": "~0.2.0" + } + }, + "node_modules/browserslist": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "dev": true + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cachedir": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.2.0.tgz", + "integrity": "sha512-VvxA0xhNqIIfg0V9AmJkDg91DaJwryutH5rVEZAhcNi4iJFj9f+QxmAjgK1LT9I8OgToX27fypX6/MeCXVbBjQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } }, - "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001662", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001662.tgz", + "integrity": "sha512-sgMUVwLmGseH8ZIrm1d51UbrhqMCH3jvS7gF/M6byuHOnKyLOBL7W8yz5V02OHwgLGA36o/AFhWzzh4uc5aqTA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", "dev": true }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "node_modules/chai": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", + "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chai/node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, - "node_modules/@tsconfig/node14": { + "node_modules/check-error": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/ci-info": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz", + "integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==", "dev": true }, - "node_modules/@tsconfig/node16": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "node_modules/cjs-module-lexer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", + "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==", "dev": true }, - "node_modules/@tybys/wasm-util": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", - "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", + "node_modules/class-transformer": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", + "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==" + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dev": true, "dependencies": { - "tslib": "^2.4.0" + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "node_modules/cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/clipanion": { + "version": "4.0.0-rc.3", + "resolved": "https://registry.npmjs.org/clipanion/-/clipanion-4.0.0-rc.3.tgz", + "integrity": "sha512-+rJOJMt2N6Oikgtfqmo/Duvme7uz3SIedL2b6ycgCztQMiTfr3aQh2DDyLHl+QUPClKMNpSg3gDJFvNQYIcq1g==", "dev": true, "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" + "typanion": "^3.8.0" + }, + "peerDependencies": { + "typanion": "*" + } + }, + "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/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "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/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "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/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/columnify": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.6.0.tgz", + "integrity": "sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==", "dev": true, "dependencies": { - "@babel/types": "^7.0.0" + "strip-ansi": "^6.0.1", + "wcwidth": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" } }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" } }, - "node_modules/@types/babel__traverse": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", - "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", "dev": true, - "dependencies": { - "@babel/types": "^7.20.7" + "optional": true, + "engines": { + "node": "^12.20.0 || >=14" } }, - "node_modules/@types/deep-freeze-strict": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@types/deep-freeze-strict/-/deep-freeze-strict-1.1.0.tgz", - "integrity": "sha1-RHpqJXYZE0SqQjEBMd099cQUksQ=", - "dev": true - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", - "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "node_modules/commitizen": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/commitizen/-/commitizen-4.2.4.tgz", + "integrity": "sha512-LlZChbDzg3Ir3O2S7jSo/cgWp5/QwylQVr59K4xayVq8S4/RdKzSyJkghAiZZHfhh5t4pxunUoyeg0ml1q/7aw==", "dev": true, "dependencies": { - "@types/node": "*" + "cachedir": "2.2.0", + "cz-conventional-changelog": "3.2.0", + "dedent": "0.7.0", + "detect-indent": "6.0.0", + "find-node-modules": "^2.1.2", + "find-root": "1.1.0", + "fs-extra": "8.1.0", + "glob": "7.1.4", + "inquirer": "6.5.2", + "is-utf8": "^0.2.1", + "lodash": "^4.17.20", + "minimist": "1.2.5", + "strip-bom": "4.0.0", + "strip-json-comments": "3.0.1" + }, + "bin": { + "commitizen": "bin/commitizen", + "cz": "bin/git-cz", + "git-cz": "bin/git-cz" + }, + "engines": { + "node": ">= 10" } }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "node_modules/commitizen/node_modules/ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "*" + "engines": { + "node": ">=4" } }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "node_modules/commitizen/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true, - "dependencies": { - "@types/istanbul-lib-report": "*" + "engines": { + "node": ">=6" } }, - "node_modules/@types/jest": { - "version": "29.5.13", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.13.tgz", - "integrity": "sha512-wd+MVEZCHt23V0/L642O5APvspWply/rGY5BcW4SUETo2UzPU3Z26qr8jC2qxpimI2jjx9h7+2cj2FwIr01bXg==", + "node_modules/commitizen/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "node_modules/@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true - }, - "node_modules/@types/node": { - "version": "18.19.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.9.tgz", - "integrity": "sha512-oZFKlC8l5YtzGQNT4zC2PiSSKzQVZ8bAwwd+EYdPLtyk0nSEq6O16SkK+rkkT2eflDAbormJgEF3QnH3oDrTSw==", + "node_modules/commitizen/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "dependencies": { - "undici-types": "~5.26.4" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true - }, - "node_modules/@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true - }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", - "dev": true - }, - "node_modules/@types/yargs": { - "version": "17.0.13", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", - "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", + "node_modules/commitizen/node_modules/cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", "dev": true, "dependencies": { - "@types/yargs-parser": "*" + "restore-cursor": "^2.0.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "node_modules/commitizen/node_modules/cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", "dev": true }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", - "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", + "node_modules/commitizen/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/type-utils": "7.18.0", - "@typescript-eslint/utils": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "color-name": "1.1.3" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", - "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", + "node_modules/commitizen/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/commitizen/node_modules/cz-conventional-changelog": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-3.2.0.tgz", + "integrity": "sha512-yAYxeGpVi27hqIilG1nh4A9Bnx4J3Ov+eXy4koL3drrR+IO9GaWPsKjik20ht608Asqi8TQPf0mczhEeyAtMzg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/utils": "7.18.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" + "chalk": "^2.4.1", + "commitizen": "^4.0.3", + "conventional-commit-types": "^3.0.0", + "lodash.map": "^4.5.1", + "longest": "^2.0.1", + "word-wrap": "^1.0.3" }, "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">= 10" + }, + "optionalDependencies": { + "@commitlint/load": ">6.1.1" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", - "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", + "node_modules/commitizen/node_modules/detect-indent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.0.0.tgz", + "integrity": "sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA==", "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0" - }, "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" + "node": ">=8" } }, - "node_modules/@typescript-eslint/parser": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", - "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", + "node_modules/commitizen/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4" - }, "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=0.8.0" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", - "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", + "node_modules/commitizen/node_modules/figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0" + "escape-string-regexp": "^1.0.5" }, "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=4" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.6.0.tgz", - "integrity": "sha512-dtePl4gsuenXVwC7dVNlb4mGDcKjDT/Ropsk4za/ouMBPplCLyznIaR+W65mvCvsyS97dymoBRrioEXI7k0XIg==", + "node_modules/commitizen/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "8.6.0", - "@typescript-eslint/utils": "8.6.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=6 <7 || >=8" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.6.0.tgz", - "integrity": "sha512-rojqFZGd4MQxw33SrOy09qIDS8WEldM8JWtKQLAjf/X5mGSeEFh5ixQlxssMNyPslVIk9yzWqXCsV2eFhYrYUw==", + "node_modules/commitizen/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=4" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.6.0.tgz", - "integrity": "sha512-MOVAzsKJIPIlLK239l5s06YXjNqpKTVhBVDnqUumQJja5+Y94V3+4VUFRA0G60y2jNnTVwRCkhyGQpavfsbq/g==", + "node_modules/commitizen/node_modules/inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.6.0", - "@typescript-eslint/visitor-keys": "8.6.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=6.0.0" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.6.0.tgz", - "integrity": "sha512-wapVFfZg9H0qOYh4grNVQiMklJGluQrOUiOhYRrQWhx7BY/+I1IYb8BczWNbbUpO+pqy0rDciv3lQH5E1bCLrg==", + "node_modules/commitizen/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true, - "dependencies": { - "@typescript-eslint/types": "8.6.0", - "eslint-visitor-keys": "^3.4.3" - }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=4" } }, - "node_modules/@typescript-eslint/type-utils/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==", + "node_modules/commitizen/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "node_modules/commitizen/node_modules/mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "node_modules/commitizen/node_modules/onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "dev": true, "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "mimic-fn": "^1.0.0" }, "engines": { - "node": ">=8.6.0" + "node": ">=4" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/commitizen/node_modules/restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=4" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "node_modules/commitizen/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=4" } }, - "node_modules/@typescript-eslint/types": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", - "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", + "node_modules/commitizen/node_modules/string-width/node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/string-width/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" + "dependencies": { + "ansi-regex": "^3.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "engines": { + "node": ">=4" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", - "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", + "node_modules/commitizen/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" + "ansi-regex": "^4.1.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=6" } }, - "node_modules/@typescript-eslint/typescript-estree/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==", + "node_modules/commitizen/node_modules/strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" + "engines": { + "node": ">=8" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/commitizen/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": { - "brace-expansion": "^2.0.1" + "has-flag": "^3.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=4" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "node_modules/commitizen/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, - "bin": { - "semver": "bin/semver.js" - }, "engines": { - "node": ">=10" + "node": ">= 4.0.0" } }, - "node_modules/@typescript-eslint/utils": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.6.0.tgz", - "integrity": "sha512-eNp9cWnYf36NaOVjkEUznf6fEgVy1TWpE0o52e4wtojjBx7D1UV2WAWGzR+8Y5lVFtpMLPwNbC67T83DWSph4A==", + "node_modules/compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.6.0", - "@typescript-eslint/types": "8.6.0", - "@typescript-eslint/typescript-estree": "8.6.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.6.0.tgz", - "integrity": "sha512-ZuoutoS5y9UOxKvpc/GkvF4cuEmpokda4wRg64JEia27wX+PysIE9q+lzDtlHHgblwUWwo5/Qn+/WyTUvDwBHw==", + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.6.0", - "@typescript-eslint/visitor-keys": "8.6.0" + "mime-db": ">= 1.43.0 < 2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">= 0.6" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.6.0.tgz", - "integrity": "sha512-rojqFZGd4MQxw33SrOy09qIDS8WEldM8JWtKQLAjf/X5mGSeEFh5ixQlxssMNyPslVIk9yzWqXCsV2eFhYrYUw==", + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.6.0.tgz", - "integrity": "sha512-MOVAzsKJIPIlLK239l5s06YXjNqpKTVhBVDnqUumQJja5+Y94V3+4VUFRA0G60y2jNnTVwRCkhyGQpavfsbq/g==", + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.6.0", - "@typescript-eslint/visitor-keys": "8.6.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "ms": "2.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.6.0.tgz", - "integrity": "sha512-wapVFfZg9H0qOYh4grNVQiMklJGluQrOUiOhYRrQWhx7BY/+I1IYb8BczWNbbUpO+pqy0rDciv3lQH5E1bCLrg==", + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/computeds": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz", + "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/confbox": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", + "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==", + "dev": true + }, + "node_modules/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", + "dev": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.6.0", - "eslint-visitor-keys": "^3.4.3" + "safe-buffer": "5.2.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">= 0.6" } }, - "node_modules/@typescript-eslint/utils/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==", + "node_modules/content-disposition/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "engines": { + "node": ">= 0.6" } }, - "node_modules/@typescript-eslint/utils/node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "node_modules/conventional-changelog": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-5.1.0.tgz", + "integrity": "sha512-aWyE/P39wGYRPllcCEZDxTVEmhyLzTc9XA6z6rVfkuCD2UBnhV/sgSOKbQrEG5z9mEZJjnopjgQooTKxEg8mAg==", "dev": true, "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "conventional-changelog-angular": "^7.0.0", + "conventional-changelog-atom": "^4.0.0", + "conventional-changelog-codemirror": "^4.0.0", + "conventional-changelog-conventionalcommits": "^7.0.2", + "conventional-changelog-core": "^7.0.0", + "conventional-changelog-ember": "^4.0.0", + "conventional-changelog-eslint": "^5.0.0", + "conventional-changelog-express": "^4.0.0", + "conventional-changelog-jquery": "^5.0.0", + "conventional-changelog-jshint": "^4.0.0", + "conventional-changelog-preset-loader": "^4.1.0" }, "engines": { - "node": ">=8.6.0" + "node": ">=16" } }, - "node_modules/@typescript-eslint/utils/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/conventional-changelog-angular": { + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", + "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "compare-func": "^2.0.0", + "q": "^1.5.1" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=10" } }, - "node_modules/@typescript-eslint/utils/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "node_modules/conventional-changelog-atom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-4.0.0.tgz", + "integrity": "sha512-q2YtiN7rnT1TGwPTwjjBSIPIzDJCRE+XAUahWxnh+buKK99Kks4WLMHoexw38GXx9OUxAsrp44f9qXe5VEMYhw==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/conventional-changelog-codemirror": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-4.0.0.tgz", + "integrity": "sha512-hQSojc/5imn1GJK3A75m9hEZZhc3urojA5gMpnar4JHmgLnuM3CUIARPpEk86glEKr3c54Po3WV/vCaO/U8g3Q==", "dev": true, - "bin": { - "semver": "bin/semver.js" - }, "engines": { - "node": ">=10" + "node": ">=16" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", - "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", + "node_modules/conventional-changelog-conventionalcommits": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.3.tgz", + "integrity": "sha512-LTTQV4fwOM4oLPad317V/QNQ1FY4Hju5qeBIM1uTHbrnCE+Eg4CdRZ3gO2pUeR+tzWdp80M2j3qFFEDWVqOV4g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.18.0", - "eslint-visitor-keys": "^3.4.3" + "compare-func": "^2.0.0", + "lodash": "^4.17.15", + "q": "^1.5.1" }, "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=10" } }, - "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/@yarnpkg/lockfile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", - "dev": true - }, - "node_modules/@yarnpkg/parsers": { - "version": "3.0.0-rc.46", - "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.0-rc.46.tgz", - "integrity": "sha512-aiATs7pSutzda/rq8fnuPwTglyVwjM22bNnK2ZgjrpAjQHSSl3lztd2f9evst1W/qnC58DRz7T7QndUDumAR4Q==", + "node_modules/conventional-changelog-core": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-7.0.0.tgz", + "integrity": "sha512-UYgaB1F/COt7VFjlYKVE/9tTzfU3VUq47r6iWf6lM5T7TlOxr0thI63ojQueRLIpVbrtHK4Ffw+yQGduw2Bhdg==", "dev": true, "dependencies": { - "js-yaml": "^3.10.0", - "tslib": "^2.4.0" + "@hutson/parse-repository-url": "^5.0.0", + "add-stream": "^1.0.0", + "conventional-changelog-writer": "^7.0.0", + "conventional-commits-parser": "^5.0.0", + "git-raw-commits": "^4.0.0", + "git-semver-tags": "^7.0.0", + "hosted-git-info": "^7.0.0", + "normalize-package-data": "^6.0.0", + "read-pkg": "^8.0.0", + "read-pkg-up": "^10.0.0" }, "engines": { - "node": ">=14.15.0" + "node": ">=16" } }, - "node_modules/@zkochan/js-yaml": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.6.tgz", - "integrity": "sha512-nzvgl3VfhcELQ8LyVrYOru+UtAy1nrygk2+AGbTm8a5YcO6o8lSjAT+pfg3vJWxIoZKOUhrK6UU7xW/+00kQrg==", + "node_modules/conventional-changelog-core/node_modules/conventional-commits-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", + "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", "dev": true, "dependencies": { - "argparse": "^2.0.1" + "is-text-path": "^2.0.0", + "JSONStream": "^1.3.5", + "meow": "^12.0.1", + "split2": "^4.0.0" }, "bin": { - "js-yaml": "bin/js-yaml.js" + "conventional-commits-parser": "cli.mjs" + }, + "engines": { + "node": ">=16" } }, - "node_modules/@zkochan/js-yaml/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "node_modules/conventional-changelog-core/node_modules/dargs": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-8.1.0.tgz", + "integrity": "sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "node_modules/conventional-changelog-core/node_modules/git-raw-commits": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-4.0.0.tgz", + "integrity": "sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==", "dev": true, + "dependencies": { + "dargs": "^8.0.0", + "meow": "^12.0.1", + "split2": "^4.0.0" + }, "bin": { - "acorn": "bin/acorn" + "git-raw-commits": "cli.mjs" }, "engines": { - "node": ">=0.4.0" + "node": ">=16" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "node_modules/conventional-changelog-core/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "node_modules/conventional-changelog-core/node_modules/is-text-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", + "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", "dev": true, + "dependencies": { + "text-extensions": "^2.0.0" + }, "engines": { - "node": ">=0.4.0" + "node": ">=8" } }, - "node_modules/add-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", - "integrity": "sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==", + "node_modules/conventional-changelog-core/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true }, - "node_modules/address": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", - "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "node_modules/conventional-changelog-core/node_modules/meow": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", + "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", "dev": true, "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "node": ">=16.10" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "node_modules/conventional-changelog-core/node_modules/normalize-package-data": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", + "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", "dev": true, + "dependencies": { + "hosted-git-info": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, "engines": { - "node": ">=6" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/conventional-changelog-core/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "type-fest": "^0.21.3" + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=10" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/conventional-changelog-core/node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", "dev": true, "engines": { - "node": ">=8" + "node": ">= 10.x" } }, - "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==", + "node_modules/conventional-changelog-core/node_modules/text-extensions": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", + "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==", "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { "node": ">=8" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "node_modules/conventional-changelog-ember": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-4.0.0.tgz", + "integrity": "sha512-D0IMhwcJUg1Y8FSry6XAplEJcljkHVlvAZddhhsdbL1rbsqRsMfGx/PIkPYq0ru5aDgn+OxhQ5N5yR7P9mfsvA==", "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, "engines": { - "node": ">= 8" + "node": ">=16" } }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/conventional-changelog-eslint": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-5.0.0.tgz", + "integrity": "sha512-6JtLWqAQIeJLn/OzUlYmzd9fKeNSWmQVim9kql+v4GrZwLx807kAJl3IJVc3jTYfVKWLxhC3BGUxYiuVEcVjgA==", "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" + "engines": { + "node": ">=16" } }, - "node_modules/array-ify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", - "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", - "dev": true - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "node_modules/conventional-changelog-express": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-4.0.0.tgz", + "integrity": "sha512-yWyy5c7raP9v7aTvPAWzqrztACNO9+FEI1FSYh7UP7YT1AkWgv5UspUeB5v3Ibv4/o60zj2o9GF2tqKQ99lIsw==", "dev": true, "engines": { - "node": ">=8" + "node": ">=16" } }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "node_modules/conventional-changelog-jquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-5.0.0.tgz", + "integrity": "sha512-slLjlXLRNa/icMI3+uGLQbtrgEny3RgITeCxevJB+p05ExiTgHACP5p3XiMKzjBn80n+Rzr83XMYfRInEtCPPw==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=16" } }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "dev": true - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "node_modules/axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "node_modules/conventional-changelog-jshint": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-4.0.0.tgz", + "integrity": "sha512-LyXq1bbl0yG0Ai1SbLxIk8ZxUOe3AjnlwE6sVRQmMgetBk+4gY9EO3d00zlEt8Y8gwsITytDnPORl8al7InTjg==", "dev": true, "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=16" } }, - "node_modules/babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "node_modules/conventional-changelog-preset-loader": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-4.1.0.tgz", + "integrity": "sha512-HozQjJicZTuRhCRTq4rZbefaiCzRM2pr6u2NL3XhrmQm4RMnDXfESU6JKu/pnKwx5xtdkYfNCsbhN5exhiKGJA==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/conventional-changelog-writer": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-7.0.1.tgz", + "integrity": "sha512-Uo+R9neH3r/foIvQ0MKcsXkX642hdm9odUp7TqgFS7BsalTcjzRlIfWZrZR1gbxOozKucaKt5KAbjW8J8xRSmA==", "dev": true, "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" + "conventional-commits-filter": "^4.0.0", + "handlebars": "^4.7.7", + "json-stringify-safe": "^5.0.1", + "meow": "^12.0.1", + "semver": "^7.5.2", + "split2": "^4.0.0" + }, + "bin": { + "conventional-changelog-writer": "cli.mjs" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=16" + } + }, + "node_modules/conventional-changelog-writer/node_modules/meow": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", + "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", + "dev": true, + "engines": { + "node": ">=16.10" }, - "peerDependencies": { - "@babel/core": "^7.8.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/babel-plugin-const-enum": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-const-enum/-/babel-plugin-const-enum-1.2.0.tgz", - "integrity": "sha512-o1m/6iyyFnp9MRsK1dHF3bneqyf3AlM2q3A/YbgQr2pCat6B6XJVDv2TXqzfY2RYUi4mak6WAksSBPlyYGx9dg==", + "node_modules/conventional-changelog-writer/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-typescript": "^7.3.3", - "@babel/traverse": "^7.16.0" + "bin": { + "semver": "bin/semver.js" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=10" } }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "node_modules/conventional-changelog-writer/node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dev": true, + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/conventional-changelog/node_modules/conventional-changelog-angular": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", + "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" + "compare-func": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=16" } }, - "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "node_modules/conventional-changelog/node_modules/conventional-changelog-conventionalcommits": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-7.0.2.tgz", + "integrity": "sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==", "dev": true, "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" + "compare-func": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=16" } }, - "node_modules/babel-plugin-istanbul/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/conventional-commit-types": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/conventional-commit-types/-/conventional-commit-types-3.0.0.tgz", + "integrity": "sha512-SmmCYnOniSsAa9GqWOeLqc179lfr5TRu5b4QFDkbsrJ5TZjPJx85wtOr3zn+1dbeNiXDKGPbZ72IKbPhLXh/Lg==", + "dev": true + }, + "node_modules/conventional-commits-filter": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-4.0.0.tgz", + "integrity": "sha512-rnpnibcSOdFcdclpFwWa+pPlZJhXE7l+XK04zxhbWrhgpR96h33QLz8hITTXbcYICxVr3HZFtbtUAQ+4LdBo9A==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "engines": { + "node": ">=16" } }, - "node_modules/babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "node_modules/conventional-commits-parser": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.3.tgz", + "integrity": "sha512-YyRDR7On9H07ICFpRm/igcdjIqebXbvf4Cff+Pf0BrBys1i1EOzx9iFXNlAbdrLAR8jf7bkUYkDAr8pEy0q4Pw==", "dev": true, "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" + "is-text-path": "^1.0.1", + "JSONStream": "^1.0.4", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "conventional-commits-parser": "cli.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" } }, - "node_modules/babel-plugin-macros": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz", - "integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==", + "node_modules/conventional-recommended-bump": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-9.0.0.tgz", + "integrity": "sha512-HR1yD0G5HgYAu6K0wJjLd7QGRK8MQDqqj6Tn1n/ja1dFwBCE6QmV+iSgQ5F7hkx7OUR/8bHpxJqYtXj2f/opPQ==", "dev": true, "dependencies": { - "@babel/runtime": "^7.7.2", - "cosmiconfig": "^6.0.0", - "resolve": "^1.12.0" + "conventional-changelog-preset-loader": "^4.1.0", + "conventional-commits-filter": "^4.0.0", + "conventional-commits-parser": "^5.0.0", + "git-raw-commits": "^4.0.0", + "git-semver-tags": "^7.0.0", + "meow": "^12.0.1" + }, + "bin": { + "conventional-recommended-bump": "cli.mjs" + }, + "engines": { + "node": ">=16" } }, - "node_modules/babel-plugin-macros/node_modules/cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "node_modules/conventional-recommended-bump/node_modules/conventional-commits-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", + "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", "dev": true, "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" + "is-text-path": "^2.0.0", + "JSONStream": "^1.3.5", + "meow": "^12.0.1", + "split2": "^4.0.0" + }, + "bin": { + "conventional-commits-parser": "cli.mjs" }, "engines": { - "node": ">=8" + "node": ">=16" } }, - "node_modules/babel-plugin-macros/node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "node_modules/conventional-recommended-bump/node_modules/dargs": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-8.1.0.tgz", + "integrity": "sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==", "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/babel-plugin-macros/node_modules/path-type": { + "node_modules/conventional-recommended-bump/node_modules/git-raw-commits": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-4.0.0.tgz", + "integrity": "sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==", "dev": true, + "dependencies": { + "dargs": "^8.0.0", + "meow": "^12.0.1", + "split2": "^4.0.0" + }, + "bin": { + "git-raw-commits": "cli.mjs" + }, "engines": { - "node": ">=8" + "node": ">=16" } }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", - "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "node_modules/conventional-recommended-bump/node_modules/is-text-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", + "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.2", - "semver": "^6.3.1" + "text-extensions": "^2.0.0" }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "engines": { + "node": ">=8" } }, - "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/conventional-recommended-bump/node_modules/meow": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", + "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "engines": { + "node": ">=16.10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.10.6", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", - "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "node_modules/conventional-recommended-bump/node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2", - "core-js-compat": "^3.38.0" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "engines": { + "node": ">= 10.x" } }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", - "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "node_modules/conventional-recommended-bump/node_modules/text-extensions": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", + "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==", "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2" + "engines": { + "node": ">=8" }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/babel-plugin-transform-typescript-metadata": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-typescript-metadata/-/babel-plugin-transform-typescript-metadata-0.3.2.tgz", - "integrity": "sha512-mWEvCQTgXQf48yDqgN7CH50waTyYBeP2Lpqx4nNWab9sxEpdXVeKgfj1qYI2/TgUPQtNFZ85i3PemRtnXVYYJg==", + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0" + "engines": { + "node": ">= 0.6" } }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", - "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, + "node_modules/core-js": { + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.37.1.tgz", + "integrity": "sha512-Xn6qmxrQZyB0FFY8E3bgRXei3lWDJHhvI+u0q9TKIYM49G8pAr0FgnnrFRAmsbptZL1yxRADVXn+x5AGsbBfyw==", + "dev": true, + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", + "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", "dev": true, "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5" + "browserslist": "^4.23.3" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" } }, - "node_modules/babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", "dev": true, "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" + "object-assign": "^4", + "vary": "^1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">= 0.10" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "node_modules/corser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", + "integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "node_modules/cosmiconfig": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "node_modules/cosmiconfig/node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, "engines": { "node": ">=8" }, @@ -5443,1784 +9125,1873 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "node_modules/cosmiconfig/node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" + "engines": { + "node": ">=8" } }, - "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==", + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": ">=8" + "node": ">= 8" } }, - "node_modules/browserslist": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "node_modules/cz-conventional-changelog": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-3.3.0.tgz", + "integrity": "sha512-U466fIzU5U22eES5lTNiNbZ+d8dfcHcssH4o7QsdWaCcRs/feIPCxKYSWkYBNs5mny7MvEfwpTLWjvbm94hecw==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "dependencies": { - "caniuse-lite": "^1.0.30001646", - "electron-to-chromium": "^1.5.4", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" - }, - "bin": { - "browserslist": "cli.js" + "chalk": "^2.4.1", + "commitizen": "^4.0.3", + "conventional-commit-types": "^3.0.0", + "lodash.map": "^4.5.1", + "longest": "^2.0.1", + "word-wrap": "^1.0.3" }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "node": ">= 10" + }, + "optionalDependencies": { + "@commitlint/load": ">6.1.1" } }, - "node_modules/bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "node_modules/cz-conventional-changelog/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "dependencies": { - "fast-json-stable-stringify": "2.x" + "color-convert": "^1.9.0" }, "engines": { - "node": ">= 6" + "node": ">=4" } }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "node_modules/cz-conventional-changelog/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "dependencies": { - "node-int64": "^0.4.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "node_modules/cz-conventional-changelog/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "color-name": "1.1.3" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "node_modules/cz-conventional-changelog/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "node_modules/cachedir": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.2.0.tgz", - "integrity": "sha512-VvxA0xhNqIIfg0V9AmJkDg91DaJwryutH5rVEZAhcNi4iJFj9f+QxmAjgK1LT9I8OgToX27fypX6/MeCXVbBjQ==", + "node_modules/cz-conventional-changelog/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/cz-conventional-changelog/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/cz-conventional-changelog/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": ">=6" + "node": ">=4" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "node_modules/dargs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", + "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", "dev": true, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + }, "engines": { - "node": ">=6" + "node": ">=0.10" } }, - "node_modules/camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "dev": true + }, + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "dependencies": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" + "ms": "^2.1.3" }, "engines": { - "node": ">=8" + "node": ">=6.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001662", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001662.tgz", - "integrity": "sha512-sgMUVwLmGseH8ZIrm1d51UbrhqMCH3jvS7gF/M6byuHOnKyLOBL7W8yz5V02OHwgLGA36o/AFhWzzh4uc5aqTA==", + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "node_modules/decamelize-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", "dev": true, "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/chardet": { + "node_modules/dedent": { "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", "dev": true }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "node_modules/deep-eql": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", "dev": true, "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "type-detect": "^4.0.0" }, "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "node": ">=6" } }, - "node_modules/ci-info": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz", - "integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==", - "dev": true + "node_modules/deep-freeze-strict": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-freeze-strict/-/deep-freeze-strict-1.1.1.tgz", + "integrity": "sha1-d9BYPKJKab5LvZrC+uQV1VUj5bA=" }, - "node_modules/cjs-module-lexer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", - "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==", + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "node_modules/class-transformer": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", - "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==" + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", "dev": true, "dependencies": { - "restore-cursor": "^3.1.0" + "clone": "^1.0.2" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-spinners": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", - "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/cli-width": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", "dev": true, "engines": { - "node": ">= 10" + "node": ">=8" } }, - "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==", + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "engines": { + "node": ">=0.4.0" } }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, "engines": { - "node": ">=0.8" + "node": ">= 0.8" } }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "dev": true, "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/collect-v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", - "dev": true - }, - "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==", + "node_modules/detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, "engines": { - "node": ">=7.0.0" + "node": ">=0.10.0" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/columnify": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.6.0.tgz", - "integrity": "sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==", + "node_modules/detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", "dev": true, - "dependencies": { - "strip-ansi": "^6.0.1", - "wcwidth": "^1.0.0" - }, "engines": { - "node": ">=8.0.0" + "node": ">=8" } }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, "engines": { - "node": ">= 0.8" + "node": ">=8" } }, - "node_modules/commitizen": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/commitizen/-/commitizen-4.2.4.tgz", - "integrity": "sha512-LlZChbDzg3Ir3O2S7jSo/cgWp5/QwylQVr59K4xayVq8S4/RdKzSyJkghAiZZHfhh5t4pxunUoyeg0ml1q/7aw==", + "node_modules/detect-port": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.6.1.tgz", + "integrity": "sha512-CmnVc+Hek2egPx1PeTFVta2W78xy2K/9Rkf6cC4T59S50tVnzKj+tnx5mmx5lwvCkujZ4uRrpRSuV+IVs3f90Q==", "dev": true, "dependencies": { - "cachedir": "2.2.0", - "cz-conventional-changelog": "3.2.0", - "dedent": "0.7.0", - "detect-indent": "6.0.0", - "find-node-modules": "^2.1.2", - "find-root": "1.1.0", - "fs-extra": "8.1.0", - "glob": "7.1.4", - "inquirer": "6.5.2", - "is-utf8": "^0.2.1", - "lodash": "^4.17.20", - "minimist": "1.2.5", - "strip-bom": "4.0.0", - "strip-json-comments": "3.0.1" + "address": "^1.0.1", + "debug": "4" }, "bin": { - "commitizen": "bin/commitizen", - "cz": "bin/git-cz", - "git-cz": "bin/git-cz" + "detect": "bin/detect-port.js", + "detect-port": "bin/detect-port.js" }, "engines": { - "node": ">= 10" + "node": ">= 4.0.0" } }, - "node_modules/commitizen/node_modules/ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, "engines": { - "node": ">=4" + "node": ">=0.3.1" } }, - "node_modules/commitizen/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, "engines": { - "node": ">=6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/commitizen/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, "dependencies": { - "color-convert": "^1.9.0" + "path-type": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/commitizen/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/dir-glob/node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/commitizen/node_modules/cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "dependencies": { - "restore-cursor": "^2.0.0" + "esutils": "^2.0.2" }, "engines": { - "node": ">=4" + "node": ">=6.0.0" } }, - "node_modules/commitizen/node_modules/cli-width": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", - "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", - "dev": true - }, - "node_modules/commitizen/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", "dev": true, "dependencies": { - "color-name": "1.1.3" + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/commitizen/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/commitizen/node_modules/cz-conventional-changelog": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-3.2.0.tgz", - "integrity": "sha512-yAYxeGpVi27hqIilG1nh4A9Bnx4J3Ov+eXy4koL3drrR+IO9GaWPsKjik20ht608Asqi8TQPf0mczhEeyAtMzg==", + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", "dev": true, - "dependencies": { - "chalk": "^2.4.1", - "commitizen": "^4.0.3", - "conventional-commit-types": "^3.0.0", - "lodash.map": "^4.5.1", - "longest": "^2.0.1", - "word-wrap": "^1.0.3" - }, "engines": { - "node": ">= 10" + "node": ">=12" }, - "optionalDependencies": { - "@commitlint/load": ">6.1.1" + "funding": { + "url": "https://dotenvx.com" } }, - "node_modules/commitizen/node_modules/detect-indent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.0.0.tgz", - "integrity": "sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA==", + "node_modules/dotenv-expand": { + "version": "11.0.6", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz", + "integrity": "sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==", "dev": true, + "dependencies": { + "dotenv": "^16.4.4" + }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" } }, - "node_modules/commitizen/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true + }, + "node_modules/duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", "dev": true, - "engines": { - "node": ">=0.8.0" + "dependencies": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" } }, - "node_modules/commitizen/node_modules/figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "node_modules/duplexify/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=4" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/commitizen/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "node_modules/duplexify/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" + "safe-buffer": "~5.1.0" } }, - "node_modules/commitizen/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", "dev": true, - "engines": { - "node": ">=4" + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" } }, - "node_modules/commitizen/node_modules/inquirer": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", - "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", "dev": true, "dependencies": { - "ansi-escapes": "^3.2.0", - "chalk": "^2.4.2", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.3", - "figures": "^2.0.0", - "lodash": "^4.17.12", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rxjs": "^6.4.0", - "string-width": "^2.1.0", - "strip-ansi": "^5.1.0", - "through": "^2.3.6" - }, - "engines": { - "node": ">=6.0.0" + "safe-buffer": "^5.0.1" } }, - "node_modules/commitizen/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", "dev": true, + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/commitizen/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } + "node_modules/electron-to-chromium": { + "version": "1.5.27", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.27.tgz", + "integrity": "sha512-o37j1vZqCoEgBuWWXLHQgTN/KDKe7zwpiY5CPeq2RvUqOyJw9xnrULzZAEVQ5p4h+zjMk7hgtOoPdnLxr7m/jw==", + "dev": true }, - "node_modules/commitizen/node_modules/mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true, "engines": { - "node": ">=4" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" } }, - "node_modules/commitizen/node_modules/mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "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/commitizen/node_modules/onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "dev": true, - "dependencies": { - "mimic-fn": "^1.0.0" - }, "engines": { - "node": ">=4" + "node": ">= 0.8" } }, - "node_modules/commitizen/node_modules/restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, "dependencies": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=4" + "once": "^1.4.0" } }, - "node_modules/commitizen/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", "dev": true, "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "ansi-colors": "^4.1.1" }, "engines": { - "node": ">=4" + "node": ">=8.6" } }, - "node_modules/commitizen/node_modules/string-width/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true, "engines": { - "node": ">=4" + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/commitizen/node_modules/string-width/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "node_modules/envinfo": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", + "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" + "bin": { + "envinfo": "dist/cli.js" }, "engines": { "node": ">=4" } }, - "node_modules/commitizen/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" + "is-arrayish": "^0.2.1" } }, - "node_modules/commitizen/node_modules/strip-json-comments": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", - "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/commitizen/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==", + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, "engines": { - "node": ">=4" + "node": ">= 0.4" } }, - "node_modules/commitizen/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, "engines": { - "node": ">= 4.0.0" + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" } }, - "node_modules/compare-func": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", - "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, - "dependencies": { - "array-ify": "^1.0.0", - "dot-prop": "^5.1.0" + "engines": { + "node": ">=6" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", "dev": true }, - "node_modules/concat-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", - "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, - "engines": [ - "node >= 6.0" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.0.2", - "typedarray": "^0.0.6" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/confusing-browser-globals": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", - "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", - "dev": true - }, - "node_modules/conventional-changelog": { - "version": "3.1.25", - "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-3.1.25.tgz", - "integrity": "sha512-ryhi3fd1mKf3fSjbLXOfK2D06YwKNic1nC9mWqybBHdObPd8KJ2vjaXZfYj1U23t+V8T8n0d7gwnc9XbIdFbyQ==", + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", "dev": true, "dependencies": { - "conventional-changelog-angular": "^5.0.12", - "conventional-changelog-atom": "^2.0.8", - "conventional-changelog-codemirror": "^2.0.8", - "conventional-changelog-conventionalcommits": "^4.5.0", - "conventional-changelog-core": "^4.2.1", - "conventional-changelog-ember": "^2.0.9", - "conventional-changelog-eslint": "^3.0.9", - "conventional-changelog-express": "^2.0.6", - "conventional-changelog-jquery": "^3.0.11", - "conventional-changelog-jshint": "^2.0.9", - "conventional-changelog-preset-loader": "^2.3.4" + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@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", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" }, "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/conventional-changelog-angular": { - "version": "5.0.13", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", - "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, - "dependencies": { - "compare-func": "^2.0.0", - "q": "^1.5.1" + "bin": { + "eslint-config-prettier": "bin/cli.js" }, - "engines": { - "node": ">=10" + "peerDependencies": { + "eslint": ">=7.0.0" } }, - "node_modules/conventional-changelog-atom": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-2.0.8.tgz", - "integrity": "sha512-xo6v46icsFTK3bb7dY/8m2qvc8sZemRgdqLb/bjpBsH2UyOS8rKNTgcb5025Hri6IpANPApbXMg15QLb1LJpBw==", + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "dependencies": { - "q": "^1.5.1" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/conventional-changelog-codemirror": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-2.0.8.tgz", - "integrity": "sha512-z5DAsn3uj1Vfp7po3gpt2Boc+Bdwmw2++ZHa5Ak9k0UKsYAO5mH1UBTN0qSCuJZREIhX6WU4E1p3IW2oRCNzQw==", + "node_modules/eslint/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "dependencies": { - "q": "^1.5.1" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/conventional-changelog-config-spec": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-config-spec/-/conventional-changelog-config-spec-2.1.0.tgz", - "integrity": "sha512-IpVePh16EbbB02V+UA+HQnnPIohgXvJRxHcS5+Uwk4AT5LjzCZJm5sp/yqs5C6KZJ1jMsV4paEV13BN1pvDuxQ==", - "dev": true - }, - "node_modules/conventional-changelog-conventionalcommits": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.3.tgz", - "integrity": "sha512-LTTQV4fwOM4oLPad317V/QNQ1FY4Hju5qeBIM1uTHbrnCE+Eg4CdRZ3gO2pUeR+tzWdp80M2j3qFFEDWVqOV4g==", + "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, "dependencies": { - "compare-func": "^2.0.0", - "lodash": "^4.17.15", - "q": "^1.5.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">=10" + "node": ">=10.13.0" } }, - "node_modules/conventional-changelog-core": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz", - "integrity": "sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg==", + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "dependencies": { - "add-stream": "^1.0.0", - "conventional-changelog-writer": "^5.0.0", - "conventional-commits-parser": "^3.2.0", - "dateformat": "^3.0.0", - "get-pkg-repo": "^4.0.0", - "git-raw-commits": "^2.0.8", - "git-remote-origin-url": "^2.0.0", - "git-semver-tags": "^4.1.1", - "lodash": "^4.17.15", - "normalize-package-data": "^3.0.0", - "q": "^1.5.1", - "read-pkg": "^3.0.0", - "read-pkg-up": "^3.0.0", - "through2": "^4.0.0" + "type-fest": "^0.20.2" }, "engines": { - "node": ">=10" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/conventional-changelog-ember": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-2.0.9.tgz", - "integrity": "sha512-ulzIReoZEvZCBDhcNYfDIsLTHzYHc7awh+eI44ZtV5cx6LVxLlVtEmcO+2/kGIHGtw+qVabJYjdI5cJOQgXh1A==", + "node_modules/eslint/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "dependencies": { - "q": "^1.5.1" + "argparse": "^2.0.1" }, - "engines": { - "node": ">=10" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/conventional-changelog-eslint": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.9.tgz", - "integrity": "sha512-6NpUCMgU8qmWmyAMSZO5NrRd7rTgErjrm4VASam2u5jrZS0n38V7Y9CzTtLT2qwz5xEChDR4BduoWIr8TfwvXA==", + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "dependencies": { - "q": "^1.5.1" + "p-locate": "^5.0.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/conventional-changelog-express": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-2.0.6.tgz", - "integrity": "sha512-SDez2f3iVJw6V563O3pRtNwXtQaSmEfTCaTBPCqn0oG0mfkq0rX4hHBq5P7De2MncoRixrALj3u3oQsNK+Q0pQ==", + "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": { - "q": "^1.5.1" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=10" + "node": "*" } }, - "node_modules/conventional-changelog-jquery": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-3.0.11.tgz", - "integrity": "sha512-x8AWz5/Td55F7+o/9LQ6cQIPwrCjfJQ5Zmfqi8thwUEKHstEn4kTIofXub7plf1xvFA2TqhZlq7fy5OmV6BOMw==", + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "dependencies": { - "q": "^1.5.1" + "yocto-queue": "^0.1.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/conventional-changelog-jshint": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-2.0.9.tgz", - "integrity": "sha512-wMLdaIzq6TNnMHMy31hql02OEQ8nCQfExw1SE0hYL5KvU+JCTuPaDO+7JiogGT2gJAxiUGATdtYYfh+nT+6riA==", + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "dependencies": { - "compare-func": "^2.0.0", - "q": "^1.5.1" + "p-limit": "^3.0.2" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/conventional-changelog-preset-loader": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz", - "integrity": "sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==", + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/conventional-changelog-writer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz", - "integrity": "sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ==", + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "dependencies": { - "conventional-commits-filter": "^2.0.7", - "dateformat": "^3.0.0", - "handlebars": "^4.7.7", - "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "semver": "^6.0.0", - "split": "^1.0.0", - "through2": "^4.0.0" - }, - "bin": { - "conventional-changelog-writer": "cli.js" + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/conventional-changelog-writer/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, "bin": { - "semver": "bin/semver.js" + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" } }, - "node_modules/conventional-commit-types": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/conventional-commit-types/-/conventional-commit-types-3.0.0.tgz", - "integrity": "sha512-SmmCYnOniSsAa9GqWOeLqc179lfr5TRu5b4QFDkbsrJ5TZjPJx85wtOr3zn+1dbeNiXDKGPbZ72IKbPhLXh/Lg==", - "dev": true - }, - "node_modules/conventional-commits-filter": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz", - "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==", + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, "dependencies": { - "lodash.ismatch": "^4.4.0", - "modify-values": "^1.0.0" + "estraverse": "^5.1.0" }, "engines": { - "node": ">=10" + "node": ">=0.10" } }, - "node_modules/conventional-commits-parser": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.3.tgz", - "integrity": "sha512-YyRDR7On9H07ICFpRm/igcdjIqebXbvf4Cff+Pf0BrBys1i1EOzx9iFXNlAbdrLAR8jf7bkUYkDAr8pEy0q4Pw==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "dependencies": { - "is-text-path": "^1.0.1", - "JSONStream": "^1.0.4", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - }, - "bin": { - "conventional-commits-parser": "cli.js" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=10" + "node": ">=4.0" } }, - "node_modules/conventional-recommended-bump": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-6.1.0.tgz", - "integrity": "sha512-uiApbSiNGM/kkdL9GTOLAqC4hbptObFo4wW2QRyHsKciGAfQuLU1ShZ1BIVI/+K2BE/W1AWYQMCXAsv4dyKPaw==", + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "dependencies": { - "concat-stream": "^2.0.0", - "conventional-changelog-preset-loader": "^2.3.4", - "conventional-commits-filter": "^2.0.7", - "conventional-commits-parser": "^3.2.0", - "git-raw-commits": "^2.0.8", - "git-semver-tags": "^4.1.1", - "meow": "^8.0.0", - "q": "^1.5.1" - }, - "bin": { - "conventional-recommended-bump": "cli.js" - }, "engines": { - "node": ">=10" + "node": ">=4.0" } }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/core-js-compat": { - "version": "3.38.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", - "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", "dev": true, "dependencies": { - "browserslist": "^4.23.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" + "@types/estree": "^1.0.0" } }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "dev": true, - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, "engines": { - "node": ">=10" + "node": ">= 0.6" } }, - "node_modules/cosmiconfig/node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/cosmiconfig/node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "dev": true, "engines": { - "node": ">=8" + "node": ">=0.8.x" } }, - "node_modules/create-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", - "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "prompts": "^2.0.1" - }, - "bin": { - "create-jest": "bin/create-jest.js" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/create-jest/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.8.0" } }, - "node_modules/create-jest/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", "dev": true, "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "homedir-polyfill": "^1.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/create-jest/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/create-jest/node_modules/jest-util": { + "node_modules/expect": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dev": true, "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "node_modules/express": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", + "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", + "dev": true, + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.10", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express-rate-limit": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.5.1.tgz", + "integrity": "sha512-MTjE2eIbHv5DyfuFz4zLYWxpqVhEhkTiwFGuB74Q9CSou2WHO52nlE5y3Zlg6SIsiYUIPj6ifFxnkPz6O3sIUg==", + "dev": true + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "node_modules/express/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "node_modules/cz-conventional-changelog": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-3.3.0.tgz", - "integrity": "sha512-U466fIzU5U22eES5lTNiNbZ+d8dfcHcssH4o7QsdWaCcRs/feIPCxKYSWkYBNs5mny7MvEfwpTLWjvbm94hecw==", - "dev": true, - "dependencies": { - "chalk": "^2.4.1", - "commitizen": "^4.0.3", - "conventional-commit-types": "^3.0.0", - "lodash.map": "^4.5.1", - "longest": "^2.0.1", - "word-wrap": "^1.0.3" - }, - "engines": { - "node": ">= 10" - }, - "optionalDependencies": { - "@commitlint/load": ">6.1.1" - } + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true }, - "node_modules/cz-conventional-changelog/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", "dev": true, "dependencies": { - "color-convert": "^1.9.0" + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" }, "engines": { "node": ">=4" } }, - "node_modules/cz-conventional-changelog/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/external-editor/node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "os-tmpdir": "~1.0.2" }, "engines": { - "node": ">=4" + "node": ">=0.6.0" } }, - "node_modules/cz-conventional-changelog/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", "dev": true, - "dependencies": { - "color-name": "1.1.3" - } + "engines": [ + "node >=0.6.0" + ] }, - "node_modules/cz-conventional-changelog/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "node_modules/cz-conventional-changelog/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "dev": true }, - "node_modules/cz-conventional-changelog/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "node_modules/fast-glob": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", + "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/cz-conventional-changelog/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==", + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fast-redact": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", + "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/dargs": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", - "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true + }, + "node_modules/fast-uri": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", + "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "reusify": "^1.0.4" } }, - "node_modules/dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, - "engines": { - "node": "*" + "dependencies": { + "bser": "2.1.1" } }, - "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "dev": true + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, "dependencies": { - "ms": "^2.1.3" + "escape-string-regexp": "^1.0.5" }, "engines": { - "node": ">=6.0" + "node": ">=8" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=0.8.0" } }, - "node_modules/decamelize-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", - "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" + "flat-cache": "^3.0.4" }, "engines": { - "node": ">=0.10.0" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/decamelize-keys/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "minimatch": "^5.0.1" } }, - "node_modules/dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", - "dev": true - }, - "node_modules/deep-freeze-strict": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-freeze-strict/-/deep-freeze-strict-1.1.1.tgz", - "integrity": "sha1-d9BYPKJKab5LvZrC+uQV1VUj5bA=" - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "node_modules/filelist/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, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "balanced-match": "^1.0.0" } }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "dependencies": { - "clone": "^1.0.2" + "brace-expansion": "^2.0.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=10" } }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, "engines": { "node": ">=8" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, "engines": { - "node": ">=0.4.0" + "node": ">= 0.8" } }, - "node_modules/detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/find-node-modules": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/find-node-modules/-/find-node-modules-2.1.2.tgz", + "integrity": "sha512-x+3P4mbtRPlSiVE1Qco0Z4YLU8WFiFcuWTf3m75OV9Uzcfs2Bg+O9N+r/K0AnmINBW06KpfqKwYJbFlFq4qNug==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "findup-sync": "^4.0.0", + "merge": "^2.1.0" } }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "dev": true + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, "engines": { "node": ">=8" } }, - "node_modules/detect-port": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.6.1.tgz", - "integrity": "sha512-CmnVc+Hek2egPx1PeTFVta2W78xy2K/9Rkf6cC4T59S50tVnzKj+tnx5mmx5lwvCkujZ4uRrpRSuV+IVs3f90Q==", + "node_modules/findup-sync": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz", + "integrity": "sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==", "dev": true, "dependencies": { - "address": "^1.0.1", - "debug": "4" - }, - "bin": { - "detect": "bin/detect-port.js", - "detect-port": "bin/detect-port.js" + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^4.0.2", + "resolve-dir": "^1.0.1" }, "engines": { - "node": ">= 4.0.0" + "node": ">= 8" } }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, - "engines": { - "node": ">=0.3.1" + "bin": { + "flat": "cli.js" } }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "node_modules/flat-cache": { + "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", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], "engines": { - "node": ">=8" + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } } }, - "node_modules/dir-glob/node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", "dev": true, "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dev": true, "dependencies": { - "esutils": "^2.0.2" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" }, "engines": { - "node": ">=6.0.0" + "node": ">= 6" } }, - "node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "dev": true, - "dependencies": { - "is-obj": "^2.0.0" - }, "engines": { - "node": ">=8" + "node": ">= 0.6" } }, - "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "dev": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" + "node": ">= 0.6" } }, - "node_modules/dotenv-expand": { - "version": "11.0.6", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz", - "integrity": "sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==", + "node_modules/front-matter": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/front-matter/-/front-matter-4.0.2.tgz", + "integrity": "sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==", "dev": true, "dependencies": { - "dotenv": "^16.4.4" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" + "js-yaml": "^3.13.1" } }, - "node_modules/dotgitignore": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/dotgitignore/-/dotgitignore-2.1.0.tgz", - "integrity": "sha512-sCm11ak2oY6DglEPpCB8TixLjWAxd3kJTs6UIcSasNYxXdFPV+YKlye92c8H4kKFqV5qYMIh7d+cYecEg0dIkA==", + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, "dependencies": { - "find-up": "^3.0.0", - "minimatch": "^3.0.4" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=6" + "node": ">=12" } }, - "node_modules/dotgitignore/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/dotgitignore/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/dotgitignore/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, "engines": { - "node": ">=6" + "node": ">=6.9.0" } }, - "node_modules/dotgitignore/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, "engines": { - "node": ">=4" + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "engines": { + "node": "*" + } }, - "node_modules/ejs": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", - "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "dependencies": { - "jake": "^10.8.5" - }, - "bin": { - "ejs": "bin/cli.js" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/electron-to-chromium": { - "version": "1.5.27", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.27.tgz", - "integrity": "sha512-o37j1vZqCoEgBuWWXLHQgTN/KDKe7zwpiY5CPeq2RvUqOyJw9xnrULzZAEVQ5p4h+zjMk7hgtOoPdnLxr7m/jw==", - "dev": true + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } }, - "node_modules/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "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/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", "dev": true, "dependencies": { - "once": "^1.4.0" + "assert-plus": "^1.0.0" } }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "node_modules/git-raw-commits": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.10.tgz", + "integrity": "sha512-sHhX5lsbG9SOO6yXdlwgEMQ/ljIn7qMpAbJZCGfXX2fq5T8M5SrDnpYk9/4HswTildcIqatsWa91vty6VhWSaQ==", "dev": true, "dependencies": { - "ansi-colors": "^4.1.1" + "dargs": "^7.0.0", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "git-raw-commits": "cli.js" }, "engines": { - "node": ">=8.6" + "node": ">=10" } }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "node_modules/git-semver-tags": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-7.0.1.tgz", + "integrity": "sha512-NY0ZHjJzyyNXHTDZmj+GG7PyuAKtMsyWSwh07CR2hOZFa+/yoTsXci/nF2obzL8UDhakFNkD9gNdt/Ed+cxh2Q==", "dev": true, "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, + "meow": "^12.0.1", + "semver": "^7.5.2" + }, + "bin": { + "git-semver-tags": "cli.mjs" + }, "engines": { - "node": ">=6" + "node": ">=16" } }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/git-semver-tags/node_modules/meow": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", + "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", "dev": true, "engines": { - "node": ">=10" + "node": ">=16.10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "node_modules/git-semver-tags/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", - "@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", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, - "bin": { - "eslint": "bin/eslint.js" + "engines": { + "node": "*" + } + }, + "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": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 6" + } + }, + "node_modules/global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "dev": true, + "dependencies": { + "ini": "^1.3.4" }, - "funding": { - "url": "https://opencollective.com/eslint" + "engines": { + "node": ">=4" } }, - "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "node_modules/global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" + "dependencies": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" }, - "peerDependencies": { - "eslint": ">=7.0.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "node_modules/global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", "dev": true, "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" }, - "funding": { - "url": "https://opencollective.com/eslint" + "bin": { + "which": "bin/which" } }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/globals": { + "version": "15.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", + "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=18" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" }, "engines": { "node": ">=10" @@ -7229,1480 +11000,1747 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/globby/node_modules/fast-glob": { + "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": { - "is-glob": "^4.0.3" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" }, "engines": { - "node": ">=10.13.0" + "node": ">=8.6.0" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "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": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" + "get-intrinsic": "^1.1.3" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "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/gunzip-maybe": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/gunzip-maybe/-/gunzip-maybe-1.4.2.tgz", + "integrity": "sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==", "dev": true, "dependencies": { - "argparse": "^2.0.1" + "browserify-zlib": "^0.1.4", + "is-deflate": "^1.0.0", + "is-gzip": "^1.0.0", + "peek-stream": "^1.1.0", + "pumpify": "^1.3.3", + "through2": "^2.0.3" }, "bin": { - "js-yaml": "bin/js-yaml.js" + "gunzip-maybe": "bin.js" } }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/gunzip-maybe/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "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==", + "node_modules/gunzip-maybe/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" + "safe-buffer": "~5.1.0" } }, - "node_modules/eslint/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/gunzip-maybe/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "dependencies": { - "yocto-queue": "^0.1.0" + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" }, "engines": { - "node": ">=10" + "node": ">=0.4.7" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "optionalDependencies": { + "uglify-js": "^3.1.4" } }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/harmony-reflect": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", + "integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==", + "dev": true + }, + "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/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "dependencies": { - "p-limit": "^3.0.2" + "es-define-property": "^1.0.0" }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "dev": true, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "function-bind": "^1.1.2" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">= 0.4" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" + "he": "bin/he" } }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", "dev": true, "dependencies": { - "estraverse": "^5.1.0" + "parse-passwd": "^1.0.0" }, "engines": { - "node": ">=0.10" + "node": ">=0.10.0" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", "dev": true, "dependencies": { - "estraverse": "^5.2.0" + "lru-cache": "^6.0.0" }, "engines": { - "node": ">=4.0" + "node": ">=10" } }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "node_modules/html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", "dev": true, + "dependencies": { + "whatwg-encoding": "^2.0.0" + }, "engines": { - "node": ">=4.0" + "node": ">=12" } }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dev": true, "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "node": ">= 0.8" } }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, "engines": { - "node": ">= 0.8.0" + "node": ">=8.0.0" } }, - "node_modules/expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "node_modules/http-server": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz", + "integrity": "sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==", "dev": true, "dependencies": { - "homedir-polyfill": "^1.0.1" + "basic-auth": "^2.0.1", + "chalk": "^4.1.2", + "corser": "^2.0.1", + "he": "^1.2.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy": "^1.18.1", + "mime": "^1.6.0", + "minimist": "^1.2.6", + "opener": "^1.5.1", + "portfinder": "^1.0.28", + "secure-compare": "3.0.1", + "union": "~0.5.0", + "url-join": "^4.0.1" + }, + "bin": { + "http-server": "bin/http-server" }, "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "node_modules/http-server/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/expect/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/http-server/node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/expect/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/http-signature": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", + "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", "dev": true, "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "assert-plus": "^1.0.0", + "jsprim": "^2.0.2", + "sshpk": "^1.14.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10" } }, - "node_modules/expect/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "node_modules/http-status-codes": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-2.3.0.tgz", + "integrity": "sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==", "dev": true }, - "node_modules/expect/node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dev": true, "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "agent-base": "6", + "debug": "4" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 6" } }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, "engines": { - "node": ">=4" + "node": ">=10.17.0" } }, - "node_modules/external-editor/node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "node_modules/husky": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.4.tgz", + "integrity": "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==", "dev": true, - "dependencies": { - "os-tmpdir": "~1.0.2" + "bin": { + "husky": "lib/bin.js" }, "engines": { - "node": ">=0.6.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" } }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "node_modules/identity-obj-proxy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", + "integrity": "sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==", "dev": true, "dependencies": { - "reusify": "^1.0.4" + "harmony-reflect": "^1.4.6" + }, + "engines": { + "node": ">=4" } }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "dev": true, - "dependencies": { - "bser": "2.1.1" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "engines": { + "node": ">= 4" } }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "node_modules/immer": { + "version": "9.0.15", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.15.tgz", + "integrity": "sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "dependencies": { - "escape-string-regexp": "^1.0.5" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/figures/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, "engines": { - "node": ">=0.8.0" + "node": ">=4" } }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "node_modules/import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/filelist": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", - "dev": true, - "dependencies": { - "minimatch": "^5.0.1" + "node": ">=8" } }, - "node_modules/filelist/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==", + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0" + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/filelist/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, "engines": { - "node": ">=10" + "node": ">=0.8.19" } }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, "engines": { "node": ">=8" } }, - "node_modules/find-node-modules": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/find-node-modules/-/find-node-modules-2.1.2.tgz", - "integrity": "sha512-x+3P4mbtRPlSiVE1Qco0Z4YLU8WFiFcuWTf3m75OV9Uzcfs2Bg+O9N+r/K0AnmINBW06KpfqKwYJbFlFq4qNug==", + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "dependencies": { - "findup-sync": "^4.0.0", - "merge": "^2.1.0" + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/inquirer": { + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", + "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", "dev": true, "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^6.0.1" }, "engines": { - "node": ">=8" + "node": ">=12.0.0" } }, - "node_modules/findup-sync": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz", - "integrity": "sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==", + "node_modules/inquirer/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^4.0.2", - "resolve-dir": "^1.0.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "node_modules/inquirer/node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", "dev": true, - "bin": { - "flat": "cli.js" + "dependencies": { + "tslib": "^2.1.0" } }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "node_modules/inquirer/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=8" } }, - "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true - }, - "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } + "node": ">= 0.10" } }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "binary-extensions": "^2.0.0" }, "engines": { - "node": ">= 6" + "node": ">=8" } }, - "node_modules/front-matter": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/front-matter/-/front-matter-4.0.2.tgz", - "integrity": "sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==", + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", "dev": true, "dependencies": { - "js-yaml": "^3.13.1" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fs-constants": { + "node_modules/is-deflate": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "resolved": "https://registry.npmjs.org/is-deflate/-/is-deflate-1.0.0.tgz", + "integrity": "sha512-YDoFpuZWu1VRXlsnlYMzKyVRITXj7Ej/V9gXQ2/pAe7X1J7M/RNOqaIYi6qUn+B7nGyB9pDXrv02dsB58d2ZAQ==", "dev": true }, - "node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "bin": { + "is-docker": "cli.js" }, "engines": { - "node": ">=12" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">=0.10.0" } }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "engines": { - "node": ">=6.9.0" + "node": ">=8" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true, "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": ">=6" } }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, "engines": { - "node": ">=8.0.0" + "node": ">=0.10.0" } }, - "node_modules/get-pkg-repo": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", - "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==", + "node_modules/is-gzip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", + "integrity": "sha512-rcfALRIb1YewtnksfRIHGcIY93QnK8BIQ/2c9yDYcG/Y6+vRoJuTWBmmSEbyLLYtXm7q35pHOHbZFQBaLrhlWQ==", "dev": true, - "dependencies": { - "@hutson/parse-repository-url": "^3.0.0", - "hosted-git-info": "^4.0.0", - "through2": "^2.0.0", - "yargs": "^16.2.0" - }, - "bin": { - "get-pkg-repo": "src/cli.js" - }, "engines": { - "node": ">=6.9.0" + "node": ">=0.10.0" } }, - "node_modules/get-pkg-repo/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "engines": { + "node": ">=8" } }, - "node_modules/get-pkg-repo/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" + "engines": { + "node": ">=0.12.0" } }, - "node_modules/get-pkg-repo/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "engines": { + "node": ">=8" } }, - "node_modules/get-pkg-repo/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "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": ">=8" } }, - "node_modules/get-pkg-repo/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", "dev": true, "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/git-raw-commits": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.10.tgz", - "integrity": "sha512-sHhX5lsbG9SOO6yXdlwgEMQ/ljIn7qMpAbJZCGfXX2fq5T8M5SrDnpYk9/4HswTildcIqatsWa91vty6VhWSaQ==", + "node_modules/is-text-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", + "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=", "dev": true, "dependencies": { - "dargs": "^7.0.0", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - }, - "bin": { - "git-raw-commits": "cli.js" + "text-extensions": "^1.0.0" }, "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/git-remote-origin-url": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", - "integrity": "sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw==", - "dev": true, - "dependencies": { - "gitconfiglocal": "^1.0.0", - "pify": "^2.3.0" - }, - "engines": { - "node": ">=4" - } + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true }, - "node_modules/git-semver-tags": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-4.1.1.tgz", - "integrity": "sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==", + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, - "dependencies": { - "meow": "^8.0.0", - "semver": "^6.0.0" - }, - "bin": { - "git-semver-tags": "cli.js" - }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/git-semver-tags/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/gitconfiglocal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", - "integrity": "sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ==", + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "dev": true, "dependencies": { - "ini": "^1.3.2" + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, "engines": { - "node": "*" + "node": ">=8" } }, - "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==", + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", "dev": true, "dependencies": { - "is-glob": "^4.0.1" + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" }, "engines": { - "node": ">= 6" + "node": ">=10" } }, - "node_modules/global-dirs": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "ini": "^1.3.4" + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=4" + "node": ">=10" } }, - "node_modules/global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "dependencies": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, "dependencies": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dev": true, "dependencies": { - "isexe": "^2.0.0" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/globals": { - "version": "15.9.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", - "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", - "dev": true, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "node_modules/jake": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", + "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", "dev": true, "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globby/node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "node_modules/jake/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=8.6.0" + "node": "*" } }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "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/handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" }, "bin": { - "handlebars": "bin/handlebars" + "jest": "bin/jest.js" }, "engines": { - "node": ">=0.4.7" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true, - "engines": { - "node": ">=6" + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/harmony-reflect": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", - "integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==", - "dev": true - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dev": true, "dependencies": { - "function-bind": "^1.1.1" + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" }, "engines": { - "node": ">= 0.4.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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/jest-changed-files/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", "dev": true, "dependencies": { - "parse-passwd": "^1.0.0" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "node_modules/jest-circus/node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "lru-cache": "^6.0.0" + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" }, "engines": { - "node": ">=10" + "node": ">=10", + "npm": ">=6" } }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true + "node_modules/jest-circus/node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "node_modules/jest-circus/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, "engines": { - "node": ">=10.17.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/husky": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.4.tgz", - "integrity": "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==", + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, "bin": { - "husky": "lib/bin.js" + "jest": "bin/jest.js" }, "engines": { - "node": ">=12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/typicode" + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dev": true, "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } } }, - "node_modules/identity-obj-proxy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", - "integrity": "sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==", + "node_modules/jest-config/node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "dependencies": { - "harmony-reflect": "^1.4.6" + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, "engines": { - "node": ">= 4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/immer": { - "version": "9.0.15", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.15.tgz", - "integrity": "sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/immer" + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dev": true, "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, "engines": { - "node": ">=4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/import-local": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", - "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, "engines": { - "node": ">=0.8.19" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/inquirer": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz", - "integrity": "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==", + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, "dependencies": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.1", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.21", - "mute-stream": "0.0.8", - "ora": "^5.4.1", - "run-async": "^2.4.0", - "rxjs": "^7.5.5", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6", - "wrap-ansi": "^7.0.0" + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" }, "engines": { - "node": ">=12.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/inquirer/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" + "node": ">=6" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } } }, - "node_modules/inquirer/node_modules/rxjs": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz", - "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==", + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, - "dependencies": { - "tslib": "^2.1.0" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, "dependencies": { - "binary-extensions": "^2.0.0" + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-core-module": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", - "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", "dev": true, "dependencies": { - "has": "^1.0.3" + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "node_modules/jest-resolve/node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", "dev": true, - "bin": { - "is-docker": "cli.js" - }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=10" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/jest-runner/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "node_modules/jest-runner/node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", "dev": true, - "engines": { - "node": ">=6" + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", "dev": true, "dependencies": { - "is-extglob": "^2.1.1" + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">=0.12.0" + "node": ">=10" } }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-text-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", - "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=", + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "dependencies": { - "text-extensions": "^1.0.0" + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "node_modules/jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", "dev": true }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, - "dependencies": { - "is-docker": "^2.0.0" + "bin": { + "jsesc": "bin/jsesc" }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, + "bin": { + "json5": "lib/cli.js" + }, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/istanbul-lib-instrument": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", - "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "node_modules/jsonc-eslint-parser": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonc-eslint-parser/-/jsonc-eslint-parser-2.4.0.tgz", + "integrity": "sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==", "dev": true, "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" + "acorn": "^8.5.0", + "eslint-visitor-keys": "^3.0.0", + "espree": "^9.0.0", + "semver": "^7.3.5" }, "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" } }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { + "node_modules/jsonc-eslint-parser/node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", @@ -8714,2532 +12752,2231 @@ "node": ">=10" } }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" + "universalify": "^2.0.0" }, - "engines": { - "node": ">=10" + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } + "engines": [ + "node >= 0.2.0" + ] }, - "node_modules/jake": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", - "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", "dev": true, "dependencies": { - "async": "^3.2.3", - "chalk": "^4.0.2", - "filelist": "^1.0.4", - "minimatch": "^3.1.2" + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" }, "bin": { - "jake": "bin/cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jake/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" + "JSONStream": "bin.js" }, "engines": { "node": "*" } }, - "node_modules/jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", - "dev": true, - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/types": "^29.6.3", - "import-local": "^3.0.2", - "jest-cli": "^29.7.0" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-changed-files": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", - "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", "dev": true, "dependencies": { - "execa": "^5.0.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0" + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12", + "npm": ">=6" } }, - "node_modules/jest-changed-files/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/jsonwebtoken/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" } }, - "node_modules/jest-changed-files/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/jsprim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", + "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", "dev": true, + "engines": [ + "node >=0.6.0" + ], "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" } }, - "node_modules/jest-changed-files/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true + "node_modules/just-extend": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.1.1.tgz", + "integrity": "sha512-1UWaMWIB90HnIZAmXOTLobwWc9lc1ZMUBRKf8PaozCAiNUif6wv1fyeXpqccWZCu7L9zxIgXG55vARuZluyvqw==" }, - "node_modules/jest-changed-files/node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", "dev": true, "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" } }, - "node_modules/jest-changed-files/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", "dev": true, "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" } }, - "node_modules/jest-circus": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", - "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^1.0.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.7.0", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.7.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "json-buffer": "3.0.1" } }, - "node_modules/jest-circus/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } - }, - "node_modules/jest-circus/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6" } }, - "node_modules/jest-circus/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "node_modules/kolorist": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", + "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", "dev": true }, - "node_modules/jest-circus/node_modules/dedent": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", - "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true, - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" - }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } + "engines": { + "node": ">=6" } }, - "node_modules/jest-circus/node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.8.0" } }, - "node_modules/jest-circus/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "node_modules/local-pkg": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", + "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", "dev": true, "dependencies": { - "yocto-queue": "^0.1.0" + "mlly": "^1.4.2", + "pkg-types": "^1.0.3" }, "engines": { - "node": ">=10" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/jest-cli": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", - "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "dependencies": { - "@jest/core": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "create-jest": "^29.7.0", - "exit": "^0.1.2", - "import-local": "^3.0.2", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "yargs": "^17.3.1" - }, - "bin": { - "jest": "bin/jest.js" + "p-locate": "^4.1.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": ">=8" } }, - "node_modules/jest-cli/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/lockfile": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lockfile/-/lockfile-1.0.4.tgz", + "integrity": "sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "signal-exit": "^3.0.2" } }, - "node_modules/jest-cli/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true }, - "node_modules/jest-cli/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "dev": true }, - "node_modules/jest-cli/node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true }, - "node_modules/jest-config": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "dev": true + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "dev": true + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "dev": true + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "dev": true + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "dev": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true + }, + "node_modules/lodash.map": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", + "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=", + "dev": true + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "dependencies": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" + "node": ">=10" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-config/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/longest": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-2.0.1.tgz", + "integrity": "sha1-eB4YMpaqlPbU2RbcM10NF676I/g=", "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-config/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", "dev": true, "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "get-func-name": "^2.0.1" } }, - "node_modules/jest-config/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/jest-config/node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "node_modules/lowdb": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowdb/-/lowdb-1.0.0.tgz", + "integrity": "sha512-2+x8esE/Wb9SQ1F9IHaYWfsC9FIecLOPrK4g17FGEayjUWH172H6nwicRovGvSE2CPZouc2MCIqCI7h9d+GftQ==", "dev": true, "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "graceful-fs": "^4.1.3", + "is-promise": "^2.1.0", + "lodash": "4", + "pify": "^3.0.0", + "steno": "^0.4.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=4" } }, - "node_modules/jest-config/node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "node_modules/lowdb/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" + "yallist": "^4.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" } }, - "node_modules/jest-docblock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", - "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "node_modules/magic-string": { + "version": "0.30.11", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", + "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", "dev": true, "dependencies": { - "detect-newline": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "@jridgewell/sourcemap-codec": "^1.5.0" } }, - "node_modules/jest-each": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", - "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "node_modules/magicast": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", + "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", "dev": true, "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "jest-util": "^29.7.0", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "@babel/parser": "^7.25.4", + "@babel/types": "^7.25.4", + "source-map-js": "^1.2.0" } }, - "node_modules/jest-each/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.27.8" + "semver": "^7.5.3" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-each/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/make-dir/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" } }, - "node_modules/jest-each/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, - "node_modules/jest-each/node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", "dev": true, "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "tmpl": "1.0.5" } }, - "node_modules/jest-environment-node": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", "dev": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-environment-node/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.6" } }, - "node_modules/jest-environment-node/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/meow": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", + "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", "dev": true, "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-environment-node/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/jest-environment-node/node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "node_modules/meow/node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "node_modules/meow/node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", "dev": true, "dependencies": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" + "node": ">=8" } }, - "node_modules/jest-haste-map/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/meow/node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.27.8" + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-haste-map/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/meow/node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/jest-haste-map/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "node_modules/meow/node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, - "node_modules/jest-haste-map/node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "node_modules/meow/node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, - "node_modules/jest-leak-detector": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", - "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "node_modules/meow/node_modules/read-pkg/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true, - "dependencies": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "bin": { + "semver": "bin/semver" } }, - "node_modules/jest-matcher-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "node_modules/meow/node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "node_modules/meow/node_modules/type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", "dev": true, - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-message-util/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/meow/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" } }, - "node_modules/jest-message-util/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/merge": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz", + "integrity": "sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==", + "dev": true + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-message-util/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, - "node_modules/jest-mock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 8" } }, - "node_modules/jest-mock/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.6" } }, - "node_modules/jest-mock/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", "dev": true, "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "braces": "^3.0.1", + "picomatch": "^2.2.3" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8.6" } }, - "node_modules/jest-mock/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/jest-mock/node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "bin": { + "mime": "cli.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=4" } }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" } }, - "node_modules/jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "dev": true, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=4" } }, - "node_modules/jest-resolve": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", - "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "node_modules/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", "dev": true, "dependencies": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "*" } }, - "node_modules/jest-resolve-dependencies": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", - "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", "dev": true, "dependencies": { - "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.7.0" + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 6" } }, - "node_modules/jest-resolve/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.27.8" + "minimist": "^1.2.6" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "bin": { + "mkdirp": "bin/cmd.js" } }, - "node_modules/jest-resolve/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/mkdirp/node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mlly": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.1.tgz", + "integrity": "sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==", "dev": true, "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, + "acorn": "^8.11.3", + "pathe": "^1.1.2", + "pkg-types": "^1.1.1", + "ufo": "^1.5.3" + } + }, + "node_modules/mrmime": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", + "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", + "dev": true, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" } }, - "node_modules/jest-resolve/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "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/jest-resolve/node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "node_modules/muggle-string": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.3.1.tgz", + "integrity": "sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==", + "dev": true + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "node_modules/mv": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", + "integrity": "sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg==", "dev": true, "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "mkdirp": "~0.5.1", + "ncp": "~2.0.0", + "rimraf": "~2.4.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.8.0" } }, - "node_modules/jest-resolve/node_modules/resolve.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "node_modules/mv/node_modules/glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, "engines": { - "node": ">=10" + "node": "*" } }, - "node_modules/jest-runner": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", - "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "node_modules/mv/node_modules/rimraf": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", + "integrity": "sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "dependencies": { - "@jest/console": "^29.7.0", - "@jest/environment": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-leak-detector": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-resolve": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-util": "^29.7.0", - "jest-watcher": "^29.7.0", - "jest-worker": "^29.7.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" + "glob": "^6.0.1" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "bin": { + "rimraf": "bin.js" } }, - "node_modules/jest-runner/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/jest-runner/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "node_modules/ncp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", + "integrity": "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==", + "dev": true, + "bin": { + "ncp": "bin/ncp" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.6" } }, - "node_modules/jest-runner/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, - "node_modules/jest-runner/node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "node_modules/node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "dev": true + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", "dev": true, "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "whatwg-url": "^5.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, - "node_modules/jest-runner/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/node-gyp-build": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz", + "integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==", + "dev": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-machine-id": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/node-machine-id/-/node-machine-id-1.1.12.tgz", + "integrity": "sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "dev": true + }, + "node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", "dev": true, "dependencies": { - "yocto-queue": "^0.1.0" + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-runner/node_modules/source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/jest-runtime": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "node_modules/npm-package-arg": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.1.tgz", + "integrity": "sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==", "dev": true, "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/globals": "^29.7.0", - "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" + "hosted-git-info": "^7.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/jest-runtime/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/npm-package-arg/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.27.8" + "lru-cache": "^10.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/jest-runtime/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/npm-package-arg/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "node_modules/npm-package-arg/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" } }, - "node_modules/jest-runtime/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/jest-runtime/node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "path-key": "^3.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/jest-snapshot": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", - "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "node_modules/nx": { + "version": "19.8.0", + "resolved": "https://registry.npmjs.org/nx/-/nx-19.8.0.tgz", + "integrity": "sha512-zD1ZvkfxECrd9QnvUyAUVLESmjl0bpIhB1gLcYN2BqsCkB1vkngbxIvXDorI98keOVEfHzeuwNSkufQNls1hug==", "dev": true, + "hasInstallScript": true, "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.7.0", - "semver": "^7.5.3" + "@napi-rs/wasm-runtime": "0.2.4", + "@nrwl/tao": "19.8.0", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.0-rc.46", + "@zkochan/js-yaml": "0.0.7", + "axios": "^1.7.4", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^8.0.1", + "dotenv": "~16.4.5", + "dotenv-expand": "~11.0.6", + "enquirer": "~2.3.6", + "figures": "3.2.0", + "flat": "^5.0.2", + "front-matter": "^4.0.2", + "fs-extra": "^11.1.0", + "ignore": "^5.0.4", + "jest-diff": "^29.4.1", + "jsonc-parser": "3.2.0", + "lines-and-columns": "2.0.3", + "minimatch": "9.0.3", + "node-machine-id": "1.1.12", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "ora": "5.3.0", + "semver": "^7.5.3", + "string-width": "^4.2.3", + "strong-log-transformer": "^2.1.0", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "bin": { + "nx": "bin/nx.js", + "nx-cloud": "bin/nx-cloud.js" + }, + "optionalDependencies": { + "@nx/nx-darwin-arm64": "19.8.0", + "@nx/nx-darwin-x64": "19.8.0", + "@nx/nx-freebsd-x64": "19.8.0", + "@nx/nx-linux-arm-gnueabihf": "19.8.0", + "@nx/nx-linux-arm64-gnu": "19.8.0", + "@nx/nx-linux-arm64-musl": "19.8.0", + "@nx/nx-linux-x64-gnu": "19.8.0", + "@nx/nx-linux-x64-musl": "19.8.0", + "@nx/nx-win32-arm64-msvc": "19.8.0", + "@nx/nx-win32-x64-msvc": "19.8.0" + }, + "peerDependencies": { + "@swc-node/register": "^1.8.0", + "@swc/core": "^1.3.85" + }, + "peerDependenciesMeta": { + "@swc-node/register": { + "optional": true + }, + "@swc/core": { + "optional": true + } } }, - "node_modules/jest-snapshot/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/nx/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": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "balanced-match": "^1.0.0" } }, - "node_modules/jest-snapshot/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/nx/node_modules/cliui": { + "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": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/jest-snapshot/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/jest-snapshot/node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "node_modules/nx/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", "dev": true, "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.14" } }, - "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "node_modules/nx/node_modules/lines-and-columns": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.3.tgz", + "integrity": "sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==", "dev": true, - "bin": { - "semver": "bin/semver.js" - }, "engines": { - "node": ">=10" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, - "node_modules/jest-util": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.1.tgz", - "integrity": "sha512-FktOu7ca1DZSyhPAxgxB6hfh2+9zMoJ7aEQA759Z6p45NuO8mWcqujH+UdHlCm/V6JTWwDztM2ITCzU1ijJAfw==", + "node_modules/nx/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "dependencies": { - "@jest/types": "^28.1.1", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "node_modules/nx/node_modules/ora": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.3.0.tgz", + "integrity": "sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==", "dev": true, "dependencies": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" + "bl": "^4.0.3", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "log-symbols": "^4.0.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-validate/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/nx/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" } }, - "node_modules/jest-validate/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/nx/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, - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/jest-validate/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", "dev": true, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-watcher": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", - "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", "dev": true, - "dependencies": { - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.0.0" } }, - "node_modules/jest-watcher/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.27.8" + "ee-first": "1.1.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.8" } }, - "node_modules/jest-watcher/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.8" } }, - "node_modules/jest-watcher/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/jest-watcher/node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "wrappy": "1" } }, - "node_modules/jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "mimic-fn": "^2.1.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-worker/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/open": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", + "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.27.8" + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-worker/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "bin": { + "opener": "bin/opener-bin.js" } }, - "node_modules/jest-worker/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/jest-worker/node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.8.0" } }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "p-try": "^2.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "p-limit": "^2.2.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=8" } }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", "dev": true }, - "node_modules/json-stable-stringify-without-jsonify": { + "node_modules/parent-module": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, - "bin": { - "json5": "lib/cli.js" + "dependencies": { + "callsites": "^3.0.0" }, "engines": { "node": ">=6" } }, - "node_modules/jsonc-eslint-parser": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonc-eslint-parser/-/jsonc-eslint-parser-2.4.0.tgz", - "integrity": "sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==", + "node_modules/parse-json": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-7.1.1.tgz", + "integrity": "sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==", "dev": true, "dependencies": { - "acorn": "^8.5.0", - "eslint-visitor-keys": "^3.0.0", - "espree": "^9.0.0", - "semver": "^7.3.5" + "@babel/code-frame": "^7.21.4", + "error-ex": "^1.3.2", + "json-parse-even-better-errors": "^3.0.0", + "lines-and-columns": "^2.0.3", + "type-fest": "^3.8.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=16" }, "funding": { - "url": "https://github.com/sponsors/ota-meshi" - } - }, - "node_modules/jsonc-eslint-parser/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", - "dev": true - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", - "dev": true, - "engines": [ - "node >= 0.2.0" - ] - }, - "node_modules/JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "node_modules/parse-json/node_modules/json-parse-even-better-errors": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", + "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", "dev": true, - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "bin": { - "JSONStream": "bin.js" - }, "engines": { - "node": "*" - } - }, - "node_modules/just-extend": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.1.1.tgz", - "integrity": "sha512-1UWaMWIB90HnIZAmXOTLobwWc9lc1ZMUBRKf8PaozCAiNUif6wv1fyeXpqccWZCu7L9zxIgXG55vARuZluyvqw==" - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "node_modules/parse-json/node_modules/lines-and-columns": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", + "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "node_modules/parse-json/node_modules/type-fest": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", "dev": true, "engines": { - "node": ">=6" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "dev": true, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, "engines": { - "node": ">= 0.8.0" + "node": ">= 0.8" } }, - "node_modules/lines-and-columns": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", - "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", "dev": true }, - "node_modules/load-json-file": { + "node_modules/path-exists": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/load-json-file/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } - }, - "node_modules/load-json-file/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, "engines": { "node": ">=8" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true - }, - "node_modules/lodash.ismatch": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", - "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==", - "dev": true - }, - "node_modules/lodash.map": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", - "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=", + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "node_modules/path-to-regexp": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", "dev": true }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", "dev": true }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "*" } }, - "node_modules/longest": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-2.0.1.tgz", - "integrity": "sha1-eB4YMpaqlPbU2RbcM10NF676I/g=", + "node_modules/peek-stream": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/peek-stream/-/peek-stream-1.1.3.tgz", + "integrity": "sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "buffer-from": "^1.0.0", + "duplexify": "^3.5.0", + "through2": "^2.0.3" } }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/peek-stream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "node_modules/peek-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "safe-buffer": "~5.1.0" } }, - "node_modules/make-dir/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "node_modules/peek-stream/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" } }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", "dev": true }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "dependencies": { - "tmpl": "1.0.5" - } + "node_modules/picocolors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "dev": true }, - "node_modules/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "engines": { - "node": ">=8" + "node": ">=8.6" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/meow": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", - "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", + "node_modules/pino": { + "version": "8.17.2", + "resolved": "https://registry.npmjs.org/pino/-/pino-8.17.2.tgz", + "integrity": "sha512-LA6qKgeDMLr2ux2y/YiUt47EfgQ+S9LznBWOJdN3q1dx2sv0ziDLUBeVpyVv17TEcGCBuWf0zNtg3M5m1NhhWQ==", "dev": true, "dependencies": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "v1.1.0", + "pino-std-serializers": "^6.0.0", + "process-warning": "^3.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^3.7.0", + "thread-stream": "^2.0.0" }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "pino": "bin.js" } }, - "node_modules/meow/node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "node_modules/pino-abstract-transport": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz", + "integrity": "sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "readable-stream": "^4.0.0", + "split2": "^4.0.0" } }, - "node_modules/meow/node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "node_modules/pino-abstract-transport/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, - "node_modules/meow/node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "node_modules/pino-abstract-transport/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", "dev": true, "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/meow/node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "node_modules/pino-abstract-transport/node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dev": true, + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/pino-std-serializers": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", + "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==", + "dev": true + }, + "node_modules/pino/node_modules/process-warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", + "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==", + "dev": true + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, "engines": { "node": ">=8" } }, - "node_modules/meow/node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/meow/node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "node_modules/pkg-types": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.2.0.tgz", + "integrity": "sha512-+ifYuSSqOQ8CqP4MbZA5hDpb97n3E8SVWdJe+Wms9kj745lmd3b7EZJiqvmLwAlmRfjrI7Hi5z3kdBJ93lFNPA==", "dev": true, "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "confbox": "^0.1.7", + "mlly": "^1.7.1", + "pathe": "^1.1.2" } }, - "node_modules/meow/node_modules/read-pkg/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "node_modules/pkginfo": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.4.1.tgz", + "integrity": "sha512-8xCNE/aT/EXKenuMDZ+xTVwkT8gsoHN2z/Q29l80u0ppGEXVvsKRzNMbtKhg8LS8k1tJLAHHylf6p4VFmP6XUQ==", "dev": true, - "bin": { - "semver": "bin/semver" + "engines": { + "node": ">= 0.4.0" } }, - "node_modules/meow/node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "node_modules/portfinder": { + "version": "1.0.32", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", + "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", "dev": true, + "dependencies": { + "async": "^2.6.4", + "debug": "^3.2.7", + "mkdirp": "^0.5.6" + }, "engines": { - "node": ">=8" + "node": ">= 0.12.0" } }, - "node_modules/meow/node_modules/type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "node_modules/portfinder/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "lodash": "^4.17.14" } }, - "node_modules/meow/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "node_modules/portfinder/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "engines": { - "node": ">=10" + "dependencies": { + "ms": "^2.1.1" } }, - "node_modules/merge": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz", - "integrity": "sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==", - "dev": true - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "node_modules/postcss": { + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" + }, "engines": { - "node": ">= 8" + "node": "^10 || ^12 || >=14" } }, - "node_modules/micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, - "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - }, "engines": { - "node": ">=8.6" + "node": ">= 0.8.0" } }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "node_modules/prettier": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, "engines": { - "node": ">= 0.6" + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "dependencies": { - "mime-db": "1.52.0" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">= 0.6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "node_modules/proc-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", + "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", "dev": true, "engines": { - "node": ">=4" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, "engines": { - "node": "*" + "node": ">= 0.6.0" } }, - "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, - "node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "node_modules/process-warning": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz", + "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==", + "dev": true + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", "dev": true, "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" }, "engines": { "node": ">= 6" } }, - "node_modules/modify-values": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", - "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "dev": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.10" } }, - "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==", + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", "dev": true }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true + "node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "node_modules/pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } }, - "node_modules/node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "dev": true + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, + "node_modules/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true, + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } }, - "node_modules/node-gyp-build": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz", - "integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==", + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dev": true, - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", "dev": true }, - "node_modules/node-machine-id": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/node-machine-id/-/node-machine-id-1.1.12.tgz", - "integrity": "sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==", + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/queue-tick": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", "dev": true }, - "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", "dev": true }, - "node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", "dev": true, - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/npm-package-arg": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.1.tgz", - "integrity": "sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==", + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dev": true, "dependencies": { - "hosted-git-info": "^7.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": ">= 0.8" } }, - "node_modules/npm-package-arg/node_modules/hosted-git-info": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", - "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true, - "dependencies": { - "lru-cache": "^10.0.1" - }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": ">= 0.8" } }, - "node_modules/npm-package-arg/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true }, - "node_modules/npm-package-arg/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "node_modules/read-pkg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-8.1.0.tgz", + "integrity": "sha512-PORM8AgzXeskHO/WEv312k9U03B8K9JSiWF/8N9sUuFjBa+9SF2u6K7VClzXwDXab51jCd8Nd36CNM+zR97ScQ==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "dependencies": { + "@types/normalize-package-data": "^2.4.1", + "normalize-package-data": "^6.0.0", + "parse-json": "^7.0.0", + "type-fest": "^4.2.0" }, "engines": { - "node": ">=10" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "node_modules/read-pkg-up": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-10.1.0.tgz", + "integrity": "sha512-aNtBq4jR8NawpKJQldrQcSW9y/d+KWH4v24HWkHljOZ7H0av+YTGANBzRh9A5pw7v/bLVsLVPpOhJ7gHNVy8lA==", "dev": true, "dependencies": { - "path-key": "^3.0.0" + "find-up": "^6.3.0", + "read-pkg": "^8.1.0", + "type-fest": "^4.2.0" }, "engines": { - "node": ">=8" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/nx": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/nx/-/nx-19.8.0.tgz", - "integrity": "sha512-zD1ZvkfxECrd9QnvUyAUVLESmjl0bpIhB1gLcYN2BqsCkB1vkngbxIvXDorI98keOVEfHzeuwNSkufQNls1hug==", + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", "dev": true, - "hasInstallScript": true, "dependencies": { - "@napi-rs/wasm-runtime": "0.2.4", - "@nrwl/tao": "19.8.0", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "3.0.0-rc.46", - "@zkochan/js-yaml": "0.0.7", - "axios": "^1.7.4", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^8.0.1", - "dotenv": "~16.4.5", - "dotenv-expand": "~11.0.6", - "enquirer": "~2.3.6", - "figures": "3.2.0", - "flat": "^5.0.2", - "front-matter": "^4.0.2", - "fs-extra": "^11.1.0", - "ignore": "^5.0.4", - "jest-diff": "^29.4.1", - "jsonc-parser": "3.2.0", - "lines-and-columns": "2.0.3", - "minimatch": "9.0.3", - "node-machine-id": "1.1.12", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "ora": "5.3.0", - "semver": "^7.5.3", - "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", - "tar-stream": "~2.2.0", - "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - }, - "bin": { - "nx": "bin/nx.js", - "nx-cloud": "bin/nx-cloud.js" + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" }, - "optionalDependencies": { - "@nx/nx-darwin-arm64": "19.8.0", - "@nx/nx-darwin-x64": "19.8.0", - "@nx/nx-freebsd-x64": "19.8.0", - "@nx/nx-linux-arm-gnueabihf": "19.8.0", - "@nx/nx-linux-arm64-gnu": "19.8.0", - "@nx/nx-linux-arm64-musl": "19.8.0", - "@nx/nx-linux-x64-gnu": "19.8.0", - "@nx/nx-linux-x64-musl": "19.8.0", - "@nx/nx-win32-arm64-msvc": "19.8.0", - "@nx/nx-win32-x64-msvc": "19.8.0" - }, - "peerDependencies": { - "@swc-node/register": "^1.8.0", - "@swc/core": "^1.3.85" + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, - "peerDependenciesMeta": { - "@swc-node/register": { - "optional": true - }, - "@swc/core": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/nx/node_modules/@zkochan/js-yaml": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.7.tgz", - "integrity": "sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==", + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", "dev": true, "dependencies": { - "argparse": "^2.0.1" + "p-locate": "^6.0.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/nx/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/nx/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" + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/nx/node_modules/cliui": { - "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==", + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", "dev": true, "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "yocto-queue": "^1.0.0" }, "engines": { - "node": ">=12" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/nx/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", "dev": true, "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "p-limit": "^4.0.0" }, "engines": { - "node": ">=14.14" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/nx/node_modules/lines-and-columns": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.3.tgz", - "integrity": "sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==", + "node_modules/read-pkg-up/node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", "dev": true, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, - "node_modules/nx/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "4.26.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz", + "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==", "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" + "engines": { + "node": ">=16" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/yocto-queue": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", + "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", + "dev": true, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=12.20" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/nx/node_modules/ora": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.3.0.tgz", - "integrity": "sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==", + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", "dev": true, "dependencies": { - "bl": "^4.0.3", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "log-symbols": "^4.0.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" + "lru-cache": "^10.0.1" }, "engines": { - "node": ">=10" + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/read-pkg/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", + "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", + "dev": true, + "dependencies": { + "hosted-git-info": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/nx/node_modules/semver": { + "node_modules/read-pkg/node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", @@ -11251,1802 +14988,2176 @@ "node": ">=10" } }, - "node_modules/nx/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==", + "node_modules/read-pkg/node_modules/type-fest": { + "version": "4.26.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz", + "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==", "dev": true, "engines": { - "node": ">=12" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dev": true, "dependencies": { - "wrappy": "1" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "dependencies": { - "mimic-fn": "^2.1.0" + "picomatch": "^2.2.1" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8.10.0" } }, - "node_modules/open": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", - "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", "dev": true, - "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 12.13.0" } }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", "dev": true, "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "node_modules/reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", + "dev": true + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", + "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", "dev": true, "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" + "regenerate": "^1.4.2" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "@babel/runtime": "^7.8.4" } }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", "dev": true, "dependencies": { - "p-try": "^2.0.0" + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", "dev": true, "dependencies": { - "p-limit": "^2.2.0" + "jsesc": "~0.5.0" }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, "engines": { - "node": ">=6" + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, "dependencies": { - "callsites": "^3.0.0" + "resolve-from": "^5.0.0" }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "node_modules/resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", "dev": true, "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "node_modules/resolve-global": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", + "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", "dev": true, + "dependencies": { + "global-dirs": "^0.1.1" + }, "engines": { "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "node_modules/resolve.exports": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", + "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, "engines": { "node": ">=8" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } }, - "node_modules/path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "dependencies": { - "pify": "^3.0.0" + "glob": "^7.1.3" }, - "engines": { - "node": ">=4" + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/path-type/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "node_modules/rollup": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.4.tgz", + "integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==", "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, "engines": { - "node": ">=4" + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.22.4", + "@rollup/rollup-android-arm64": "4.22.4", + "@rollup/rollup-darwin-arm64": "4.22.4", + "@rollup/rollup-darwin-x64": "4.22.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.22.4", + "@rollup/rollup-linux-arm-musleabihf": "4.22.4", + "@rollup/rollup-linux-arm64-gnu": "4.22.4", + "@rollup/rollup-linux-arm64-musl": "4.22.4", + "@rollup/rollup-linux-powerpc64le-gnu": "4.22.4", + "@rollup/rollup-linux-riscv64-gnu": "4.22.4", + "@rollup/rollup-linux-s390x-gnu": "4.22.4", + "@rollup/rollup-linux-x64-gnu": "4.22.4", + "@rollup/rollup-linux-x64-musl": "4.22.4", + "@rollup/rollup-win32-arm64-msvc": "4.22.4", + "@rollup/rollup-win32-ia32-msvc": "4.22.4", + "@rollup/rollup-win32-x64-msvc": "4.22.4", + "fsevents": "~2.3.2" } }, - "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "node_modules/rollup/node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, - "node_modules/picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", "dev": true, "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "node": ">=0.12.0" } }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, "engines": { - "node": ">=0.10.0" + "npm": ">=2.0.0" } }, - "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "node_modules/rxjs/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", "dev": true, "engines": { - "node": ">= 6" + "node": ">=10" } }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/secure-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", + "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==", + "dev": true + }, + "node_modules/semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", "dev": true, "dependencies": { - "find-up": "^4.0.0" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, "engines": { "node": ">= 0.8.0" } }, - "node_modules/prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "node": ">= 0.8" } }, - "node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dev": true, "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.8.0" } }, - "node_modules/pretty-format/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.27.8" + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" } }, - "node_modules/pretty-format/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "dev": true }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=8" } }, - "node_modules/proc-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sirv": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", + "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", "dev": true, "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" }, "engines": { - "node": ">= 6" + "node": ">= 10" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", "dev": true }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/pure-rand": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", - "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "node_modules/sonic-boom": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.0.tgz", + "integrity": "sha512-ybz6OYOUjoQQCQ/i4LU8kaToD8ACtYP+Cj5qd2AO36bwbdewxWJ3ArmJ2cr6AvxlL2o0PqnCcPGUgkILbfkaCA==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ] + "dependencies": { + "atomic-sleep": "^1.0.0" + } }, - "node_modules/q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" + "node": ">=0.10.0" } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } }, - "node_modules/read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", "dev": true, "dependencies": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - }, - "engines": { - "node": ">=4" + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/read-pkg-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", - "integrity": "sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==", + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, "dependencies": { - "find-up": "^2.0.0", - "read-pkg": "^3.0.0" - }, - "engines": { - "node": ">=4" + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "node_modules/spdx-license-ids": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", + "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", + "dev": true + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", "dev": true, "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" + "readable-stream": "^3.0.0" } }, - "node_modules/read-pkg-up/node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/sshpk": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", "dev": true, "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/read-pkg-up/node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "dev": true, "dependencies": { - "p-try": "^1.0.0" + "escape-string-regexp": "^2.0.0" }, "engines": { - "node": ">=4" + "node": ">=10" } }, - "node_modules/read-pkg-up/node_modules/p-locate": { + "node_modules/stack-utils/node_modules/escape-string-regexp": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, - "dependencies": { - "p-limit": "^1.1.0" - }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/read-pkg-up/node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true, "engines": { - "node": ">=4" + "node": ">= 0.8" } }, - "node_modules/read-pkg-up/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "node_modules/std-env": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", + "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", + "dev": true + }, + "node_modules/steno": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/steno/-/steno-0.4.4.tgz", + "integrity": "sha512-EEHMVYHNXFHfGtgjNITnka0aHhiAlo93F7z2/Pwd+g0teG9CnM3JIINM7hVVB5/rhw9voufD7Wukwgtw2uqh6w==", "dev": true, - "engines": { - "node": ">=4" + "dependencies": { + "graceful-fs": "^4.1.3" } }, - "node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "node_modules/stream-shift": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", "dev": true }, - "node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "node_modules/streamx": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.20.1.tgz", + "integrity": "sha512-uTa0mU6WUC65iUvzKH4X9hEdvSW7rbPxPtwfWiLMSj3qTdQbAiUboZTxauKfpFuGIGa1C2BYijZ7wgdUXICJhA==", "dev": true, "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "fast-fifo": "^1.3.2", + "queue-tick": "^1.0.1", + "text-decoder": "^1.1.0" + }, + "optionalDependencies": { + "bare-events": "^2.2.0" } }, - "node_modules/read-pkg/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", "dev": true, - "bin": { - "semver": "bin/semver" + "engines": { + "node": ">=0.6.19" } }, - "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", "dev": true, "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">= 6" + "node": ">=10" } }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "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": { - "picomatch": "^2.2.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=8.10.0" + "node": ">=8" } }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" + "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", - "dev": true + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } }, - "node_modules/regenerate-unicode-properties": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", - "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", "dev": true, "dependencies": { - "regenerate": "^1.4.2" + "min-indent": "^1.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true - }, - "node_modules/regenerator-transform": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", - "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, - "dependencies": { - "@babel/runtime": "^7.8.4" + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "node_modules/strip-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.0.tgz", + "integrity": "sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==", "dev": true, "dependencies": { - "@babel/regjsgen": "^0.8.0", - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" + "js-tokens": "^9.0.0" }, - "engines": { - "node": ">=4" + "funding": { + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "node_modules/strip-literal/node_modules/js-tokens": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.0.tgz", + "integrity": "sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==", + "dev": true + }, + "node_modules/strong-log-transformer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", + "integrity": "sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==", "dev": true, "dependencies": { - "jsesc": "~0.5.0" + "duplexer": "^0.1.1", + "minimist": "^1.2.0", + "through": "^2.3.4" }, "bin": { - "regjsparser": "bin/parser" + "sl-log-transformer": "bin/sl-log-transformer.js" + }, + "engines": { + "node": ">=4" } }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "bin": { - "jsesc": "bin/jsesc" + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "dev": true, "dependencies": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=6" } }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, "dependencies": { - "resolve-from": "^5.0.0" + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" }, "engines": { "node": ">=8" } }, - "node_modules/resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "node_modules/text-decoder": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.0.tgz", + "integrity": "sha512-n1yg1mOj9DNpk3NeZOx7T6jchTbyJS3i3cucbNN6FcdPriMZx7NsgrGpWWdWZZGxD7ES1XB+3uoqHMgOKaN+fg==", "dev": true, "dependencies": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" + "b4a": "^1.6.4" } }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "node_modules/text-extensions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", + "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", "dev": true, "engines": { - "node": ">=8" + "node": ">=0.10" } }, - "node_modules/resolve-global": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", - "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/thread-stream": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.7.0.tgz", + "integrity": "sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==", "dev": true, "dependencies": { - "global-dirs": "^0.1.1" - }, + "real-require": "^0.2.0" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true + }, + "node_modules/tinypool": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz", + "integrity": "sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==", + "dev": true, "engines": { - "node": ">=8" + "node": ">=14.0.0" } }, - "node_modules/resolve.exports": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", - "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", + "node_modules/tinyspy": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", + "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", "dev": true, "engines": { - "node": ">=10" + "node": ">=14.0.0" } }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", "dev": true, "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "rimraf": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=8.17.0" } }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" + "is-number": "^7.0.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">=8.0" } }, - "node_modules/run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true, "engines": { - "node": ">=0.12.0" + "node": ">=0.6" } }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" + "engines": { + "node": ">=6" } }, - "node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", "dev": true, "dependencies": { - "tslib": "^1.9.0" + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" }, "engines": { - "npm": ">=2.0.0" + "node": ">=6" } }, - "node_modules/rxjs/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "dev": true }, - "node_modules/semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "node_modules/trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, "engines": { - "node": ">=8" + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "node_modules/ts-jest": { + "version": "29.2.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.5.tgz", + "integrity": "sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==", "dev": true, + "dependencies": { + "bs-logger": "^0.2.6", + "ejs": "^3.1.10", + "fast-json-stable-stringify": "^2.1.0", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.6.3", + "yargs-parser": "^21.1.1" + }, + "bin": { + "ts-jest": "cli.js" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "node_modules/ts-jest/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/ts-jest/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": ">=0.10.0" + "node": ">=12" } }, - "node_modules/source-map-support": { - "version": "0.5.20", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", - "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", + "node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } } }, - "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", "dev": true, "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tsconfig-paths/node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "engines": { + "node": ">=4" } }, - "node_modules/spdx-license-ids": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", - "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", - "dev": true + "node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" }, - "node_modules/split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "dev": true, "dependencies": { - "through": "2" + "safe-buffer": "^5.0.1" }, "engines": { "node": "*" } }, - "node_modules/split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "dev": true, - "dependencies": { - "readable-stream": "^3.0.0" - } + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "node_modules/typanion": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/typanion/-/typanion-3.14.0.tgz", + "integrity": "sha512-ZW/lVMRabETuYCd9O9ZvMhAh8GslSqaUjxmK/JLPCh6l73CvLBiuXswj/+7LdnWOgYsQ130FqLzFz5aGT4I3Ug==", "dev": true }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "dependencies": { - "escape-string-regexp": "^2.0.0" + "prelude-ls": "^1.2.1" }, "engines": { - "node": ">=10" + "node": ">= 0.8.0" } }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/standard-version": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/standard-version/-/standard-version-9.5.0.tgz", - "integrity": "sha512-3zWJ/mmZQsOaO+fOlsa0+QK90pwhNd042qEcw6hKFNoLFs7peGyvPffpEBbK/DSGPbyOvli0mUIFv5A4qTjh2Q==", + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, - "dependencies": { - "chalk": "^2.4.2", - "conventional-changelog": "3.1.25", - "conventional-changelog-config-spec": "2.1.0", - "conventional-changelog-conventionalcommits": "4.6.3", - "conventional-recommended-bump": "6.1.0", - "detect-indent": "^6.0.0", - "detect-newline": "^3.1.0", - "dotgitignore": "^2.1.0", - "figures": "^3.1.0", - "find-up": "^5.0.0", - "git-semver-tags": "^4.0.0", - "semver": "^7.1.1", - "stringify-package": "^1.0.1", - "yargs": "^16.0.0" - }, - "bin": { - "standard-version": "bin/cli.js" - }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/standard-version/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dev": true, "dependencies": { - "color-convert": "^1.9.0" + "media-typer": "0.3.0", + "mime-types": "~2.1.24" }, "engines": { - "node": ">=4" + "node": ">= 0.6" } }, - "node_modules/standard-version/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/typescript": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4" + "node": ">=14.17" } }, - "node_modules/standard-version/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/ufo": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", + "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==", + "dev": true + }, + "node_modules/uglify-js": { + "version": "3.17.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.3.tgz", + "integrity": "sha512-JmMFDME3iufZnBpyKL+uS78LRiC+mK55zWfM5f/pWBJfpOttXAqYfdDGRukYhJuyRinvPVAtUhvy7rlDybNtFg==", "dev": true, - "dependencies": { - "color-name": "1.1.3" + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" } }, - "node_modules/standard-version/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "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/standard-version/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", "dev": true, "engines": { - "node": ">=0.8.0" + "node": ">=4" } }, - "node_modules/standard-version/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "dev": true, "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/standard-version/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", + "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", "dev": true, "engines": { "node": ">=4" } }, - "node_modules/standard-version/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/standard-version/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/union": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", + "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", "dev": true, "dependencies": { - "yocto-queue": "^0.1.0" + "qs": "^6.4.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.8.0" } }, - "node_modules/standard-version/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 10.0.0" } }, - "node_modules/standard-version/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==", + "node_modules/unix-crypt-td-js": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/unix-crypt-td-js/-/unix-crypt-td-js-1.1.4.tgz", + "integrity": "sha512-8rMeVYWSIyccIJscb9NdCfZKSRBKYTeVnwmiRYT2ulE3qd1RaDQ0xQDP+rI3ccIWbhu/zuo5cgN8z73belNZgw==", + "dev": true + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, "engines": { - "node": ">=4" + "node": ">= 0.8" } }, - "node_modules/standard-version/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "node_modules/update-browserslist-db": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "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" + "escalade": "^3.1.2", + "picocolors": "^1.0.1" }, - "engines": { - "node": ">=10" - } - }, - "node_modules/standard-version/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "engines": { - "node": ">=10" + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "dependencies": { - "safe-buffer": "~5.2.0" + "punycode": "^2.1.0" } }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "dev": true }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", "dev": true, "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" } }, - "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==", + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, "engines": { - "node": ">=8" + "node": ">= 0.4.0" } }, - "node_modules/stringify-package": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stringify-package/-/stringify-package-1.0.1.tgz", - "integrity": "sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg==", + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", "dev": true, "dependencies": { - "ansi-regex": "^5.0.1" + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=10.12.0" } }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" } }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "node_modules/validate-npm-package-name": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", + "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", "dev": true, "engines": { - "node": ">=6" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "node_modules/validator": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", + "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", "dev": true, - "dependencies": { - "min-indent": "^1.0.0" - }, "engines": { - "node": ">=8" + "node": ">= 0.10" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "dev": true, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.8" } }, - "node_modules/strong-log-transformer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", - "integrity": "sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==", - "dev": true, - "dependencies": { - "duplexer": "^0.1.1", - "minimist": "^1.2.0", - "through": "^2.3.4" + "node_modules/verdaccio": { + "version": "5.32.2", + "resolved": "https://registry.npmjs.org/verdaccio/-/verdaccio-5.32.2.tgz", + "integrity": "sha512-QnVYIUvwB884fwVcA/D+x7AabsRPlTPyYAKMtExm8kJjiH+s2LGK2qX2o3I4VmYXqBR3W9b8gEnyQnGwQhUPsw==", + "dev": true, + "dependencies": { + "@cypress/request": "3.0.1", + "@verdaccio/auth": "8.0.0-next-8.1", + "@verdaccio/config": "8.0.0-next-8.1", + "@verdaccio/core": "8.0.0-next-8.1", + "@verdaccio/local-storage-legacy": "11.0.2", + "@verdaccio/logger-7": "8.0.0-next-8.1", + "@verdaccio/middleware": "8.0.0-next-8.1", + "@verdaccio/search-indexer": "8.0.0-next-8.0", + "@verdaccio/signature": "8.0.0-next-8.0", + "@verdaccio/streams": "10.2.1", + "@verdaccio/tarball": "13.0.0-next-8.1", + "@verdaccio/ui-theme": "8.0.0-next-8.1", + "@verdaccio/url": "13.0.0-next-8.1", + "@verdaccio/utils": "7.0.1-next-8.1", + "async": "3.2.5", + "clipanion": "4.0.0-rc.3", + "compression": "1.7.4", + "cors": "2.8.5", + "debug": "^4.3.5", + "envinfo": "7.13.0", + "express": "4.21.0", + "express-rate-limit": "5.5.1", + "fast-safe-stringify": "2.1.1", + "handlebars": "4.7.8", + "js-yaml": "4.1.0", + "JSONStream": "1.3.5", + "jsonwebtoken": "9.0.2", + "kleur": "4.1.5", + "lodash": "4.17.21", + "lru-cache": "7.18.3", + "mime": "3.0.0", + "mkdirp": "1.0.4", + "mv": "2.1.1", + "pkginfo": "0.4.1", + "semver": "7.6.3", + "validator": "13.12.0", + "verdaccio-audit": "13.0.0-next-8.1", + "verdaccio-htpasswd": "13.0.0-next-8.1" }, "bin": { - "sl-log-transformer": "bin/sl-log-transformer.js" + "verdaccio": "bin/verdaccio" }, "engines": { - "node": ">=4" + "node": ">=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" } }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/verdaccio-audit": { + "version": "13.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/verdaccio-audit/-/verdaccio-audit-13.0.0-next-8.1.tgz", + "integrity": "sha512-EEfUeC1kHuErtwF9FC670W+EXHhcl+iuigONkcprwRfkPxmdBs+Hx36745hgAMZ9SCqedNECaycnGF3tZ3VYfw==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "@verdaccio/config": "8.0.0-next-8.1", + "@verdaccio/core": "8.0.0-next-8.1", + "express": "4.21.0", + "https-proxy-agent": "5.0.1", + "node-fetch": "cjs" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" } }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "node_modules/verdaccio-htpasswd": { + "version": "13.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/verdaccio-htpasswd/-/verdaccio-htpasswd-13.0.0-next-8.1.tgz", + "integrity": "sha512-BfvmO+ZdbwfttOwrdTPD6Bccr1ZfZ9Tk/9wpXamxdWB/XPWlk3FtyGsvqCmxsInRLPhQ/FSk9c3zRCGvICTFYg==", "dev": true, "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" + "@verdaccio/core": "8.0.0-next-8.1", + "@verdaccio/file-locking": "13.0.0-next-8.0", + "apache-md5": "1.1.8", + "bcryptjs": "2.4.3", + "core-js": "3.37.1", + "debug": "4.3.7", + "http-errors": "2.0.0", + "unix-crypt-td-js": "1.1.4" }, "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" } }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "node_modules/verdaccio-htpasswd/node_modules/@verdaccio/file-locking": { + "version": "13.0.0-next-8.0", + "resolved": "https://registry.npmjs.org/@verdaccio/file-locking/-/file-locking-13.0.0-next-8.0.tgz", + "integrity": "sha512-28XRwpKiE3Z6KsnwE7o8dEM+zGWOT+Vef7RVJyUlG176JVDbGGip3HfCmFioE1a9BklLyGEFTu6D69BzfbRkzA==", "dev": true, "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" + "lockfile": "1.0.4" }, "engines": { - "node": ">=8" - } - }, - "node_modules/text-extensions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", - "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", - "dev": true, - "engines": { - "node": ">=0.10" + "node": ">=12" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "node_modules/verdaccio/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "node_modules/verdaccio/node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", "dev": true }, - "node_modules/through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "node_modules/verdaccio/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "dependencies": { - "readable-stream": "3" + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "node_modules/verdaccio/node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", "dev": true, - "dependencies": { - "rimraf": "^3.0.0" - }, "engines": { - "node": ">=8.17.0" + "node": ">=6" } }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true + "node_modules/verdaccio/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "node_modules/verdaccio/node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", "dev": true, + "bin": { + "mime": "cli.js" + }, "engines": { - "node": ">=4" + "node": ">=10.0.0" } }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "node_modules/verdaccio/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, - "dependencies": { - "is-number": "^7.0.0" + "bin": { + "mkdirp": "bin/cmd.js" }, "engines": { - "node": ">=8.0" + "node": ">=10" } }, - "node_modules/trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "node_modules/verdaccio/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", "dev": true, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" } }, - "node_modules/ts-jest": { - "version": "28.0.8", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-28.0.8.tgz", - "integrity": "sha512-5FaG0lXmRPzApix8oFG8RKjAz4ehtm8yMKOTy5HX3fY6W8kmvOrmcY0hKDElW52FJov+clhUbrKAqofnj4mXTg==", + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true + }, + "node_modules/vite": { + "version": "5.4.7", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.7.tgz", + "integrity": "sha512-5l2zxqMEPVENgvzTuBpHer2awaetimj2BGkhBPdnwKbPNOlHsODU+oiazEZzLK7KhAnOrO+XGYJYn4ZlUhDtDQ==", "dev": true, "dependencies": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^28.0.0", - "json5": "^2.2.1", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "7.x", - "yargs-parser": "^21.0.1" + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" }, "bin": { - "ts-jest": "cli.js" + "vite": "bin/vite.js" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" }, "peerDependencies": { - "@babel/core": ">=7.0.0-beta.0 <8", - "@jest/types": "^28.0.0", - "babel-jest": "^28.0.0", - "jest": "^28.0.0", - "typescript": ">=4.3" + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" }, "peerDependenciesMeta": { - "@babel/core": { + "@types/node": { "optional": true }, - "@jest/types": { + "less": { "optional": true }, - "babel-jest": { + "lightningcss": { "optional": true }, - "esbuild": { + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { "optional": true } } }, - "node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "node_modules/vite-node": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.0.tgz", + "integrity": "sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==", "dev": true, "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" + "cac": "^6.7.14", + "debug": "^4.3.4", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^5.0.0" }, "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vite-plugin-dts": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/vite-plugin-dts/-/vite-plugin-dts-3.8.3.tgz", + "integrity": "sha512-yRHiRosQw7MXdOhmcrVI+kRiB8YEShbSxnADNteK4eZGdEoyOkMHihvO5XOAVlOq8ng9sIqu8vVefDK1zcj3qw==", + "dev": true, + "dependencies": { + "@microsoft/api-extractor": "7.43.0", + "@rollup/pluginutils": "^5.1.0", + "@vue/language-core": "^1.8.27", + "debug": "^4.3.4", + "kolorist": "^1.8.0", + "magic-string": "^0.30.8", + "vue-tsc": "^1.8.27" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" }, "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" + "typescript": "*", + "vite": "*" }, "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { + "vite": { "optional": true } } }, - "node_modules/tsconfig-paths": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", - "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "node_modules/vitest": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.6.0.tgz", + "integrity": "sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==", "dev": true, "dependencies": { - "json5": "^2.2.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "@vitest/expect": "1.6.0", + "@vitest/runner": "1.6.0", + "@vitest/snapshot": "1.6.0", + "@vitest/spy": "1.6.0", + "@vitest/utils": "1.6.0", + "acorn-walk": "^8.3.2", + "chai": "^4.3.10", + "debug": "^4.3.4", + "execa": "^8.0.1", + "local-pkg": "^0.5.0", + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "std-env": "^3.5.0", + "strip-literal": "^2.0.0", + "tinybench": "^2.5.1", + "tinypool": "^0.8.3", + "vite": "^5.0.0", + "vite-node": "1.6.0", + "why-is-node-running": "^2.2.2" + }, + "bin": { + "vitest": "vitest.mjs" }, "engines": { - "node": ">=6" - } - }, - "node_modules/tsconfig-paths/node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, + "node": "^18.0.0 || >=20.0.0" + }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "engines": { - "node": ">=4" + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "1.6.0", + "@vitest/ui": "1.6.0", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } } }, - "node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "node_modules/vitest/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "dev": true, "dependencies": { - "prelude-ls": "^1.2.1" + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" }, "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "node_modules/vitest/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "dev": true, "engines": { - "node": ">=10" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", - "dev": true - }, - "node_modules/typescript": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", - "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", + "node_modules/vitest/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, "engines": { - "node": ">=4.2.0" + "node": ">=16.17.0" } }, - "node_modules/uglify-js": { - "version": "3.17.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.3.tgz", - "integrity": "sha512-JmMFDME3iufZnBpyKL+uS78LRiC+mK55zWfM5f/pWBJfpOttXAqYfdDGRukYhJuyRinvPVAtUhvy7rlDybNtFg==", + "node_modules/vitest/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "dev": true, - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, "engines": { - "node": ">=0.8.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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/unicode-canonical-property-names-ecmascript": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", - "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "node_modules/vitest/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "dev": true, "engines": { - "node": ">=4" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "node_modules/vitest/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "dev": true, "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" + "path-key": "^4.0.0" }, "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", - "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "node_modules/vitest/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" + "mimic-fn": "^4.0.0" }, - "bin": { - "update-browserslist-db": "cli.js" + "engines": { + "node": ">=12" }, - "peerDependencies": { - "browserslist": ">= 4.21.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "node_modules/vitest/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", "dev": true, - "dependencies": { - "punycode": "^2.1.0" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true + "node_modules/vitest/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/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true + "node_modules/vitest/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/v8-to-istanbul": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", - "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "node_modules/vue-template-compiler": { + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz", + "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - }, - "engines": { - "node": ">=10.12.0" + "de-indent": "^1.0.2", + "he": "^1.2.0" } }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "node_modules/vue-tsc": { + "version": "1.8.27", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.27.tgz", + "integrity": "sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==", "dev": true, "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "@volar/typescript": "~1.11.1", + "@vue/language-core": "1.8.27", + "semver": "^7.5.4" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": "*" } }, - "node_modules/validate-npm-package-name": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", - "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", + "node_modules/vue-tsc/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=10" } }, "node_modules/walker": { @@ -13067,6 +17178,46 @@ "defaults": "^1.0.3" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -13082,6 +17233,22 @@ "node": ">= 8" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -13236,6 +17403,26 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/z-schema": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz", + "integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==", + "dev": true, + "dependencies": { + "lodash.get": "^4.4.2", + "lodash.isequal": "^4.5.0", + "validator": "^13.7.0" + }, + "bin": { + "z-schema": "bin/z-schema" + }, + "engines": { + "node": ">=8.0.0" + }, + "optionalDependencies": { + "commander": "^9.4.1" + } } }, "dependencies": { @@ -13689,7 +17876,8 @@ "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dev": true + "dev": true, + "requires": {} }, "@babel/plugin-syntax-async-generators": { "version": "7.8.4", @@ -14613,6 +18801,23 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "@buf/google_cel-spec.bufbuild_es": { + "version": "2.1.0-20240829202630-b69910e4e9bc.1", + "resolved": "https://buf.build/gen/npm/v1/@buf/google_cel-spec.bufbuild_es/-/google_cel-spec.bufbuild_es-2.1.0-20240829202630-b69910e4e9bc.1.tgz", + "requires": { + "@buf/googleapis_googleapis.bufbuild_es": "2.1.0-20240827201746-e7f8d366f526.1" + } + }, + "@buf/googleapis_googleapis.bufbuild_es": { + "version": "2.1.0-20240827201746-e7f8d366f526.1", + "resolved": "https://buf.build/gen/npm/v1/@buf/googleapis_googleapis.bufbuild_es/-/googleapis_googleapis.bufbuild_es-2.1.0-20240827201746-e7f8d366f526.1.tgz", + "requires": {} + }, + "@bufbuild/protobuf": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.1.0.tgz", + "integrity": "sha512-+2Mx67Y3skJ4NCD/qNSdBJNWtu6x6Qr53jeNg+QcwiL6mt0wK+3jwHH2x1p7xaYH6Ve2JKOVn0OxU35WsmqI9A==" + }, "@commitlint/cli": { "version": "14.1.0", "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-14.1.0.tgz", @@ -14728,6 +18933,14 @@ "lodash": "^4.17.19", "resolve-from": "^5.0.0", "typescript": "^4.4.3" + }, + "dependencies": { + "typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true + } } }, "@commitlint/message": { @@ -14868,61 +19081,270 @@ } } }, + "@cypress/request": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.1.tgz", + "integrity": "sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "http-signature": "~1.3.6", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "performance-now": "^2.1.0", + "qs": "6.10.4", + "safe-buffer": "^5.1.2", + "tough-cookie": "^4.1.3", + "tunnel-agent": "^0.6.0", + "uuid": "^8.3.2" + }, + "dependencies": { + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "qs": { + "version": "6.10.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz", + "integrity": "sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } + } + } + }, "@emnapi/core": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.2.0.tgz", "integrity": "sha512-E7Vgw78I93we4ZWdYCb4DGAwRROGkMIXk7/y87UmANR+J6qsWusmC3gLt0H+O0KOt5e6O38U8oJamgbudrES/w==", "dev": true, - "requires": { - "@emnapi/wasi-threads": "1.0.1", - "tslib": "^2.4.0" - } + "requires": { + "@emnapi/wasi-threads": "1.0.1", + "tslib": "^2.4.0" + } + }, + "@emnapi/runtime": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz", + "integrity": "sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==", + "dev": true, + "requires": { + "tslib": "^2.4.0" + } + }, + "@emnapi/wasi-threads": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.1.tgz", + "integrity": "sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==", + "dev": true, + "requires": { + "tslib": "^2.4.0" + } + }, + "@endemolshinegroup/cosmiconfig-typescript-loader": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@endemolshinegroup/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-3.0.2.tgz", + "integrity": "sha512-QRVtqJuS1mcT56oHpVegkKBlgtWjXw/gHNWO3eL9oyB5Sc7HBoc2OLG/nYpVfT/Jejvo3NUrD0Udk7XgoyDKkA==", + "dev": true, + "requires": { + "lodash.get": "^4", + "make-error": "^1", + "ts-node": "^9", + "tslib": "^2" + }, + "dependencies": { + "ts-node": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", + "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", + "dev": true, + "requires": { + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + } + } + } + }, + "@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "dev": true, + "optional": true }, - "@emnapi/runtime": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz", - "integrity": "sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==", + "@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", "dev": true, - "requires": { - "tslib": "^2.4.0" - } + "optional": true }, - "@emnapi/wasi-threads": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.1.tgz", - "integrity": "sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==", + "@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", "dev": true, - "requires": { - "tslib": "^2.4.0" - } + "optional": true }, - "@endemolshinegroup/cosmiconfig-typescript-loader": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@endemolshinegroup/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-3.0.2.tgz", - "integrity": "sha512-QRVtqJuS1mcT56oHpVegkKBlgtWjXw/gHNWO3eL9oyB5Sc7HBoc2OLG/nYpVfT/Jejvo3NUrD0Udk7XgoyDKkA==", + "@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", "dev": true, - "requires": { - "lodash.get": "^4", - "make-error": "^1", - "ts-node": "^9", - "tslib": "^2" - }, - "dependencies": { - "ts-node": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", - "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", - "dev": true, - "requires": { - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "source-map-support": "^0.5.17", - "yn": "3.1.1" - } - } - } + "optional": true }, "@eslint-community/eslint-utils": { "version": "4.4.0", @@ -15033,9 +19455,9 @@ "dev": true }, "@hutson/parse-repository-url": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", - "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-5.0.0.tgz", + "integrity": "sha512-e5+YUKENATs1JgYHMzTr2MW/NDcXGfYFAuOQU8gJgF/kEh4EqKgfGrfLI67bMD4tbhZVlkigz/9YYwWcbOFthg==", "dev": true }, "@istanbuljs/load-nyc-config": { @@ -15069,51 +19491,6 @@ "jest-message-util": "^29.7.0", "jest-util": "^29.7.0", "slash": "^3.0.0" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - } } }, "@jest/core": { @@ -15150,51 +19527,6 @@ "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - } } }, "@jest/environment": { @@ -15207,37 +19539,6 @@ "@jest/types": "^29.6.3", "@types/node": "*", "jest-mock": "^29.7.0" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - } } }, "@jest/expect": { @@ -15271,51 +19572,6 @@ "jest-message-util": "^29.7.0", "jest-mock": "^29.7.0", "jest-util": "^29.7.0" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - } } }, "@jest/globals": { @@ -15328,37 +19584,6 @@ "@jest/expect": "^29.7.0", "@jest/types": "^29.6.3", "jest-mock": "^29.7.0" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - } } }, "@jest/reporters": { @@ -15391,60 +19616,15 @@ "string-length": "^4.0.1", "strip-ansi": "^6.0.0", "v8-to-istanbul": "^9.0.1" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - } } }, "@jest/schemas": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", - "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "requires": { - "@sinclair/typebox": "^0.24.1" + "@sinclair/typebox": "^0.27.8" } }, "@jest/source-map": { @@ -15468,37 +19648,6 @@ "@jest/types": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - } } }, "@jest/test-sequencer": { @@ -15534,60 +19683,15 @@ "pirates": "^4.0.4", "slash": "^3.0.0", "write-file-atomic": "^4.0.2" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - } } }, "@jest/types": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", - "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, "requires": { - "@jest/schemas": "^28.1.3", + "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -15619,40 +19723,199 @@ "dev": true }, "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "dev": true }, - "@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "@jscutlery/semver": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@jscutlery/semver/-/semver-5.3.1.tgz", + "integrity": "sha512-LJk85tsYnISmRBQid4fjavBYUN8W5QwVQrcZ9KuTv+/D8Qy1A3wbMcc0kfBnnsGwFcKjYTwr4/eGJ/i1HgVk2Q==", + "dev": true, + "requires": { + "chalk": "4.1.2", + "conventional-changelog": "^5.1.0", + "conventional-changelog-angular": "^7.0.0", + "conventional-changelog-atom": "^4.0.0", + "conventional-changelog-codemirror": "^4.0.0", + "conventional-changelog-conventionalcommits": "^7.0.2", + "conventional-changelog-ember": "^4.0.0", + "conventional-changelog-eslint": "^5.0.0", + "conventional-changelog-express": "^4.0.0", + "conventional-changelog-jquery": "^5.0.0", + "conventional-changelog-jshint": "^4.0.0", + "conventional-commits-parser": "^5.0.0", + "conventional-recommended-bump": "^9.0.0", + "detect-indent": "6.1.0", + "git-semver-tags": "^7.0.1", + "inquirer": "8.2.6", + "rxjs": "7.8.1" + }, + "dependencies": { + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "conventional-changelog-angular": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", + "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==", + "dev": true, + "requires": { + "compare-func": "^2.0.0" + } + }, + "conventional-changelog-conventionalcommits": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-7.0.2.tgz", + "integrity": "sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==", + "dev": true, + "requires": { + "compare-func": "^2.0.0" + } + }, + "conventional-commits-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", + "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", + "dev": true, + "requires": { + "is-text-path": "^2.0.0", + "JSONStream": "^1.3.5", + "meow": "^12.0.1", + "split2": "^4.0.0" + } + }, + "is-text-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", + "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", + "dev": true, + "requires": { + "text-extensions": "^2.0.0" + } + }, + "meow": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", + "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", + "dev": true + }, + "rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + }, + "split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dev": true + }, + "text-extensions": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", + "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==", + "dev": true + } + } + }, + "@microsoft/api-extractor": { + "version": "7.43.0", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.43.0.tgz", + "integrity": "sha512-GFhTcJpB+MI6FhvXEI9b2K0snulNLWHqC/BbcJtyNYcKUiw7l3Lgis5ApsYncJ0leALX7/of4XfmXk+maT111w==", + "dev": true, + "requires": { + "@microsoft/api-extractor-model": "7.28.13", + "@microsoft/tsdoc": "0.14.2", + "@microsoft/tsdoc-config": "~0.16.1", + "@rushstack/node-core-library": "4.0.2", + "@rushstack/rig-package": "0.5.2", + "@rushstack/terminal": "0.10.0", + "@rushstack/ts-command-line": "4.19.1", + "lodash": "~4.17.15", + "minimatch": "~3.0.3", + "resolve": "~1.22.1", + "semver": "~7.5.4", + "source-map": "~0.6.1", + "typescript": "5.4.2" + }, + "dependencies": { + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "typescript": { + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", + "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", + "dev": true + } + } + }, + "@microsoft/api-extractor-model": { + "version": "7.28.13", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.28.13.tgz", + "integrity": "sha512-39v/JyldX4MS9uzHcdfmjjfS6cYGAoXV+io8B5a338pkHiSt+gy2eXQ0Q7cGFJ7quSa1VqqlMdlPrB6sLR/cAw==", "dev": true, "requires": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "@microsoft/tsdoc": "0.14.2", + "@microsoft/tsdoc-config": "~0.16.1", + "@rushstack/node-core-library": "4.0.2" } }, - "@jscutlery/semver": { - "version": "2.27.1", - "resolved": "https://registry.npmjs.org/@jscutlery/semver/-/semver-2.27.1.tgz", - "integrity": "sha512-uApRqj8Pc2CG9BbN/ZiWFz9xNq14XDueJZQnhsdO0B9CYoAZqCEoKLbToM7yRXkQ/ZRg7uV3xkrFYEWXVl1K8Q==", + "@microsoft/tsdoc": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz", + "integrity": "sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==", + "dev": true + }, + "@microsoft/tsdoc-config": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz", + "integrity": "sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==", "dev": true, "requires": { - "detect-indent": "6.1.0", - "inquirer": "8.2.4", - "rxjs": "7.5.6", - "standard-version": "9.5.0" + "@microsoft/tsdoc": "0.14.2", + "ajv": "~6.12.6", + "jju": "~1.4.0", + "resolve": "~1.19.0" }, "dependencies": { - "rxjs": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.6.tgz", - "integrity": "sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw==", + "resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", "dev": true, "requires": { - "tslib": "^2.1.0" + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" } } } @@ -15712,6 +19975,15 @@ "nx": "15.0.0" } }, + "@zkochan/js-yaml": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.6.tgz", + "integrity": "sha512-nzvgl3VfhcELQ8LyVrYOru+UtAy1nrygk2+AGbTm8a5YcO6o8lSjAT+pfg3vJWxIoZKOUhrK6UU7xW/+00kQrg==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -15875,6 +20147,24 @@ "tslib": "^2.3.0" } }, + "@nrwl/vite": { + "version": "19.8.0", + "resolved": "https://registry.npmjs.org/@nrwl/vite/-/vite-19.8.0.tgz", + "integrity": "sha512-Nux7PN5HYFnSbVj0lVIhgMRkfJ7AYRBr8lXDsJBFboxUtmnPGpG5aV6o/9Fu2XD/eiLBsHCmMcusqkD0+jCvMA==", + "dev": true, + "requires": { + "@nx/vite": "19.8.0" + } + }, + "@nrwl/web": { + "version": "19.8.0", + "resolved": "https://registry.npmjs.org/@nrwl/web/-/web-19.8.0.tgz", + "integrity": "sha512-rYADRAx2x88iiQdqRBbFN1m9pjBwBhT7v9XCKnZRjt/vRbjszBA73WlYpiZ41FqLwpJ9BgKITDYgQ9L0V4DpGw==", + "dev": true, + "requires": { + "@nx/web": "19.8.0" + } + }, "@nrwl/workspace": { "version": "19.8.0", "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.8.0.tgz", @@ -16007,41 +20297,242 @@ "jest-resolve": "^29.4.1", "jest-util": "^29.4.1", "minimatch": "9.0.3", - "resolve.exports": "1.1.0", - "semver": "^7.5.3", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" + "resolve.exports": "1.1.0", + "semver": "^7.5.3", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" + }, + "dependencies": { + "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, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true + }, + "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 + } + } + }, + "@nx/js": { + "version": "19.8.0", + "resolved": "https://registry.npmjs.org/@nx/js/-/js-19.8.0.tgz", + "integrity": "sha512-gexu1nYN3Hl3+yNuowgfd3sW5uooMKx9Dg6FPWWn/27+eJlTny5A2nQ3YR85yKRiJbNEP23am4le788pyVq2MQ==", + "dev": true, + "requires": { + "@babel/core": "^7.23.2", + "@babel/plugin-proposal-decorators": "^7.22.7", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-runtime": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/preset-typescript": "^7.22.5", + "@babel/runtime": "^7.22.6", + "@nrwl/js": "19.8.0", + "@nx/devkit": "19.8.0", + "@nx/workspace": "19.8.0", + "babel-plugin-const-enum": "^1.0.1", + "babel-plugin-macros": "^2.8.0", + "babel-plugin-transform-typescript-metadata": "^0.3.1", + "chalk": "^4.1.0", + "columnify": "^1.6.0", + "detect-port": "^1.5.1", + "fast-glob": "3.2.7", + "ignore": "^5.0.4", + "js-tokens": "^4.0.0", + "jsonc-parser": "3.2.0", + "minimatch": "9.0.3", + "npm-package-arg": "11.0.1", + "npm-run-path": "^4.0.1", + "ora": "5.3.0", + "semver": "^7.5.3", + "source-map-support": "0.5.19", + "ts-node": "10.9.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0" + }, + "dependencies": { + "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, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "ora": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.3.0.tgz", + "integrity": "sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==", + "dev": true, + "requires": { + "bl": "^4.0.3", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "log-symbols": "^4.0.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + } + }, + "semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, + "@nx/linter": { + "version": "19.8.0", + "resolved": "https://registry.npmjs.org/@nx/linter/-/linter-19.8.0.tgz", + "integrity": "sha512-v7jftcKnQLwz+ohlRR4EdbBXVumAFLzusNjnnpxYaCP7Vy4RK4qNZuLn4xANURhRgv/KlJBa+6TL9TttHpvT7g==", + "dev": true, + "requires": { + "@nx/eslint": "19.8.0" + } + }, + "@nx/node": { + "version": "19.8.0", + "resolved": "https://registry.npmjs.org/@nx/node/-/node-19.8.0.tgz", + "integrity": "sha512-93ANC3WfZu27BU9afedKoHBjMkNgqRY9FsKwI3L0c7gpzhA4yJBdzujI+oQSGP49oG3ipNcVz3n0ar3kerlMWQ==", + "dev": true, + "requires": { + "@nrwl/node": "19.8.0", + "@nx/devkit": "19.8.0", + "@nx/eslint": "19.8.0", + "@nx/jest": "19.8.0", + "@nx/js": "19.8.0", + "tslib": "^2.3.0" + } + }, + "@nx/nx-darwin-arm64": { + "version": "19.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.8.0.tgz", + "integrity": "sha512-JWtBb6ndCdGE+RBIwKN85BZnX41lFGsFxnsmot71GeAj/g7Cb0PM2qcmxawoy8yLPTBGZhb+eHER3z3nDIqRog==", + "dev": true, + "optional": true + }, + "@nx/nx-darwin-x64": { + "version": "19.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.8.0.tgz", + "integrity": "sha512-NcNaqbbStBkyahLaoKFtW6nEdjCjYT5ZOmGjc6UpAx1Y3pkk/FcIOYJRCBxwuOsRRsEAyeVcHPdYrouZmV+6Yw==", + "dev": true, + "optional": true + }, + "@nx/nx-freebsd-x64": { + "version": "19.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.8.0.tgz", + "integrity": "sha512-QXHRnMW5LrpYvtmdFRL2CRgX9CWDccrs2xhQNNzcgsLgL87Wte5kjDoJJN4GQjtrmjD3Q93w67CE9lhqnpXBvQ==", + "dev": true, + "optional": true + }, + "@nx/nx-linux-arm-gnueabihf": { + "version": "19.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.8.0.tgz", + "integrity": "sha512-VjZOLMxz0gT+0AdDygxQS0Vvi3AcEzO3y9o9WdGKKaDVUDycrFn72X+ZbvFoio1dF7S1s2TbmOlR09Bu1yTgGg==", + "dev": true, + "optional": true + }, + "@nx/nx-linux-arm64-gnu": { + "version": "19.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.8.0.tgz", + "integrity": "sha512-sCSrXkSmEfDUDGLESXB3eHXECAIYz9nosFZpCggyUP1vgF/QcV40fHnV38nrFbKaVHuoaxy43RgnD+I3o6sDSw==", + "dev": true, + "optional": true + }, + "@nx/nx-linux-arm64-musl": { + "version": "19.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.8.0.tgz", + "integrity": "sha512-F3xEe7NGjsVKZTVlvUiUOTmCzxteRsQH2SSsYXyAfgJ42P3eZPc9HgeLx6RByjC/NBCwc7XEECMP1FjQgQXHVw==", + "dev": true, + "optional": true + }, + "@nx/nx-linux-x64-gnu": { + "version": "19.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.8.0.tgz", + "integrity": "sha512-4uYuE+LvxOFXvi9z9ueJSVrME5D383SHNCjs6jYwc9KovCsmL5oPVXRieoE4/hYI4lrjly+CrAnPZU1P7ocBiw==", + "dev": true, + "optional": true + }, + "@nx/nx-linux-x64-musl": { + "version": "19.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.8.0.tgz", + "integrity": "sha512-9UDEGjOvNt+m+kMBCAB7CGisSwv05Xvaq8K3NJ+xM5GPG74EkQel24mSoIJfm/6zmDkdZCiRzNN9VRjOjzOz6Q==", + "dev": true, + "optional": true + }, + "@nx/nx-win32-arm64-msvc": { + "version": "19.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.8.0.tgz", + "integrity": "sha512-JVzm0KjyLZY5ponBukZ/b35wttW0b3LB0nqaiiHY7WKwSzo+m0UGEYHD/Yk6rKA0RRZN2wQVeIzLeWfYcZYrhA==", + "dev": true, + "optional": true + }, + "@nx/nx-win32-x64-msvc": { + "version": "19.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.8.0.tgz", + "integrity": "sha512-IRLhMZIInvp9okLsjnj76zaz8iaMovtLr6MHIFOOPIMsZYRhqQTArF5Os/NqEezeYYxvX6YZ5hKYe0xQO7A5LA==", + "dev": true, + "optional": true + }, + "@nx/vite": { + "version": "19.8.0", + "resolved": "https://registry.npmjs.org/@nx/vite/-/vite-19.8.0.tgz", + "integrity": "sha512-Krok+zalc6as1w+V+D/mmY+vh5qKdkvz4omMds2k3d+RQNxIb7Mh78ueGVQr5zRtR9CKSSPvDMtUklnjDlp1SQ==", + "dev": true, + "requires": { + "@nrwl/vite": "19.8.0", + "@nx/devkit": "19.8.0", + "@nx/js": "19.8.0", + "@phenomnomnominal/tsquery": "~5.0.1", + "@swc/helpers": "~0.5.0", + "enquirer": "~2.3.6", + "minimatch": "9.0.3", + "tsconfig-paths": "^4.1.2" }, "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, "brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -16051,20 +20542,6 @@ "balanced-match": "^1.0.0" } }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, "minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", @@ -16073,267 +20550,464 @@ "requires": { "brace-expansion": "^2.0.1" } - }, - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true - }, - "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 } } }, - "@nx/js": { + "@nx/web": { "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@nx/js/-/js-19.8.0.tgz", - "integrity": "sha512-gexu1nYN3Hl3+yNuowgfd3sW5uooMKx9Dg6FPWWn/27+eJlTny5A2nQ3YR85yKRiJbNEP23am4le788pyVq2MQ==", + "resolved": "https://registry.npmjs.org/@nx/web/-/web-19.8.0.tgz", + "integrity": "sha512-eP+NsnVlUAil35B6MuE5AGLPrruhlKNbkjYgExEwMEMVqFykvXY7drsxy2nhkmHJoO0IAG7emIQj+ZuFdUdKMw==", "dev": true, "requires": { - "@babel/core": "^7.23.2", - "@babel/plugin-proposal-decorators": "^7.22.7", - "@babel/plugin-transform-class-properties": "^7.22.5", - "@babel/plugin-transform-runtime": "^7.23.2", - "@babel/preset-env": "^7.23.2", - "@babel/preset-typescript": "^7.22.5", - "@babel/runtime": "^7.22.6", - "@nrwl/js": "19.8.0", + "@nrwl/web": "19.8.0", "@nx/devkit": "19.8.0", - "@nx/workspace": "19.8.0", - "babel-plugin-const-enum": "^1.0.1", - "babel-plugin-macros": "^2.8.0", - "babel-plugin-transform-typescript-metadata": "^0.3.1", + "@nx/js": "19.8.0", "chalk": "^4.1.0", - "columnify": "^1.6.0", "detect-port": "^1.5.1", - "fast-glob": "3.2.7", - "ignore": "^5.0.4", - "js-tokens": "^4.0.0", - "jsonc-parser": "3.2.0", - "minimatch": "9.0.3", - "npm-package-arg": "11.0.1", - "npm-run-path": "^4.0.1", - "ora": "5.3.0", - "semver": "^7.5.3", - "source-map-support": "0.5.19", - "ts-node": "10.9.1", - "tsconfig-paths": "^4.1.2", + "http-server": "^14.1.0", "tslib": "^2.3.0" + } + }, + "@nx/workspace": { + "version": "19.8.0", + "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.8.0.tgz", + "integrity": "sha512-8/NHRuJAqurNaFIUuSZdV8qNqiFykXlHjPp6E4raNmB8seIKYJVeYZgw9D7d5piOuLHA3o0JWSKJQ3nBElfCBw==", + "dev": true, + "requires": { + "@nrwl/workspace": "19.8.0", + "@nx/devkit": "19.8.0", + "chalk": "^4.1.0", + "enquirer": "~2.3.6", + "nx": "19.8.0", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" }, "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "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 + } + } + }, + "@parcel/watcher": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.0.4.tgz", + "integrity": "sha512-cTDi+FUDBIUOBKEtj+nhiJ71AZVlkAsQFuGQTun5tV9mwQBQgZvhCzG+URPQc8myeN32yRVZEfVAPCs1RW+Jvg==", + "dev": true, + "requires": { + "node-addon-api": "^3.2.1", + "node-gyp-build": "^4.3.0" + } + }, + "@phenomnomnominal/tsquery": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@phenomnomnominal/tsquery/-/tsquery-5.0.1.tgz", + "integrity": "sha512-3nVv+e2FQwsW8Aw6qTU6f+1rfcJ3hrcnvH/mu9i8YhxO+9sqbOfpL8m6PbET5+xKOlz/VSbp0RoYWYCtIsnmuA==", + "dev": true, + "requires": { + "esquery": "^1.4.0" + } + }, + "@polka/url": { + "version": "1.0.0-next.28", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz", + "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==", + "dev": true + }, + "@rollup/pluginutils": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.2.tgz", + "integrity": "sha512-/FIdS3PyZ39bjZlwqFnWqCOVnW7o963LtKMwQOD0NhQqw22gSr2YY1afu3FxRip4ZCZNsD5jq6Aaz6QV3D/Njw==", + "dev": true, + "requires": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "dependencies": { + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + } + } + }, + "@rollup/rollup-android-arm-eabi": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz", + "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==", + "dev": true, + "optional": true + }, + "@rollup/rollup-android-arm64": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz", + "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==", + "dev": true, + "optional": true + }, + "@rollup/rollup-darwin-arm64": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz", + "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==", + "dev": true, + "optional": true + }, + "@rollup/rollup-darwin-x64": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz", + "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz", + "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-arm-musleabihf": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz", + "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-arm64-gnu": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz", + "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-arm64-musl": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz", + "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz", + "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-riscv64-gnu": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz", + "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-s390x-gnu": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz", + "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-x64-gnu": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz", + "integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-x64-musl": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz", + "integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==", + "dev": true, + "optional": true + }, + "@rollup/rollup-win32-arm64-msvc": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz", + "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==", + "dev": true, + "optional": true + }, + "@rollup/rollup-win32-ia32-msvc": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz", + "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==", + "dev": true, + "optional": true + }, + "@rollup/rollup-win32-x64-msvc": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz", + "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==", + "dev": true, + "optional": true + }, + "@rushstack/node-core-library": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-4.0.2.tgz", + "integrity": "sha512-hyES82QVpkfQMeBMteQUnrhASL/KHPhd7iJ8euduwNJG4mu2GSOKybf0rOEjOm1Wz7CwJEUm9y0yD7jg2C1bfg==", + "dev": true, + "requires": { + "fs-extra": "~7.0.1", + "import-lazy": "~4.0.0", + "jju": "~1.4.0", + "resolve": "~1.22.1", + "semver": "~7.5.4", + "z-schema": "~5.0.2" + }, + "dependencies": { + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "dev": true, "requires": { - "balanced-match": "^1.0.0" + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" } }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, "requires": { - "brace-expansion": "^2.0.1" + "graceful-fs": "^4.1.6" } }, - "ora": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.3.0.tgz", - "integrity": "sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==", + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "requires": { - "bl": "^4.0.3", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "log-symbols": "^4.0.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" + "lru-cache": "^6.0.0" } }, - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true - }, - "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + } + } + }, + "@rushstack/rig-package": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.5.2.tgz", + "integrity": "sha512-mUDecIJeH3yYGZs2a48k+pbhM6JYwWlgjs2Ca5f2n1G2/kgdgP9D/07oglEGf6mRyXEnazhEENeYTSNDRCwdqA==", + "dev": true, + "requires": { + "resolve": "~1.22.1", + "strip-json-comments": "~3.1.1" + } + }, + "@rushstack/terminal": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.10.0.tgz", + "integrity": "sha512-UbELbXnUdc7EKwfH2sb8ChqNgapUOdqcCIdQP4NGxBpTZV2sQyeekuK3zmfQSa/MN+/7b4kBogl2wq0vpkpYGw==", + "dev": true, + "requires": { + "@rushstack/node-core-library": "4.0.2", + "supports-color": "~8.1.1" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "has-flag": "^4.0.0" } } } }, - "@nx/linter": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@nx/linter/-/linter-19.8.0.tgz", - "integrity": "sha512-v7jftcKnQLwz+ohlRR4EdbBXVumAFLzusNjnnpxYaCP7Vy4RK4qNZuLn4xANURhRgv/KlJBa+6TL9TttHpvT7g==", + "@rushstack/ts-command-line": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.19.1.tgz", + "integrity": "sha512-J7H768dgcpG60d7skZ5uSSwyCZs/S2HrWP1Ds8d1qYAyaaeJmpmmLr9BVw97RjFzmQPOYnoXcKA4GkqDCkduQg==", + "dev": true, + "requires": { + "@rushstack/terminal": "0.10.0", + "@types/argparse": "1.0.38", + "argparse": "~1.0.9", + "string-argv": "~0.3.1" + } + }, + "@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^3.0.0" + } + }, + "@swc-node/core": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/@swc-node/core/-/core-1.13.3.tgz", + "integrity": "sha512-OGsvXIid2Go21kiNqeTIn79jcaX4l0G93X2rAnas4LFoDyA9wAwVK7xZdm+QsKoMn5Mus2yFLCc4OtX2dD/PWA==", + "dev": true, + "requires": {} + }, + "@swc-node/register": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@swc-node/register/-/register-1.9.2.tgz", + "integrity": "sha512-BBjg0QNuEEmJSoU/++JOXhrjWdu3PTyYeJWsvchsI0Aqtj8ICkz/DqlwtXbmZVZ5vuDPpTfFlwDBZe81zgShMA==", "dev": true, "requires": { - "@nx/eslint": "19.8.0" + "@swc-node/core": "^1.13.1", + "@swc-node/sourcemap-support": "^0.5.0", + "colorette": "^2.0.20", + "debug": "^4.3.4", + "pirates": "^4.0.6", + "tslib": "^2.6.2" } }, - "@nx/node": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@nx/node/-/node-19.8.0.tgz", - "integrity": "sha512-93ANC3WfZu27BU9afedKoHBjMkNgqRY9FsKwI3L0c7gpzhA4yJBdzujI+oQSGP49oG3ipNcVz3n0ar3kerlMWQ==", + "@swc-node/sourcemap-support": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@swc-node/sourcemap-support/-/sourcemap-support-0.5.1.tgz", + "integrity": "sha512-JxIvIo/Hrpv0JCHSyRpetAdQ6lB27oFYhv0PKCNf1g2gUXOjpeR1exrXccRxLMuAV5WAmGFBwRnNOJqN38+qtg==", "dev": true, "requires": { - "@nrwl/node": "19.8.0", - "@nx/devkit": "19.8.0", - "@nx/eslint": "19.8.0", - "@nx/jest": "19.8.0", - "@nx/js": "19.8.0", - "tslib": "^2.3.0" + "source-map-support": "^0.5.21", + "tslib": "^2.6.3" } }, - "@nx/nx-darwin-arm64": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.8.0.tgz", - "integrity": "sha512-JWtBb6ndCdGE+RBIwKN85BZnX41lFGsFxnsmot71GeAj/g7Cb0PM2qcmxawoy8yLPTBGZhb+eHER3z3nDIqRog==", + "@swc/core": { + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.5.29.tgz", + "integrity": "sha512-nvTtHJI43DUSOAf3h9XsqYg8YXKc0/N4il9y4j0xAkO0ekgDNo+3+jbw6MInawjKJF9uulyr+f5bAutTsOKVlw==", "dev": true, - "optional": true + "requires": { + "@swc/core-darwin-arm64": "1.5.29", + "@swc/core-darwin-x64": "1.5.29", + "@swc/core-linux-arm-gnueabihf": "1.5.29", + "@swc/core-linux-arm64-gnu": "1.5.29", + "@swc/core-linux-arm64-musl": "1.5.29", + "@swc/core-linux-x64-gnu": "1.5.29", + "@swc/core-linux-x64-musl": "1.5.29", + "@swc/core-win32-arm64-msvc": "1.5.29", + "@swc/core-win32-ia32-msvc": "1.5.29", + "@swc/core-win32-x64-msvc": "1.5.29", + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.8" + } }, - "@nx/nx-darwin-x64": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.8.0.tgz", - "integrity": "sha512-NcNaqbbStBkyahLaoKFtW6nEdjCjYT5ZOmGjc6UpAx1Y3pkk/FcIOYJRCBxwuOsRRsEAyeVcHPdYrouZmV+6Yw==", + "@swc/core-darwin-arm64": { + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.5.29.tgz", + "integrity": "sha512-6F/sSxpHaq3nzg2ADv9FHLi4Fu2A8w8vP8Ich8gIl16D2htStlwnaPmCLjRswO+cFkzgVqy/l01gzNGWd4DFqA==", "dev": true, "optional": true }, - "@nx/nx-freebsd-x64": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.8.0.tgz", - "integrity": "sha512-QXHRnMW5LrpYvtmdFRL2CRgX9CWDccrs2xhQNNzcgsLgL87Wte5kjDoJJN4GQjtrmjD3Q93w67CE9lhqnpXBvQ==", + "@swc/core-darwin-x64": { + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.5.29.tgz", + "integrity": "sha512-rF/rXkvUOTdTIfoYbmszbSUGsCyvqACqy1VeP3nXONS+LxFl4bRmRcUTRrblL7IE5RTMCKUuPbqbQSE2hK7bqg==", "dev": true, "optional": true }, - "@nx/nx-linux-arm-gnueabihf": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.8.0.tgz", - "integrity": "sha512-VjZOLMxz0gT+0AdDygxQS0Vvi3AcEzO3y9o9WdGKKaDVUDycrFn72X+ZbvFoio1dF7S1s2TbmOlR09Bu1yTgGg==", + "@swc/core-linux-arm-gnueabihf": { + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.5.29.tgz", + "integrity": "sha512-2OAPL8iWBsmmwkjGXqvuUhbmmoLxS1xNXiMq87EsnCNMAKohGc7wJkdAOUL6J/YFpean/vwMWg64rJD4pycBeg==", "dev": true, "optional": true }, - "@nx/nx-linux-arm64-gnu": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.8.0.tgz", - "integrity": "sha512-sCSrXkSmEfDUDGLESXB3eHXECAIYz9nosFZpCggyUP1vgF/QcV40fHnV38nrFbKaVHuoaxy43RgnD+I3o6sDSw==", + "@swc/core-linux-arm64-gnu": { + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.5.29.tgz", + "integrity": "sha512-eH/Q9+8O5qhSxMestZnhuS1xqQMr6M7SolZYxiXJqxArXYILLCF+nq2R9SxuMl0CfjHSpb6+hHPk/HXy54eIRA==", "dev": true, "optional": true }, - "@nx/nx-linux-arm64-musl": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.8.0.tgz", - "integrity": "sha512-F3xEe7NGjsVKZTVlvUiUOTmCzxteRsQH2SSsYXyAfgJ42P3eZPc9HgeLx6RByjC/NBCwc7XEECMP1FjQgQXHVw==", + "@swc/core-linux-arm64-musl": { + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.5.29.tgz", + "integrity": "sha512-TERh2OICAJz+SdDIK9+0GyTUwF6r4xDlFmpoiHKHrrD/Hh3u+6Zue0d7jQ/he/i80GDn4tJQkHlZys+RZL5UZg==", "dev": true, "optional": true }, - "@nx/nx-linux-x64-gnu": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.8.0.tgz", - "integrity": "sha512-4uYuE+LvxOFXvi9z9ueJSVrME5D383SHNCjs6jYwc9KovCsmL5oPVXRieoE4/hYI4lrjly+CrAnPZU1P7ocBiw==", + "@swc/core-linux-x64-gnu": { + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.5.29.tgz", + "integrity": "sha512-WMDPqU7Ji9dJpA+Llek2p9t7pcy7Bob8ggPUvgsIlv3R/eesF9DIzSbrgl6j3EAEPB9LFdSafsgf6kT/qnvqFg==", "dev": true, "optional": true }, - "@nx/nx-linux-x64-musl": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.8.0.tgz", - "integrity": "sha512-9UDEGjOvNt+m+kMBCAB7CGisSwv05Xvaq8K3NJ+xM5GPG74EkQel24mSoIJfm/6zmDkdZCiRzNN9VRjOjzOz6Q==", + "@swc/core-linux-x64-musl": { + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.5.29.tgz", + "integrity": "sha512-DO14glwpdKY4POSN0201OnGg1+ziaSVr6/RFzuSLggshwXeeyVORiHv3baj7NENhJhWhUy3NZlDsXLnRFkmhHQ==", "dev": true, "optional": true }, - "@nx/nx-win32-arm64-msvc": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.8.0.tgz", - "integrity": "sha512-JVzm0KjyLZY5ponBukZ/b35wttW0b3LB0nqaiiHY7WKwSzo+m0UGEYHD/Yk6rKA0RRZN2wQVeIzLeWfYcZYrhA==", + "@swc/core-win32-arm64-msvc": { + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.5.29.tgz", + "integrity": "sha512-V3Y1+a1zG1zpYXUMqPIHEMEOd+rHoVnIpO/KTyFwAmKVu8v+/xPEVx/AGoYE67x4vDAAvPQrKI3Aokilqa5yVg==", "dev": true, "optional": true }, - "@nx/nx-win32-x64-msvc": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.8.0.tgz", - "integrity": "sha512-IRLhMZIInvp9okLsjnj76zaz8iaMovtLr6MHIFOOPIMsZYRhqQTArF5Os/NqEezeYYxvX6YZ5hKYe0xQO7A5LA==", + "@swc/core-win32-ia32-msvc": { + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.5.29.tgz", + "integrity": "sha512-OrM6yfXw4wXhnVFosOJzarw0Fdz5Y0okgHfn9oFbTPJhoqxV5Rdmd6kXxWu2RiVKs6kGSJFZXHDeUq2w5rTIMg==", "dev": true, "optional": true }, - "@nx/workspace": { - "version": "19.8.0", - "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.8.0.tgz", - "integrity": "sha512-8/NHRuJAqurNaFIUuSZdV8qNqiFykXlHjPp6E4raNmB8seIKYJVeYZgw9D7d5piOuLHA3o0JWSKJQ3nBElfCBw==", - "dev": true, - "requires": { - "@nrwl/workspace": "19.8.0", - "@nx/devkit": "19.8.0", - "chalk": "^4.1.0", - "enquirer": "~2.3.6", - "nx": "19.8.0", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - }, - "dependencies": { - "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 - } - } - }, - "@parcel/watcher": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.0.4.tgz", - "integrity": "sha512-cTDi+FUDBIUOBKEtj+nhiJ71AZVlkAsQFuGQTun5tV9mwQBQgZvhCzG+URPQc8myeN32yRVZEfVAPCs1RW+Jvg==", - "dev": true, - "requires": { - "node-addon-api": "^3.2.1", - "node-gyp-build": "^4.3.0" - } - }, - "@phenomnomnominal/tsquery": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@phenomnomnominal/tsquery/-/tsquery-5.0.1.tgz", - "integrity": "sha512-3nVv+e2FQwsW8Aw6qTU6f+1rfcJ3hrcnvH/mu9i8YhxO+9sqbOfpL8m6PbET5+xKOlz/VSbp0RoYWYCtIsnmuA==", + "@swc/core-win32-x64-msvc": { + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.5.29.tgz", + "integrity": "sha512-eD/gnxqKyZQQR0hR7TMkIlJ+nCF9dzYmVVNbYZWuA1Xy94aBPUsEk3Uw3oG7q6R3ErrEUPP0FNf2ztEnv+I+dw==", "dev": true, - "requires": { - "esquery": "^1.4.0" - } + "optional": true }, - "@sinclair/typebox": { - "version": "0.24.46", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.46.tgz", - "integrity": "sha512-ng4ut1z2MCBhK/NwDVwIQp3pAUOCs/KNaW3cBxdFB2xTDrOuo1xuNmpr/9HHFhxqIvHrs1NTH3KJg6q+JSy1Kw==", + "@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", "dev": true }, - "@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "@swc/helpers": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.13.tgz", + "integrity": "sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==", "dev": true, "requires": { - "type-detect": "4.0.8" + "tslib": "^2.4.0" } }, - "@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "@swc/types": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.12.tgz", + "integrity": "sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==", "dev": true, "requires": { - "@sinonjs/commons": "^3.0.0" + "@swc/counter": "^0.1.3" } }, "@tsconfig/node10": { @@ -16369,6 +21043,12 @@ "tslib": "^2.4.0" } }, + "@types/argparse": { + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz", + "integrity": "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==", + "dev": true + }, "@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -16416,6 +21096,12 @@ "integrity": "sha1-RHpqJXYZE0SqQjEBMd099cQUksQ=", "dev": true }, + "@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true + }, "@types/graceful-fs": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", @@ -16585,12 +21271,153 @@ "integrity": "sha512-dtePl4gsuenXVwC7dVNlb4mGDcKjDT/Ropsk4za/ouMBPplCLyznIaR+W65mvCvsyS97dymoBRrioEXI7k0XIg==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "8.6.0", - "@typescript-eslint/utils": "8.6.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" + "@typescript-eslint/typescript-estree": "8.6.0", + "@typescript-eslint/utils": "8.6.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "dependencies": { + "@typescript-eslint/types": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.6.0.tgz", + "integrity": "sha512-rojqFZGd4MQxw33SrOy09qIDS8WEldM8JWtKQLAjf/X5mGSeEFh5ixQlxssMNyPslVIk9yzWqXCsV2eFhYrYUw==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.6.0.tgz", + "integrity": "sha512-MOVAzsKJIPIlLK239l5s06YXjNqpKTVhBVDnqUumQJja5+Y94V3+4VUFRA0G60y2jNnTVwRCkhyGQpavfsbq/g==", + "dev": true, + "requires": { + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/visitor-keys": "8.6.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.6.0.tgz", + "integrity": "sha512-wapVFfZg9H0qOYh4grNVQiMklJGluQrOUiOhYRrQWhx7BY/+I1IYb8BczWNbbUpO+pqy0rDciv3lQH5E1bCLrg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "8.6.0", + "eslint-visitor-keys": "^3.4.3" + } + }, + "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, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "fast-glob": { + "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, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, + "minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true + } + } + }, + "@typescript-eslint/types": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", + "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", + "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "dependencies": { + "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, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true + } + } + }, + "@typescript-eslint/utils": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.6.0.tgz", + "integrity": "sha512-eNp9cWnYf36NaOVjkEUznf6fEgVy1TWpE0o52e4wtojjBx7D1UV2WAWGzR+8Y5lVFtpMLPwNbC67T83DWSph4A==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.6.0", + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/typescript-estree": "8.6.0" }, "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.6.0.tgz", + "integrity": "sha512-ZuoutoS5y9UOxKvpc/GkvF4cuEmpokda4wRg64JEia27wX+PysIE9q+lzDtlHHgblwUWwo5/Qn+/WyTUvDwBHw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/visitor-keys": "8.6.0" + } + }, "@typescript-eslint/types": { "version": "8.6.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.6.0.tgz", @@ -16662,28 +21489,77 @@ } } }, - "@typescript-eslint/types": { + "@typescript-eslint/visitor-keys": { "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", - "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", + "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "7.18.0", + "eslint-visitor-keys": "^3.4.3" + } + }, + "@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 }, - "@typescript-eslint/typescript-estree": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", - "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", + "@verdaccio/auth": { + "version": "8.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/@verdaccio/auth/-/auth-8.0.0-next-8.1.tgz", + "integrity": "sha512-sPmHdnYuRSMgABCsTJEfz8tb/smONsWVg0g4KK2QycyYZ/A+RwZLV1JLiQb4wzu9zvS0HSloqWqkWlyNHW3mtw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" + "@verdaccio/config": "8.0.0-next-8.1", + "@verdaccio/core": "8.0.0-next-8.1", + "@verdaccio/loaders": "8.0.0-next-8.1", + "@verdaccio/logger": "8.0.0-next-8.1", + "@verdaccio/signature": "8.0.0-next-8.0", + "@verdaccio/utils": "7.0.1-next-8.1", + "debug": "4.3.7", + "lodash": "4.17.21", + "verdaccio-htpasswd": "13.0.0-next-8.1" + } + }, + "@verdaccio/commons-api": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@verdaccio/commons-api/-/commons-api-10.2.0.tgz", + "integrity": "sha512-F/YZANu4DmpcEV0jronzI7v2fGVWkQ5Mwi+bVmV+ACJ+EzR0c9Jbhtbe5QyLUuzR97t8R5E/Xe53O0cc2LukdQ==", + "dev": true, + "requires": { + "http-errors": "2.0.0", + "http-status-codes": "2.2.0" + }, + "dependencies": { + "http-status-codes": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-2.2.0.tgz", + "integrity": "sha512-feERVo9iWxvnejp3SEfm/+oNG517npqL2/PIA8ORjyOZjGC7TwCRQsZylciLS64i6pJ0wRYz3rkXLRwbtFa8Ng==", + "dev": true + } + } + }, + "@verdaccio/config": { + "version": "8.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/@verdaccio/config/-/config-8.0.0-next-8.1.tgz", + "integrity": "sha512-goDVOH4e8xMUxjHybJpi5HwIecVFqzJ9jeNFrRUgtUUn0PtFuNMHgxOeqDKRVboZhc5HK90yed8URK/1O6VsUw==", + "dev": true, + "requires": { + "@verdaccio/core": "8.0.0-next-8.1", + "@verdaccio/utils": "7.0.1-next-8.1", + "debug": "4.3.7", + "js-yaml": "4.1.0", + "lodash": "4.17.21", + "minimatch": "7.4.6" }, "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, "brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -16693,14 +21569,57 @@ "balanced-match": "^1.0.0" } }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, "minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz", + "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==", "dev": true, "requires": { "brace-expansion": "^2.0.1" } + } + } + }, + "@verdaccio/core": { + "version": "8.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/@verdaccio/core/-/core-8.0.0-next-8.1.tgz", + "integrity": "sha512-kQRCB2wgXEh8H88G51eQgAFK9IxmnBtkQ8sY5FbmB6PbBkyHrbGcCp+2mtRqqo36j0W1VAlfM3XzoknMy6qQnw==", + "dev": true, + "requires": { + "ajv": "8.17.1", + "core-js": "3.37.1", + "http-errors": "2.0.0", + "http-status-codes": "2.3.0", + "process-warning": "1.0.0", + "semver": "7.6.3" + }, + "dependencies": { + "ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true }, "semver": { "version": "7.6.3", @@ -16710,69 +21629,447 @@ } } }, - "@typescript-eslint/utils": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.6.0.tgz", - "integrity": "sha512-eNp9cWnYf36NaOVjkEUznf6fEgVy1TWpE0o52e4wtojjBx7D1UV2WAWGzR+8Y5lVFtpMLPwNbC67T83DWSph4A==", + "@verdaccio/file-locking": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/@verdaccio/file-locking/-/file-locking-10.3.1.tgz", + "integrity": "sha512-oqYLfv3Yg3mAgw9qhASBpjD50osj2AX4IwbkUtyuhhKGyoFU9eZdrbeW6tpnqUnj6yBMtAPm2eGD4BwQuX400g==", "dev": true, "requires": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.6.0", - "@typescript-eslint/types": "8.6.0", - "@typescript-eslint/typescript-estree": "8.6.0" + "lockfile": "1.0.4" + } + }, + "@verdaccio/loaders": { + "version": "8.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/@verdaccio/loaders/-/loaders-8.0.0-next-8.1.tgz", + "integrity": "sha512-mqGCUBs862g8mICZwX8CG92p1EZ1Un0DJ2DB7+iVu2TYaEeKoHoIdafabVdiYrbOjLcAOOBrMKE1Wnn14eLxpA==", + "dev": true, + "requires": { + "@verdaccio/logger": "8.0.0-next-8.1", + "debug": "4.3.7", + "lodash": "4.17.21" + } + }, + "@verdaccio/local-storage-legacy": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/@verdaccio/local-storage-legacy/-/local-storage-legacy-11.0.2.tgz", + "integrity": "sha512-7AXG7qlcVFmF+Nue2oKaraprGRtaBvrQIOvc/E89+7hAe399V01KnZI6E/ET56u7U9fq0MSlp92HBcdotlpUXg==", + "dev": true, + "requires": { + "@verdaccio/commons-api": "10.2.0", + "@verdaccio/file-locking": "10.3.1", + "@verdaccio/streams": "10.2.1", + "async": "3.2.4", + "debug": "4.3.4", + "lodash": "4.17.21", + "lowdb": "1.0.0", + "mkdirp": "1.0.4" }, "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.6.0.tgz", - "integrity": "sha512-ZuoutoS5y9UOxKvpc/GkvF4cuEmpokda4wRg64JEia27wX+PysIE9q+lzDtlHHgblwUWwo5/Qn+/WyTUvDwBHw==", + "async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "requires": { - "@typescript-eslint/types": "8.6.0", - "@typescript-eslint/visitor-keys": "8.6.0" + "ms": "2.1.2" } }, - "@typescript-eslint/types": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.6.0.tgz", - "integrity": "sha512-rojqFZGd4MQxw33SrOy09qIDS8WEldM8JWtKQLAjf/X5mGSeEFh5ixQlxssMNyPslVIk9yzWqXCsV2eFhYrYUw==", + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true }, - "@typescript-eslint/typescript-estree": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.6.0.tgz", - "integrity": "sha512-MOVAzsKJIPIlLK239l5s06YXjNqpKTVhBVDnqUumQJja5+Y94V3+4VUFRA0G60y2jNnTVwRCkhyGQpavfsbq/g==", + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@verdaccio/logger": { + "version": "8.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/@verdaccio/logger/-/logger-8.0.0-next-8.1.tgz", + "integrity": "sha512-w5kR0/umQkfH2F4PK5Fz9T6z3xz+twewawKLPTUfAgrVAOiWxcikGhhcHWhSGiJ0lPqIa+T0VYuLWMeVeDirGw==", + "dev": true, + "requires": { + "@verdaccio/logger-commons": "8.0.0-next-8.1", + "pino": "8.17.2" + } + }, + "@verdaccio/logger-7": { + "version": "8.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/@verdaccio/logger-7/-/logger-7-8.0.0-next-8.1.tgz", + "integrity": "sha512-V+/B1Wnct3IZ90q6HkI1a3dqbS0ds7s/5WPrS5cmBeLEw78/OGgF76XkhI2+lett7Un1CjVow7mcebOWcZ/Sqw==", + "dev": true, + "requires": { + "@verdaccio/logger-commons": "8.0.0-next-8.1", + "pino": "7.11.0" + }, + "dependencies": { + "duplexify": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz", + "integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==", "dev": true, "requires": { - "@typescript-eslint/types": "8.6.0", - "@typescript-eslint/visitor-keys": "8.6.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.2" } }, - "@typescript-eslint/visitor-keys": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.6.0.tgz", - "integrity": "sha512-wapVFfZg9H0qOYh4grNVQiMklJGluQrOUiOhYRrQWhx7BY/+I1IYb8BczWNbbUpO+pqy0rDciv3lQH5E1bCLrg==", + "on-exit-leak-free": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz", + "integrity": "sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg==", + "dev": true + }, + "pino": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-7.11.0.tgz", + "integrity": "sha512-dMACeu63HtRLmCG8VKdy4cShCPKaYDR4youZqoSWLxl5Gu99HUw8bw75thbPv9Nip+H+QYX8o3ZJbTdVZZ2TVg==", "dev": true, "requires": { - "@typescript-eslint/types": "8.6.0", - "eslint-visitor-keys": "^3.4.3" + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.0.0", + "on-exit-leak-free": "^0.2.0", + "pino-abstract-transport": "v0.5.0", + "pino-std-serializers": "^4.0.0", + "process-warning": "^1.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.1.0", + "safe-stable-stringify": "^2.1.0", + "sonic-boom": "^2.2.1", + "thread-stream": "^0.15.1" + } + }, + "pino-abstract-transport": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-0.5.0.tgz", + "integrity": "sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ==", + "dev": true, + "requires": { + "duplexify": "^4.1.2", + "split2": "^4.0.0" + } + }, + "pino-std-serializers": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz", + "integrity": "sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q==", + "dev": true + }, + "real-require": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.1.0.tgz", + "integrity": "sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg==", + "dev": true + }, + "sonic-boom": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.8.0.tgz", + "integrity": "sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg==", + "dev": true, + "requires": { + "atomic-sleep": "^1.0.0" + } + }, + "split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dev": true + }, + "thread-stream": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-0.15.2.tgz", + "integrity": "sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA==", + "dev": true, + "requires": { + "real-require": "^0.1.0" } + } + } + }, + "@verdaccio/logger-commons": { + "version": "8.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/@verdaccio/logger-commons/-/logger-commons-8.0.0-next-8.1.tgz", + "integrity": "sha512-jCge//RT4uaK7MarhpzcJeJ5Uvtu/DbJ1wvJQyGiFe+9AvxDGm3EUFXvawLFZ0lzYhmLt1nvm7kevcc3vOm2ZQ==", + "dev": true, + "requires": { + "@verdaccio/core": "8.0.0-next-8.1", + "@verdaccio/logger-prettify": "8.0.0-next-8.0", + "colorette": "2.0.20", + "debug": "4.3.7" + } + }, + "@verdaccio/logger-prettify": { + "version": "8.0.0-next-8.0", + "resolved": "https://registry.npmjs.org/@verdaccio/logger-prettify/-/logger-prettify-8.0.0-next-8.0.tgz", + "integrity": "sha512-7mAFHZF2NPTubrOXYp2+fbMjRW5MMWXMeS3LcpupMAn5uPp6jkKEM8NC4IVJEevC5Ph4vPVZqpoPDpgXHEaV3Q==", + "dev": true, + "requires": { + "colorette": "2.0.20", + "dayjs": "1.11.13", + "lodash": "4.17.21", + "pino-abstract-transport": "1.1.0", + "sonic-boom": "3.8.0" + } + }, + "@verdaccio/middleware": { + "version": "8.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/@verdaccio/middleware/-/middleware-8.0.0-next-8.1.tgz", + "integrity": "sha512-GpAdJYky1WmOERpxPoCkVSwTTJIsVAjqf2a2uQNvi7R3UZhs059JKhWcZjJMVCGV0uz9xgQvtb3DEuYGHqyaOg==", + "dev": true, + "requires": { + "@verdaccio/config": "8.0.0-next-8.1", + "@verdaccio/core": "8.0.0-next-8.1", + "@verdaccio/url": "13.0.0-next-8.1", + "@verdaccio/utils": "7.0.1-next-8.1", + "debug": "4.3.7", + "express": "4.21.0", + "express-rate-limit": "5.5.1", + "lodash": "4.17.21", + "lru-cache": "7.18.3", + "mime": "2.6.0" + }, + "dependencies": { + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true }, + "mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true + } + } + }, + "@verdaccio/search-indexer": { + "version": "8.0.0-next-8.0", + "resolved": "https://registry.npmjs.org/@verdaccio/search-indexer/-/search-indexer-8.0.0-next-8.0.tgz", + "integrity": "sha512-VS9axVt8XAueiPceVCgaj9nlvYj5s/T4MkAILSf2rVZeFFOMUyxU3mddUCajSHzL+YpqCuzLLL9865sRRzOJ9w==", + "dev": true + }, + "@verdaccio/signature": { + "version": "8.0.0-next-8.0", + "resolved": "https://registry.npmjs.org/@verdaccio/signature/-/signature-8.0.0-next-8.0.tgz", + "integrity": "sha512-klcc2UlCvQxXDV65Qewo2rZOfv7S1y8NekS/8uurSaCTjU35T+fz+Pbqz1S9XK9oQlMp4vCQ7w3iMPWQbvphEQ==", + "dev": true, + "requires": { + "debug": "4.3.7", + "jsonwebtoken": "9.0.2" + } + }, + "@verdaccio/streams": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/@verdaccio/streams/-/streams-10.2.1.tgz", + "integrity": "sha512-OojIG/f7UYKxC4dYX8x5ax8QhRx1b8OYUAMz82rUottCuzrssX/4nn5QE7Ank0DUSX3C9l/HPthc4d9uKRJqJQ==", + "dev": true + }, + "@verdaccio/tarball": { + "version": "13.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/@verdaccio/tarball/-/tarball-13.0.0-next-8.1.tgz", + "integrity": "sha512-58uimU2Bqt9+s+9ixy7wK/nPCqbOXhhhr/MQjl+otIlsUhSeATndhFzEctz/W+4MhUDg0tUnE9HC2yeNHHAo1Q==", + "dev": true, + "requires": { + "@verdaccio/core": "8.0.0-next-8.1", + "@verdaccio/url": "13.0.0-next-8.1", + "@verdaccio/utils": "7.0.1-next-8.1", + "debug": "4.3.7", + "gunzip-maybe": "^1.4.2", + "lodash": "4.17.21", + "tar-stream": "^3.1.7" + }, + "dependencies": { + "tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "dev": true, + "requires": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + } + } + }, + "@verdaccio/ui-theme": { + "version": "8.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/@verdaccio/ui-theme/-/ui-theme-8.0.0-next-8.1.tgz", + "integrity": "sha512-9PxV8+jE2Tr+iy9DQW/bzny4YqOlW0mCZ9ct6jhcUW4GdfzU//gY2fBN/DDtQVmfbTy8smuj4Enyv5f0wCsnYg==", + "dev": true + }, + "@verdaccio/url": { + "version": "13.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/@verdaccio/url/-/url-13.0.0-next-8.1.tgz", + "integrity": "sha512-h6pkJf+YtogImKgOrmPP9UVG3p3gtb67gqkQU0bZnK+SEKQt6Rkek/QvtJ8MbmciagYS18bDhpI8DxqLHjDfZQ==", + "dev": true, + "requires": { + "@verdaccio/core": "8.0.0-next-8.1", + "debug": "4.3.7", + "lodash": "4.17.21", + "validator": "13.12.0" + } + }, + "@verdaccio/utils": { + "version": "7.0.1-next-8.1", + "resolved": "https://registry.npmjs.org/@verdaccio/utils/-/utils-7.0.1-next-8.1.tgz", + "integrity": "sha512-cyJdRrVa+8CS7UuIQb3K3IJFjMe64v38tYiBnohSmhRbX7dX9IT3jWbjrwkqWh4KeS1CS6BYENrGG1evJ2ggrQ==", + "dev": true, + "requires": { + "@verdaccio/core": "8.0.0-next-8.1", + "lodash": "4.17.21", + "minimatch": "7.4.6", + "semver": "7.6.3" + }, + "dependencies": { "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, "requires": { - "balanced-match": "^1.0.0" + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz", + "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true + } + } + }, + "@vitest/coverage-v8": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-1.6.0.tgz", + "integrity": "sha512-KvapcbMY/8GYIG0rlwwOKCVNRc0OL20rrhFkg/CHNzncV03TE2XWvO5w9uZYoxNiMEBacAJt3unSOiZ7svePew==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.2.1", + "@bcoe/v8-coverage": "^0.2.3", + "debug": "^4.3.4", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-lib-source-maps": "^5.0.4", + "istanbul-reports": "^3.1.6", + "magic-string": "^0.30.5", + "magicast": "^0.3.3", + "picocolors": "^1.0.0", + "std-env": "^3.5.0", + "strip-literal": "^2.0.0", + "test-exclude": "^6.0.0" + }, + "dependencies": { + "istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" + } + } + } + }, + "@vitest/expect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.0.tgz", + "integrity": "sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==", + "dev": true, + "requires": { + "@vitest/spy": "1.6.0", + "@vitest/utils": "1.6.0", + "chai": "^4.3.10" + } + }, + "@vitest/runner": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.6.0.tgz", + "integrity": "sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==", + "dev": true, + "requires": { + "@vitest/utils": "1.6.0", + "p-limit": "^5.0.0", + "pathe": "^1.1.1" + }, + "dependencies": { + "p-limit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", + "dev": true, + "requires": { + "yocto-queue": "^1.0.0" } }, + "yocto-queue": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", + "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", + "dev": true + } + } + }, + "@vitest/snapshot": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.6.0.tgz", + "integrity": "sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==", + "dev": true, + "requires": { + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "pretty-format": "^29.7.0" + } + }, + "@vitest/spy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.0.tgz", + "integrity": "sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==", + "dev": true, + "requires": { + "tinyspy": "^2.2.0" + } + }, + "@vitest/ui": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-1.6.0.tgz", + "integrity": "sha512-k3Lyo+ONLOgylctiGovRKy7V4+dIN2yxstX3eY5cWFXH6WP+ooVX79YSyi0GagdTQzLmT43BF27T0s6dOIPBXA==", + "dev": true, + "requires": { + "@vitest/utils": "1.6.0", + "fast-glob": "^3.3.2", + "fflate": "^0.8.1", + "flatted": "^3.2.9", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "sirv": "^2.0.4" + }, + "dependencies": { "fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -16785,6 +22082,105 @@ "merge2": "^1.3.0", "micromatch": "^4.0.4" } + } + } + }, + "@vitest/utils": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.0.tgz", + "integrity": "sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==", + "dev": true, + "requires": { + "diff-sequences": "^29.6.3", + "estree-walker": "^3.0.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" + } + }, + "@volar/language-core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-1.11.1.tgz", + "integrity": "sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==", + "dev": true, + "requires": { + "@volar/source-map": "1.11.1" + } + }, + "@volar/source-map": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-1.11.1.tgz", + "integrity": "sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg==", + "dev": true, + "requires": { + "muggle-string": "^0.3.1" + } + }, + "@volar/typescript": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-1.11.1.tgz", + "integrity": "sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ==", + "dev": true, + "requires": { + "@volar/language-core": "1.11.1", + "path-browserify": "^1.0.1" + } + }, + "@vue/compiler-core": { + "version": "3.5.8", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.8.tgz", + "integrity": "sha512-Uzlxp91EPjfbpeO5KtC0KnXPkuTfGsNDeaKQJxQN718uz+RqDYarEf7UhQJGK+ZYloD2taUbHTI2J4WrUaZQNA==", + "dev": true, + "requires": { + "@babel/parser": "^7.25.3", + "@vue/shared": "3.5.8", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" + }, + "dependencies": { + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + } + } + }, + "@vue/compiler-dom": { + "version": "3.5.8", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.8.tgz", + "integrity": "sha512-GUNHWvoDSbSa5ZSHT9SnV5WkStWfzJwwTd6NMGzilOE/HM5j+9EB9zGXdtu/fCNEmctBqMs6C9SvVPpVPuk1Eg==", + "dev": true, + "requires": { + "@vue/compiler-core": "3.5.8", + "@vue/shared": "3.5.8" + } + }, + "@vue/language-core": { + "version": "1.8.27", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.27.tgz", + "integrity": "sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==", + "dev": true, + "requires": { + "@volar/language-core": "~1.11.1", + "@volar/source-map": "~1.11.1", + "@vue/compiler-dom": "^3.3.0", + "@vue/shared": "^3.3.0", + "computeds": "^0.0.1", + "minimatch": "^9.0.3", + "muggle-string": "^0.3.1", + "path-browserify": "^1.0.1", + "vue-template-compiler": "^2.7.14" + }, + "dependencies": { + "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, + "requires": { + "balanced-match": "^1.0.0" + } }, "minimatch": { "version": "9.0.5", @@ -16794,29 +22190,13 @@ "requires": { "brace-expansion": "^2.0.1" } - }, - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true } } }, - "@typescript-eslint/visitor-keys": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", - "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "7.18.0", - "eslint-visitor-keys": "^3.4.3" - } - }, - "@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==", + "@vue/shared": { + "version": "3.5.8", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.8.tgz", + "integrity": "sha512-mJleSWbAGySd2RJdX1RBtcrUBX6snyOc0qHpgk3lGi4l9/P/3ny3ELqFWqYdkXIwwNN/kdm8nD9ky8o6l/Lx2A==", "dev": true }, "@yarnpkg/lockfile": { @@ -16836,9 +22216,9 @@ } }, "@zkochan/js-yaml": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.6.tgz", - "integrity": "sha512-nzvgl3VfhcELQ8LyVrYOru+UtAy1nrygk2+AGbTm8a5YcO6o8lSjAT+pfg3vJWxIoZKOUhrK6UU7xW/+00kQrg==", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.7.tgz", + "integrity": "sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==", "dev": true, "requires": { "argparse": "^2.0.1" @@ -16852,6 +22232,25 @@ } } }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "requires": { + "event-target-shim": "^5.0.0" + } + }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, "acorn": { "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", @@ -16862,13 +22261,17 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true + "dev": true, + "requires": {} }, "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "requires": { + "acorn": "^8.11.0" + } }, "add-stream": { "version": "1.0.0", @@ -16882,6 +22285,15 @@ "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", "dev": true }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -16924,6 +22336,11 @@ "color-convert": "^2.0.1" } }, + "antlr4": { + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.13.2.tgz", + "integrity": "sha512-QiVbZhyy4xAZ17UPEuG3YTOt8ZaoeOR1CvEAqrEsDBsOqINslaB147i9xqljZqoyf5S+EUlGStaj+t22LT9MOg==" + }, "anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", @@ -16934,6 +22351,12 @@ "picomatch": "^2.0.4" } }, + "apache-md5": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/apache-md5/-/apache-md5-1.1.8.tgz", + "integrity": "sha512-FCAJojipPn0bXjuEpjOOOMN8FZDkxfWWp4JGN9mifU2IhxvKyXZYqpzPHdnTSUpmPDy+tsslB6Z1g+Vg6nVbYA==", + "dev": true + }, "arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -16949,6 +22372,12 @@ "sprintf-js": "~1.0.2" } }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, "array-ify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", @@ -16967,6 +22396,27 @@ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, + "asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, "async": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", @@ -16979,6 +22429,24 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true }, + "atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "dev": true + }, + "aws4": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", + "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", + "dev": true + }, "axios": { "version": "1.7.7", "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", @@ -16990,6 +22458,12 @@ "proxy-from-env": "^1.1.0" } }, + "b4a": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", + "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==", + "dev": true + }, "babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -17192,12 +22666,43 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "bare-events": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.4.2.tgz", + "integrity": "sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==", + "dev": true, + "optional": true + }, "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "dev": true }, + "basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==", + "dev": true + }, "binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -17215,6 +22720,49 @@ "readable-stream": "^3.4.0" } }, + "body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "dev": true, + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + } + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -17234,6 +22782,15 @@ "fill-range": "^7.0.1" } }, + "browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==", + "dev": true, + "requires": { + "pako": "~0.2.0" + } + }, "browserslist": { "version": "4.23.3", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", @@ -17274,18 +22831,49 @@ "ieee754": "^1.1.13" } }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "dev": true + }, "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "dev": true + }, + "cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true + }, "cachedir": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.2.0.tgz", "integrity": "sha512-VvxA0xhNqIIfg0V9AmJkDg91DaJwryutH5rVEZAhcNi4iJFj9f+QxmAjgK1LT9I8OgToX27fypX6/MeCXVbBjQ==", "dev": true }, + "call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + } + }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -17315,6 +22903,35 @@ "integrity": "sha512-sgMUVwLmGseH8ZIrm1d51UbrhqMCH3jvS7gF/M6byuHOnKyLOBL7W8yz5V02OHwgLGA36o/AFhWzzh4uc5aqTA==", "dev": true }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true + }, + "chai": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", + "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.1.0" + }, + "dependencies": { + "type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "dev": true + } + } + }, "chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -17337,6 +22954,15 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, + "check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "requires": { + "get-func-name": "^2.0.2" + } + }, "chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -17391,6 +23017,15 @@ "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", "dev": true }, + "clipanion": { + "version": "4.0.0-rc.3", + "resolved": "https://registry.npmjs.org/clipanion/-/clipanion-4.0.0-rc.3.tgz", + "integrity": "sha512-+rJOJMt2N6Oikgtfqmo/Duvme7uz3SIedL2b6ycgCztQMiTfr3aQh2DDyLHl+QUPClKMNpSg3gDJFvNQYIcq1g==", + "dev": true, + "requires": { + "typanion": "^3.8.0" + } + }, "cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -17435,6 +23070,12 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, "columnify": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.6.0.tgz", @@ -17454,6 +23095,13 @@ "delayed-stream": "~1.0.0" } }, + "commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "optional": true + }, "commitizen": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/commitizen/-/commitizen-4.2.4.tgz", @@ -17727,23 +23375,64 @@ "dot-prop": "^5.1.0" } }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + } + } + }, + "computeds": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz", + "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==", + "dev": true + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, - "concat-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", - "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.0.2", - "typedarray": "^0.0.6" - } + "confbox": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", + "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==", + "dev": true }, "confusing-browser-globals": { "version": "1.0.11", @@ -17751,23 +23440,66 @@ "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", "dev": true }, - "conventional-changelog": { - "version": "3.1.25", - "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-3.1.25.tgz", - "integrity": "sha512-ryhi3fd1mKf3fSjbLXOfK2D06YwKNic1nC9mWqybBHdObPd8KJ2vjaXZfYj1U23t+V8T8n0d7gwnc9XbIdFbyQ==", + "content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dev": true, "requires": { - "conventional-changelog-angular": "^5.0.12", - "conventional-changelog-atom": "^2.0.8", - "conventional-changelog-codemirror": "^2.0.8", - "conventional-changelog-conventionalcommits": "^4.5.0", - "conventional-changelog-core": "^4.2.1", - "conventional-changelog-ember": "^2.0.9", - "conventional-changelog-eslint": "^3.0.9", - "conventional-changelog-express": "^2.0.6", - "conventional-changelog-jquery": "^3.0.11", - "conventional-changelog-jshint": "^2.0.9", - "conventional-changelog-preset-loader": "^2.3.4" + "safe-buffer": "5.2.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true + }, + "conventional-changelog": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-5.1.0.tgz", + "integrity": "sha512-aWyE/P39wGYRPllcCEZDxTVEmhyLzTc9XA6z6rVfkuCD2UBnhV/sgSOKbQrEG5z9mEZJjnopjgQooTKxEg8mAg==", + "dev": true, + "requires": { + "conventional-changelog-angular": "^7.0.0", + "conventional-changelog-atom": "^4.0.0", + "conventional-changelog-codemirror": "^4.0.0", + "conventional-changelog-conventionalcommits": "^7.0.2", + "conventional-changelog-core": "^7.0.0", + "conventional-changelog-ember": "^4.0.0", + "conventional-changelog-eslint": "^5.0.0", + "conventional-changelog-express": "^4.0.0", + "conventional-changelog-jquery": "^5.0.0", + "conventional-changelog-jshint": "^4.0.0", + "conventional-changelog-preset-loader": "^4.1.0" + }, + "dependencies": { + "conventional-changelog-angular": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", + "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==", + "dev": true, + "requires": { + "compare-func": "^2.0.0" + } + }, + "conventional-changelog-conventionalcommits": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-7.0.2.tgz", + "integrity": "sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==", + "dev": true, + "requires": { + "compare-func": "^2.0.0" + } + } } }, "conventional-changelog-angular": { @@ -17781,27 +23513,15 @@ } }, "conventional-changelog-atom": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-2.0.8.tgz", - "integrity": "sha512-xo6v46icsFTK3bb7dY/8m2qvc8sZemRgdqLb/bjpBsH2UyOS8rKNTgcb5025Hri6IpANPApbXMg15QLb1LJpBw==", - "dev": true, - "requires": { - "q": "^1.5.1" - } + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-4.0.0.tgz", + "integrity": "sha512-q2YtiN7rnT1TGwPTwjjBSIPIzDJCRE+XAUahWxnh+buKK99Kks4WLMHoexw38GXx9OUxAsrp44f9qXe5VEMYhw==", + "dev": true }, "conventional-changelog-codemirror": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-2.0.8.tgz", - "integrity": "sha512-z5DAsn3uj1Vfp7po3gpt2Boc+Bdwmw2++ZHa5Ak9k0UKsYAO5mH1UBTN0qSCuJZREIhX6WU4E1p3IW2oRCNzQw==", - "dev": true, - "requires": { - "q": "^1.5.1" - } - }, - "conventional-changelog-config-spec": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-config-spec/-/conventional-changelog-config-spec-2.1.0.tgz", - "integrity": "sha512-IpVePh16EbbB02V+UA+HQnnPIohgXvJRxHcS5+Uwk4AT5LjzCZJm5sp/yqs5C6KZJ1jMsV4paEV13BN1pvDuxQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-4.0.0.tgz", + "integrity": "sha512-hQSojc/5imn1GJK3A75m9hEZZhc3urojA5gMpnar4JHmgLnuM3CUIARPpEk86glEKr3c54Po3WV/vCaO/U8g3Q==", "dev": true }, "conventional-changelog-conventionalcommits": { @@ -17816,100 +23536,182 @@ } }, "conventional-changelog-core": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz", - "integrity": "sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-7.0.0.tgz", + "integrity": "sha512-UYgaB1F/COt7VFjlYKVE/9tTzfU3VUq47r6iWf6lM5T7TlOxr0thI63ojQueRLIpVbrtHK4Ffw+yQGduw2Bhdg==", "dev": true, "requires": { + "@hutson/parse-repository-url": "^5.0.0", "add-stream": "^1.0.0", - "conventional-changelog-writer": "^5.0.0", - "conventional-commits-parser": "^3.2.0", - "dateformat": "^3.0.0", - "get-pkg-repo": "^4.0.0", - "git-raw-commits": "^2.0.8", - "git-remote-origin-url": "^2.0.0", - "git-semver-tags": "^4.1.1", - "lodash": "^4.17.15", - "normalize-package-data": "^3.0.0", - "q": "^1.5.1", - "read-pkg": "^3.0.0", - "read-pkg-up": "^3.0.0", - "through2": "^4.0.0" + "conventional-changelog-writer": "^7.0.0", + "conventional-commits-parser": "^5.0.0", + "git-raw-commits": "^4.0.0", + "git-semver-tags": "^7.0.0", + "hosted-git-info": "^7.0.0", + "normalize-package-data": "^6.0.0", + "read-pkg": "^8.0.0", + "read-pkg-up": "^10.0.0" + }, + "dependencies": { + "conventional-commits-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", + "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", + "dev": true, + "requires": { + "is-text-path": "^2.0.0", + "JSONStream": "^1.3.5", + "meow": "^12.0.1", + "split2": "^4.0.0" + } + }, + "dargs": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-8.1.0.tgz", + "integrity": "sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==", + "dev": true + }, + "git-raw-commits": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-4.0.0.tgz", + "integrity": "sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==", + "dev": true, + "requires": { + "dargs": "^8.0.0", + "meow": "^12.0.1", + "split2": "^4.0.0" + } + }, + "hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "dev": true, + "requires": { + "lru-cache": "^10.0.1" + } + }, + "is-text-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", + "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", + "dev": true, + "requires": { + "text-extensions": "^2.0.0" + } + }, + "lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "meow": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", + "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", + "dev": true + }, + "normalize-package-data": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", + "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", + "dev": true, + "requires": { + "hosted-git-info": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + } + }, + "semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true + }, + "split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dev": true + }, + "text-extensions": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", + "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==", + "dev": true + } } }, "conventional-changelog-ember": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-2.0.9.tgz", - "integrity": "sha512-ulzIReoZEvZCBDhcNYfDIsLTHzYHc7awh+eI44ZtV5cx6LVxLlVtEmcO+2/kGIHGtw+qVabJYjdI5cJOQgXh1A==", - "dev": true, - "requires": { - "q": "^1.5.1" - } + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-4.0.0.tgz", + "integrity": "sha512-D0IMhwcJUg1Y8FSry6XAplEJcljkHVlvAZddhhsdbL1rbsqRsMfGx/PIkPYq0ru5aDgn+OxhQ5N5yR7P9mfsvA==", + "dev": true }, "conventional-changelog-eslint": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.9.tgz", - "integrity": "sha512-6NpUCMgU8qmWmyAMSZO5NrRd7rTgErjrm4VASam2u5jrZS0n38V7Y9CzTtLT2qwz5xEChDR4BduoWIr8TfwvXA==", - "dev": true, - "requires": { - "q": "^1.5.1" - } + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-5.0.0.tgz", + "integrity": "sha512-6JtLWqAQIeJLn/OzUlYmzd9fKeNSWmQVim9kql+v4GrZwLx807kAJl3IJVc3jTYfVKWLxhC3BGUxYiuVEcVjgA==", + "dev": true }, "conventional-changelog-express": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-2.0.6.tgz", - "integrity": "sha512-SDez2f3iVJw6V563O3pRtNwXtQaSmEfTCaTBPCqn0oG0mfkq0rX4hHBq5P7De2MncoRixrALj3u3oQsNK+Q0pQ==", - "dev": true, - "requires": { - "q": "^1.5.1" - } + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-4.0.0.tgz", + "integrity": "sha512-yWyy5c7raP9v7aTvPAWzqrztACNO9+FEI1FSYh7UP7YT1AkWgv5UspUeB5v3Ibv4/o60zj2o9GF2tqKQ99lIsw==", + "dev": true }, "conventional-changelog-jquery": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-3.0.11.tgz", - "integrity": "sha512-x8AWz5/Td55F7+o/9LQ6cQIPwrCjfJQ5Zmfqi8thwUEKHstEn4kTIofXub7plf1xvFA2TqhZlq7fy5OmV6BOMw==", - "dev": true, - "requires": { - "q": "^1.5.1" - } + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-5.0.0.tgz", + "integrity": "sha512-slLjlXLRNa/icMI3+uGLQbtrgEny3RgITeCxevJB+p05ExiTgHACP5p3XiMKzjBn80n+Rzr83XMYfRInEtCPPw==", + "dev": true }, "conventional-changelog-jshint": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-2.0.9.tgz", - "integrity": "sha512-wMLdaIzq6TNnMHMy31hql02OEQ8nCQfExw1SE0hYL5KvU+JCTuPaDO+7JiogGT2gJAxiUGATdtYYfh+nT+6riA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-4.0.0.tgz", + "integrity": "sha512-LyXq1bbl0yG0Ai1SbLxIk8ZxUOe3AjnlwE6sVRQmMgetBk+4gY9EO3d00zlEt8Y8gwsITytDnPORl8al7InTjg==", "dev": true, "requires": { - "compare-func": "^2.0.0", - "q": "^1.5.1" + "compare-func": "^2.0.0" } }, "conventional-changelog-preset-loader": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz", - "integrity": "sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-4.1.0.tgz", + "integrity": "sha512-HozQjJicZTuRhCRTq4rZbefaiCzRM2pr6u2NL3XhrmQm4RMnDXfESU6JKu/pnKwx5xtdkYfNCsbhN5exhiKGJA==", "dev": true }, "conventional-changelog-writer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz", - "integrity": "sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-7.0.1.tgz", + "integrity": "sha512-Uo+R9neH3r/foIvQ0MKcsXkX642hdm9odUp7TqgFS7BsalTcjzRlIfWZrZR1gbxOozKucaKt5KAbjW8J8xRSmA==", "dev": true, "requires": { - "conventional-commits-filter": "^2.0.7", - "dateformat": "^3.0.0", + "conventional-commits-filter": "^4.0.0", "handlebars": "^4.7.7", "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "semver": "^6.0.0", - "split": "^1.0.0", - "through2": "^4.0.0" + "meow": "^12.0.1", + "semver": "^7.5.2", + "split2": "^4.0.0" }, "dependencies": { + "meow": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", + "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", + "dev": true + }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true + }, + "split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", "dev": true } } @@ -17921,14 +23723,10 @@ "dev": true }, "conventional-commits-filter": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz", - "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==", - "dev": true, - "requires": { - "lodash.ismatch": "^4.4.0", - "modify-values": "^1.0.0" - } + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-4.0.0.tgz", + "integrity": "sha512-rnpnibcSOdFcdclpFwWa+pPlZJhXE7l+XK04zxhbWrhgpR96h33QLz8hITTXbcYICxVr3HZFtbtUAQ+4LdBo9A==", + "dev": true }, "conventional-commits-parser": { "version": "3.2.3", @@ -17945,19 +23743,75 @@ } }, "conventional-recommended-bump": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-6.1.0.tgz", - "integrity": "sha512-uiApbSiNGM/kkdL9GTOLAqC4hbptObFo4wW2QRyHsKciGAfQuLU1ShZ1BIVI/+K2BE/W1AWYQMCXAsv4dyKPaw==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-9.0.0.tgz", + "integrity": "sha512-HR1yD0G5HgYAu6K0wJjLd7QGRK8MQDqqj6Tn1n/ja1dFwBCE6QmV+iSgQ5F7hkx7OUR/8bHpxJqYtXj2f/opPQ==", "dev": true, "requires": { - "concat-stream": "^2.0.0", - "conventional-changelog-preset-loader": "^2.3.4", - "conventional-commits-filter": "^2.0.7", - "conventional-commits-parser": "^3.2.0", - "git-raw-commits": "^2.0.8", - "git-semver-tags": "^4.1.1", - "meow": "^8.0.0", - "q": "^1.5.1" + "conventional-changelog-preset-loader": "^4.1.0", + "conventional-commits-filter": "^4.0.0", + "conventional-commits-parser": "^5.0.0", + "git-raw-commits": "^4.0.0", + "git-semver-tags": "^7.0.0", + "meow": "^12.0.1" + }, + "dependencies": { + "conventional-commits-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", + "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", + "dev": true, + "requires": { + "is-text-path": "^2.0.0", + "JSONStream": "^1.3.5", + "meow": "^12.0.1", + "split2": "^4.0.0" + } + }, + "dargs": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-8.1.0.tgz", + "integrity": "sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==", + "dev": true + }, + "git-raw-commits": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-4.0.0.tgz", + "integrity": "sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==", + "dev": true, + "requires": { + "dargs": "^8.0.0", + "meow": "^12.0.1", + "split2": "^4.0.0" + } + }, + "is-text-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", + "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", + "dev": true, + "requires": { + "text-extensions": "^2.0.0" + } + }, + "meow": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", + "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", + "dev": true + }, + "split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dev": true + }, + "text-extensions": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", + "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==", + "dev": true + } } }, "convert-source-map": { @@ -17966,6 +23820,24 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, + "cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, + "core-js": { + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.37.1.tgz", + "integrity": "sha512-Xn6qmxrQZyB0FFY8E3bgRXei3lWDJHhvI+u0q9TKIYM49G8pAr0FgnnrFRAmsbptZL1yxRADVXn+x5AGsbBfyw==", + "dev": true + }, "core-js-compat": { "version": "3.38.1", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", @@ -17981,6 +23853,22 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, + "corser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", + "integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==", + "dev": true + }, "cosmiconfig": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", @@ -18027,51 +23915,6 @@ "jest-config": "^29.7.0", "jest-util": "^29.7.0", "prompts": "^2.0.1" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - } } }, "create-require": { @@ -18170,10 +24013,25 @@ "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", "dev": true }, - "dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "dev": true + }, + "de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", "dev": true }, "debug": { @@ -18215,6 +24073,15 @@ "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", "dev": true }, + "deep-eql": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } + }, "deep-freeze-strict": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/deep-freeze-strict/-/deep-freeze-strict-1.1.1.tgz", @@ -18241,6 +24108,17 @@ "clone": "^1.0.2" } }, + "define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + } + }, "define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -18253,6 +24131,18 @@ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true + }, + "destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true + }, "detect-file": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", @@ -18343,56 +24233,73 @@ "dotenv": "^16.4.4" } }, - "dotgitignore": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/dotgitignore/-/dotgitignore-2.1.0.tgz", - "integrity": "sha512-sCm11ak2oY6DglEPpCB8TixLjWAxd3kJTs6UIcSasNYxXdFPV+YKlye92c8H4kKFqV5qYMIh7d+cYecEg0dIkA==", - "dev": true, - "requires": { - "find-up": "^3.0.0", - "minimatch": "^3.0.4" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "p-limit": "^2.0.0" + "safe-buffer": "~5.1.0" } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true } } }, - "duplexer": { + "ecc-jsbn": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "dev": true }, "ejs": { @@ -18422,6 +24329,12 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true + }, "end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -18440,6 +24353,18 @@ "ansi-colors": "^4.1.1" } }, + "entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true + }, + "envinfo": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", + "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", + "dev": true + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -18449,12 +24374,64 @@ "is-arrayish": "^0.2.1" } }, + "es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "requires": { + "get-intrinsic": "^1.2.4" + } + }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true + }, + "esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "requires": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, "escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -18598,7 +24575,8 @@ "version": "9.1.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", - "dev": true + "dev": true, + "requires": {} }, "eslint-scope": { "version": "7.2.2", @@ -18657,12 +24635,45 @@ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true }, + "estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "requires": { + "@types/estree": "^1.0.0" + } + }, "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true + }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true + }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true + }, "execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -18706,53 +24717,82 @@ "jest-matcher-utils": "^29.7.0", "jest-message-util": "^29.7.0", "jest-util": "^29.7.0" + } + }, + "express": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", + "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", + "dev": true, + "requires": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.10", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" }, "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "ms": "2.0.0" } }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true } } }, + "express-rate-limit": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.5.1.tgz", + "integrity": "sha512-MTjE2eIbHv5DyfuFz4zLYWxpqVhEhkTiwFGuB74Q9CSou2WHO52nlE5y3Zlg6SIsiYUIPj6ifFxnkPz6O3sIUg==", + "dev": true + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, "external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -18775,12 +24815,24 @@ } } }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "dev": true + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "dev": true + }, "fast-glob": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", @@ -18805,6 +24857,24 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "fast-redact": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", + "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", + "dev": true + }, + "fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true + }, + "fast-uri": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", + "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", + "dev": true + }, "fastq": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", @@ -18823,6 +24893,12 @@ "bser": "2.1.1" } }, + "fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "dev": true + }, "figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -18887,6 +24963,38 @@ "to-regex-range": "^5.0.1" } }, + "finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + } + } + }, "find-node-modules": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/find-node-modules/-/find-node-modules-2.1.2.tgz", @@ -18954,6 +25062,12 @@ "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "dev": true }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "dev": true + }, "form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -18965,6 +25079,18 @@ "mime-types": "^2.1.12" } }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true + }, "front-matter": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/front-matter/-/front-matter-4.0.2.tgz", @@ -18998,16 +25124,16 @@ "dev": true }, "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "optional": true }, "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true }, "gensync": { @@ -19022,87 +25148,46 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, - "get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", "dev": true }, - "get-pkg-repo": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", - "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==", + "get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "requires": { - "@hutson/parse-repository-url": "^3.0.0", - "hosted-git-info": "^4.0.0", - "through2": "^2.0.0", - "yargs": "^16.2.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "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" - } - }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true - } + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" } }, + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true + }, "get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, "git-raw-commits": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.10.tgz", @@ -19116,43 +25201,30 @@ "through2": "^4.0.0" } }, - "git-remote-origin-url": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", - "integrity": "sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw==", - "dev": true, - "requires": { - "gitconfiglocal": "^1.0.0", - "pify": "^2.3.0" - } - }, "git-semver-tags": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-4.1.1.tgz", - "integrity": "sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-7.0.1.tgz", + "integrity": "sha512-NY0ZHjJzyyNXHTDZmj+GG7PyuAKtMsyWSwh07CR2hOZFa+/yoTsXci/nF2obzL8UDhakFNkD9gNdt/Ed+cxh2Q==", "dev": true, "requires": { - "meow": "^8.0.0", - "semver": "^6.0.0" + "meow": "^12.0.1", + "semver": "^7.5.2" }, "dependencies": { + "meow": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", + "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", + "dev": true + }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true } } }, - "gitconfiglocal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", - "integrity": "sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ==", - "dev": true, - "requires": { - "ini": "^1.3.2" - } - }, "glob": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", @@ -19255,6 +25327,15 @@ } } }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.3" + } + }, "graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", @@ -19267,14 +25348,64 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, + "gunzip-maybe": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/gunzip-maybe/-/gunzip-maybe-1.4.2.tgz", + "integrity": "sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==", + "dev": true, + "requires": { + "browserify-zlib": "^0.1.4", + "is-deflate": "^1.0.0", + "is-gzip": "^1.0.0", + "peek-stream": "^1.1.0", + "pumpify": "^1.3.3", + "through2": "^2.0.3" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, "handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "dev": true, "requires": { "minimist": "^1.2.5", - "neo-async": "^2.6.0", + "neo-async": "^2.6.2", "source-map": "^0.6.1", "uglify-js": "^3.1.4", "wordwrap": "^1.0.0" @@ -19292,19 +25423,46 @@ "integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==", "dev": true }, - "has": { + "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 + }, + "has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "requires": { + "es-define-property": "^1.0.0" + } + }, + "has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true + }, + "has-symbols": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true + }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, "requires": { - "function-bind": "^1.1.1" + "function-bind": "^1.1.2" } }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, "homedir-polyfill": { @@ -19325,12 +25483,111 @@ "lru-cache": "^6.0.0" } }, + "html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dev": true, + "requires": { + "whatwg-encoding": "^2.0.0" + } + }, "html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-server": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz", + "integrity": "sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==", + "dev": true, + "requires": { + "basic-auth": "^2.0.1", + "chalk": "^4.1.2", + "corser": "^2.0.1", + "he": "^1.2.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy": "^1.18.1", + "mime": "^1.6.0", + "minimist": "^1.2.6", + "opener": "^1.5.1", + "portfinder": "^1.0.28", + "secure-compare": "3.0.1", + "union": "~0.5.0", + "url-join": "^4.0.1" + }, + "dependencies": { + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true + } + } + }, + "http-signature": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", + "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^2.0.2", + "sshpk": "^1.14.1" + } + }, + "http-status-codes": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-2.3.0.tgz", + "integrity": "sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==", + "dev": true + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -19396,6 +25653,12 @@ } } }, + "import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "dev": true + }, "import-local": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", @@ -19441,9 +25704,9 @@ "dev": true }, "inquirer": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz", - "integrity": "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==", + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", + "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", "dev": true, "requires": { "ansi-escapes": "^4.2.1", @@ -19460,7 +25723,7 @@ "string-width": "^4.1.0", "strip-ansi": "^6.0.0", "through": "^2.3.6", - "wrap-ansi": "^7.0.0" + "wrap-ansi": "^6.0.1" }, "dependencies": { "chalk": { @@ -19474,16 +25737,33 @@ } }, "rxjs": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz", - "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==", + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", "dev": true, "requires": { "tslib": "^2.1.0" } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } } } }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -19500,14 +25780,20 @@ } }, "is-core-module": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", - "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", "dev": true, "requires": { - "has": "^1.0.3" + "hasown": "^2.0.2" } }, + "is-deflate": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-deflate/-/is-deflate-1.0.0.tgz", + "integrity": "sha512-YDoFpuZWu1VRXlsnlYMzKyVRITXj7Ej/V9gXQ2/pAe7X1J7M/RNOqaIYi6qUn+B7nGyB9pDXrv02dsB58d2ZAQ==", + "dev": true + }, "is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", @@ -19541,6 +25827,12 @@ "is-extglob": "^2.1.1" } }, + "is-gzip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", + "integrity": "sha512-rcfALRIb1YewtnksfRIHGcIY93QnK8BIQ/2c9yDYcG/Y6+vRoJuTWBmmSEbyLLYtXm7q35pHOHbZFQBaLrhlWQ==", + "dev": true + }, "is-interactive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", @@ -19571,6 +25863,12 @@ "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", "dev": true }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true + }, "is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -19586,6 +25884,12 @@ "text-extensions": "^1.0.0" } }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true + }, "is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -19625,6 +25929,12 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true + }, "istanbul-lib-coverage": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", @@ -19717,37 +26027,6 @@ "@jest/types": "^29.6.3", "import-local": "^3.0.2", "jest-cli": "^29.7.0" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - } } }, "jest-changed-files": { @@ -19761,49 +26040,6 @@ "p-limit": "^3.1.0" }, "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -19843,54 +26079,25 @@ "stack-utils": "^2.0.3" }, "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", "dev": true, + "optional": true, + "peer": true, "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" } }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, "dedent": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } + "requires": {} }, "p-limit": { "version": "3.1.0", @@ -19920,51 +26127,6 @@ "jest-util": "^29.7.0", "jest-validate": "^29.7.0", "yargs": "^17.3.1" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - } } }, "jest-config": { @@ -19997,49 +26159,6 @@ "strip-json-comments": "^3.1.1" }, "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, "parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -20086,51 +26205,6 @@ "jest-get-type": "^29.6.3", "jest-util": "^29.7.0", "pretty-format": "^29.7.0" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - } } }, "jest-environment-node": { @@ -20145,51 +26219,6 @@ "@types/node": "*", "jest-mock": "^29.7.0", "jest-util": "^29.7.0" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - } } }, "jest-get-type": { @@ -20216,51 +26245,6 @@ "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "walker": "^1.0.8" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - } } }, "jest-leak-detector": { @@ -20300,37 +26284,6 @@ "pretty-format": "^29.7.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - } } }, "jest-mock": { @@ -20340,60 +26293,16 @@ "dev": true, "requires": { "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - } + "@types/node": "*", + "jest-util": "^29.7.0" } }, "jest-pnp-resolver": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true + "dev": true, + "requires": {} }, "jest-regex-util": { "version": "29.6.3", @@ -20418,49 +26327,6 @@ "slash": "^3.0.0" }, "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, "resolve.exports": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", @@ -20508,49 +26374,6 @@ "source-map-support": "0.5.13" }, "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -20600,51 +26423,6 @@ "jest-util": "^29.7.0", "slash": "^3.0.0", "strip-bom": "^4.0.0" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - } } }, "jest-snapshot": { @@ -20675,49 +26453,6 @@ "semver": "^7.5.3" }, "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, "semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -20727,12 +26462,12 @@ } }, "jest-util": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.1.tgz", - "integrity": "sha512-FktOu7ca1DZSyhPAxgxB6hfh2+9zMoJ7aEQA759Z6p45NuO8mWcqujH+UdHlCm/V6JTWwDztM2ITCzU1ijJAfw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, "requires": { - "@jest/types": "^28.1.1", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -20754,35 +26489,6 @@ "pretty-format": "^29.7.0" }, "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, "camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", @@ -20805,51 +26511,6 @@ "emittery": "^0.13.1", "jest-util": "^29.7.0", "string-length": "^4.0.1" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - } } }, "jest-worker": { @@ -20864,49 +26525,6 @@ "supports-color": "^8.0.0" }, "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, "supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -20918,6 +26536,12 @@ } } }, + "jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", + "dev": true + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -20934,6 +26558,12 @@ "esprima": "^4.0.0" } }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true + }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -20946,18 +26576,18 @@ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, "json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, + "json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -21034,11 +26664,70 @@ "through": ">=2.2.7 <3" } }, + "jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dev": true, + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "dependencies": { + "semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true + } + } + }, + "jsprim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", + "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, "just-extend": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.1.1.tgz", "integrity": "sha512-1UWaMWIB90HnIZAmXOTLobwWc9lc1ZMUBRKf8PaozCAiNUif6wv1fyeXpqccWZCu7L9zxIgXG55vARuZluyvqw==" }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dev": true, + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dev": true, + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -21060,6 +26749,12 @@ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true }, + "kolorist": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", + "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", + "dev": true + }, "leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -21082,30 +26777,14 @@ "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", "dev": true }, - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "local-pkg": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", + "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true - } + "mlly": "^1.4.2", + "pkg-types": "^1.0.3" } }, "locate-path": { @@ -21117,6 +26796,15 @@ "p-locate": "^4.1.0" } }, + "lockfile": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lockfile/-/lockfile-1.0.4.tgz", + "integrity": "sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==", + "dev": true, + "requires": { + "signal-exit": "^3.0.2" + } + }, "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -21135,10 +26823,46 @@ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", "dev": true }, - "lodash.ismatch": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", - "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==", + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "dev": true + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "dev": true + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "dev": true + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "dev": true + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "dev": true + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", "dev": true }, "lodash.map": { @@ -21159,6 +26883,12 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "dev": true + }, "log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -21175,6 +26905,36 @@ "integrity": "sha1-eB4YMpaqlPbU2RbcM10NF676I/g=", "dev": true }, + "loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "requires": { + "get-func-name": "^2.0.1" + } + }, + "lowdb": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowdb/-/lowdb-1.0.0.tgz", + "integrity": "sha512-2+x8esE/Wb9SQ1F9IHaYWfsC9FIecLOPrK4g17FGEayjUWH172H6nwicRovGvSE2CPZouc2MCIqCI7h9d+GftQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.3", + "is-promise": "^2.1.0", + "lodash": "4", + "pify": "^3.0.0", + "steno": "^0.4.1" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true + } + } + }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -21184,6 +26944,26 @@ "yallist": "^4.0.0" } }, + "magic-string": { + "version": "0.30.11", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", + "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", + "dev": true, + "requires": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "magicast": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", + "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", + "dev": true, + "requires": { + "@babel/parser": "^7.25.4", + "@babel/types": "^7.25.4", + "source-map-js": "^1.2.0" + } + }, "make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -21222,6 +27002,12 @@ "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", "dev": true }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true + }, "meow": { "version": "8.1.2", "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", @@ -21336,6 +27122,12 @@ "integrity": "sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==", "dev": true }, + "merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true + }, "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -21348,6 +27140,12 @@ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true + }, "micromatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", @@ -21358,6 +27156,12 @@ "picomatch": "^2.2.3" } }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -21411,10 +27215,39 @@ "kind-of": "^6.0.3" } }, - "modify-values": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", - "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + }, + "dependencies": { + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true + } + } + }, + "mlly": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.1.tgz", + "integrity": "sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==", + "dev": true, + "requires": { + "acorn": "^8.11.3", + "pathe": "^1.1.2", + "pkg-types": "^1.1.1", + "ufo": "^1.5.3" + } + }, + "mrmime": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", + "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", "dev": true }, "ms": { @@ -21423,18 +27256,77 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, + "muggle-string": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.3.1.tgz", + "integrity": "sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==", + "dev": true + }, "mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "mv": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", + "integrity": "sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg==", + "dev": true, + "requires": { + "mkdirp": "~0.5.1", + "ncp": "~2.0.0", + "rimraf": "~2.4.0" + }, + "dependencies": { + "glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "rimraf": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", + "integrity": "sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ==", + "dev": true, + "requires": { + "glob": "^6.0.1" + } + } + } + }, + "nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "ncp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", + "integrity": "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==", + "dev": true + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true + }, "neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -21447,6 +27339,15 @@ "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", "dev": true }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } + }, "node-gyp-build": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz", @@ -21586,21 +27487,6 @@ "yargs-parser": "21.1.1" }, "dependencies": { - "@zkochan/js-yaml": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.7.tgz", - "integrity": "sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, "brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -21677,6 +27563,39 @@ } } }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true + }, + "object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "dev": true + }, + "on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "dev": true + }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -21706,6 +27625,12 @@ "is-wsl": "^2.2.0" } }, + "opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "dev": true + }, "optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -21767,6 +27692,12 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", + "dev": true + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -21777,13 +27708,36 @@ } }, "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-7.1.1.tgz", + "integrity": "sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==", "dev": true, "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" + "@babel/code-frame": "^7.21.4", + "error-ex": "^1.3.2", + "json-parse-even-better-errors": "^3.0.0", + "lines-and-columns": "^2.0.3", + "type-fest": "^3.8.0" + }, + "dependencies": { + "json-parse-even-better-errors": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", + "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", + "dev": true + }, + "lines-and-columns": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", + "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", + "dev": true + }, + "type-fest": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "dev": true + } } }, "parse-passwd": { @@ -21792,6 +27746,18 @@ "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "dev": true }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, + "path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -21816,23 +27782,77 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "path-to-regexp": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "dev": true + }, + "pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true + }, + "pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true + }, + "peek-stream": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/peek-stream/-/peek-stream-1.1.3.tgz", + "integrity": "sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==", "dev": true, "requires": { - "pify": "^3.0.0" + "buffer-from": "^1.0.0", + "duplexify": "^3.5.0", + "through2": "^2.0.3" }, "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } } } }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "dev": true + }, "picocolors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", @@ -21840,15 +27860,83 @@ "dev": true }, "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "pino": { + "version": "8.17.2", + "resolved": "https://registry.npmjs.org/pino/-/pino-8.17.2.tgz", + "integrity": "sha512-LA6qKgeDMLr2ux2y/YiUt47EfgQ+S9LznBWOJdN3q1dx2sv0ziDLUBeVpyVv17TEcGCBuWf0zNtg3M5m1NhhWQ==", + "dev": true, + "requires": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "v1.1.0", + "pino-std-serializers": "^6.0.0", + "process-warning": "^3.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^3.7.0", + "thread-stream": "^2.0.0" + }, + "dependencies": { + "process-warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", + "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==", + "dev": true + } + } + }, + "pino-abstract-transport": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz", + "integrity": "sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==", + "dev": true, + "requires": { + "readable-stream": "^4.0.0", + "split2": "^4.0.0" + }, + "dependencies": { + "buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dev": true, + "requires": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + } + }, + "split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dev": true + } + } + }, + "pino-std-serializers": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", + "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==", "dev": true }, "pirates": { @@ -21866,6 +27954,65 @@ "find-up": "^4.0.0" } }, + "pkg-types": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.2.0.tgz", + "integrity": "sha512-+ifYuSSqOQ8CqP4MbZA5hDpb97n3E8SVWdJe+Wms9kj745lmd3b7EZJiqvmLwAlmRfjrI7Hi5z3kdBJ93lFNPA==", + "dev": true, + "requires": { + "confbox": "^0.1.7", + "mlly": "^1.7.1", + "pathe": "^1.1.2" + } + }, + "pkginfo": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.4.1.tgz", + "integrity": "sha512-8xCNE/aT/EXKenuMDZ+xTVwkT8gsoHN2z/Q29l80u0ppGEXVvsKRzNMbtKhg8LS8k1tJLAHHylf6p4VFmP6XUQ==", + "dev": true + }, + "portfinder": { + "version": "1.0.32", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", + "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", + "dev": true, + "requires": { + "async": "^2.6.4", + "debug": "^3.2.7", + "mkdirp": "^0.5.6" + }, + "dependencies": { + "async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "postcss": { + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "dev": true, + "requires": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" + } + }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -21889,21 +28036,6 @@ "react-is": "^18.0.0" }, "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, "ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", @@ -21918,12 +28050,24 @@ "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", "dev": true }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "process-warning": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz", + "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==", + "dev": true + }, "prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -21934,12 +28078,49 @@ "sisteransi": "^1.0.5" } }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + } + }, "proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, + "psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, "punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -21958,18 +28139,71 @@ "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", "dev": true }, + "qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, + "requires": { + "side-channel": "^1.0.6" + } + }, + "querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true }, + "queue-tick": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", + "dev": true + }, + "quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "dev": true + }, "quick-lru": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", "dev": true }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "requires": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true + } + } + }, "react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -21977,99 +28211,121 @@ "dev": true }, "read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-8.1.0.tgz", + "integrity": "sha512-PORM8AgzXeskHO/WEv312k9U03B8K9JSiWF/8N9sUuFjBa+9SF2u6K7VClzXwDXab51jCd8Nd36CNM+zR97ScQ==", "dev": true, "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" + "@types/normalize-package-data": "^2.4.1", + "normalize-package-data": "^6.0.0", + "parse-json": "^7.0.0", + "type-fest": "^4.2.0" }, "dependencies": { "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "dev": true, + "requires": { + "lru-cache": "^10.0.1" + } + }, + "lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true }, "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", + "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", "dev": true, "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "hosted-git-info": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" } }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true + }, + "type-fest": { + "version": "4.26.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz", + "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==", "dev": true } } }, "read-pkg-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", - "integrity": "sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-10.1.0.tgz", + "integrity": "sha512-aNtBq4jR8NawpKJQldrQcSW9y/d+KWH4v24HWkHljOZ7H0av+YTGANBzRh9A5pw7v/bLVsLVPpOhJ7gHNVy8lA==", "dev": true, "requires": { - "find-up": "^2.0.0", - "read-pkg": "^3.0.0" + "find-up": "^6.3.0", + "read-pkg": "^8.1.0", + "type-fest": "^4.2.0" }, "dependencies": { "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", "dev": true, "requires": { - "locate-path": "^2.0.0" + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" } }, "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", "dev": true, "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" + "p-locate": "^6.0.0" } }, "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", "dev": true, "requires": { - "p-try": "^1.0.0" + "yocto-queue": "^1.0.0" } }, "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", "dev": true, "requires": { - "p-limit": "^1.1.0" + "p-limit": "^4.0.0" } }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", + "path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", "dev": true }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "type-fest": { + "version": "4.26.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz", + "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==", + "dev": true + }, + "yocto-queue": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", + "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", "dev": true } } @@ -22094,6 +28350,12 @@ "picomatch": "^2.2.1" } }, + "real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "dev": true + }, "redent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", @@ -22177,14 +28439,27 @@ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" } }, "resolve-cwd": { @@ -22252,6 +28527,40 @@ "glob": "^7.1.3" } }, + "rollup": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.4.tgz", + "integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==", + "dev": true, + "requires": { + "@rollup/rollup-android-arm-eabi": "4.22.4", + "@rollup/rollup-android-arm64": "4.22.4", + "@rollup/rollup-darwin-arm64": "4.22.4", + "@rollup/rollup-darwin-x64": "4.22.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.22.4", + "@rollup/rollup-linux-arm-musleabihf": "4.22.4", + "@rollup/rollup-linux-arm64-gnu": "4.22.4", + "@rollup/rollup-linux-arm64-musl": "4.22.4", + "@rollup/rollup-linux-powerpc64le-gnu": "4.22.4", + "@rollup/rollup-linux-riscv64-gnu": "4.22.4", + "@rollup/rollup-linux-s390x-gnu": "4.22.4", + "@rollup/rollup-linux-x64-gnu": "4.22.4", + "@rollup/rollup-linux-x64-musl": "4.22.4", + "@rollup/rollup-win32-arm64-msvc": "4.22.4", + "@rollup/rollup-win32-ia32-msvc": "4.22.4", + "@rollup/rollup-win32-x64-msvc": "4.22.4", + "@types/estree": "1.0.5", + "fsevents": "~2.3.2" + }, + "dependencies": { + "@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + } + } + }, "run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", @@ -22290,12 +28599,24 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, + "safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "dev": true + }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, + "secure-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", + "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==", + "dev": true + }, "semver": { "version": "7.3.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", @@ -22305,6 +28626,84 @@ "lru-cache": "^6.0.0" } }, + "send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + } + } + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true + } + } + }, + "serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "dev": true, + "requires": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + } + }, + "set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "requires": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + } + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -22320,12 +28719,41 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + } + }, + "siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true + }, "signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "sirv": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", + "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", + "dev": true, + "requires": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + } + }, "sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -22338,16 +28766,31 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, + "sonic-boom": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.0.tgz", + "integrity": "sha512-ybz6OYOUjoQQCQ/i4LU8kaToD8ACtYP+Cj5qd2AO36bwbdewxWJ3ArmJ2cr6AvxlL2o0PqnCcPGUgkILbfkaCA==", + "dev": true, + "requires": { + "atomic-sleep": "^1.0.0" + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, + "source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true + }, "source-map-support": { - "version": "0.5.20", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", - "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -22386,15 +28829,6 @@ "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", "dev": true }, - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true, - "requires": { - "through": "2" - } - }, "split2": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", @@ -22410,6 +28844,23 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, + "sshpk": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, "stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", @@ -22427,142 +28878,49 @@ } } }, - "standard-version": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/standard-version/-/standard-version-9.5.0.tgz", - "integrity": "sha512-3zWJ/mmZQsOaO+fOlsa0+QK90pwhNd042qEcw6hKFNoLFs7peGyvPffpEBbK/DSGPbyOvli0mUIFv5A4qTjh2Q==", + "stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true + }, + "std-env": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", + "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", + "dev": true + }, + "steno": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/steno/-/steno-0.4.4.tgz", + "integrity": "sha512-EEHMVYHNXFHfGtgjNITnka0aHhiAlo93F7z2/Pwd+g0teG9CnM3JIINM7hVVB5/rhw9voufD7Wukwgtw2uqh6w==", "dev": true, "requires": { - "chalk": "^2.4.2", - "conventional-changelog": "3.1.25", - "conventional-changelog-config-spec": "2.1.0", - "conventional-changelog-conventionalcommits": "4.6.3", - "conventional-recommended-bump": "6.1.0", - "detect-indent": "^6.0.0", - "detect-newline": "^3.1.0", - "dotgitignore": "^2.1.0", - "figures": "^3.1.0", - "find-up": "^5.0.0", - "git-semver-tags": "^4.0.0", - "semver": "^7.1.1", - "stringify-package": "^1.0.1", - "yargs": "^16.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "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, - "requires": { - "has-flag": "^3.0.0" - } - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "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" - } - }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true - } + "graceful-fs": "^4.1.3" + } + }, + "stream-shift": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", + "dev": true + }, + "streamx": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.20.1.tgz", + "integrity": "sha512-uTa0mU6WUC65iUvzKH4X9hEdvSW7rbPxPtwfWiLMSj3qTdQbAiUboZTxauKfpFuGIGa1C2BYijZ7wgdUXICJhA==", + "dev": true, + "requires": { + "bare-events": "^2.2.0", + "fast-fifo": "^1.3.2", + "queue-tick": "^1.0.1", + "text-decoder": "^1.1.0" } }, "string_decoder": { @@ -22582,6 +28940,12 @@ } } }, + "string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true + }, "string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -22603,12 +28967,6 @@ "strip-ansi": "^6.0.1" } }, - "stringify-package": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stringify-package/-/stringify-package-1.0.1.tgz", - "integrity": "sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg==", - "dev": true - }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -22645,6 +29003,23 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, + "strip-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.0.tgz", + "integrity": "sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==", + "dev": true, + "requires": { + "js-tokens": "^9.0.0" + }, + "dependencies": { + "js-tokens": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.0.tgz", + "integrity": "sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==", + "dev": true + } + } + }, "strong-log-transformer": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", @@ -22665,6 +29040,12 @@ "has-flag": "^4.0.0" } }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, "tar-stream": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", @@ -22689,6 +29070,15 @@ "minimatch": "^3.0.4" } }, + "text-decoder": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.0.tgz", + "integrity": "sha512-n1yg1mOj9DNpk3NeZOx7T6jchTbyJS3i3cucbNN6FcdPriMZx7NsgrGpWWdWZZGxD7ES1XB+3uoqHMgOKaN+fg==", + "dev": true, + "requires": { + "b4a": "^1.6.4" + } + }, "text-extensions": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", @@ -22701,6 +29091,15 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "thread-stream": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.7.0.tgz", + "integrity": "sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==", + "dev": true, + "requires": { + "real-require": "^0.2.0" + } + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -22716,6 +29115,24 @@ "readable-stream": "3" } }, + "tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true + }, + "tinypool": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz", + "integrity": "sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==", + "dev": true + }, + "tinyspy": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", + "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", + "dev": true + }, "tmp": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", @@ -22746,6 +29163,44 @@ "is-number": "^7.0.0" } }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true + }, + "totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true + }, + "tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "dev": true, + "requires": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "dependencies": { + "universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true + } + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, "trim-newlines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", @@ -22756,22 +29211,38 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", - "dev": true + "dev": true, + "requires": {} }, "ts-jest": { - "version": "28.0.8", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-28.0.8.tgz", - "integrity": "sha512-5FaG0lXmRPzApix8oFG8RKjAz4ehtm8yMKOTy5HX3fY6W8kmvOrmcY0hKDElW52FJov+clhUbrKAqofnj4mXTg==", + "version": "29.2.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.5.tgz", + "integrity": "sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==", "dev": true, "requires": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^28.0.0", - "json5": "^2.2.1", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "7.x", - "yargs-parser": "^21.0.1" + "bs-logger": "^0.2.6", + "ejs": "^3.1.10", + "fast-json-stable-stringify": "^2.1.0", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.6.3", + "yargs-parser": "^21.1.1" + }, + "dependencies": { + "semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true + }, + "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 + } } }, "ts-node": { @@ -22821,9 +29292,30 @@ } }, "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true + }, + "typanion": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/typanion/-/typanion-3.14.0.tgz", + "integrity": "sha512-ZW/lVMRabETuYCd9O9ZvMhAh8GslSqaUjxmK/JLPCh6l73CvLBiuXswj/+7LdnWOgYsQ130FqLzFz5aGT4I3Ug==", + "dev": true }, "type-check": { "version": "0.4.0", @@ -22846,16 +29338,26 @@ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", - "dev": true + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } }, "typescript": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", - "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "dev": true + }, + "ufo": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", + "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==", "dev": true }, "uglify-js": { @@ -22899,12 +29401,33 @@ "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", "dev": true }, + "union": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", + "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", + "dev": true, + "requires": { + "qs": "^6.4.0" + } + }, "universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "dev": true }, + "unix-crypt-td-js": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/unix-crypt-td-js/-/unix-crypt-td-js-1.1.4.tgz", + "integrity": "sha512-8rMeVYWSIyccIJscb9NdCfZKSRBKYTeVnwmiRYT2ulE3qd1RaDQ0xQDP+rI3ccIWbhu/zuo5cgN8z73belNZgw==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true + }, "update-browserslist-db": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", @@ -22924,12 +29447,40 @@ "punycode": "^2.1.0" } }, + "url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "dev": true + }, + "url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true + }, "v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -22969,6 +29520,352 @@ "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", "dev": true }, + "validator": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", + "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", + "dev": true + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true + }, + "verdaccio": { + "version": "5.32.2", + "resolved": "https://registry.npmjs.org/verdaccio/-/verdaccio-5.32.2.tgz", + "integrity": "sha512-QnVYIUvwB884fwVcA/D+x7AabsRPlTPyYAKMtExm8kJjiH+s2LGK2qX2o3I4VmYXqBR3W9b8gEnyQnGwQhUPsw==", + "dev": true, + "requires": { + "@cypress/request": "3.0.1", + "@verdaccio/auth": "8.0.0-next-8.1", + "@verdaccio/config": "8.0.0-next-8.1", + "@verdaccio/core": "8.0.0-next-8.1", + "@verdaccio/local-storage-legacy": "11.0.2", + "@verdaccio/logger-7": "8.0.0-next-8.1", + "@verdaccio/middleware": "8.0.0-next-8.1", + "@verdaccio/search-indexer": "8.0.0-next-8.0", + "@verdaccio/signature": "8.0.0-next-8.0", + "@verdaccio/streams": "10.2.1", + "@verdaccio/tarball": "13.0.0-next-8.1", + "@verdaccio/ui-theme": "8.0.0-next-8.1", + "@verdaccio/url": "13.0.0-next-8.1", + "@verdaccio/utils": "7.0.1-next-8.1", + "async": "3.2.5", + "clipanion": "4.0.0-rc.3", + "compression": "1.7.4", + "cors": "2.8.5", + "debug": "^4.3.5", + "envinfo": "7.13.0", + "express": "4.21.0", + "express-rate-limit": "5.5.1", + "fast-safe-stringify": "2.1.1", + "handlebars": "4.7.8", + "js-yaml": "4.1.0", + "JSONStream": "1.3.5", + "jsonwebtoken": "9.0.2", + "kleur": "4.1.5", + "lodash": "4.17.21", + "lru-cache": "7.18.3", + "mime": "3.0.0", + "mkdirp": "1.0.4", + "mv": "2.1.1", + "pkginfo": "0.4.1", + "semver": "7.6.3", + "validator": "13.12.0", + "verdaccio-audit": "13.0.0-next-8.1", + "verdaccio-htpasswd": "13.0.0-next-8.1" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true + }, + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true + }, + "mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true + } + } + }, + "verdaccio-audit": { + "version": "13.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/verdaccio-audit/-/verdaccio-audit-13.0.0-next-8.1.tgz", + "integrity": "sha512-EEfUeC1kHuErtwF9FC670W+EXHhcl+iuigONkcprwRfkPxmdBs+Hx36745hgAMZ9SCqedNECaycnGF3tZ3VYfw==", + "dev": true, + "requires": { + "@verdaccio/config": "8.0.0-next-8.1", + "@verdaccio/core": "8.0.0-next-8.1", + "express": "4.21.0", + "https-proxy-agent": "5.0.1", + "node-fetch": "cjs" + } + }, + "verdaccio-htpasswd": { + "version": "13.0.0-next-8.1", + "resolved": "https://registry.npmjs.org/verdaccio-htpasswd/-/verdaccio-htpasswd-13.0.0-next-8.1.tgz", + "integrity": "sha512-BfvmO+ZdbwfttOwrdTPD6Bccr1ZfZ9Tk/9wpXamxdWB/XPWlk3FtyGsvqCmxsInRLPhQ/FSk9c3zRCGvICTFYg==", + "dev": true, + "requires": { + "@verdaccio/core": "8.0.0-next-8.1", + "@verdaccio/file-locking": "13.0.0-next-8.0", + "apache-md5": "1.1.8", + "bcryptjs": "2.4.3", + "core-js": "3.37.1", + "debug": "4.3.7", + "http-errors": "2.0.0", + "unix-crypt-td-js": "1.1.4" + }, + "dependencies": { + "@verdaccio/file-locking": { + "version": "13.0.0-next-8.0", + "resolved": "https://registry.npmjs.org/@verdaccio/file-locking/-/file-locking-13.0.0-next-8.0.tgz", + "integrity": "sha512-28XRwpKiE3Z6KsnwE7o8dEM+zGWOT+Vef7RVJyUlG176JVDbGGip3HfCmFioE1a9BklLyGEFTu6D69BzfbRkzA==", + "dev": true, + "requires": { + "lockfile": "1.0.4" + } + } + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "dependencies": { + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true + } + } + }, + "vite": { + "version": "5.4.7", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.7.tgz", + "integrity": "sha512-5l2zxqMEPVENgvzTuBpHer2awaetimj2BGkhBPdnwKbPNOlHsODU+oiazEZzLK7KhAnOrO+XGYJYn4ZlUhDtDQ==", + "dev": true, + "requires": { + "esbuild": "^0.21.3", + "fsevents": "~2.3.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + } + }, + "vite-node": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.0.tgz", + "integrity": "sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==", + "dev": true, + "requires": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^5.0.0" + } + }, + "vite-plugin-dts": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/vite-plugin-dts/-/vite-plugin-dts-3.8.3.tgz", + "integrity": "sha512-yRHiRosQw7MXdOhmcrVI+kRiB8YEShbSxnADNteK4eZGdEoyOkMHihvO5XOAVlOq8ng9sIqu8vVefDK1zcj3qw==", + "dev": true, + "requires": { + "@microsoft/api-extractor": "7.43.0", + "@rollup/pluginutils": "^5.1.0", + "@vue/language-core": "^1.8.27", + "debug": "^4.3.4", + "kolorist": "^1.8.0", + "magic-string": "^0.30.8", + "vue-tsc": "^1.8.27" + } + }, + "vitest": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.6.0.tgz", + "integrity": "sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==", + "dev": true, + "requires": { + "@vitest/expect": "1.6.0", + "@vitest/runner": "1.6.0", + "@vitest/snapshot": "1.6.0", + "@vitest/spy": "1.6.0", + "@vitest/utils": "1.6.0", + "acorn-walk": "^8.3.2", + "chai": "^4.3.10", + "debug": "^4.3.4", + "execa": "^8.0.1", + "local-pkg": "^0.5.0", + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "std-env": "^3.5.0", + "strip-literal": "^2.0.0", + "tinybench": "^2.5.1", + "tinypool": "^0.8.3", + "vite": "^5.0.0", + "vite-node": "1.6.0", + "why-is-node-running": "^2.2.2" + }, + "dependencies": { + "execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + } + }, + "get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true + }, + "human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true + }, + "is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true + }, + "mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true + }, + "npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "requires": { + "path-key": "^4.0.0" + } + }, + "onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "requires": { + "mimic-fn": "^4.0.0" + } + }, + "path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true + }, + "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 + }, + "strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true + } + } + }, + "vue-template-compiler": { + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz", + "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==", + "dev": true, + "requires": { + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, + "vue-tsc": { + "version": "1.8.27", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.27.tgz", + "integrity": "sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==", + "dev": true, + "requires": { + "@volar/typescript": "~1.11.1", + "@vue/language-core": "1.8.27", + "semver": "^7.5.4" + }, + "dependencies": { + "semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true + } + } + }, "walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -22987,6 +29884,42 @@ "defaults": "^1.0.3" } }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, + "requires": { + "iconv-lite": "0.6.3" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -22996,6 +29929,16 @@ "isexe": "^2.0.0" } }, + "why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "requires": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + } + }, "word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -23110,6 +30053,18 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true + }, + "z-schema": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz", + "integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==", + "dev": true, + "requires": { + "commander": "^9.4.1", + "lodash.get": "^4.4.2", + "lodash.isequal": "^4.5.0", + "validator": "^13.7.0" + } } } } diff --git a/package.json b/package.json index e8e267e..ad906ab 100644 --- a/package.json +++ b/package.json @@ -4,14 +4,15 @@ "license": "MIT", "scripts": { "cz": "cz", - "nx": "nx" + "nx": "nx", + "generate-cel-parser": "antlr4 -Dlanguage=TypeScript packages/cel/src/lib/gen/CEL.g4 -visitor" }, "private": true, "devDependencies": { "@commitlint/cli": "^14.1.0", "@commitlint/config-angular": "^14.1.0", "@commitlint/config-conventional": "^14.1.0", - "@jscutlery/semver": "^2.27.1", + "@jscutlery/semver": "^5.3.1", "@nrwl/cli": "15.0.0", "@nrwl/eslint-plugin-nx": "19.8.0", "@nrwl/jest": "19.8.0", @@ -19,11 +20,19 @@ "@nrwl/linter": "19.8.0", "@nrwl/node": "19.8.0", "@nrwl/workspace": "19.8.0", + "@nx/js": "19.8.0", + "@nx/vite": "19.8.0", + "@nx/web": "19.8.0", + "@swc-node/register": "~1.9.1", + "@swc/core": "~1.5.7", + "@swc/helpers": "~0.5.11", "@types/deep-freeze-strict": "^1.1.0", "@types/jest": "29.5.13", "@types/node": "18.19.9", "@typescript-eslint/eslint-plugin": "7.18.0", "@typescript-eslint/parser": "7.18.0", + "@vitest/coverage-v8": "^1.0.4", + "@vitest/ui": "^1.3.1", "commitizen": "^4.2.4", "cz-conventional-changelog": "^3.3.0", "eslint": "8.57.1", @@ -33,11 +42,18 @@ "nx": "19.8.0", "prettier": "2.7.1", "reflect-metadata": "^0.1.13", - "ts-jest": "28.0.8", + "ts-jest": "^29.2.5", "ts-node": "10.9.1", - "typescript": "4.8.4" + "typescript": "~5.5.2", + "verdaccio": "^5.0.4", + "vite": "^5.0.0", + "vite-plugin-dts": "~3.8.1", + "vitest": "^1.3.1" }, "dependencies": { + "@buf/google_cel-spec.bufbuild_es": "^2.1.0-20240829202630-b69910e4e9bc.1", + "@bufbuild/protobuf": "^2.1.0", + "antlr4": "^4.13.2", "class-transformer": "^0.5.1", "deep-freeze-strict": "^1.1.1", "fast-json-stable-stringify": "^2.1.0", @@ -49,5 +65,8 @@ "commitizen": { "path": "cz-conventional-changelog" } + }, + "nx": { + "includedScripts": [] } } diff --git a/packages/cel/.eslintrc.json b/packages/cel/.eslintrc.json new file mode 100644 index 0000000..80382ac --- /dev/null +++ b/packages/cel/.eslintrc.json @@ -0,0 +1,23 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*", "src/lib/conformance/**/*", "src/lib/gen/**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.json"], + "parser": "jsonc-eslint-parser", + "rules": {} + } + ] +} diff --git a/packages/cel/README.md b/packages/cel/README.md new file mode 100644 index 0000000..4de12fe --- /dev/null +++ b/packages/cel/README.md @@ -0,0 +1,11 @@ +# cel + +This library was generated with [Nx](https://nx.dev). + +## Building + +Run `nx build cel` to build the library. + +## Running unit tests + +Run `nx test cel` to execute the unit tests via [Vitest](https://vitest.dev/). diff --git a/packages/cel/package.json b/packages/cel/package.json new file mode 100644 index 0000000..45a120f --- /dev/null +++ b/packages/cel/package.json @@ -0,0 +1,10 @@ +{ + "name": "@bearclaw/cel", + "version": "0.0.1", + "dependencies": { + "@bearclaw/is": "*" + }, + "main": "./index.js", + "module": "./index.mjs", + "typings": "./index.d.ts" +} diff --git a/packages/cel/project.json b/packages/cel/project.json new file mode 100644 index 0000000..eaf35d6 --- /dev/null +++ b/packages/cel/project.json @@ -0,0 +1,55 @@ +{ + "name": "cel", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "packages/cel/src", + "projectType": "library", + "release": { + "version": { + "generatorOptions": { + "packageRoot": "dist/{projectRoot}", + "currentVersionResolver": "git-tag" + } + } + }, + "tags": [], + "targets": { + "build": { + "executor": "@nx/vite:build", + "outputs": ["{options.outputPath}"], + "defaultConfiguration": "production", + "options": { + "outputPath": "dist/packages/cel" + }, + "configurations": { + "development": { + "mode": "development" + }, + "production": { + "mode": "production" + } + } + }, + "nx-release-publish": { + "options": { + "packageRoot": "dist/{projectRoot}" + } + }, + "test": { + "executor": "@nx/vite:test", + "outputs": ["{options.reportsDirectory}"], + "options": { + "reportsDirectory": "../../coverage/packages/cel" + } + }, + "lint": { + "executor": "@nx/eslint:lint" + }, + "prepare-conformance": { + "executor": "nx:run-commands", + "options": { + "command": "go run textproto-to-json.go", + "cwd": "packages/cel/src/lib/conformance" + } + } + } +} diff --git a/packages/cel/src/index.ts b/packages/cel/src/index.ts new file mode 100644 index 0000000..3a77b6c --- /dev/null +++ b/packages/cel/src/index.ts @@ -0,0 +1 @@ +export * from './lib/cel'; diff --git a/packages/cel/src/lib/balancer.ts b/packages/cel/src/lib/balancer.ts new file mode 100644 index 0000000..5b9f0f4 --- /dev/null +++ b/packages/cel/src/lib/balancer.ts @@ -0,0 +1,61 @@ +import { + Expr, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { create } from '@bufbuild/protobuf'; + +export class ExpressionBalancer { + private readonly fn!: string; + private readonly terms!: Expr[]; + private readonly ids!: bigint[]; + + constructor(fn: string, expr: Expr) { + if (!fn || fn.trim() === '') { + throw new Error('Function cannot be null or empty'); + } + + this.fn = fn; + this.terms = [expr]; + this.ids = []; + } + + add(operationId: bigint, expr: Expr): void { + if (!expr) { + throw new Error('Expression cannot be null'); + } + + if (operationId <= 0) { + throw new Error('OperationId must be greater than 0'); + } + + this.terms.push(expr); + this.ids.push(operationId); + } + + balance(): Expr { + if (this.terms.length <= 1) { + throw new Error('At least two expressions are required to balance'); + } + + return this.balanceRecursive(0, this.ids.length - 1); + } + + private balanceRecursive(lo: number, hi: number): Expr { + const mid = Math.floor((lo + hi + 1) / 2); + const left = + mid === lo ? this.terms[mid] : this.balanceRecursive(lo, mid - 1); + const right = + mid === hi ? this.terms[mid + 1] : this.balanceRecursive(mid + 1, hi); + + return create(ExprSchema, { + id: BigInt(this.ids[mid]), + exprKind: { + case: 'callExpr', + value: { + function: this.fn, + args: [left, right], + }, + }, + }); + } +} diff --git a/packages/cel/src/lib/cel.spec.ts b/packages/cel/src/lib/cel.spec.ts new file mode 100644 index 0000000..a7a8efb --- /dev/null +++ b/packages/cel/src/lib/cel.spec.ts @@ -0,0 +1,7 @@ +import { cel } from './cel'; + +describe('cel', () => { + it('should work', () => { + expect(cel()).toEqual('cel'); + }); +}); diff --git a/packages/cel/src/lib/cel.ts b/packages/cel/src/lib/cel.ts new file mode 100644 index 0000000..19aae82 --- /dev/null +++ b/packages/cel/src/lib/cel.ts @@ -0,0 +1,3 @@ +export function cel(): string { + return 'cel'; +} diff --git a/packages/cel/src/lib/conformance/go.mod b/packages/cel/src/lib/conformance/go.mod new file mode 100644 index 0000000..7d9d937 --- /dev/null +++ b/packages/cel/src/lib/conformance/go.mod @@ -0,0 +1,13 @@ +module textproto-to-json + +go 1.22.4 + +require ( + cel.dev/expr v0.16.2 + google.golang.org/protobuf v1.34.2 +) + +require ( + google.golang.org/genproto/googleapis/api v0.0.0-20240826202546-f6391c0de4c7 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7 // indirect +) diff --git a/packages/cel/src/lib/conformance/go.sum b/packages/cel/src/lib/conformance/go.sum new file mode 100644 index 0000000..22e8d73 --- /dev/null +++ b/packages/cel/src/lib/conformance/go.sum @@ -0,0 +1,10 @@ +cel.dev/expr v0.16.2 h1:RwRhoH17VhAu9U5CMvMhH1PDVgf0tuz9FT+24AfMLfU= +cel.dev/expr v0.16.2/go.mod h1:gXngZQMkWJoSbE8mOzehJlXQyubn/Vg0vR9/F3W7iw8= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +google.golang.org/genproto/googleapis/api v0.0.0-20240826202546-f6391c0de4c7 h1:YcyjlL1PRr2Q17/I0dPk2JmYS5CDXfcdb2Z3YRioEbw= +google.golang.org/genproto/googleapis/api v0.0.0-20240826202546-f6391c0de4c7/go.mod h1:OCdP9MfskevB/rbYvHTsXTtKC+3bHWajPdoKgjcYkfo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7 h1:2035KHhUv+EpyB+hWgJnaWKJOdX1E95w2S8Rr4uWKTs= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= diff --git a/packages/cel/src/lib/conformance/testdata/README.md b/packages/cel/src/lib/conformance/testdata/README.md new file mode 100644 index 0000000..50effee --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/README.md @@ -0,0 +1,66 @@ +# Simple Conformance Test Data Files + +The test data files for the `simple` conformance test suite +are described by the `SimpleTestFile` message defined in +[`simple.proto`](../../../proto/test/v1/simple.proto). +See the documentation in that file for the meaning of the various fields. + +A run of the simple tests chooses one or more data files and attempts +to run all the tests in those files. Test files are organized so that +implementations can implement a prescribed subset of CEL functionality. +For instance, implementations which don't support macros can avoid testing +against the `macros.textproto` file. + +The available test files are: + +- [`plumbing.textproto`](plumbing.textproto) Checks the basics of the CelService + protocol to ensure that the server is implemented correctly. + +- [`basic.textproto`](basic.textproto) Checks the most basic operations that + all CEL implementations should support: + - literals of various types; + - variables of various types. + +- [`comparisons.textproto`](comparisons.textproto) Checks the standard functions + that return a boolean value. + +- [`conversions.textproto`](conversions.textproto) Checks conversions between + types and type tests. + +- [`dynamic.textproto`](dynamic.textproto) Checks the automatic conversions + associated with the well-known protobuf messages. + +- [`enums.textproto`](enums.textproto) Checks handling of protobuf enums. + +- [`fields.textproto`](fields.textproto) Checks field selection in messages + and maps. + +- [`fp_math.textproto`](fp_math.textproto) Checks floating-point arithmetic. + +- [`integer_math.textproto`](integer_math.textproto) Checks integer arithmetic. + +- [`lists.textproto`](lists.textproto) Checks list operations. + +- [`logic.textproto`](logic.textproto) Checks special logical operators. + +- [`macros.textproto`](macros.textproto) Checks use of CEL macros. + +- [`namespace.textproto`](namespace.textproto) Checks use of namespaces and + qualified identifiers. + +- [`parse.textproto`](parse.textproto) End-to-end tests of parsing. More + detailed parsing tests will the subject of a later conformance suite. + +- [`proto2.textproto`](proto2.textproto) Checks use of protocol buffers version + 2. + +- [`proto3.textproto`](proto3.textproto) Checks use of protocol buffers version + 3. + +- [`string.textproto`](string.textproto) Checks functions on strings. + +- [`timestamps.textproto`](timestamps.textproto) Checks `timestamp` and `duration` + values and operations. + +- [`unknowns.textproto`](unknowns.textproto) Checks evaluation where some + inputs are marked as unknown. diff --git a/packages/cel/src/lib/conformance/testdata/basic.json b/packages/cel/src/lib/conformance/testdata/basic.json new file mode 100755 index 0000000..9427a39 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/basic.json @@ -0,0 +1,436 @@ +{ + "name": "basic", + "description": "Basic conformance tests that all implementations should pass.", + "section": [ + { + "name": "self_eval_zeroish", + "description": "Simple self-evaluating forms to zero-ish values.", + "test": [ + { + "name": "self_eval_int_zero", + "expr": "0", + "value": { + "int64Value": "0" + } + }, + { + "name": "self_eval_uint_zero", + "expr": "0u", + "value": { + "uint64Value": "0" + } + }, + { + "name": "self_eval_uint_alias_zero", + "expr": "0U", + "value": { + "uint64Value": "0" + } + }, + { + "name": "self_eval_float_zero", + "expr": "0.0", + "value": { + "doubleValue": 0 + } + }, + { + "name": "self_eval_float_zerowithexp", + "expr": "0e+0", + "value": { + "doubleValue": 0 + } + }, + { + "name": "self_eval_string_empty", + "expr": "''", + "value": { + "stringValue": "" + } + }, + { + "name": "self_eval_string_empty_quotes", + "expr": "\"\"", + "value": { + "stringValue": "" + } + }, + { + "name": "self_eval_string_raw_prefix", + "expr": "r\"\"", + "value": { + "stringValue": "" + } + }, + { + "name": "self_eval_bytes_empty", + "expr": "b\"\"", + "value": { + "bytesValue": "" + } + }, + { + "name": "self_eval_bool_false", + "expr": "false", + "value": { + "boolValue": false + } + }, + { + "name": "self_eval_null", + "expr": "null", + "value": { + "nullValue": null + } + }, + { + "name": "self_eval_empty_list", + "expr": "[]", + "value": { + "listValue": {} + } + }, + { + "name": "self_eval_empty_map", + "expr": "{}", + "value": { + "mapValue": {} + } + }, + { + "name": "self_eval_string_raw_prefix_triple_double", + "expr": "r\"\"\"\"\"\"", + "value": { + "stringValue": "" + } + }, + { + "name": "self_eval_string_raw_prefix_triple_single", + "expr": "r''''''", + "value": { + "stringValue": "" + } + } + ] + }, + { + "name": "self_eval_nonzeroish", + "description": "Simple self-evaluating forms to non-zero-ish values.", + "test": [ + { + "name": "self_eval_int_nonzero", + "expr": "42", + "value": { + "int64Value": "42" + } + }, + { + "name": "self_eval_uint_nonzero", + "expr": "123456789u", + "value": { + "uint64Value": "123456789" + } + }, + { + "name": "self_eval_uint_alias_nonzero", + "expr": "123456789U", + "value": { + "uint64Value": "123456789" + } + }, + { + "name": "self_eval_int_negative_min", + "expr": "-9223372036854775808", + "value": { + "int64Value": "-9223372036854775808" + } + }, + { + "name": "self_eval_float_negative_exp", + "expr": "-2.3e+1", + "value": { + "doubleValue": -23 + } + }, + { + "name": "self_eval_string_excl", + "expr": "\"!\"", + "value": { + "stringValue": "!" + } + }, + { + "name": "self_eval_string_escape", + "expr": "'\\''", + "value": { + "stringValue": "'" + } + }, + { + "name": "self_eval_bytes_escape", + "expr": "b'ÿ'", + "value": { + "bytesValue": "w78=" + } + }, + { + "name": "self_eval_bytes_invalid_utf8", + "expr": "b'\\000\\xff'", + "value": { + "bytesValue": "AP8=" + } + }, + { + "name": "self_eval_list_singleitem", + "expr": "[-1]", + "value": { + "listValue": { + "values": [ + { + "int64Value": "-1" + } + ] + } + } + }, + { + "name": "self_eval_map_singleitem", + "expr": "{\"k\":\"v\"}", + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "k" + }, + "value": { + "stringValue": "v" + } + } + ] + } + } + }, + { + "name": "self_eval_bool_true", + "expr": "true", + "value": { + "boolValue": true + } + }, + { + "name": "self_eval_int_hex", + "expr": "0x55555555", + "value": { + "int64Value": "1431655765" + } + }, + { + "name": "self_eval_int_hex_negative", + "expr": "-0x55555555", + "value": { + "int64Value": "-1431655765" + } + }, + { + "name": "self_eval_uint_hex", + "expr": "0x55555555u", + "value": { + "uint64Value": "1431655765" + } + }, + { + "name": "self_eval_uint_alias_hex", + "expr": "0x55555555U", + "value": { + "uint64Value": "1431655765" + } + }, + { + "name": "self_eval_unicode_escape_four", + "expr": "\"\\u270c\"", + "value": { + "stringValue": "✌" + } + }, + { + "name": "self_eval_unicode_escape_eight", + "expr": "\"\\U0001f431\"", + "value": { + "stringValue": "🐱" + } + }, + { + "name": "self_eval_ascii_escape_seq", + "expr": "\"\\a\\b\\f\\n\\r\\t\\v\\\"\\'\\\\\"", + "value": { + "stringValue": "\u0007\b\f\n\r\t\u000b\"'\\" + } + } + ] + }, + { + "name": "variables", + "description": "Variable lookups.", + "test": [ + { + "name": "self_eval_bound_lookup", + "expr": "x", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "primitive": "INT64" + } + } + } + ], + "bindings": { + "x": { + "value": { + "int64Value": "123" + } + } + }, + "value": { + "int64Value": "123" + } + }, + { + "name": "self_eval_unbound_lookup", + "description": "An unbound variable should be marked as an error during execution. See google/cel-go#154", + "expr": "x", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "undeclared reference to 'x' (in container '')" + } + ] + } + }, + { + "name": "unbound_is_runtime_error", + "description": "Make sure we can short-circuit around an unbound variable.", + "expr": "x || true", + "disableCheck": true, + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "functions", + "description": "Basic mechanisms for function calls.", + "test": [ + { + "name": "binop", + "expr": "1 + 1", + "value": { + "int64Value": "2" + } + }, + { + "name": "unbound", + "expr": "f_unknown(17)", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "unbound function" + } + ] + } + }, + { + "name": "unbound_is_runtime_error", + "expr": "f_unknown(17) || true", + "disableCheck": true, + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "reserved_const", + "description": "Named constants should never be shadowed by identifiers.", + "test": [ + { + "name": "false", + "expr": "false", + "typeEnv": [ + { + "name": "false", + "ident": { + "type": { + "primitive": "BOOL" + } + } + } + ], + "bindings": { + "false": { + "value": { + "boolValue": true + } + } + }, + "value": { + "boolValue": false + } + }, + { + "name": "true", + "expr": "true", + "typeEnv": [ + { + "name": "true", + "ident": { + "type": { + "primitive": "BOOL" + } + } + } + ], + "bindings": { + "true": { + "value": { + "boolValue": false + } + } + }, + "value": { + "boolValue": true + } + }, + { + "name": "null", + "expr": "null", + "typeEnv": [ + { + "name": "null", + "ident": { + "type": { + "primitive": "BOOL" + } + } + } + ], + "bindings": { + "null": { + "value": { + "boolValue": true + } + } + }, + "value": { + "nullValue": null + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/basic.textproto b/packages/cel/src/lib/conformance/testdata/basic.textproto new file mode 100644 index 0000000..4697b6e --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/basic.textproto @@ -0,0 +1,290 @@ +name: "basic" +description: "Basic conformance tests that all implementations should pass." +section { + name: "self_eval_zeroish" + description: "Simple self-evaluating forms to zero-ish values." + test { + name: "self_eval_int_zero" + expr: "0" + value: { int64_value: 0 } + } + test { + name: "self_eval_uint_zero" + expr: "0u" + value: { uint64_value: 0 } + } + test { + name: "self_eval_uint_alias_zero" + expr: "0U" + value: { uint64_value: 0 } + } + test { + name: "self_eval_float_zero" + expr: "0.0" + value: { double_value: 0 } + } + test { + name: "self_eval_float_zerowithexp" + expr: "0e+0" + value: { double_value: 0 } + } + test { + name: "self_eval_string_empty" + expr: "''" + value: { string_value: "" } + } + test { + name: "self_eval_string_empty_quotes" + expr: '""' + value: { string_value: "" } + } + test { + name: "self_eval_string_raw_prefix" + expr: 'r""' + value: { string_value: "" } + } + test { + name: "self_eval_bytes_empty" + expr: 'b""' + value: { bytes_value: "" } + } + test { + name: "self_eval_bool_false" + expr: "false" + value: { bool_value: false } + } + test { + name: "self_eval_null" + expr: "null" + value: { null_value: NULL_VALUE } + } + test { + name: "self_eval_empty_list" + expr: '[]' + value: { list_value: {} } + } + test { + name: "self_eval_empty_map" + expr: '{}' + value: { map_value: {} } + } + test { + name: "self_eval_string_raw_prefix_triple_double" + expr: 'r""""""' + value: { string_value: "" } + } + test { + name: "self_eval_string_raw_prefix_triple_single" + expr: "r''''''" + value: { string_value: "" } + } +} +section { + name: "self_eval_nonzeroish" + description: "Simple self-evaluating forms to non-zero-ish values." + test { + name: "self_eval_int_nonzero" + expr: "42" + value: { int64_value: 42 } + } + test { + name: "self_eval_uint_nonzero" + expr: "123456789u" + value: { uint64_value: 123456789 } + } + test { + name: "self_eval_uint_alias_nonzero" + expr: "123456789U" + value: { uint64_value: 123456789 } + } + test { + name: "self_eval_int_negative_min" + expr: "-9223372036854775808" + value: { int64_value: -9223372036854775808 } + } + test { + name: "self_eval_float_negative_exp" + expr: "-2.3e+1" + value: { double_value: -23.0 } + } + test { + name: "self_eval_string_excl" + expr: '"!"' + value: { string_value: "!" } + } + test { + name: "self_eval_string_escape" + expr: "'\\''" + value: { string_value: "'" } + } + test { + name: "self_eval_bytes_escape" + expr: "b'ÿ'" + value: { bytes_value: "\303\277" } + } + test { + name: "self_eval_bytes_invalid_utf8" + expr: "b'\\000\\xff'" + value: { bytes_value: "\000\377" } + } + test { + name: "self_eval_list_singleitem" + expr: "[-1]" + value: { + list_value { + values: { int64_value: -1 } + } + } + } + test { + name: "self_eval_map_singleitem" + expr: '{"k":"v"}' + value: { + map_value { + entries { + key: { string_value: "k" } + value: { string_value: "v" } + } + } + } + } + test { + name: "self_eval_bool_true" + expr: "true" + value: { bool_value: true } + } + test { + name: "self_eval_int_hex" + expr: "0x55555555" + value: { int64_value: 1431655765 } + } + test { + name: "self_eval_int_hex_negative" + expr: "-0x55555555" + value: { int64_value: -1431655765 } + } + test { + name: "self_eval_uint_hex" + expr: "0x55555555u" + value: { uint64_value: 1431655765 } + } + test { + name: "self_eval_uint_alias_hex" + expr: "0x55555555U" + value: { uint64_value: 1431655765 } + } + test { + name: "self_eval_unicode_escape_four" + expr: '"\\u270c"' + value: { string_value: "\xe2\x9c\x8c" } + } + test { + name: "self_eval_unicode_escape_eight" + expr: '"\\U0001f431"' + value: { string_value: "\xf0\x9f\x90\xb1" } + } + test { + name: "self_eval_ascii_escape_seq" + expr: '"\\a\\b\\f\\n\\r\\t\\v\\"\\\'\\\\"' + value: { string_value: "\a\b\f\n\r\t\v\"'\\" } + } +} +section { + name: "variables" + description: "Variable lookups." + test { + name: "self_eval_bound_lookup" + expr: "x" + type_env: { + name: "x", + ident: { type: { primitive: INT64 } } + } + bindings: { + key: "x" + value: { value: { int64_value: 123 } } + } + value: { int64_value: 123 } + } + test { + name: "self_eval_unbound_lookup" + description: "An unbound variable should be marked as an error during execution. See google/cel-go#154" + expr: "x" + disable_check: true + eval_error: { + errors: { message: "undeclared reference to 'x' (in container '')" } + } + } + test { + name: "unbound_is_runtime_error" + description: "Make sure we can short-circuit around an unbound variable." + expr: "x || true" + disable_check: true + value { bool_value: true } + } +} +section { + name: "functions" + description: "Basic mechanisms for function calls." + test { + name: "binop" + expr: "1 + 1" + value { int64_value: 2 } + } + test { + name: "unbound" + expr: "f_unknown(17)" + disable_check: true + eval_error { + errors { message: "unbound function" } + } + } + test { + name: "unbound_is_runtime_error" + expr: "f_unknown(17) || true" + disable_check: true + value { bool_value: true } + } +} +section { + name: "reserved_const" + description: "Named constants should never be shadowed by identifiers." + test { + name: "false" + expr: "false" + type_env: { + name: "false" + ident: { type: { primitive: BOOL } } + } + bindings { + key: "false" + value: { value: { bool_value: true } } + } + value: { bool_value: false } + } + test { + name: "true" + expr: "true" + type_env: { + name: "true" + ident: { type: { primitive: BOOL } } + } + bindings { + key: "true" + value: { value: { bool_value: false } } + } + value: { bool_value: true } + } + test { + name: "null" + expr: "null" + type_env: { + name: "null" + ident: { type: { primitive: BOOL } } + } + bindings { + key: "null" + value: { value: { bool_value: true } } + } + value: { null_value: 0 } + } +} diff --git a/packages/cel/src/lib/conformance/testdata/bindings_ext.json b/packages/cel/src/lib/conformance/testdata/bindings_ext.json new file mode 100755 index 0000000..c310298 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/bindings_ext.json @@ -0,0 +1,46 @@ +{ + "name": "bindings_ext", + "description": "Tests for the bindings extension library.", + "section": [ + { + "name": "bind", + "test": [ + { + "name": "boolean_literal", + "expr": "cel.bind(t, true, t)", + "value": { + "boolValue": true + } + }, + { + "name": "string_concat", + "expr": "cel.bind(msg, \"hello\", msg + msg + msg)", + "value": { + "stringValue": "hellohellohello" + } + }, + { + "name": "bind_nested", + "expr": "cel.bind(t1, true, cel.bind(t2, true, t1 && t2))", + "value": { + "boolValue": true + } + }, + { + "name": "macro_exists", + "expr": "cel.bind(valid_elems, [1, 2, 3], [3, 4, 5].exists(e, e in valid_elems))", + "value": { + "boolValue": true + } + }, + { + "name": "macro_not_exists", + "expr": "cel.bind(valid_elems, [1, 2, 3], ![4, 5].exists(e, e in valid_elems))", + "value": { + "boolValue": true + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/bindings_ext.textproto b/packages/cel/src/lib/conformance/testdata/bindings_ext.textproto new file mode 100644 index 0000000..1e01b29 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/bindings_ext.textproto @@ -0,0 +1,41 @@ +name: "bindings_ext" +description: "Tests for the bindings extension library." +section: { + name: "bind" + test: { + name: "boolean_literal" + expr: "cel.bind(t, true, t)" + value: { + bool_value: true + } + } + test: { + name: "string_concat" + expr: "cel.bind(msg, \"hello\", msg + msg + msg)" + value: { + string_value: "hellohellohello" + } + } + test: { + name: "bind_nested" + expr: "cel.bind(t1, true, cel.bind(t2, true, t1 && t2))" + value: { + bool_value: true + } + } + test: { + name: "macro_exists" + expr: "cel.bind(valid_elems, [1, 2, 3], [3, 4, 5].exists(e, e in valid_elems))" + value: { + bool_value: true + } + } + test: { + name: "macro_not_exists" + expr: "cel.bind(valid_elems, [1, 2, 3], ![4, 5].exists(e, e in valid_elems))" + value: { + bool_value: true + } + } +} + diff --git a/packages/cel/src/lib/conformance/testdata/block_ext.json b/packages/cel/src/lib/conformance/testdata/block_ext.json new file mode 100755 index 0000000..e5d5d2d --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/block_ext.json @@ -0,0 +1,956 @@ +{ + "name": "block_ext", + "description": "Tests for cel.block.", + "section": [ + { + "name": "basic", + "test": [ + { + "name": "int_add", + "expr": "cel.block([1, cel.index(0) + 1, cel.index(1) + 1, cel.index(2) + 1], cel.index(3))", + "value": { + "int64Value": "4" + } + }, + { + "name": "size_1", + "expr": "cel.block([[1, 2], size(cel.index(0)), cel.index(1) + cel.index(1), cel.index(2) + 1], cel.index(3))", + "value": { + "int64Value": "5" + } + }, + { + "name": "size_2", + "expr": "cel.block([[1, 2], size(cel.index(0)), 2 + cel.index(1), cel.index(2) + cel.index(1), cel.index(3) + 1], cel.index(4))", + "value": { + "int64Value": "7" + } + }, + { + "name": "size_3", + "expr": "cel.block([[0], size(cel.index(0)), [1, 2], size(cel.index(2)), cel.index(1) + cel.index(1), cel.index(4) + cel.index(3), cel.index(5) + cel.index(3)], cel.index(6))", + "value": { + "int64Value": "6" + } + }, + { + "name": "size_4", + "expr": "cel.block([[0], size(cel.index(0)), [1, 2], size(cel.index(2)), [1, 2, 3], size(cel.index(4)), 5 + cel.index(1), cel.index(6) + cel.index(1), cel.index(7) + cel.index(3), cel.index(8) + cel.index(3), cel.index(9) + cel.index(5), cel.index(10) + cel.index(5)], cel.index(11))", + "value": { + "int64Value": "17" + } + }, + { + "name": "timestamp", + "expr": "cel.block([timestamp(1000000000), int(cel.index(0)), timestamp(cel.index(1)), cel.index(2).getFullYear(), timestamp(50), int(cel.index(4)), timestamp(cel.index(5)), timestamp(200), int(cel.index(7)), timestamp(cel.index(8)), cel.index(9).getFullYear(), timestamp(75), int(cel.index(11)), timestamp(cel.index(12)), cel.index(13).getFullYear(), cel.index(3) + cel.index(14), cel.index(6).getFullYear(), cel.index(15) + cel.index(16), cel.index(17) + cel.index(3), cel.index(6).getSeconds(), cel.index(18) + cel.index(19), cel.index(20) + cel.index(10), cel.index(21) + cel.index(10), cel.index(13).getMinutes(), cel.index(22) + cel.index(23), cel.index(24) + cel.index(3)], cel.index(25))", + "value": { + "int64Value": "13934" + } + }, + { + "name": "map_index", + "expr": "cel.block([{\"a\": 2}, cel.index(0)[\"a\"], cel.index(1) * cel.index(1), cel.index(1) + cel.index(2)], cel.index(3))", + "value": { + "int64Value": "6" + } + }, + { + "name": "nested_map_construction", + "expr": "cel.block([{\"b\": 1}, {\"e\": cel.index(0)}], {\"a\": cel.index(0), \"c\": cel.index(0), \"d\": cel.index(1), \"e\": cel.index(1)})", + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "a" + }, + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "b" + }, + "value": { + "int64Value": "1" + } + } + ] + } + } + }, + { + "key": { + "stringValue": "c" + }, + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "b" + }, + "value": { + "int64Value": "1" + } + } + ] + } + } + }, + { + "key": { + "stringValue": "d" + }, + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "e" + }, + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "b" + }, + "value": { + "int64Value": "1" + } + } + ] + } + } + } + ] + } + } + }, + { + "key": { + "stringValue": "e" + }, + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "e" + }, + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "b" + }, + "value": { + "int64Value": "1" + } + } + ] + } + } + } + ] + } + } + } + ] + } + } + }, + { + "name": "nested_list_construction", + "expr": "cel.block([[1, 2, 3, 4], [1, 2], [cel.index(1), cel.index(0)]], [1, cel.index(0), 2, cel.index(0), 5, cel.index(0), 7, cel.index(2), cel.index(1)])", + "value": { + "listValue": { + "values": [ + { + "int64Value": "1" + }, + { + "listValue": { + "values": [ + { + "int64Value": "1" + }, + { + "int64Value": "2" + }, + { + "int64Value": "3" + }, + { + "int64Value": "4" + } + ] + } + }, + { + "int64Value": "2" + }, + { + "listValue": { + "values": [ + { + "int64Value": "1" + }, + { + "int64Value": "2" + }, + { + "int64Value": "3" + }, + { + "int64Value": "4" + } + ] + } + }, + { + "int64Value": "5" + }, + { + "listValue": { + "values": [ + { + "int64Value": "1" + }, + { + "int64Value": "2" + }, + { + "int64Value": "3" + }, + { + "int64Value": "4" + } + ] + } + }, + { + "int64Value": "7" + }, + { + "listValue": { + "values": [ + { + "listValue": { + "values": [ + { + "int64Value": "1" + }, + { + "int64Value": "2" + } + ] + } + }, + { + "listValue": { + "values": [ + { + "int64Value": "1" + }, + { + "int64Value": "2" + }, + { + "int64Value": "3" + }, + { + "int64Value": "4" + } + ] + } + } + ] + } + }, + { + "listValue": { + "values": [ + { + "int64Value": "1" + }, + { + "int64Value": "2" + } + ] + } + } + ] + } + } + }, + { + "name": "select", + "expr": "cel.block([msg.single_int64, cel.index(0) + cel.index(0)], cel.index(1))", + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt32": 5, + "singleInt64": "3", + "oneofType": { + "payload": { + "singleInt32": 8, + "singleInt64": "10", + "mapInt32Int64": { + "0": "1", + "1": "5", + "2": "2" + }, + "mapStringString": { + "key": "A" + } + } + } + } + } + } + }, + "value": { + "int64Value": "6" + } + }, + { + "name": "select_nested_1", + "expr": "cel.block([msg.oneof_type, cel.index(0).payload, cel.index(1).single_int64, cel.index(1).single_int32, cel.index(2) + cel.index(3), cel.index(4) + cel.index(2), msg.single_int64, cel.index(5) + cel.index(6), cel.index(1).oneof_type, cel.index(8).payload, cel.index(9).single_int64, cel.index(7) + cel.index(10)], cel.index(11))", + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt32": 5, + "singleInt64": "3", + "oneofType": { + "payload": { + "singleInt32": 8, + "singleInt64": "10", + "mapInt32Int64": { + "0": "1", + "1": "5", + "2": "2" + }, + "mapStringString": { + "key": "A" + } + } + } + } + } + } + }, + "value": { + "int64Value": "31" + } + }, + { + "name": "select_nested_2", + "expr": "cel.block([msg.oneof_type, cel.index(0).payload, cel.index(1).oneof_type, cel.index(2).payload, cel.index(3).oneof_type, cel.index(4).payload, cel.index(5).oneof_type, cel.index(6).payload, cel.index(7).single_bool, true || cel.index(8), cel.index(4).child, cel.index(10).child, cel.index(11).payload, cel.index(12).single_bool], cel.index(9) || cel.index(13))", + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt32": 5, + "singleInt64": "3", + "oneofType": { + "payload": { + "singleInt32": 8, + "singleInt64": "10", + "mapInt32Int64": { + "0": "1", + "1": "5", + "2": "2" + }, + "mapStringString": { + "key": "A" + } + } + } + } + } + } + }, + "value": { + "boolValue": true + } + }, + { + "name": "select_nested_message_map_index_1", + "expr": "cel.block([msg.oneof_type, cel.index(0).payload, cel.index(1).map_int32_int64, cel.index(2)[1], cel.index(3) + cel.index(3), cel.index(4) + cel.index(3)], cel.index(5))", + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt32": 5, + "singleInt64": "3", + "oneofType": { + "payload": { + "singleInt32": 8, + "singleInt64": "10", + "mapInt32Int64": { + "0": "1", + "1": "5", + "2": "2" + }, + "mapStringString": { + "key": "A" + } + } + } + } + } + } + }, + "value": { + "int64Value": "15" + } + }, + { + "name": "select_nested_message_map_index_2", + "expr": "cel.block([msg.oneof_type, cel.index(0).payload, cel.index(1).map_int32_int64, cel.index(2)[0], cel.index(2)[1], cel.index(3) + cel.index(4), cel.index(2)[2], cel.index(5) + cel.index(6)], cel.index(7))", + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt32": 5, + "singleInt64": "3", + "oneofType": { + "payload": { + "singleInt32": 8, + "singleInt64": "10", + "mapInt32Int64": { + "0": "1", + "1": "5", + "2": "2" + }, + "mapStringString": { + "key": "A" + } + } + } + } + } + } + }, + "value": { + "int64Value": "8" + } + }, + { + "name": "ternary", + "expr": "cel.block([msg.single_int64, cel.index(0) > 0, cel.index(1) ? cel.index(0) : 0], cel.index(2))", + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt32": 5, + "singleInt64": "3", + "oneofType": { + "payload": { + "singleInt32": 8, + "singleInt64": "10", + "mapInt32Int64": { + "0": "1", + "1": "5", + "2": "2" + }, + "mapStringString": { + "key": "A" + } + } + } + } + } + } + }, + "value": { + "int64Value": "3" + } + }, + { + "name": "nested_ternary", + "expr": "cel.block([msg.single_int64, msg.single_int32, cel.index(0) > 0, cel.index(1) > 0, cel.index(0) + cel.index(1), cel.index(3) ? cel.index(4) : 0, cel.index(2) ? cel.index(5) : 0], cel.index(6))", + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt32": 5, + "singleInt64": "3", + "oneofType": { + "payload": { + "singleInt32": 8, + "singleInt64": "10", + "mapInt32Int64": { + "0": "1", + "1": "5", + "2": "2" + }, + "mapStringString": { + "key": "A" + } + } + } + } + } + } + }, + "value": { + "int64Value": "8" + } + }, + { + "name": "multiple_macros_1", + "expr": "cel.block([[1].exists(cel.iterVar(0, 0), cel.iterVar(0, 0) > 0), size([cel.index(0)]), [2].exists(cel.iterVar(0, 0), cel.iterVar(0, 0) > 1), size([cel.index(2)])], cel.index(1) + cel.index(1) + cel.index(3) + cel.index(3))", + "value": { + "int64Value": "4" + } + }, + { + "name": "multiple_macros_2", + "expr": "cel.block([[1].exists(cel.iterVar(0, 0), cel.iterVar(0, 0) > 0), [cel.index(0)], ['a'].exists(cel.iterVar(0, 1), cel.iterVar(0, 1) == 'a'), [cel.index(2)]], cel.index(1) + cel.index(1) + cel.index(3) + cel.index(3))", + "value": { + "listValue": { + "values": [ + { + "boolValue": true + }, + { + "boolValue": true + }, + { + "boolValue": true + }, + { + "boolValue": true + } + ] + } + } + }, + { + "name": "multiple_macros_3", + "expr": "cel.block([[1].exists(cel.iterVar(0, 0), cel.iterVar(0, 0) > 0)], cel.index(0) && cel.index(0) && [1].exists(cel.iterVar(0, 0), cel.iterVar(0, 0) > 1) && [2].exists(cel.iterVar(0, 0), cel.iterVar(0, 0) > 1))", + "value": { + "boolValue": false + } + }, + { + "name": "nested_macros_1", + "expr": "cel.block([[1, 2, 3]], cel.index(0).map(cel.iterVar(0, 0), cel.index(0).map(cel.iterVar(1, 0), cel.iterVar(1, 0) + 1)))", + "value": { + "listValue": { + "values": [ + { + "listValue": { + "values": [ + { + "int64Value": "2" + }, + { + "int64Value": "3" + }, + { + "int64Value": "4" + } + ] + } + }, + { + "listValue": { + "values": [ + { + "int64Value": "2" + }, + { + "int64Value": "3" + }, + { + "int64Value": "4" + } + ] + } + }, + { + "listValue": { + "values": [ + { + "int64Value": "2" + }, + { + "int64Value": "3" + }, + { + "int64Value": "4" + } + ] + } + } + ] + } + } + }, + { + "name": "nested_macros_2", + "expr": "[1, 2].map(cel.iterVar(0, 0), [1, 2, 3].filter(cel.iterVar(1, 0), cel.iterVar(1, 0) == cel.iterVar(0, 0)))", + "value": { + "listValue": { + "values": [ + { + "listValue": { + "values": [ + { + "int64Value": "1" + } + ] + } + }, + { + "listValue": { + "values": [ + { + "int64Value": "2" + } + ] + } + } + ] + } + } + }, + { + "name": "adjacent_macros", + "expr": "cel.block([[1, 2, 3], cel.index(0).map(cel.iterVar(0, 0), cel.index(0).map(cel.iterVar(1, 0), cel.iterVar(1, 0) + 1))], cel.index(1) == cel.index(1))", + "value": { + "boolValue": true + } + }, + { + "name": "macro_shadowed_variable_1", + "expr": "cel.block([x - 1, cel.index(0) > 3], [cel.index(1) ? cel.index(0) : 5].exists(cel.iterVar(0, 0), cel.iterVar(0, 0) - 1 > 3) || cel.index(1))", + "bindings": { + "x": { + "value": { + "int64Value": "5" + } + } + }, + "value": { + "boolValue": true + } + }, + { + "name": "macro_shadowed_variable_2", + "expr": "['foo', 'bar'].map(cel.iterVar(1, 0), [cel.iterVar(1, 0) + cel.iterVar(1, 0), cel.iterVar(1, 0) + cel.iterVar(1, 0)]).map(cel.iterVar(0, 0), [cel.iterVar(0, 0) + cel.iterVar(0, 0), cel.iterVar(0, 0) + cel.iterVar(0, 0)])", + "bindings": { + "x": { + "value": { + "int64Value": "5" + } + } + }, + "value": { + "listValue": { + "values": [ + { + "listValue": { + "values": [ + { + "listValue": { + "values": [ + { + "stringValue": "foofoo" + }, + { + "stringValue": "foofoo" + }, + { + "stringValue": "foofoo" + }, + { + "stringValue": "foofoo" + } + ] + } + }, + { + "listValue": { + "values": [ + { + "stringValue": "foofoo" + }, + { + "stringValue": "foofoo" + }, + { + "stringValue": "foofoo" + }, + { + "stringValue": "foofoo" + } + ] + } + } + ] + } + }, + { + "listValue": { + "values": [ + { + "listValue": { + "values": [ + { + "stringValue": "barbar" + }, + { + "stringValue": "barbar" + }, + { + "stringValue": "barbar" + }, + { + "stringValue": "barbar" + } + ] + } + }, + { + "listValue": { + "values": [ + { + "stringValue": "barbar" + }, + { + "stringValue": "barbar" + }, + { + "stringValue": "barbar" + }, + { + "stringValue": "barbar" + } + ] + } + } + ] + } + } + ] + } + } + }, + { + "name": "inclusion_list", + "expr": "cel.block([[1, 2, 3], 1 in cel.index(0), 2 in cel.index(0), cel.index(1) && cel.index(2), [3, cel.index(0)], 3 in cel.index(4), cel.index(5) && cel.index(1)], cel.index(3) && cel.index(6))", + "value": { + "boolValue": true + } + }, + { + "name": "inclusion_map", + "expr": "cel.block([{true: false}, {\"a\": 1, 2: cel.index(0), 3: cel.index(0)}], 2 in cel.index(1))", + "value": { + "boolValue": true + } + }, + { + "name": "presence_test", + "expr": "cel.block([{\"a\": true}, has(cel.index(0).a), cel.index(0)[\"a\"]], cel.index(1) && cel.index(2))", + "value": { + "boolValue": true + } + }, + { + "name": "presence_test_2", + "expr": "cel.block([{\"a\": true}, has(cel.index(0).a)], cel.index(1) && cel.index(1))", + "value": { + "boolValue": true + } + }, + { + "name": "presence_test_with_ternary", + "expr": "cel.block([msg.oneof_type, has(cel.index(0).payload), cel.index(0).payload, cel.index(2).single_int64, cel.index(1) ? cel.index(3) : 0], cel.index(4))", + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt32": 5, + "singleInt64": "3", + "oneofType": { + "payload": { + "singleInt32": 8, + "singleInt64": "10", + "mapInt32Int64": { + "0": "1", + "1": "5", + "2": "2" + }, + "mapStringString": { + "key": "A" + } + } + } + } + } + } + }, + "value": { + "int64Value": "10" + } + }, + { + "name": "presence_test_with_ternary_2", + "expr": "cel.block([msg.oneof_type, cel.index(0).payload, cel.index(1).single_int64, has(cel.index(0).payload), cel.index(2) * 0, cel.index(3) ? cel.index(2) : cel.index(4)], cel.index(5))", + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt32": 5, + "singleInt64": "3", + "oneofType": { + "payload": { + "singleInt32": 8, + "singleInt64": "10", + "mapInt32Int64": { + "0": "1", + "1": "5", + "2": "2" + }, + "mapStringString": { + "key": "A" + } + } + } + } + } + } + }, + "value": { + "int64Value": "10" + } + }, + { + "name": "presence_test_with_ternary_3", + "expr": "cel.block([msg.oneof_type, cel.index(0).payload, cel.index(1).single_int64, has(cel.index(1).single_int64), cel.index(2) * 0, cel.index(3) ? cel.index(2) : cel.index(4)], cel.index(5))", + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt32": 5, + "singleInt64": "3", + "oneofType": { + "payload": { + "singleInt32": 8, + "singleInt64": "10", + "mapInt32Int64": { + "0": "1", + "1": "5", + "2": "2" + }, + "mapStringString": { + "key": "A" + } + } + } + } + } + } + }, + "value": { + "int64Value": "10" + } + }, + { + "name": "presence_test_with_ternary_nested", + "expr": "cel.block([msg.oneof_type, cel.index(0).payload, cel.index(1).map_string_string, has(msg.oneof_type), has(cel.index(0).payload), cel.index(3) && cel.index(4), has(cel.index(1).single_int64), cel.index(5) && cel.index(6), has(cel.index(1).map_string_string), has(cel.index(2).key), cel.index(8) && cel.index(9), cel.index(2).key, cel.index(11) == \"A\", cel.index(10) ? cel.index(12) : false], cel.index(7) ? cel.index(13) : false)", + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt32": 5, + "singleInt64": "3", + "oneofType": { + "payload": { + "singleInt32": 8, + "singleInt64": "10", + "mapInt32Int64": { + "0": "1", + "1": "5", + "2": "2" + }, + "mapStringString": { + "key": "A" + } + } + } + } + } + } + }, + "value": { + "boolValue": true + } + }, + { + "name": "optional_list", + "expr": "cel.block([optional.none(), [?cel.index(0), ?optional.of(opt_x)], [5], [10, ?cel.index(0), cel.index(1), cel.index(1)], [10, cel.index(2), cel.index(2)]], cel.index(3) == cel.index(4))", + "bindings": { + "opt_x": { + "value": { + "int64Value": "5" + } + } + }, + "value": { + "boolValue": true + } + }, + { + "name": "optional_map", + "expr": "cel.block([optional.of(\"hello\"), {?\"hello\": cel.index(0)}, cel.index(1)[\"hello\"], cel.index(2) + cel.index(2)], cel.index(3) == \"hellohello\")", + "value": { + "boolValue": true + } + }, + { + "name": "optional_map_chained", + "expr": "cel.block([{\"key\": \"test\"}, optional.of(\"test\"), {?\"key\": cel.index(1)}, cel.index(2)[?\"bogus\"], cel.index(0)[?\"bogus\"], cel.index(3).or(cel.index(4)), cel.index(0)[\"key\"], cel.index(5).orValue(cel.index(6))], cel.index(7))", + "value": { + "stringValue": "test" + } + }, + { + "name": "optional_message", + "expr": "cel.block([optional.ofNonZeroValue(1), optional.of(4), TestAllTypes{?single_int64: cel.index(0), ?single_int32: cel.index(1)}, cel.index(2).single_int32, cel.index(2).single_int64, cel.index(3) + cel.index(4)], cel.index(5))", + "container": "google.api.expr.test.v1.proto3", + "value": { + "int64Value": "5" + } + }, + { + "name": "call", + "expr": "cel.block([\"h\" + \"e\", cel.index(0) + \"l\", cel.index(1) + \"l\", cel.index(2) + \"o\", cel.index(3) + \" world\"], cel.index(4).matches(cel.index(3)))", + "value": { + "boolValue": true + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/block_ext.textproto b/packages/cel/src/lib/conformance/testdata/block_ext.textproto new file mode 100644 index 0000000..7c89739 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/block_ext.textproto @@ -0,0 +1,1011 @@ +# This conformance test relies on the test-only macros cel.block, cel.index, +# cel.iterVar, and cel.accuVar. These test-only macros allow excercising +# cel.block without the optimizers being present. +# `cel.block(l, e)` must rewrite itself to be `cel.block(l, e)` +# `cel.index(N)` must rewrite itself to `@indexN` +# `cel.iterVar(N, M)` must rewrite itself to `@it:N:M` +# `cel.accuVar(N, M)` must rewrite itself to `@ac:N:M` + +name: "block_ext" +description: "Tests for cel.block." +section: { + name: "basic" + test: { + name: "int_add" + expr: "cel.block([1, cel.index(0) + 1, cel.index(1) + 1, cel.index(2) + 1], cel.index(3))" + value: { + int64_value: 4 + } + } + test: { + name: "size_1" + expr: "cel.block([[1, 2], size(cel.index(0)), cel.index(1) + cel.index(1), cel.index(2) + 1], cel.index(3))" + value: { + int64_value: 5 + } + } + test: { + name: "size_2" + expr: "cel.block([[1, 2], size(cel.index(0)), 2 + cel.index(1), cel.index(2) + cel.index(1), cel.index(3) + 1], cel.index(4))" + value: { + int64_value: 7 + } + } + test: { + name: "size_3" + expr: "cel.block([[0], size(cel.index(0)), [1, 2], size(cel.index(2)), cel.index(1) + cel.index(1), cel.index(4) + cel.index(3), cel.index(5) + cel.index(3)], cel.index(6))" + value: { + int64_value: 6 + } + } + test: { + name: "size_4" + expr: "cel.block([[0], size(cel.index(0)), [1, 2], size(cel.index(2)), [1, 2, 3], size(cel.index(4)), 5 + cel.index(1), cel.index(6) + cel.index(1), cel.index(7) + cel.index(3), cel.index(8) + cel.index(3), cel.index(9) + cel.index(5), cel.index(10) + cel.index(5)], cel.index(11))" + value: { + int64_value: 17 + } + } + test: { + name: "timestamp" + expr: "cel.block([timestamp(1000000000), int(cel.index(0)), timestamp(cel.index(1)), cel.index(2).getFullYear(), timestamp(50), int(cel.index(4)), timestamp(cel.index(5)), timestamp(200), int(cel.index(7)), timestamp(cel.index(8)), cel.index(9).getFullYear(), timestamp(75), int(cel.index(11)), timestamp(cel.index(12)), cel.index(13).getFullYear(), cel.index(3) + cel.index(14), cel.index(6).getFullYear(), cel.index(15) + cel.index(16), cel.index(17) + cel.index(3), cel.index(6).getSeconds(), cel.index(18) + cel.index(19), cel.index(20) + cel.index(10), cel.index(21) + cel.index(10), cel.index(13).getMinutes(), cel.index(22) + cel.index(23), cel.index(24) + cel.index(3)], cel.index(25))" + value: { + int64_value: 13934 + } + } + test: { + name: "map_index" + expr: "cel.block([{\"a\": 2}, cel.index(0)[\"a\"], cel.index(1) * cel.index(1), cel.index(1) + cel.index(2)], cel.index(3))" + value: { + int64_value: 6 + } + } + test: { + name: "nested_map_construction" + expr: "cel.block([{\"b\": 1}, {\"e\": cel.index(0)}], {\"a\": cel.index(0), \"c\": cel.index(0), \"d\": cel.index(1), \"e\": cel.index(1)})" + value: { + map_value: { + entries { + key: { + string_value: 'a' + } + value: { + map_value: { + entries { + key: { + string_value: 'b' + } + value: { + int64_value: 1 + } + } + } + } + } + entries { + key: { + string_value: 'c' + } + value: { + map_value: { + entries { + key: { + string_value: 'b' + } + value: { + int64_value: 1 + } + } + } + } + } + entries { + key: { + string_value: 'd' + } + value: { + map_value: { + entries { + key: { + string_value: 'e' + } + value: { + map_value: { + entries { + key: { + string_value: 'b' + } + value: { + int64_value: 1 + } + } + } + } + } + } + } + } + entries { + key: { + string_value: 'e' + } + value: { + map_value: { + entries { + key: { + string_value: 'e' + } + value: { + map_value: { + entries { + key: { + string_value: 'b' + } + value: { + int64_value: 1 + } + } + } + } + } + } + } + } + } + } + } + test: { + name: "nested_list_construction" + expr: "cel.block([[1, 2, 3, 4], [1, 2], [cel.index(1), cel.index(0)]], [1, cel.index(0), 2, cel.index(0), 5, cel.index(0), 7, cel.index(2), cel.index(1)])" + value: { + list_value: { + values { + int64_value: 1 + } + values { + list_value: { + values { + int64_value: 1 + } + values { + int64_value: 2 + } + values { + int64_value: 3 + } + values { + int64_value: 4 + } + } + } + values { + int64_value: 2 + } + values { + list_value: { + values { + int64_value: 1 + } + values { + int64_value: 2 + } + values { + int64_value: 3 + } + values { + int64_value: 4 + } + } + } + values { + int64_value: 5 + } + values { + list_value: { + values { + int64_value: 1 + } + values { + int64_value: 2 + } + values { + int64_value: 3 + } + values { + int64_value: 4 + } + } + } + values { + int64_value: 7 + } + values { + list_value: { + values { + list_value: { + values { + int64_value: 1 + } + values { + int64_value: 2 + } + } + } + values { + list_value: { + values { + int64_value: 1 + } + values { + int64_value: 2 + } + values { + int64_value: 3 + } + values { + int64_value: 4 + } + } + } + } + } + values { + list_value: { + values { + int64_value: 1 + } + values { + int64_value: 2 + } + } + } + } + } + } + test: { + name: "select" + expr: "cel.block([msg.single_int64, cel.index(0) + cel.index(0)], cel.index(1))" + value: { + int64_value: 6 + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_int64: 3 + single_int32: 5 + oneof_type: { + payload: { + single_int32: 8 + single_int64: 10 + map_int32_int64 { + key: 0 + value: 1 + } + map_int32_int64 { + key: 1 + value: 5 + } + map_int32_int64 { + key: 2 + value: 2 + } + map_string_string { + key: "key" + value: "A" + } + } + } + } + } + } + } + } + } + test: { + name: "select_nested_1" + expr: "cel.block([msg.oneof_type, cel.index(0).payload, cel.index(1).single_int64, cel.index(1).single_int32, cel.index(2) + cel.index(3), cel.index(4) + cel.index(2), msg.single_int64, cel.index(5) + cel.index(6), cel.index(1).oneof_type, cel.index(8).payload, cel.index(9).single_int64, cel.index(7) + cel.index(10)], cel.index(11))" + value: { + int64_value: 31 + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_int64: 3 + single_int32: 5 + oneof_type: { + payload: { + single_int32: 8 + single_int64: 10 + map_int32_int64 { + key: 0 + value: 1 + } + map_int32_int64 { + key: 1 + value: 5 + } + map_int32_int64 { + key: 2 + value: 2 + } + map_string_string { + key: "key" + value: "A" + } + } + } + } + } + } + } + } + } + test: { + name: "select_nested_2" + expr: "cel.block([msg.oneof_type, cel.index(0).payload, cel.index(1).oneof_type, cel.index(2).payload, cel.index(3).oneof_type, cel.index(4).payload, cel.index(5).oneof_type, cel.index(6).payload, cel.index(7).single_bool, true || cel.index(8), cel.index(4).child, cel.index(10).child, cel.index(11).payload, cel.index(12).single_bool], cel.index(9) || cel.index(13))" + value: { + bool_value: true + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_int64: 3 + single_int32: 5 + oneof_type: { + payload: { + single_int32: 8 + single_int64: 10 + map_int32_int64 { + key: 0 + value: 1 + } + map_int32_int64 { + key: 1 + value: 5 + } + map_int32_int64 { + key: 2 + value: 2 + } + map_string_string { + key: "key" + value: "A" + } + } + } + } + } + } + } + } + } + test: { + name: "select_nested_message_map_index_1" + expr: "cel.block([msg.oneof_type, cel.index(0).payload, cel.index(1).map_int32_int64, cel.index(2)[1], cel.index(3) + cel.index(3), cel.index(4) + cel.index(3)], cel.index(5))" + value: { + int64_value: 15 + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_int64: 3 + single_int32: 5 + oneof_type: { + payload: { + single_int32: 8 + single_int64: 10 + map_int32_int64 { + key: 0 + value: 1 + } + map_int32_int64 { + key: 1 + value: 5 + } + map_int32_int64 { + key: 2 + value: 2 + } + map_string_string { + key: "key" + value: "A" + } + } + } + } + } + } + } + } + } + test: { + name: "select_nested_message_map_index_2" + expr: "cel.block([msg.oneof_type, cel.index(0).payload, cel.index(1).map_int32_int64, cel.index(2)[0], cel.index(2)[1], cel.index(3) + cel.index(4), cel.index(2)[2], cel.index(5) + cel.index(6)], cel.index(7))" + value: { + int64_value: 8 + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_int64: 3 + single_int32: 5 + oneof_type: { + payload: { + single_int32: 8 + single_int64: 10 + map_int32_int64 { + key: 0 + value: 1 + } + map_int32_int64 { + key: 1 + value: 5 + } + map_int32_int64 { + key: 2 + value: 2 + } + map_string_string { + key: "key" + value: "A" + } + } + } + } + } + } + } + } + } + test: { + name: "ternary" + expr: "cel.block([msg.single_int64, cel.index(0) > 0, cel.index(1) ? cel.index(0) : 0], cel.index(2))" + value: { + int64_value: 3 + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_int64: 3 + single_int32: 5 + oneof_type: { + payload: { + single_int32: 8 + single_int64: 10 + map_int32_int64 { + key: 0 + value: 1 + } + map_int32_int64 { + key: 1 + value: 5 + } + map_int32_int64 { + key: 2 + value: 2 + } + map_string_string { + key: "key" + value: "A" + } + } + } + } + } + } + } + } + } + test: { + name: "nested_ternary" + expr: "cel.block([msg.single_int64, msg.single_int32, cel.index(0) > 0, cel.index(1) > 0, cel.index(0) + cel.index(1), cel.index(3) ? cel.index(4) : 0, cel.index(2) ? cel.index(5) : 0], cel.index(6))" + value: { + int64_value: 8 + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_int64: 3 + single_int32: 5 + oneof_type: { + payload: { + single_int32: 8 + single_int64: 10 + map_int32_int64 { + key: 0 + value: 1 + } + map_int32_int64 { + key: 1 + value: 5 + } + map_int32_int64 { + key: 2 + value: 2 + } + map_string_string { + key: "key" + value: "A" + } + } + } + } + } + } + } + } + } + test: { + name: "multiple_macros_1" + expr: "cel.block([[1].exists(cel.iterVar(0, 0), cel.iterVar(0, 0) > 0), size([cel.index(0)]), [2].exists(cel.iterVar(0, 0), cel.iterVar(0, 0) > 1), size([cel.index(2)])], cel.index(1) + cel.index(1) + cel.index(3) + cel.index(3))" + value: { + int64_value: 4 + } + } + test: { + name: "multiple_macros_2" + expr: "cel.block([[1].exists(cel.iterVar(0, 0), cel.iterVar(0, 0) > 0), [cel.index(0)], ['a'].exists(cel.iterVar(0, 1), cel.iterVar(0, 1) == 'a'), [cel.index(2)]], cel.index(1) + cel.index(1) + cel.index(3) + cel.index(3))" + value: { + list_value: { + values { + bool_value: true + } + values { + bool_value: true + } + values { + bool_value: true + } + values { + bool_value: true + } + } + } + } + test: { + name: "multiple_macros_3" + expr: "cel.block([[1].exists(cel.iterVar(0, 0), cel.iterVar(0, 0) > 0)], cel.index(0) && cel.index(0) && [1].exists(cel.iterVar(0, 0), cel.iterVar(0, 0) > 1) && [2].exists(cel.iterVar(0, 0), cel.iterVar(0, 0) > 1))" + value: { + bool_value: false + } + } + test: { + name: "nested_macros_1" + expr: "cel.block([[1, 2, 3]], cel.index(0).map(cel.iterVar(0, 0), cel.index(0).map(cel.iterVar(1, 0), cel.iterVar(1, 0) + 1)))" + value: { + list_value: { + values { + list_value: { + values { + int64_value: 2 + } + values { + int64_value: 3 + } + values { + int64_value: 4 + } + } + } + values { + list_value: { + values { + int64_value: 2 + } + values { + int64_value: 3 + } + values { + int64_value: 4 + } + } + } + values { + list_value: { + values { + int64_value: 2 + } + values { + int64_value: 3 + } + values { + int64_value: 4 + } + } + } + } + } + } + test: { + name: "nested_macros_2" + expr: "[1, 2].map(cel.iterVar(0, 0), [1, 2, 3].filter(cel.iterVar(1, 0), cel.iterVar(1, 0) == cel.iterVar(0, 0)))" + value: { + list_value: { + values { + list_value: { + values { + int64_value: 1 + } + } + } + values { + list_value: { + values { + int64_value: 2 + } + } + } + } + } + } + test: { + name: "adjacent_macros" + expr: "cel.block([[1, 2, 3], cel.index(0).map(cel.iterVar(0, 0), cel.index(0).map(cel.iterVar(1, 0), cel.iterVar(1, 0) + 1))], cel.index(1) == cel.index(1))" + value: { + bool_value: true + } + } + test: { + name: "macro_shadowed_variable_1" + expr: "cel.block([x - 1, cel.index(0) > 3], [cel.index(1) ? cel.index(0) : 5].exists(cel.iterVar(0, 0), cel.iterVar(0, 0) - 1 > 3) || cel.index(1))" + value: { + bool_value: true + } + bindings: { + key: "x" + value: { + value: { + int64_value: 5 + } + } + } + } + test: { + name: "macro_shadowed_variable_2" + expr: "['foo', 'bar'].map(cel.iterVar(1, 0), [cel.iterVar(1, 0) + cel.iterVar(1, 0), cel.iterVar(1, 0) + cel.iterVar(1, 0)]).map(cel.iterVar(0, 0), [cel.iterVar(0, 0) + cel.iterVar(0, 0), cel.iterVar(0, 0) + cel.iterVar(0, 0)])" + value: { + list_value: { + values { + list_value: { + values { + list_value: { + values { + string_value: "foofoo" + } + values { + string_value: "foofoo" + } + values { + string_value: "foofoo" + } + values { + string_value: "foofoo" + } + } + } + values { + list_value: { + values { + string_value: "foofoo" + } + values { + string_value: "foofoo" + } + values { + string_value: "foofoo" + } + values { + string_value: "foofoo" + } + } + } + } + } + values { + list_value: { + values { + list_value: { + values { + string_value: "barbar" + } + values { + string_value: "barbar" + } + values { + string_value: "barbar" + } + values { + string_value: "barbar" + } + } + } + values { + list_value: { + values { + string_value: "barbar" + } + values { + string_value: "barbar" + } + values { + string_value: "barbar" + } + values { + string_value: "barbar" + } + } + } + } + } + } + } + bindings: { + key: "x" + value: { + value: { + int64_value: 5 + } + } + } + } + test: { + name: "inclusion_list" + expr: "cel.block([[1, 2, 3], 1 in cel.index(0), 2 in cel.index(0), cel.index(1) && cel.index(2), [3, cel.index(0)], 3 in cel.index(4), cel.index(5) && cel.index(1)], cel.index(3) && cel.index(6))" + value: { + bool_value: true + } + } + test: { + name: "inclusion_map" + expr: "cel.block([{true: false}, {\"a\": 1, 2: cel.index(0), 3: cel.index(0)}], 2 in cel.index(1))" + value: { + bool_value: true + } + } + test: { + name: "presence_test" + expr: "cel.block([{\"a\": true}, has(cel.index(0).a), cel.index(0)[\"a\"]], cel.index(1) && cel.index(2))" + value: { + bool_value: true + } + } + test: { + name: "presence_test_2" + expr: "cel.block([{\"a\": true}, has(cel.index(0).a)], cel.index(1) && cel.index(1))" + value: { + bool_value: true + } + } + test: { + name: "presence_test_with_ternary" + expr: "cel.block([msg.oneof_type, has(cel.index(0).payload), cel.index(0).payload, cel.index(2).single_int64, cel.index(1) ? cel.index(3) : 0], cel.index(4))" + value: { + int64_value: 10 + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_int64: 3 + single_int32: 5 + oneof_type: { + payload: { + single_int32: 8 + single_int64: 10 + map_int32_int64 { + key: 0 + value: 1 + } + map_int32_int64 { + key: 1 + value: 5 + } + map_int32_int64 { + key: 2 + value: 2 + } + map_string_string { + key: "key" + value: "A" + } + } + } + } + } + } + } + } + } + test: { + name: "presence_test_with_ternary_2" + expr: "cel.block([msg.oneof_type, cel.index(0).payload, cel.index(1).single_int64, has(cel.index(0).payload), cel.index(2) * 0, cel.index(3) ? cel.index(2) : cel.index(4)], cel.index(5))" + value: { + int64_value: 10 + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_int64: 3 + single_int32: 5 + oneof_type: { + payload: { + single_int32: 8 + single_int64: 10 + map_int32_int64 { + key: 0 + value: 1 + } + map_int32_int64 { + key: 1 + value: 5 + } + map_int32_int64 { + key: 2 + value: 2 + } + map_string_string { + key: "key" + value: "A" + } + } + } + } + } + } + } + } + } + test: { + name: "presence_test_with_ternary_3" + expr: "cel.block([msg.oneof_type, cel.index(0).payload, cel.index(1).single_int64, has(cel.index(1).single_int64), cel.index(2) * 0, cel.index(3) ? cel.index(2) : cel.index(4)], cel.index(5))" + value: { + int64_value: 10 + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_int64: 3 + single_int32: 5 + oneof_type: { + payload: { + single_int32: 8 + single_int64: 10 + map_int32_int64 { + key: 0 + value: 1 + } + map_int32_int64 { + key: 1 + value: 5 + } + map_int32_int64 { + key: 2 + value: 2 + } + map_string_string { + key: "key" + value: "A" + } + } + } + } + } + } + } + } + } + test: { + name: "presence_test_with_ternary_nested" + expr: "cel.block([msg.oneof_type, cel.index(0).payload, cel.index(1).map_string_string, has(msg.oneof_type), has(cel.index(0).payload), cel.index(3) && cel.index(4), has(cel.index(1).single_int64), cel.index(5) && cel.index(6), has(cel.index(1).map_string_string), has(cel.index(2).key), cel.index(8) && cel.index(9), cel.index(2).key, cel.index(11) == \"A\", cel.index(10) ? cel.index(12) : false], cel.index(7) ? cel.index(13) : false)" + value: { + bool_value: true + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_int64: 3 + single_int32: 5 + oneof_type: { + payload: { + single_int32: 8 + single_int64: 10 + map_int32_int64 { + key: 0 + value: 1 + } + map_int32_int64 { + key: 1 + value: 5 + } + map_int32_int64 { + key: 2 + value: 2 + } + map_string_string { + key: "key" + value: "A" + } + } + } + } + } + } + } + } + } + test: { + name: "optional_list" + expr: "cel.block([optional.none(), [?cel.index(0), ?optional.of(opt_x)], [5], [10, ?cel.index(0), cel.index(1), cel.index(1)], [10, cel.index(2), cel.index(2)]], cel.index(3) == cel.index(4))" + value: { + bool_value: true + } + bindings: { + key: "opt_x", + value: { + value: { + int64_value: 5 + } + } + } + } + test: { + name: "optional_map" + expr: "cel.block([optional.of(\"hello\"), {?\"hello\": cel.index(0)}, cel.index(1)[\"hello\"], cel.index(2) + cel.index(2)], cel.index(3) == \"hellohello\")" + value: { + bool_value: true + } + } + test: { + name: "optional_map_chained" + expr: "cel.block([{\"key\": \"test\"}, optional.of(\"test\"), {?\"key\": cel.index(1)}, cel.index(2)[?\"bogus\"], cel.index(0)[?\"bogus\"], cel.index(3).or(cel.index(4)), cel.index(0)[\"key\"], cel.index(5).orValue(cel.index(6))], cel.index(7))" + value: { + string_value: 'test' + } + } + test: { + name: "optional_message" + container: "google.api.expr.test.v1.proto3" + expr: "cel.block([optional.ofNonZeroValue(1), optional.of(4), TestAllTypes{?single_int64: cel.index(0), ?single_int32: cel.index(1)}, cel.index(2).single_int32, cel.index(2).single_int64, cel.index(3) + cel.index(4)], cel.index(5))" + value: { + int64_value: 5 + } + } + test: { + name: "call" + expr: "cel.block([\"h\" + \"e\", cel.index(0) + \"l\", cel.index(1) + \"l\", cel.index(2) + \"o\", cel.index(3) + \" world\"], cel.index(4).matches(cel.index(3)))" + value: { + bool_value: true + } + } +} diff --git a/packages/cel/src/lib/conformance/testdata/comparisons.json b/packages/cel/src/lib/conformance/testdata/comparisons.json new file mode 100755 index 0000000..75be550 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/comparisons.json @@ -0,0 +1,3279 @@ +{ + "name": "comparisons", + "description": "Tests for boolean-valued functions and operators.", + "section": [ + { + "name": "eq_literal", + "description": "Literals comparison on _==_", + "test": [ + { + "name": "eq_int", + "expr": "1 == 1", + "value": { + "boolValue": true + } + }, + { + "name": "not_eq_int", + "expr": "-1 == 1", + "value": { + "boolValue": false + } + }, + { + "name": "eq_int_uint", + "expr": "dyn(1) == 1u", + "value": { + "boolValue": true + } + }, + { + "name": "not_eq_int_uint", + "expr": "dyn(2) == 1u", + "value": { + "boolValue": false + } + }, + { + "name": "eq_int_double", + "expr": "dyn(1) == 1.0", + "value": { + "boolValue": true + } + }, + { + "name": "not_eq_int_double", + "expr": "dyn(2) == 1.0", + "value": { + "boolValue": false + } + }, + { + "name": "eq_uint", + "expr": "2u == 2u", + "value": { + "boolValue": true + } + }, + { + "name": "not_eq_uint", + "expr": "1u == 2u", + "value": { + "boolValue": false + } + }, + { + "name": "eq_uint_int", + "expr": "dyn(1u) == 1", + "value": { + "boolValue": true + } + }, + { + "name": "not_eq_uint_int", + "expr": "dyn(2u) == 1", + "value": { + "boolValue": false + } + }, + { + "name": "eq_uint_double", + "expr": "dyn(1u) == 1.0", + "value": { + "boolValue": true + } + }, + { + "name": "not_eq_uint_double", + "expr": "dyn(2u) == 1.0", + "value": { + "boolValue": false + } + }, + { + "name": "eq_double", + "expr": "1.0 == 1.0e+0", + "value": { + "boolValue": true + } + }, + { + "name": "not_eq_double", + "expr": "-1.0 == 1.0", + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_double_nan", + "expr": "0.0/0.0 == 0.0/0.0", + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_int_double_nan", + "expr": "dyn(1) == 0.0/0.0", + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_uint_double_nan", + "expr": "dyn(1u) == 0.0/0.0", + "value": { + "boolValue": false + } + }, + { + "name": "eq_double_int", + "expr": "dyn(1.0) == 1", + "value": { + "boolValue": true + } + }, + { + "name": "not_eq_double_int", + "expr": "dyn(2.0) == 1", + "value": { + "boolValue": false + } + }, + { + "name": "eq_double_uint", + "expr": "dyn(1.0) == 1u", + "value": { + "boolValue": true + } + }, + { + "name": "not_eq_double_uint", + "expr": "dyn(2.0) == 1u", + "value": { + "boolValue": false + } + }, + { + "name": "eq_string", + "expr": "'' == \"\"", + "value": { + "boolValue": true + } + }, + { + "name": "not_eq_string", + "expr": "'a' == 'b'", + "value": { + "boolValue": false + } + }, + { + "name": "eq_raw_string", + "expr": "'abc' == r'abc'", + "value": { + "boolValue": true + } + }, + { + "name": "not_eq_string_case", + "expr": "'abc' == 'ABC'", + "value": { + "boolValue": false + } + }, + { + "name": "eq_string_unicode", + "expr": "'ίσος' == 'ίσος'", + "value": { + "boolValue": true + } + }, + { + "name": "not_eq_string_unicode_ascii", + "expr": "'a' == 'à'", + "value": { + "boolValue": false + } + }, + { + "name": "no_string_normalization", + "description": "Should not normalize Unicode.", + "expr": "'Am\\u00E9lie' == 'Ame\\u0301lie'", + "value": { + "boolValue": false + } + }, + { + "name": "no_string_normalization_surrogate", + "description": "Should not replace surrogate pairs.", + "expr": "'\\U0001F436' == '\\xef\\xbf\\xbd\\xef\\xbf\\bd'", + "value": { + "boolValue": false + } + }, + { + "name": "eq_null", + "expr": "null == null", + "value": { + "boolValue": true + } + }, + { + "name": "eq_bool", + "expr": "true == true", + "value": { + "boolValue": true + } + }, + { + "name": "not_eq_bool", + "expr": "false == true", + "value": { + "boolValue": false + } + }, + { + "name": "eq_bytes", + "description": "Test bytes literal equality with encoding", + "expr": "b'ÿ' == b'\\303\\277'", + "value": { + "boolValue": true + } + }, + { + "name": "not_eq_bytes", + "expr": "b'abc' == b'abcd'", + "value": { + "boolValue": false + } + }, + { + "name": "eq_list_empty", + "expr": "[] == []", + "value": { + "boolValue": true + } + }, + { + "name": "eq_list_null", + "expr": "[null] == [null]", + "value": { + "boolValue": true + } + }, + { + "name": "not_eq_list_null", + "expr": "['1', '2', null] == ['1', '2', '3']", + "value": { + "boolValue": false + } + }, + { + "name": "eq_list_numbers", + "expr": "[1, 2, 3] == [1, 2, 3]", + "value": { + "boolValue": true + } + }, + { + "name": "eq_list_mixed_type_numbers", + "expr": "[1.0, 2.0, 3] == [1u, 2, 3u]", + "value": { + "boolValue": true + } + }, + { + "name": "not_eq_list_mixed_type_numbers", + "expr": "[1.0, 2.1] == [1u, 2]", + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_list_order", + "expr": "[1, 2, 3] == [1, 3, 2]", + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_list_string_case", + "expr": "['case'] == ['cAse']", + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_list_length", + "expr": "['one'] == [2, 3]", + "disableCheck": true, + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_list_false_vs_types", + "expr": "[1, 'dos', 3] == [1, 2, 4]", + "value": { + "boolValue": false + } + }, + { + "name": "eq_map_empty", + "expr": "{} == {}", + "value": { + "boolValue": true + } + }, + { + "name": "eq_map_null", + "expr": "{'k': null} == {'k': null}", + "value": { + "boolValue": true + } + }, + { + "name": "not_eq_map_null", + "expr": "{'k': 1, 'j': 2} == {'k': 1, 'j': null}", + "value": { + "boolValue": false + } + }, + { + "name": "eq_map_onekey", + "expr": "{'k':'v'} == {\"k\":\"v\"}", + "value": { + "boolValue": true + } + }, + { + "name": "eq_map_double_value", + "expr": "{'k':1.0} == {'k':1e+0}", + "value": { + "boolValue": true + } + }, + { + "name": "eq_map_mixed_type_numbers", + "expr": "{1: 1.0, 2u: 3u} == {1u: 1, 2: 3.0}", + "value": { + "boolValue": true + } + }, + { + "name": "not_eq_map_value", + "expr": "{'k':'v'} == {'k':'v1'}", + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_map_extra_key", + "expr": "{'k':'v','k1':'v1'} == {'k':'v'}", + "value": { + "boolValue": false + } + }, + { + "name": "eq_map_key_order", + "expr": "{'k1':'v1','k2':'v2'} == {'k2':'v2','k1':'v1'}", + "value": { + "boolValue": true + } + }, + { + "name": "not_eq_map_key_casing", + "expr": "{'key':'value'} == {'Key':'value'}", + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_map_false_vs_types", + "expr": "{'k1': 1, 'k2': 'dos', 'k3': 3} == {'k1': 1, 'k2': 2, 'k3': 4}", + "value": { + "boolValue": false + } + }, + { + "name": "eq_mixed_types", + "expr": "1.0 == 1", + "disableCheck": true, + "value": { + "boolValue": true + } + }, + { + "name": "eq_list_elem_mixed_types", + "expr": "[1] == [1.0]", + "disableCheck": true, + "value": { + "boolValue": true + } + }, + { + "name": "eq_map_value_mixed_types", + "expr": "{'k':'v', 1:1} == {'k':'v', 1:'v1'}", + "value": { + "boolValue": false + } + }, + { + "name": "eq_dyn_json_null", + "expr": "dyn(google.protobuf.Value{}) == null", + "value": { + "boolValue": true + } + }, + { + "name": "not_eq_dyn_bool_null", + "expr": "dyn(false) == null", + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_dyn_bytes_null", + "expr": "dyn(b'') == null", + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_dyn_double_null", + "expr": "dyn(2.1) == null", + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_dyn_duration_null", + "expr": "dyn(duration('0s')) == null", + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_dyn_int_null", + "expr": "dyn(1) == null", + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_dyn_list_null", + "expr": "dyn([]) == null", + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_dyn_map_null", + "expr": "dyn({}) == null", + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_dyn_proto2_msg_null", + "expr": "dyn(TestAllTypes{}) == null", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_dyn_proto3_msg_null", + "expr": "dyn(TestAllTypes{}) == null", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_dyn_string_null", + "expr": "dyn('') == null", + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_dyn_timestamp_null", + "expr": "dyn(timestamp(0)) == null", + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_list_elem_null", + "expr": "[1, 2, null] == [1, null, 3]", + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_map_value_null", + "expr": "{1:'hello', 2:'world'} == {1:'goodbye', 2:null}", + "value": { + "boolValue": false + } + }, + { + "name": "eq_dyn_int_uint", + "expr": "dyn(1) == 1u", + "value": { + "boolValue": true + } + }, + { + "name": "eq_dyn_int_double", + "expr": "dyn(1) == 1.0", + "value": { + "boolValue": true + } + }, + { + "name": "eq_dyn_uint_int", + "expr": "dyn(1u) == 1", + "value": { + "boolValue": true + } + }, + { + "name": "eq_dyn_uint_double", + "expr": "dyn(1u) == 1.0", + "value": { + "boolValue": true + } + }, + { + "name": "eq_dyn_double_int", + "expr": "dyn(1.0) == 1", + "value": { + "boolValue": true + } + }, + { + "name": "eq_dyn_double_uint", + "expr": "dyn(1.0) == 1u", + "value": { + "boolValue": true + } + }, + { + "name": "not_eq_dyn_int_uint", + "expr": "dyn(1) == 2u", + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_dyn_int_double", + "expr": "dyn(1) == 2.0", + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_dyn_uint_int", + "expr": "dyn(1u) == 2", + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_dyn_uint_double", + "expr": "dyn(1u) == 120", + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_dyn_double_int", + "expr": "dyn(1.0) == 2", + "value": { + "boolValue": false + } + }, + { + "name": "not_eq_dyn_double_uint", + "expr": "dyn(1.0) == 2u", + "value": { + "boolValue": false + } + } + ] + }, + { + "name": "eq_wrapper", + "description": "Wrapper type comparison on _==_. Wrapper types treated as boxed primitives when they appear on message fields. An unset wrapper field should be treated as null. The tests show the distinction between unset, empty, and set equality behavior.", + "test": [ + { + "name": "eq_bool", + "expr": "google.protobuf.BoolValue{value: true} == true", + "value": { + "boolValue": true + } + }, + { + "name": "eq_bool_empty", + "expr": "google.protobuf.BoolValue{} == false", + "value": { + "boolValue": true + } + }, + { + "name": "eq_bool_not_null", + "expr": "google.protobuf.BoolValue{} != null", + "value": { + "boolValue": true + } + }, + { + "name": "eq_bool_proto2_null", + "expr": "TestAllTypes{}.single_bool_wrapper == null", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "eq_bool_proto3_null", + "expr": "TestAllTypes{}.single_bool_wrapper == null", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "eq_bytes", + "expr": "google.protobuf.BytesValue{value: b'set'} == b'set'", + "value": { + "boolValue": true + } + }, + { + "name": "eq_bytes_empty", + "expr": "google.protobuf.BytesValue{} == b''", + "value": { + "boolValue": true + } + }, + { + "name": "eq_bytes_not_null", + "expr": "google.protobuf.BytesValue{} != null", + "value": { + "boolValue": true + } + }, + { + "name": "eq_bytes_proto2_null", + "expr": "TestAllTypes{}.single_bytes_wrapper == null", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "eq_bytes_proto3_null", + "expr": "TestAllTypes{}.single_bytes_wrapper == null", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "eq_double", + "expr": "google.protobuf.DoubleValue{value: -1.175494e-40} == -1.175494e-40", + "value": { + "boolValue": true + } + }, + { + "name": "eq_double_empty", + "expr": "google.protobuf.DoubleValue{} == 0.0", + "value": { + "boolValue": true + } + }, + { + "name": "eq_double_not_null", + "expr": "google.protobuf.DoubleValue{} != null", + "value": { + "boolValue": true + } + }, + { + "name": "eq_double_proto2_null", + "expr": "TestAllTypes{}.single_double_wrapper == null", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "eq_double_proto3_null", + "expr": "TestAllTypes{}.single_double_wrapper == null", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "eq_float", + "expr": "google.protobuf.FloatValue{value: -1.5} == -1.5", + "value": { + "boolValue": true + } + }, + { + "name": "eq_float_empty", + "expr": "google.protobuf.FloatValue{} == 0.0", + "value": { + "boolValue": true + } + }, + { + "name": "eq_float_not_null", + "expr": "google.protobuf.FloatValue{} != null", + "value": { + "boolValue": true + } + }, + { + "name": "eq_float_proto2_null", + "expr": "TestAllTypes{}.single_float_wrapper == null", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "eq_float_proto3_null", + "expr": "TestAllTypes{}.single_float_wrapper == null", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "eq_int32", + "expr": "google.protobuf.Int32Value{value: 123} == 123", + "value": { + "boolValue": true + } + }, + { + "name": "eq_int32_empty", + "expr": "google.protobuf.Int32Value{} == 0", + "value": { + "boolValue": true + } + }, + { + "name": "eq_int32_not_null", + "expr": "google.protobuf.Int32Value{} != null", + "value": { + "boolValue": true + } + }, + { + "name": "eq_int32_proto2_null", + "expr": "TestAllTypes{}.single_int32_wrapper == null", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "eq_int32_proto3_null", + "expr": "TestAllTypes{}.single_int32_wrapper == null", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "eq_int64", + "expr": "google.protobuf.Int64Value{value: 2147483650} == 2147483650", + "value": { + "boolValue": true + } + }, + { + "name": "eq_int64_empty", + "expr": "google.protobuf.Int64Value{} == 0", + "value": { + "boolValue": true + } + }, + { + "name": "eq_int64_not_null", + "expr": "google.protobuf.Int64Value{} != null", + "value": { + "boolValue": true + } + }, + { + "name": "eq_int64_proto2_null", + "expr": "TestAllTypes{}.single_int64_wrapper == null", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "eq_int64_proto3_null", + "expr": "TestAllTypes{}.single_int64_wrapper == null", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "eq_string", + "expr": "google.protobuf.StringValue{value: 'set'} == 'set'", + "value": { + "boolValue": true + } + }, + { + "name": "eq_string_empty", + "expr": "google.protobuf.StringValue{} == ''", + "value": { + "boolValue": true + } + }, + { + "name": "eq_string_not_null", + "expr": "google.protobuf.StringValue{} != null", + "value": { + "boolValue": true + } + }, + { + "name": "eq_string_proto2_null", + "expr": "TestAllTypes{}.single_string_wrapper == null", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "eq_string_proto3_null", + "expr": "TestAllTypes{}.single_string_wrapper == null", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "eq_uint32", + "expr": "google.protobuf.UInt32Value{value: 42u} == 42u", + "value": { + "boolValue": true + } + }, + { + "name": "eq_uint32_empty", + "expr": "google.protobuf.UInt32Value{} == 0u", + "value": { + "boolValue": true + } + }, + { + "name": "eq_uint32_not_null", + "expr": "google.protobuf.UInt32Value{} != null", + "value": { + "boolValue": true + } + }, + { + "name": "eq_uint32_proto2_null", + "expr": "TestAllTypes{}.single_uint32_wrapper == null", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "eq_uint32_proto3_null", + "expr": "TestAllTypes{}.single_uint32_wrapper == null", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "eq_uint64", + "expr": "google.protobuf.UInt64Value{value: 4294967296u} == 4294967296u", + "value": { + "boolValue": true + } + }, + { + "name": "eq_uint64_empty", + "expr": "google.protobuf.UInt64Value{} == 0u", + "value": { + "boolValue": true + } + }, + { + "name": "eq_uint64_not_null", + "expr": "google.protobuf.UInt64Value{} != null", + "value": { + "boolValue": true + } + }, + { + "name": "eq_uint64_proto2_null", + "expr": "TestAllTypes{}.single_uint64_wrapper == null", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "eq_uint64_proto3_null", + "expr": "TestAllTypes{}.single_uint64_wrapper == null", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "eq_proto2", + "expr": "TestAllTypes{single_int64: 1234, single_string: '1234'} == TestAllTypes{single_int64: 1234, single_string: '1234'}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "eq_proto3", + "expr": "TestAllTypes{single_int64: 1234, single_string: '1234'} == TestAllTypes{single_int64: 1234, single_string: '1234'}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "eq_proto2_missing_fields_neq", + "expr": "TestAllTypes{single_int64: 1234} == TestAllTypes{single_string: '1234'}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": false + } + }, + { + "name": "eq_proto3_missing_fields_neq", + "expr": "TestAllTypes{single_int64: 1234} == TestAllTypes{single_string: '1234'}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": false + } + }, + { + "name": "eq_proto_nan_equal", + "description": "For proto equality, fields with NaN value are treated as not equal.", + "expr": "TestAllTypes{single_double: double('NaN')} == TestAllTypes{single_double: double('NaN')}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": false + } + }, + { + "name": "eq_proto_different_types", + "description": "At runtime, differently typed messages are treated as not equal.", + "expr": "dyn(TestAllTypes{}) == dyn(NestedTestAllTypes{})", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": false + } + }, + { + "name": "eq_proto2_any_unpack_equal", + "description": "Any values should be unpacked and compared.", + "expr": "TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001r\\0041234'}} == TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'r\\0041234\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001'}}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "eq_proto2_any_unpack_not_equal", + "description": "Any values should be unpacked and compared.", + "expr": "TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'a\\000\\000\\000\\000\\000H\\223\\300r\\0041234'}} == TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'r\\0041234\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001'}}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": false + } + }, + { + "name": "eq_proto2_any_unpack_bytewise_fallback_not_equal", + "description": "If an any field is missing its type_url, the comparison should fallback to a bytewise comparison of the serialized proto.", + "expr": "TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\242\\006\\023\\022\\021\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001r\\0041234'}} == TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\242\\006\\023\\022\\021r\\0041234\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001'}}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": false + } + }, + { + "name": "eq_proto2_any_unpack_bytewise_fallback_equal", + "description": "If an any field is missing its type_url, the comparison should fallback to a bytewise comparison of the serialized proto.", + "expr": "TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\242\\006\\023\\022\\021\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001r\\0041234'}} == TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\242\\006\\023\\022\\021\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001r\\0041234'}}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "eq_proto3_any_unpack_equal", + "description": "Any values should be unpacked and compared.", + "expr": "TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001r\\0041234'}} == TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'r\\0041234\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001'}}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "eq_proto3_any_unpack_not_equal", + "description": "Any values should be unpacked and compared.", + "expr": "TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'a\\000\\000\\000\\000\\000H\\223\\300r\\0041234'}} == TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'r\\0041234\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001'}}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": false + } + }, + { + "name": "eq_proto3_any_unpack_bytewise_fallback_not_equal", + "description": "If an any field is missing its type_url, the comparison should fallback to a bytewise comparison of the serialized proto.", + "expr": "TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\242\\006\\023\\022\\021\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001r\\0041234'}} == TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\242\\006\\023\\022\\021r\\0041234\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001'}}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": false + } + }, + { + "name": "eq_proto3_any_unpack_bytewise_fallback_equal", + "description": "If an any field is missing its type_url, the comparison should fallback to a bytewise comparison of the serialized proto.", + "expr": "TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\242\\006\\023\\022\\021\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001r\\0041234'}} == TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\242\\006\\023\\022\\021\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001r\\0041234'}}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "ne_literal", + "description": "Literals comparison on _!=_", + "test": [ + { + "name": "ne_int", + "expr": "24 != 42", + "value": { + "boolValue": true + } + }, + { + "name": "not_ne_int", + "expr": "1 != 1", + "value": { + "boolValue": false + } + }, + { + "name": "ne_int_double", + "expr": "dyn(24) != 24.1", + "value": { + "boolValue": true + } + }, + { + "name": "not_ne_int_double", + "expr": "dyn(1) != 1.0", + "value": { + "boolValue": false + } + }, + { + "name": "ne_int_uint", + "expr": "dyn(24) != 42u", + "value": { + "boolValue": true + } + }, + { + "name": "not_ne_int_uint", + "expr": "dyn(1) != 1u", + "value": { + "boolValue": false + } + }, + { + "name": "ne_uint", + "expr": "1u != 2u", + "value": { + "boolValue": true + } + }, + { + "name": "not_ne_uint", + "expr": "99u != 99u", + "value": { + "boolValue": false + } + }, + { + "name": "ne_uint_double", + "expr": "dyn(1u) != 2.0", + "value": { + "boolValue": true + } + }, + { + "name": "not_ne_uint_double", + "expr": "dyn(99u) != 99.0", + "value": { + "boolValue": false + } + }, + { + "name": "ne_double", + "expr": "9.0e+3 != 9001.0", + "value": { + "boolValue": true + } + }, + { + "name": "not_ne_double_nan", + "expr": "0.0/0.0 != 0.0/0.0", + "value": { + "boolValue": true + } + }, + { + "name": "not_ne_int_double_nan", + "expr": "dyn(1) != 0.0/0.0", + "value": { + "boolValue": true + } + }, + { + "name": "not_ne_uint_double_nan", + "expr": "dyn(1u) != 0.0/0.0", + "value": { + "boolValue": true + } + }, + { + "name": "not_ne_double", + "expr": "1.0 != 1e+0", + "value": { + "boolValue": false + } + }, + { + "name": "ne_double_int", + "expr": "dyn(9000) != 9001.0", + "value": { + "boolValue": true + } + }, + { + "name": "not_ne_double_int", + "expr": "dyn(1) != 1e+0", + "value": { + "boolValue": false + } + }, + { + "name": "ne_double_uint", + "expr": "dyn(9000u) != 9001.0", + "value": { + "boolValue": true + } + }, + { + "name": "not_ne_double_uint", + "expr": "dyn(1u) != 1e+0", + "value": { + "boolValue": false + } + }, + { + "name": "ne_double_nan", + "expr": "0.0/0.0 != 0.0/0.0", + "value": { + "boolValue": true + } + }, + { + "name": "ne_string", + "expr": "'abc' != ''", + "value": { + "boolValue": true + } + }, + { + "name": "not_ne_string", + "expr": "'abc' != 'abc'", + "value": { + "boolValue": false + } + }, + { + "name": "ne_string_unicode", + "expr": "'résumé' != 'resume'", + "value": { + "boolValue": true + } + }, + { + "name": "not_ne_string_unicode", + "expr": "'ίδιο' != 'ίδιο'", + "value": { + "boolValue": false + } + }, + { + "name": "ne_bytes", + "expr": "b'\\x00\\xFF' != b'ÿ'", + "value": { + "boolValue": true + } + }, + { + "name": "not_ne_bytes", + "expr": "b'\\303\\277' != b'ÿ'", + "value": { + "boolValue": false + } + }, + { + "name": "ne_bool", + "expr": "false != true", + "value": { + "boolValue": true + } + }, + { + "name": "not_ne_bool", + "expr": "true != true", + "value": { + "boolValue": false + } + }, + { + "name": "not_ne_null", + "description": "null can only be equal to null, or else it won't match", + "expr": "null != null", + "value": { + "boolValue": false + } + }, + { + "name": "ne_list_empty", + "expr": "[] != [1]", + "value": { + "boolValue": true + } + }, + { + "name": "not_ne_list_empty", + "expr": "[] != []", + "value": { + "boolValue": false + } + }, + { + "name": "ne_list_bool", + "expr": "[true, false, true] != [true, true, false]", + "value": { + "boolValue": true + } + }, + { + "name": "not_ne_list_bool", + "expr": "[false, true] != [false, true]", + "value": { + "boolValue": false + } + }, + { + "name": "not_ne_list_of_list", + "expr": "[[]] != [[]]", + "value": { + "boolValue": false + } + }, + { + "name": "ne_map_by_value", + "expr": "{'k':'v'} != {'k':'v1'}", + "value": { + "boolValue": true + } + }, + { + "name": "ne_map_by_key", + "expr": "{'k':true} != {'k1':true}", + "value": { + "boolValue": true + } + }, + { + "name": "not_ne_map_int_to_float", + "expr": "{1:1.0} != {1:1.0}", + "value": { + "boolValue": false + } + }, + { + "name": "not_ne_map_key_order", + "expr": "{'a':'b','c':'d'} != {'c':'d','a':'b'}", + "value": { + "boolValue": false + } + }, + { + "name": "ne_mixed_types", + "expr": "2u != 2", + "disableCheck": true, + "value": { + "boolValue": false + } + }, + { + "name": "ne_proto2", + "expr": "TestAllTypes{single_int64: 1234, single_string: '1234'} != TestAllTypes{single_int64: 1234, single_string: '1234'}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": false + } + }, + { + "name": "ne_proto3", + "expr": "TestAllTypes{single_int64: 1234, single_string: '1234'} != TestAllTypes{single_int64: 1234, single_string: '1234'}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": false + } + }, + { + "name": "ne_proto2_missing_fields_neq", + "expr": "TestAllTypes{single_int64: 1234} != TestAllTypes{single_string: '1234'}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "ne_proto3_missing_fields_neq", + "expr": "TestAllTypes{single_int64: 1234} != TestAllTypes{single_string: '1234'}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "ne_proto_nan_not_equal", + "description": "For proto equality, NaN field values are not considered equal.", + "expr": "TestAllTypes{single_double: double('NaN')} != TestAllTypes{single_double: double('NaN')}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "ne_proto_different_types", + "description": "At runtime, comparing differently typed messages is false.", + "expr": "dyn(TestAllTypes{}) != dyn(NestedTestAllTypes{})", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "ne_proto2_any_unpack", + "description": "Any values should be unpacked and compared.", + "expr": "TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001r\\0041234'}} != TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'r\\0041234\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001'}}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": false + } + }, + { + "name": "ne_proto2_any_unpack_bytewise_fallback", + "description": "If an any field is missing its type_url, the comparison should fallback to a bytewise comparison of the serialized proto.", + "expr": "TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\242\\006\\023\\022\\021\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001r\\0041234'}} != TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\242\\006\\023\\022\\021r\\0041234\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001'}}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "ne_proto3_any_unpack", + "description": "Any values should be unpacked and compared.", + "expr": "TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001r\\0041234'}} != TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'r\\0041234\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001'}}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": false + } + }, + { + "name": "ne_proto3_any_unpack_bytewise_fallback", + "description": "If an any field is missing its type_url, the comparison should fallback to a bytewise comparison of the serialized proto.", + "expr": "TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\242\\006\\023\\022\\021\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001r\\0041234'}} != TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\242\\006\\023\\022\\021r\\0041234\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001'}}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "lt_literal", + "description": "Literals comparison on _<_. (a < b) == (b > a) == !(a >= b) == !(b <= a)", + "test": [ + { + "name": "lt_int", + "expr": "-1 < 0", + "value": { + "boolValue": true + } + }, + { + "name": "not_lt_int", + "expr": "0 < 0", + "value": { + "boolValue": false + } + }, + { + "name": "lt_uint", + "expr": "0u < 1u", + "value": { + "boolValue": true + } + }, + { + "name": "not_lt_uint", + "expr": "2u < 2u", + "value": { + "boolValue": false + } + }, + { + "name": "lt_double", + "expr": "1.0 < 1.0000001", + "value": { + "boolValue": true + } + }, + { + "name": "not_lt_double", + "description": "Following IEEE 754, negative zero compares equal to zero", + "expr": "-0.0 < 0.0", + "value": { + "boolValue": false + } + }, + { + "name": "lt_string", + "expr": "'a' < 'b'", + "value": { + "boolValue": true + } + }, + { + "name": "lt_string_empty_to_nonempty", + "expr": "'' < 'a'", + "value": { + "boolValue": true + } + }, + { + "name": "lt_string_case", + "expr": "'Abc' < 'aBC'", + "value": { + "boolValue": true + } + }, + { + "name": "lt_string_length", + "expr": "'abc' < 'abcd'", + "value": { + "boolValue": true + } + }, + { + "name": "lt_string_diacritical_mark_sensitive", + "description": "Verifies that the we're not using a string comparison function that strips diacritical marks (á)", + "expr": "'a' < '\\u00E1'", + "value": { + "boolValue": true + } + }, + { + "name": "not_lt_string_empty", + "expr": "'' < ''", + "value": { + "boolValue": false + } + }, + { + "name": "not_lt_string_same", + "expr": "'abc' < 'abc'", + "value": { + "boolValue": false + } + }, + { + "name": "not_lt_string_case_length", + "expr": "'a' < 'AB'", + "value": { + "boolValue": false + } + }, + { + "name": "unicode_order_lexical", + "description": "Compare the actual code points of the string, instead of decomposing ế into 'e' plus accent modifiers.", + "expr": "'f' < '\\u1EBF'", + "value": { + "boolValue": true + } + }, + { + "name": "lt_bytes", + "expr": "b'a' < b'b'", + "value": { + "boolValue": true + } + }, + { + "name": "not_lt_bytes_same", + "expr": "b'abc' < b'abc'", + "value": { + "boolValue": false + } + }, + { + "name": "not_lt_bytes_width", + "expr": "b'á' < b'b'", + "value": { + "boolValue": false + } + }, + { + "name": "lt_bool_false_first", + "expr": "false < true", + "value": { + "boolValue": true + } + }, + { + "name": "not_lt_bool_same", + "expr": "true < true", + "value": { + "boolValue": false + } + }, + { + "name": "not_lt_bool_true_first", + "expr": "true < false", + "value": { + "boolValue": false + } + }, + { + "name": "lt_list_unsupported", + "expr": "[0] < [1]", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "lt_map_unsupported", + "expr": "{0:'a'} < {1:'b'}", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "lt_null_unsupported", + "description": "Ensure _<_ doesn't have a binding for null", + "expr": "null < null", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "lt_mixed_types_error", + "expr": "'foo' < 1024", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "lt_dyn_int_uint", + "expr": "dyn(1) < 2u", + "value": { + "boolValue": true + } + }, + { + "name": "lt_dyn_int_double", + "expr": "dyn(1) < 2.0", + "value": { + "boolValue": true + } + }, + { + "name": "lt_dyn_uint_int", + "expr": "dyn(1u) < 2", + "value": { + "boolValue": true + } + }, + { + "name": "lt_dyn_uint_double", + "expr": "dyn(1u) < 2.0", + "value": { + "boolValue": true + } + }, + { + "name": "lt_dyn_double_int", + "expr": "dyn(1.0) < 2", + "value": { + "boolValue": true + } + }, + { + "name": "lt_dyn_double_uint", + "expr": "dyn(1.0) < 2u", + "value": { + "boolValue": true + } + }, + { + "name": "not_lt_dyn_int_uint", + "expr": "dyn(1) < 1u", + "value": { + "boolValue": false + } + }, + { + "name": "not_lt_dyn_int_double", + "expr": "dyn(1) < 1.0", + "value": { + "boolValue": false + } + }, + { + "name": "not_lt_dyn_uint_int", + "expr": "dyn(1u) < 1", + "value": { + "boolValue": false + } + }, + { + "name": "not_lt_dyn_uint_double", + "expr": "dyn(1u) < 1.0", + "value": { + "boolValue": false + } + }, + { + "name": "not_lt_dyn_double_int", + "expr": "dyn(1.0) < 1", + "value": { + "boolValue": false + } + }, + { + "name": "not_lt_dyn_double_uint", + "expr": "dyn(1.0) < 1u", + "value": { + "boolValue": false + } + }, + { + "name": "lt_dyn_int_big_uint", + "expr": "dyn(1) < 9223372036854775808u", + "value": { + "boolValue": true + } + }, + { + "name": "lt_dyn_small_int_uint", + "expr": "dyn(-1) < 0u", + "value": { + "boolValue": true + } + }, + { + "name": "not_lt_dyn_int_big_lossy_double", + "expr": "dyn(9223372036854775807) < 9223372036854775808.0", + "value": { + "boolValue": false + } + }, + { + "name": "lt_dyn_int_big_lossy_double", + "expr": "dyn(9223372036854775807) < 9223372036854777857.0", + "value": { + "boolValue": true + } + }, + { + "name": "not_lt_dyn_int_small_double", + "expr": "dyn(9223372036854775807) < -9223372036854777857.0", + "value": { + "boolValue": false + } + }, + { + "name": "not_lt_dyn_int_small_lossy_double", + "expr": "dyn(-9223372036854775808) < -9223372036854775809.0", + "value": { + "boolValue": false + } + }, + { + "name": "not_lt_dyn_uint_small_int", + "expr": "dyn(1u) < -9223372036854775808", + "value": { + "boolValue": false + } + }, + { + "name": "not_lt_dyn_big_uint_int", + "expr": "dyn(9223372036854775808u) < 1", + "value": { + "boolValue": false + } + }, + { + "name": "not_lt_dyn_uint_small_double", + "expr": "dyn(18446744073709551615u) < -1.0", + "value": { + "boolValue": false + } + }, + { + "name": "lt_dyn_uint_big_double", + "expr": "dyn(18446744073709551615u) < 18446744073709590000.0", + "value": { + "boolValue": true + } + }, + { + "name": "not_lt_dyn_big_double_uint", + "expr": "dyn(18446744073709553665.0) < 18446744073709551615u", + "value": { + "boolValue": false + } + }, + { + "name": "not_lt_dyn_big_double_int", + "expr": "dyn(9223372036854775808.0) < 9223372036854775807", + "value": { + "boolValue": false + } + }, + { + "name": "not_lt_dyn_small_double_int", + "expr": "dyn(-9223372036854775809.0) < -9223372036854775808", + "value": { + "boolValue": false + } + } + ] + }, + { + "name": "gt_literal", + "description": "Literals comparison on _>_", + "test": [ + { + "name": "gt_int", + "expr": "42 > -42", + "value": { + "boolValue": true + } + }, + { + "name": "not_gt_int", + "expr": "0 > 0", + "value": { + "boolValue": false + } + }, + { + "name": "gt_uint", + "expr": "48u > 46u", + "value": { + "boolValue": true + } + }, + { + "name": "not_gt_uint", + "expr": "0u > 999u", + "value": { + "boolValue": false + } + }, + { + "name": "gt_double", + "expr": "1e+1 > 1e+0", + "value": { + "boolValue": true + } + }, + { + "name": "not_gt_double", + "expr": ".99 > 9.9e-1", + "value": { + "boolValue": false + } + }, + { + "name": "gt_string_case", + "expr": "'abc' > 'aBc'", + "value": { + "boolValue": true + } + }, + { + "name": "gt_string_to_empty", + "expr": "'A' > ''", + "value": { + "boolValue": true + } + }, + { + "name": "not_gt_string_empty_to_empty", + "expr": "'' > ''", + "value": { + "boolValue": false + } + }, + { + "name": "gt_string_unicode", + "expr": "'α' > 'omega'", + "value": { + "boolValue": true + } + }, + { + "name": "gt_bytes_one", + "expr": "b'\u0001' > b'\u0000'", + "value": { + "boolValue": true + } + }, + { + "name": "gt_bytes_one_to_empty", + "expr": "b'\u0000' > b''", + "value": { + "boolValue": true + } + }, + { + "name": "not_gt_bytes_sorting", + "expr": "b'\u0000\u0001' > b'\u0001'", + "value": { + "boolValue": false + } + }, + { + "name": "gt_bool_true_false", + "expr": "true > false", + "value": { + "boolValue": true + } + }, + { + "name": "not_gt_bool_false_true", + "expr": "false > true", + "value": { + "boolValue": false + } + }, + { + "name": "not_gt_bool_same", + "expr": "true > true", + "value": { + "boolValue": false + } + }, + { + "name": "gt_null_unsupported", + "expr": "null > null", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "gt_list_unsupported", + "expr": "[1] > [0]", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "gt_map_unsupported", + "expr": "{1:'b'} > {0:'a'}", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "gt_mixed_types_error", + "expr": "'foo' > 1024", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "gt_dyn_int_uint", + "expr": "dyn(2) > 1u", + "value": { + "boolValue": true + } + }, + { + "name": "gt_dyn_int_double", + "expr": "dyn(2) > 1.0", + "value": { + "boolValue": true + } + }, + { + "name": "gt_dyn_uint_int", + "expr": "dyn(2u) > 1", + "value": { + "boolValue": true + } + }, + { + "name": "gt_dyn_uint_double", + "expr": "dyn(2u) > 1.0", + "value": { + "boolValue": true + } + }, + { + "name": "gt_dyn_double_int", + "expr": "dyn(2.0) > 1", + "value": { + "boolValue": true + } + }, + { + "name": "gt_dyn_double_uint", + "expr": "dyn(2.0) > 1u", + "value": { + "boolValue": true + } + }, + { + "name": "not_gt_dyn_int_uint", + "expr": "dyn(1) > 1u", + "value": { + "boolValue": false + } + }, + { + "name": "not_gt_dyn_int_double", + "expr": "dyn(1) > 1.0", + "value": { + "boolValue": false + } + }, + { + "name": "not_gt_dyn_uint_int", + "expr": "dyn(1u) > 1", + "value": { + "boolValue": false + } + }, + { + "name": "not_gt_dyn_uint_double", + "expr": "dyn(1u) > 1.0", + "value": { + "boolValue": false + } + }, + { + "name": "not_gt_dyn_double_int", + "expr": "dyn(1.0) > 1", + "value": { + "boolValue": false + } + }, + { + "name": "not_gt_dyn_double_uint", + "expr": "dyn(1.0) > 1u", + "value": { + "boolValue": false + } + }, + { + "name": "not_gt_dyn_int_big_uint", + "expr": "dyn(1) > 9223372036854775808u", + "value": { + "boolValue": false + } + }, + { + "name": "not_gt_dyn_small_int_uint", + "expr": "dyn(-1) > 0u", + "value": { + "boolValue": false + } + }, + { + "name": "not_gt_dyn_int_big_double", + "expr": "dyn(9223372036854775807) > 9223372036854775808.0", + "value": { + "boolValue": false + } + }, + { + "name": "not_gt_dyn_int_small_lossy_double", + "description": "The conversion of the int to double is lossy and the numbers end up being equal", + "expr": "dyn(-9223372036854775808) > -9223372036854775809.0", + "value": { + "boolValue": false + } + }, + { + "name": "gt_dyn_int_small_lossy_double_greater", + "expr": "dyn(-9223372036854775808) > -9223372036854777857.0", + "value": { + "boolValue": true + } + }, + { + "name": "gt_dyn_uint_small_int", + "expr": "dyn(1u) > -1", + "value": { + "boolValue": true + } + }, + { + "name": "gt_dyn_big_uint_int", + "expr": "dyn(9223372036854775808u) > 1", + "value": { + "boolValue": true + } + }, + { + "name": "gt_dyn_uint_small_double", + "expr": "dyn(9223372036854775807u) > -1.0", + "value": { + "boolValue": true + } + }, + { + "name": "not_gt_dyn_uint_big_double", + "expr": "dyn(18446744073709551615u) > 18446744073709590000.0", + "value": { + "boolValue": false + } + }, + { + "name": "gt_dyn_big_double_uint", + "expr": "dyn(18446744073709553665.0) > 18446744073709551615u", + "value": { + "boolValue": true + } + }, + { + "name": "not_gt_dyn_big_double_int", + "expr": "dyn(9223372036854775808.0) > 9223372036854775807", + "value": { + "boolValue": false + } + }, + { + "name": "not_gt_dyn_small_double_int", + "expr": "dyn(-9223372036854775809.0) > -9223372036854775808", + "value": { + "boolValue": false + } + } + ] + }, + { + "name": "lte_literal", + "description": "Literals comparison on _<=_", + "test": [ + { + "name": "lte_int_lt", + "expr": "0 <= 1", + "value": { + "boolValue": true + } + }, + { + "name": "lte_int_eq", + "expr": "1 <= 1", + "value": { + "boolValue": true + } + }, + { + "name": "not_lte_int_gt", + "expr": "1 <= -1", + "value": { + "boolValue": false + } + }, + { + "name": "lte_uint_lt", + "expr": "0u <= 1u", + "value": { + "boolValue": true + } + }, + { + "name": "lte_uint_eq", + "expr": "1u <= 1u", + "value": { + "boolValue": true + } + }, + { + "name": "not_lte_uint_gt", + "expr": "1u <= 0u", + "value": { + "boolValue": false + } + }, + { + "name": "lte_double_lt", + "expr": "0.0 <= 0.1e-31", + "value": { + "boolValue": true + } + }, + { + "name": "lte_double_eq", + "expr": "0.0 <= 0e-1", + "value": { + "boolValue": true + } + }, + { + "name": "not_lte_double_gt", + "expr": "1.0 <= 0.99", + "value": { + "boolValue": false + } + }, + { + "name": "lte_string_empty", + "expr": "'' <= ''", + "value": { + "boolValue": true + } + }, + { + "name": "lte_string_from_empty", + "expr": "'' <= 'a'", + "value": { + "boolValue": true + } + }, + { + "name": "not_lte_string_to_empty", + "expr": "'a' <= ''", + "value": { + "boolValue": false + } + }, + { + "name": "lte_string_lexicographical", + "expr": "'aBc' <= 'abc'", + "value": { + "boolValue": true + } + }, + { + "name": "lte_string_unicode_eq", + "expr": "'α' <= 'α'", + "value": { + "boolValue": true + } + }, + { + "name": "lte_string_unicode_lt", + "expr": "'a' <= 'α'", + "value": { + "boolValue": true + } + }, + { + "name": "not_lte_string_unicode", + "expr": "'α' <= 'a'", + "value": { + "boolValue": false + } + }, + { + "name": "lte_bytes_empty", + "expr": "b'' <= b'\u0000'", + "value": { + "boolValue": true + } + }, + { + "name": "not_lte_bytes_length", + "expr": "b'\u0001\u0000' <= b'\u0001'", + "value": { + "boolValue": false + } + }, + { + "name": "lte_bool_false_true", + "expr": "false <= true", + "value": { + "boolValue": true + } + }, + { + "name": "lte_bool_false_false", + "expr": "false <= false", + "value": { + "boolValue": true + } + }, + { + "name": "lte_bool_true_false", + "expr": "true <= false", + "value": { + "boolValue": false + } + }, + { + "name": "lte_null_unsupported", + "expr": "null <= null", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "lte_list_unsupported", + "expr": "[0] <= [0]", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "lte_map_unsupported", + "expr": "{0:'a'} <= {1:'b'}", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "lte_mixed_types_error", + "expr": "'foo' <= 1024", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "lte_dyn_int_uint", + "expr": "dyn(1) <= 2u", + "value": { + "boolValue": true + } + }, + { + "name": "lte_dyn_int_double", + "expr": "dyn(1) <= 2.0", + "value": { + "boolValue": true + } + }, + { + "name": "lte_dyn_uint_int", + "expr": "dyn(1u) <= 2", + "value": { + "boolValue": true + } + }, + { + "name": "lte_dyn_uint_double", + "expr": "dyn(1u) <= 2.0", + "value": { + "boolValue": true + } + }, + { + "name": "lte_dyn_double_int", + "expr": "dyn(1.0) <= 2", + "value": { + "boolValue": true + } + }, + { + "name": "lte_dyn_double_uint", + "expr": "dyn(1.0) <= 2u", + "value": { + "boolValue": true + } + }, + { + "name": "not_lte_dyn_int_uint", + "expr": "dyn(2) <= 1u", + "value": { + "boolValue": false + } + }, + { + "name": "not_lte_dyn_int_double", + "expr": "dyn(2) <= 1.0", + "value": { + "boolValue": false + } + }, + { + "name": "not_lte_dyn_uint_int", + "expr": "dyn(2u) <= 1", + "value": { + "boolValue": false + } + }, + { + "name": "not_lte_dyn_uint_double", + "expr": "dyn(2u) <= 1.0", + "value": { + "boolValue": false + } + }, + { + "name": "not_lte_dyn_double_int", + "expr": "dyn(2.0) <= 1", + "value": { + "boolValue": false + } + }, + { + "name": "not_lte_dyn_double_uint", + "expr": "dyn(2.0) <= 1u", + "value": { + "boolValue": false + } + }, + { + "name": "lte_dyn_int_big_uint", + "expr": "dyn(1) <= 9223372036854775808u", + "value": { + "boolValue": true + } + }, + { + "name": "lte_dyn_small_int_uint", + "expr": "dyn(-1) <= 0u", + "value": { + "boolValue": true + } + }, + { + "name": "lte_dyn_int_big_double", + "expr": "dyn(9223372036854775807) <= 9223372036854775808.0", + "value": { + "boolValue": true + } + }, + { + "name": "lte_dyn_int_small_lossy_double", + "description": "The conversion of the int to double is lossy and the numbers end up being equal", + "expr": "dyn(-9223372036854775808) <= -9223372036854775809.0", + "value": { + "boolValue": true + } + }, + { + "name": "not_lte_dyn_int_small_lossy_double_less", + "expr": "dyn(-9223372036854775808) <= -9223372036854777857.0", + "value": { + "boolValue": false + } + }, + { + "name": "not_lte_dyn_uint_small_int", + "expr": "dyn(1u) <= -9223372036854775808", + "value": { + "boolValue": false + } + }, + { + "name": "not_lte_dyn_big_uint_int", + "expr": "dyn(9223372036854775808u) <= 1", + "value": { + "boolValue": false + } + }, + { + "name": "not_lte_dyn_uint_small_double", + "expr": "dyn(18446744073709551615u) <= -1.0", + "value": { + "boolValue": false + } + }, + { + "name": "lte_dyn_uint_big_double", + "expr": "dyn(18446744073709551615u) <= 18446744073709590000.0", + "value": { + "boolValue": true + } + }, + { + "name": "not_lte_dyn_big_double_uint", + "expr": "dyn(18446744073709553665.0) <= 18446744073709551615u", + "value": { + "boolValue": false + } + }, + { + "name": "lte_dyn_big_double_int", + "expr": "dyn(9223372036854775808.0) <= 9223372036854775807", + "value": { + "boolValue": true + } + }, + { + "name": "lte_dyn_small_double_int", + "expr": "dyn(-9223372036854775809.0) <= -9223372036854775808", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "gte_literal", + "description": "Literals comparison on _>=_", + "test": [ + { + "name": "gte_int_gt", + "expr": "0 >= -1", + "value": { + "boolValue": true + } + }, + { + "name": "gte_int_eq", + "expr": "999 >= 999", + "value": { + "boolValue": true + } + }, + { + "name": "not_gte_int_lt", + "expr": "999 >= 1000", + "value": { + "boolValue": false + } + }, + { + "name": "gte_uint_gt", + "expr": "1u >= 0u", + "value": { + "boolValue": true + } + }, + { + "name": "gte_uint_eq", + "expr": "0u >= 0u", + "value": { + "boolValue": true + } + }, + { + "name": "not_gte_uint_lt", + "expr": "1u >= 10u", + "value": { + "boolValue": false + } + }, + { + "name": "gte_double_gt", + "expr": "1e+1 >= 1e+0", + "value": { + "boolValue": true + } + }, + { + "name": "gte_double_eq", + "expr": "9.80665 >= 9.80665e+0", + "value": { + "boolValue": true + } + }, + { + "name": "not_gte_double_lt", + "expr": "0.9999 >= 1.0", + "value": { + "boolValue": false + } + }, + { + "name": "gte_string_empty", + "expr": "'' >= ''", + "value": { + "boolValue": true + } + }, + { + "name": "gte_string_to_empty", + "expr": "'a' >= ''", + "value": { + "boolValue": true + } + }, + { + "name": "gte_string_empty_to_nonempty", + "expr": "'' >= 'a'", + "value": { + "boolValue": false + } + }, + { + "name": "gte_string_length", + "expr": "'abcd' >= 'abc'", + "value": { + "boolValue": true + } + }, + { + "name": "not_gte_string_lexicographical", + "expr": "'abc' >= 'abd'", + "value": { + "boolValue": false + } + }, + { + "name": "gte_string_unicode_eq", + "expr": "'τ' >= 'τ'", + "value": { + "boolValue": true + } + }, + { + "name": "gte_string_unicode_gt", + "expr": "'τ' >= 't'", + "value": { + "boolValue": true + } + }, + { + "name": "not_get_string_unicode", + "expr": "'t' >= 'τ'", + "value": { + "boolValue": false + } + }, + { + "name": "gte_bytes_to_empty", + "expr": "b'\u0000' >= b''", + "value": { + "boolValue": true + } + }, + { + "name": "not_gte_bytes_empty_to_nonempty", + "expr": "b'' >= b'\u0000'", + "value": { + "boolValue": false + } + }, + { + "name": "gte_bytes_samelength", + "expr": "b'\u0000\u0001' >= b'\u0001\u0000'", + "value": { + "boolValue": false + } + }, + { + "name": "gte_bool_gt", + "expr": "true >= false", + "value": { + "boolValue": true + } + }, + { + "name": "gte_bool_eq", + "expr": "true >= true", + "value": { + "boolValue": true + } + }, + { + "name": "not_gte_bool_lt", + "expr": "false >= true", + "value": { + "boolValue": false + } + }, + { + "name": "gte_null_unsupported", + "expr": "null >= null", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "gte_list_unsupported", + "expr": "['y'] >= ['x']", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "gte_map_unsupported", + "expr": "{1:'b'} >= {0:'a'}", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "gte_mixed_types_error", + "expr": "'foo' >= 1.0", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "gte_dyn_int_uint", + "expr": "dyn(2) >= 1u", + "value": { + "boolValue": true + } + }, + { + "name": "gte_dyn_int_double", + "expr": "dyn(2) >= 1.0", + "value": { + "boolValue": true + } + }, + { + "name": "gte_dyn_uint_int", + "expr": "dyn(2u) >= 1", + "value": { + "boolValue": true + } + }, + { + "name": "gte_dyn_uint_double", + "expr": "dyn(2u) >= 1.0", + "value": { + "boolValue": true + } + }, + { + "name": "gte_dyn_double_int", + "expr": "dyn(2.0) >= 1", + "value": { + "boolValue": true + } + }, + { + "name": "gte_dyn_double_uint", + "expr": "dyn(2.0) >= 1u", + "value": { + "boolValue": true + } + }, + { + "name": "not_gte_dyn_int_uint", + "expr": "dyn(0) >= 1u", + "value": { + "boolValue": false + } + }, + { + "name": "not_gte_dyn_int_double", + "expr": "dyn(0) >= 1.0", + "value": { + "boolValue": false + } + }, + { + "name": "not_gte_dyn_uint_int", + "expr": "dyn(0u) >= 1", + "value": { + "boolValue": false + } + }, + { + "name": "not_gte_dyn_uint_double", + "expr": "dyn(0u) >= 1.0", + "value": { + "boolValue": false + } + }, + { + "name": "not_gte_dyn_double_int", + "expr": "dyn(0.0) >= 1", + "value": { + "boolValue": false + } + }, + { + "name": "not_gte_dyn_double_uint", + "expr": "dyn(0.0) >= 1u", + "value": { + "boolValue": false + } + }, + { + "name": "not_gte_dyn_int_big_uint", + "expr": "dyn(1) >= 9223372036854775808u", + "value": { + "boolValue": false + } + }, + { + "name": "not_gte_dyn_small_int_uint", + "expr": "dyn(-1) >= 0u", + "value": { + "boolValue": false + } + }, + { + "name": "gte_dyn_int_big_lossy_double", + "expr": "dyn(9223372036854775807) >= 9223372036854775808.0", + "value": { + "boolValue": true + } + }, + { + "name": "not_gte_dyn_int_big_double", + "expr": "dyn(9223372036854775807) >= 9223372036854777857.0", + "value": { + "boolValue": false + } + }, + { + "name": "gte_dyn_int_small_lossy_double_equal", + "description": "The conversion of the int to double is lossy and the numbers end up being equal", + "expr": "dyn(-9223372036854775808) >= -9223372036854775809.0", + "value": { + "boolValue": true + } + }, + { + "name": "gte_dyn_int_small_lossy_double_greater", + "expr": "dyn(-9223372036854775808) >= -9223372036854777857.0", + "value": { + "boolValue": true + } + }, + { + "name": "gte_dyn_uint_small_int", + "expr": "dyn(1u) >= -1", + "value": { + "boolValue": true + } + }, + { + "name": "gte_dyn_big_uint_int", + "expr": "dyn(9223372036854775808u) >= 1", + "value": { + "boolValue": true + } + }, + { + "name": "gte_dyn_uint_small_double", + "expr": "dyn(9223372036854775807u) >= -1.0", + "value": { + "boolValue": true + } + }, + { + "name": "not_gte_dyn_uint_big_double", + "expr": "dyn(18446744073709551615u) >= 18446744073709553665.0", + "value": { + "boolValue": false + } + }, + { + "name": "gte_dyn_big_double_uint", + "expr": "dyn(18446744073709553665.0) >= 18446744073709551615u", + "value": { + "boolValue": true + } + }, + { + "name": "gte_dyn_big_double_int", + "expr": "dyn(9223372036854775808.0) >= 9223372036854775807", + "value": { + "boolValue": true + } + }, + { + "name": "gte_dyn_small_double_int", + "expr": "dyn(-9223372036854775809.0) >= -9223372036854775808", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "in_list_literal", + "description": "Set membership tests using list literals and the 'in' operator", + "test": [ + { + "name": "elem_not_in_empty_list", + "expr": "'empty' in []", + "value": { + "boolValue": false + } + }, + { + "name": "elem_in_list", + "expr": "'elem' in ['elem', 'elemA', 'elemB']", + "value": { + "boolValue": true + } + }, + { + "name": "elem_not_in_list", + "expr": "'not' in ['elem1', 'elem2', 'elem3']", + "value": { + "boolValue": false + } + }, + { + "name": "elem_in_mixed_type_list", + "description": "Set membership tests should succeed if the 'elem' exists in a mixed element type list.", + "expr": "'elem' in [1, 'elem', 2]", + "value": { + "boolValue": true + } + }, + { + "name": "elem_in_mixed_type_list_cross_type", + "description": "Set membership tests should return false due to the introduction of heterogeneous-equality. Set membership via 'in' is equivalent to the macro exists() behavior.", + "expr": "'elem' in [1u, 'str', 2, b'bytes']", + "value": { + "boolValue": false + } + } + ] + }, + { + "name": "in_map_literal", + "description": "Set membership tests using map literals and the 'in' operator", + "test": [ + { + "name": "key_not_in_empty_map", + "expr": "'empty' in {}", + "value": { + "boolValue": false + } + }, + { + "name": "key_in_map", + "expr": "'key' in {'key':'1', 'other':'2'}", + "value": { + "boolValue": true + } + }, + { + "name": "key_not_in_map", + "expr": "'key' in {'lock':1, 'gate':2}", + "value": { + "boolValue": false + } + }, + { + "name": "key_in_mixed_key_type_map", + "description": "Map keys are of mixed type, but since the key is present the result is true.", + "expr": "'key' in {3:3.0, 'key':2u}", + "value": { + "boolValue": true + } + }, + { + "name": "key_in_mixed_key_type_map_cross_type", + "expr": "'key' in {1u:'str', 2:b'bytes'}", + "value": { + "boolValue": false + } + } + ] + }, + { + "name": "bound", + "description": "Comparing bound variables with literals or other variables", + "test": [ + { + "name": "bytes_gt_left_false", + "expr": "x > b'\u0000'", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "primitive": "BYTES" + } + } + } + ], + "bindings": { + "x": { + "value": { + "bytesValue": "AA==" + } + } + }, + "value": { + "boolValue": false + } + }, + { + "name": "int_lte_right_true", + "expr": "123 <= x", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "primitive": "INT64" + } + } + } + ], + "bindings": { + "x": { + "value": { + "int64Value": "124" + } + } + }, + "value": { + "boolValue": true + } + }, + { + "name": "bool_lt_right_true", + "expr": "false < x", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "primitive": "BOOL" + } + } + } + ], + "bindings": { + "x": { + "value": { + "boolValue": true + } + } + }, + "value": { + "boolValue": true + } + }, + { + "name": "double_ne_left_false", + "expr": "x != 9.8", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "primitive": "DOUBLE" + } + } + } + ], + "bindings": { + "x": { + "value": { + "doubleValue": 9.8 + } + } + }, + "value": { + "boolValue": false + } + }, + { + "name": "map_ne_right_false", + "expr": "{'a':'b','c':'d'} != x", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "mapType": { + "keyType": { + "primitive": "STRING" + }, + "valueType": { + "primitive": "STRING" + } + } + } + } + } + ], + "bindings": { + "x": { + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "c" + }, + "value": { + "stringValue": "d" + } + }, + { + "key": { + "stringValue": "a" + }, + "value": { + "stringValue": "b" + } + } + ] + } + } + } + }, + "value": { + "boolValue": false + } + }, + { + "name": "null_eq_left_true", + "description": "A comparison _==_ against null only binds if the type is determined to be null or we skip the type checking", + "expr": "x == null", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "null": null + } + } + } + ], + "bindings": { + "x": { + "value": { + "nullValue": null + } + } + }, + "value": { + "boolValue": true + } + }, + { + "name": "list_eq_right_false", + "expr": "[1, 2] == x", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "listType": { + "elemType": { + "primitive": "INT64" + } + } + } + } + } + ], + "bindings": { + "x": { + "value": { + "listValue": { + "values": [ + { + "int64Value": "2" + }, + { + "int64Value": "1" + } + ] + } + } + } + }, + "value": { + "boolValue": false + } + }, + { + "name": "string_gte_right_true", + "expr": "'abcd' >= x", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "primitive": "STRING" + } + } + } + ], + "bindings": { + "x": { + "value": { + "stringValue": "abc" + } + } + }, + "value": { + "boolValue": true + } + }, + { + "name": "uint_eq_right_false", + "expr": "999u == x", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "primitive": "UINT64" + } + } + } + ], + "bindings": { + "x": { + "value": { + "uint64Value": "1000" + } + } + }, + "value": { + "boolValue": false + } + }, + { + "name": "null_lt_right_no_such_overload", + "description": "There is no _<_ operation for null, even if both operands are null", + "expr": "null < x", + "disableCheck": true, + "bindings": { + "x": { + "value": { + "nullValue": null + } + } + }, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/comparisons.textproto b/packages/cel/src/lib/conformance/testdata/comparisons.textproto new file mode 100644 index 0000000..7bae66d --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/comparisons.textproto @@ -0,0 +1,2373 @@ +name: "comparisons" +description: "Tests for boolean-valued functions and operators." +section { + name: "eq_literal" + description: "Literals comparison on _==_" + test { + name: "eq_int" + expr: "1 == 1" + value: { bool_value: true } + } + test { + name: "not_eq_int" + expr: "-1 == 1" + value: { bool_value: false } + } + test { + name: "eq_int_uint" + expr: "dyn(1) == 1u" + value: { bool_value: true } + } + test { + name: "not_eq_int_uint" + expr: "dyn(2) == 1u" + value: { bool_value: false } + } + test { + name: "eq_int_double" + expr: "dyn(1) == 1.0" + value: { bool_value: true } + } + test { + name: "not_eq_int_double" + expr: "dyn(2) == 1.0" + value: { bool_value: false } + } + test { + name: "eq_uint" + expr: "2u == 2u" + value: { bool_value: true } + } + test { + name: "not_eq_uint" + expr: "1u == 2u" + value: { bool_value: false } + } + test { + name: "eq_uint_int" + expr: "dyn(1u) == 1" + value: { bool_value: true } + } + test { + name: "not_eq_uint_int" + expr: "dyn(2u) == 1" + value: { bool_value: false } + } + test { + name: "eq_uint_double" + expr: "dyn(1u) == 1.0" + value: { bool_value: true } + } + test { + name: "not_eq_uint_double" + expr: "dyn(2u) == 1.0" + value: { bool_value: false } + } + test { + name: "eq_double" + expr: "1.0 == 1.0e+0" + value: { bool_value: true } + } + test { + name: "not_eq_double" + expr: "-1.0 == 1.0" + value: { bool_value: false } + } + test { + name: "not_eq_double_nan" + expr: "0.0/0.0 == 0.0/0.0" + value: { bool_value: false } + } + test { + name: "not_eq_int_double_nan" + expr: "dyn(1) == 0.0/0.0" + value: { bool_value: false } + } + test { + name: "not_eq_uint_double_nan" + expr: "dyn(1u) == 0.0/0.0" + value: { bool_value: false } + } + test { + name: "eq_double_int" + expr: "dyn(1.0) == 1" + value: { bool_value: true } + } + test { + name: "not_eq_double_int" + expr: "dyn(2.0) == 1" + value: { bool_value: false } + } + test { + name: "eq_double_uint" + expr: "dyn(1.0) == 1u" + value: { bool_value: true } + } + test { + name: "not_eq_double_uint" + expr: "dyn(2.0) == 1u" + value: { bool_value: false } + } + test { + name: "eq_string" + expr: "'' == \"\"" + value: { bool_value: true } + } + test { + name: "not_eq_string" + expr: "'a' == 'b'" + value: { bool_value: false } + } + test { + name: "eq_raw_string" + expr: "'abc' == r'abc'" + value: { bool_value: true } + } + test { + name: "not_eq_string_case" + expr: "'abc' == 'ABC'" + value: { bool_value: false } + } + test { + name: "eq_string_unicode" + expr: "'ίσος' == 'ίσος'" + value: { bool_value: true } + } + test { + name: "not_eq_string_unicode_ascii" + expr: "'a' == 'à'" + value: { bool_value: false } + } + test { + name: "no_string_normalization" + description: "Should not normalize Unicode." + expr: "'Am\\u00E9lie' == 'Ame\\u0301lie'" + value: { bool_value: false } + } + test { + name: "no_string_normalization_surrogate" + description: "Should not replace surrogate pairs." + expr: "'\\U0001F436' == '\\xef\\xbf\\xbd\\xef\\xbf\\bd'" + value: { bool_value: false } + } + test { + name: "eq_null" + expr: "null == null" + value: { bool_value: true } + } + test { + name: "eq_bool" + expr: "true == true" + value: { bool_value: true } + } + test { + name: "not_eq_bool" + expr: "false == true" + value: { bool_value: false } + } + test { + name: "eq_bytes" + description: "Test bytes literal equality with encoding" + expr: "b'ÿ' == b'\\303\\277'" + value: { bool_value: true } + } + test { + name: "not_eq_bytes" + expr: "b'abc' == b'abcd'" + value: { bool_value: false } + } + test { + name: "eq_list_empty" + expr: "[] == []" + value: { bool_value: true } + } + test { + name: "eq_list_null" + expr: "[null] == [null]" + value: { bool_value: true } + } + test { + name: "not_eq_list_null" + expr: "['1', '2', null] == ['1', '2', '3']" + value: { bool_value: false } + } + test { + name: "eq_list_numbers" + expr: "[1, 2, 3] == [1, 2, 3]" + value: { bool_value: true } + } + test { + name: "eq_list_mixed_type_numbers" + expr: "[1.0, 2.0, 3] == [1u, 2, 3u]" + value: { bool_value: true } + } + test { + name: "not_eq_list_mixed_type_numbers" + expr: "[1.0, 2.1] == [1u, 2]" + value: { bool_value: false } + } + test { + name: "not_eq_list_order" + expr: "[1, 2, 3] == [1, 3, 2]" + value: { bool_value: false } + } + test { + name: "not_eq_list_string_case" + expr: "['case'] == ['cAse']" + value: { bool_value: false } + } + test { + name: "not_eq_list_length" + expr: "['one'] == [2, 3]" + disable_check: true + value: { bool_value: false } + } + test { + name: "not_eq_list_false_vs_types" + expr: "[1, 'dos', 3] == [1, 2, 4]" + value: { bool_value: false } + } + test { + name: "eq_map_empty" + expr: "{} == {}" + value: { bool_value: true } + } + test { + name: "eq_map_null" + expr: "{'k': null} == {'k': null}" + value: { bool_value: true } + } + test { + name: "not_eq_map_null" + expr: "{'k': 1, 'j': 2} == {'k': 1, 'j': null}" + value: { bool_value: false } + } + test { + name: "eq_map_onekey" + expr: "{'k':'v'} == {\"k\":\"v\"}" + value: { bool_value: true } + } + test { + name: "eq_map_double_value" + expr: "{'k':1.0} == {'k':1e+0}" + value: { bool_value: true } + } + test { + name: "eq_map_mixed_type_numbers" + expr: "{1: 1.0, 2u: 3u} == {1u: 1, 2: 3.0}" + value: { bool_value: true } + } + test { + name: "not_eq_map_value" + expr: "{'k':'v'} == {'k':'v1'}" + value: { bool_value: false } + } + test { + name: "not_eq_map_extra_key" + expr: "{'k':'v','k1':'v1'} == {'k':'v'}" + value: { bool_value: false } + } + test { + name: "eq_map_key_order" + expr: "{'k1':'v1','k2':'v2'} == {'k2':'v2','k1':'v1'}" + value: { bool_value: true } + } + test { + name: "not_eq_map_key_casing" + expr: "{'key':'value'} == {'Key':'value'}" + value: { bool_value: false } + } + test { + name: "not_eq_map_false_vs_types" + expr: "{'k1': 1, 'k2': 'dos', 'k3': 3} == {'k1': 1, 'k2': 2, 'k3': 4}" + value: { bool_value: false } + } + test { + name: "eq_mixed_types" + expr: "1.0 == 1" + disable_check: true # need to make it fail in the evaluation phase + value: { bool_value: true } + } + test { + name: "eq_list_elem_mixed_types" + expr: "[1] == [1.0]" + disable_check: true # need to make it fail in the evaluation phase + value: { bool_value: true } + } + test { + name: "eq_map_value_mixed_types" + expr: "{'k':'v', 1:1} == {'k':'v', 1:'v1'}" + value: { bool_value: false } + } + test { + name: "eq_dyn_json_null" + expr: "dyn(google.protobuf.Value{}) == null" + value: { bool_value: true } + } + test { + name: "not_eq_dyn_bool_null" + expr: "dyn(false) == null" + value: { bool_value: false } + } + test { + name: "not_eq_dyn_bytes_null" + expr: "dyn(b'') == null" + value: { bool_value: false } + } + test { + name: "not_eq_dyn_double_null" + expr: "dyn(2.1) == null" + value: { bool_value: false } + } + test { + name: "not_eq_dyn_duration_null" + expr: "dyn(duration('0s')) == null" + value: { bool_value: false } + } + test { + name: "not_eq_dyn_int_null" + expr: "dyn(1) == null" + value: { bool_value: false } + } + test { + name: "not_eq_dyn_list_null" + expr: "dyn([]) == null" + value: { bool_value: false } + } + test { + name: "not_eq_dyn_map_null" + expr: "dyn({}) == null" + value: { bool_value: false } + } + test { + name: "not_eq_dyn_proto2_msg_null" + container: "google.api.expr.test.v1.proto2" + expr: "dyn(TestAllTypes{}) == null" + value: { bool_value: false } + } + test { + name: "not_eq_dyn_proto3_msg_null" + container: "google.api.expr.test.v1.proto3" + expr: "dyn(TestAllTypes{}) == null" + value: { bool_value: false } + } + test { + name: "not_eq_dyn_string_null" + expr: "dyn('') == null" + value: { bool_value: false } + } + test { + name: "not_eq_dyn_timestamp_null" + expr: "dyn(timestamp(0)) == null" + value: { bool_value: false } + } + test { + name: "not_eq_list_elem_null" + expr: "[1, 2, null] == [1, null, 3]" + value: { bool_value: false } + } + test { + name: "not_eq_map_value_null" + expr: "{1:'hello', 2:'world'} == {1:'goodbye', 2:null}" + value: { bool_value: false } + } + test { + name: "eq_dyn_int_uint" + expr: "dyn(1) == 1u" + value: { bool_value: true } + } + test { + name: "eq_dyn_int_double" + expr: "dyn(1) == 1.0" + value: { bool_value: true } + } + test { + name: "eq_dyn_uint_int" + expr: "dyn(1u) == 1" + value: { bool_value: true } + } + test { + name: "eq_dyn_uint_double" + expr: "dyn(1u) == 1.0" + value: { bool_value: true } + } + test { + name: "eq_dyn_double_int" + expr: "dyn(1.0) == 1" + value: { bool_value: true } + } + test { + name: "eq_dyn_double_uint" + expr: "dyn(1.0) == 1u" + value: { bool_value: true } + } + test { + name: "not_eq_dyn_int_uint" + expr: "dyn(1) == 2u" + value: { bool_value: false } + } + test { + name: "not_eq_dyn_int_double" + expr: "dyn(1) == 2.0" + value: { bool_value: false } + } + test { + name: "not_eq_dyn_uint_int" + expr: "dyn(1u) == 2" + value: { bool_value: false } + } + test { + name: "not_eq_dyn_uint_double" + expr: "dyn(1u) == 120" + value: { bool_value: false } + } + test { + name: "not_eq_dyn_double_int" + expr: "dyn(1.0) == 2" + value: { bool_value: false } + } + test { + name: "not_eq_dyn_double_uint" + expr: "dyn(1.0) == 2u" + value: { bool_value: false } + } +} +section { + name: "eq_wrapper" + description: "Wrapper type comparison on _==_. Wrapper types treated as boxed primitives when they appear on message fields. An unset wrapper field should be treated as null. The tests show the distinction between unset, empty, and set equality behavior." + test { + name: "eq_bool" + expr: "google.protobuf.BoolValue{value: true} == true" + value: { bool_value: true } + } + test { + name: "eq_bool_empty" + expr: "google.protobuf.BoolValue{} == false" + value: { bool_value: true } + } + test { + name: "eq_bool_not_null" + expr: "google.protobuf.BoolValue{} != null" + value: { bool_value: true } + } + test { + name: "eq_bool_proto2_null" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.single_bool_wrapper == null" + value: { bool_value: true } + } + test { + name: "eq_bool_proto3_null" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.single_bool_wrapper == null" + value: { bool_value: true } + } + + test { + name: "eq_bytes" + expr: "google.protobuf.BytesValue{value: b'set'} == b'set'" + value: { bool_value: true } + } + test { + name: "eq_bytes_empty" + expr: "google.protobuf.BytesValue{} == b''" + value: { bool_value: true } + } + test { + name: "eq_bytes_not_null" + expr: "google.protobuf.BytesValue{} != null" + value: { bool_value: true } + } + test { + name: "eq_bytes_proto2_null" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.single_bytes_wrapper == null" + value: { bool_value: true } + } + test { + name: "eq_bytes_proto3_null" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.single_bytes_wrapper == null" + value: { bool_value: true } + } + + test { + name: "eq_double" + expr: "google.protobuf.DoubleValue{value: -1.175494e-40} == -1.175494e-40" + value: { bool_value: true } + } + test { + name: "eq_double_empty" + expr: "google.protobuf.DoubleValue{} == 0.0" + value: { bool_value: true } + } + test { + name: "eq_double_not_null" + expr: "google.protobuf.DoubleValue{} != null" + value: { bool_value: true } + } + test { + name: "eq_double_proto2_null" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.single_double_wrapper == null" + value: { bool_value: true } + } + test { + name: "eq_double_proto3_null" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.single_double_wrapper == null" + value: { bool_value: true } + } + + test { + name: "eq_float" + expr: "google.protobuf.FloatValue{value: -1.5} == -1.5" + value: { bool_value: true } + } + test { + name: "eq_float_empty" + expr: "google.protobuf.FloatValue{} == 0.0" + value: { bool_value: true } + } + test { + name: "eq_float_not_null" + expr: "google.protobuf.FloatValue{} != null" + value: { bool_value: true } + } + test { + name: "eq_float_proto2_null" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.single_float_wrapper == null" + value: { bool_value: true } + } + test { + name: "eq_float_proto3_null" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.single_float_wrapper == null" + value: { bool_value: true } + } + + test { + name: "eq_int32" + expr: "google.protobuf.Int32Value{value: 123} == 123" + value: { bool_value: true } + } + test { + name: "eq_int32_empty" + expr: "google.protobuf.Int32Value{} == 0" + value: { bool_value: true } + } + test { + name: "eq_int32_not_null" + expr: "google.protobuf.Int32Value{} != null" + value: { bool_value: true } + } + test { + name: "eq_int32_proto2_null" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.single_int32_wrapper == null" + value: { bool_value: true } + } + test { + name: "eq_int32_proto3_null" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.single_int32_wrapper == null" + value: { bool_value: true } + } + + test { + name: "eq_int64" + expr: "google.protobuf.Int64Value{value: 2147483650} == 2147483650" + value: { bool_value: true } + } + test { + name: "eq_int64_empty" + expr: "google.protobuf.Int64Value{} == 0" + value: { bool_value: true } + } + test { + name: "eq_int64_not_null" + expr: "google.protobuf.Int64Value{} != null" + value: { bool_value: true } + } + test { + name: "eq_int64_proto2_null" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.single_int64_wrapper == null" + value: { bool_value: true } + } + test { + name: "eq_int64_proto3_null" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.single_int64_wrapper == null" + value: { bool_value: true } + } + + test { + name: "eq_string" + expr: "google.protobuf.StringValue{value: 'set'} == 'set'" + value: { bool_value: true } + } + test { + name: "eq_string_empty" + expr: "google.protobuf.StringValue{} == ''" + value: { bool_value: true } + } + test { + name: "eq_string_not_null" + expr: "google.protobuf.StringValue{} != null" + value: { bool_value: true } + } + test { + name: "eq_string_proto2_null" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.single_string_wrapper == null" + value: { bool_value: true } + } + test { + name: "eq_string_proto3_null" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.single_string_wrapper == null" + value: { bool_value: true } + } + + test { + name: "eq_uint32" + expr: "google.protobuf.UInt32Value{value: 42u} == 42u" + value: { bool_value: true } + } + test { + name: "eq_uint32_empty" + expr: "google.protobuf.UInt32Value{} == 0u" + value: { bool_value: true } + } + test { + name: "eq_uint32_not_null" + expr: "google.protobuf.UInt32Value{} != null" + value: { bool_value: true } + } + test { + name: "eq_uint32_proto2_null" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.single_uint32_wrapper == null" + value: { bool_value: true } + } + test { + name: "eq_uint32_proto3_null" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.single_uint32_wrapper == null" + value: { bool_value: true } + } + + test { + name: "eq_uint64" + expr: "google.protobuf.UInt64Value{value: 4294967296u} == 4294967296u" + value: { bool_value: true } + } + test { + name: "eq_uint64_empty" + expr: "google.protobuf.UInt64Value{} == 0u" + value: { bool_value: true } + } + test { + name: "eq_uint64_not_null" + expr: "google.protobuf.UInt64Value{} != null" + value: { bool_value: true } + } + test { + name: "eq_uint64_proto2_null" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.single_uint64_wrapper == null" + value: { bool_value: true } + } + test { + name: "eq_uint64_proto3_null" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.single_uint64_wrapper == null" + value: { bool_value: true } + } + test { + name: "eq_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_int64: 1234, single_string: '1234'} == TestAllTypes{single_int64: 1234, single_string: '1234'}" + value { bool_value: true } + } + test { + name: "eq_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_int64: 1234, single_string: '1234'} == TestAllTypes{single_int64: 1234, single_string: '1234'}" + value { bool_value: true } + } + test { + name: "eq_proto2_missing_fields_neq" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_int64: 1234} == TestAllTypes{single_string: '1234'}" + value { bool_value: false } + } + test { + name: "eq_proto3_missing_fields_neq" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_int64: 1234} == TestAllTypes{single_string: '1234'}" + value { bool_value: false } + } + test { + name: "eq_proto_nan_equal" + container: "google.api.expr.test.v1.proto2" + description: "For proto equality, fields with NaN value are treated as not equal." + expr: "TestAllTypes{single_double: double('NaN')} == TestAllTypes{single_double: double('NaN')}" + value { bool_value: false } + } + test { + name: "eq_proto_different_types" + container: "google.api.expr.test.v1.proto2" + description: "At runtime, differently typed messages are treated as not equal." + expr: "dyn(TestAllTypes{}) == dyn(NestedTestAllTypes{})" + value { bool_value: false } + } + test { + name: "eq_proto2_any_unpack_equal" + description: "Any values should be unpacked and compared." + container: "google.api.expr.test.v1.proto2" + # Two equal messages with any fields serialized differently (but both are valid). + # TestAllTypes{single_any: [TestAllTypes]{single_int64: 1234, single_string: '1234'}} + expr: + "TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001r\\0041234'}} ==" + " TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'r\\0041234\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001'}}" + value { bool_value: true } + } + test { + name: "eq_proto2_any_unpack_not_equal" + description: "Any values should be unpacked and compared." + container: "google.api.expr.test.v1.proto2" + # Two messages with any fields that are not equal + # TestAllTypes{single_any: [TestAllTypes]{single_int64: 1234, single_string: '1234'}} + # TestAllTypes{single_any: [TestAllTypes]{single_double: -1234.0, single_string: '1234'}} + expr: + "TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'a\\000\\000\\000\\000\\000H\\223\\300r\\0041234'}} ==" + " TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'r\\0041234\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001'}}" + value { bool_value: false } + } + test { + name: "eq_proto2_any_unpack_bytewise_fallback_not_equal" + description: "If an any field is missing its type_url, the comparison should fallback to a bytewise comparison of the serialized proto." + container: "google.api.expr.test.v1.proto2" + # The missing type info any is doubly nested to skip create message validations. + expr: + "TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\242\\006\\023\\022\\021\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001r\\0041234'}} ==" + " TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\242\\006\\023\\022\\021r\\0041234\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001'}}" + value { bool_value: false } + } + test { + name: "eq_proto2_any_unpack_bytewise_fallback_equal" + description: "If an any field is missing its type_url, the comparison should fallback to a bytewise comparison of the serialized proto." + container: "google.api.expr.test.v1.proto2" + # The missing type info any is doubly nested to skip create message validations. + expr: + "TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\242\\006\\023\\022\\021\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001r\\0041234'}} ==" + " TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\242\\006\\023\\022\\021\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001r\\0041234'}}" + value { bool_value: true } + } + test { + name: "eq_proto3_any_unpack_equal" + description: "Any values should be unpacked and compared." + container: "google.api.expr.test.v1.proto3" + # Two equal messages with any fields serialized differently (but both are valid). + expr: + "TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001r\\0041234'}} ==" + " TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'r\\0041234\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001'}}" + value { bool_value: true } + } + test { + name: "eq_proto3_any_unpack_not_equal" + description: "Any values should be unpacked and compared." + container: "google.api.expr.test.v1.proto3" + # Two messages with any fields that are not equal + # TestAllTypes{single_any: [TestAllTypes]{single_int64: 1234, single_string: '1234'}} + # TestAllTypes{single_any: [TestAllTypes]{single_double: -1234.0, single_string: '1234'}} + expr: + "TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'a\\000\\000\\000\\000\\000H\\223\\300r\\0041234'}} ==" + " TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'r\\0041234\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001'}}" + value { bool_value: false } + } + test { + name: "eq_proto3_any_unpack_bytewise_fallback_not_equal" + description: "If an any field is missing its type_url, the comparison should fallback to a bytewise comparison of the serialized proto." + container: "google.api.expr.test.v1.proto3" + # The missing type info any is doubly nested to skip create message validations. + expr: + "TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\242\\006\\023\\022\\021\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001r\\0041234'}} ==" + " TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\242\\006\\023\\022\\021r\\0041234\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001'}}" + value { bool_value: false } + } + test { + name: "eq_proto3_any_unpack_bytewise_fallback_equal" + description: "If an any field is missing its type_url, the comparison should fallback to a bytewise comparison of the serialized proto." + container: "google.api.expr.test.v1.proto3" + # The missing type info any is doubly nested to skip create message validations. + expr: + "TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\242\\006\\023\\022\\021\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001r\\0041234'}} ==" + " TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\242\\006\\023\\022\\021\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001r\\0041234'}}" + value { bool_value: true } + } +} +section { + name: "ne_literal" + description: "Literals comparison on _!=_" + test { + name: "ne_int" + expr: "24 != 42" + value: { bool_value: true } + } + test { + name: "not_ne_int" + expr: "1 != 1" + value: { bool_value: false } + } + test { + name: "ne_int_double" + expr: "dyn(24) != 24.1" + value: { bool_value: true } + } + test { + name: "not_ne_int_double" + expr: "dyn(1) != 1.0" + value: { bool_value: false } + } + test { + name: "ne_int_uint" + expr: "dyn(24) != 42u" + value: { bool_value: true } + } + test { + name: "not_ne_int_uint" + expr: "dyn(1) != 1u" + value: { bool_value: false } + } + test { + name: "ne_uint" + expr: "1u != 2u" + value: { bool_value: true } + } + test { + name: "not_ne_uint" + expr: "99u != 99u" + value: { bool_value: false } + } + test { + name: "ne_uint_double" + expr: "dyn(1u) != 2.0" + value: { bool_value: true } + } + test { + name: "not_ne_uint_double" + expr: "dyn(99u) != 99.0" + value: { bool_value: false } + } + test { + name: "ne_double" + expr: "9.0e+3 != 9001.0" + value: { bool_value: true } + } + test { + name: "not_ne_double_nan" + expr: "0.0/0.0 != 0.0/0.0" + value: { bool_value: true } + } + test { + name: "not_ne_int_double_nan" + expr: "dyn(1) != 0.0/0.0" + value: { bool_value: true } + } + test { + name: "not_ne_uint_double_nan" + expr: "dyn(1u) != 0.0/0.0" + value: { bool_value: true } + } + test { + name: "not_ne_double" + expr: "1.0 != 1e+0" + value: { bool_value: false } + } + test { + name: "ne_double_int" + expr: "dyn(9000) != 9001.0" + value: { bool_value: true } + } + test { + name: "not_ne_double_int" + expr: "dyn(1) != 1e+0" + value: { bool_value: false } + } + test { + name: "ne_double_uint" + expr: "dyn(9000u) != 9001.0" + value: { bool_value: true } + } + test { + name: "not_ne_double_uint" + expr: "dyn(1u) != 1e+0" + value: { bool_value: false } + } + test { + name: "ne_double_nan" + expr: "0.0/0.0 != 0.0/0.0" + value: { bool_value: true } + } + test { + name: "ne_string" + expr: "'abc' != ''" + value: { bool_value: true } + } + test { + name: "not_ne_string" + expr: "'abc' != 'abc'" + value: { bool_value: false } + } + test { + name: "ne_string_unicode" + expr: "'résumé' != 'resume'" + value: { bool_value: true } + } + test { + name: "not_ne_string_unicode" + expr: "'ίδιο' != 'ίδιο'" + value: { bool_value: false } + } + test { + name: "ne_bytes" + expr: "b'\\x00\\xFF' != b'ÿ'" + value: { bool_value: true } + } + test { + name: "not_ne_bytes" + expr: "b'\\303\\277' != b'ÿ'" + value: { bool_value: false } + } + test { + name: "ne_bool" + expr: "false != true" + value: { bool_value: true } + } + test { + name: "not_ne_bool" + expr: "true != true" + value: { bool_value: false } + } + test { + name: "not_ne_null" + description: "null can only be equal to null, or else it won't match" + expr: "null != null" + value: { bool_value: false } + } + test { + name: "ne_list_empty" + expr: "[] != [1]" + value: { bool_value: true } + } + test { + name: "not_ne_list_empty" + expr: "[] != []" + value: { bool_value: false } + } + test { + name: "ne_list_bool" + expr: "[true, false, true] != [true, true, false]" + value: { bool_value: true } + } + test { + name: "not_ne_list_bool" + expr: "[false, true] != [false, true]" + value: { bool_value: false } + } + test { + name: "not_ne_list_of_list" + expr: "[[]] != [[]]" + value: { bool_value: false } + } + test { + name: "ne_map_by_value" + expr: "{'k':'v'} != {'k':'v1'}" + value: { bool_value: true } + } + test { + name: "ne_map_by_key" + expr: "{'k':true} != {'k1':true}" + value: { bool_value: true } + } + test { + name: "not_ne_map_int_to_float" + expr: "{1:1.0} != {1:1.0}" + value: { bool_value: false } + } + test { + name: "not_ne_map_key_order" + expr: "{'a':'b','c':'d'} != {'c':'d','a':'b'}" + value: { bool_value: false } + } + test { + name: "ne_mixed_types" + expr: "2u != 2" + disable_check: true + value: { bool_value: false } + } + test { + name: "ne_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_int64: 1234, single_string: '1234'} != TestAllTypes{single_int64: 1234, single_string: '1234'}" + value { bool_value: false } + } + test { + name: "ne_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_int64: 1234, single_string: '1234'} != TestAllTypes{single_int64: 1234, single_string: '1234'}" + value { bool_value: false } + } + test { + name: "ne_proto2_missing_fields_neq" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_int64: 1234} != TestAllTypes{single_string: '1234'}" + value { bool_value: true } + } + test { + name: "ne_proto3_missing_fields_neq" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_int64: 1234} != TestAllTypes{single_string: '1234'}" + value { bool_value: true } + } + test { + name: "ne_proto_nan_not_equal" + container: "google.api.expr.test.v1.proto2" + description: "For proto equality, NaN field values are not considered equal." + expr: "TestAllTypes{single_double: double('NaN')} != TestAllTypes{single_double: double('NaN')}" + value { bool_value: true } + } + test { + name: "ne_proto_different_types" + container: "google.api.expr.test.v1.proto2" + description: "At runtime, comparing differently typed messages is false." + expr: "dyn(TestAllTypes{}) != dyn(NestedTestAllTypes{})" + value: { bool_value: true } + } + test { + name: "ne_proto2_any_unpack" + description: "Any values should be unpacked and compared." + container: "google.api.expr.test.v1.proto2" + # Two equal messages with any fields serialized differently (but both are valid). + # TestAllTypes{single_any: [TestAllTypes]{single_int64: 1234, single_string: '1234'}} + expr: + "TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001r\\0041234'}} !=" + " TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'r\\0041234\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001'}}" + value { bool_value: false } + } + test { + name: "ne_proto2_any_unpack_bytewise_fallback" + description: "If an any field is missing its type_url, the comparison should fallback to a bytewise comparison of the serialized proto." + container: "google.api.expr.test.v1.proto3" + # The missing type info any is doubly nested to skip create + # message validations. + expr: + "TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\242\\006\\023\\022\\021\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001r\\0041234'}} !=" + " TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\242\\006\\023\\022\\021r\\0041234\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001'}}" + value { bool_value: true } + } + test { + name: "ne_proto3_any_unpack" + description: "Any values should be unpacked and compared." + container: "google.api.expr.test.v1.proto2" + # Two equal messages with any fields serialized differently (but both are valid). + expr: + "TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001r\\0041234'}} !=" + " TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'r\\0041234\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001'}}" + value { bool_value: false } + } + test { + name: "ne_proto3_any_unpack_bytewise_fallback" + description: "If an any field is missing its type_url, the comparison should fallback to a bytewise comparison of the serialized proto." + container: "google.api.expr.test.v1.proto3" + # The missing type info any is doubly nested to skip create message validations. + expr: + "TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\242\\006\\023\\022\\021\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001r\\0041234'}} !=" + " TestAllTypes{single_any: protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\242\\006\\023\\022\\021r\\0041234\\020\\256\\366\\377\\377\\377\\377\\377\\377\\377\\001'}}" + value { bool_value: true } + } +} +section { + name: "lt_literal" + description: "Literals comparison on _<_. (a < b) == (b > a) == !(a >= b) == !(b <= a)" + test { + name: "lt_int" + expr: "-1 < 0" + value: { bool_value: true } + } + test { + name: "not_lt_int" + expr: "0 < 0" + value: { bool_value: false } + } + test { + name: "lt_uint" + expr: "0u < 1u" + value: { bool_value: true } + } + test { + name: "not_lt_uint" + expr: "2u < 2u" + value: { bool_value: false } + } + test { + name: "lt_double" + expr: "1.0 < 1.0000001" + value: { bool_value: true } + } + test { + name: "not_lt_double" + description: "Following IEEE 754, negative zero compares equal to zero" + expr: "-0.0 < 0.0" + value: { bool_value: false } + } + test { + name: "lt_string" + expr: "'a' < 'b'" + value: { bool_value: true } + } + test { + name: "lt_string_empty_to_nonempty" + expr: "'' < 'a'" + value: { bool_value: true } + } + test { + name: "lt_string_case" + expr: "'Abc' < 'aBC'" + value: { bool_value: true } + } + test { + name: "lt_string_length" + expr: "'abc' < 'abcd'" + value: { bool_value: true } + } + test { + name: "lt_string_diacritical_mark_sensitive" + description: "Verifies that the we're not using a string comparison function that strips diacritical marks (á)" + expr: "'a' < '\\u00E1'" + value: { bool_value: true } + } + test { + name: "not_lt_string_empty" + expr: "'' < ''" + value: { bool_value: false } + } + test { + name: "not_lt_string_same" + expr: "'abc' < 'abc'" + value: { bool_value: false } + } + test { + name: "not_lt_string_case_length" + expr: "'a' < 'AB'" + value: { bool_value: false } + } + test { + name: "unicode_order_lexical" + description: "Compare the actual code points of the string, instead of decomposing ế into 'e' plus accent modifiers." + expr: "'f' < '\\u1EBF'" + value: { bool_value: true } + } + test { + name: "lt_bytes" + expr: "b'a' < b'b'" + value: { bool_value: true } + } + test { + name: "not_lt_bytes_same" + expr: "b'abc' < b'abc'" + value: { bool_value: false } + } + test { + name: "not_lt_bytes_width" + expr: "b'á' < b'b'" + value: { bool_value: false } + } + test { + name: "lt_bool_false_first" + expr: "false < true" + value: { bool_value: true } + } + test { + name: "not_lt_bool_same" + expr: "true < true" + value: { bool_value: false } + } + test { + name: "not_lt_bool_true_first" + expr: "true < false" + value: { bool_value: false } + } + test { + name: "lt_list_unsupported" + expr: "[0] < [1]" + disable_check: true + eval_error: { + errors: { message: "no such overload" } + } + } + test { + name: "lt_map_unsupported" + expr: "{0:'a'} < {1:'b'}" + disable_check: true + eval_error: { + errors: { message: "no such overload" } + } + } + test { + name: "lt_null_unsupported" + description: "Ensure _<_ doesn't have a binding for null" + expr: "null < null" + disable_check: true + eval_error: { + errors: { message: "no such overload" } + } + } + test { + name: "lt_mixed_types_error" + expr: "'foo' < 1024" + disable_check: true + eval_error: { + errors: { message: "no such overload" } + } + } + test { + name: "lt_dyn_int_uint" + expr: "dyn(1) < 2u" + value: { bool_value: true } + } + test { + name: "lt_dyn_int_double" + expr: "dyn(1) < 2.0" + value: { bool_value: true } + } + test { + name: "lt_dyn_uint_int" + expr: "dyn(1u) < 2" + value: { bool_value: true } + } + test { + name: "lt_dyn_uint_double" + expr: "dyn(1u) < 2.0" + value: { bool_value: true } + } + test { + name: "lt_dyn_double_int" + expr: "dyn(1.0) < 2" + value: { bool_value: true } + } + test { + name: "lt_dyn_double_uint" + expr: "dyn(1.0) < 2u" + value: { bool_value: true } + } + test { + name: "not_lt_dyn_int_uint" + expr: "dyn(1) < 1u" + value: { bool_value: false } + } + test { + name: "not_lt_dyn_int_double" + expr: "dyn(1) < 1.0" + value: { bool_value: false } + } + test { + name: "not_lt_dyn_uint_int" + expr: "dyn(1u) < 1" + value: { bool_value: false } + } + test { + name: "not_lt_dyn_uint_double" + expr: "dyn(1u) < 1.0" + value: { bool_value: false } + } + test { + name: "not_lt_dyn_double_int" + expr: "dyn(1.0) < 1" + value: { bool_value: false } + } + test { + name: "not_lt_dyn_double_uint" + expr: "dyn(1.0) < 1u" + value: { bool_value: false } + } + test { + name: "lt_dyn_int_big_uint" + expr: "dyn(1) < 9223372036854775808u" + value: { bool_value: true } + } + test { + name: "lt_dyn_small_int_uint" + expr: "dyn(-1) < 0u" + value: { bool_value: true } + } + test { + name: "not_lt_dyn_int_big_lossy_double" + expr: "dyn(9223372036854775807) < 9223372036854775808.0" + value: { bool_value: false } + } + test { + name: "lt_dyn_int_big_lossy_double" + expr: "dyn(9223372036854775807) < 9223372036854777857.0" + value: { bool_value: true } + } + test { + name: "not_lt_dyn_int_small_double" + expr: "dyn(9223372036854775807) < -9223372036854777857.0" + value: { bool_value: false } + } + test { + name: "not_lt_dyn_int_small_lossy_double" + expr: "dyn(-9223372036854775808) < -9223372036854775809.0" + value: { bool_value: false } + } + test { + name: "not_lt_dyn_uint_small_int" + expr: "dyn(1u) < -9223372036854775808" + value: { bool_value: false } + } + test { + name: "not_lt_dyn_big_uint_int" + expr: "dyn(9223372036854775808u) < 1" + value: { bool_value: false } + } + test { + name: "not_lt_dyn_uint_small_double" + expr: "dyn(18446744073709551615u) < -1.0" + value: { bool_value: false } + } + test { + name: "lt_dyn_uint_big_double" + expr: "dyn(18446744073709551615u) < 18446744073709590000.0" + value: { bool_value: true } + } + test { + name: "not_lt_dyn_big_double_uint" + expr: "dyn(18446744073709553665.0) < 18446744073709551615u" + value: { bool_value: false } + } + test { + name: "not_lt_dyn_big_double_int" + expr: "dyn(9223372036854775808.0) < 9223372036854775807" + value: { bool_value: false } + } + test { + name: "not_lt_dyn_small_double_int" + expr: "dyn(-9223372036854775809.0) < -9223372036854775808" + value: { bool_value: false } + } + +} +section { + name: "gt_literal" + description: "Literals comparison on _>_" + test { + name: "gt_int" + expr: "42 > -42" + value: { bool_value: true } + } + test { + name: "not_gt_int" + expr: "0 > 0" + value: { bool_value: false } + } + test { + name: "gt_uint" + expr: "48u > 46u" + value: { bool_value: true } + } + test { + name: "not_gt_uint" + expr: "0u > 999u" + value: { bool_value: false } + } + test { + name: "gt_double" + expr: "1e+1 > 1e+0" + value: { bool_value: true } + } + test { + name: "not_gt_double" + expr: ".99 > 9.9e-1" + value: { bool_value: false } + } + test { + name: "gt_string_case" + expr: "'abc' > 'aBc'" + value: { bool_value: true } + } + test { + name: "gt_string_to_empty" + expr: "'A' > ''" + value: { bool_value: true } + } + test { + name: "not_gt_string_empty_to_empty" + expr: "'' > ''" + value: { bool_value: false } + } + test { + name: "gt_string_unicode" + expr: "'α' > 'omega'" + value: { bool_value: true } + } + test { + name: "gt_bytes_one" + expr: "b'\x01' > b'\x00'" + value: { bool_value: true } + } + test { + name: "gt_bytes_one_to_empty" + expr: "b'\x00' > b''" + value: { bool_value: true } + } + test { + name: "not_gt_bytes_sorting" + expr: "b'\x00\x01' > b'\x01'" + value: { bool_value: false } + } + test { + name: "gt_bool_true_false" + expr: "true > false" + value: { bool_value: true } + } + test { + name: "not_gt_bool_false_true" + expr: "false > true" + value: { bool_value: false } + } + test { + name: "not_gt_bool_same" + expr: "true > true" + value: { bool_value: false } + } + test { + name: "gt_null_unsupported" + expr: "null > null" + disable_check: true + eval_error: { + errors: { message: "no such overload" } + } + } + test { + name: "gt_list_unsupported" + expr: "[1] > [0]" + disable_check: true + eval_error: { + errors: { message: "no such overload" } + } + } + test { + name: "gt_map_unsupported" + expr: "{1:'b'} > {0:'a'}" + disable_check: true + eval_error: { + errors: { message: "no such overload" } + } + } + test { + name: "gt_mixed_types_error" + expr: "'foo' > 1024" + disable_check: true + eval_error: { + errors: { message: "no such overload" } + } + } + test { + name: "gt_dyn_int_uint" + expr: "dyn(2) > 1u" + value: { bool_value: true } + } + test { + name: "gt_dyn_int_double" + expr: "dyn(2) > 1.0" + value: { bool_value: true } + } + test { + name: "gt_dyn_uint_int" + expr: "dyn(2u) > 1" + value: { bool_value: true } + } + test { + name: "gt_dyn_uint_double" + expr: "dyn(2u) > 1.0" + value: { bool_value: true } + } + test { + name: "gt_dyn_double_int" + expr: "dyn(2.0) > 1" + value: { bool_value: true } + } + test { + name: "gt_dyn_double_uint" + expr: "dyn(2.0) > 1u" + value: { bool_value: true } + } + test { + name: "not_gt_dyn_int_uint" + expr: "dyn(1) > 1u" + value: { bool_value: false } + } + test { + name: "not_gt_dyn_int_double" + expr: "dyn(1) > 1.0" + value: { bool_value: false } + } + test { + name: "not_gt_dyn_uint_int" + expr: "dyn(1u) > 1" + value: { bool_value: false } + } + test { + name: "not_gt_dyn_uint_double" + expr: "dyn(1u) > 1.0" + value: { bool_value: false } + } + test { + name: "not_gt_dyn_double_int" + expr: "dyn(1.0) > 1" + value: { bool_value: false } + } + test { + name: "not_gt_dyn_double_uint" + expr: "dyn(1.0) > 1u" + value: { bool_value: false } + } + test { + name: "not_gt_dyn_int_big_uint" + expr: "dyn(1) > 9223372036854775808u" + value: { bool_value: false } + } + test { + name: "not_gt_dyn_small_int_uint" + expr: "dyn(-1) > 0u" + value: { bool_value: false } + } + test { + name: "not_gt_dyn_int_big_double" + expr: "dyn(9223372036854775807) > 9223372036854775808.0" + value: { bool_value: false } + } + test { + name: "not_gt_dyn_int_small_lossy_double" + description: "The conversion of the int to double is lossy and the numbers end up being equal" + expr: "dyn(-9223372036854775808) > -9223372036854775809.0" + value: { bool_value: false } + } + test { + name: "gt_dyn_int_small_lossy_double_greater" + expr: "dyn(-9223372036854775808) > -9223372036854777857.0" + value: { bool_value: true } + } + test { + name: "gt_dyn_uint_small_int" + expr: "dyn(1u) > -1" + value: { bool_value: true } + } + test { + name: "gt_dyn_big_uint_int" + expr: "dyn(9223372036854775808u) > 1" + value: { bool_value: true } + } + test { + name: "gt_dyn_uint_small_double" + expr: "dyn(9223372036854775807u) > -1.0" + value: { bool_value: true } + } + test { + name: "not_gt_dyn_uint_big_double" + expr: "dyn(18446744073709551615u) > 18446744073709590000.0" + value: { bool_value: false } + } + test { + name: "gt_dyn_big_double_uint" + expr: "dyn(18446744073709553665.0) > 18446744073709551615u" + value: { bool_value: true } + } + test { + name: "not_gt_dyn_big_double_int" + expr: "dyn(9223372036854775808.0) > 9223372036854775807" + value: { bool_value: false } + } + test { + name: "not_gt_dyn_small_double_int" + expr: "dyn(-9223372036854775809.0) > -9223372036854775808" + value: { bool_value: false } + } +} +section { + name: "lte_literal" + description: "Literals comparison on _<=_" + test { + name: "lte_int_lt" + expr: "0 <= 1" + value: { bool_value: true } + } + test { + name: "lte_int_eq" + expr: "1 <= 1" + value: { bool_value: true } + } + test { + name: "not_lte_int_gt" + expr: "1 <= -1" + value: { bool_value: false } + } + test { + name: "lte_uint_lt" + expr: "0u <= 1u" + value: { bool_value: true } + } + test { + name: "lte_uint_eq" + expr: "1u <= 1u" + value: { bool_value: true } + } + test { + name: "not_lte_uint_gt" + expr: "1u <= 0u" + value: { bool_value: false } + } + test { + name: "lte_double_lt" + expr: "0.0 <= 0.1e-31" + value: { bool_value: true } + } + test { + name: "lte_double_eq" + expr: "0.0 <= 0e-1" + value: { bool_value: true } + } + test { + name: "not_lte_double_gt" + expr: "1.0 <= 0.99" + value: { bool_value: false } + } + test { + name: "lte_string_empty" + expr: "'' <= ''" + value: { bool_value: true } + } + test { + name: "lte_string_from_empty" + expr: "'' <= 'a'" + value: { bool_value: true } + } + test { + name: "not_lte_string_to_empty" + expr: "'a' <= ''" + value: { bool_value: false } + } + test { + name: "lte_string_lexicographical" + expr: "'aBc' <= 'abc'" + value: { bool_value: true } + } + test { + name: "lte_string_unicode_eq" + expr: "'α' <= 'α'" + value: { bool_value: true } + } + test { + name: "lte_string_unicode_lt" + expr: "'a' <= 'α'" + value: { bool_value: true } + } + test { + name: "not_lte_string_unicode" + expr: "'α' <= 'a'" + value: { bool_value: false } + } + test { + name: "lte_bytes_empty" + expr: "b'' <= b'\x00'" + value: { bool_value: true } + } + test { + name: "not_lte_bytes_length" + expr: "b'\x01\x00' <= b'\x01'" + value: { bool_value: false } + } + test { + name: "lte_bool_false_true" + expr: "false <= true" + value: { bool_value: true } + } + test { + name: "lte_bool_false_false" + expr: "false <= false" + value: { bool_value: true } + } + test { + name: "lte_bool_true_false" + expr: "true <= false" + value: { bool_value: false } + } + test { + name: "lte_null_unsupported" + expr: "null <= null" + disable_check: true + eval_error: { + errors: { message: "no such overload" } + } + } + test { + name: "lte_list_unsupported" + expr: "[0] <= [0]" + disable_check: true + eval_error: { + errors: { message: "no such overload" } + } + } + test { + name: "lte_map_unsupported" + expr: "{0:'a'} <= {1:'b'}" + disable_check: true + eval_error: { + errors: { message: "no such overload" } + } + } + test { + name: "lte_mixed_types_error" + expr: "'foo' <= 1024" + disable_check: true + eval_error: { + errors: { message: "no such overload" } + } + } + test { + name: "lte_dyn_int_uint" + expr: "dyn(1) <= 2u" + value: { bool_value: true } + } + test { + name: "lte_dyn_int_double" + expr: "dyn(1) <= 2.0" + value: { bool_value: true } + } + test { + name: "lte_dyn_uint_int" + expr: "dyn(1u) <= 2" + value: { bool_value: true } + } + test { + name: "lte_dyn_uint_double" + expr: "dyn(1u) <= 2.0" + value: { bool_value: true } + } + test { + name: "lte_dyn_double_int" + expr: "dyn(1.0) <= 2" + value: { bool_value: true } + } + test { + name: "lte_dyn_double_uint" + expr: "dyn(1.0) <= 2u" + value: { bool_value: true } + } + test { + name: "not_lte_dyn_int_uint" + expr: "dyn(2) <= 1u" + value: { bool_value: false } + } + test { + name: "not_lte_dyn_int_double" + expr: "dyn(2) <= 1.0" + value: { bool_value: false } + } + test { + name: "not_lte_dyn_uint_int" + expr: "dyn(2u) <= 1" + value: { bool_value: false } + } + test { + name: "not_lte_dyn_uint_double" + expr: "dyn(2u) <= 1.0" + value: { bool_value: false } + } + test { + name: "not_lte_dyn_double_int" + expr: "dyn(2.0) <= 1" + value: { bool_value: false } + } + test { + name: "not_lte_dyn_double_uint" + expr: "dyn(2.0) <= 1u" + value: { bool_value: false } + } + test { + name: "lte_dyn_int_big_uint" + expr: "dyn(1) <= 9223372036854775808u" + value: { bool_value: true } + } + test { + name: "lte_dyn_small_int_uint" + expr: "dyn(-1) <= 0u" + value: { bool_value: true } + } + test { + name: "lte_dyn_int_big_double" + expr: "dyn(9223372036854775807) <= 9223372036854775808.0" + value: { bool_value: true } + } + test { + name: "lte_dyn_int_small_lossy_double" + description: "The conversion of the int to double is lossy and the numbers end up being equal" + expr: "dyn(-9223372036854775808) <= -9223372036854775809.0" + value: { bool_value: true } + } + test { + name: "not_lte_dyn_int_small_lossy_double_less" + expr: "dyn(-9223372036854775808) <= -9223372036854777857.0" + value: { bool_value: false } + } + test { + name: "not_lte_dyn_uint_small_int" + expr: "dyn(1u) <= -9223372036854775808" + value: { bool_value: false } + } + test { + name: "not_lte_dyn_big_uint_int" + expr: "dyn(9223372036854775808u) <= 1" + value: { bool_value: false } + } + test { + name: "not_lte_dyn_uint_small_double" + expr: "dyn(18446744073709551615u) <= -1.0" + value: { bool_value: false } + } + test { + name: "lte_dyn_uint_big_double" + expr: "dyn(18446744073709551615u) <= 18446744073709590000.0" + value: { bool_value: true } + } + test { + name: "not_lte_dyn_big_double_uint" + expr: "dyn(18446744073709553665.0) <= 18446744073709551615u" + value: { bool_value: false } + } + test { + name: "lte_dyn_big_double_int" + expr: "dyn(9223372036854775808.0) <= 9223372036854775807" + value: { bool_value: true } + } + test { + name: "lte_dyn_small_double_int" + expr: "dyn(-9223372036854775809.0) <= -9223372036854775808" + value: { bool_value: true } + } +} +section { + name: "gte_literal" + description: "Literals comparison on _>=_" + test { + name: "gte_int_gt" + expr: "0 >= -1" + value: { bool_value: true } + } + test { + name: "gte_int_eq" + expr: "999 >= 999" + value: { bool_value: true } + } + test { + name: "not_gte_int_lt" + expr: "999 >= 1000" + value: { bool_value: false } + } + test { + name: "gte_uint_gt" + expr: "1u >= 0u" + value: { bool_value: true } + } + test { + name: "gte_uint_eq" + expr: "0u >= 0u" + value: { bool_value: true } + } + test { + name: "not_gte_uint_lt" + expr: "1u >= 10u" + value: { bool_value: false } + } + test { + name: "gte_double_gt" + expr: "1e+1 >= 1e+0" + value: { bool_value: true } + } + test { + name: "gte_double_eq" + expr: "9.80665 >= 9.80665e+0" + value: { bool_value: true } + } + test { + name: "not_gte_double_lt" + expr: "0.9999 >= 1.0" + value: { bool_value: false } + } + test { + name: "gte_string_empty" + expr: "'' >= ''" + value: { bool_value: true } + } + test { + name: "gte_string_to_empty" + expr: "'a' >= ''" + value: { bool_value: true } + } + test { + name: "gte_string_empty_to_nonempty" + expr: "'' >= 'a'" + value: { bool_value: false } + } + test { + name: "gte_string_length" + expr: "'abcd' >= 'abc'" + value: { bool_value: true } + } + test { + name: "not_gte_string_lexicographical" + expr: "'abc' >= 'abd'" + value: { bool_value: false } + } + test { + name: "gte_string_unicode_eq" + expr: "'τ' >= 'τ'" + value: { bool_value: true } + } + test { + name: "gte_string_unicode_gt" + expr: "'τ' >= 't'" + value: { bool_value: true } + } + test { + name: "not_get_string_unicode" + expr: "'t' >= 'τ'" + value: { bool_value: false } + } + test { + name: "gte_bytes_to_empty" + expr: "b'\x00' >= b''" + value: { bool_value: true } + } + test { + name: "not_gte_bytes_empty_to_nonempty" + expr: "b'' >= b'\x00'" + value: { bool_value: false } + } + test { + name: "gte_bytes_samelength" + expr: "b'\x00\x01' >= b'\x01\x00'" + value: { bool_value: false } + } + test { + name: "gte_bool_gt" + expr: "true >= false" + value: { bool_value: true } + } + test { + name: "gte_bool_eq" + expr: "true >= true" + value: { bool_value: true } + } + test { + name: "not_gte_bool_lt" + expr: "false >= true" + value: { bool_value: false } + } + test { + name: "gte_null_unsupported" + expr: "null >= null" + disable_check: true + eval_error: { + errors: { message: "no such overload" } + } + } + test { + name: "gte_list_unsupported" + expr: "['y'] >= ['x']" + disable_check: true + eval_error: { + errors: { message: "no such overload" } + } + } + test { + name: "gte_map_unsupported" + expr: "{1:'b'} >= {0:'a'}" + disable_check: true + eval_error: { + errors: { message: "no such overload" } + } + } + test { + name: "gte_mixed_types_error" + expr: "'foo' >= 1.0" + disable_check: true + eval_error: { + errors: { message: "no such overload" } + } + } + test { + name: "gte_dyn_int_uint" + expr: "dyn(2) >= 1u" + value: { bool_value: true } + } + test { + name: "gte_dyn_int_double" + expr: "dyn(2) >= 1.0" + value: { bool_value: true } + } + test { + name: "gte_dyn_uint_int" + expr: "dyn(2u) >= 1" + value: { bool_value: true } + } + test { + name: "gte_dyn_uint_double" + expr: "dyn(2u) >= 1.0" + value: { bool_value: true } + } + test { + name: "gte_dyn_double_int" + expr: "dyn(2.0) >= 1" + value: { bool_value: true } + } + test { + name: "gte_dyn_double_uint" + expr: "dyn(2.0) >= 1u" + value: { bool_value: true } + } + test { + name: "not_gte_dyn_int_uint" + expr: "dyn(0) >= 1u" + value: { bool_value: false } + } + test { + name: "not_gte_dyn_int_double" + expr: "dyn(0) >= 1.0" + value: { bool_value: false } + } + test { + name: "not_gte_dyn_uint_int" + expr: "dyn(0u) >= 1" + value: { bool_value: false } + } + test { + name: "not_gte_dyn_uint_double" + expr: "dyn(0u) >= 1.0" + value: { bool_value: false } + } + test { + name: "not_gte_dyn_double_int" + expr: "dyn(0.0) >= 1" + value: { bool_value: false } + } + test { + name: "not_gte_dyn_double_uint" + expr: "dyn(0.0) >= 1u" + value: { bool_value: false } + } + test { + name: "not_gte_dyn_int_big_uint" + expr: "dyn(1) >= 9223372036854775808u" + value: { bool_value: false } + } + test { + name: "not_gte_dyn_small_int_uint" + expr: "dyn(-1) >= 0u" + value: { bool_value: false } + } + test { + name: "gte_dyn_int_big_lossy_double" + expr: "dyn(9223372036854775807) >= 9223372036854775808.0" + value: { bool_value: true } + } + test { + name: "not_gte_dyn_int_big_double" + expr: "dyn(9223372036854775807) >= 9223372036854777857.0" + value: { bool_value: false } + } + test { + name: "gte_dyn_int_small_lossy_double_equal" + description: "The conversion of the int to double is lossy and the numbers end up being equal" + expr: "dyn(-9223372036854775808) >= -9223372036854775809.0" + value: { bool_value: true } + } + test { + name: "gte_dyn_int_small_lossy_double_greater" + expr: "dyn(-9223372036854775808) >= -9223372036854777857.0" + value: { bool_value: true } + } + test { + name: "gte_dyn_uint_small_int" + expr: "dyn(1u) >= -1" + value: { bool_value: true } + } + test { + name: "gte_dyn_big_uint_int" + expr: "dyn(9223372036854775808u) >= 1" + value: { bool_value: true } + } + test { + name: "gte_dyn_uint_small_double" + expr: "dyn(9223372036854775807u) >= -1.0" + value: { bool_value: true } + } + test { + name: "not_gte_dyn_uint_big_double" + expr: "dyn(18446744073709551615u) >= 18446744073709553665.0" + value: { bool_value: false } + } + test { + name: "gte_dyn_big_double_uint" + expr: "dyn(18446744073709553665.0) >= 18446744073709551615u" + value: { bool_value: true } + } + test { + name: "gte_dyn_big_double_int" + expr: "dyn(9223372036854775808.0) >= 9223372036854775807" + value: { bool_value: true } + } + test { + name: "gte_dyn_small_double_int" + expr: "dyn(-9223372036854775809.0) >= -9223372036854775808" + value: { bool_value: true } + } +} +section { + name: "in_list_literal" + description: "Set membership tests using list literals and the 'in' operator" + test { + name: "elem_not_in_empty_list" + expr: "'empty' in []" + value { bool_value: false } + } + test { + name: "elem_in_list" + expr: "'elem' in ['elem', 'elemA', 'elemB']" + value { bool_value: true } + } + test { + name: "elem_not_in_list" + expr: "'not' in ['elem1', 'elem2', 'elem3']" + value { bool_value: false } + } + test { + name: "elem_in_mixed_type_list" + description: "Set membership tests should succeed if the 'elem' exists in a mixed element type list." + expr: "'elem' in [1, 'elem', 2]" + value { bool_value: true } + } + test { + name: "elem_in_mixed_type_list_cross_type" + description: "Set membership tests should return false due to the introduction of heterogeneous-equality. Set membership via 'in' is equivalent to the macro exists() behavior." + expr: "'elem' in [1u, 'str', 2, b'bytes']" + value: { bool_value: false } + } +} +section { + name: "in_map_literal" + description: "Set membership tests using map literals and the 'in' operator" + test { + name: "key_not_in_empty_map" + expr: "'empty' in {}" + value { bool_value: false } + } + test { + name: "key_in_map" + expr: "'key' in {'key':'1', 'other':'2'}" + value { bool_value: true } + } + test { + name: "key_not_in_map" + expr: "'key' in {'lock':1, 'gate':2}" + value { bool_value: false } + } + test { + name: "key_in_mixed_key_type_map" + description: "Map keys are of mixed type, but since the key is present the result is true." + expr: "'key' in {3:3.0, 'key':2u}" + value { bool_value: true } + } + test { + name: "key_in_mixed_key_type_map_cross_type" + expr: "'key' in {1u:'str', 2:b'bytes'}" + value: { bool_value: false } + } +} +section { + name: "bound" + description: "Comparing bound variables with literals or other variables" + test { + name: "bytes_gt_left_false" + expr: "x > b'\x00'" + value: { bool_value: false } + type_env: { + name: "x" + ident: { type: { primitive: BYTES } } + } + bindings: { + key: "x" + value: { value: { bytes_value: "\x00" } } + } + } + test { + name: "int_lte_right_true" + expr: "123 <= x" + value: { bool_value: true } + type_env: { + name: "x" + ident: { type: { primitive: INT64 } } + } + bindings: { + key: "x" + value: { value: { int64_value: 124 } } + } + } + test { + name: "bool_lt_right_true" + expr: "false < x" + value: { bool_value: true } + type_env: { + name: "x" + ident: { type: { primitive: BOOL } } + } + bindings: { + key: "x" + value: { value: { bool_value: true } } + } + } + test { + name: "double_ne_left_false" + expr: "x != 9.8" + value: { bool_value: false } + type_env: { + name: "x" + ident: { type: { primitive: DOUBLE } } + } + bindings: { + key: "x" + value: { value: { double_value: 9.8 } } + } + } + test { + name: "map_ne_right_false" + expr: "{'a':'b','c':'d'} != x" + value: { bool_value: false } + type_env: { + name: "x" + ident: { + type: { + map_type: { + key_type: { primitive: STRING } + value_type: { primitive: STRING } + } + } + } + } + bindings: { + key: "x" + value: { + value: { + map_value { + entries { + key: { string_value: "c" } + value: { string_value: "d" } + } + entries { + key: { string_value: "a" } + value: { string_value: "b" } + } + } + } + } + } + } + test { + name: "null_eq_left_true" + description: "A comparison _==_ against null only binds if the type is determined to be null or we skip the type checking" + expr: "x == null" + value: { bool_value: true } + type_env: { + name: "x" + ident: { type: { null: NULL_VALUE } } + } + bindings: { + key: "x" + value: { value: { null_value: NULL_VALUE } } + } + } + test { + name: "list_eq_right_false" + expr: "[1, 2] == x" + value: { bool_value: false } + type_env: { + name: "x" + ident: { + type: { + list_type: { + elem_type: { primitive: INT64 } + } + } + } + } + bindings: { + key: "x" + value: { + value: { + list_value { + values: { int64_value: 2 } + values: { int64_value: 1 } + } + } + } + } + } + test { + name: "string_gte_right_true" + expr: "'abcd' >= x" + value: { bool_value: true } + type_env: { + name: "x" + ident: { + type: { primitive: STRING } + } + } + bindings: { + key: "x" + value: { value: { string_value: "abc" } } + } + } + test { + name: "uint_eq_right_false" + expr: "999u == x" + value: { bool_value: false } + type_env: { + name: "x" + ident: { + type: { primitive: UINT64 } + } + } + bindings: { + key: "x" + value: { value: { uint64_value: 1000 } } + } + } + test { + name: "null_lt_right_no_such_overload" + description: "There is no _<_ operation for null, even if both operands are null" + expr: "null < x" + eval_error: { + errors: { message: "no such overload" } + } + disable_check: true + bindings: { + key: "x" + value: { value: { null_value: NULL_VALUE } } + } + } +} diff --git a/packages/cel/src/lib/conformance/testdata/conversions.json b/packages/cel/src/lib/conformance/testdata/conversions.json new file mode 100755 index 0000000..f532de3 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/conversions.json @@ -0,0 +1,881 @@ +{ + "name": "conversions", + "description": "Tests for type conversions.", + "section": [ + { + "name": "bytes", + "description": "Conversions to bytes.", + "test": [ + { + "name": "string_empty", + "expr": "bytes('')", + "value": { + "bytesValue": "" + } + }, + { + "name": "string", + "expr": "bytes('abc')", + "value": { + "bytesValue": "YWJj" + } + }, + { + "name": "string_unicode", + "expr": "bytes('ÿ')", + "value": { + "bytesValue": "w78=" + } + }, + { + "name": "string_unicode_vs_literal", + "expr": "bytes('\\377') == b'\\377'", + "value": { + "boolValue": false + } + } + ] + }, + { + "name": "double", + "description": "Conversions to double.", + "test": [ + { + "name": "int_zero", + "expr": "double(0)", + "value": { + "doubleValue": 0 + } + }, + { + "name": "int_pos", + "expr": "double(1000000000000)", + "value": { + "doubleValue": 1000000000000 + } + }, + { + "name": "int_neg", + "expr": "double(-1000000000000000)", + "value": { + "doubleValue": -1000000000000000 + } + }, + { + "name": "int_min_exact", + "description": "Smallest contiguous representable int (-2^53).", + "expr": "double(-9007199254740992)", + "value": { + "doubleValue": -9007199254740992 + } + }, + { + "name": "int_max_exact", + "description": "Largest contiguous representable int (2^53).", + "expr": "double(9007199254740992)", + "value": { + "doubleValue": 9007199254740992 + } + }, + { + "name": "int_range", + "description": "Largest signed 64-bit. Rounds to nearest double.", + "expr": "double(9223372036854775807)", + "value": { + "doubleValue": 9223372036854776000 + } + }, + { + "name": "uint_zero", + "expr": "double(0u)", + "value": { + "doubleValue": 0 + } + }, + { + "name": "uint_pos", + "expr": "double(123u)", + "value": { + "doubleValue": 123 + } + }, + { + "name": "uint_max_exact", + "description": "Largest contiguous representable int (2^53).", + "expr": "double(9007199254740992u)", + "value": { + "doubleValue": 9007199254740992 + } + }, + { + "name": "uint_range", + "description": "Largest unsigned 64-bit.", + "expr": "double(18446744073709551615u)", + "value": { + "doubleValue": 18446744073709552000 + } + }, + { + "name": "string_zero", + "expr": "double('0')", + "value": { + "doubleValue": 0 + } + }, + { + "name": "string_zero_dec", + "expr": "double('0.0')", + "value": { + "doubleValue": 0 + } + }, + { + "name": "string_neg_zero", + "expr": "double('-0.0')", + "value": { + "doubleValue": -0 + } + }, + { + "name": "string_no_dec", + "expr": "double('123')", + "value": { + "doubleValue": 123 + } + }, + { + "name": "string_pos", + "expr": "double('123.456')", + "value": { + "doubleValue": 123.456 + } + }, + { + "name": "string_neg", + "expr": "double('-987.654')", + "value": { + "doubleValue": -987.654 + } + }, + { + "name": "string_exp_pos_pos", + "expr": "double('6.02214e23')", + "value": { + "doubleValue": 6.02214e+23 + } + }, + { + "name": "string_exp_pos_neg", + "expr": "double('1.38e-23')", + "value": { + "doubleValue": 1.38e-23 + } + }, + { + "name": "string_exp_neg_pos", + "expr": "double('-84.32e7')", + "value": { + "doubleValue": -843200000 + } + }, + { + "name": "string_exp_neg_neg", + "expr": "double('-5.43e-21')", + "value": { + "doubleValue": -5.43e-21 + } + } + ] + }, + { + "name": "dyn", + "description": "Tests for dyn annotation.", + "test": [ + { + "name": "dyn_heterogeneous_list", + "description": "No need to disable type checking.", + "expr": "type(dyn([1, 'one']))", + "value": { + "typeValue": "list" + } + } + ] + }, + { + "name": "int", + "description": "Conversions to int.", + "test": [ + { + "name": "uint", + "expr": "int(42u)", + "value": { + "int64Value": "42" + } + }, + { + "name": "uint_zero", + "expr": "int(0u)", + "value": { + "int64Value": "0" + } + }, + { + "name": "uint_max_exact", + "expr": "int(9223372036854775807u)", + "value": { + "int64Value": "9223372036854775807" + } + }, + { + "name": "uint_range", + "expr": "int(18446744073709551615u)", + "evalError": { + "errors": [ + { + "message": "range error" + } + ] + } + }, + { + "name": "double_round_neg", + "expr": "int(-123.456)", + "value": { + "int64Value": "-123" + } + }, + { + "name": "double_truncate", + "expr": "int(1.9)", + "value": { + "int64Value": "1" + } + }, + { + "name": "double_truncate_neg", + "expr": "int(-7.9)", + "value": { + "int64Value": "-7" + } + }, + { + "name": "double_half_pos", + "expr": "int(11.5)", + "value": { + "int64Value": "11" + } + }, + { + "name": "double_half_neg", + "expr": "int(-3.5)", + "value": { + "int64Value": "-3" + } + }, + { + "name": "double_big_exact", + "description": "Beyond exact range (2^53), but no loss of precision (2^55).", + "expr": "int(double(36028797018963968))", + "value": { + "int64Value": "36028797018963968" + } + }, + { + "name": "double_big_precision", + "description": "Beyond exact range (2^53), but loses precisons (2^55 + 1).", + "expr": "int(double(36028797018963969))", + "value": { + "int64Value": "36028797018963968" + } + }, + { + "name": "double_int_max_range", + "description": "The double(2^63-1) cast produces a floating point value outside the int range", + "expr": "int(9223372036854775807.0)", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + }, + { + "name": "double_int_min_range", + "description": "The double(-2^63) cast produces a floating point value outside the int range", + "expr": "int(-9223372036854775808.0)", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + }, + { + "name": "double_range", + "expr": "int(1e99)", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + }, + { + "name": "string", + "expr": "int('987')", + "value": { + "int64Value": "987" + } + }, + { + "name": "timestamp", + "expr": "int(timestamp('2004-09-16T23:59:59Z'))", + "value": { + "int64Value": "1095379199" + } + } + ] + }, + { + "name": "string", + "description": "Conversions to string.", + "test": [ + { + "name": "int", + "expr": "string(123)", + "value": { + "stringValue": "123" + } + }, + { + "name": "int_neg", + "expr": "string(-456)", + "value": { + "stringValue": "-456" + } + }, + { + "name": "uint", + "expr": "string(9876u)", + "value": { + "stringValue": "9876" + } + }, + { + "name": "double", + "expr": "string(123.456)", + "value": { + "stringValue": "123.456" + } + }, + { + "name": "double_hard", + "expr": "string(-4.5e-3)", + "value": { + "stringValue": "-0.0045" + } + }, + { + "name": "bytes", + "expr": "string(b'abc')", + "value": { + "stringValue": "abc" + } + }, + { + "name": "bytes_unicode", + "expr": "string(b'\\303\\277')", + "value": { + "stringValue": "ÿ" + } + }, + { + "name": "bytes_invalid", + "expr": "string(b'\\000\\xff')", + "evalError": { + "errors": [ + { + "message": "invalid UTF-8" + } + ] + } + } + ] + }, + { + "name": "type", + "description": "Type reflection tests.", + "test": [ + { + "name": "bool", + "expr": "type(true)", + "value": { + "typeValue": "bool" + } + }, + { + "name": "bool_denotation", + "expr": "bool", + "value": { + "typeValue": "bool" + } + }, + { + "name": "dyn_no_denotation", + "expr": "dyn", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "unknown varaible" + } + ] + } + }, + { + "name": "int", + "expr": "type(0)", + "value": { + "typeValue": "int" + } + }, + { + "name": "int_denotation", + "expr": "int", + "value": { + "typeValue": "int" + } + }, + { + "name": "eq_same", + "expr": "type(true) == type(false)", + "value": { + "boolValue": true + } + }, + { + "name": "uint", + "expr": "type(64u)", + "value": { + "typeValue": "uint" + } + }, + { + "name": "uint_denotation", + "expr": "uint", + "value": { + "typeValue": "uint" + } + }, + { + "name": "double", + "expr": "type(3.14)", + "value": { + "typeValue": "double" + } + }, + { + "name": "double_denotation", + "expr": "double", + "value": { + "typeValue": "double" + } + }, + { + "name": "null_type", + "expr": "type(null)", + "value": { + "typeValue": "null_type" + } + }, + { + "name": "null_type_denotation", + "expr": "null_type", + "value": { + "typeValue": "null_type" + } + }, + { + "name": "string", + "expr": "type('foo')", + "value": { + "typeValue": "string" + } + }, + { + "name": "string_denotation", + "expr": "string", + "value": { + "typeValue": "string" + } + }, + { + "name": "bytes", + "expr": "type(b'\\xff')", + "value": { + "typeValue": "bytes" + } + }, + { + "name": "bytes_denotation", + "expr": "bytes", + "value": { + "typeValue": "bytes" + } + }, + { + "name": "list", + "expr": "type([1, 2, 3])", + "value": { + "typeValue": "list" + } + }, + { + "name": "list_denotation", + "expr": "list", + "value": { + "typeValue": "list" + } + }, + { + "name": "lists_monomorphic", + "expr": "type([1, 2, 3]) == type(['one', 'two', 'three'])", + "value": { + "boolValue": true + } + }, + { + "name": "map", + "expr": "type({4: 16})", + "value": { + "typeValue": "map" + } + }, + { + "name": "map_denotation", + "expr": "map", + "value": { + "typeValue": "map" + } + }, + { + "name": "map_monomorphic", + "expr": "type({'one': 1}) == type({1: 'one'})", + "value": { + "boolValue": true + } + }, + { + "name": "eq_diff", + "expr": "type(7) == type(7u)", + "value": { + "boolValue": false + } + }, + { + "name": "neq_same", + "expr": "type(0.0) != type(-0.0)", + "value": { + "boolValue": false + } + }, + { + "name": "neq_diff", + "expr": "type(0.0) != type(0)", + "value": { + "boolValue": true + } + }, + { + "name": "meta", + "expr": "type(type(7)) == type(type(7u))", + "value": { + "boolValue": true + } + }, + { + "name": "type", + "expr": "type(int)", + "value": { + "typeValue": "type" + } + }, + { + "name": "type_denotation", + "expr": "type", + "value": { + "typeValue": "type" + } + }, + { + "name": "type_type", + "expr": "type(type)", + "value": { + "typeValue": "type" + } + } + ] + }, + { + "name": "uint", + "description": "Conversions to uint.", + "test": [ + { + "name": "int", + "expr": "uint(1729)", + "value": { + "uint64Value": "1729" + } + }, + { + "name": "int_max", + "expr": "uint(9223372036854775807)", + "value": { + "uint64Value": "9223372036854775807" + } + }, + { + "name": "int_neg", + "expr": "uint(-1)", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + }, + { + "name": "double", + "expr": "uint(3.14159265)", + "value": { + "uint64Value": "3" + } + }, + { + "name": "double_truncate", + "expr": "uint(1.9)", + "value": { + "uint64Value": "1" + } + }, + { + "name": "double_half", + "expr": "uint(25.5)", + "value": { + "uint64Value": "25" + } + }, + { + "name": "double_big_exact", + "description": "Beyond exact range (2^53), but no loss of precision (2^55).", + "expr": "uint(double(36028797018963968u))", + "value": { + "uint64Value": "36028797018963968" + } + }, + { + "name": "double_big_precision", + "description": "Beyond exact range (2^53), but loses precisons (2^55 + 1).", + "expr": "uint(double(36028797018963969u))", + "value": { + "uint64Value": "36028797018963968" + } + }, + { + "name": "double_uint_max_range", + "description": "The exact conversion of uint max as a double does not round trip.", + "expr": "int(18446744073709551615.0)", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + }, + { + "name": "double_range_beyond_uint", + "expr": "uint(6.022e23)", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + }, + { + "name": "string", + "expr": "uint('300')", + "value": { + "uint64Value": "300" + } + } + ] + }, + { + "name": "bool", + "description": "Conversions to bool", + "test": [ + { + "name": "string_1", + "expr": "bool('1')", + "value": { + "boolValue": true + } + }, + { + "name": "string_t", + "expr": "bool('t')", + "value": { + "boolValue": true + } + }, + { + "name": "string_true_lowercase", + "expr": "bool('true')", + "value": { + "boolValue": true + } + }, + { + "name": "string_true_uppercase", + "expr": "bool('TRUE')", + "value": { + "boolValue": true + } + }, + { + "name": "string_true_pascalcase", + "expr": "bool('True')", + "value": { + "boolValue": true + } + }, + { + "name": "string_0", + "expr": "bool('0')", + "value": { + "boolValue": false + } + }, + { + "name": "string_f", + "expr": "bool('f')", + "value": { + "boolValue": false + } + }, + { + "name": "string_false_lowercase", + "expr": "bool('false')", + "value": { + "boolValue": false + } + }, + { + "name": "string_false_uppercase", + "expr": "bool('FALSE')", + "value": { + "boolValue": false + } + }, + { + "name": "string_false_pascalcase", + "expr": "bool('False')", + "value": { + "boolValue": false + } + }, + { + "name": "string_true_badcase", + "expr": "bool('TrUe')", + "evalError": { + "errors": [ + { + "message": "Type conversion error" + } + ] + } + }, + { + "name": "string_false_badcase", + "expr": "bool('FaLsE')", + "evalError": { + "errors": [ + { + "message": "Type conversion error" + } + ] + } + } + ] + }, + { + "name": "identity", + "description": "Identity functions", + "test": [ + { + "name": "bool", + "expr": "bool(true)", + "value": { + "boolValue": true + } + }, + { + "name": "int", + "expr": "int(1)", + "value": { + "int64Value": "1" + } + }, + { + "name": "uint", + "expr": "uint(1u)", + "value": { + "uint64Value": "1" + } + }, + { + "name": "double", + "expr": "double(5.5)", + "value": { + "doubleValue": 5.5 + } + }, + { + "name": "string", + "expr": "string('hello')", + "value": { + "stringValue": "hello" + } + }, + { + "name": "bytes", + "expr": "bytes(b'abc')", + "value": { + "bytesValue": "YWJj" + } + }, + { + "name": "duration", + "expr": "duration(duration('100s')) == duration('100s')", + "value": { + "boolValue": true + } + }, + { + "name": "timestamp", + "expr": "timestamp(timestamp(1000000000)) == timestamp(1000000000)", + "value": { + "boolValue": true + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/conversions.textproto b/packages/cel/src/lib/conformance/testdata/conversions.textproto new file mode 100644 index 0000000..ed8f408 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/conversions.textproto @@ -0,0 +1,619 @@ +name: "conversions" +description: "Tests for type conversions." +section { + name: "bytes" + description: "Conversions to bytes." + test { + name: "string_empty" + expr: "bytes('')" + value: { bytes_value: "" } + } + test { + name: "string" + expr: "bytes('abc')" + value: { bytes_value: "abc" } + } + test { + name: "string_unicode" + expr: "bytes('ÿ')" + value: { bytes_value: "\303\277" } + } + test { + name: "string_unicode_vs_literal" + expr: "bytes('\\377') == b'\\377'" + value: { bool_value: false } + } +} +section { + name: "double" + description: "Conversions to double." + test { + name: "int_zero" + expr: "double(0)" + value: { double_value: 0.0 } + } + test { + name: "int_pos" + expr: "double(1000000000000)" + value: { double_value: 1e12 } + } + test { + name: "int_neg" + expr: "double(-1000000000000000)" + value: { double_value: -1e15 } + } + test { + name: "int_min_exact" + description: "Smallest contiguous representable int (-2^53)." + expr: "double(-9007199254740992)" + value { double_value: -9.007199254740992e15 } + } + test { + name: "int_max_exact" + description: "Largest contiguous representable int (2^53)." + expr: "double(9007199254740992)" + value { double_value: 9.007199254740992e15 } + } + test { + name: "int_range" + description: "Largest signed 64-bit. Rounds to nearest double." + expr: "double(9223372036854775807)" + value: { double_value: 9.223372036854775807e18 } + } + test { + name: "uint_zero" + expr: "double(0u)" + value: { double_value: 0.0 } + } + test { + name: "uint_pos" + expr: "double(123u)" + value: { double_value: 123.0 } + } + test { + name: "uint_max_exact" + description: "Largest contiguous representable int (2^53)." + expr: "double(9007199254740992u)" + value { double_value: 9.007199254740992e15 } + } + test { + name: "uint_range" + description: "Largest unsigned 64-bit." + expr: "double(18446744073709551615u)" + value: { double_value: 1.8446744073709551615e19 } + } + test { + name: "string_zero" + expr: "double('0')" + value: { double_value: 0.0 } + } + test { + name: "string_zero_dec" + expr: "double('0.0')" + value: { double_value: 0.0 } + } + test { + name: "string_neg_zero" + expr: "double('-0.0')" + value: { double_value: -0.0 } + } + test { + name: "string_no_dec" + expr: "double('123')" + value: { double_value: 123.0 } + } + test { + name: "string_pos" + expr: "double('123.456')" + value: { double_value: 123.456 } + } + test { + name: "string_neg" + expr: "double('-987.654')" + value: { double_value: -987.654 } + } + test { + name: "string_exp_pos_pos" + expr: "double('6.02214e23')" + value: { double_value: 6.02214e23 } + } + test { + name: "string_exp_pos_neg" + expr: "double('1.38e-23')" + value: { double_value: 1.38e-23 } + } + test { + name: "string_exp_neg_pos" + expr: "double('-84.32e7')" + value: { double_value: -8.432e8 } + } + test { + name: "string_exp_neg_neg" + expr: "double('-5.43e-21')" + value: { double_value: -5.43e-21 } + } +} +section { + name: "dyn" + description: "Tests for dyn annotation." + test { + name: "dyn_heterogeneous_list" + description: "No need to disable type checking." + expr: "type(dyn([1, 'one']))" + value: { type_value: "list" } + } +} +section { + name: "int" + description: "Conversions to int." + test { + name: "uint" + expr: "int(42u)" + value: { int64_value: 42 } + } + test { + name: "uint_zero" + expr: "int(0u)" + value: { int64_value: 0 } + } + test { + name: "uint_max_exact" + expr: "int(9223372036854775807u)" + value { int64_value: 9223372036854775807 } + } + test { + name: "uint_range" + expr: "int(18446744073709551615u)" + eval_error { + errors { message: "range error" } + } + } + test { + name: "double_round_neg" + expr: "int(-123.456)" + value: { int64_value: -123 } + } + test { + name: "double_truncate" + expr: "int(1.9)" + value: { int64_value: 1 } + } + test { + name: "double_truncate_neg" + expr: "int(-7.9)" + value: { int64_value: -7 } + } + test { + name: "double_half_pos" + expr: "int(11.5)" + value: { int64_value: 11 } + } + test { + name: "double_half_neg" + expr: "int(-3.5)" + value: { int64_value: -3 } + } + test { + name: "double_big_exact" + description: "Beyond exact range (2^53), but no loss of precision (2^55)." + expr: "int(double(36028797018963968))" + value { int64_value: 36028797018963968 } + } + test { + name: "double_big_precision" + description: "Beyond exact range (2^53), but loses precisons (2^55 + 1)." + expr: "int(double(36028797018963969))" + value { int64_value: 36028797018963968 } + } + test { + name: "double_int_max_range" + description: "The double(2^63-1) cast produces a floating point value outside the int range" + expr: "int(9223372036854775807.0)" + eval_error { + errors: { message: "range" } + } + } + test { + name: "double_int_min_range" + description: "The double(-2^63) cast produces a floating point value outside the int range" + expr: "int(-9223372036854775808.0)" + eval_error { + errors: { message: "range" } + } + } + test { + name: "double_range" + expr: "int(1e99)" + eval_error { + errors: { message: "range" } + } + } + test { + name: "string" + expr: "int('987')" + value: { int64_value: 987 } + } + test { + name: "timestamp" + expr: "int(timestamp('2004-09-16T23:59:59Z'))" + value: { int64_value: 1095379199 } + } +} +section { + name: "string" + description: "Conversions to string." + test { + name: "int" + expr: "string(123)" + value: { string_value: "123" } + } + test { + name: "int_neg" + expr: "string(-456)" + value: { string_value: "-456" } + } + test { + name: "uint" + expr: "string(9876u)" + value: { string_value: "9876" } + } + test { + name: "double" + expr: "string(123.456)" + value: { string_value: "123.456" } + } + test { + name: "double_hard" + expr: "string(-4.5e-3)" + value: { string_value: "-0.0045" } + } + test { + name: "bytes" + expr: "string(b'abc')" + value: { string_value: "abc" } + } + test { + name: "bytes_unicode" + expr: "string(b'\\303\\277')" + value: { string_value: "ÿ" } + } + test { + name: "bytes_invalid" + expr: "string(b'\\000\\xff')" + eval_error { + errors { message: "invalid UTF-8" } + } + } +} +section { + name: "type" + description: "Type reflection tests." + test { + name: "bool" + expr: "type(true)" + value: { type_value: "bool" } + } + test { + name: "bool_denotation" + expr: "bool" + value: { type_value: "bool" } + } + test { + name: "dyn_no_denotation" + expr: "dyn" + disable_check: true + eval_error { + errors { message: "unknown varaible" } + } + } + test { + name: "int" + expr: "type(0)" + value: { type_value: "int" } + } + test { + name: "int_denotation" + expr: "int" + value: { type_value: "int" } + } + test { + name: "eq_same" + expr: "type(true) == type(false)" + value: { bool_value: true } + } + test { + name: "uint" + expr: "type(64u)" + value: { type_value: "uint" } + } + test { + name: "uint_denotation" + expr: "uint" + value: { type_value: "uint" } + } + test { + name: "double" + expr: "type(3.14)" + value: { type_value: "double" } + } + test { + name: "double_denotation" + expr: "double" + value: { type_value: "double" } + } + test { + name: "null_type" + expr: "type(null)" + value: { type_value: "null_type" } + } + test { + name: "null_type_denotation" + expr: "null_type" + value: { type_value: "null_type" } + } + test { + name: "string" + expr: "type('foo')" + value: { type_value: "string" } + } + test { + name: "string_denotation" + expr: "string" + value: { type_value: "string" } + } + test { + name: "bytes" + expr: "type(b'\\xff')" + value: { type_value: "bytes" } + } + test { + name: "bytes_denotation" + expr: "bytes" + value: { type_value: "bytes" } + } + test { + name: "list" + expr: "type([1, 2, 3])" + value: { type_value: "list" } + } + test { + name: "list_denotation" + expr: "list" + value: { type_value: "list" } + } + test { + name: "lists_monomorphic" + expr: "type([1, 2, 3]) == type(['one', 'two', 'three'])" + value: { bool_value: true } + } + test { + name: "map" + expr: "type({4: 16})" + value: { type_value: "map" } + } + test { + name: "map_denotation" + expr: "map" + value: { type_value: "map" } + } + test { + name: "map_monomorphic" + expr: "type({'one': 1}) == type({1: 'one'})" + value: { bool_value: true } + } + test { + name: "eq_diff" + expr: "type(7) == type(7u)" + value: { bool_value: false } + } + test { + name: "neq_same" + expr: "type(0.0) != type(-0.0)" + value: { bool_value: false } + } + test { + name: "neq_diff" + expr: "type(0.0) != type(0)" + value: { bool_value: true } + } + test { + name: "meta" + expr: "type(type(7)) == type(type(7u))" + value: { bool_value: true } + } + test { + name: "type" + expr: "type(int)" + value: { type_value: "type" } + } + test { + name: "type_denotation" + expr: "type" + value: { type_value: "type" } + } + test { + name: "type_type" + expr: "type(type)" + value: { type_value: "type" } + } +} +section { + name: "uint" + description: "Conversions to uint." + test { + name: "int" + expr: "uint(1729)" + value: { uint64_value: 1729 } + } + test { + name: "int_max" + expr: "uint(9223372036854775807)" + value { uint64_value: 9223372036854775807 } + } + test { + name: "int_neg" + expr: "uint(-1)" + eval_error { + errors { message: "range" } + } + } + test { + name: "double" + expr: "uint(3.14159265)" + value: { uint64_value: 3 } + } + test { + name: "double_truncate" + expr: "uint(1.9)" + value: { uint64_value: 1 } + } + test { + name: "double_half" + expr: "uint(25.5)" + value: { uint64_value: 25 } + } + test { + name: "double_big_exact" + description: "Beyond exact range (2^53), but no loss of precision (2^55)." + expr: "uint(double(36028797018963968u))" + value { uint64_value: 36028797018963968 } + } + test { + name: "double_big_precision" + description: "Beyond exact range (2^53), but loses precisons (2^55 + 1)." + expr: "uint(double(36028797018963969u))" + value { uint64_value: 36028797018963968 } + } + test { + name: "double_uint_max_range" + description: "The exact conversion of uint max as a double does not round trip." + expr: "int(18446744073709551615.0)" + eval_error { + errors: { message: "range" } + } + } + test { + name: "double_range_beyond_uint" + expr: "uint(6.022e23)" + eval_error { + errors { message: "range" } + } + } + test { + name: "string" + expr: "uint('300')" + value: { uint64_value: 300 } + } +} +section { + name: "bool" + description: "Conversions to bool" + test { + name: "string_1" + expr: "bool('1')" + value: { bool_value: true } + } + test { + name: "string_t" + expr: "bool('t')" + value: { bool_value: true } + } + test { + name: "string_true_lowercase" + expr: "bool('true')" + value: { bool_value: true } + } + test { + name: "string_true_uppercase" + expr: "bool('TRUE')" + value: { bool_value: true } + } + test { + name: "string_true_pascalcase" + expr: "bool('True')" + value: { bool_value: true } + } + test { + name: "string_0" + expr: "bool('0')" + value: { bool_value: false } + } + test { + name: "string_f" + expr: "bool('f')" + value: { bool_value: false } + } + test { + name: "string_false_lowercase" + expr: "bool('false')" + value: { bool_value: false } + } + test { + name: "string_false_uppercase" + expr: "bool('FALSE')" + value: { bool_value: false } + } + test { + name: "string_false_pascalcase" + expr: "bool('False')" + value: { bool_value: false } + } + test { + name: "string_true_badcase" + expr: "bool('TrUe')" + eval_error { + errors { message: "Type conversion error" } + } + } + test { + name: "string_false_badcase" + expr: "bool('FaLsE')" + eval_error { + errors { message: "Type conversion error" } + } + } +} +section { + name: "identity" + description: "Identity functions" + test { + name: "bool" + expr: "bool(true)" + value: { bool_value: true } + } + test { + name: "int" + expr: "int(1)" + value: { int64_value: 1 } + } + test { + name: "uint" + expr: "uint(1u)" + value: { uint64_value: 1 } + } + test { + name: "double" + expr: "double(5.5)" + value: { double_value: 5.5 } + } + test { + name: "string" + expr: "string('hello')" + value: { string_value: "hello" } + } + test { + name: "bytes" + expr: "bytes(b'abc')" + value: { bytes_value: "abc" } + } + test { + name: "duration" + expr: "duration(duration('100s')) == duration('100s')" + value: { bool_value: true } + } + test { + name: "timestamp" + expr: "timestamp(timestamp(1000000000)) == timestamp(1000000000)" + value: { bool_value: true } + } +} diff --git a/packages/cel/src/lib/conformance/testdata/dynamic.json b/packages/cel/src/lib/conformance/testdata/dynamic.json new file mode 100755 index 0000000..0e6d749 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/dynamic.json @@ -0,0 +1,2876 @@ +{ + "name": "dynamic", + "description": "Tests for 'dynamic' proto behavior, including JSON, wrapper, and Any messages.", + "section": [ + { + "name": "int32", + "description": "Tests for int32 conversion.", + "test": [ + { + "name": "literal", + "expr": "google.protobuf.Int32Value{value: -123}", + "value": { + "int64Value": "-123" + } + }, + { + "name": "literal_no_field_access", + "expr": "google.protobuf.Int32Value{value: -123}.value", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no_matching_overload" + } + ] + } + }, + { + "name": "literal_zero", + "expr": "google.protobuf.Int32Value{}", + "value": { + "int64Value": "0" + } + }, + { + "name": "var", + "expr": "x", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.protobuf.Int32Value" + } + } + } + ], + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.protobuf.Int32Value", + "value": 2000000 + } + } + } + }, + "value": { + "int64Value": "2000000" + } + }, + { + "name": "field_assign_proto2", + "expr": "TestAllTypes{single_int32_wrapper: 432}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleInt32Wrapper": 432 + } + } + }, + { + "name": "field_assign_proto2_zero", + "expr": "TestAllTypes{single_int32_wrapper: 0}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleInt32Wrapper": 0 + } + } + }, + { + "name": "field_assign_proto2_max", + "expr": "TestAllTypes{single_int32_wrapper: 2147483647}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleInt32Wrapper": 2147483647 + } + } + }, + { + "name": "field_assign_proto2_min", + "expr": "TestAllTypes{single_int32_wrapper: -2147483648}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleInt32Wrapper": -2147483648 + } + } + }, + { + "name": "field_assign_proto2_range", + "expr": "TestAllTypes{single_int32_wrapper: 12345678900}", + "container": "google.api.expr.test.v1.proto2", + "evalError": { + "errors": [ + { + "message": "range error" + } + ] + } + }, + { + "name": "field_read_proto2", + "expr": "TestAllTypes{single_int32_wrapper: 642}.single_int32_wrapper", + "container": "google.api.expr.test.v1.proto2", + "value": { + "int64Value": "642" + } + }, + { + "name": "field_read_proto2_zero", + "expr": "TestAllTypes{single_int32_wrapper: 0}.single_int32_wrapper", + "container": "google.api.expr.test.v1.proto2", + "value": { + "int64Value": "0" + } + }, + { + "name": "field_read_proto2_unset", + "expr": "TestAllTypes{}.single_int32_wrapper", + "container": "google.api.expr.test.v1.proto2", + "value": { + "nullValue": null + } + }, + { + "name": "field_assign_proto3", + "expr": "TestAllTypes{single_int32_wrapper: -975}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt32Wrapper": -975 + } + } + }, + { + "name": "field_assign_proto3_zero", + "expr": "TestAllTypes{single_int32_wrapper: 0}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt32Wrapper": 0 + } + } + }, + { + "name": "field_assign_proto3_max", + "expr": "TestAllTypes{single_int32_wrapper: 2147483647}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt32Wrapper": 2147483647 + } + } + }, + { + "name": "field_assign_proto3_min", + "expr": "TestAllTypes{single_int32_wrapper: -2147483648}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt32Wrapper": -2147483648 + } + } + }, + { + "name": "field_assign_proto3_range", + "expr": "TestAllTypes{single_int32_wrapper: -998877665544332211}", + "container": "google.api.expr.test.v1.proto3", + "evalError": { + "errors": [ + { + "message": "range error" + } + ] + } + }, + { + "name": "field_read_proto3", + "expr": "TestAllTypes{single_int32_wrapper: 642}.single_int32_wrapper", + "container": "google.api.expr.test.v1.proto3", + "value": { + "int64Value": "642" + } + }, + { + "name": "field_read_proto3_zero", + "expr": "TestAllTypes{single_int32_wrapper: 0}.single_int32_wrapper", + "container": "google.api.expr.test.v1.proto3", + "value": { + "int64Value": "0" + } + }, + { + "name": "field_read_proto3_unset", + "expr": "TestAllTypes{}.single_int32_wrapper", + "container": "google.api.expr.test.v1.proto3", + "value": { + "nullValue": null + } + } + ] + }, + { + "name": "int64", + "description": "Tests for int64 conversion.", + "test": [ + { + "name": "literal", + "expr": "google.protobuf.Int64Value{value: -123}", + "value": { + "int64Value": "-123" + } + }, + { + "name": "literal_no_field_access", + "expr": "google.protobuf.Int64Value{value: -123}.value", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no_matching_overload" + } + ] + } + }, + { + "name": "literal_zero", + "expr": "google.protobuf.Int64Value{}", + "value": { + "int64Value": "0" + } + }, + { + "name": "var", + "expr": "x", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.protobuf.Int64Value" + } + } + } + ], + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.protobuf.Int64Value", + "value": "2000000" + } + } + } + }, + "value": { + "int64Value": "2000000" + } + }, + { + "name": "field_assign_proto2", + "expr": "TestAllTypes{single_int64_wrapper: 432}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleInt64Wrapper": "432" + } + } + }, + { + "name": "field_assign_proto2_zero", + "expr": "TestAllTypes{single_int64_wrapper: 0}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleInt64Wrapper": "0" + } + } + }, + { + "name": "field_assign_proto3", + "expr": "TestAllTypes{single_int64_wrapper: -975}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt64Wrapper": "-975" + } + } + }, + { + "name": "field_assign_proto3_zero", + "expr": "TestAllTypes{single_int64_wrapper: 0}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt64Wrapper": "0" + } + } + } + ] + }, + { + "name": "uint32", + "description": "Tests for uint32 conversion.", + "test": [ + { + "name": "literal", + "expr": "google.protobuf.UInt32Value{value: 123u}", + "value": { + "uint64Value": "123" + } + }, + { + "name": "literal_no_field_access", + "expr": "google.protobuf.UInt32Value{value: 123u}.value", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no_matching_overload" + } + ] + } + }, + { + "name": "literal_zero", + "expr": "google.protobuf.UInt32Value{}", + "value": { + "uint64Value": "0" + } + }, + { + "name": "var", + "expr": "x", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.protobuf.UInt32Value" + } + } + } + ], + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.protobuf.UInt32Value", + "value": 2000000 + } + } + } + }, + "value": { + "uint64Value": "2000000" + } + }, + { + "name": "field_assign_proto2", + "expr": "TestAllTypes{single_uint32_wrapper: 432u}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleUint32Wrapper": 432 + } + } + }, + { + "name": "field_assign_proto2_zero", + "expr": "TestAllTypes{single_uint32_wrapper: 0u}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleUint32Wrapper": 0 + } + } + }, + { + "name": "field_assign_proto2_max", + "expr": "TestAllTypes{single_uint32_wrapper: 4294967295u}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleUint32Wrapper": 4294967295 + } + } + }, + { + "name": "field_assign_proto2_range", + "expr": "TestAllTypes{single_uint32_wrapper: 6111222333u}", + "container": "google.api.expr.test.v1.proto2", + "evalError": { + "errors": [ + { + "message": "range error" + } + ] + } + }, + { + "name": "field_assign_proto3", + "expr": "TestAllTypes{single_uint32_wrapper: 975u}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleUint32Wrapper": 975 + } + } + }, + { + "name": "field_assign_proto3_zero", + "expr": "TestAllTypes{single_uint32_wrapper: 0u}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleUint32Wrapper": 0 + } + } + }, + { + "name": "field_assign_proto3_max", + "expr": "TestAllTypes{single_uint32_wrapper: 4294967295u}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleUint32Wrapper": 4294967295 + } + } + }, + { + "name": "field_assign_proto3_range", + "expr": "TestAllTypes{single_uint32_wrapper: 6111222333u}", + "container": "google.api.expr.test.v1.proto3", + "evalError": { + "errors": [ + { + "message": "range error" + } + ] + } + }, + { + "name": "field_read_proto2", + "expr": "TestAllTypes{single_uint32_wrapper: 258u}.single_uint32_wrapper", + "container": "google.api.expr.test.v1.proto2", + "value": { + "uint64Value": "258" + } + }, + { + "name": "field_read_proto2_zero", + "expr": "TestAllTypes{single_uint32_wrapper: 0u}.single_uint32_wrapper", + "container": "google.api.expr.test.v1.proto2", + "value": { + "uint64Value": "0" + } + }, + { + "name": "field_read_proto2_unset", + "expr": "TestAllTypes{}.single_uint32_wrapper", + "container": "google.api.expr.test.v1.proto2", + "value": { + "nullValue": null + } + } + ] + }, + { + "name": "uint64", + "description": "Tests for uint64 conversion.", + "test": [ + { + "name": "literal", + "expr": "google.protobuf.UInt64Value{value: 123u}", + "value": { + "uint64Value": "123" + } + }, + { + "name": "literal_no_field_access", + "expr": "google.protobuf.UInt64Value{value: 123u}.value", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no_matching_overload" + } + ] + } + }, + { + "name": "literal_zero", + "expr": "google.protobuf.UInt64Value{}", + "value": { + "uint64Value": "0" + } + }, + { + "name": "var", + "expr": "x", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.protobuf.UInt64Value" + } + } + } + ], + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.protobuf.UInt64Value", + "value": "2000000" + } + } + } + }, + "value": { + "uint64Value": "2000000" + } + }, + { + "name": "field_assign_proto2", + "expr": "TestAllTypes{single_uint64_wrapper: 432u}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleUint64Wrapper": "432" + } + } + }, + { + "name": "field_assign_proto2_zero", + "expr": "TestAllTypes{single_uint64_wrapper: 0u}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleUint64Wrapper": "0" + } + } + }, + { + "name": "field_assign_proto3", + "expr": "TestAllTypes{single_uint64_wrapper: 975u}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleUint64Wrapper": "975" + } + } + }, + { + "name": "field_assign_proto3_zero", + "expr": "TestAllTypes{single_uint64_wrapper: 0u}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleUint64Wrapper": "0" + } + } + }, + { + "name": "field_read_proto2", + "expr": "TestAllTypes{single_uint64_wrapper: 5123123123u}.single_uint64_wrapper", + "container": "google.api.expr.test.v1.proto2", + "value": { + "uint64Value": "5123123123" + } + }, + { + "name": "field_read_proto2_zero", + "expr": "TestAllTypes{single_uint64_wrapper: 0u}.single_uint64_wrapper", + "container": "google.api.expr.test.v1.proto2", + "value": { + "uint64Value": "0" + } + }, + { + "name": "field_read_proto2_unset", + "expr": "TestAllTypes{}.single_uint64_wrapper", + "container": "google.api.expr.test.v1.proto2", + "value": { + "nullValue": null + } + } + ] + }, + { + "name": "float", + "description": "Tests for float conversion.", + "test": [ + { + "name": "literal", + "expr": "google.protobuf.FloatValue{value: -1.5e3}", + "value": { + "doubleValue": -1500 + } + }, + { + "name": "literal_not_double", + "description": "Use a number with no exact representation to make sure we actually narrow to a float.", + "expr": "google.protobuf.FloatValue{value: 1.333} == 1.333", + "value": { + "boolValue": false + } + }, + { + "name": "literal_no_field_access", + "expr": "google.protobuf.FloatValue{value: 3.1416}.value", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no_matching_overload" + } + ] + } + }, + { + "name": "literal_zero", + "expr": "google.protobuf.FloatValue{}", + "value": { + "doubleValue": 0 + } + }, + { + "name": "var", + "expr": "x", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.protobuf.FloatValue" + } + } + } + ], + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.protobuf.FloatValue", + "value": -1250000 + } + } + } + }, + "value": { + "doubleValue": -1250000 + } + }, + { + "name": "field_assign_proto2", + "expr": "TestAllTypes{single_float_wrapper: 86.75}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleFloatWrapper": 86.75 + } + } + }, + { + "name": "field_assign_proto2_zero", + "expr": "TestAllTypes{single_float_wrapper: 0.0}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleFloatWrapper": 0 + } + } + }, + { + "name": "field_assign_proto2_subnorm", + "description": "Subnormal single floats range from ~1e-38 to ~1e-45.", + "expr": "TestAllTypes{single_float_wrapper: 1e-40}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleFloatWrapper": 1e-40 + } + } + }, + { + "name": "field_assign_proto2_round_to_zero", + "description": "Subnormal single floats range from ~1e-38 to ~1e-45.", + "expr": "TestAllTypes{single_float_wrapper: 1e-50}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleFloatWrapper": 0 + } + } + }, + { + "name": "field_assign_proto2_range", + "description": "Single float max is about 3.4e38", + "expr": "TestAllTypes{single_float_wrapper: 1.4e55}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleFloatWrapper": "Infinity" + } + } + }, + { + "name": "field_read_proto2", + "expr": "TestAllTypes{single_float_wrapper: -12.375}.single_float_wrapper", + "container": "google.api.expr.test.v1.proto2", + "value": { + "doubleValue": -12.375 + } + }, + { + "name": "field_read_proto2_zero", + "expr": "TestAllTypes{single_float_wrapper: 0.0}.single_float_wrapper", + "container": "google.api.expr.test.v1.proto2", + "value": { + "doubleValue": 0 + } + }, + { + "name": "field_read_proto2_unset", + "expr": "TestAllTypes{}.single_float_wrapper", + "container": "google.api.expr.test.v1.proto2", + "value": { + "nullValue": null + } + }, + { + "name": "field_assign_proto3", + "expr": "TestAllTypes{single_float_wrapper: -9.75}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleFloatWrapper": -9.75 + } + } + }, + { + "name": "field_assign_proto3_zero", + "expr": "TestAllTypes{single_float_wrapper: 0.0}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleFloatWrapper": 0 + } + } + }, + { + "name": "field_assign_proto2_subnorm", + "description": "Subnormal single floats range from ~1e-38 to ~1e-45.", + "expr": "TestAllTypes{single_float_wrapper: 1e-40}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleFloatWrapper": 1e-40 + } + } + }, + { + "name": "field_assign_proto3_round_to_zero", + "expr": "TestAllTypes{single_float_wrapper: -9.9e-100}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleFloatWrapper": -0 + } + } + }, + { + "name": "field_assign_proto3_range", + "description": "Single float min is about -3.4e38", + "expr": "TestAllTypes{single_float_wrapper: -9.9e100}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleFloatWrapper": "-Infinity" + } + } + }, + { + "name": "field_read_proto3", + "expr": "TestAllTypes{single_float_wrapper: 64.25}.single_float_wrapper", + "container": "google.api.expr.test.v1.proto3", + "value": { + "doubleValue": 64.25 + } + }, + { + "name": "field_read_proto3_zero", + "expr": "TestAllTypes{single_float_wrapper: 0.0}.single_float_wrapper", + "container": "google.api.expr.test.v1.proto3", + "value": { + "doubleValue": 0 + } + }, + { + "name": "field_read_proto3_unset", + "expr": "TestAllTypes{}.single_float_wrapper", + "container": "google.api.expr.test.v1.proto3", + "value": { + "nullValue": null + } + } + ] + }, + { + "name": "double", + "description": "Tests for double conversion.", + "test": [ + { + "name": "literal", + "expr": "google.protobuf.DoubleValue{value: -1.5e3}", + "value": { + "doubleValue": -1500 + } + }, + { + "name": "literal_no_field_access", + "expr": "google.protobuf.DoubleValue{value: 3.1416}.value", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no_matching_overload" + } + ] + } + }, + { + "name": "literal_zero", + "expr": "google.protobuf.DoubleValue{}", + "value": { + "doubleValue": 0 + } + }, + { + "name": "var", + "expr": "x", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.protobuf.DoubleValue" + } + } + } + ], + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.protobuf.DoubleValue", + "value": -1250000 + } + } + } + }, + "value": { + "doubleValue": -1250000 + } + }, + { + "name": "field_assign_proto2", + "expr": "TestAllTypes{single_double_wrapper: 86.75}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleDoubleWrapper": 86.75 + } + } + }, + { + "name": "field_assign_proto2_zero", + "expr": "TestAllTypes{single_double_wrapper: 0.0}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleDoubleWrapper": 0 + } + } + }, + { + "name": "field_assign_proto2_range", + "expr": "TestAllTypes{single_double_wrapper: 1.4e55}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleDoubleWrapper": 1.4e+55 + } + } + }, + { + "name": "field_read_proto2", + "expr": "TestAllTypes{single_double_wrapper: -12.375}.single_double_wrapper", + "container": "google.api.expr.test.v1.proto2", + "value": { + "doubleValue": -12.375 + } + }, + { + "name": "field_read_proto2_zero", + "expr": "TestAllTypes{single_int32_wrapper: 0}.single_int32_wrapper", + "container": "google.api.expr.test.v1.proto2", + "value": { + "int64Value": "0" + } + }, + { + "name": "field_read_proto2_unset", + "expr": "TestAllTypes{}.single_double_wrapper", + "container": "google.api.expr.test.v1.proto2", + "value": { + "nullValue": null + } + }, + { + "name": "field_assign_proto3", + "expr": "TestAllTypes{single_double_wrapper: -9.75}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleDoubleWrapper": -9.75 + } + } + }, + { + "name": "field_assign_proto3_zero", + "expr": "TestAllTypes{single_double_wrapper: 0.0}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleDoubleWrapper": 0 + } + } + }, + { + "name": "field_assign_proto3_range", + "expr": "TestAllTypes{single_double_wrapper: -9.9e100}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleDoubleWrapper": -9.9e+100 + } + } + }, + { + "name": "field_read_proto3", + "expr": "TestAllTypes{single_double_wrapper: 64.25}.single_double_wrapper", + "container": "google.api.expr.test.v1.proto3", + "value": { + "doubleValue": 64.25 + } + }, + { + "name": "field_read_proto3_zero", + "expr": "TestAllTypes{single_double_wrapper: 0.0}.single_double_wrapper", + "container": "google.api.expr.test.v1.proto3", + "value": { + "doubleValue": 0 + } + }, + { + "name": "field_read_proto3_unset", + "expr": "TestAllTypes{}.single_double_wrapper", + "container": "google.api.expr.test.v1.proto3", + "value": { + "nullValue": null + } + } + ] + }, + { + "name": "bool", + "description": "Tests for bool conversion.", + "test": [ + { + "name": "literal", + "expr": "google.protobuf.BoolValue{value: true}", + "value": { + "boolValue": true + } + }, + { + "name": "literal_no_field_access", + "expr": "google.protobuf.BoolValue{value: true}.value", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no_matching_overload" + } + ] + } + }, + { + "name": "literal_empty", + "expr": "google.protobuf.BoolValue{}", + "value": { + "boolValue": false + } + }, + { + "name": "var", + "expr": "x", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.protobuf.BoolValue" + } + } + } + ], + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.protobuf.BoolValue", + "value": true + } + } + } + }, + "value": { + "boolValue": true + } + }, + { + "name": "field_assign_proto2", + "expr": "TestAllTypes{single_bool_wrapper: true}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleBoolWrapper": true + } + } + }, + { + "name": "field_assign_proto2_false", + "expr": "TestAllTypes{single_bool_wrapper: false}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleBoolWrapper": false + } + } + }, + { + "name": "field_assign_proto3", + "expr": "TestAllTypes{single_bool_wrapper: true}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleBoolWrapper": true + } + } + }, + { + "name": "field_assign_proto3_false", + "expr": "TestAllTypes{single_bool_wrapper: false}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleBoolWrapper": false + } + } + } + ] + }, + { + "name": "string", + "description": "Tests for string conversion.", + "test": [ + { + "name": "literal", + "expr": "google.protobuf.StringValue{value: 'foo'}", + "value": { + "stringValue": "foo" + } + }, + { + "name": "literal_no_field_access", + "expr": "google.protobuf.StringValue{value: 'foo'}.value", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no_matching_overload" + } + ] + } + }, + { + "name": "literal_empty", + "expr": "google.protobuf.StringValue{}", + "value": { + "stringValue": "" + } + }, + { + "name": "literal_unicode", + "expr": "google.protobuf.StringValue{value: 'flambé'}", + "value": { + "stringValue": "flambé" + } + }, + { + "name": "var", + "expr": "x", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.protobuf.StringValue" + } + } + } + ], + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.protobuf.StringValue", + "value": "bar" + } + } + } + }, + "value": { + "stringValue": "bar" + } + }, + { + "name": "field_assign_proto2", + "expr": "TestAllTypes{single_string_wrapper: 'baz'}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleStringWrapper": "baz" + } + } + }, + { + "name": "field_assign_proto2_empty", + "expr": "TestAllTypes{single_string_wrapper: ''}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleStringWrapper": "" + } + } + }, + { + "name": "field_assign_proto3", + "expr": "TestAllTypes{single_string_wrapper: 'bletch'}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleStringWrapper": "bletch" + } + } + }, + { + "name": "field_assign_proto3_empty", + "expr": "TestAllTypes{single_string_wrapper: ''}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleStringWrapper": "" + } + } + } + ] + }, + { + "name": "bytes", + "description": "Tests for bytes conversion.", + "test": [ + { + "name": "literal", + "expr": "google.protobuf.BytesValue{value: b'foo\\123'}", + "value": { + "bytesValue": "Zm9vUw==" + } + }, + { + "name": "literal_no_field_access", + "expr": "google.protobuf.BytesValue{value: b'foo'}.value", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no_matching_overload" + } + ] + } + }, + { + "name": "literal_empty", + "expr": "google.protobuf.BytesValue{}", + "value": { + "bytesValue": "" + } + }, + { + "name": "literal_unicode", + "expr": "google.protobuf.BytesValue{value: b'flambé'}", + "value": { + "bytesValue": "ZmxhbWLDqQ==" + } + }, + { + "name": "var", + "expr": "x", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.protobuf.BytesValue" + } + } + } + ], + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.protobuf.BytesValue", + "value": "YmFy" + } + } + } + }, + "value": { + "bytesValue": "YmFy" + } + }, + { + "name": "field_assign_proto2", + "expr": "TestAllTypes{single_bytes_wrapper: b'baz'}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleBytesWrapper": "YmF6" + } + } + }, + { + "name": "field_assign_proto2_empty", + "expr": "TestAllTypes{single_bytes_wrapper: b''}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleBytesWrapper": "" + } + } + }, + { + "name": "field_assign_proto3", + "expr": "TestAllTypes{single_bytes_wrapper: b'bletch'}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleBytesWrapper": "YmxldGNo" + } + } + }, + { + "name": "field_assign_proto3_empty", + "expr": "TestAllTypes{single_bytes_wrapper: b''}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleBytesWrapper": "" + } + } + } + ] + }, + { + "name": "list", + "description": "Tests for list conversion.", + "test": [ + { + "name": "literal", + "expr": "google.protobuf.ListValue{values: [3.0, 'foo', null]}", + "value": { + "listValue": { + "values": [ + { + "doubleValue": 3 + }, + { + "stringValue": "foo" + }, + { + "nullValue": null + } + ] + } + } + }, + { + "name": "literal_no_field_access", + "expr": "google.protobuf.ListValue{values: [3.0, 'foo', null]}.values", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no_matching_overload" + } + ] + } + }, + { + "name": "literal_empty", + "expr": "google.protobuf.ListValue{values: []}", + "value": { + "listValue": {} + } + }, + { + "name": "var", + "expr": "x", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.protobuf.ListValue" + } + } + } + ], + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.protobuf.ListValue", + "value": [ + "bar", + [ + "a", + "b" + ] + ] + } + } + } + }, + "value": { + "listValue": { + "values": [ + { + "stringValue": "bar" + }, + { + "listValue": { + "values": [ + { + "stringValue": "a" + }, + { + "stringValue": "b" + } + ] + } + } + ] + } + } + }, + { + "name": "field_assign_proto2", + "expr": "TestAllTypes{list_value: [1.0, 'one']}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "listValue": [ + 1, + "one" + ] + } + } + }, + { + "name": "field_assign_proto2_empty", + "expr": "TestAllTypes{list_value: []}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "listValue": [] + } + } + }, + { + "name": "field_read_proto2", + "expr": "TestAllTypes{list_value: [1.0, 'one']}.list_value", + "container": "google.api.expr.test.v1.proto2", + "value": { + "listValue": { + "values": [ + { + "doubleValue": 1 + }, + { + "stringValue": "one" + } + ] + } + } + }, + { + "name": "field_read_proto2_empty", + "expr": "TestAllTypes{list_value: []}.list_value", + "container": "google.api.expr.test.v1.proto2", + "value": { + "listValue": {} + } + }, + { + "name": "field_read_proto2_unset", + "description": "Not a wrapper type, so doesn't convert to null.", + "expr": "TestAllTypes{}.list_value", + "container": "google.api.expr.test.v1.proto2", + "value": { + "listValue": {} + } + }, + { + "name": "field_assign_proto3", + "expr": "TestAllTypes{list_value: [1.0, 'one']}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "listValue": [ + 1, + "one" + ] + } + } + }, + { + "name": "field_assign_proto3_empty", + "expr": "TestAllTypes{list_value: []}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "listValue": [] + } + } + }, + { + "name": "field_read_proto3", + "expr": "TestAllTypes{list_value: [1.0, 'one']}.list_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "listValue": { + "values": [ + { + "doubleValue": 1 + }, + { + "stringValue": "one" + } + ] + } + } + }, + { + "name": "field_read_proto3_empty", + "expr": "TestAllTypes{list_value: []}.list_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "listValue": {} + } + }, + { + "name": "field_read_proto3_unset", + "description": "Not a wrapper type, so doesn't convert to null.", + "expr": "TestAllTypes{}.list_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "listValue": {} + } + } + ] + }, + { + "name": "struct", + "description": "Tests for struct conversion.", + "test": [ + { + "name": "literal", + "expr": "google.protobuf.Struct{fields: {'uno': 1.0, 'dos': 2.0}}", + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "uno" + }, + "value": { + "doubleValue": 1 + } + }, + { + "key": { + "stringValue": "dos" + }, + "value": { + "doubleValue": 2 + } + } + ] + } + } + }, + { + "name": "literal_no_field_access", + "expr": "google.protobuf.Struct{fields: {'uno': 1.0, 'dos': 2.0}}.fields", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no_matching_overload" + } + ] + } + }, + { + "name": "literal_empty", + "expr": "google.protobuf.Struct{fields: {}}", + "value": { + "mapValue": {} + } + }, + { + "name": "var", + "expr": "x", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.protobuf.Struct" + } + } + } + ], + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.protobuf.Struct", + "value": { + "first": "Abraham", + "last": "Lincoln" + } + } + } + } + }, + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "first" + }, + "value": { + "stringValue": "Abraham" + } + }, + { + "key": { + "stringValue": "last" + }, + "value": { + "stringValue": "Lincoln" + } + } + ] + } + } + }, + { + "name": "field_assign_proto2", + "expr": "TestAllTypes{single_struct: {'un': 1.0, 'deux': 2.0}}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleStruct": { + "deux": 2, + "un": 1 + } + } + } + }, + { + "name": "field_assign_proto2_empty", + "expr": "TestAllTypes{single_struct: {}}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleStruct": {} + } + } + }, + { + "name": "field_assign_proto2_bad", + "expr": "TestAllTypes{single_struct: {1: 'uno'}}", + "disableCheck": true, + "container": "google.api.expr.test.v1.proto2", + "evalError": { + "errors": [ + { + "message": "bad key type" + } + ] + } + }, + { + "name": "field_read_proto2", + "expr": "TestAllTypes{single_struct: {'one': 1.0}}.single_struct", + "container": "google.api.expr.test.v1.proto2", + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "one" + }, + "value": { + "doubleValue": 1 + } + } + ] + } + } + }, + { + "name": "field_read_proto2_empty", + "expr": "TestAllTypes{single_struct: {}}.single_struct", + "container": "google.api.expr.test.v1.proto2", + "value": { + "mapValue": {} + } + }, + { + "name": "field_read_proto2_unset", + "description": "Not a wrapper type, so doesn't convert to null.", + "expr": "TestAllTypes{}.single_struct", + "container": "google.api.expr.test.v1.proto2", + "value": { + "mapValue": {} + } + }, + { + "name": "field_assign_proto3", + "expr": "TestAllTypes{single_struct: {'un': 1.0, 'deux': 2.0}}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleStruct": { + "deux": 2, + "un": 1 + } + } + } + }, + { + "name": "field_assign_proto3_empty", + "expr": "TestAllTypes{single_struct: {}}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleStruct": {} + } + } + }, + { + "name": "field_assign_proto3_bad", + "expr": "TestAllTypes{single_struct: {1: 'uno'}}", + "disableCheck": true, + "container": "google.api.expr.test.v1.proto3", + "evalError": { + "errors": [ + { + "message": "bad key type" + } + ] + } + }, + { + "name": "field_read_proto3", + "expr": "TestAllTypes{single_struct: {'one': 1.0}}.single_struct", + "container": "google.api.expr.test.v1.proto3", + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "one" + }, + "value": { + "doubleValue": 1 + } + } + ] + } + } + }, + { + "name": "field_read_proto3_empty", + "expr": "TestAllTypes{single_struct: {}}.single_struct", + "container": "google.api.expr.test.v1.proto3", + "value": { + "mapValue": {} + } + }, + { + "name": "field_read_proto3_unset", + "description": "Not a wrapper type, so doesn't convert to null.", + "expr": "TestAllTypes{}.single_struct", + "container": "google.api.expr.test.v1.proto3", + "value": { + "mapValue": {} + } + } + ] + }, + { + "name": "value_null", + "description": "Tests for null conversions.", + "test": [ + { + "name": "literal", + "expr": "Value{null_value: NullValue.NULL_VALUE}", + "container": "google.protobuf", + "value": { + "nullValue": null + } + }, + { + "name": "literal_no_field_access", + "expr": "Value{null_value: NullValue.NULL_VALUE}.null_value", + "disableCheck": true, + "container": "google.protobuf", + "evalError": { + "errors": [ + { + "message": "no_matching_overload" + } + ] + } + }, + { + "name": "literal_unset", + "expr": "google.protobuf.Value{}", + "value": { + "nullValue": null + } + }, + { + "name": "var", + "expr": "x", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.protobuf.Value" + } + } + } + ], + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.protobuf.Value", + "value": null + } + } + } + }, + "value": { + "nullValue": null + } + }, + { + "name": "field_assign_proto2", + "expr": "TestAllTypes{single_value: null}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleValue": null + } + } + }, + { + "name": "field_read_proto2", + "expr": "TestAllTypes{single_value: null}.single_value", + "container": "google.api.expr.test.v1.proto2", + "value": { + "nullValue": null + } + }, + { + "name": "field_read_proto2_unset", + "expr": "TestAllTypes{}.single_value", + "container": "google.api.expr.test.v1.proto2", + "value": { + "nullValue": null + } + }, + { + "name": "field_assign_proto3", + "expr": "TestAllTypes{single_value: null}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleValue": null + } + } + }, + { + "name": "field_read_proto3", + "expr": "TestAllTypes{single_value: null}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "nullValue": null + } + }, + { + "name": "field_read_proto3_unset", + "expr": "TestAllTypes{}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "nullValue": null + } + } + ] + }, + { + "name": "value_number", + "description": "Tests for number conversions in Value.", + "test": [ + { + "name": "literal", + "expr": "google.protobuf.Value{number_value: 12.5}", + "value": { + "doubleValue": 12.5 + } + }, + { + "name": "literal_no_field_access", + "expr": "google.protobuf.Value{number_value: 12.5}.number_value", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no_matching_overload" + } + ] + } + }, + { + "name": "literal_zero", + "expr": "google.protobuf.Value{number_value: 0.0}", + "value": { + "doubleValue": 0 + } + }, + { + "name": "var", + "expr": "x", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.protobuf.Value" + } + } + } + ], + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.protobuf.Value", + "value": -26.375 + } + } + } + }, + "value": { + "doubleValue": -26.375 + } + }, + { + "name": "field_assign_proto2", + "expr": "TestAllTypes{single_value: 7e23}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleValue": 7e+23 + } + } + }, + { + "name": "field_assign_proto2_zero", + "expr": "TestAllTypes{single_value: 0.0}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleValue": 0 + } + } + }, + { + "name": "field_read_proto2", + "expr": "TestAllTypes{single_value: 7e23}.single_value", + "container": "google.api.expr.test.v1.proto2", + "value": { + "doubleValue": 7e+23 + } + }, + { + "name": "field_read_proto2_zero", + "expr": "TestAllTypes{single_value: 0.0}.single_value", + "container": "google.api.expr.test.v1.proto2", + "value": { + "doubleValue": 0 + } + }, + { + "name": "field_assign_proto3", + "expr": "TestAllTypes{single_value: 7e23}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleValue": 7e+23 + } + } + }, + { + "name": "field_assign_proto3_zero", + "expr": "TestAllTypes{single_value: 0.0}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleValue": 0 + } + } + }, + { + "name": "field_read_proto3", + "expr": "TestAllTypes{single_value: 7e23}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "doubleValue": 7e+23 + } + }, + { + "name": "field_read_proto3_zero", + "expr": "TestAllTypes{single_value: 0.0}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "doubleValue": 0 + } + } + ] + }, + { + "name": "value_string", + "description": "Tests for string conversions in Value.", + "test": [ + { + "name": "literal", + "expr": "google.protobuf.Value{string_value: 'foo'}", + "value": { + "stringValue": "foo" + } + }, + { + "name": "literal_no_field_access", + "expr": "google.protobuf.Value{string_value: 'foo'}.string_value", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no_matching_overload" + } + ] + } + }, + { + "name": "literal_empty", + "expr": "google.protobuf.Value{string_value: ''}", + "value": { + "stringValue": "" + } + }, + { + "name": "var", + "expr": "x", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.protobuf.Value" + } + } + } + ], + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.protobuf.Value", + "value": "bar" + } + } + } + }, + "value": { + "stringValue": "bar" + } + }, + { + "name": "field_assign_proto2", + "expr": "TestAllTypes{single_value: 'baz'}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleValue": "baz" + } + } + }, + { + "name": "field_assign_proto2_empty", + "expr": "TestAllTypes{single_value: ''}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleValue": "" + } + } + }, + { + "name": "field_read_proto2", + "expr": "TestAllTypes{single_value: 'bletch'}.single_value", + "container": "google.api.expr.test.v1.proto2", + "value": { + "stringValue": "bletch" + } + }, + { + "name": "field_read_proto2_zero", + "expr": "TestAllTypes{single_value: ''}.single_value", + "container": "google.api.expr.test.v1.proto2", + "value": { + "stringValue": "" + } + }, + { + "name": "field_assign_proto3", + "expr": "TestAllTypes{single_value: 'baz'}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleValue": "baz" + } + } + }, + { + "name": "field_assign_proto3_empty", + "expr": "TestAllTypes{single_value: ''}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleValue": "" + } + } + }, + { + "name": "field_read_proto3", + "expr": "TestAllTypes{single_value: 'bletch'}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "stringValue": "bletch" + } + }, + { + "name": "field_read_proto3_zero", + "expr": "TestAllTypes{single_value: ''}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "stringValue": "" + } + } + ] + }, + { + "name": "value_bool", + "description": "Tests for boolean conversions in Value.", + "test": [ + { + "name": "literal", + "expr": "google.protobuf.Value{bool_value: true}", + "value": { + "boolValue": true + } + }, + { + "name": "literal_no_field_access", + "expr": "google.protobuf.Value{bool_value: true}.bool_value", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no_matching_overload" + } + ] + } + }, + { + "name": "literal_false", + "expr": "google.protobuf.Value{bool_value: false}", + "value": { + "boolValue": false + } + }, + { + "name": "var", + "expr": "x", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.protobuf.Value" + } + } + } + ], + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.protobuf.Value", + "value": true + } + } + } + }, + "value": { + "boolValue": true + } + }, + { + "name": "field_assign_proto2", + "expr": "TestAllTypes{single_value: true}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleValue": true + } + } + }, + { + "name": "field_assign_proto2_false", + "expr": "TestAllTypes{single_value: false}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleValue": false + } + } + }, + { + "name": "field_read_proto2", + "expr": "TestAllTypes{single_value: true}.single_value", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "field_read_proto2_false", + "expr": "TestAllTypes{single_value: false}.single_value", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": false + } + }, + { + "name": "field_assign_proto3", + "expr": "TestAllTypes{single_value: true}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleValue": true + } + } + }, + { + "name": "field_assign_proto3_false", + "expr": "TestAllTypes{single_value: false}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleValue": false + } + } + }, + { + "name": "field_read_proto3", + "expr": "TestAllTypes{single_value: true}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "field_read_proto3_false", + "expr": "TestAllTypes{single_value: false}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": false + } + } + ] + }, + { + "name": "value_struct", + "description": "Tests for struct conversions in Value.", + "test": [ + { + "name": "literal", + "expr": "google.protobuf.Value{struct_value: {'a': 1.0, 'b': 'two'}}", + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "a" + }, + "value": { + "doubleValue": 1 + } + }, + { + "key": { + "stringValue": "b" + }, + "value": { + "stringValue": "two" + } + } + ] + } + } + }, + { + "name": "literal_no_field_access", + "expr": "google.protobuf.Value{struct_value: {'a': 1.0, 'b': 'two'}}.struct_value", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no_matching_overload" + } + ] + } + }, + { + "name": "literal_empty", + "expr": "google.protobuf.Value{struct_value: {}}", + "value": { + "mapValue": {} + } + }, + { + "name": "var", + "expr": "x", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.protobuf.Value" + } + } + } + ], + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.protobuf.Value", + "value": { + "x": null, + "y": false + } + } + } + } + }, + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "x" + }, + "value": { + "nullValue": null + } + }, + { + "key": { + "stringValue": "y" + }, + "value": { + "boolValue": false + } + } + ] + } + } + }, + { + "name": "field_assign_proto2", + "expr": "TestAllTypes{single_value: {'un': 1.0, 'deux': 2.0}}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleValue": { + "deux": 2, + "un": 1 + } + } + } + }, + { + "name": "field_assign_proto2_empty", + "expr": "TestAllTypes{single_value: {}}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleValue": {} + } + } + }, + { + "name": "field_read_proto2", + "expr": "TestAllTypes{single_value: {'i': true}}.single_value", + "container": "google.api.expr.test.v1.proto2", + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "i" + }, + "value": { + "boolValue": true + } + } + ] + } + } + }, + { + "name": "field_read_proto2_empty", + "expr": "TestAllTypes{single_value: {}}.single_value", + "container": "google.api.expr.test.v1.proto2", + "value": { + "mapValue": {} + } + }, + { + "name": "field_assign_proto3", + "expr": "TestAllTypes{single_value: {'un': 1.0, 'deux': 2.0}}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleValue": { + "deux": 2, + "un": 1 + } + } + } + }, + { + "name": "field_assign_proto3_empty", + "expr": "TestAllTypes{single_value: {}}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleValue": {} + } + } + }, + { + "name": "field_read_proto3", + "expr": "TestAllTypes{single_value: {'i': true}}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "i" + }, + "value": { + "boolValue": true + } + } + ] + } + } + }, + { + "name": "field_read_proto3_empty", + "expr": "TestAllTypes{single_value: {}}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "mapValue": {} + } + } + ] + }, + { + "name": "value_list", + "description": "Tests for list conversions in Value.", + "test": [ + { + "name": "literal", + "expr": "google.protobuf.Value{list_value: ['a', 3.0]}", + "value": { + "listValue": { + "values": [ + { + "stringValue": "a" + }, + { + "doubleValue": 3 + } + ] + } + } + }, + { + "name": "literal_no_field_access", + "expr": "google.protobuf.Value{list_value: []}.list_value", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no_matching_overload" + } + ] + } + }, + { + "name": "literal_empty", + "expr": "google.protobuf.Value{list_value: []}", + "value": { + "listValue": {} + } + }, + { + "name": "var", + "expr": "x", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.protobuf.Value" + } + } + } + ], + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.protobuf.Value", + "value": [ + 1, + true, + "hi" + ] + } + } + } + }, + "value": { + "listValue": { + "values": [ + { + "doubleValue": 1 + }, + { + "boolValue": true + }, + { + "stringValue": "hi" + } + ] + } + } + }, + { + "name": "field_assign_proto2", + "expr": "TestAllTypes{single_value: ['un', 1.0]}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleValue": [ + "un", + 1 + ] + } + } + }, + { + "name": "field_assign_proto2_empty", + "expr": "TestAllTypes{single_value: []}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleValue": [] + } + } + }, + { + "name": "field_read_proto2", + "expr": "TestAllTypes{single_value: ['i', true]}.single_value", + "container": "google.api.expr.test.v1.proto2", + "value": { + "listValue": { + "values": [ + { + "stringValue": "i" + }, + { + "boolValue": true + } + ] + } + } + }, + { + "name": "field_read_proto2_empty", + "expr": "TestAllTypes{single_value: []}.single_value", + "container": "google.api.expr.test.v1.proto2", + "value": { + "listValue": {} + } + }, + { + "name": "field_assign_proto3", + "expr": "TestAllTypes{single_value: ['un', 1.0]}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleValue": [ + "un", + 1 + ] + } + } + }, + { + "name": "field_assign_proto3_empty", + "expr": "TestAllTypes{single_value: []}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleValue": [] + } + } + }, + { + "name": "field_read_proto3", + "expr": "TestAllTypes{single_value: ['i', true]}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "listValue": { + "values": [ + { + "stringValue": "i" + }, + { + "boolValue": true + } + ] + } + } + }, + { + "name": "field_read_proto3_empty", + "expr": "TestAllTypes{single_value: []}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "listValue": {} + } + } + ] + }, + { + "name": "any", + "description": "Tests for Any conversion.", + "test": [ + { + "name": "literal", + "expr": "google.protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\x08\\x96\\x01'}", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleInt32": 150 + } + } + }, + { + "name": "literal_no_field_access", + "expr": "google.protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\x08\\x96\\x01'}.type_url", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no_matching_overload" + } + ] + } + }, + { + "name": "literal_empty", + "expr": "google.protobuf.Any{}", + "evalError": { + "errors": [ + { + "message": "conversion" + } + ] + } + }, + { + "name": "var", + "expr": "x", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.protubuf.Any" + } + } + } + ], + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.protobuf.Any", + "value": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleInt32": 150 + } + } + } + } + }, + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleInt32": 150 + } + } + }, + { + "name": "field_assign_proto2", + "expr": "TestAllTypes{single_any: TestAllTypes{single_int32: 150}}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleAny": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleInt32": 150 + } + } + } + }, + { + "name": "field_read_proto2", + "expr": "TestAllTypes{single_any: TestAllTypes{single_int32: 150}}.single_any", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleInt32": 150 + } + } + }, + { + "name": "field_assign_proto3", + "expr": "TestAllTypes{single_any: TestAllTypes{single_int32: 150}}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleAny": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt32": 150 + } + } + } + }, + { + "name": "field_read_proto3", + "expr": "TestAllTypes{single_any: TestAllTypes{single_int32: 150}}.single_any", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt32": 150 + } + } + } + ] + }, + { + "name": "complex", + "description": "Tests combining various dynamic conversions.", + "test": [ + { + "name": "any_list_map", + "expr": "TestAllTypes{single_any: [{'almost': 'done'}]}.single_any", + "container": "google.api.expr.test.v1.proto3", + "value": { + "listValue": { + "values": [ + { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "almost" + }, + "value": { + "stringValue": "done" + } + } + ] + } + } + ] + } + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/dynamic.textproto b/packages/cel/src/lib/conformance/testdata/dynamic.textproto new file mode 100644 index 0000000..c89df02 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/dynamic.textproto @@ -0,0 +1,2288 @@ +name: "dynamic" +description: "Tests for 'dynamic' proto behavior, including JSON, wrapper, and Any messages." +section { + name: "int32" + description: "Tests for int32 conversion." + test { + name: "literal" + expr: "google.protobuf.Int32Value{value: -123}" + value { int64_value: -123 } + } + test { + name: "literal_no_field_access" + expr: "google.protobuf.Int32Value{value: -123}.value" + disable_check: true + eval_error { + errors { message: "no_matching_overload" } + } + } + test { + name: "literal_zero" + expr: "google.protobuf.Int32Value{}" + value { int64_value: 0 } + } + test { + name: "var" + expr: "x" + type_env { + name: "x" + ident { type { message_type: "google.protobuf.Int32Value" } } + } + bindings { + key: "x" + value { value { object_value { + [type.googleapis.com/google.protobuf.Int32Value] + { value: 2000000 } + } } } + } + value { int64_value: 2000000 } + } + test { + name: "field_assign_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_int32_wrapper: 432}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_int32_wrapper { value: 432 } } + } + } + } + test { + name: "field_assign_proto2_zero" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_int32_wrapper: 0}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_int32_wrapper { } } + } + } + } + test { + name: "field_assign_proto2_max" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_int32_wrapper: 2147483647}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_int32_wrapper { value: 2147483647 } } + } + } + } + test { + name: "field_assign_proto2_min" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_int32_wrapper: -2147483648}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_int32_wrapper { value: -2147483648 } } + } + } + } + test { + name: "field_assign_proto2_range" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_int32_wrapper: 12345678900}" + eval_error { + errors { message: "range error" } + } + } + test { + name: "field_read_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_int32_wrapper: 642}.single_int32_wrapper" + value { int64_value: 642 } + } + test { + name: "field_read_proto2_zero" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_int32_wrapper: 0}.single_int32_wrapper" + value { int64_value: 0 } + } + test { + name: "field_read_proto2_unset" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.single_int32_wrapper" + value { null_value: NULL_VALUE } + } + test { + name: "field_assign_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_int32_wrapper: -975}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_int32_wrapper { value: -975 } } + } + } + } + test { + name: "field_assign_proto3_zero" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_int32_wrapper: 0}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_int32_wrapper { } } + } + } + } + test { + name: "field_assign_proto3_max" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_int32_wrapper: 2147483647}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_int32_wrapper { value: 2147483647 } } + } + } + } + test { + name: "field_assign_proto3_min" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_int32_wrapper: -2147483648}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_int32_wrapper { value: -2147483648 } } + } + } + } + test { + name: "field_assign_proto3_range" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_int32_wrapper: -998877665544332211}" + eval_error { + errors { message: "range error" } + } + } + test { + name: "field_read_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_int32_wrapper: 642}.single_int32_wrapper" + value { int64_value: 642 } + } + test { + name: "field_read_proto3_zero" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_int32_wrapper: 0}.single_int32_wrapper" + value { int64_value: 0 } + } + test { + name: "field_read_proto3_unset" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.single_int32_wrapper" + value { null_value: NULL_VALUE } + } +} +section { + name: "int64" + description: "Tests for int64 conversion." + test { + name: "literal" + expr: "google.protobuf.Int64Value{value: -123}" + value { int64_value: -123 } + } + test { + name: "literal_no_field_access" + expr: "google.protobuf.Int64Value{value: -123}.value" + disable_check: true + eval_error { + errors { message: "no_matching_overload" } + } + } + test { + name: "literal_zero" + expr: "google.protobuf.Int64Value{}" + value { int64_value: 0 } + } + test { + name: "var" + expr: "x" + type_env { + name: "x" + ident { type { message_type: "google.protobuf.Int64Value" } } + } + bindings { + key: "x" + value { value { object_value { + [type.googleapis.com/google.protobuf.Int64Value] + { value: 2000000 } + } } } + } + value { int64_value: 2000000 } + } + test { + name: "field_assign_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_int64_wrapper: 432}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_int64_wrapper { value: 432 } } + } + } + } + test { + name: "field_assign_proto2_zero" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_int64_wrapper: 0}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_int64_wrapper { } } + } + } + } + test { + name: "field_assign_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_int64_wrapper: -975}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_int64_wrapper { value: -975 } } + } + } + } + test { + name: "field_assign_proto3_zero" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_int64_wrapper: 0}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_int64_wrapper { } } + } + } + } +} +section { + name: "uint32" + description: "Tests for uint32 conversion." + test { + name: "literal" + expr: "google.protobuf.UInt32Value{value: 123u}" + value { uint64_value: 123 } + } + test { + name: "literal_no_field_access" + expr: "google.protobuf.UInt32Value{value: 123u}.value" + disable_check: true + eval_error { + errors { message: "no_matching_overload" } + } + } + test { + name: "literal_zero" + expr: "google.protobuf.UInt32Value{}" + value { uint64_value: 0 } + } + test { + name: "var" + expr: "x" + type_env { + name: "x" + ident { type { message_type: "google.protobuf.UInt32Value" } } + } + bindings { + key: "x" + value { value { object_value { + [type.googleapis.com/google.protobuf.UInt32Value] + { value: 2000000 } + } } } + } + value { uint64_value: 2000000 } + } + test { + name: "field_assign_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_uint32_wrapper: 432u}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_uint32_wrapper { value: 432 } } + } + } + } + test { + name: "field_assign_proto2_zero" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_uint32_wrapper: 0u}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_uint32_wrapper { } } + } + } + } + test { + name: "field_assign_proto2_max" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_uint32_wrapper: 4294967295u}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_uint32_wrapper { value: 4294967295} } + } + } + } + test { + name: "field_assign_proto2_range" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_uint32_wrapper: 6111222333u}" + eval_error { + errors { message: "range error" } + } + } + test { + name: "field_assign_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_uint32_wrapper: 975u}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_uint32_wrapper { value: 975 } } + } + } + } + test { + name: "field_assign_proto3_zero" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_uint32_wrapper: 0u}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_uint32_wrapper { } } + } + } + } + test { + name: "field_assign_proto3_max" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_uint32_wrapper: 4294967295u}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_uint32_wrapper { value: 4294967295 } } + } + } + } + test { + name: "field_assign_proto3_range" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_uint32_wrapper: 6111222333u}" + eval_error { + errors { message: "range error" } + } + } + test { + name: "field_read_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_uint32_wrapper: 258u}.single_uint32_wrapper" + value { uint64_value: 258 } + } + test { + name: "field_read_proto2_zero" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_uint32_wrapper: 0u}.single_uint32_wrapper" + value { uint64_value: 0 } + } + test { + name: "field_read_proto2_unset" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.single_uint32_wrapper" + value { null_value: NULL_VALUE } + } +} +section { + name: "uint64" + description: "Tests for uint64 conversion." + test { + name: "literal" + expr: "google.protobuf.UInt64Value{value: 123u}" + value { uint64_value: 123 } + } + test { + name: "literal_no_field_access" + expr: "google.protobuf.UInt64Value{value: 123u}.value" + disable_check: true + eval_error { + errors { message: "no_matching_overload" } + } + } + test { + name: "literal_zero" + expr: "google.protobuf.UInt64Value{}" + value { uint64_value: 0 } + } + test { + name: "var" + expr: "x" + type_env { + name: "x" + ident { type { message_type: "google.protobuf.UInt64Value" } } + } + bindings { + key: "x" + value { value { object_value { + [type.googleapis.com/google.protobuf.UInt64Value] + { value: 2000000 } + } } } + } + value { uint64_value: 2000000 } + } + test { + name: "field_assign_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_uint64_wrapper: 432u}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_uint64_wrapper { value: 432 } } + } + } + } + test { + name: "field_assign_proto2_zero" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_uint64_wrapper: 0u}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_uint64_wrapper { } } + } + } + } + test { + name: "field_assign_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_uint64_wrapper: 975u}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_uint64_wrapper { value: 975 } } + } + } + } + test { + name: "field_assign_proto3_zero" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_uint64_wrapper: 0u}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_uint64_wrapper { } } + } + } + } + test { + name: "field_read_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_uint64_wrapper: 5123123123u}.single_uint64_wrapper" + value { uint64_value: 5123123123 } + } + test { + name: "field_read_proto2_zero" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_uint64_wrapper: 0u}.single_uint64_wrapper" + value { uint64_value: 0 } + } + test { + name: "field_read_proto2_unset" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.single_uint64_wrapper" + value { null_value: NULL_VALUE } + } +} +section { + name: "float" + description: "Tests for float conversion." + test { + name: "literal" + expr: "google.protobuf.FloatValue{value: -1.5e3}" + value { double_value: -1500.0 } + } + test { + name: "literal_not_double" + description: "Use a number with no exact representation to make sure we actually narrow to a float." + expr: "google.protobuf.FloatValue{value: 1.333} == 1.333" + value { bool_value: false } + } + test { + name: "literal_no_field_access" + expr: "google.protobuf.FloatValue{value: 3.1416}.value" + disable_check: true + eval_error { + errors { message: "no_matching_overload" } + } + } + test { + name: "literal_zero" + expr: "google.protobuf.FloatValue{}" + value { double_value: 0.0 } + } + test { + name: "var" + expr: "x" + type_env { + name: "x" + ident { type { message_type: "google.protobuf.FloatValue" } } + } + bindings { + key: "x" + value { value { object_value { + [type.googleapis.com/google.protobuf.FloatValue] + { value: -1.25e6 } + } } } + } + value { double_value: -1250000.0 } + } + test { + name: "field_assign_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_float_wrapper: 86.75}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_float_wrapper { value: 86.75 } } + } + } + } + test { + name: "field_assign_proto2_zero" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_float_wrapper: 0.0}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_float_wrapper { } } + } + } + } + test { + name: "field_assign_proto2_subnorm" + description: "Subnormal single floats range from ~1e-38 to ~1e-45." + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_float_wrapper: 1e-40}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_float_wrapper { value: 1e-40 } } + } + } + } + test { + name: "field_assign_proto2_round_to_zero" + description: "Subnormal single floats range from ~1e-38 to ~1e-45." + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_float_wrapper: 1e-50}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_float_wrapper { } } + } + } + } + test { + name: "field_assign_proto2_range" + description: "Single float max is about 3.4e38" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_float_wrapper: 1.4e55}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_float_wrapper { value: inf } } + } + } + } + test { + name: "field_read_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_float_wrapper: -12.375}.single_float_wrapper" + value { double_value: -12.375 } + } + test { + name: "field_read_proto2_zero" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_float_wrapper: 0.0}.single_float_wrapper" + value { double_value: 0.0 } + } + test { + name: "field_read_proto2_unset" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.single_float_wrapper" + value { null_value: NULL_VALUE } + } + test { + name: "field_assign_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_float_wrapper: -9.75}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_float_wrapper { value: -9.75 } } + } + } + } + test { + name: "field_assign_proto3_zero" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_float_wrapper: 0.0}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_float_wrapper { } } + } + } + } + test { + name: "field_assign_proto2_subnorm" + description: "Subnormal single floats range from ~1e-38 to ~1e-45." + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_float_wrapper: 1e-40}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_float_wrapper { value: 1e-40 } } + } + } + } + test { + name: "field_assign_proto3_round_to_zero" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_float_wrapper: -9.9e-100}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_float_wrapper { value: -0 } } + } + } + } + test { + name: "field_assign_proto3_range" + description: "Single float min is about -3.4e38" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_float_wrapper: -9.9e100}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_float_wrapper { value: -inf } } + } + } + } + test { + name: "field_read_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_float_wrapper: 64.25}.single_float_wrapper" + value { double_value: 64.25 } + } + test { + name: "field_read_proto3_zero" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_float_wrapper: 0.0}.single_float_wrapper" + value { double_value: 0.0 } + } + test { + name: "field_read_proto3_unset" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.single_float_wrapper" + value { null_value: NULL_VALUE } + } +} +section { + name: "double" + description: "Tests for double conversion." + test { + name: "literal" + expr: "google.protobuf.DoubleValue{value: -1.5e3}" + value { double_value: -1500.0 } + } + test { + name: "literal_no_field_access" + expr: "google.protobuf.DoubleValue{value: 3.1416}.value" + disable_check: true + eval_error { + errors { message: "no_matching_overload" } + } + } + test { + name: "literal_zero" + expr: "google.protobuf.DoubleValue{}" + value { double_value: 0.0 } + } + test { + name: "var" + expr: "x" + type_env { + name: "x" + ident { type { message_type: "google.protobuf.DoubleValue" } } + } + bindings { + key: "x" + value { value { object_value { + [type.googleapis.com/google.protobuf.DoubleValue] + { value: -1.25e6 } + } } } + } + value { double_value: -1250000.0 } + } + test { + name: "field_assign_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_double_wrapper: 86.75}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_double_wrapper { value: 86.75 } } + } + } + } + test { + name: "field_assign_proto2_zero" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_double_wrapper: 0.0}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_double_wrapper { } } + } + } + } + test { + name: "field_assign_proto2_range" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_double_wrapper: 1.4e55}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_double_wrapper { value: 1.4e55 } } + } + } + } + test { + name: "field_read_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_double_wrapper: -12.375}.single_double_wrapper" + value { double_value: -12.375 } + } + test { + name: "field_read_proto2_zero" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_int32_wrapper: 0}.single_int32_wrapper" + value { int64_value: 0 } + } + test { + name: "field_read_proto2_unset" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.single_double_wrapper" + value { null_value: NULL_VALUE } + } + test { + name: "field_assign_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_double_wrapper: -9.75}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_double_wrapper { value: -9.75 } } + } + } + } + test { + name: "field_assign_proto3_zero" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_double_wrapper: 0.0}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_double_wrapper { } } + } + } + } + test { + name: "field_assign_proto3_range" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_double_wrapper: -9.9e100}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_double_wrapper { value: -9.9e100 } } + } + } + } + test { + name: "field_read_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_double_wrapper: 64.25}.single_double_wrapper" + value { double_value: 64.25 } + } + test { + name: "field_read_proto3_zero" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_double_wrapper: 0.0}.single_double_wrapper" + value { double_value: 0.0 } + } + test { + name: "field_read_proto3_unset" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.single_double_wrapper" + value { null_value: NULL_VALUE } + } +} +section { + name: "bool" + description: "Tests for bool conversion." + test { + name: "literal" + expr: "google.protobuf.BoolValue{value: true}" + value { bool_value: true } + } + test { + name: "literal_no_field_access" + expr: "google.protobuf.BoolValue{value: true}.value" + disable_check: true + eval_error { + errors { message: "no_matching_overload" } + } + } + test { + name: "literal_empty" + expr: "google.protobuf.BoolValue{}" + value { bool_value: false } + } + test { + name: "var" + expr: "x" + type_env { + name: "x" + ident { type { message_type: "google.protobuf.BoolValue" } } + } + bindings { + key: "x" + value { value { object_value { + [type.googleapis.com/google.protobuf.BoolValue] + { value: true } + } } } + } + value { bool_value: true } + } + test { + name: "field_assign_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_bool_wrapper: true}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_bool_wrapper { value: true } } + } + } + } + test { + name: "field_assign_proto2_false" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_bool_wrapper: false}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_bool_wrapper { } } + } + } + } + test { + name: "field_assign_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_bool_wrapper: true}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_bool_wrapper { value: true } } + } + } + } + test { + name: "field_assign_proto3_false" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_bool_wrapper: false}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_bool_wrapper { } } + } + } + } +} +section { + name: "string" + description: "Tests for string conversion." + test { + name: "literal" + expr: "google.protobuf.StringValue{value: 'foo'}" + value { string_value: "foo" } + } + test { + name: "literal_no_field_access" + expr: "google.protobuf.StringValue{value: 'foo'}.value" + disable_check: true + eval_error { + errors { message: "no_matching_overload" } + } + } + test { + name: "literal_empty" + expr: "google.protobuf.StringValue{}" + value { string_value: "" } + } + test { + name: "literal_unicode" + expr: "google.protobuf.StringValue{value: 'flambé'}" + value { string_value: "flambé" } + } + test { + name: "var" + expr: "x" + type_env { + name: "x" + ident { type { message_type: "google.protobuf.StringValue" } } + } + bindings { + key: "x" + value { value { object_value { + [type.googleapis.com/google.protobuf.StringValue] + { value: "bar" } + } } } + } + value { string_value: "bar" } + } + test { + name: "field_assign_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_string_wrapper: 'baz'}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_string_wrapper { value: "baz" } } + } + } + } + test { + name: "field_assign_proto2_empty" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_string_wrapper: ''}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_string_wrapper { } } + } + } + } + test { + name: "field_assign_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_string_wrapper: 'bletch'}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_string_wrapper { value: "bletch" } } + } + } + } + test { + name: "field_assign_proto3_empty" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_string_wrapper: ''}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_string_wrapper { } } + } + } + } +} +section { + name: "bytes" + description: "Tests for bytes conversion." + test { + name: "literal" + expr: "google.protobuf.BytesValue{value: b'foo\\123'}" + value { bytes_value: "foo\123" } + } + test { + name: "literal_no_field_access" + expr: "google.protobuf.BytesValue{value: b'foo'}.value" + disable_check: true + eval_error { + errors { message: "no_matching_overload" } + } + } + test { + name: "literal_empty" + expr: "google.protobuf.BytesValue{}" + value { bytes_value: "" } + } + test { + name: "literal_unicode" + expr: "google.protobuf.BytesValue{value: b'flambé'}" + value { bytes_value: "flambé" } + } + test { + name: "var" + expr: "x" + type_env { + name: "x" + ident { type { message_type: "google.protobuf.BytesValue" } } + } + bindings { + key: "x" + value { value { object_value { + [type.googleapis.com/google.protobuf.BytesValue] + { value: "bar" } + } } } + } + value { bytes_value: "bar" } + } + test { + name: "field_assign_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_bytes_wrapper: b'baz'}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_bytes_wrapper { value: "baz" } } + } + } + } + test { + name: "field_assign_proto2_empty" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_bytes_wrapper: b''}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_bytes_wrapper { } } + } + } + } + test { + name: "field_assign_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_bytes_wrapper: b'bletch'}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_bytes_wrapper { value: "bletch" } } + } + } + } + test { + name: "field_assign_proto3_empty" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_bytes_wrapper: b''}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_bytes_wrapper { } } + } + } + } +} +section { + name: "list" + description: "Tests for list conversion." + test { + name: "literal" + expr: "google.protobuf.ListValue{values: [3.0, 'foo', null]}" + value { + list_value { + values { double_value: 3.0 } + values { string_value: "foo" } + values { null_value: NULL_VALUE } + } + } + } + test { + name: "literal_no_field_access" + expr: "google.protobuf.ListValue{values: [3.0, 'foo', null]}.values" + disable_check: true + eval_error { + errors { message: "no_matching_overload" } + } + } + test { + name: "literal_empty" + expr: "google.protobuf.ListValue{values: []}" + value { list_value { } } + } + test { + name: "var" + expr: "x" + type_env { + name: "x" + ident { type { message_type: "google.protobuf.ListValue" } } + } + bindings { + key: "x" + value { value { object_value { + [type.googleapis.com/google.protobuf.ListValue] + { + values { string_value: "bar" } + values { list_value { + values { string_value: "a" } + values { string_value: "b" } + } } + } + } } } + } + value { + list_value { + values { string_value: "bar" } + values { + list_value { + values { string_value: "a" } + values { string_value: "b" } + } + } + } + } + } + test { + name: "field_assign_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{list_value: [1.0, 'one']}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { list_value { + values: { number_value: 1.0 } + values: { string_value: "one" } + } } + } + } + } + test { + name: "field_assign_proto2_empty" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{list_value: []}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { list_value { } } + } + } + } + test { + name: "field_read_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{list_value: [1.0, 'one']}.list_value" + value { + list_value { + values { double_value: 1.0 } + values { string_value: "one" } + } + } + } + test { + name: "field_read_proto2_empty" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{list_value: []}.list_value" + value { list_value { } } + } + test { + name: "field_read_proto2_unset" + description: "Not a wrapper type, so doesn't convert to null." + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.list_value" + value { list_value { } } + } + test { + name: "field_assign_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{list_value: [1.0, 'one']}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { list_value { + values: { number_value: 1.0 } + values: { string_value: "one" } + } } + } + } + } + test { + name: "field_assign_proto3_empty" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{list_value: []}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { list_value { } } + } + } + } + test { + name: "field_read_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{list_value: [1.0, 'one']}.list_value" + value { + list_value { + values { double_value: 1.0 } + values { string_value: "one" } + } + } + } + test { + name: "field_read_proto3_empty" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{list_value: []}.list_value" + value { list_value { } } + } + test { + name: "field_read_proto3_unset" + description: "Not a wrapper type, so doesn't convert to null." + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.list_value" + value { list_value { } } + } +} +section { + name: "struct" + description: "Tests for struct conversion." + test { + name: "literal" + expr: "google.protobuf.Struct{fields: {'uno': 1.0, 'dos': 2.0}}" + value { + map_value { + entries { + key { string_value: "uno" } + value { double_value: 1.0 } + } + entries { + key { string_value: "dos" } + value { double_value: 2.0 } + } + } + } + } + test { + name: "literal_no_field_access" + expr: "google.protobuf.Struct{fields: {'uno': 1.0, 'dos': 2.0}}.fields" + disable_check: true + eval_error { + errors { message: "no_matching_overload" } + } + } + test { + name: "literal_empty" + expr: "google.protobuf.Struct{fields: {}}" + value { map_value { } } + } + test { + name: "var" + expr: "x" + type_env { + name: "x" + ident { type { message_type: "google.protobuf.Struct" } } + } + bindings { + key: "x" + value { value { object_value { + [type.googleapis.com/google.protobuf.Struct] + { + fields { + key: "first" + value { string_value: "Abraham" } + } + fields { + key: "last" + value { string_value: "Lincoln" } + } + } + } } } + } + value { + map_value { + entries { + key { string_value: "first" } + value { string_value: "Abraham" } + } + entries { + key { string_value: "last" } + value { string_value: "Lincoln" } + } + } + } + } + test { + name: "field_assign_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_struct: {'un': 1.0, 'deux': 2.0}}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_struct { + fields { + key: "un" + value { number_value: 1.0 } + } + fields { + key: "deux" + value { number_value: 2.0 } + } + } } + } + } + } + test { + name: "field_assign_proto2_empty" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_struct: {}}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_struct { } } + } + } + } + test { + name: "field_assign_proto2_bad" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_struct: {1: 'uno'}}" + disable_check: true + eval_error { + errors { message: "bad key type" } + } + } + test { + name: "field_read_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_struct: {'one': 1.0}}.single_struct" + value { + map_value { + entries { + key { string_value: "one" } + value { double_value: 1.0 } + } + } + } + } + test { + name: "field_read_proto2_empty" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_struct: {}}.single_struct" + value { map_value { } } + } + test { + name: "field_read_proto2_unset" + description: "Not a wrapper type, so doesn't convert to null." + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.single_struct" + value { map_value { } } + } + test { + name: "field_assign_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_struct: {'un': 1.0, 'deux': 2.0}}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_struct { + fields { + key: "un" + value { number_value: 1.0 } + } + fields { + key: "deux" + value { number_value: 2.0 } + } + } } + } + } + } + test { + name: "field_assign_proto3_empty" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_struct: {}}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_struct { } } + } + } + } + test { + name: "field_assign_proto3_bad" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_struct: {1: 'uno'}}" + disable_check: true + eval_error { + errors { message: "bad key type" } + } + } + test { + name: "field_read_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_struct: {'one': 1.0}}.single_struct" + value { + map_value { + entries { + key { string_value: "one" } + value { double_value: 1.0 } + } + } + } + } + test { + name: "field_read_proto3_empty" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_struct: {}}.single_struct" + value { map_value { } } + } + test { + name: "field_read_proto3_unset" + description: "Not a wrapper type, so doesn't convert to null." + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.single_struct" + value { map_value { } } + } +} +section { + name: "value_null" + description: "Tests for null conversions." + test { + name: "literal" + container: "google.protobuf" + expr: "Value{null_value: NullValue.NULL_VALUE}" + value { null_value: NULL_VALUE } + } + test { + name: "literal_no_field_access" + container: "google.protobuf" + expr: "Value{null_value: NullValue.NULL_VALUE}.null_value" + disable_check: true + eval_error { + errors { message: "no_matching_overload" } + } + } + test { + name: "literal_unset" + expr: "google.protobuf.Value{}" + value { null_value: NULL_VALUE } + } + test { + name: "var" + expr: "x" + type_env { + name: "x" + ident { type { message_type: "google.protobuf.Value" } } + } + bindings { + key: "x" + value { value { object_value { + [type.googleapis.com/google.protobuf.Value] + { null_value: NULL_VALUE } + } } } + } + value { null_value: NULL_VALUE } + } + test { + name: "field_assign_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_value: null}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_value { null_value: NULL_VALUE } } + } + } + } + test { + name: "field_read_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_value: null}.single_value" + value { null_value: NULL_VALUE } + } + test { + name: "field_read_proto2_unset" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.single_value" + value { null_value: NULL_VALUE } + } + test { + name: "field_assign_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: null}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_value { null_value: NULL_VALUE } } + } + } + } + test { + name: "field_read_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: null}.single_value" + value { null_value: NULL_VALUE } + } + test { + name: "field_read_proto3_unset" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.single_value" + value { null_value: NULL_VALUE } + } +} +section { + name: "value_number" + description: "Tests for number conversions in Value." + test { + name: "literal" + expr: "google.protobuf.Value{number_value: 12.5}" + value { double_value: 12.5 } + } + test { + name: "literal_no_field_access" + expr: "google.protobuf.Value{number_value: 12.5}.number_value" + disable_check: true + eval_error { + errors { message: "no_matching_overload" } + } + } + test { + name: "literal_zero" + expr: "google.protobuf.Value{number_value: 0.0}" + value { double_value: 0.0 } + } + test { + name: "var" + expr: "x" + type_env { + name: "x" + ident { type { message_type: "google.protobuf.Value" } } + } + bindings { + key: "x" + value { value { object_value { + [type.googleapis.com/google.protobuf.Value] + { number_value: -26.375 } + } } } + } + value { double_value: -26.375 } + } + test { + name: "field_assign_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_value: 7e23}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_value { number_value: 7e23 } } + } + } + } + test { + name: "field_assign_proto2_zero" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_value: 0.0}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_value { number_value: 0.0 } } + } + } + } + test { + name: "field_read_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_value: 7e23}.single_value" + value { double_value: 7e23 } + } + test { + name: "field_read_proto2_zero" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_value: 0.0}.single_value" + value { double_value: 0.0 } + } + test { + name: "field_assign_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: 7e23}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_value { number_value: 7e23 } } + } + } + } + test { + name: "field_assign_proto3_zero" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: 0.0}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_value { number_value: 0.0 } } + } + } + } + test { + name: "field_read_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: 7e23}.single_value" + value { double_value: 7e23 } + } + test { + name: "field_read_proto3_zero" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: 0.0}.single_value" + value { double_value: 0.0 } + } +} +section { + name: "value_string" + description: "Tests for string conversions in Value." + test { + name: "literal" + expr: "google.protobuf.Value{string_value: 'foo'}" + value { string_value: "foo" } + } + test { + name: "literal_no_field_access" + expr: "google.protobuf.Value{string_value: 'foo'}.string_value" + disable_check: true + eval_error { + errors { message: "no_matching_overload" } + } + } + test { + name: "literal_empty" + expr: "google.protobuf.Value{string_value: ''}" + value { string_value: "" } + } + test { + name: "var" + expr: "x" + type_env { + name: "x" + ident { type { message_type: "google.protobuf.Value" } } + } + bindings { + key: "x" + value { value { object_value { + [type.googleapis.com/google.protobuf.Value] + { string_value: "bar" } + } } } + } + value { string_value: "bar" } + } + test { + name: "field_assign_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_value: 'baz'}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_value { string_value: "baz" } } + } + } + } + test { + name: "field_assign_proto2_empty" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_value: ''}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_value { string_value: "" } } + } + } + } + test { + name: "field_read_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_value: 'bletch'}.single_value" + value { string_value: "bletch" } + } + test { + name: "field_read_proto2_zero" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_value: ''}.single_value" + value { string_value: "" } + } + test { + name: "field_assign_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: 'baz'}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_value { string_value: "baz" } } + } + } + } + test { + name: "field_assign_proto3_empty" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: ''}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_value { string_value: "" } } + } + } + } + test { + name: "field_read_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: 'bletch'}.single_value" + value { string_value: "bletch" } + } + test { + name: "field_read_proto3_zero" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: ''}.single_value" + value { string_value: "" } + } +} +section { + name: "value_bool" + description: "Tests for boolean conversions in Value." + test { + name: "literal" + expr: "google.protobuf.Value{bool_value: true}" + value { bool_value: true } + } + test { + name: "literal_no_field_access" + expr: "google.protobuf.Value{bool_value: true}.bool_value" + disable_check: true + eval_error { + errors { message: "no_matching_overload" } + } + } + test { + name: "literal_false" + expr: "google.protobuf.Value{bool_value: false}" + value { bool_value: false } + } + test { + name: "var" + expr: "x" + type_env { + name: "x" + ident { type { message_type: "google.protobuf.Value" } } + } + bindings { + key: "x" + value { value { object_value { + [type.googleapis.com/google.protobuf.Value] + { bool_value: true } + } } } + } + value { bool_value: true } + } + test { + name: "field_assign_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_value: true}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_value { bool_value: true } } + } + } + } + test { + name: "field_assign_proto2_false" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_value: false}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_value { bool_value: false } } + } + } + } + test { + name: "field_read_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_value: true}.single_value" + value { bool_value: true } + } + test { + name: "field_read_proto2_false" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_value: false}.single_value" + value { bool_value: false } + } + test { + name: "field_assign_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: true}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_value { bool_value: true } } + } + } + } + test { + name: "field_assign_proto3_false" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: false}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_value { bool_value: false } } + } + } + } + test { + name: "field_read_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: true}.single_value" + value { bool_value: true } + } + test { + name: "field_read_proto3_false" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: false}.single_value" + value { bool_value: false } + } +} +section { + name: "value_struct" + description: "Tests for struct conversions in Value." + test { + name: "literal" + expr: "google.protobuf.Value{struct_value: {'a': 1.0, 'b': 'two'}}" + value { + map_value { + entries { + key { string_value: "a" } + value { double_value: 1.0 } + } + entries { + key { string_value: "b" } + value { string_value: "two" } + } + } + } + } + test { + name: "literal_no_field_access" + expr: "google.protobuf.Value{struct_value: {'a': 1.0, 'b': 'two'}}.struct_value" + disable_check: true + eval_error { + errors { message: "no_matching_overload" } + } + } + test { + name: "literal_empty" + expr: "google.protobuf.Value{struct_value: {}}" + value { map_value: { } } + } + test { + name: "var" + expr: "x" + type_env { + name: "x" + ident { type { message_type: "google.protobuf.Value" } } + } + bindings { + key: "x" + value { value { object_value { + [type.googleapis.com/google.protobuf.Value] + { struct_value { + fields { + key: "x" + value { null_value: NULL_VALUE } + } + fields { + key: "y" + value { bool_value: false } + } + } } + } } } + } + value { + map_value { + entries { + key { string_value: "x" } + value { null_value: NULL_VALUE } + } + entries { + key { string_value: "y" } + value { bool_value: false } + } + } + } + } + test { + name: "field_assign_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_value: {'un': 1.0, 'deux': 2.0}}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_value { struct_value { + fields { + key: "un" + value { number_value: 1.0 } + } + fields { + key: "deux" + value { number_value: 2.0 } + } + } } } + } + } + } + test { + name: "field_assign_proto2_empty" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_value: {}}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_value { struct_value: { } } } + } + } + } + test { + name: "field_read_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_value: {'i': true}}.single_value" + value { + map_value { + entries { + key { string_value: "i" } + value { bool_value: true } + } + } + } + } + test { + name: "field_read_proto2_empty" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_value: {}}.single_value" + value { map_value: { } } + } + test { + name: "field_assign_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: {'un': 1.0, 'deux': 2.0}}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_value { struct_value { + fields { + key: "un" + value { number_value: 1.0 } + } + fields { + key: "deux" + value { number_value: 2.0 } + } + } } } + } + } + } + test { + name: "field_assign_proto3_empty" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: {}}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_value { struct_value: { } } } + } + } + } + test { + name: "field_read_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: {'i': true}}.single_value" + value { + map_value { + entries { + key { string_value: "i" } + value { bool_value: true } + } + } + } + } + test { + name: "field_read_proto3_empty" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: {}}.single_value" + value { map_value: { } } + } +} +section { + name: "value_list" + description: "Tests for list conversions in Value." + test { + name: "literal" + expr: "google.protobuf.Value{list_value: ['a', 3.0]}" + value { + list_value { + values { string_value: "a" } + values { double_value: 3.0 } + } + } + } + test { + name: "literal_no_field_access" + expr: "google.protobuf.Value{list_value: []}.list_value" + disable_check: true + eval_error { + errors { message: "no_matching_overload" } + } + } + test { + name: "literal_empty" + expr: "google.protobuf.Value{list_value: []}" + value { list_value: { } } + } + test { + name: "var" + expr: "x" + type_env { + name: "x" + ident { type { message_type: "google.protobuf.Value" } } + } + bindings { + key: "x" + value { value { object_value { + [type.googleapis.com/google.protobuf.Value] + { list_value { + values { number_value: 1.0 } + values { bool_value: true } + values { string_value: "hi" } + } } + } } } + } + value { + list_value { + values { double_value: 1.0 } + values { bool_value: true } + values { string_value: "hi" } + } + } + } + test { + name: "field_assign_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_value: ['un', 1.0]}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_value { list_value { + values { string_value: "un" } + values { number_value: 1.0 } + } } } + } + } + } + test { + name: "field_assign_proto2_empty" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_value: []}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_value { list_value: { } } } + } + } + } + test { + name: "field_read_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_value: ['i', true]}.single_value" + value { + list_value { + values { string_value: "i" } + values { bool_value: true } + } + } + } + test { + name: "field_read_proto2_empty" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_value: []}.single_value" + value { list_value: { } } + } + test { + name: "field_assign_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: ['un', 1.0]}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_value { list_value { + values { string_value: "un" } + values { number_value: 1.0 } + } } } + } + } + } + test { + name: "field_assign_proto3_empty" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: []}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_value { list_value: { } } } + } + } + } + test { + name: "field_read_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: ['i', true]}.single_value" + value { + list_value { + values { string_value: "i" } + values { bool_value: true } + } + } + } + test { + name: "field_read_proto3_empty" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: []}.single_value" + value { list_value: { } } + } +} +section { + name: "any" + description: "Tests for Any conversion." + test { + name: "literal" + expr: "google.protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\x08\\x96\\x01'}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_int32: 150 } + } + } + } + test { + name: "literal_no_field_access" + expr: "google.protobuf.Any{type_url: 'type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes', value: b'\\x08\\x96\\x01'}.type_url" + disable_check: true + eval_error { + errors { message: "no_matching_overload" } + } + } + test { + name: "literal_empty" + expr: "google.protobuf.Any{}" + eval_error { + errors { message: "conversion" } + } + } + test { + name: "var" + expr: "x" + type_env { + name: "x" + ident { type { message_type: "google.protubuf.Any" } } + } + bindings { + key: "x" + value { value { object_value { + [type.googleapis.com/google.protobuf.Any] + { + type_url: "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes" + value: "\x08\x96\x01" + } + } } } + } + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_int32: 150 } + } + } + } + test { + name: "field_assign_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_any: TestAllTypes{single_int32: 150}}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { + single_any { + type_url: "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes" + value: "\x08\x96\x01" + } + } + } + } + } + test { + name: "field_read_proto2" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_any: TestAllTypes{single_int32: 150}}.single_any" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_int32: 150 } + } + } + } + test { + name: "field_assign_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_any: TestAllTypes{single_int32: 150}}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { + single_any { + type_url: "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes" + value: "\x08\x96\x01" + } + } + } + } + } + test { + name: "field_read_proto3" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_any: TestAllTypes{single_int32: 150}}.single_any" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_int32: 150 } + } + } + } +} +section { + name: "complex" + description: "Tests combining various dynamic conversions." + test { + name: "any_list_map" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_any: [{'almost': 'done'}]}.single_any" + value { + list_value { + values { + map_value { + entries { + key { string_value: "almost" } + value { string_value: "done" } + } + } + } + } + } + } +} diff --git a/packages/cel/src/lib/conformance/testdata/encoders_ext.json b/packages/cel/src/lib/conformance/testdata/encoders_ext.json new file mode 100755 index 0000000..9941b8a --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/encoders_ext.json @@ -0,0 +1,49 @@ +{ + "name": "encoders_ext", + "description": "Tests for the encoders extension library.", + "section": [ + { + "name": "encode", + "test": [ + { + "name": "hello", + "expr": "base64.encode(b'hello')", + "value": { + "stringValue": "aGVsbG8=" + } + } + ] + }, + { + "name": "decode", + "test": [ + { + "name": "hello", + "expr": "base64.decode('aGVsbG8=')", + "value": { + "bytesValue": "aGVsbG8=" + } + }, + { + "name": "hello_without_padding", + "expr": "base64.decode('aGVsbG8')", + "value": { + "bytesValue": "aGVsbG8=" + } + } + ] + }, + { + "name": "round_trip", + "test": [ + { + "name": "hello", + "expr": "base64.decode(base64.encode(b'Hello World!'))", + "value": { + "bytesValue": "SGVsbG8gV29ybGQh" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/encoders_ext.textproto b/packages/cel/src/lib/conformance/testdata/encoders_ext.textproto new file mode 100644 index 0000000..f475240 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/encoders_ext.textproto @@ -0,0 +1,42 @@ +name: "encoders_ext" +description: "Tests for the encoders extension library." +section: { + name: "encode" + test: { + name: "hello" + expr: "base64.encode(b'hello')" + value: { + string_value: "aGVsbG8=" + } + } +} + +section: { + name: "decode" + test: { + name: "hello" + expr: "base64.decode('aGVsbG8=')" + value: { + bytes_value: "hello" + } + } + test: { + name: "hello_without_padding" + expr: "base64.decode('aGVsbG8')" + value: { + bytes_value: "hello" + } + } +} + +section: { + name: "round_trip" + test: { + name: "hello" + expr: "base64.decode(base64.encode(b'Hello World!'))" + value: { + bytes_value: "Hello World!" + } + } +} + diff --git a/packages/cel/src/lib/conformance/testdata/enums.json b/packages/cel/src/lib/conformance/testdata/enums.json new file mode 100755 index 0000000..04f9364 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/enums.json @@ -0,0 +1,936 @@ +{ + "name": "enums", + "description": "Tests for enum types.", + "section": [ + { + "name": "legacy_proto2", + "description": "Legacy semantics where all enums are ints, proto2.", + "test": [ + { + "name": "literal_global", + "expr": "GlobalEnum.GAZ", + "container": "google.api.expr.test.v1.proto2", + "value": { + "int64Value": "2" + } + }, + { + "name": "literal_nested", + "expr": "TestAllTypes.NestedEnum.BAR", + "container": "google.api.expr.test.v1.proto2", + "value": { + "int64Value": "1" + } + }, + { + "name": "literal_zero", + "expr": "GlobalEnum.GOO", + "container": "google.api.expr.test.v1.proto2", + "value": { + "int64Value": "0" + } + }, + { + "name": "comparision", + "expr": "GlobalEnum.GAR == 1", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "arithmetic", + "expr": "TestAllTypes.NestedEnum.BAR + 3", + "container": "google.api.expr.test.v1.proto2", + "value": { + "int64Value": "4" + } + }, + { + "name": "type_global", + "expr": "type(GlobalEnum.GOO)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "typeValue": "int" + } + }, + { + "name": "type_nested", + "expr": "type(TestAllTypes.NestedEnum.BAZ)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "typeValue": "int" + } + }, + { + "name": "select_default", + "expr": "TestAllTypes{}.standalone_enum", + "container": "google.api.expr.test.v1.proto2", + "value": { + "int64Value": "0" + } + }, + { + "name": "field_type", + "expr": "type(TestAllTypes{}.standalone_enum)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "typeValue": "int" + } + }, + { + "name": "assign_standalone_name", + "expr": "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum.BAZ}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "standaloneEnum": "BAZ" + } + } + }, + { + "name": "assign_standalone_int", + "expr": "TestAllTypes{standalone_enum: 1}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "standaloneEnum": "BAR" + } + } + }, + { + "name": "assign_standalone_int_too_big", + "expr": "TestAllTypes{standalone_enum: 5000000000}", + "container": "google.api.expr.test.v1.proto2", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + }, + { + "name": "assign_standalone_int_too_neg", + "expr": "TestAllTypes{standalone_enum: -7000000000}", + "container": "google.api.expr.test.v1.proto2", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + } + ] + }, + { + "name": "legacy_proto3", + "description": "Legacy semantics where all enums are ints, proto3", + "test": [ + { + "name": "literal_global", + "expr": "GlobalEnum.GAZ", + "container": "google.api.expr.test.v1.proto3", + "value": { + "int64Value": "2" + } + }, + { + "name": "literal_nested", + "expr": "TestAllTypes.NestedEnum.BAR", + "container": "google.api.expr.test.v1.proto3", + "value": { + "int64Value": "1" + } + }, + { + "name": "literal_zero", + "expr": "GlobalEnum.GOO", + "container": "google.api.expr.test.v1.proto3", + "value": { + "int64Value": "0" + } + }, + { + "name": "comparision", + "expr": "GlobalEnum.GAR == 1", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "arithmetic", + "expr": "TestAllTypes.NestedEnum.BAR + 3", + "container": "google.api.expr.test.v1.proto3", + "value": { + "int64Value": "4" + } + }, + { + "name": "type_global", + "expr": "type(GlobalEnum.GOO)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "typeValue": "int" + } + }, + { + "name": "type_nested", + "expr": "type(TestAllTypes.NestedEnum.BAZ)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "typeValue": "int" + } + }, + { + "name": "select_default", + "expr": "TestAllTypes{}.standalone_enum", + "container": "google.api.expr.test.v1.proto3", + "value": { + "int64Value": "0" + } + }, + { + "name": "select", + "expr": "x.standalone_enum", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto3.TestAllTypes" + } + } + } + ], + "container": "google.api.expr.test.v1.proto3", + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "standaloneEnum": "BAZ" + } + } + } + }, + "value": { + "int64Value": "2" + } + }, + { + "name": "select_big", + "expr": "x.standalone_enum", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto3.TestAllTypes" + } + } + } + ], + "container": "google.api.expr.test.v1.proto3", + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "standaloneEnum": 108 + } + } + } + }, + "value": { + "int64Value": "108" + } + }, + { + "name": "select_neg", + "expr": "x.standalone_enum", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto3.TestAllTypes" + } + } + } + ], + "container": "google.api.expr.test.v1.proto3", + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "standaloneEnum": -3 + } + } + } + }, + "value": { + "int64Value": "-3" + } + }, + { + "name": "field_type", + "expr": "type(TestAllTypes{}.standalone_enum)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "typeValue": "int" + } + }, + { + "name": "assign_standalone_name", + "expr": "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum.BAZ}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "standaloneEnum": "BAZ" + } + } + }, + { + "name": "assign_standalone_int", + "expr": "TestAllTypes{standalone_enum: 1}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "standaloneEnum": "BAR" + } + } + }, + { + "name": "assign_standalone_int_big", + "expr": "TestAllTypes{standalone_enum: 99}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "standaloneEnum": 99 + } + } + }, + { + "name": "assign_standalone_int_neg", + "expr": "TestAllTypes{standalone_enum: -1}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "standaloneEnum": -1 + } + } + }, + { + "name": "assign_standalone_int_too_big", + "expr": "TestAllTypes{standalone_enum: 5000000000}", + "container": "google.api.expr.test.v1.proto3", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + }, + { + "name": "assign_standalone_int_too_neg", + "expr": "TestAllTypes{standalone_enum: -7000000000}", + "container": "google.api.expr.test.v1.proto3", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + } + ] + }, + { + "name": "strong_proto2", + "description": "String semantics where enums are distinct types, proto2.", + "test": [ + { + "name": "literal_global", + "expr": "GlobalEnum.GAZ", + "container": "google.api.expr.test.v1.proto2", + "value": { + "enumValue": { + "type": "google.api.expr.test.v1.proto2.GlobalEnum", + "value": 2 + } + } + }, + { + "name": "literal_nested", + "expr": "TestAllTypes.NestedEnum.BAR", + "container": "google.api.expr.test.v1.proto2", + "value": { + "enumValue": { + "type": "google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum", + "value": 1 + } + } + }, + { + "name": "literal_zero", + "expr": "GlobalEnum.GOO", + "container": "google.api.expr.test.v1.proto2", + "value": { + "enumValue": { + "type": "google.api.expr.test.v1.proto2.GlobalEnum" + } + } + }, + { + "name": "comparision_true", + "expr": "GlobalEnum.GAR == GlobalEnum.GAR", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "comparision_false", + "expr": "GlobalEnum.GAR == GlobalEnum.GAZ", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": false + } + }, + { + "name": "type_global", + "expr": "type(GlobalEnum.GOO)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "typeValue": "google.api.expr.test.v1.proto2.GlobalEnum" + } + }, + { + "name": "type_nested", + "expr": "type(TestAllTypes.NestedEnum.BAZ)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "typeValue": "google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum" + } + }, + { + "name": "select_default", + "expr": "TestAllTypes{}.standalone_enum", + "container": "google.api.expr.test.v1.proto2", + "value": { + "enumValue": { + "type": "google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum" + } + } + }, + { + "name": "field_type", + "expr": "type(TestAllTypes{}.standalone_enum)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "typeValue": "google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum" + } + }, + { + "name": "assign_standalone_name", + "expr": "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum.BAZ}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "standaloneEnum": "BAZ" + } + } + }, + { + "name": "assign_standalone_int", + "expr": "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum(1)}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "standaloneEnum": "BAR" + } + } + }, + { + "name": "convert_symbol_to_int", + "expr": "int(GlobalEnum.GAZ)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "int64Value": "2" + } + }, + { + "name": "convert_unnamed_to_int", + "description": "Disable check - missing way to declare enums.", + "expr": "int(x)", + "disableCheck": true, + "bindings": { + "x": { + "value": { + "enumValue": { + "type": "google.api.expr.test.v1.proto2.GlobalEnum", + "value": 444 + } + } + } + }, + "value": { + "int64Value": "444" + } + }, + { + "name": "convert_int_inrange", + "expr": "TestAllTypes.NestedEnum(2)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "enumValue": { + "type": "google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum", + "value": 2 + } + } + }, + { + "name": "convert_int_big", + "expr": "TestAllTypes.NestedEnum(20000)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "enumValue": { + "type": "google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum", + "value": 20000 + } + } + }, + { + "name": "convert_int_neg", + "expr": "GlobalEnum(-33)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "enumValue": { + "type": "google.api.expr.test.v1.proto2.GlobalEnum", + "value": -33 + } + } + }, + { + "name": "convert_int_too_big", + "expr": "TestAllTypes.NestedEnum(5000000000)", + "container": "google.api.expr.test.v1.proto2", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + }, + { + "name": "convert_int_too_neg", + "expr": "TestAllTypes.NestedEnum(-7000000000)", + "container": "google.api.expr.test.v1.proto2", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + }, + { + "name": "convert_string", + "expr": "TestAllTypes.NestedEnum('BAZ')", + "container": "google.api.expr.test.v1.proto2", + "value": { + "enumValue": { + "type": "google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum", + "value": 2 + } + } + }, + { + "name": "convert_string_bad", + "expr": "TestAllTypes.NestedEnum('BLETCH')", + "container": "google.api.expr.test.v1.proto2", + "evalError": { + "errors": [ + { + "message": "invalid" + } + ] + } + } + ] + }, + { + "name": "strong_proto3", + "description": "String semantics where enums are distinct types, proto3.", + "test": [ + { + "name": "literal_global", + "expr": "GlobalEnum.GAZ", + "container": "google.api.expr.test.v1.proto3", + "value": { + "enumValue": { + "type": "google.api.expr.test.v1.proto3.GlobalEnum", + "value": 2 + } + } + }, + { + "name": "literal_nested", + "expr": "TestAllTypes.NestedEnum.BAR", + "container": "google.api.expr.test.v1.proto3", + "value": { + "enumValue": { + "type": "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum", + "value": 1 + } + } + }, + { + "name": "literal_zero", + "expr": "GlobalEnum.GOO", + "container": "google.api.expr.test.v1.proto3", + "value": { + "enumValue": { + "type": "google.api.expr.test.v1.proto3.GlobalEnum" + } + } + }, + { + "name": "comparision_true", + "expr": "GlobalEnum.GAR == GlobalEnum.GAR", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "comparision_false", + "expr": "GlobalEnum.GAR == GlobalEnum.GAZ", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": false + } + }, + { + "name": "type_global", + "expr": "type(GlobalEnum.GOO)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "typeValue": "google.api.expr.test.v1.proto3.GlobalEnum" + } + }, + { + "name": "type_nested", + "expr": "type(TestAllTypes.NestedEnum.BAZ)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "typeValue": "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum" + } + }, + { + "name": "select_default", + "expr": "TestAllTypes{}.standalone_enum", + "container": "google.api.expr.test.v1.proto3", + "value": { + "enumValue": { + "type": "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum" + } + } + }, + { + "name": "select", + "expr": "x.standalone_enum", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto3.TestAllTypes" + } + } + } + ], + "container": "google.api.expr.test.v1.proto3", + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "standaloneEnum": "BAZ" + } + } + } + }, + "value": { + "enumValue": { + "type": "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum", + "value": 2 + } + } + }, + { + "name": "select_big", + "expr": "x.standalone_enum", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto3.TestAllTypes" + } + } + } + ], + "container": "google.api.expr.test.v1.proto3", + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "standaloneEnum": 108 + } + } + } + }, + "value": { + "enumValue": { + "type": "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum", + "value": 108 + } + } + }, + { + "name": "select_neg", + "expr": "x.standalone_enum", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto3.TestAllTypes" + } + } + } + ], + "container": "google.api.expr.test.v1.proto3", + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "standaloneEnum": -3 + } + } + } + }, + "value": { + "enumValue": { + "type": "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum", + "value": -3 + } + } + }, + { + "name": "field_type", + "expr": "type(TestAllTypes{}.standalone_enum)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "typeValue": "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum" + } + }, + { + "name": "assign_standalone_name", + "expr": "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum.BAZ}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "standaloneEnum": "BAZ" + } + } + }, + { + "name": "assign_standalone_int", + "expr": "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum(1)}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "standaloneEnum": "BAR" + } + } + }, + { + "name": "assign_standalone_int_big", + "expr": "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum(99)}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "standaloneEnum": 99 + } + } + }, + { + "name": "assign_standalone_int_neg", + "expr": "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum(-1)}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "standaloneEnum": -1 + } + } + }, + { + "name": "convert_symbol_to_int", + "expr": "int(GlobalEnum.GAZ)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "int64Value": "2" + } + }, + { + "name": "convert_unnamed_to_int", + "description": "Disable check - missing way to declare enums.", + "expr": "int(x)", + "disableCheck": true, + "bindings": { + "x": { + "value": { + "enumValue": { + "type": "google.api.expr.test.v1.proto3.GlobalEnum", + "value": 444 + } + } + } + }, + "value": { + "int64Value": "444" + } + }, + { + "name": "convert_unnamed_to_int_select", + "expr": "int(x.standalone_enum)", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto3.TestAllTypes" + } + } + } + ], + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "standaloneEnum": -987 + } + } + } + }, + "value": { + "int64Value": "-987" + } + }, + { + "name": "convert_int_inrange", + "expr": "TestAllTypes.NestedEnum(2)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "enumValue": { + "type": "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum", + "value": 2 + } + } + }, + { + "name": "convert_int_big", + "expr": "TestAllTypes.NestedEnum(20000)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "enumValue": { + "type": "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum", + "value": 20000 + } + } + }, + { + "name": "convert_int_neg", + "expr": "GlobalEnum(-33)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "enumValue": { + "type": "google.api.expr.test.v1.proto3.GlobalEnum", + "value": -33 + } + } + }, + { + "name": "convert_int_too_big", + "expr": "TestAllTypes.NestedEnum(5000000000)", + "container": "google.api.expr.test.v1.proto3", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + }, + { + "name": "convert_int_too_neg", + "expr": "TestAllTypes.NestedEnum(-7000000000)", + "container": "google.api.expr.test.v1.proto3", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + }, + { + "name": "convert_string", + "expr": "TestAllTypes.NestedEnum('BAZ')", + "container": "google.api.expr.test.v1.proto3", + "value": { + "enumValue": { + "type": "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum", + "value": 2 + } + } + }, + { + "name": "convert_string_bad", + "expr": "TestAllTypes.NestedEnum('BLETCH')", + "container": "google.api.expr.test.v1.proto3", + "evalError": { + "errors": [ + { + "message": "invalid" + } + ] + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/enums.textproto b/packages/cel/src/lib/conformance/testdata/enums.textproto new file mode 100644 index 0000000..8c31667 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/enums.textproto @@ -0,0 +1,844 @@ +name: "enums" +description: "Tests for enum types." +section { + name: "legacy_proto2" + description: "Legacy semantics where all enums are ints, proto2." + test { + name: "literal_global" + container: "google.api.expr.test.v1.proto2" + expr: "GlobalEnum.GAZ" + value { int64_value: 2 } + } + test { + name: "literal_nested" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes.NestedEnum.BAR" + value { int64_value: 1 } + } + test { + name: "literal_zero" + container: "google.api.expr.test.v1.proto2" + expr: "GlobalEnum.GOO" + value { int64_value: 0 } + } + test { + name: "comparision" + container: "google.api.expr.test.v1.proto2" + expr: "GlobalEnum.GAR == 1" + value { bool_value: true } + } + test { + name: "arithmetic" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes.NestedEnum.BAR + 3" + value { int64_value: 4 } + } + test { + name: "type_global" + container: "google.api.expr.test.v1.proto2" + expr: "type(GlobalEnum.GOO)" + value { type_value: "int" } + } + test { + name: "type_nested" + container: "google.api.expr.test.v1.proto2" + expr: "type(TestAllTypes.NestedEnum.BAZ)" + value { type_value: "int" } + } + test { + name: "select_default" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.standalone_enum" + value { int64_value: 0 } + } + test { + name: "field_type" + container: "google.api.expr.test.v1.proto2" + expr: "type(TestAllTypes{}.standalone_enum)" + value { type_value: "int" } + } + test { + name: "assign_standalone_name" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum.BAZ}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + standalone_enum: BAZ + } + } + } + } + test { + name: "assign_standalone_int" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{standalone_enum: 1}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + standalone_enum: BAR + } + } + } + } + test { + name: "assign_standalone_int_too_big" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{standalone_enum: 5000000000}" + eval_error { + errors { + message: "range" + } + } + } + test { + name: "assign_standalone_int_too_neg" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{standalone_enum: -7000000000}" + eval_error { + errors { + message: "range" + } + } + } +} +section { + name: "legacy_proto3" + description: "Legacy semantics where all enums are ints, proto3" + test { + name: "literal_global" + container: "google.api.expr.test.v1.proto3" + expr: "GlobalEnum.GAZ" + value { int64_value: 2 } + } + test { + name: "literal_nested" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes.NestedEnum.BAR" + value { int64_value: 1 } + } + test { + name: "literal_zero" + container: "google.api.expr.test.v1.proto3" + expr: "GlobalEnum.GOO" + value { int64_value: 0 } + } + test { + name: "comparision" + container: "google.api.expr.test.v1.proto3" + expr: "GlobalEnum.GAR == 1" + value { bool_value: true } + } + test { + name: "arithmetic" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes.NestedEnum.BAR + 3" + value { int64_value: 4 } + } + test { + name: "type_global" + container: "google.api.expr.test.v1.proto3" + expr: "type(GlobalEnum.GOO)" + value { type_value: "int" } + } + test { + name: "type_nested" + container: "google.api.expr.test.v1.proto3" + expr: "type(TestAllTypes.NestedEnum.BAZ)" + value { type_value: "int" } + } + test { + name: "select_default" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.standalone_enum" + value { int64_value: 0 } + } + test { + name: "select" + container: "google.api.expr.test.v1.proto3" + expr: "x.standalone_enum" + type_env { + name: "x" + ident { + type { message_type: "google.api.expr.test.v1.proto3.TestAllTypes" } + } + } + bindings { + key: "x" + value { + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: 2 + } + } + } + } + } + value { int64_value: 2 } + } + test { + name: "select_big" + container: "google.api.expr.test.v1.proto3" + expr: "x.standalone_enum" + type_env { + name: "x" + ident { + type { message_type: "google.api.expr.test.v1.proto3.TestAllTypes" } + } + } + bindings { + key: "x" + value { + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: 108 + } + } + } + } + } + value { int64_value: 108 } + } + test { + name: "select_neg" + container: "google.api.expr.test.v1.proto3" + expr: "x.standalone_enum" + type_env { + name: "x" + ident { + type { message_type: "google.api.expr.test.v1.proto3.TestAllTypes" } + } + } + bindings { + key: "x" + value { + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: -3 + } + } + } + } + } + value { int64_value: -3 } + } + test { + name: "field_type" + container: "google.api.expr.test.v1.proto3" + expr: "type(TestAllTypes{}.standalone_enum)" + value { type_value: "int" } + } + test { + name: "assign_standalone_name" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum.BAZ}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: BAZ + } + } + } + } + test { + name: "assign_standalone_int" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{standalone_enum: 1}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: BAR + } + } + } + } + test { + name: "assign_standalone_int_big" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{standalone_enum: 99}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: 99 + } + } + } + } + test { + name: "assign_standalone_int_neg" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{standalone_enum: -1}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: -1 + } + } + } + } + test { + name: "assign_standalone_int_too_big" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{standalone_enum: 5000000000}" + eval_error { + errors { + message: "range" + } + } + } + test { + name: "assign_standalone_int_too_neg" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{standalone_enum: -7000000000}" + eval_error { + errors { + message: "range" + } + } + } +} +section { + name: "strong_proto2" + description: "String semantics where enums are distinct types, proto2." + test { + name: "literal_global" + container: "google.api.expr.test.v1.proto2" + expr: "GlobalEnum.GAZ" + value { + enum_value { + type: "google.api.expr.test.v1.proto2.GlobalEnum" + value: 2 + } + } + } + test { + name: "literal_nested" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes.NestedEnum.BAR" + value { + enum_value { + type: "google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum" + value: 1 + } + } + } + test { + name: "literal_zero" + container: "google.api.expr.test.v1.proto2" + expr: "GlobalEnum.GOO" + value { + enum_value { + type: "google.api.expr.test.v1.proto2.GlobalEnum" + value: 0 + } + } + } + test { + name: "comparision_true" + container: "google.api.expr.test.v1.proto2" + expr: "GlobalEnum.GAR == GlobalEnum.GAR" + value { bool_value: true } + } + test { + name: "comparision_false" + container: "google.api.expr.test.v1.proto2" + expr: "GlobalEnum.GAR == GlobalEnum.GAZ" + value { bool_value: false } + } + test { + name: "type_global" + container: "google.api.expr.test.v1.proto2" + expr: "type(GlobalEnum.GOO)" + value { type_value: "google.api.expr.test.v1.proto2.GlobalEnum" } + } + test { + name: "type_nested" + container: "google.api.expr.test.v1.proto2" + expr: "type(TestAllTypes.NestedEnum.BAZ)" + value { + type_value: "google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum" + } + } + test { + name: "select_default" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.standalone_enum" + value { + enum_value { + type: "google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum" + value: 0 + } + } + } + test { + name: "field_type" + container: "google.api.expr.test.v1.proto2" + expr: "type(TestAllTypes{}.standalone_enum)" + value { + type_value: "google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum" + } + } + test { + name: "assign_standalone_name" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum.BAZ}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + standalone_enum: BAZ + } + } + } + } + test { + name: "assign_standalone_int" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum(1)}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + standalone_enum: BAR + } + } + } + } + test { + name: "convert_symbol_to_int" + container: "google.api.expr.test.v1.proto2" + expr: "int(GlobalEnum.GAZ)" + value { int64_value: 2 } + } + test { + name: "convert_unnamed_to_int" + description: "Disable check - missing way to declare enums." + expr: "int(x)" + disable_check: true + bindings { + key: "x" + value { + value { + enum_value { + type: "google.api.expr.test.v1.proto2.GlobalEnum" + value: 444 + } + } + } + } + value { int64_value: 444 } + } + test { + name: "convert_int_inrange" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes.NestedEnum(2)" + value { + enum_value { + type: "google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum" + value: 2 + } + } + } + test { + name: "convert_int_big" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes.NestedEnum(20000)" + value { + enum_value { + type: "google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum" + value: 20000 + } + } + } + test { + name: "convert_int_neg" + container: "google.api.expr.test.v1.proto2" + expr: "GlobalEnum(-33)" + value { + enum_value { + type: "google.api.expr.test.v1.proto2.GlobalEnum" + value: -33 + } + } + } + test { + name: "convert_int_too_big" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes.NestedEnum(5000000000)" + eval_error { + errors { + message: "range" + } + } + } + test { + name: "convert_int_too_neg" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes.NestedEnum(-7000000000)" + eval_error { + errors { + message: "range" + } + } + } + test { + name: "convert_string" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes.NestedEnum('BAZ')" + value { + enum_value { + type: "google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum" + value: 2 + } + } + } + test { + name: "convert_string_bad" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes.NestedEnum('BLETCH')" + eval_error { + errors { + message: "invalid" + } + } + } +} +section { + name: "strong_proto3" + description: "String semantics where enums are distinct types, proto3." + test { + name: "literal_global" + container: "google.api.expr.test.v1.proto3" + expr: "GlobalEnum.GAZ" + value { + enum_value { + type: "google.api.expr.test.v1.proto3.GlobalEnum" + value: 2 + } + } + } + test { + name: "literal_nested" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes.NestedEnum.BAR" + value { + enum_value { + type: "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum" + value: 1 + } + } + } + test { + name: "literal_zero" + container: "google.api.expr.test.v1.proto3" + expr: "GlobalEnum.GOO" + value { + enum_value { + type: "google.api.expr.test.v1.proto3.GlobalEnum" + value: 0 + } + } + } + test { + name: "comparision_true" + container: "google.api.expr.test.v1.proto3" + expr: "GlobalEnum.GAR == GlobalEnum.GAR" + value { bool_value: true } + } + test { + name: "comparision_false" + container: "google.api.expr.test.v1.proto3" + expr: "GlobalEnum.GAR == GlobalEnum.GAZ" + value { bool_value: false } + } + test { + name: "type_global" + container: "google.api.expr.test.v1.proto3" + expr: "type(GlobalEnum.GOO)" + value { type_value: "google.api.expr.test.v1.proto3.GlobalEnum" } + } + test { + name: "type_nested" + container: "google.api.expr.test.v1.proto3" + expr: "type(TestAllTypes.NestedEnum.BAZ)" + value { + type_value: "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum" + } + } + test { + name: "select_default" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.standalone_enum" + value { + enum_value { + type: "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum" + value: 0 + } + } + } + test { + name: "select" + container: "google.api.expr.test.v1.proto3" + expr: "x.standalone_enum" + type_env { + name: "x" + ident { + type { message_type: "google.api.expr.test.v1.proto3.TestAllTypes" } + } + } + bindings { + key: "x" + value { + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: 2 + } + } + } + } + } + value { + enum_value { + type: "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum" + value: 2 + } + } + } + test { + name: "select_big" + container: "google.api.expr.test.v1.proto3" + expr: "x.standalone_enum" + type_env { + name: "x" + ident { + type { message_type: "google.api.expr.test.v1.proto3.TestAllTypes" } + } + } + bindings { + key: "x" + value { + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: 108 + } + } + } + } + } + value { + enum_value { + type: "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum" + value: 108 + } + } + } + test { + name: "select_neg" + container: "google.api.expr.test.v1.proto3" + expr: "x.standalone_enum" + type_env { + name: "x" + ident { + type { message_type: "google.api.expr.test.v1.proto3.TestAllTypes" } + } + } + bindings { + key: "x" + value { + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: -3 + } + } + } + } + } + value { + enum_value { + type: "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum" + value: -3 + } + } + } + test { + name: "field_type" + container: "google.api.expr.test.v1.proto3" + expr: "type(TestAllTypes{}.standalone_enum)" + value { + type_value: "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum" + } + } + test { + name: "assign_standalone_name" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum.BAZ}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: BAZ + } + } + } + } + test { + name: "assign_standalone_int" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum(1)}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: BAR + } + } + } + } + test { + name: "assign_standalone_int_big" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum(99)}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: 99 + } + } + } + } + test { + name: "assign_standalone_int_neg" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum(-1)}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: -1 + } + } + } + } + test { + name: "convert_symbol_to_int" + container: "google.api.expr.test.v1.proto3" + expr: "int(GlobalEnum.GAZ)" + value { int64_value: 2 } + } + test { + name: "convert_unnamed_to_int" + description: "Disable check - missing way to declare enums." + expr: "int(x)" + disable_check: true + bindings { + key: "x" + value { + value { + enum_value { + type: "google.api.expr.test.v1.proto3.GlobalEnum" + value: 444 + } + } + } + } + value { int64_value: 444 } + } + test { + name: "convert_unnamed_to_int_select" + expr: "int(x.standalone_enum)" + type_env { + name: "x" + ident { + type { message_type: "google.api.expr.test.v1.proto3.TestAllTypes" } + } + } + bindings { + key: "x" + value { + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: -987 + } + } + } + } + } + value { int64_value: -987 } + } + test { + name: "convert_int_inrange" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes.NestedEnum(2)" + value { + enum_value { + type: "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum" + value: 2 + } + } + } + test { + name: "convert_int_big" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes.NestedEnum(20000)" + value { + enum_value { + type: "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum" + value: 20000 + } + } + } + test { + name: "convert_int_neg" + container: "google.api.expr.test.v1.proto3" + expr: "GlobalEnum(-33)" + value { + enum_value { + type: "google.api.expr.test.v1.proto3.GlobalEnum" + value: -33 + } + } + } + test { + name: "convert_int_too_big" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes.NestedEnum(5000000000)" + eval_error { + errors { + message: "range" + } + } + } + test { + name: "convert_int_too_neg" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes.NestedEnum(-7000000000)" + eval_error { + errors { + message: "range" + } + } + } + test { + name: "convert_string" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes.NestedEnum('BAZ')" + value { + enum_value { + type: "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum" + value: 2 + } + } + } + test { + name: "convert_string_bad" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes.NestedEnum('BLETCH')" + eval_error { + errors { + message: "invalid" + } + } + } +} diff --git a/packages/cel/src/lib/conformance/testdata/fields.json b/packages/cel/src/lib/conformance/testdata/fields.json new file mode 100755 index 0000000..4002cdc --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/fields.json @@ -0,0 +1,654 @@ +{ + "name": "fields", + "description": "Tests for field access in maps.", + "section": [ + { + "name": "map_fields", + "description": "select an element in a map", + "test": [ + { + "name": "map_key_int64", + "expr": "{0:1,2:2,5:true}[5]", + "value": { + "boolValue": true + } + }, + { + "name": "map_key_uint64", + "expr": "{0u:1u,2u:'happy',5u:3u}[2u]", + "value": { + "stringValue": "happy" + } + }, + { + "name": "map_key_string", + "expr": "{'name':100u}['name']", + "value": { + "uint64Value": "100" + } + }, + { + "name": "map_key_bool", + "expr": "{true:5}[true]", + "value": { + "int64Value": "5" + } + }, + { + "name": "map_key_mixed_type", + "expr": "{true:1,2:2,5u:3}[true]", + "value": { + "int64Value": "1" + } + }, + { + "name": "map_key_mixed_numbers_double_key", + "expr": "{1u: 1.0, 2: 2.0, 3u: 3.0}[3.0]", + "value": { + "doubleValue": 3 + } + }, + { + "name": "map_key_mixed_numbers_lossy_double_key", + "expr": "{1u: 1.0, 2: 2.0, 3u: 3.0}[3.1]", + "evalError": { + "errors": [ + { + "message": "no such key" + } + ] + } + }, + { + "name": "map_key_mixed_numbers_uint_key", + "expr": "{1u: 1.0, 2: 2.0, 3u: 3.0}[2u]", + "value": { + "doubleValue": 2 + } + }, + { + "name": "map_key_mixed_numbers_int_key", + "expr": "{1u: 1.0, 2: 2.0, 3u: 3.0}[1]", + "value": { + "doubleValue": 1 + } + }, + { + "name": "map_field_access", + "expr": "x.name", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "mapType": { + "keyType": { + "primitive": "STRING" + }, + "valueType": { + "primitive": "INT64" + } + } + } + } + } + ], + "bindings": { + "x": { + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "name" + }, + "value": { + "int64Value": "1024" + } + } + ] + } + } + } + }, + "value": { + "int64Value": "1024" + } + }, + { + "name": "map_no_such_key", + "expr": "{0:1,2:2,5:3}[1]", + "evalError": { + "errors": [ + { + "message": "no such key" + } + ] + } + }, + { + "name": "map_field_select_no_such_key", + "expr": "x.name", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "mapType": { + "keyType": { + "primitive": "STRING" + }, + "valueType": { + "primitive": "STRING" + } + } + } + } + } + ], + "bindings": { + "x": { + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "holiday" + }, + "value": { + "stringValue": "field" + } + } + ] + } + } + } + }, + "evalError": { + "errors": [ + { + "message": "no such key: 'name'" + } + ] + } + }, + { + "name": "map_value_null", + "expr": "{true:null}[true]", + "value": { + "nullValue": null + } + }, + { + "name": "map_value_bool", + "expr": "{27:false}[27]", + "value": { + "boolValue": false + } + }, + { + "name": "map_value_string", + "expr": "{'n':'x'}['n']", + "value": { + "stringValue": "x" + } + }, + { + "name": "map_value_float", + "expr": "{3:15.15}[3]", + "value": { + "doubleValue": 15.15 + } + }, + { + "name": "map_value_uint64", + "expr": "{0u:1u,2u:2u,5u:3u}[0u]", + "value": { + "uint64Value": "1" + } + }, + { + "name": "map_value_int64", + "expr": "{true:1,false:2}[true]", + "value": { + "int64Value": "1" + } + }, + { + "name": "map_value_bytes", + "expr": "{0:b\"\"}[0]", + "value": { + "bytesValue": "" + } + }, + { + "name": "map_value_list", + "expr": "{0u:[1]}[0u]", + "value": { + "listValue": { + "values": [ + { + "int64Value": "1" + } + ] + } + } + }, + { + "name": "map_value_map", + "expr": "{\"map\": {\"k\": \"v\"}}[\"map\"]", + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "k" + }, + "value": { + "stringValue": "v" + } + } + ] + } + } + }, + { + "name": "map_value_mix_type", + "expr": "{\"map\": {\"k\": \"v\"}, \"list\": [1]}[\"map\"]", + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "k" + }, + "value": { + "stringValue": "v" + } + } + ] + } + } + } + ] + }, + { + "name": "map_has", + "description": "Has macro for map entries.", + "test": [ + { + "name": "has", + "expr": "has({'a': 1, 'b': 2}.a)", + "value": { + "boolValue": true + } + }, + { + "name": "has_not", + "expr": "has({'a': 1, 'b': 2}.c)", + "value": { + "boolValue": false + } + }, + { + "name": "has_empty", + "expr": "has({}.a)", + "value": { + "boolValue": false + } + } + ] + }, + { + "name": "qualified_identifier_resolution", + "description": "Tests for qualified identifier resolution.", + "test": [ + { + "name": "qualified_ident", + "expr": "a.b.c", + "typeEnv": [ + { + "name": "a.b.c", + "ident": { + "type": { + "primitive": "STRING" + } + } + } + ], + "bindings": { + "a.b.c": { + "value": { + "stringValue": "yeah" + } + } + }, + "value": { + "stringValue": "yeah" + } + }, + { + "name": "map_field_select", + "expr": "a.b.c", + "typeEnv": [ + { + "name": "a.b", + "ident": { + "type": { + "mapType": { + "keyType": { + "primitive": "STRING" + }, + "valueType": { + "primitive": "STRING" + } + } + } + } + } + ], + "bindings": { + "a.b": { + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "c" + }, + "value": { + "stringValue": "yeah" + } + } + ] + } + } + } + }, + "value": { + "stringValue": "yeah" + } + }, + { + "name": "qualified_identifier_resolution_unchecked", + "description": "namespace resolution should try to find the longest prefix for the evaluator.", + "expr": "a.b.c", + "disableCheck": true, + "typeEnv": [ + { + "name": "a.b.c", + "ident": { + "type": { + "primitive": "STRING" + } + } + }, + { + "name": "a.b", + "ident": { + "type": { + "mapType": { + "keyType": { + "primitive": "STRING" + }, + "valueType": { + "primitive": "STRING" + } + } + } + } + } + ], + "bindings": { + "a.b": { + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "c" + }, + "value": { + "stringValue": "oops" + } + } + ] + } + } + }, + "a.b.c": { + "value": { + "stringValue": "yeah" + } + } + }, + "value": { + "stringValue": "yeah" + } + }, + { + "name": "list_field_select_unsupported", + "expr": "a.b.pancakes", + "disableCheck": true, + "typeEnv": [ + { + "name": "a.b", + "ident": { + "type": { + "listType": { + "elemType": { + "primitive": "STRING" + } + } + } + } + } + ], + "bindings": { + "a.b": { + "value": { + "listValue": { + "values": [ + { + "stringValue": "pancakes" + } + ] + } + } + } + }, + "evalError": { + "errors": [ + { + "message": "type 'list_type: > ' does not support field selection" + } + ] + } + }, + { + "name": "int64_field_select_unsupported", + "expr": "a.pancakes", + "disableCheck": true, + "typeEnv": [ + { + "name": "a", + "ident": { + "type": { + "primitive": "INT64" + } + } + } + ], + "bindings": { + "a": { + "value": { + "int64Value": "15" + } + } + }, + "evalError": { + "errors": [ + { + "message": "type 'int64_type' does not support field selection" + } + ] + } + }, + { + "name": "ident_with_longest_prefix_check", + "description": "namespace resolution should try to find the longest prefix for the checker.", + "expr": "a.b.c", + "typeEnv": [ + { + "name": "a.b.c", + "ident": { + "type": { + "primitive": "STRING" + } + } + }, + { + "name": "a.b", + "ident": { + "type": { + "mapType": { + "keyType": { + "primitive": "STRING" + }, + "valueType": { + "primitive": "STRING" + } + } + } + } + } + ], + "bindings": { + "a.b": { + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "c" + }, + "value": { + "stringValue": "oops" + } + } + ] + } + } + }, + "a.b.c": { + "value": { + "stringValue": "yeah" + } + } + }, + "value": { + "stringValue": "yeah" + } + }, + { + "name": "map_key_float", + "description": "map should not support float as the key.", + "expr": "{3.3:15.15, 1.0: 5}[1.0]", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "unsupported key type" + } + ] + } + }, + { + "name": "map_key_null", + "description": "map should not support null as the key.", + "expr": "{null:false}[null]", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "unsupported key type" + } + ] + } + }, + { + "name": "map_value_repeat_key", + "description": "map should not support repeated key.", + "expr": "{true:1,false:2,true:3}[true]", + "evalError": { + "errors": [ + { + "message": "Failed with repeated key" + } + ] + } + }, + { + "name": "map_value_repeat_key_heterogeneous", + "description": "map should not support repeated key.", + "expr": "{0: 1, 0u: 2}[0.0]", + "evalError": { + "errors": [ + { + "message": "Failed with repeated key" + } + ] + } + } + ] + }, + { + "name": "in", + "description": "Tests for 'in' operator for maps.", + "test": [ + { + "name": "empty", + "expr": "7 in {}", + "value": { + "boolValue": false + } + }, + { + "name": "singleton", + "expr": "true in {true: 1}", + "value": { + "boolValue": true + } + }, + { + "name": "present", + "expr": "'George' in {'John': 'smart', 'Paul': 'cute', 'George': 'quiet', 'Ringo': 'funny'}", + "value": { + "boolValue": true + } + }, + { + "name": "absent", + "expr": "'spider' in {'ant': 6, 'fly': 6, 'centipede': 100}", + "value": { + "boolValue": false + } + }, + { + "name": "mixed_numbers_and_keys_present", + "expr": "3.0 in {1: 1, 2: 2, 3u: 3} && 2u in {1u: 1, 2: 2} && 1 in {1u: 1, 2: 2}", + "value": { + "boolValue": true + } + }, + { + "name": "mixed_numbers_and_keys_absent", + "expr": "3.1 in {1: 1, 2: 2, 3u: 3}", + "value": { + "boolValue": false + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/fields.textproto b/packages/cel/src/lib/conformance/testdata/fields.textproto new file mode 100644 index 0000000..963827b --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/fields.textproto @@ -0,0 +1,462 @@ +name: "fields" +description: "Tests for field access in maps." +section { + name: "map_fields" + description: "select an element in a map" + test { + name: "map_key_int64" + expr: "{0:1,2:2,5:true}[5]" + value: { bool_value: true } + } + test { + name: "map_key_uint64" + expr: "{0u:1u,2u:'happy',5u:3u}[2u]" + value: { string_value: "happy" } + } + test { + name: "map_key_string" + expr: "{'name':100u}['name']" + value: { uint64_value: 100 } + } + test { + name: "map_key_bool" + expr: '{true:5}[true]' + value: { int64_value: 5 } + } + test { + name: "map_key_mixed_type" + expr: "{true:1,2:2,5u:3}[true]" + value: { int64_value: 1 } + } + test { + name: "map_key_mixed_numbers_double_key" + expr: "{1u: 1.0, 2: 2.0, 3u: 3.0}[3.0]" + value: { double_value: 3.0 } + } + test { + name: "map_key_mixed_numbers_lossy_double_key" + expr: "{1u: 1.0, 2: 2.0, 3u: 3.0}[3.1]" + eval_error: { + errors: { message: "no such key" } + } + } + test { + name: "map_key_mixed_numbers_uint_key" + expr: "{1u: 1.0, 2: 2.0, 3u: 3.0}[2u]" + value: { double_value: 2.0 } + } + test { + name: "map_key_mixed_numbers_int_key" + expr: "{1u: 1.0, 2: 2.0, 3u: 3.0}[1]" + value: { double_value: 1.0 } + } + test { + name: "map_field_access" + expr: "x.name" + type_env: { + name: "x", + ident: { + type: { + map_type: { + key_type: {primitive: STRING} + value_type: {primitive: INT64} + } + } + } + } + bindings: { + key: "x", + value: { + value: { + map_value: { + entries { + key: { string_value: "name" } + value: { int64_value: 1024 } + } + } + } + } + } + value: { int64_value: 1024 } + } + test { + name: "map_no_such_key" + expr: "{0:1,2:2,5:3}[1]" + eval_error: { + errors: { message: "no such key" } + } + } + test { + name: "map_field_select_no_such_key" + expr: "x.name" + type_env: { + name: "x", + ident: { + type: { + map_type: { + key_type: {primitive: STRING} + value_type: {primitive: STRING} + } + } + } + } + bindings: { + key: "x", + value: { + value: { + map_value: { + entries { + key: { string_value: "holiday" } + value: { string_value: "field" } + } + } + } + } + } + eval_error: { + errors: { message:"no such key: 'name'" } + } + } + test { + name: "map_value_null" + expr: '{true:null}[true]' + value: { null_value: NULL_VALUE } + } + test { + name: "map_value_bool" + expr: '{27:false}[27]' + value: { bool_value: false } + } + test { + name: "map_value_string" + expr: "{'n':'x'}['n']" + value: { string_value: 'x' } + } + test { + name: "map_value_float" + expr: "{3:15.15}[3]" + value: { double_value: 15.15 } + } + test { + name: "map_value_uint64" + expr: "{0u:1u,2u:2u,5u:3u}[0u]" + value: { uint64_value: 1 } + } + test { + name: "map_value_int64" + expr: "{true:1,false:2}[true]" + value: { int64_value: 1 } + } + test { + name: "map_value_bytes" + expr: '{0:b""}[0]' + value: { bytes_value: "" } + } + test { + name: "map_value_list" + expr: '{0u:[1]}[0u]' + value: { + list_value: { + values: { int64_value: 1 } + } + } + } + test { + name: "map_value_map" + expr: '{"map": {"k": "v"}}["map"]' + value: { + map_value { + entries { + key: { string_value: "k" } + value: { string_value: "v" } + } + } + } + } + test { + name: "map_value_mix_type" + expr: '{"map": {"k": "v"}, "list": [1]}["map"]' + value: { + map_value { + entries { + key: { string_value: "k" } + value: { string_value: "v" } + } + } + } + } +} +section { + name: "map_has" + description: "Has macro for map entries." + test { + name: "has" + expr: "has({'a': 1, 'b': 2}.a)" + value: { bool_value: true } + } + test { + name: "has_not" + expr: "has({'a': 1, 'b': 2}.c)" + value: { bool_value: false } + } + test { + name: "has_empty" + expr: "has({}.a)" + value: { bool_value: false } + } +} +section { + name: "qualified_identifier_resolution" + description: "Tests for qualified identifier resolution." + test { + name: "qualified_ident" + expr: "a.b.c" + type_env: { + name: "a.b.c", + ident: { type: { primitive: STRING } } + } + bindings: { + key: "a.b.c", + value: { value: { string_value: "yeah" } } + } + value: { string_value: "yeah" } + } + test { + name: "map_field_select" + expr: "a.b.c" + type_env: { + name: "a.b", + ident: { + type: { + map_type: { + key_type: {primitive: STRING} + value_type: {primitive: STRING} + } + } + } + } + bindings: { + key: "a.b", + value: { + value: { + map_value: { + entries { + key: { string_value: "c" } + value: { string_value: "yeah" } + } + } + } + } + } + value: { string_value: "yeah" } + } + test { + name: "qualified_identifier_resolution_unchecked" + description: "namespace resolution should try to find the longest prefix for the evaluator." + expr: "a.b.c" + type_env: { + name: "a.b.c", + ident: { type: { primitive: STRING } } + } + bindings: { + key: "a.b.c", + value: { value: { string_value: "yeah" } } + } + type_env: { + name: "a.b", + ident: { + type: { + map_type: { + key_type: {primitive: STRING} + value_type: {primitive: STRING} + } + } + } + } + bindings: { + key: "a.b" + value: { + value: { + map_value: { + entries { + key: { string_value: "c" } + value: { string_value: "oops" } + } + } + } + } + } + disable_check: true ## when check is disabled, the evaluator should evaluate it in the correct order + value: { string_value: "yeah" } + } + test { + name: "list_field_select_unsupported" + expr: "a.b.pancakes" + disable_check: true + type_env: { + name: "a.b", + ident: { + type: { + list_type: { + elem_type: {primitive: STRING} + } + } + } + } + bindings: { + key: "a.b", + value: { + value: { + list_value: { + values: { string_value: "pancakes" } + } + } + } + } + eval_error: { + errors: { + message:"type 'list_type: > ' does not support field selection" + } + } + } + test { + name: "int64_field_select_unsupported" + expr: "a.pancakes" + disable_check: true + type_env: { + name: "a", + ident: { + type: { + primitive: INT64 + } + } + } + bindings: { + key: "a", + value: { + value: { + int64_value: 15 + } + } + } + eval_error: { + errors: { + message:"type 'int64_type' does not support field selection" + } + } + } + test { + name: "ident_with_longest_prefix_check" + description: "namespace resolution should try to find the longest prefix for the checker." + expr: "a.b.c" + type_env: { + name: "a.b.c", + ident: { type: { primitive: STRING } } + } + bindings: { + key: "a.b.c", + value: { value: { string_value: "yeah" } } + } + type_env: { + name: "a.b", + ident: { + type: { + map_type: { + key_type: {primitive: STRING} + value_type: {primitive: STRING} + } + } + } + } + bindings: { + key: "a.b" + value: { + value: { + map_value: { + entries { + key: { string_value: "c" } + value: { string_value: "oops" } + } + } + } + } + } + value: { string_value: "yeah" } + } + test { + name: "map_key_float" + description: "map should not support float as the key." + expr: "{3.3:15.15, 1.0: 5}[1.0]" + disable_check: true # need to make it fail in the evaluation phase + eval_error: { + errors: { message: "unsupported key type" } + } + ## Current behavior + ## value: { int64_value: 5 } + } + test { + name: "map_key_null" + description: "map should not support null as the key." + expr: "{null:false}[null]" + disable_check: true # need to make it fail in the evaluation phase + eval_error: { + errors: { message: "unsupported key type" } + } + ## Current behavior + ## value: { bool_value: false } + } + test { + name: "map_value_repeat_key" + description: "map should not support repeated key." + expr: "{true:1,false:2,true:3}[true]" + eval_error: { + errors: { message: "Failed with repeated key" } + } + ## Current behavior: + ## value: { int64_value: 1 } + } + test { + name: "map_value_repeat_key_heterogeneous" + description: "map should not support repeated key." + expr: "{0: 1, 0u: 2}[0.0]" + eval_error: { + errors: { message: "Failed with repeated key" } + } + ## Current behavior: + ## value: { int64_value: 1 } + } +} +section { + name: "in" + description: "Tests for 'in' operator for maps." + test { + name: "empty" + expr: "7 in {}" + value: { bool_value: false } + } + test { + name: "singleton" + expr: "true in {true: 1}" + value: { bool_value: true } + } + test { + name: "present" + expr: "'George' in {'John': 'smart', 'Paul': 'cute', 'George': 'quiet', 'Ringo': 'funny'}" + value: { bool_value: true } + } + test { + name: "absent" + expr: "'spider' in {'ant': 6, 'fly': 6, 'centipede': 100}" + value: { bool_value: false } + } + test { + name: "mixed_numbers_and_keys_present" + expr: "3.0 in {1: 1, 2: 2, 3u: 3} && 2u in {1u: 1, 2: 2} && 1 in {1u: 1, 2: 2}" + value: { bool_value: true } + } + test { + name: "mixed_numbers_and_keys_absent" + expr: "3.1 in {1: 1, 2: 2, 3u: 3}" + value: { bool_value: false } + } +} diff --git a/packages/cel/src/lib/conformance/testdata/fp_math.json b/packages/cel/src/lib/conformance/testdata/fp_math.json new file mode 100755 index 0000000..683cb41 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/fp_math.json @@ -0,0 +1,230 @@ +{ + "name": "fp_math", + "description": "Tests for floating-point math.", + "section": [ + { + "name": "fp_math", + "description": "Simple tests for floating point.", + "test": [ + { + "name": "add_positive_positive", + "expr": "4.25 + 15.25", + "value": { + "doubleValue": 19.5 + } + }, + { + "name": "add_positive_negative", + "expr": "17.75 + (-7.75)", + "value": { + "doubleValue": 10 + } + }, + { + "name": "add_negative_negative", + "expr": "-4.125 + (-2.125)", + "value": { + "doubleValue": -6.25 + } + }, + { + "name": "sub_positive_positive", + "expr": "42.0 - 12.0", + "value": { + "doubleValue": 30 + } + }, + { + "name": "sub_positive_negative", + "expr": "42.875 - (-22.0)", + "value": { + "doubleValue": 64.875 + } + }, + { + "name": "sub_negative_negative", + "expr": "-4.875 - (-0.125)", + "value": { + "doubleValue": -4.75 + } + }, + { + "name": "multiply_positive_positive", + "expr": "42.5 * 0.2", + "value": { + "doubleValue": 8.5 + } + }, + { + "name": "multiply_positive_negative", + "expr": "40.75 * (-2.25)", + "value": { + "doubleValue": -91.6875 + } + }, + { + "name": "multiply_negative_negative", + "expr": "-3.0 * (-2.5)", + "value": { + "doubleValue": 7.5 + } + }, + { + "name": "divide_positive_positive", + "expr": "0.0625 / 0.002", + "value": { + "doubleValue": 31.25 + } + }, + { + "name": "divide_positive_negative", + "expr": "-2.0 / 2.0", + "value": { + "doubleValue": -1 + } + }, + { + "name": "divide_negative_negative", + "expr": "-8.875 / (-0.0625)", + "value": { + "doubleValue": 142 + } + }, + { + "name": "mod_not_support", + "expr": "47.5 % 5.5", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "found no matching overload for '_%_' applied to '(double, double)'" + } + ] + } + }, + { + "name": "negative", + "expr": "-(4.5)", + "value": { + "doubleValue": -4.5 + } + }, + { + "name": "double_negative", + "expr": "-(-1.25)", + "value": { + "doubleValue": 1.25 + } + }, + { + "name": "negative_zero", + "expr": "-(0.0)", + "value": { + "doubleValue": -0 + } + }, + { + "name": "divide_zero", + "expr": "15.75 / 0.0", + "value": { + "doubleValue": "Infinity" + } + }, + { + "name": "multiply_zero", + "expr": "15.36 * 0.0", + "value": { + "doubleValue": 0 + } + }, + { + "name": "add_left_identity", + "expr": "0.0 + 1.75", + "value": { + "doubleValue": 1.75 + } + }, + { + "name": "add_right_identity", + "expr": " 2.5 + 0.0", + "value": { + "doubleValue": 2.5 + } + }, + { + "name": "add_commutative", + "expr": "7.5 + 1.5 == 1.5 + 7.5", + "value": { + "boolValue": true + } + }, + { + "name": "add_associative", + "expr": "5.625 + (15.75 + 2.0) == (5.625 + 15.75) + 2.0", + "value": { + "boolValue": true + } + }, + { + "name": "mul_left_identity", + "expr": "1.0 * 45.25", + "value": { + "doubleValue": 45.25 + } + }, + { + "name": "mul_right_identity", + "expr": "-25.25 * 1.0", + "value": { + "doubleValue": -25.25 + } + }, + { + "name": "mul_commutative", + "expr": "1.5 * 25.875 == 25.875 * 1.5", + "value": { + "boolValue": true + } + }, + { + "name": "mul_associative", + "expr": "1.5 * (23.625 * 0.75) == (1.5 * 23.625) * 0.75", + "value": { + "boolValue": true + } + }, + { + "name": "add_mul_distribute", + "expr": "5.75 * (1.5 + 2.5) == 5.75 * 1.5 + 5.75 * 2.5", + "value": { + "boolValue": true + } + }, + { + "name": "fp_overflow_positive", + "description": "DBL_MAX(2^1023) times two", + "expr": "2.0 * 8.988466e+307 ", + "value": { + "doubleValue": "Infinity" + } + }, + { + "name": "fp_overflow_negative", + "description": "-DBL_MAX(-2^1023) times two", + "expr": "2.0 * -8.988466e+307 ", + "value": { + "doubleValue": "-Infinity" + } + }, + { + "name": "fp_underflow", + "description": "DBL_MIN(2^-1074) divided by two", + "expr": "1e-324 / 2.0", + "value": { + "doubleValue": 0 + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/fp_math.textproto b/packages/cel/src/lib/conformance/testdata/fp_math.textproto new file mode 100644 index 0000000..38a3eae --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/fp_math.textproto @@ -0,0 +1,164 @@ +name: "fp_math" +description: "Tests for floating-point math." +section { + name: "fp_math" + description: "Simple tests for floating point." + test { + name: "add_positive_positive" + expr: "4.25 + 15.25" + value: { double_value: 19.5 } + } + test { + name: "add_positive_negative" + expr: "17.75 + (-7.75)" + value: { double_value: 10 } + } + test { + name: "add_negative_negative" + expr: "-4.125 + (-2.125)" + value: { double_value: -6.25 } + } + test { + name: "sub_positive_positive" + expr: "42.0 - 12.0" + value: { double_value: 30 } + } + test { + name: "sub_positive_negative" + expr: "42.875 - (-22.0)" + value: { double_value: 64.875 } + } + test { + name: "sub_negative_negative" + expr: "-4.875 - (-0.125)" + value: { double_value: -4.75 } + } + test { + name: "multiply_positive_positive" + expr: "42.5 * 0.2" + value: { double_value: 8.5 } + } + test { + name: "multiply_positive_negative" + expr: "40.75 * (-2.25)" + value: { double_value: -91.6875 } + } + test { + name: "multiply_negative_negative" + expr: "-3.0 * (-2.5)" + value: { double_value: 7.5 } + } + test { + name: "divide_positive_positive" + expr: "0.0625 / 0.002" + value: { double_value: 31.25 } + } + test { + name: "divide_positive_negative" + expr: "-2.0 / 2.0" + value: { double_value: -1 } + } + test { + name: "divide_negative_negative" + expr: "-8.875 / (-0.0625)" + value: { double_value: 142 } + } + test { + name: "mod_not_support" + expr: "47.5 % 5.5" + disable_check: true + eval_error: { + errors: { message:"found no matching overload for '_%_' applied to '(double, double)'" } + } + } + test { + name: "negative" + expr: "-(4.5)" + value: { double_value: -4.5 } + } + test { + name: "double_negative" + expr: "-(-1.25)" + value: { double_value: 1.25 } + } + test { + name: "negative_zero" + expr: "-(0.0)" + value: { double_value: -0.0 } + } + test { + name: "divide_zero" + expr: "15.75 / 0.0" + value: { double_value: Infinity } + } + test { + name: "multiply_zero" + expr: "15.36 * 0.0" + value: { double_value: 0 } + } + test { + name: "add_left_identity" + expr: "0.0 + 1.75" + value: { double_value: 1.75} + } + test { + name: "add_right_identity" + expr: " 2.5 + 0.0" + value: { double_value: 2.5 } + } + test { + name: "add_commutative" + expr: "7.5 + 1.5 == 1.5 + 7.5" + value: { bool_value: true } + } + test { + name: "add_associative" + expr: "5.625 + (15.75 + 2.0) == (5.625 + 15.75) + 2.0" + value: { bool_value: true } + } + test { + name: "mul_left_identity" + expr: "1.0 * 45.25" + value: { double_value: 45.25 } + } + test { + name: "mul_right_identity" + expr: "-25.25 * 1.0" + value: { double_value: -25.25 } + } + test { + name: "mul_commutative" + expr: "1.5 * 25.875 == 25.875 * 1.5" + value: { bool_value: true } + } + test { + name: "mul_associative" + expr: "1.5 * (23.625 * 0.75) == (1.5 * 23.625) * 0.75" + value: { bool_value: true } + } + test { + name: "add_mul_distribute" + expr: "5.75 * (1.5 + 2.5) == 5.75 * 1.5 + 5.75 * 2.5" + ## overflow or underflow may cause this not equal. + value: { bool_value: true } + } + test { + name: "fp_overflow_positive" + description: "DBL_MAX(2^1023) times two" + expr: "2.0 * 8.988466e+307 " + value: {double_value: inf} + } + test { + name: "fp_overflow_negative" + description: "-DBL_MAX(-2^1023) times two" + expr: "2.0 * -8.988466e+307 " + value: {double_value: -inf} + } + test { + name: "fp_underflow" + description: "DBL_MIN(2^-1074) divided by two" + expr: "1e-324 / 2.0" + ## Expect it to be the closest number to the exact result. + value: {double_value: 0} + } +} diff --git a/packages/cel/src/lib/conformance/testdata/integer_math.json b/packages/cel/src/lib/conformance/testdata/integer_math.json new file mode 100755 index 0000000..6c96418 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/integer_math.json @@ -0,0 +1,557 @@ +{ + "name": "integer_math", + "description": "Tests for int and uint math.", + "section": [ + { + "name": "int64_math", + "description": "Simple tests for int64.", + "test": [ + { + "name": "add_positive_positive", + "expr": "40 + 2", + "value": { + "int64Value": "42" + } + }, + { + "name": "add_positive_negative", + "expr": "42 + (-7)", + "value": { + "int64Value": "35" + } + }, + { + "name": "add_negative_negative", + "expr": "-4 + (-2)", + "value": { + "int64Value": "-6" + } + }, + { + "name": "sub_positive_positive", + "expr": "42 - 12", + "value": { + "int64Value": "30" + } + }, + { + "name": "sub_positive_negative", + "expr": "42 - (-22)", + "value": { + "int64Value": "64" + } + }, + { + "name": "sub_negative_negative", + "expr": "-42 - (-12)", + "value": { + "int64Value": "-30" + } + }, + { + "name": "multiply_positive_positive", + "expr": "42 * 2", + "value": { + "int64Value": "84" + } + }, + { + "name": "multiply_positive_negative", + "expr": "40 * (-2)", + "value": { + "int64Value": "-80" + } + }, + { + "name": "multiply_negative_negative", + "expr": "-30 * (-2)", + "value": { + "int64Value": "60" + } + }, + { + "name": "divide_positive_positive", + "expr": "42 / 2", + "value": { + "int64Value": "21" + } + }, + { + "name": "divide_positive_negative", + "expr": "-20 / 2", + "value": { + "int64Value": "-10" + } + }, + { + "name": "divide_negative_negative", + "expr": "-80 / (-2)", + "value": { + "int64Value": "40" + } + }, + { + "name": "mod_positive_positive", + "expr": "47 % 5", + "value": { + "int64Value": "2" + } + }, + { + "name": "mod_positive_negative", + "expr": "43 % (-5)", + "value": { + "int64Value": "3" + } + }, + { + "name": "mod_negative_negative", + "expr": "-42 % (-5)", + "value": { + "int64Value": "-2" + } + }, + { + "name": "mod_negative_positive", + "expr": "-3 % 5", + "value": { + "int64Value": "-3" + } + }, + { + "name": "unary_minus_pos", + "expr": "-(42)", + "value": { + "int64Value": "-42" + } + }, + { + "name": "unary_minus_neg", + "expr": "-(-42)", + "value": { + "int64Value": "42" + } + }, + { + "name": "unary_minus_no_overload", + "expr": "-(42u)", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no_such_overload" + } + ] + } + }, + { + "name": "unary_minus_not_bool", + "expr": "-false", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no_such_overload" + } + ] + } + }, + { + "name": "mod_zero", + "expr": "34 % 0", + "evalError": { + "errors": [ + { + "message": "modulus by zero" + } + ] + } + }, + { + "name": "negtive_zero", + "expr": "-(0)", + "value": { + "int64Value": "0" + } + }, + { + "name": "double_negative", + "expr": "-(-42)", + "value": { + "int64Value": "42" + } + }, + { + "name": "divide_zero", + "expr": "15 / 0", + "evalError": { + "errors": [ + { + "message": "divide by zero" + } + ] + } + }, + { + "name": "multiply_zero", + "expr": "15 * 0", + "value": { + "int64Value": "0" + } + }, + { + "name": "add_left_identity", + "expr": "0 + 17", + "value": { + "int64Value": "17" + } + }, + { + "name": "add_right_identity", + "expr": " 29 + 0", + "value": { + "int64Value": "29" + } + }, + { + "name": "add_commutative", + "expr": "75 + 15 == 15 + 75", + "value": { + "boolValue": true + } + }, + { + "name": "add_associative", + "expr": "5 + (15 + 20) == (5 + 15) + 20", + "value": { + "boolValue": true + } + }, + { + "name": "mul_left_identity", + "expr": "1 * 45", + "value": { + "int64Value": "45" + } + }, + { + "name": "mul_right_identity", + "expr": "-25 * 1", + "value": { + "int64Value": "-25" + } + }, + { + "name": "mul_commutative", + "expr": "15 * 25 == 25 * 15", + "value": { + "boolValue": true + } + }, + { + "name": "mul_associative", + "expr": "15 * (23 * 88) == (15 * 23) * 88", + "value": { + "boolValue": true + } + }, + { + "name": "add_mul_distribute", + "expr": "5 * (15 + 25) == 5 * 15 + 5 * 25", + "value": { + "boolValue": true + } + }, + { + "name": "int64_overflow_positive", + "description": "LLONG_MAX plus one.", + "expr": "9223372036854775807 + 1", + "evalError": { + "errors": [ + { + "message": "return error for overflow" + } + ] + } + }, + { + "name": "int64_overflow_negative", + "description": "LLONG_MIN minus one.", + "expr": "-9223372036854775808 - 1", + "evalError": { + "errors": [ + { + "message": "return error for overflow" + } + ] + } + }, + { + "name": "int64_overflow_add_negative", + "description": "negative overflow via addition", + "expr": "-9223372036854775808 + (-1)", + "evalError": { + "errors": [ + { + "message": "return error for overflow" + } + ] + } + }, + { + "name": "int64_overflow_sub_positive", + "description": "positive overflow via subtraction", + "expr": "1 - (-9223372036854775807)", + "evalError": { + "errors": [ + { + "message": "return error for overflow" + } + ] + } + }, + { + "name": "int64_min_negate", + "description": "Negated LLONG_MIN is not representable.", + "expr": "-(-9223372036854775808)", + "evalError": { + "errors": [ + { + "message": "return error for overflow" + } + ] + } + }, + { + "name": "int64_min_negate_mul", + "description": "Negate LLONG_MIN via multiplication", + "expr": "(-9223372036854775808) * -1", + "evalError": { + "errors": [ + { + "message": "return error for overflow" + } + ] + } + }, + { + "name": "int64_min_negate_div", + "description": "Negate LLONG_MIN via division.", + "expr": "(-9223372036854775808)/-1", + "evalError": { + "errors": [ + { + "message": "return error for overflow" + } + ] + } + }, + { + "name": "int64_overflow_mul_positive", + "description": "Overflow via multiplication.", + "expr": "5000000000 * 5000000000", + "evalError": { + "errors": [ + { + "message": "return error for overflow" + } + ] + } + }, + { + "name": "int64_overflow_mul_negative", + "description": "Overflow via multiplication.", + "expr": "(-5000000000) * 5000000000", + "evalError": { + "errors": [ + { + "message": "return error for overflow" + } + ] + } + }, + { + "name": "uint64_overflow_positive", + "description": "ULLONG_MAX plus one.", + "expr": "18446744073709551615u + 1u", + "evalError": { + "errors": [ + { + "message": "return error for overflow" + } + ] + } + }, + { + "name": "uint64_overflow_negative", + "description": "zero minus one.", + "expr": "0u - 1u", + "evalError": { + "errors": [ + { + "message": "return error for overflow" + } + ] + } + }, + { + "name": "uint64_overflow_mul_positive", + "description": "Overflow via multiplication.", + "expr": "5000000000u * 5000000000u", + "evalError": { + "errors": [ + { + "message": "return error for overflow" + } + ] + } + } + ] + }, + { + "name": "uint64_math", + "description": "Simple tests for uint64.", + "test": [ + { + "name": "add", + "expr": "42u + 2u", + "value": { + "uint64Value": "44" + } + }, + { + "name": "sub", + "expr": "42u - 12u", + "value": { + "uint64Value": "30" + } + }, + { + "name": "multiply", + "expr": "40u * 2u", + "value": { + "uint64Value": "80" + } + }, + { + "name": "divide", + "expr": "60u / 2u", + "value": { + "uint64Value": "30" + } + }, + { + "name": "mod", + "expr": "42u % 5u", + "value": { + "uint64Value": "2" + } + }, + { + "name": "negtive_no_overload", + "expr": "-(5u)", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "mod_zero", + "expr": "34u % 0u", + "evalError": { + "errors": [ + { + "message": "modulus by zero" + } + ] + } + }, + { + "name": "divide_zero", + "expr": "15u / 0u", + "evalError": { + "errors": [ + { + "message": "divide by zero" + } + ] + } + }, + { + "name": "multiply_zero", + "expr": "15u * 0u", + "value": { + "uint64Value": "0" + } + }, + { + "name": "add_left_identity", + "expr": "0u + 17u", + "value": { + "uint64Value": "17" + } + }, + { + "name": "add_right_identity", + "expr": " 29u + 0u", + "value": { + "uint64Value": "29" + } + }, + { + "name": "add_commutative", + "expr": "75u + 15u == 15u + 75u", + "value": { + "boolValue": true + } + }, + { + "name": "add_associative", + "expr": "5u + (15u + 20u) == (5u + 15u) + 20u", + "value": { + "boolValue": true + } + }, + { + "name": "mul_left_identity", + "expr": "1u * 45u", + "value": { + "uint64Value": "45" + } + }, + { + "name": "mul_right_identity", + "expr": "25u * 1u", + "value": { + "uint64Value": "25" + } + }, + { + "name": "mul_commutative", + "expr": "15u * 25u == 25u * 15u", + "value": { + "boolValue": true + } + }, + { + "name": "mul_associative", + "expr": "15u * (23u * 88u) == (15u * 23u) * 88u", + "value": { + "boolValue": true + } + }, + { + "name": "add_mul_distribute", + "expr": "5u * (15u + 25u) == 5u * 15u + 5u * 25u", + "value": { + "boolValue": true + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/integer_math.textproto b/packages/cel/src/lib/conformance/testdata/integer_math.textproto new file mode 100644 index 0000000..0d15330 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/integer_math.textproto @@ -0,0 +1,383 @@ +name: "integer_math" +description: "Tests for int and uint math." +section { + name: "int64_math" + description: "Simple tests for int64." + test { + name: "add_positive_positive" + expr: "40 + 2" + value: { int64_value: 42 } + } + test { + name: "add_positive_negative" + expr: "42 + (-7)" + value: { int64_value: 35 } + } + test { + name: "add_negative_negative" + expr: "-4 + (-2)" + value: { int64_value: -6 } + } + test { + name: "sub_positive_positive" + expr: "42 - 12" + value: { int64_value: 30 } + } + test { + name: "sub_positive_negative" + expr: "42 - (-22)" + value: { int64_value: 64 } + } + test { + name: "sub_negative_negative" + expr: "-42 - (-12)" + value: { int64_value: -30 } + } + test { + name: "multiply_positive_positive" + expr: "42 * 2" + value: { int64_value: 84 } + } + test { + name: "multiply_positive_negative" + expr: "40 * (-2)" + value: { int64_value: -80 } + } + test { + name: "multiply_negative_negative" + expr: "-30 * (-2)" + value: { int64_value: 60 } + } + test { + name: "divide_positive_positive" + expr: "42 / 2" + value: { int64_value: 21 } + } + test { + name: "divide_positive_negative" + expr: "-20 / 2" + value: { int64_value: -10 } + } + test { + name: "divide_negative_negative" + expr: "-80 / (-2)" + value: { int64_value: 40 } + } + test { + name: "mod_positive_positive" + expr: "47 % 5" + value: { int64_value: 2 } + } + test { + name: "mod_positive_negative" + expr: "43 % (-5)" + value: { int64_value: 3 } + } + test { + name: "mod_negative_negative" + expr: "-42 % (-5)" + value: { int64_value: -2 } + } + test { + name: "mod_negative_positive" + expr: "-3 % 5" + value: { int64_value: -3 } + } + test { + name: "unary_minus_pos" + expr: "-(42)" + value: { int64_value: -42 } + } + test { + name: "unary_minus_neg" + expr: "-(-42)" + value: { int64_value: 42 } + } + test { + name: "unary_minus_no_overload" + expr: "-(42u)" + disable_check: true + eval_error: { + errors: { message:"no_such_overload" } + } + } + test { + name: "unary_minus_not_bool" + expr: "-false" + disable_check: true + eval_error: { + errors: { message:"no_such_overload" } + } + } + test { + name: "mod_zero" + expr: "34 % 0" + eval_error: { + errors: { message:"modulus by zero" } + } + } + test { + name: "negtive_zero" + expr: "-(0)" + value: { int64_value: 0 } + } + test { + name: "double_negative" + expr: "-(-42)" + value: { int64_value: 42 } + } + test { + name: "divide_zero" + expr: "15 / 0" + eval_error: { + errors: { message:"divide by zero" } + } + } + test { + name: "multiply_zero" + expr: "15 * 0" + value: { int64_value: 0 } + } + test { + name: "add_left_identity" + expr: "0 + 17" + value: { int64_value: 17} + } + test { + name: "add_right_identity" + expr: " 29 + 0" + value: { int64_value: 29 } + } + test { + name: "add_commutative" + expr: "75 + 15 == 15 + 75" + value: { bool_value: true } + } + test { + name: "add_associative" + expr: "5 + (15 + 20) == (5 + 15) + 20" + value: { bool_value: true } + } + test { + name: "mul_left_identity" + expr: "1 * 45" + value: { int64_value: 45 } + } + test { + name: "mul_right_identity" + expr: "-25 * 1" + value: { int64_value: -25 } + } + test { + name: "mul_commutative" + expr: "15 * 25 == 25 * 15" + value: { bool_value: true } + } + test { + name: "mul_associative" + expr: "15 * (23 * 88) == (15 * 23) * 88" + value: { bool_value: true } + } + test { + name: "add_mul_distribute" + expr: "5 * (15 + 25) == 5 * 15 + 5 * 25" + value: { bool_value: true } + } + test { + name: "int64_overflow_positive" + description: "LLONG_MAX plus one." + expr: "9223372036854775807 + 1" + eval_error: { + errors: { message: "return error for overflow" } + } + } + test { + name: "int64_overflow_negative" + description: "LLONG_MIN minus one." + expr: "-9223372036854775808 - 1" + eval_error: { + errors: { message: "return error for overflow" } + } + } + test { + name: "int64_overflow_add_negative" + description: "negative overflow via addition" + expr: "-9223372036854775808 + (-1)" + eval_error: { + errors: { message: "return error for overflow" } + } + } + test { + name: "int64_overflow_sub_positive" + description: "positive overflow via subtraction" + expr: "1 - (-9223372036854775807)" + eval_error: { + errors: { message: "return error for overflow" } + } + } + test { + name: "int64_min_negate" + description: "Negated LLONG_MIN is not representable." + expr: "-(-9223372036854775808)" + eval_error: { + errors: { message: "return error for overflow" } + } + } + test { + name: "int64_min_negate_mul" + description: "Negate LLONG_MIN via multiplication" + expr: "(-9223372036854775808) * -1" + eval_error: { + errors: { message: "return error for overflow" } + } + } + test { + name: "int64_min_negate_div" + description: "Negate LLONG_MIN via division." + expr: "(-9223372036854775808)/-1" + eval_error: { + errors: { message: "return error for overflow" } + } + } + test { + name: "int64_overflow_mul_positive" + description: "Overflow via multiplication." + expr: "5000000000 * 5000000000" + eval_error: { + errors: { message: "return error for overflow" } + } + } + test { + name: "int64_overflow_mul_negative" + description: "Overflow via multiplication." + expr: "(-5000000000) * 5000000000" + eval_error: { + errors: { message: "return error for overflow" } + } + } + test { + name: "uint64_overflow_positive" + description: "ULLONG_MAX plus one." + expr: "18446744073709551615u + 1u" + eval_error: { + errors: { message: "return error for overflow" } + } + } + test { + name: "uint64_overflow_negative" + description: "zero minus one." + expr: "0u - 1u" + eval_error: { + errors: { message: "return error for overflow" } + } + } + test { + name: "uint64_overflow_mul_positive" + description: "Overflow via multiplication." + expr: "5000000000u * 5000000000u" + eval_error: { + errors: { message: "return error for overflow" } + } + } +} +section { + name: "uint64_math" + description: "Simple tests for uint64." + test { + name: "add" + expr: "42u + 2u" + value: { uint64_value: 44 } + } + test { + name: "sub" + expr: "42u - 12u" + value: { uint64_value: 30 } + } + test { + name: "multiply" + expr: "40u * 2u" + value: { uint64_value: 80 } + } + test { + name: "divide" + expr: "60u / 2u" + value: { uint64_value: 30 } + } + test { + name: "mod" + expr: "42u % 5u" + value: { uint64_value: 2 } + } + test { + name: "negtive_no_overload" + expr: "-(5u)" + disable_check: true + eval_error: { + errors: { message:"no such overload" } + } + } + test { + name: "mod_zero" + expr: "34u % 0u" + eval_error: { + errors: { message:"modulus by zero" } + } + } + test { + name: "divide_zero" + expr: "15u / 0u" + eval_error: { + errors: { message:"divide by zero" } + } + } + test { + name: "multiply_zero" + expr: "15u * 0u" + value: { uint64_value: 0 } + } + test { + name: "add_left_identity" + expr: "0u + 17u" + value: { uint64_value: 17} + } + test { + name: "add_right_identity" + expr: " 29u + 0u" + value: { uint64_value: 29 } + } + test { + name: "add_commutative" + expr: "75u + 15u == 15u + 75u" + value: { bool_value: true } + } + test { + name: "add_associative" + expr: "5u + (15u + 20u) == (5u + 15u) + 20u" + value: { bool_value: true } + } + test { + name: "mul_left_identity" + expr: "1u * 45u" + value: { uint64_value: 45 } + } + test { + name: "mul_right_identity" + expr: "25u * 1u" + value: { uint64_value: 25 } + } + test { + name: "mul_commutative" + expr: "15u * 25u == 25u * 15u" + value: { bool_value: true } + } + test { + name: "mul_associative" + expr: "15u * (23u * 88u) == (15u * 23u) * 88u" + value: { bool_value: true } + } + test { + name: "add_mul_distribute" + expr: "5u * (15u + 25u) == 5u * 15u + 5u * 25u" + value: { bool_value: true } + } +} diff --git a/packages/cel/src/lib/conformance/testdata/lists.json b/packages/cel/src/lib/conformance/testdata/lists.json new file mode 100755 index 0000000..a09ccf3 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/lists.json @@ -0,0 +1,275 @@ +{ + "name": "lists", + "description": "Tests for list operations.", + "section": [ + { + "name": "concatentation", + "description": "Tests for list concatenation.", + "test": [ + { + "name": "list_append", + "expr": "[0, 1, 2] + [3, 4, 5] == [0, 1, 2, 3, 4, 5]", + "value": { + "boolValue": true + } + }, + { + "name": "list_not_commutative", + "expr": "[0, 1, 2] + [3, 4, 5] == [3, 4, 5, 0, 1, 2]", + "value": { + "boolValue": false + } + }, + { + "name": "list_repeat", + "expr": "[2] + [2]", + "value": { + "listValue": { + "values": [ + { + "int64Value": "2" + }, + { + "int64Value": "2" + } + ] + } + } + }, + { + "name": "empty_empty", + "expr": "[] + []", + "value": { + "listValue": {} + } + }, + { + "name": "left_unit", + "expr": "[] + [3, 4]", + "value": { + "listValue": { + "values": [ + { + "int64Value": "3" + }, + { + "int64Value": "4" + } + ] + } + } + }, + { + "name": "right_unit", + "expr": "[1, 2] + []", + "value": { + "listValue": { + "values": [ + { + "int64Value": "1" + }, + { + "int64Value": "2" + } + ] + } + } + } + ] + }, + { + "name": "index", + "description": "List indexing tests.", + "test": [ + { + "name": "zero_based", + "expr": "[7, 8, 9][0]", + "value": { + "int64Value": "7" + } + }, + { + "name": "zero_based_double", + "expr": "[7, 8, 9][dyn(0.0)]", + "value": { + "int64Value": "7" + } + }, + { + "name": "zero_based_double_error", + "expr": "[7, 8, 9][dyn(0.1)]", + "evalError": { + "errors": [ + { + "message": "invalid_argument" + } + ] + } + }, + { + "name": "zero_based_uint", + "expr": "[7, 8, 9][dyn(0u)]", + "value": { + "int64Value": "7" + } + }, + { + "name": "singleton", + "expr": "['foo'][0]", + "value": { + "stringValue": "foo" + } + }, + { + "name": "middle", + "expr": "[0, 1, 1, 2, 3, 5, 8, 13][4]", + "value": { + "int64Value": "3" + } + }, + { + "name": "last", + "expr": "['George', 'John', 'Paul', 'Ringo'][3]", + "value": { + "stringValue": "Ringo" + } + }, + { + "name": "range", + "expr": "[1, 2, 3][3]", + "evalError": { + "errors": [ + { + "message": "invalid_argument" + } + ] + } + } + ] + }, + { + "name": "in", + "description": "List membership tests.", + "test": [ + { + "name": "empty", + "expr": "7 in []", + "value": { + "boolValue": false + } + }, + { + "name": "singleton", + "expr": "4u in [4u]", + "value": { + "boolValue": true + } + }, + { + "name": "first", + "expr": "'alpha' in ['alpha', 'beta', 'gamma']", + "value": { + "boolValue": true + } + }, + { + "name": "middle", + "expr": "3 in [5, 4, 3, 2, 1]", + "value": { + "boolValue": true + } + }, + { + "name": "last", + "expr": "20u in [4u, 6u, 8u, 12u, 20u]", + "value": { + "boolValue": true + } + }, + { + "name": "double_in_ints", + "expr": "dyn(3.0) in [5, 4, 3, 2, 1]", + "value": { + "boolValue": true + } + }, + { + "name": "uint_in_ints", + "expr": "dyn(3u) in [5, 4, 3, 2, 1]", + "value": { + "boolValue": true + } + }, + { + "name": "int_in_doubles", + "expr": "dyn(3) in [5.0, 4.0, 3.0, 2.0, 1.0]", + "value": { + "boolValue": true + } + }, + { + "name": "uint_in_doubles", + "expr": "dyn(3u) in [5.0, 4.0, 3.0, 2.0, 1.0]", + "value": { + "boolValue": true + } + }, + { + "name": "int_in_uints", + "expr": "dyn(3) in [5u, 4u, 3u, 2u, 1u]", + "value": { + "boolValue": true + } + }, + { + "name": "double_in_uints", + "expr": "dyn(3.0) in [5u, 4u, 3u, 2u, 1u]", + "value": { + "boolValue": true + } + }, + { + "name": "missing", + "expr": "'hawaiian' in ['meat', 'veggie', 'margarita', 'cheese']", + "value": { + "boolValue": false + } + } + ] + }, + { + "name": "size", + "description": "List and map size tests.", + "test": [ + { + "name": "list_empty", + "expr": "size([])", + "value": { + "int64Value": "0" + } + }, + { + "name": "list", + "expr": "size([1, 2, 3])", + "value": { + "int64Value": "3" + } + }, + { + "name": "map_empty", + "expr": "size({})", + "value": { + "int64Value": "0" + } + }, + { + "name": "map", + "expr": "size({1: 'one', 2: 'two', 3: 'three'})", + "value": { + "int64Value": "3" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/lists.textproto b/packages/cel/src/lib/conformance/testdata/lists.textproto new file mode 100644 index 0000000..5b1f4f4 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/lists.textproto @@ -0,0 +1,187 @@ +name: "lists" +description: "Tests for list operations." +section { + name: "concatentation" + description: "Tests for list concatenation." + test { + name: "list_append" + expr: "[0, 1, 2] + [3, 4, 5] == [0, 1, 2, 3, 4, 5]" + value: { bool_value: true } + } + test { + name: "list_not_commutative" + expr: "[0, 1, 2] + [3, 4, 5] == [3, 4, 5, 0, 1, 2]" + value: { bool_value: false } + } + test { + name: "list_repeat" + expr: "[2] + [2]" + value: { + list_value { + values: { int64_value: 2 } + values: { int64_value: 2 } + } + } + } + test { + name: "empty_empty" + expr: "[] + []" + value: { list_value { } } + } + test { + name: "left_unit" + expr: "[] + [3, 4]" + value: { + list_value { + values { int64_value: 3 } + values { int64_value: 4 } + } + } + } + test { + name: "right_unit" + expr: "[1, 2] + []" + value { + list_value { + values { int64_value: 1 } + values { int64_value: 2 } + } + } + } +} +section { + name: "index" + description: "List indexing tests." + test { + name: "zero_based" + expr: "[7, 8, 9][0]" + value: { int64_value: 7 } + } + test { + name: "zero_based_double" + expr: "[7, 8, 9][dyn(0.0)]" + value: { int64_value: 7 } + } + test { + name: "zero_based_double_error" + expr: "[7, 8, 9][dyn(0.1)]" + eval_error { + errors { message: "invalid_argument" } + } + } + test { + name: "zero_based_uint" + expr: "[7, 8, 9][dyn(0u)]" + value: { int64_value: 7 } + } + test { + name: "singleton" + expr: "['foo'][0]" + value: { string_value: "foo" } + } + test { + name: "middle" + expr: "[0, 1, 1, 2, 3, 5, 8, 13][4]" + value: { int64_value: 3 } + } + test { + name: "last" + expr: "['George', 'John', 'Paul', 'Ringo'][3]" + value: { string_value: "Ringo" } + } + test { + name: "range" + expr: "[1, 2, 3][3]" + eval_error { + errors { message: "invalid_argument" } + } + } +} +section { + name: "in" + description: "List membership tests." + test { + name: "empty" + expr: "7 in []" + value: { bool_value: false } + } + test { + name: "singleton" + expr: "4u in [4u]" + value: { bool_value: true } + } + test { + name: "first" + expr: "'alpha' in ['alpha', 'beta', 'gamma']" + value: { bool_value: true } + } + test { + name: "middle" + expr: "3 in [5, 4, 3, 2, 1]" + value: { bool_value: true } + } + test { + name: "last" + expr: "20u in [4u, 6u, 8u, 12u, 20u]" + value: { bool_value: true } + } + test { + name: "double_in_ints" + expr: "dyn(3.0) in [5, 4, 3, 2, 1]" + value: { bool_value: true } + } + test { + name: "uint_in_ints" + expr: "dyn(3u) in [5, 4, 3, 2, 1]" + value: { bool_value: true } + } + test { + name: "int_in_doubles" + expr: "dyn(3) in [5.0, 4.0, 3.0, 2.0, 1.0]" + value: { bool_value: true } + } + test { + name: "uint_in_doubles" + expr: "dyn(3u) in [5.0, 4.0, 3.0, 2.0, 1.0]" + value: { bool_value: true } + } + test { + name: "int_in_uints" + expr: "dyn(3) in [5u, 4u, 3u, 2u, 1u]" + value: { bool_value: true } + } + test { + name: "double_in_uints" + expr: "dyn(3.0) in [5u, 4u, 3u, 2u, 1u]" + value: { bool_value: true } + } + test { + name: "missing" + expr: "'hawaiian' in ['meat', 'veggie', 'margarita', 'cheese']" + value: { bool_value: false } + } +} +section { + name: "size" + description: "List and map size tests." + test { + name: "list_empty" + expr: "size([])" + value: { int64_value: 0 } + } + test { + name: "list" + expr: "size([1, 2, 3])" + value: { int64_value: 3 } + } + test { + name: "map_empty" + expr: "size({})" + value: { int64_value: 0 } + } + test { + name: "map" + expr: "size({1: 'one', 2: 'two', 3: 'three'})" + value: { int64_value: 3 } + } +} diff --git a/packages/cel/src/lib/conformance/testdata/logic.json b/packages/cel/src/lib/conformance/testdata/logic.json new file mode 100755 index 0000000..b13234c --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/logic.json @@ -0,0 +1,285 @@ +{ + "name": "logic", + "description": "Tests for logical special operators.", + "section": [ + { + "name": "conditional", + "description": "Tests for the conditional operator.", + "test": [ + { + "name": "true_case", + "expr": "true ? 1 : 2", + "value": { + "int64Value": "1" + } + }, + { + "name": "false_case", + "expr": "false ? 'foo' : 'bar'", + "value": { + "stringValue": "bar" + } + }, + { + "name": "error_case", + "expr": "2 / 0 > 4 ? 'baz' : 'quux'", + "evalError": { + "errors": [ + { + "message": "division by zero" + } + ] + } + }, + { + "name": "mixed_type", + "expr": "true ? 'cows' : 17", + "disableCheck": true, + "value": { + "stringValue": "cows" + } + }, + { + "name": "bad_type", + "expr": "'cows' ? false : 17", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no matching overload" + } + ] + } + } + ] + }, + { + "name": "AND", + "description": "Tests for logical AND.", + "test": [ + { + "name": "all_true", + "expr": "true && true", + "value": { + "boolValue": true + } + }, + { + "name": "all_false", + "expr": "false && false", + "value": { + "boolValue": false + } + }, + { + "name": "false_left", + "expr": "false && true", + "value": { + "boolValue": false + } + }, + { + "name": "false_right", + "expr": "true && false", + "value": { + "boolValue": false + } + }, + { + "name": "short_circuit_type_left", + "expr": "false && 32", + "disableCheck": true, + "value": { + "boolValue": false + } + }, + { + "name": "short_circuit_type_right", + "expr": "'horses' && false", + "disableCheck": true, + "value": { + "boolValue": false + } + }, + { + "name": "short_circuit_error_left", + "expr": "false && (2 / 0 > 3 ? false : true)", + "value": { + "boolValue": false + } + }, + { + "name": "short_circuit_error_right", + "expr": "(2 / 0 > 3 ? false : true) && false", + "value": { + "boolValue": false + } + }, + { + "name": "error_right", + "expr": "true && 1/0 != 0", + "evalError": { + "errors": [ + { + "message": "no matching overload" + } + ] + } + }, + { + "name": "error_left", + "expr": "1/0 != 0 && true", + "evalError": { + "errors": [ + { + "message": "no matching overload" + } + ] + } + }, + { + "name": "no_overload", + "expr": "'less filling' && 'tastes great'", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no matching overload" + } + ] + } + } + ] + }, + { + "name": "OR", + "description": "Tests for logical OR", + "test": [ + { + "name": "all_true", + "expr": "true || true", + "value": { + "boolValue": true + } + }, + { + "name": "all_false", + "expr": "false || false", + "value": { + "boolValue": false + } + }, + { + "name": "false_left", + "expr": "false || true", + "value": { + "boolValue": true + } + }, + { + "name": "false_right", + "expr": "true || false", + "value": { + "boolValue": true + } + }, + { + "name": "short_circuit_type_left", + "expr": "true || 32", + "disableCheck": true, + "value": { + "boolValue": true + } + }, + { + "name": "short_circuit_type_right", + "expr": "'horses' || true", + "disableCheck": true, + "value": { + "boolValue": true + } + }, + { + "name": "short_circuit_error_left", + "expr": "true || (2 / 0 > 3 ? false : true)", + "value": { + "boolValue": true + } + }, + { + "name": "short_circuit_error_right", + "expr": "(2 / 0 > 3 ? false : true) || true", + "value": { + "boolValue": true + } + }, + { + "name": "error_right", + "expr": "false || 1/0 != 0", + "evalError": { + "errors": [ + { + "message": "no matching overload" + } + ] + } + }, + { + "name": "error_left", + "expr": "1/0 != 0 || false", + "evalError": { + "errors": [ + { + "message": "no matching overload" + } + ] + } + }, + { + "name": "no_overload", + "expr": "'less filling' || 'tastes great'", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no matching overload" + } + ] + } + } + ] + }, + { + "name": "NOT", + "description": "Tests for logical NOT.", + "test": [ + { + "name": "not_true", + "expr": "!true", + "value": { + "boolValue": false + } + }, + { + "name": "not_false", + "expr": "!false", + "value": { + "boolValue": true + } + }, + { + "name": "no_overload", + "expr": "!0", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no matching overload" + } + ] + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/logic.textproto b/packages/cel/src/lib/conformance/testdata/logic.textproto new file mode 100644 index 0000000..42d9f7c --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/logic.textproto @@ -0,0 +1,195 @@ +name: "logic" +description: "Tests for logical special operators." +section { + name: "conditional" + description: "Tests for the conditional operator." + test { + name: "true_case" + expr: "true ? 1 : 2" + value: { int64_value: 1 } + } + test { + name: "false_case" + expr: "false ? 'foo' : 'bar'" + value: { string_value: "bar" } + } + test { + name: "error_case" + expr: "2 / 0 > 4 ? 'baz' : 'quux'" + eval_error: { + errors: { message: "division by zero" } + } + } + test { + name: "mixed_type" + expr: "true ? 'cows' : 17" + disable_check: true + value: { string_value: "cows" } + } + test { + name: "bad_type" + expr: "'cows' ? false : 17" + disable_check: true + eval_error: { + errors: { message: "no matching overload" } + } + } +} +section { + name: "AND" + description: "Tests for logical AND." + test { + name: "all_true" + expr: "true && true" + value: { bool_value: true } + } + test { + name: "all_false" + expr: "false && false" + value: { bool_value: false } + } + test { + name: "false_left" + expr: "false && true" + value: { bool_value: false } + } + test { + name: "false_right" + expr: "true && false" + value: { bool_value: false } + } + test { + name: "short_circuit_type_left" + expr: "false && 32" + disable_check: true + value: { bool_value: false } + } + test { + name: "short_circuit_type_right" + expr: "'horses' && false" + disable_check: true + value: { bool_value: false } + } + test { + name: "short_circuit_error_left" + expr: "false && (2 / 0 > 3 ? false : true)" + value: { bool_value: false } + } + test { + name: "short_circuit_error_right" + expr: "(2 / 0 > 3 ? false : true) && false" + value: { bool_value: false } + } + test { + name: "error_right" + expr: "true && 1/0 != 0" + eval_error: { + errors: { message: "no matching overload" } + } + } + test { + name: "error_left" + expr: "1/0 != 0 && true" + eval_error: { + errors: { message: "no matching overload" } + } + } + test { + name: "no_overload" + expr: "'less filling' && 'tastes great'" + disable_check: true + eval_error: { + errors: { message: "no matching overload" } + } + } +} +section { + name: "OR" + description: "Tests for logical OR" + test { + name: "all_true" + expr: "true || true" + value: { bool_value: true } + } + test { + name: "all_false" + expr: "false || false" + value: { bool_value: false } + } + test { + name: "false_left" + expr: "false || true" + value: { bool_value: true } + } + test { + name: "false_right" + expr: "true || false" + value: { bool_value: true } + } + test { + name: "short_circuit_type_left" + expr: "true || 32" + disable_check: true + value: { bool_value: true } + } + test { + name: "short_circuit_type_right" + expr: "'horses' || true" + disable_check: true + value: { bool_value: true } + } + test { + name: "short_circuit_error_left" + expr: "true || (2 / 0 > 3 ? false : true)" + value: { bool_value: true } + } + test { + name: "short_circuit_error_right" + expr: "(2 / 0 > 3 ? false : true) || true" + value: { bool_value: true } + } + test { + name: "error_right" + expr: "false || 1/0 != 0" + eval_error: { + errors: { message: "no matching overload" } + } + } + test { + name: "error_left" + expr: "1/0 != 0 || false" + eval_error: { + errors: { message: "no matching overload" } + } + } + test { + name: "no_overload" + expr: "'less filling' || 'tastes great'" + disable_check: true + eval_error: { + errors: { message: "no matching overload" } + } + } +} +section { + name: "NOT" + description: "Tests for logical NOT." + test { + name: "not_true" + expr: "!true" + value: { bool_value: false } + } + test { + name: "not_false" + expr: "!false" + value: { bool_value: true } + } + test { + name: "no_overload" + expr: "!0" + disable_check: true + eval_error: { + errors: { message: "no matching overload" } + } + } +} diff --git a/packages/cel/src/lib/conformance/testdata/macros.json b/packages/cel/src/lib/conformance/testdata/macros.json new file mode 100755 index 0000000..9dde3ab --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/macros.json @@ -0,0 +1,430 @@ +{ + "name": "macros", + "description": "Tests for CEL macros.", + "section": [ + { + "name": "exists", + "description": "Tests for the .exists() macro, which is equivalent to joining the evaluated elements with logical-OR.", + "test": [ + { + "name": "list_elem_all_true", + "expr": "[1, 2, 3].exists(e, e > 0)", + "value": { + "boolValue": true + } + }, + { + "name": "list_elem_some_true", + "expr": "[1, 2, 3].exists(e, e == 2)", + "value": { + "boolValue": true + } + }, + { + "name": "list_elem_none_true", + "expr": "[1, 2, 3].exists(e, e > 3)", + "value": { + "boolValue": false + } + }, + { + "name": "list_elem_type_shortcircuit", + "description": "Exists filter is true for the last element.", + "expr": "[1, 'foo', 3].exists(e, e != '1')", + "value": { + "boolValue": true + } + }, + { + "name": "list_elem_type_exhaustive", + "description": "Exists filter is never true, but heterogenous equality ensure the result is false.", + "expr": "[1, 'foo', 3].exists(e, e == '10')", + "value": { + "boolValue": false + } + }, + { + "name": "list_elem_exists_error", + "expr": "[1, 2, 3].exists(e, e / 0 == 17)", + "evalError": { + "errors": [ + { + "message": "divide by zero" + } + ] + } + }, + { + "name": "list_empty", + "expr": "[].exists(e, e == 2)", + "value": { + "boolValue": false + } + }, + { + "name": "map_key", + "expr": "{'key1':1, 'key2':2}.exists(k, k == 'key2')", + "value": { + "boolValue": true + } + }, + { + "name": "not_map_key", + "expr": "!{'key1':1, 'key2':2}.exists(k, k == 'key3')", + "value": { + "boolValue": true + } + }, + { + "name": "map_key_type_shortcircuit", + "description": "Exists filter is true for the second key", + "expr": "{'key':1, 1:21}.exists(k, k != 2)", + "value": { + "boolValue": true + } + }, + { + "name": "map_key_type_exhaustive", + "description": "Exists filter is never true, but heterogeneous equality ensures the result is false.", + "expr": "!{'key':1, 1:42}.exists(k, k == 2)", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "all", + "description": "Tests for the .all() macro, which is equivalent to joining the evaluated elements with logical-AND.", + "test": [ + { + "name": "list_elem_all_true", + "expr": "[1, 2, 3].all(e, e > 0)", + "value": { + "boolValue": true + } + }, + { + "name": "list_elem_some_true", + "expr": "[1, 2, 3].all(e, e == 2)", + "value": { + "boolValue": false + } + }, + { + "name": "list_elem_none_true", + "expr": "[1, 2, 3].all(e, e == 17)", + "value": { + "boolValue": false + } + }, + { + "name": "list_elem_type_shortcircuit", + "expr": "[1, 'foo', 3].all(e, e == 1)", + "value": { + "boolValue": false + } + }, + { + "name": "list_elem_type_exhaustive", + "expr": "[1, 'foo', 3].all(e, e % 2 == 1)", + "evalError": { + "errors": [ + { + "message": "no_such_overload" + } + ] + } + }, + { + "name": "list_elem_error_shortcircuit", + "expr": "[1, 2, 3].all(e, 6 / (2 - e) == 6)", + "value": { + "boolValue": false + } + }, + { + "name": "list_elem_error_exhaustive", + "expr": "[1, 2, 3].all(e, e / 0 != 17)", + "evalError": { + "errors": [ + { + "message": "divide by zero" + } + ] + } + }, + { + "name": "list_empty", + "expr": "[].all(e, e > 0)", + "value": { + "boolValue": true + } + }, + { + "name": "map_key", + "expr": "{'key1':1, 'key2':2}.all(k, k == 'key2')", + "value": { + "boolValue": false + } + } + ] + }, + { + "name": "exists_one", + "description": "Tests for exists_one() macro. An expression 'L.exists_one(I, E)' is equivalent to 'size(L.filter(I, E)) == 1'.", + "test": [ + { + "name": "list_empty", + "expr": "[].exists_one(a, a == 7)", + "value": { + "boolValue": false + } + }, + { + "name": "list_one_true", + "expr": "[7].exists_one(a, a == 7)", + "value": { + "boolValue": true + } + }, + { + "name": "list_one_false", + "expr": "[8].exists_one(a, a == 7)", + "value": { + "boolValue": false + } + }, + { + "name": "list_none", + "expr": "[1, 2, 3].exists_one(x, x > 20)", + "value": { + "boolValue": false + } + }, + { + "name": "list_one", + "expr": "[6, 7, 8].exists_one(foo, foo % 5 == 2)", + "value": { + "boolValue": true + } + }, + { + "name": "list_many", + "expr": "[0, 1, 2, 3, 4].exists_one(n, n % 2 == 1)", + "value": { + "boolValue": false + } + }, + { + "name": "list_all", + "expr": "['foal', 'foo', 'four'].exists_one(n, n.startsWith('fo'))", + "value": { + "boolValue": false + } + }, + { + "name": "list_no_shortcircuit", + "description": "Errors invalidate everything, even if already false.", + "expr": "[3, 2, 1, 0].exists_one(n, 12 / n > 1)", + "evalError": { + "errors": [ + { + "message": "divide by zero" + } + ] + } + }, + { + "name": "map_one", + "expr": "{6: 'six', 7: 'seven', 8: 'eight'}.exists_one(foo, foo % 5 == 2)", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "map", + "description": "Tests for map() macro.", + "test": [ + { + "name": "list_empty", + "expr": "[].map(n, n / 2)", + "value": { + "listValue": {} + } + }, + { + "name": "list_one", + "expr": "[3].map(n, n * n)", + "value": { + "listValue": { + "values": [ + { + "int64Value": "9" + } + ] + } + } + }, + { + "name": "list_many", + "expr": "[2, 4, 6].map(n, n / 2)", + "value": { + "listValue": { + "values": [ + { + "int64Value": "1" + }, + { + "int64Value": "2" + }, + { + "int64Value": "3" + } + ] + } + } + }, + { + "name": "list_error", + "expr": "[2, 1, 0].map(n, 4 / n)", + "evalError": { + "errors": [ + { + "message": "divide by zero" + } + ] + } + }, + { + "name": "map_extract_keys", + "expr": "{'John': 'smart'}.map(key, key) == ['John']", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "filter", + "description": "Tests for filter() macro.", + "test": [ + { + "name": "list_empty", + "expr": "[].filter(n, n % 2 == 0)", + "value": { + "listValue": {} + } + }, + { + "name": "list_one_true", + "expr": "[2].filter(n, n == 2)", + "value": { + "listValue": { + "values": [ + { + "int64Value": "2" + } + ] + } + } + }, + { + "name": "list_one_false", + "expr": "[1].filter(n, n > 3)", + "value": { + "listValue": {} + } + }, + { + "name": "list_none", + "expr": "[1, 2, 3].filter(e, e > 3)", + "value": { + "listValue": {} + } + }, + { + "name": "list_some", + "expr": "[0, 1, 2, 3, 4].filter(x, x % 2 == 1)", + "value": { + "listValue": { + "values": [ + { + "int64Value": "1" + }, + { + "int64Value": "3" + } + ] + } + } + }, + { + "name": "list_all", + "expr": "[1, 2, 3].filter(n, n > 0)", + "value": { + "listValue": { + "values": [ + { + "int64Value": "1" + }, + { + "int64Value": "2" + }, + { + "int64Value": "3" + } + ] + } + } + }, + { + "name": "list_no_shortcircuit", + "expr": "[3, 2, 1, 0].filter(n, 12 / n > 4)", + "evalError": { + "errors": [ + { + "message": "divide by zero" + } + ] + } + }, + { + "name": "map_filter_keys", + "expr": "{'John': 'smart', 'Paul': 'cute', 'George': 'quiet', 'Ringo': 'funny'}.filter(key, key == 'Ringo') == ['Ringo']", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "nested", + "description": "Tests with nested macros.", + "test": [ + { + "name": "filter_all", + "expr": "['signer'].filter(signer, ['artifact'].all(artifact, true))", + "value": { + "listValue": { + "values": [ + { + "stringValue": "signer" + } + ] + } + } + }, + { + "name": "all_all", + "expr": "['signer'].all(signer, ['artifact'].all(artifact, true))", + "value": { + "boolValue": true + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/macros.textproto b/packages/cel/src/lib/conformance/testdata/macros.textproto new file mode 100644 index 0000000..cd2e3f8 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/macros.textproto @@ -0,0 +1,286 @@ +name: "macros" +description: "Tests for CEL macros." +section { + name: "exists" + description: "Tests for the .exists() macro, which is equivalent to joining the evaluated elements with logical-OR." + test { + name: "list_elem_all_true" + expr: "[1, 2, 3].exists(e, e > 0)" + value: { bool_value: true } + } + test { + name: "list_elem_some_true" + expr: "[1, 2, 3].exists(e, e == 2)" + value: { bool_value: true } + } + test { + name: "list_elem_none_true" + expr: "[1, 2, 3].exists(e, e > 3)" + value: { bool_value: false } + } + test { + name: "list_elem_type_shortcircuit" + description: "Exists filter is true for the last element." + expr: "[1, 'foo', 3].exists(e, e != '1')" + value: { bool_value: true } + } + test { + name: "list_elem_type_exhaustive" + description: "Exists filter is never true, but heterogenous equality ensure the result is false." + expr: "[1, 'foo', 3].exists(e, e == '10')" + value: { bool_value: false } + } + test { + name: "list_elem_exists_error" + expr: "[1, 2, 3].exists(e, e / 0 == 17)" + eval_error: { + errors: { message: "divide by zero" } + } + } + test { + name: "list_empty" + expr: "[].exists(e, e == 2)" + value: { bool_value: false } + } + test { + name: "map_key" + expr: "{'key1':1, 'key2':2}.exists(k, k == 'key2')" + value: { bool_value: true } + } + test { + name: "not_map_key" + expr: "!{'key1':1, 'key2':2}.exists(k, k == 'key3')" + value: { bool_value: true } + } + test { + name: "map_key_type_shortcircuit" + description: "Exists filter is true for the second key" + expr: "{'key':1, 1:21}.exists(k, k != 2)" + value: { bool_value: true } + } + test { + name: "map_key_type_exhaustive" + description: "Exists filter is never true, but heterogeneous equality ensures the result is false." + expr: "!{'key':1, 1:42}.exists(k, k == 2)" + value: { bool_value: true } + } +} +section { + name: "all" + description: "Tests for the .all() macro, which is equivalent to joining the evaluated elements with logical-AND." + test { + name: "list_elem_all_true" + expr: "[1, 2, 3].all(e, e > 0)" + value: { bool_value: true } + } + test { + name: "list_elem_some_true" + expr: "[1, 2, 3].all(e, e == 2)" + value: { bool_value: false } + } + test { + name: "list_elem_none_true" + expr: "[1, 2, 3].all(e, e == 17)" + value: { bool_value: false } + } + test { + name: "list_elem_type_shortcircuit" + expr: "[1, 'foo', 3].all(e, e == 1)" + value: { bool_value: false } + } + test { + name: "list_elem_type_exhaustive" + expr: "[1, 'foo', 3].all(e, e % 2 == 1)" + eval_error: { + errors: { message: "no_such_overload" } + } + } + test { + name: "list_elem_error_shortcircuit" + expr: "[1, 2, 3].all(e, 6 / (2 - e) == 6)" + value: { bool_value: false } + } + test { + name: "list_elem_error_exhaustive" + expr: "[1, 2, 3].all(e, e / 0 != 17)" + eval_error: { + errors: { message: "divide by zero" } + } + } + test { + name: "list_empty" + expr: "[].all(e, e > 0)" + value: { bool_value: true } + } + test { + name: "map_key" + expr: "{'key1':1, 'key2':2}.all(k, k == 'key2')" + value: { bool_value: false } + } +} +section { + name: "exists_one" + description: "Tests for exists_one() macro. An expression 'L.exists_one(I, E)' is equivalent to 'size(L.filter(I, E)) == 1'." + test { + name: "list_empty" + expr: "[].exists_one(a, a == 7)" + value: { bool_value: false } + } + test { + name: "list_one_true" + expr: "[7].exists_one(a, a == 7)" + value: { bool_value: true } + } + test { + name: "list_one_false" + expr: "[8].exists_one(a, a == 7)" + value: { bool_value: false } + } + test { + name: "list_none" + expr: "[1, 2, 3].exists_one(x, x > 20)" + value: { bool_value: false } + } + test { + name: "list_one" + expr: "[6, 7, 8].exists_one(foo, foo % 5 == 2)" + value: { bool_value: true } + } + test { + name: "list_many" + expr: "[0, 1, 2, 3, 4].exists_one(n, n % 2 == 1)" + value: { bool_value: false } + } + test { + name: "list_all" + expr: "['foal', 'foo', 'four'].exists_one(n, n.startsWith('fo'))" + value: { bool_value: false } + } + test { + name: "list_no_shortcircuit" + description: "Errors invalidate everything, even if already false." + expr: "[3, 2, 1, 0].exists_one(n, 12 / n > 1)" + eval_error { + errors: { message: "divide by zero" } + } + } + test { + name: "map_one" + expr: "{6: 'six', 7: 'seven', 8: 'eight'}.exists_one(foo, foo % 5 == 2)" + value: { bool_value: true } + } +} +section { + name: "map" + description: "Tests for map() macro." + test { + name: "list_empty" + expr: "[].map(n, n / 2)" + value: { list_value: {} } + } + test { + name: "list_one" + expr: "[3].map(n, n * n)" + value: { list_value { + values: { int64_value: 9 } + } + } + } + test { + name: "list_many" + expr: "[2, 4, 6].map(n, n / 2)" + value: { list_value { + values: { int64_value: 1 } + values: { int64_value: 2 } + values: { int64_value: 3 } + } + } + } + test { + name: "list_error" + expr: "[2, 1, 0].map(n, 4 / n)" + eval_error { + errors: { message: "divide by zero" } + } + } + test { + name: "map_extract_keys" + expr: "{'John': 'smart'}.map(key, key) == ['John']" + value: { bool_value: true } + } +} +section { + name: "filter" + description: "Tests for filter() macro." + test { + name: "list_empty" + expr: "[].filter(n, n % 2 == 0)" + value: { list_value {} } + } + test { + name: "list_one_true" + expr: "[2].filter(n, n == 2)" + value: { list_value { + values: { int64_value: 2 } + } + } + } + test { + name: "list_one_false" + expr: "[1].filter(n, n > 3)" + value: { list_value {} } + } + test { + name: "list_none" + expr: "[1, 2, 3].filter(e, e > 3)" + value: { list_value {} } + } + test { + name: "list_some" + expr: "[0, 1, 2, 3, 4].filter(x, x % 2 == 1)" + value: { list_value { + values: { int64_value: 1 } + values: { int64_value: 3 } + } + } + } + test { + name: "list_all" + expr: "[1, 2, 3].filter(n, n > 0)" + value: { list_value { + values: { int64_value: 1 } + values: { int64_value: 2 } + values: { int64_value: 3 } + } + } + } + test { + name: "list_no_shortcircuit" + expr: "[3, 2, 1, 0].filter(n, 12 / n > 4)" + eval_error { + errors: { message: "divide by zero" } + } + } + test { + name: "map_filter_keys" + expr: "{'John': 'smart', 'Paul': 'cute', 'George': 'quiet', 'Ringo': 'funny'}.filter(key, key == 'Ringo') == ['Ringo']" + value: { bool_value: true } + } +} +section { + name: "nested" + description: "Tests with nested macros." + test { + name: "filter_all" + expr: "['signer'].filter(signer, ['artifact'].all(artifact, true))" + value: { list_value { + values: { string_value: "signer" } + } + } + } + test { + name: "all_all" + expr: "['signer'].all(signer, ['artifact'].all(artifact, true))" + value: { bool_value: true } + } +} diff --git a/packages/cel/src/lib/conformance/testdata/math_ext.json b/packages/cel/src/lib/conformance/testdata/math_ext.json new file mode 100755 index 0000000..4926574 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/math_ext.json @@ -0,0 +1,1323 @@ +{ + "name": "math_ext", + "description": "Tests for the math extension library.", + "section": [ + { + "name": "greatest_int_result", + "test": [ + { + "name": "unary_negative", + "expr": "math.greatest(-5)", + "value": { + "int64Value": "-5" + } + }, + { + "name": "unary_positive", + "expr": "math.greatest(5)", + "value": { + "int64Value": "5" + } + }, + { + "name": "binary_same_args", + "expr": "math.greatest(1, 1)", + "value": { + "int64Value": "1" + } + }, + { + "name": "binary_with_decimal", + "expr": "math.greatest(1, 1.0) == 1" + }, + { + "name": "binary_with_uint", + "expr": "math.greatest(1, 1u) == 1" + }, + { + "name": "binary_first_arg_greater", + "expr": "math.greatest(3, -3)", + "value": { + "int64Value": "3" + } + }, + { + "name": "binary_second_arg_greater", + "expr": "math.greatest(-7, 5)", + "value": { + "int64Value": "5" + } + }, + { + "name": "binary_first_arg_int_max", + "expr": "math.greatest(9223372036854775807, 1)", + "value": { + "int64Value": "9223372036854775807" + } + }, + { + "name": "binary_second_arg_int_max", + "expr": "math.greatest(1, 9223372036854775807)", + "value": { + "int64Value": "9223372036854775807" + } + }, + { + "name": "binary_first_arg_int_min", + "expr": "math.greatest(-9223372036854775808, 1)", + "value": { + "int64Value": "1" + } + }, + { + "name": "binary_second_arg_int_min", + "expr": "math.greatest(1, -9223372036854775808)", + "value": { + "int64Value": "1" + } + }, + { + "name": "ternary_same_args", + "expr": "math.greatest(1, 1, 1) == 1" + }, + { + "name": "ternary_with_decimal", + "expr": "math.greatest(1, 1.0, 1.0) == 1" + }, + { + "name": "ternary_with_uint", + "expr": "math.greatest(1, 1u, 1u) == 1" + }, + { + "name": "ternary_first_arg_greatest", + "expr": "math.greatest(10, 1, 3) == 10" + }, + { + "name": "ternary_third_arg_greatest", + "expr": "math.greatest(1, 3, 10) == 10" + }, + { + "name": "ternary_with_negatives", + "expr": "math.greatest(-1, -2, -3) == -1" + }, + { + "name": "ternary_int_max", + "expr": "math.greatest(9223372036854775807, 1, 5) == 9223372036854775807" + }, + { + "name": "ternary_int_min", + "expr": "math.greatest(-9223372036854775807, -1, -5) == -1" + }, + { + "name": "quaternary_mixed", + "expr": "math.greatest(5.4, 10, 3u, -5.0, 9223372036854775807) == 9223372036854775807" + }, + { + "name": "quaternary_mixed_array", + "expr": "math.greatest([5.4, 10, 3u, -5.0, 3.5]) == 10" + }, + { + "name": "quaternary_mixed_dyn_array", + "expr": "math.greatest([dyn(5.4), dyn(10), dyn(3u), dyn(-5.0), dyn(3.5)]) == 10" + } + ] + }, + { + "name": "greatest_double_result", + "test": [ + { + "name": "unary_negative", + "expr": "math.greatest(-5.0)", + "value": { + "doubleValue": -5 + } + }, + { + "name": "unary_positive", + "expr": "math.greatest(5.0)", + "value": { + "doubleValue": 5 + } + }, + { + "name": "binary_same_args", + "expr": "math.greatest(1.0, 1.0)", + "value": { + "doubleValue": 1 + } + }, + { + "name": "binary_with_int", + "expr": "math.greatest(1.0, 1) == 1.0" + }, + { + "name": "binary_with_uint", + "expr": "math.greatest(1.0, 1u) == 1.0" + }, + { + "name": "binary_first_arg_greater", + "expr": "math.greatest(5.0, -7.0)", + "value": { + "doubleValue": 5 + } + }, + { + "name": "binary_second_arg_greater", + "expr": "math.greatest(-3.0, 3.0)", + "value": { + "doubleValue": 3 + } + }, + { + "name": "binary_first_arg_double_max", + "expr": "math.greatest(1.797693e308, 1)", + "value": { + "doubleValue": 1.797693e+308 + } + }, + { + "name": "binary_second_arg_double_max", + "expr": "math.greatest(1, 1.797693e308)", + "value": { + "doubleValue": 1.797693e+308 + } + }, + { + "name": "binary_first_arg_double_min", + "expr": "math.greatest(-1.797693e308, 1.5)", + "value": { + "doubleValue": 1.5 + } + }, + { + "name": "binary_second_arg_double_min", + "expr": "math.greatest(1.5, -1.797693e308)", + "value": { + "doubleValue": 1.5 + } + }, + { + "name": "ternary_same_args", + "expr": "math.greatest(1.0, 1.0, 1.0) == 1.0" + }, + { + "name": "ternary_with_int", + "expr": "math.greatest(1.0, 1, 1) == 1.0" + }, + { + "name": "ternary_with_uint", + "expr": "math.greatest(1.0, 1u, 1u) == 1.0" + }, + { + "name": "ternary_first_arg_greatest", + "expr": "math.greatest(10.5, 1.5, 3.5) == 10.5" + }, + { + "name": "ternary_third_arg_greatest", + "expr": "math.greatest(1.5, 3.5, 10.5) == 10.5" + }, + { + "name": "ternary_with_negatives", + "expr": "math.greatest(-1.5, -2.5, -3.5) == -1.5" + }, + { + "name": "ternary_double_max", + "expr": "math.greatest(1.797693e308, 1, 5) == 1.797693e308" + }, + { + "name": "ternary_double_min", + "expr": "math.greatest(-1.797693e308, -1, -5) == -1" + }, + { + "name": "quaternary_mixed", + "expr": "math.greatest(5.4, 10, 3u, -5.0, 1.797693e308) == 1.797693e308" + }, + { + "name": "quaternary_mixed_array", + "expr": "math.greatest([5.4, 10.5, 3u, -5.0, 3.5]) == 10.5" + }, + { + "name": "quaternary_mixed_dyn_array", + "expr": "math.greatest([dyn(5.4), dyn(10.5), dyn(3u), dyn(-5.0), dyn(3.5)]) == 10.5" + } + ] + }, + { + "name": "greatest_uint_result", + "test": [ + { + "name": "unary", + "expr": "math.greatest(5u)", + "value": { + "uint64Value": "5" + } + }, + { + "name": "binary_same_args", + "expr": "math.greatest(1u, 1u)", + "value": { + "uint64Value": "1" + } + }, + { + "name": "binary_with_decimal", + "expr": "math.greatest(1u, 1.0) == 1" + }, + { + "name": "binary_with_int", + "expr": "math.greatest(1u, 1) == 1u" + }, + { + "name": "binary_first_arg_greater", + "expr": "math.greatest(5u, -7)", + "value": { + "uint64Value": "5" + } + }, + { + "name": "binary_second_arg_greater", + "expr": "math.greatest(-3, 3u)", + "value": { + "uint64Value": "3" + } + }, + { + "name": "binary_first_arg_uint_max", + "expr": "math.greatest(18446744073709551615u, 1u)", + "value": { + "uint64Value": "18446744073709551615" + } + }, + { + "name": "binary_second_arg_uint_max", + "expr": "math.greatest(1u, 18446744073709551615u)", + "value": { + "uint64Value": "18446744073709551615" + } + }, + { + "name": "ternary_same_args", + "expr": "math.greatest(1u, 1u, 1u) == 1u" + }, + { + "name": "ternary_with_decimal", + "expr": "math.greatest(1u, 1.0, 1.0) == 1u" + }, + { + "name": "ternary_with_int", + "expr": "math.greatest(1u, 1, 1) == 1u" + }, + { + "name": "ternary_first_arg_greatest", + "expr": "math.greatest(10u, 1u, 3u) == 10u" + }, + { + "name": "ternary_third_arg_greatest", + "expr": "math.greatest(1u, 3u, 10u) == 10u" + }, + { + "name": "ternary_int_max", + "expr": "math.greatest(18446744073709551615u, 1u, 5u) == 18446744073709551615u" + }, + { + "name": "quaternary_mixed", + "expr": "math.greatest(5.4, 10, 3u, -5.0, 18446744073709551615u) == 18446744073709551615u" + }, + { + "name": "quaternary_mixed_array", + "expr": "math.greatest([5.4, 10u, 3u, -5.0, 3.5]) == 10u" + }, + { + "name": "quaternary_mixed_dyn_array", + "expr": "math.greatest([dyn(5.4), dyn(10u), dyn(3u), dyn(-5.0), dyn(3.5)]) == 10u" + } + ] + }, + { + "name": "least_int_result", + "test": [ + { + "name": "unary_negative", + "expr": "math.least(-5)", + "value": { + "int64Value": "-5" + } + }, + { + "name": "unary_positive", + "expr": "math.least(5)", + "value": { + "int64Value": "5" + } + }, + { + "name": "binary_same_args", + "expr": "math.least(1, 1)", + "value": { + "int64Value": "1" + } + }, + { + "name": "binary_with_decimal", + "expr": "math.least(1, 1.0) == 1" + }, + { + "name": "binary_with_uint", + "expr": "math.least(1, 1u) == 1" + }, + { + "name": "binary_first_arg_least", + "expr": "math.least(-3, 3)", + "value": { + "int64Value": "-3" + } + }, + { + "name": "binary_second_arg_least", + "expr": "math.least(5, -7)", + "value": { + "int64Value": "-7" + } + }, + { + "name": "binary_first_arg_int_max", + "expr": "math.least(9223372036854775807, 1)", + "value": { + "int64Value": "1" + } + }, + { + "name": "binary_second_arg_int_max", + "expr": "math.least(1, 9223372036854775807)", + "value": { + "int64Value": "1" + } + }, + { + "name": "binary_first_arg_int_min", + "expr": "math.least(-9223372036854775808, 1)", + "value": { + "int64Value": "-9223372036854775808" + } + }, + { + "name": "binary_second_arg_int_min", + "expr": "math.least(1, -9223372036854775808)", + "value": { + "int64Value": "-9223372036854775808" + } + }, + { + "name": "ternary_same_args", + "expr": "math.least(1, 1, 1) == 1" + }, + { + "name": "ternary_with_decimal", + "expr": "math.least(1, 1.0, 1.0) == 1" + }, + { + "name": "ternary_with_uint", + "expr": "math.least(1, 1u, 1u) == 1" + }, + { + "name": "ternary_first_arg_least", + "expr": "math.least(0, 1, 3) == 0" + }, + { + "name": "ternary_third_arg_least", + "expr": "math.least(1, 3, 0) == 0" + }, + { + "name": "ternary_with_negatives", + "expr": "math.least(-1, -2, -3) == -3" + }, + { + "name": "ternary_int_max", + "expr": "math.least(9223372036854775807, 1, 5) == 1" + }, + { + "name": "ternary_int_min", + "expr": "math.least(-9223372036854775808, -1, -5) == -9223372036854775808" + }, + { + "name": "quaternary_mixed", + "expr": "math.least(5.4, 10, 3u, -5.0, 9223372036854775807) == -5.0" + }, + { + "name": "quaternary_mixed_array", + "expr": "math.least([5.4, 10, 3u, -5.0, 3.5]) == -5.0" + }, + { + "name": "quaternary_mixed_dyn_array", + "expr": "math.least([dyn(5.4), dyn(10), dyn(3u), dyn(-5.0), dyn(3.5)]) == -5.0" + } + ] + }, + { + "name": "least_double_result", + "test": [ + { + "name": "unary_negative", + "expr": "math.least(-5.5)", + "value": { + "doubleValue": -5.5 + } + }, + { + "name": "unary_positive", + "expr": "math.least(5.5)", + "value": { + "doubleValue": 5.5 + } + }, + { + "name": "binary_same_args", + "expr": "math.least(1.5, 1.5)", + "value": { + "doubleValue": 1.5 + } + }, + { + "name": "binary_with_int", + "expr": "math.least(1.0, 1) == 1" + }, + { + "name": "binary_with_uint", + "expr": "math.least(1, 1u) == 1" + }, + { + "name": "binary_first_arg_least", + "expr": "math.least(-3.5, 3.5)", + "value": { + "doubleValue": -3.5 + } + }, + { + "name": "binary_second_arg_least", + "expr": "math.least(5.5, -7.5)", + "value": { + "doubleValue": -7.5 + } + }, + { + "name": "binary_first_arg_double_max", + "expr": "math.least(1.797693e308, 1.5)", + "value": { + "doubleValue": 1.5 + } + }, + { + "name": "binary_second_arg_double_max", + "expr": "math.least(1.5, 1.797693e308)", + "value": { + "doubleValue": 1.5 + } + }, + { + "name": "binary_first_arg_double_min", + "expr": "math.least(-1.797693e308, 1.5)", + "value": { + "doubleValue": -1.797693e+308 + } + }, + { + "name": "binary_second_arg_double_min", + "expr": "math.least(1.5, -1.797693e308)", + "value": { + "doubleValue": -1.797693e+308 + } + }, + { + "name": "ternary_same_args", + "expr": "math.least(1.5, 1.5, 1.5) == 1.5" + }, + { + "name": "ternary_with_int", + "expr": "math.least(1.0, 1, 1) == 1.0" + }, + { + "name": "ternary_with_uint", + "expr": "math.least(1.0, 1u, 1u) == 1" + }, + { + "name": "ternary_first_arg_least", + "expr": "math.least(0.5, 1.5, 3.5) == 0.5" + }, + { + "name": "ternary_third_arg_least", + "expr": "math.least(1.5, 3.5, 0.5) == 0.5" + }, + { + "name": "ternary_with_negatives", + "expr": "math.least(-1.5, -2.5, -3.5) == -3.5" + }, + { + "name": "ternary_double_max", + "expr": "math.least(1.797693e308, 1, 5) == 1" + }, + { + "name": "ternary_double_min", + "expr": "math.least(-1.797693e308, -1, -5) == -1.797693e308" + }, + { + "name": "quaternary_mixed", + "expr": "math.least(5.4, 10, 3u, -5.0, 1.797693e308) == -5.0" + }, + { + "name": "quaternary_mixed_array", + "expr": "math.least([5.4, 10.5, 3u, -5.0, 3.5]) == -5.0" + }, + { + "name": "quaternary_mixed_dyn_array", + "expr": "math.least([dyn(5.4), dyn(10.5), dyn(3u), dyn(-5.0), dyn(3.5)]) == -5.0" + } + ] + }, + { + "name": "least_uint_result", + "test": [ + { + "name": "unary", + "expr": "math.least(5u)", + "value": { + "uint64Value": "5" + } + }, + { + "name": "binary_same_args", + "expr": "math.least(1u, 1u)", + "value": { + "uint64Value": "1" + } + }, + { + "name": "binary_with_decimal", + "expr": "math.least(1u, 1.0) == 1u" + }, + { + "name": "binary_with_int", + "expr": "math.least(1u, 1) == 1u" + }, + { + "name": "binary_first_arg_least", + "expr": "math.least(1u, 3u)", + "value": { + "uint64Value": "1" + } + }, + { + "name": "binary_second_arg_least", + "expr": "math.least(5u, 2u)", + "value": { + "uint64Value": "2" + } + }, + { + "name": "binary_first_arg_uint_max", + "expr": "math.least(18446744073709551615u, 1u)", + "value": { + "uint64Value": "1" + } + }, + { + "name": "binary_second_arg_uint_max", + "expr": "math.least(1u, 18446744073709551615u)", + "value": { + "uint64Value": "1" + } + }, + { + "name": "ternary_same_args", + "expr": "math.least(1u, 1u, 1u) == 1u" + }, + { + "name": "ternary_with_decimal", + "expr": "math.least(1u, 1.0, 1.0) == 1u" + }, + { + "name": "ternary_with_int", + "expr": "math.least(1u, 1, 1) == 1u" + }, + { + "name": "ternary_first_arg_least", + "expr": "math.least(1u, 10u, 3u) == 1u" + }, + { + "name": "ternary_third_arg_least", + "expr": "math.least(10u, 3u, 1u) == 1u" + }, + { + "name": "ternary_uint_max", + "expr": "math.least(18446744073709551615u, 1u, 5u) == 1u" + }, + { + "name": "quaternary_mixed", + "expr": "math.least(5.4, 10, 3u, 1u, 18446744073709551615u) == 1u" + }, + { + "name": "quaternary_mixed_array", + "expr": "math.least([5.4, 10u, 3u, 1u, 3.5]) == 1u" + }, + { + "name": "quaternary_mixed_dyn_array", + "expr": "math.least([dyn(5.4), dyn(10u), dyn(3u), dyn(1u), dyn(3.5)]) == 1u" + } + ] + }, + { + "name": "ceil", + "test": [ + { + "name": "negative", + "expr": "math.ceil(-1.2)", + "value": { + "doubleValue": -1 + } + }, + { + "name": "positive", + "expr": "math.ceil(1.2)", + "value": { + "doubleValue": 2 + } + }, + { + "name": "dyn_error", + "expr": "math.ceil(dyn(1))", + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + } + ] + }, + { + "name": "floor", + "test": [ + { + "name": "negative", + "expr": "math.floor(-1.2)", + "value": { + "doubleValue": -2 + } + }, + { + "name": "positive", + "expr": "math.floor(1.2)", + "value": { + "doubleValue": 1 + } + }, + { + "name": "dyn_error", + "expr": "math.floor(dyn(1))", + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + } + ] + }, + { + "name": "round", + "test": [ + { + "name": "negative_down", + "expr": "math.round(-1.6)", + "value": { + "doubleValue": -2 + } + }, + { + "name": "negative_up", + "expr": "math.round(-1.4)", + "value": { + "doubleValue": -1 + } + }, + { + "name": "negative_mid", + "expr": "math.round(-1.5)", + "value": { + "doubleValue": -2 + } + }, + { + "name": "positive_down", + "expr": "math.round(1.2)", + "value": { + "doubleValue": 1 + } + }, + { + "name": "positive_up", + "expr": "math.round(1.5)", + "value": { + "doubleValue": 2 + } + }, + { + "name": "nan", + "expr": "math.isNaN(math.round(0.0/0.0))" + }, + { + "name": "dyn_error", + "expr": "math.round(dyn(1))", + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + } + ] + }, + { + "name": "trunc", + "test": [ + { + "name": "negative", + "expr": "math.trunc(-1.2)", + "value": { + "doubleValue": -1 + } + }, + { + "name": "positive", + "expr": "math.trunc(1.2)", + "value": { + "doubleValue": 1 + } + }, + { + "name": "nan", + "expr": "math.isNaN(math.trunc(0.0/0.0))" + }, + { + "name": "dyn_error", + "expr": "math.trunc(dyn(1))", + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + } + ] + }, + { + "name": "abs", + "test": [ + { + "name": "uint", + "expr": "math.abs(1u)", + "value": { + "uint64Value": "1" + } + }, + { + "name": "positive_int", + "expr": "math.abs(1)", + "value": { + "int64Value": "1" + } + }, + { + "name": "negative_int", + "expr": "math.abs(-11)", + "value": { + "int64Value": "11" + } + }, + { + "name": "positive_double", + "expr": "math.abs(1.5)", + "value": { + "doubleValue": 1.5 + } + }, + { + "name": "negative_double", + "expr": "math.abs(-11.5)", + "value": { + "doubleValue": 11.5 + } + }, + { + "name": "int_overflow", + "expr": "math.abs(-9223372036854775808)", + "evalError": { + "errors": [ + { + "message": "overflow" + } + ] + } + } + ] + }, + { + "name": "sign", + "test": [ + { + "name": "positive_uint", + "expr": "math.sign(100u)", + "value": { + "uint64Value": "1" + } + }, + { + "name": "zero_uint", + "expr": "math.sign(0u)", + "value": { + "uint64Value": "0" + } + }, + { + "name": "positive_int", + "expr": "math.sign(100)", + "value": { + "int64Value": "1" + } + }, + { + "name": "negative_int", + "expr": "math.sign(-11)", + "value": { + "int64Value": "-1" + } + }, + { + "name": "zero_int", + "expr": "math.sign(0)", + "value": { + "int64Value": "0" + } + }, + { + "name": "positive_double", + "expr": "math.sign(100.5)", + "value": { + "doubleValue": 1 + } + }, + { + "name": "negative_double", + "expr": "math.sign(-32.0)", + "value": { + "doubleValue": -1 + } + }, + { + "name": "zero_double", + "expr": "math.sign(0.0)", + "value": { + "doubleValue": 0 + } + }, + { + "name": "dyn_error", + "expr": "math.sign(dyn(true))", + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + } + ] + }, + { + "name": "isNaN", + "test": [ + { + "name": "true", + "expr": "math.isNaN(0.0/0.0)" + }, + { + "name": "false", + "expr": "!math.isNaN(1.0/0.0)" + }, + { + "name": "dyn_error", + "expr": "math.isNaN(dyn(true))", + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + } + ] + }, + { + "name": "isInf", + "test": [ + { + "name": "true", + "expr": "math.isInf(1.0/0.0)" + }, + { + "name": "false", + "expr": "!math.isInf(0.0/0.0)" + }, + { + "name": "dyn_error", + "expr": "math.isInf(dyn(true))", + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + } + ] + }, + { + "name": "isFinite", + "test": [ + { + "name": "true", + "expr": "math.isFinite(1.0/1.5)" + }, + { + "name": "false_nan", + "expr": "!math.isFinite(0.0/0.0)" + }, + { + "name": "false_inf", + "expr": "!math.isFinite(-1.0/0.0)" + }, + { + "name": "dyn_error", + "expr": "math.isFinite(dyn(true))", + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + } + ] + }, + { + "name": "bit_and", + "test": [ + { + "name": "int_int_non_intersect", + "expr": "math.bitAnd(1, 2)", + "value": { + "int64Value": "0" + } + }, + { + "name": "int_int_intersect", + "expr": "math.bitAnd(1, 3)", + "value": { + "int64Value": "1" + } + }, + { + "name": "int_int_intersect_neg", + "expr": "math.bitAnd(1, -1)", + "value": { + "int64Value": "1" + } + }, + { + "name": "uint_uint_non_intersect", + "expr": "math.bitAnd(1u, 2u)", + "value": { + "uint64Value": "0" + } + }, + { + "name": "uint_uint_intersect", + "expr": "math.bitAnd(1u, 3u)", + "value": { + "uint64Value": "1" + } + }, + { + "name": "int_dyn_error", + "expr": "math.bitAnd(2u, dyn(''))", + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + } + ] + }, + { + "name": "bit_or", + "test": [ + { + "name": "int_int_positive", + "expr": "math.bitOr(1, 2)", + "value": { + "int64Value": "3" + } + }, + { + "name": "int_int_positive_negative", + "expr": "math.bitOr(4, -2)", + "value": { + "int64Value": "-2" + } + }, + { + "name": "uint_uint", + "expr": "math.bitOr(1u, 4u)", + "value": { + "uint64Value": "5" + } + }, + { + "name": "dyn_int_error", + "expr": "math.bitOr(dyn(1.2), 1)", + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + } + ] + }, + { + "name": "bit_xor", + "test": [ + { + "name": "int_int_positive", + "expr": "math.bitXor(1, 3)", + "value": { + "int64Value": "2" + } + }, + { + "name": "int_int_positive_negative", + "expr": "math.bitXor(4, -2)", + "value": { + "int64Value": "-6" + } + }, + { + "name": "uint_uint", + "expr": "math.bitXor(1u, 3u)", + "value": { + "uint64Value": "2" + } + }, + { + "name": "dyn_dyn_error", + "expr": "math.bitXor(dyn([]), dyn([1]))", + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + } + ] + }, + { + "name": "bit_not", + "test": [ + { + "name": "int_positive", + "expr": "math.bitNot(1)", + "value": { + "int64Value": "-2" + } + }, + { + "name": "int_negative", + "expr": "math.bitNot(-1)", + "value": { + "int64Value": "0" + } + }, + { + "name": "int_zero", + "expr": "math.bitNot(0)", + "value": { + "int64Value": "-1" + } + }, + { + "name": "uint_positive", + "expr": "math.bitNot(1u)", + "value": { + "uint64Value": "18446744073709551614" + } + }, + { + "name": "uint_zero", + "expr": "math.bitNot(0u)", + "value": { + "uint64Value": "18446744073709551615" + } + }, + { + "name": "dyn_error", + "expr": "math.bitNot(dyn(''))", + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + } + ] + }, + { + "name": "bit_shift_left", + "test": [ + { + "name": "int", + "expr": "math.bitShiftLeft(1, 2)", + "value": { + "int64Value": "4" + } + }, + { + "name": "int_large_shift", + "expr": "math.bitShiftLeft(1, 200)", + "value": { + "int64Value": "0" + } + }, + { + "name": "int_negative_large_shift", + "expr": "math.bitShiftLeft(-1, 200)", + "value": { + "int64Value": "0" + } + }, + { + "name": "uint", + "expr": "math.bitShiftLeft(1u, 2)", + "value": { + "uint64Value": "4" + } + }, + { + "name": "uint_large_shift", + "expr": "math.bitShiftLeft(1u, 200)", + "value": { + "uint64Value": "0" + } + }, + { + "name": "bad_shift", + "expr": "math.bitShiftLeft(1u, -1)", + "evalError": { + "errors": [ + { + "message": "negative offset" + } + ] + } + }, + { + "name": "dyn_int_error", + "expr": "math.bitShiftLeft(dyn(4.3), 1)", + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + } + ] + }, + { + "name": "bit_shift_right", + "test": [ + { + "name": "int", + "expr": "math.bitShiftRight(1024, 2)", + "value": { + "int64Value": "256" + } + }, + { + "name": "int_large_shift", + "expr": "math.bitShiftRight(1024, 64)", + "value": { + "int64Value": "0" + } + }, + { + "name": "int_negative", + "expr": "math.bitShiftRight(-1024, 3)", + "value": { + "int64Value": "2305843009213693824" + } + }, + { + "name": "int_negative_large_shift", + "expr": "math.bitShiftRight(-1024, 64)", + "value": { + "int64Value": "0" + } + }, + { + "name": "uint", + "expr": "math.bitShiftRight(1024u, 2)", + "value": { + "uint64Value": "256" + } + }, + { + "name": "uint_large_shift", + "expr": "math.bitShiftRight(1024u, 200)", + "value": { + "uint64Value": "0" + } + }, + { + "name": "bad_shift", + "expr": "math.bitShiftRight(1u, -1)", + "evalError": { + "errors": [ + { + "message": "negative offset" + } + ] + } + }, + { + "name": "dyn_int_error", + "expr": "math.bitShiftRight(dyn(b'123'), 1)", + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/math_ext.textproto b/packages/cel/src/lib/conformance/testdata/math_ext.textproto new file mode 100644 index 0000000..8584d92 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/math_ext.textproto @@ -0,0 +1,1263 @@ +name: "math_ext" +description: "Tests for the math extension library." +section: { + name: "greatest_int_result" + test: { + name: "unary_negative" + expr: "math.greatest(-5)" + value: { + int64_value: -5 + } + } + test: { + name: "unary_positive" + expr: "math.greatest(5)" + value: { + int64_value: 5 + } + } + test: { + name: "binary_same_args" + expr: "math.greatest(1, 1)" + value: { + int64_value: 1 + } + } + test: { + name: "binary_with_decimal" + expr: "math.greatest(1, 1.0) == 1" + } + test: { + name: "binary_with_uint" + expr: "math.greatest(1, 1u) == 1" + } + test: { + name: "binary_first_arg_greater" + expr: "math.greatest(3, -3)" + value: { + int64_value: 3 + } + } + test: { + name: "binary_second_arg_greater" + expr: "math.greatest(-7, 5)" + value: { + int64_value: 5 + } + } + test: { + name: "binary_first_arg_int_max" + expr: "math.greatest(9223372036854775807, 1)" + value: { + int64_value: 9223372036854775807 + } + } + test: { + name: "binary_second_arg_int_max" + expr: "math.greatest(1, 9223372036854775807)" + value: { + int64_value: 9223372036854775807 + } + } + test: { + name: "binary_first_arg_int_min" + expr: "math.greatest(-9223372036854775808, 1)" + value: { + int64_value: 1 + } + } + test: { + name: "binary_second_arg_int_min" + expr: "math.greatest(1, -9223372036854775808)" + value: { + int64_value: 1 + } + } + test: { + name: "ternary_same_args" + expr: "math.greatest(1, 1, 1) == 1" + } + test: { + name: "ternary_with_decimal" + expr: "math.greatest(1, 1.0, 1.0) == 1" + } + test: { + name: "ternary_with_uint" + expr: "math.greatest(1, 1u, 1u) == 1" + } + test: { + name: "ternary_first_arg_greatest" + expr: "math.greatest(10, 1, 3) == 10" + } + test: { + name: "ternary_third_arg_greatest" + expr: "math.greatest(1, 3, 10) == 10" + } + test: { + name: "ternary_with_negatives" + expr: "math.greatest(-1, -2, -3) == -1" + } + test: { + name: "ternary_int_max" + expr: "math.greatest(9223372036854775807, 1, 5) == 9223372036854775807" + } + test: { + name: "ternary_int_min" + expr: "math.greatest(-9223372036854775807, -1, -5) == -1" + } + test: { + name: "quaternary_mixed" + expr: "math.greatest(5.4, 10, 3u, -5.0, 9223372036854775807) == 9223372036854775807" + } + test: { + name: "quaternary_mixed_array" + expr: "math.greatest([5.4, 10, 3u, -5.0, 3.5]) == 10" + } + test: { + name: "quaternary_mixed_dyn_array" + expr: "math.greatest([dyn(5.4), dyn(10), dyn(3u), dyn(-5.0), dyn(3.5)]) == 10" + } +} + +section: { + name: "greatest_double_result" + test: { + name: "unary_negative" + expr: "math.greatest(-5.0)" + value: { + double_value: -5.0 + } + } + test: { + name: "unary_positive" + expr: "math.greatest(5.0)" + value: { + double_value: 5.0 + } + } + test: { + name: "binary_same_args" + expr: "math.greatest(1.0, 1.0)" + value: { + double_value: 1.0 + } + } + test: { + name: "binary_with_int" + expr: "math.greatest(1.0, 1) == 1.0" + } + test: { + name: "binary_with_uint" + expr: "math.greatest(1.0, 1u) == 1.0" + } + test: { + name: "binary_first_arg_greater" + expr: "math.greatest(5.0, -7.0)" + value: { + double_value: 5.0 + } + } + test: { + name: "binary_second_arg_greater" + expr: "math.greatest(-3.0, 3.0)" + value: { + double_value: 3.0 + } + } + test: { + name: "binary_first_arg_double_max" + expr: "math.greatest(1.797693e308, 1)" + value: { + double_value: 1.797693e308 + } + } + test: { + name: "binary_second_arg_double_max" + expr: "math.greatest(1, 1.797693e308)" + value: { + double_value: 1.797693e308 + } + } + test: { + name: "binary_first_arg_double_min" + expr: "math.greatest(-1.797693e308, 1.5)" + value: { + double_value: 1.5 + } + } + test: { + name: "binary_second_arg_double_min" + expr: "math.greatest(1.5, -1.797693e308)" + value: { + double_value: 1.5 + } + } + test: { + name: "ternary_same_args" + expr: "math.greatest(1.0, 1.0, 1.0) == 1.0" + } + test: { + name: "ternary_with_int" + expr: "math.greatest(1.0, 1, 1) == 1.0" + } + test: { + name: "ternary_with_uint" + expr: "math.greatest(1.0, 1u, 1u) == 1.0" + } + test: { + name: "ternary_first_arg_greatest" + expr: "math.greatest(10.5, 1.5, 3.5) == 10.5" + } + test: { + name: "ternary_third_arg_greatest" + expr: "math.greatest(1.5, 3.5, 10.5) == 10.5" + } + test: { + name: "ternary_with_negatives" + expr: "math.greatest(-1.5, -2.5, -3.5) == -1.5" + } + test: { + name: "ternary_double_max" + expr: "math.greatest(1.797693e308, 1, 5) == 1.797693e308" + } + test: { + name: "ternary_double_min" + expr: "math.greatest(-1.797693e308, -1, -5) == -1" + } + test: { + name: "quaternary_mixed" + expr: "math.greatest(5.4, 10, 3u, -5.0, 1.797693e308) == 1.797693e308" + } + test: { + name: "quaternary_mixed_array" + expr: "math.greatest([5.4, 10.5, 3u, -5.0, 3.5]) == 10.5" + } + test: { + name: "quaternary_mixed_dyn_array" + expr: "math.greatest([dyn(5.4), dyn(10.5), dyn(3u), dyn(-5.0), dyn(3.5)]) == 10.5" + } +} + +section: { + name: "greatest_uint_result" + test: { + name: "unary" + expr: "math.greatest(5u)" + value: { + uint64_value: 5 + } + } + test: { + name: "binary_same_args" + expr: "math.greatest(1u, 1u)" + value: { + uint64_value: 1 + } + } + test: { + name: "binary_with_decimal" + expr: "math.greatest(1u, 1.0) == 1" + } + test: { + name: "binary_with_int" + expr: "math.greatest(1u, 1) == 1u" + } + test: { + name: "binary_first_arg_greater" + expr: "math.greatest(5u, -7)" + value: { + uint64_value: 5 + } + } + test: { + name: "binary_second_arg_greater" + expr: "math.greatest(-3, 3u)" + value: { + uint64_value: 3 + } + } + test: { + name: "binary_first_arg_uint_max" + expr: "math.greatest(18446744073709551615u, 1u)" + value: { + uint64_value: 18446744073709551615 + } + } + test: { + name: "binary_second_arg_uint_max" + expr: "math.greatest(1u, 18446744073709551615u)" + value: { + uint64_value: 18446744073709551615 + } + } + test: { + name: "ternary_same_args" + expr: "math.greatest(1u, 1u, 1u) == 1u" + } + test: { + name: "ternary_with_decimal" + expr: "math.greatest(1u, 1.0, 1.0) == 1u" + } + test: { + name: "ternary_with_int" + expr: "math.greatest(1u, 1, 1) == 1u" + } + test: { + name: "ternary_first_arg_greatest" + expr: "math.greatest(10u, 1u, 3u) == 10u" + } + test: { + name: "ternary_third_arg_greatest" + expr: "math.greatest(1u, 3u, 10u) == 10u" + } + test: { + name: "ternary_int_max" + expr: "math.greatest(18446744073709551615u, 1u, 5u) == 18446744073709551615u" + } + test: { + name: "quaternary_mixed" + expr: "math.greatest(5.4, 10, 3u, -5.0, 18446744073709551615u) == 18446744073709551615u" + } + test: { + name: "quaternary_mixed_array" + expr: "math.greatest([5.4, 10u, 3u, -5.0, 3.5]) == 10u" + } + test: { + name: "quaternary_mixed_dyn_array" + expr: "math.greatest([dyn(5.4), dyn(10u), dyn(3u), dyn(-5.0), dyn(3.5)]) == 10u" + } +} + +section: { + name: "least_int_result" + test: { + name: "unary_negative" + expr: "math.least(-5)" + value: { + int64_value: -5 + } + } + test: { + name: "unary_positive" + expr: "math.least(5)" + value: { + int64_value: 5 + } + } + test: { + name: "binary_same_args" + expr: "math.least(1, 1)" + value: { + int64_value: 1 + } + } + test: { + name: "binary_with_decimal" + expr: "math.least(1, 1.0) == 1" + } + test: { + name: "binary_with_uint" + expr: "math.least(1, 1u) == 1" + } + test: { + name: "binary_first_arg_least" + expr: "math.least(-3, 3)" + value: { + int64_value: -3 + } + } + test: { + name: "binary_second_arg_least" + expr: "math.least(5, -7)" + value: { + int64_value: -7 + } + } + test: { + name: "binary_first_arg_int_max" + expr: "math.least(9223372036854775807, 1)" + value: { + int64_value: 1 + } + } + test: { + name: "binary_second_arg_int_max" + expr: "math.least(1, 9223372036854775807)" + value: { + int64_value: 1 + } + } + test: { + name: "binary_first_arg_int_min" + expr: "math.least(-9223372036854775808, 1)" + value: { + int64_value: -9223372036854775808 + } + } + test: { + name: "binary_second_arg_int_min" + expr: "math.least(1, -9223372036854775808)" + value: { + int64_value: -9223372036854775808 + } + } + test: { + name: "ternary_same_args" + expr: "math.least(1, 1, 1) == 1" + } + test: { + name: "ternary_with_decimal" + expr: "math.least(1, 1.0, 1.0) == 1" + } + test: { + name: "ternary_with_uint" + expr: "math.least(1, 1u, 1u) == 1" + } + test: { + name: "ternary_first_arg_least" + expr: "math.least(0, 1, 3) == 0" + } + test: { + name: "ternary_third_arg_least" + expr: "math.least(1, 3, 0) == 0" + } + test: { + name: "ternary_with_negatives" + expr: "math.least(-1, -2, -3) == -3" + } + test: { + name: "ternary_int_max" + expr: "math.least(9223372036854775807, 1, 5) == 1" + } + test: { + name: "ternary_int_min" + expr: "math.least(-9223372036854775808, -1, -5) == -9223372036854775808" + } + test: { + name: "quaternary_mixed" + expr: "math.least(5.4, 10, 3u, -5.0, 9223372036854775807) == -5.0" + } + test: { + name: "quaternary_mixed_array" + expr: "math.least([5.4, 10, 3u, -5.0, 3.5]) == -5.0" + } + test: { + name: "quaternary_mixed_dyn_array" + expr: "math.least([dyn(5.4), dyn(10), dyn(3u), dyn(-5.0), dyn(3.5)]) == -5.0" + } +} + +section: { + name: "least_double_result" + test: { + name: "unary_negative" + expr: "math.least(-5.5)" + value: { + double_value: -5.5 + } + } + test: { + name: "unary_positive" + expr: "math.least(5.5)" + value: { + double_value: 5.5 + } + } + test: { + name: "binary_same_args" + expr: "math.least(1.5, 1.5)" + value: { + double_value: 1.5 + } + } + test: { + name: "binary_with_int" + expr: "math.least(1.0, 1) == 1" + } + test: { + name: "binary_with_uint" + expr: "math.least(1, 1u) == 1" + } + test: { + name: "binary_first_arg_least" + expr: "math.least(-3.5, 3.5)" + value: { + double_value: -3.5 + } + } + test: { + name: "binary_second_arg_least" + expr: "math.least(5.5, -7.5)" + value: { + double_value: -7.5 + } + } + test: { + name: "binary_first_arg_double_max" + expr: "math.least(1.797693e308, 1.5)" + value: { + double_value: 1.5 + } + } + test: { + name: "binary_second_arg_double_max" + expr: "math.least(1.5, 1.797693e308)" + value: { + double_value: 1.5 + } + } + test: { + name: "binary_first_arg_double_min" + expr: "math.least(-1.797693e308, 1.5)" + value: { + double_value: -1.797693e308 + } + } + test: { + name: "binary_second_arg_double_min" + expr: "math.least(1.5, -1.797693e308)" + value: { + double_value: -1.797693e308 + } + } + test: { + name: "ternary_same_args" + expr: "math.least(1.5, 1.5, 1.5) == 1.5" + } + test: { + name: "ternary_with_int" + expr: "math.least(1.0, 1, 1) == 1.0" + } + test: { + name: "ternary_with_uint" + expr: "math.least(1.0, 1u, 1u) == 1" + } + test: { + name: "ternary_first_arg_least" + expr: "math.least(0.5, 1.5, 3.5) == 0.5" + } + test: { + name: "ternary_third_arg_least" + expr: "math.least(1.5, 3.5, 0.5) == 0.5" + } + test: { + name: "ternary_with_negatives" + expr: "math.least(-1.5, -2.5, -3.5) == -3.5" + } + test: { + name: "ternary_double_max" + expr: "math.least(1.797693e308, 1, 5) == 1" + } + test: { + name: "ternary_double_min" + expr: "math.least(-1.797693e308, -1, -5) == -1.797693e308" + } + test: { + name: "quaternary_mixed" + expr: "math.least(5.4, 10, 3u, -5.0, 1.797693e308) == -5.0" + } + test: { + name: "quaternary_mixed_array" + expr: "math.least([5.4, 10.5, 3u, -5.0, 3.5]) == -5.0" + } + test: { + name: "quaternary_mixed_dyn_array" + expr: "math.least([dyn(5.4), dyn(10.5), dyn(3u), dyn(-5.0), dyn(3.5)]) == -5.0" + } +} + +section: { + name: "least_uint_result" + test: { + name: "unary" + expr: "math.least(5u)" + value: { + uint64_value: 5 + } + } + test: { + name: "binary_same_args" + expr: "math.least(1u, 1u)" + value: { + uint64_value: 1 + } + } + test: { + name: "binary_with_decimal" + expr: "math.least(1u, 1.0) == 1u" + } + test: { + name: "binary_with_int" + expr: "math.least(1u, 1) == 1u" + } + test: { + name: "binary_first_arg_least" + expr: "math.least(1u, 3u)" + value: { + uint64_value: 1 + } + } + test: { + name: "binary_second_arg_least" + expr: "math.least(5u, 2u)" + value: { + uint64_value: 2 + } + } + test: { + name: "binary_first_arg_uint_max" + expr: "math.least(18446744073709551615u, 1u)" + value: { + uint64_value: 1 + } + } + test: { + name: "binary_second_arg_uint_max" + expr: "math.least(1u, 18446744073709551615u)" + value: { + uint64_value: 1 + } + } + test: { + name: "ternary_same_args" + expr: "math.least(1u, 1u, 1u) == 1u" + } + test: { + name: "ternary_with_decimal" + expr: "math.least(1u, 1.0, 1.0) == 1u" + } + test: { + name: "ternary_with_int" + expr: "math.least(1u, 1, 1) == 1u" + } + test: { + name: "ternary_first_arg_least" + expr: "math.least(1u, 10u, 3u) == 1u" + } + test: { + name: "ternary_third_arg_least" + expr: "math.least(10u, 3u, 1u) == 1u" + } + test: { + name: "ternary_uint_max" + expr: "math.least(18446744073709551615u, 1u, 5u) == 1u" + } + test: { + name: "quaternary_mixed" + expr: "math.least(5.4, 10, 3u, 1u, 18446744073709551615u) == 1u" + } + test: { + name: "quaternary_mixed_array" + expr: "math.least([5.4, 10u, 3u, 1u, 3.5]) == 1u" + } + test: { + name: "quaternary_mixed_dyn_array" + expr: "math.least([dyn(5.4), dyn(10u), dyn(3u), dyn(1u), dyn(3.5)]) == 1u" + } +} + +section: { + name: "ceil" + test: { + name: "negative" + expr: "math.ceil(-1.2)" + value: { + double_value: -1.0 + } + } + test: { + name: "positive" + expr: "math.ceil(1.2)" + value: { + double_value: 2.0 + } + } + test: { + name: "dyn_error" + expr: "math.ceil(dyn(1))" + eval_error: { + errors: { + message: "no such overload" + } + } + } +} + +section: { + name: "floor" + test: { + name: "negative" + expr: "math.floor(-1.2)" + value: { + double_value: -2.0 + } + } + test: { + name: "positive" + expr: "math.floor(1.2)" + value: { + double_value: 1.0 + } + } + test: { + name: "dyn_error" + expr: "math.floor(dyn(1))" + eval_error: { + errors: { + message: "no such overload" + } + } + } +} + +section: { + name: "round" + test: { + name: "negative_down" + expr: "math.round(-1.6)" + value: { + double_value: -2.0 + } + } + test: { + name: "negative_up" + expr: "math.round(-1.4)" + value: { + double_value: -1.0 + } + } + test: { + name: "negative_mid" + expr: "math.round(-1.5)" + value: { + double_value: -2.0 + } + } + test: { + name: "positive_down" + expr: "math.round(1.2)" + value: { + double_value: 1.0 + } + } + test: { + name: "positive_up" + expr: "math.round(1.5)" + value: { + double_value: 2.0 + } + } + test: { + name: "nan" + expr: "math.isNaN(math.round(0.0/0.0))" + } + test: { + name: "dyn_error" + expr: "math.round(dyn(1))" + eval_error: { + errors: { + message: "no such overload" + } + } + } +} + +section: { + name: "trunc" + test: { + name: "negative" + expr: "math.trunc(-1.2)" + value: { + double_value: -1.0 + } + } + test: { + name: "positive" + expr: "math.trunc(1.2)" + value: { + double_value: 1.0 + } + } + test: { + name: "nan" + expr: "math.isNaN(math.trunc(0.0/0.0))" + } + test: { + name: "dyn_error" + expr: "math.trunc(dyn(1))" + eval_error: { + errors: { + message: "no such overload" + } + } + } +} + +section: { + name: "abs" + test: { + name: "uint" + expr: "math.abs(1u)" + value: { + uint64_value: 1 + } + } + test: { + name: "positive_int" + expr: "math.abs(1)" + value: { + int64_value: 1 + } + } + test: { + name: "negative_int" + expr: "math.abs(-11)" + value: { + int64_value: 11 + } + } + test: { + name: "positive_double" + expr: "math.abs(1.5)" + value: { + double_value: 1.5 + } + } + test: { + name: "negative_double" + expr: "math.abs(-11.5)" + value: { + double_value: 11.5 + } + } + test: { + name: "int_overflow" + expr: "math.abs(-9223372036854775808)" + eval_error: { + errors: { + message: "overflow" + } + } + } +} + +section: { + name: "sign" + test: { + name: "positive_uint" + expr: "math.sign(100u)" + value: { + uint64_value: 1 + } + } + test: { + name: "zero_uint" + expr: "math.sign(0u)" + value: { + uint64_value: 0 + } + } + test: { + name: "positive_int" + expr: "math.sign(100)" + value: { + int64_value: 1 + } + } + test: { + name: "negative_int" + expr: "math.sign(-11)" + value: { + int64_value: -1 + } + } + test: { + name: "zero_int" + expr: "math.sign(0)" + value: { + int64_value: 0 + } + } + test: { + name: "positive_double" + expr: "math.sign(100.5)" + value: { + double_value: 1.0 + } + } + test: { + name: "negative_double" + expr: "math.sign(-32.0)" + value: { + double_value: -1.0 + } + } + test: { + name: "zero_double" + expr: "math.sign(0.0)" + value: { + double_value: 0.0 + } + } + test: { + name: "dyn_error" + expr: "math.sign(dyn(true))" + eval_error: { + errors: { + message: "no such overload" + } + } + } +} + +section: { + name: "isNaN" + test: { + name: "true" + expr: "math.isNaN(0.0/0.0)" + } + test: { + name: "false" + expr: "!math.isNaN(1.0/0.0)" + } + test: { + name: "dyn_error" + expr: "math.isNaN(dyn(true))" + eval_error: { + errors: { + message: "no such overload" + } + } + } +} + +section: { + name: "isInf" + test: { + name: "true" + expr: "math.isInf(1.0/0.0)" + } + test: { + name: "false" + expr: "!math.isInf(0.0/0.0)" + } + test: { + name: "dyn_error" + expr: "math.isInf(dyn(true))" + eval_error: { + errors: { + message: "no such overload" + } + } + } +} + +section: { + name: "isFinite" + test: { + name: "true" + expr: "math.isFinite(1.0/1.5)" + } + test: { + name: "false_nan" + expr: "!math.isFinite(0.0/0.0)" + } + test: { + name: "false_inf" + expr: "!math.isFinite(-1.0/0.0)" + } + test: { + name: "dyn_error" + expr: "math.isFinite(dyn(true))" + eval_error: { + errors: { + message: "no such overload" + } + } + } +} + +section: { + name: "bit_and" + test: { + name: "int_int_non_intersect" + expr: "math.bitAnd(1, 2)" + value: { + int64_value: 0 + } + } + test: { + name: "int_int_intersect" + expr: "math.bitAnd(1, 3)" + value: { + int64_value: 1 + } + } + test: { + name: "int_int_intersect_neg" + expr: "math.bitAnd(1, -1)" + value: { + int64_value: 1 + } + } + test: { + name: "uint_uint_non_intersect" + expr: "math.bitAnd(1u, 2u)" + value: { + uint64_value: 0 + } + } + test: { + name: "uint_uint_intersect" + expr: "math.bitAnd(1u, 3u)" + value: { + uint64_value: 1 + } + } + test: { + name: "int_dyn_error" + expr: "math.bitAnd(2u, dyn(''))" + eval_error: { + errors: { + message: "no such overload" + } + } + } +} + +section: { + name: "bit_or" + test: { + name: "int_int_positive" + expr: "math.bitOr(1, 2)" + value: { + int64_value: 3 + } + } + test: { + name: "int_int_positive_negative" + expr: "math.bitOr(4, -2)" + value: { + int64_value: -2 + } + } + test: { + name: "uint_uint" + expr: "math.bitOr(1u, 4u)" + value: { + uint64_value: 5 + } + } + test: { + name: "dyn_int_error" + expr: "math.bitOr(dyn(1.2), 1)" + eval_error: { + errors: { + message: "no such overload" + } + } + } +} + +section: { + name: "bit_xor" + test: { + name: "int_int_positive" + expr: "math.bitXor(1, 3)" + value: { + int64_value: 2 + } + } + test: { + name: "int_int_positive_negative" + expr: "math.bitXor(4, -2)" + value: { + int64_value: -6 + } + } + test: { + name: "uint_uint" + expr: "math.bitXor(1u, 3u)" + value: { + uint64_value: 2 + } + } + test: { + name: "dyn_dyn_error" + expr: "math.bitXor(dyn([]), dyn([1]))" + eval_error: { + errors: { + message: "no such overload" + } + } + } +} + +section: { + name: "bit_not" + test: { + name: "int_positive" + expr: "math.bitNot(1)" + value: { + int64_value: -2 + } + } + test: { + name: "int_negative" + expr: "math.bitNot(-1)" + value: { + int64_value: 0 + } + } + test: { + name: "int_zero" + expr: "math.bitNot(0)" + value: { + int64_value: -1 + } + } + test: { + name: "uint_positive" + expr: "math.bitNot(1u)" + value: { + uint64_value: 18446744073709551614 + } + } + test: { + name: "uint_zero" + expr: "math.bitNot(0u)" + value: { + uint64_value: 18446744073709551615 + } + } + test: { + name: "dyn_error" + expr: "math.bitNot(dyn(''))" + eval_error: { + errors: { + message: "no such overload" + } + } + } +} + +section: { + name: "bit_shift_left" + test: { + name: "int", + expr: "math.bitShiftLeft(1, 2)" + value: { + int64_value: 4 + } + } + test: { + name: "int_large_shift", + expr: "math.bitShiftLeft(1, 200)" + value: { + int64_value: 0 + } + } + test: { + name: "int_negative_large_shift", + expr: "math.bitShiftLeft(-1, 200)" + value: { + int64_value: 0 + } + } + test: { + name: "uint", + expr: "math.bitShiftLeft(1u, 2)" + value: { + uint64_value: 4 + } + } + test: { + name: "uint_large_shift", + expr: "math.bitShiftLeft(1u, 200)" + value: { + uint64_value: 0 + } + } + test: { + name: "bad_shift", + expr: "math.bitShiftLeft(1u, -1)" + eval_error: { + errors: { + message: "negative offset" + } + } + } + test: { + name: "dyn_int_error" + expr: "math.bitShiftLeft(dyn(4.3), 1)" + eval_error: { + errors: { + message: "no such overload" + } + } + } +} + +section: { + name: "bit_shift_right" + test: { + name: "int", + expr: "math.bitShiftRight(1024, 2)" + value: { + int64_value: 256 + } + } + test: { + name: "int_large_shift", + expr: "math.bitShiftRight(1024, 64)" + value: { + int64_value: 0 + } + } + test: { + name: "int_negative", + expr: "math.bitShiftRight(-1024, 3)" + value: { + int64_value: 2305843009213693824 + } + } + test: { + name: "int_negative_large_shift", + expr: "math.bitShiftRight(-1024, 64)" + value: { + int64_value: 0 + } + } + test: { + name: "uint", + expr: "math.bitShiftRight(1024u, 2)" + value: { + uint64_value: 256 + } + } + test: { + name: "uint_large_shift", + expr: "math.bitShiftRight(1024u, 200)" + value: { + uint64_value: 0 + } + } + test: { + name: "bad_shift", + expr: "math.bitShiftRight(1u, -1)" + eval_error: { + errors: { + message: "negative offset" + } + } + } + test: { + name: "dyn_int_error" + expr: "math.bitShiftRight(dyn(b'123'), 1)" + eval_error: { + errors: { + message: "no such overload" + } + } + } +} diff --git a/packages/cel/src/lib/conformance/testdata/namespace.json b/packages/cel/src/lib/conformance/testdata/namespace.json new file mode 100755 index 0000000..3833504 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/namespace.json @@ -0,0 +1,119 @@ +{ + "name": "namespace", + "description": "Uses of qualified identifiers and namespaces.", + "section": [ + { + "name": "qualified", + "description": "Qualified variable lookups.", + "test": [ + { + "name": "self_eval_qualified_lookup", + "expr": "x.y", + "typeEnv": [ + { + "name": "x.y", + "ident": { + "type": { + "primitive": "BOOL" + } + } + } + ], + "bindings": { + "x.y": { + "value": { + "boolValue": true + } + } + }, + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "namespace", + "description": "Namespaced identifiers.", + "test": [ + { + "name": "self_eval_container_lookup", + "expr": "y", + "typeEnv": [ + { + "name": "x.y", + "ident": { + "type": { + "primitive": "BOOL" + } + } + }, + { + "name": "y", + "ident": { + "type": { + "primitive": "STRING" + } + } + } + ], + "container": "x", + "bindings": { + "x.y": { + "value": { + "boolValue": true + } + }, + "y": { + "value": { + "stringValue": "false" + } + } + }, + "value": { + "boolValue": true + } + }, + { + "name": "self_eval_container_lookup_unchecked", + "expr": "y", + "disableCheck": true, + "typeEnv": [ + { + "name": "x.y", + "ident": { + "type": { + "primitive": "BOOL" + } + } + }, + { + "name": "y", + "ident": { + "type": { + "primitive": "BOOL" + } + } + } + ], + "container": "x", + "bindings": { + "x.y": { + "value": { + "boolValue": true + } + }, + "y": { + "value": { + "boolValue": false + } + } + }, + "value": { + "boolValue": true + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/namespace.textproto b/packages/cel/src/lib/conformance/testdata/namespace.textproto new file mode 100644 index 0000000..df439c6 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/namespace.textproto @@ -0,0 +1,68 @@ +name: "namespace" +description: "Uses of qualified identifiers and namespaces." +section { + name: "qualified" + description: "Qualified variable lookups." + test { + name: "self_eval_qualified_lookup" + expr: "x.y" + value: { bool_value: true } + type_env: { + name: "x.y", + ident: { type: { primitive: BOOL } } + } + bindings: { + key: "x.y" + value: { value: { bool_value: true } } + } + } +} +section { + name: "namespace" + description: "Namespaced identifiers." + test { + name: "self_eval_container_lookup" + expr: "y" + container: "x" + type_env: { + name: "x.y", + ident: { type: { primitive: BOOL } } + } + type_env: { + name: "y", + ident: { type: { primitive: STRING } } + } + bindings: { + key: "x.y" + value: { value: { bool_value: true } } + } + bindings: { + key: "y" + value: { value: { string_value: "false" } } + } + value: { bool_value: true } + } + test { + name: "self_eval_container_lookup_unchecked" + expr: "y" + container: "x" + type_env: { + name: "x.y", + ident: { type: { primitive: BOOL } } + } + type_env: { + name: "y", + ident: { type: { primitive: BOOL } } + } + bindings: { + key: "x.y" + value: { value: { bool_value: true } } + } + bindings: { + key: "y" + value: { value: { bool_value: false } } + } + disable_check: true ## ensure unchecked ASTs resolve the same as checked ASTs + value: { bool_value: true } + } +} diff --git a/packages/cel/src/lib/conformance/testdata/optionals.json b/packages/cel/src/lib/conformance/testdata/optionals.json new file mode 100755 index 0000000..e8418b1 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/optionals.json @@ -0,0 +1,585 @@ +{ + "name": "optionals", + "description": "Tests for optionals.", + "section": [ + { + "name": "optionals", + "test": [ + { + "name": "null", + "expr": "optional.of(null).hasValue()", + "value": { + "boolValue": true + } + }, + { + "name": "null_non_zero_value", + "expr": "optional.ofNonZeroValue(null).hasValue()", + "value": { + "boolValue": false + } + }, + { + "name": "none_or_none_or_value", + "expr": "optional.none().or(optional.none()).orValue(42)", + "value": { + "int64Value": "42" + } + }, + { + "name": "none_optMap_hasValue", + "expr": "optional.none().optMap(y, y + 1).hasValue()", + "value": { + "boolValue": false + } + }, + { + "name": "empty_map_optFlatMap_hasValue", + "expr": "{}.?key.optFlatMap(k, k.?subkey).hasValue()", + "value": { + "boolValue": false + } + }, + { + "name": "map_empty_submap_optFlatMap_hasValue", + "expr": "{'key': {}}.?key.optFlatMap(k, k.?subkey).hasValue()", + "value": { + "boolValue": false + } + }, + { + "name": "map_null_entry_hasValue", + "expr": "{'null_key': dyn(null)}.?null_key.hasValue()", + "value": { + "boolValue": true + } + }, + { + "name": "map_null_entry_no_such_key", + "expr": "{'null_key': dyn(null)}.?null_key.invalid.hasValue()", + "evalError": { + "errors": [ + { + "message": "no such key" + } + ] + } + }, + { + "name": "map_absent_key_absent_field_none", + "expr": "{true: dyn(0)}[?false].absent.hasValue()", + "value": { + "boolValue": false + } + }, + { + "name": "map_present_key_invalid_field", + "expr": "{true: dyn(0)}[?true].absent.hasValue()", + "evalError": { + "errors": [ + { + "message": "no such key" + } + ] + } + }, + { + "name": "map_undefined_entry_hasValue", + "expr": "{}.?null_key.invalid.hasValue()", + "value": { + "boolValue": false + } + }, + { + "name": "map_submap_subkey_optFlatMap_value", + "expr": "{'key': {'subkey': 'subvalue'}}.?key.optFlatMap(k, k.?subkey).value()", + "value": { + "stringValue": "subvalue" + } + }, + { + "name": "map_submap_optFlatMap_value", + "expr": "{'key': {'subkey': ''}}.?key.optFlatMap(k, k.?subkey).value()", + "value": { + "stringValue": "" + } + }, + { + "name": "map_optindex_optFlatMap_optional_ofNonZeroValue_hasValue", + "expr": "{'key': {'subkey': ''}}.?key.optFlatMap(k, optional.ofNonZeroValue(k.subkey)).hasValue()", + "value": { + "boolValue": false + } + }, + { + "name": "optional_of_optMap_value", + "expr": "optional.of(42).optMap(y, y + 1).value()", + "value": { + "int64Value": "43" + } + }, + { + "name": "optional_ofNonZeroValue_or_optional_value", + "expr": "optional.ofNonZeroValue(42).or(optional.of(20)).value() == 42", + "value": { + "boolValue": true + } + }, + { + "name": "ternary_optional_hasValue", + "expr": "(has({}.x) ? optional.of({}.x) : optional.none()).hasValue()", + "value": { + "boolValue": false + } + }, + { + "name": "map_optindex_hasValue", + "expr": "{}.?x.hasValue()", + "value": { + "boolValue": false + } + }, + { + "name": "has_map_optindex", + "expr": "has({}.?x.y)", + "value": { + "boolValue": false + } + }, + { + "name": "has_map_optindex_field", + "expr": "has({'x': {'y': 'z'}}.?x.y)", + "value": { + "boolValue": true + } + }, + { + "name": "type", + "expr": "type(optional.none()) == optional_type", + "value": { + "boolValue": true + } + }, + { + "name": "optional_chaining_1", + "expr": "optional.ofNonZeroValue('').or(optional.of({'c': {'dashed-index': 'goodbye'}}.c['dashed-index'])).orValue('default value')", + "value": { + "stringValue": "goodbye" + } + }, + { + "name": "optional_chaining_2", + "expr": "{'c': {'dashed-index': 'goodbye'}}.c[?'dashed-index'].orValue('default value')", + "value": { + "stringValue": "goodbye" + } + }, + { + "name": "optional_chaining_3", + "expr": "{'c': {}}.c[?'missing-index'].orValue('default value')", + "value": { + "stringValue": "default value" + } + }, + { + "name": "optional_chaining_4", + "expr": "optional.of({'c': {'index': 'goodbye'}}).c.index.orValue('default value')", + "value": { + "stringValue": "goodbye" + } + }, + { + "name": "optional_chaining_5", + "expr": "optional.of({'c': {}}).c.missing.or(optional.none()[0]).orValue('default value')", + "value": { + "stringValue": "default value" + } + }, + { + "name": "optional_chaining_6", + "expr": "optional.of({'c': {}}).c.missing.or(optional.of(['list-value'])[0]).orValue('default value')", + "value": { + "stringValue": "list-value" + } + }, + { + "name": "optional_chaining_7", + "expr": "optional.of({'c': {'index': 'goodbye'}}).c['index'].orValue('default value')", + "value": { + "stringValue": "goodbye" + } + }, + { + "name": "optional_chaining_8", + "expr": "optional.of({'c': {}}).c['missing'].orValue('default value')", + "value": { + "stringValue": "default value" + } + }, + { + "name": "optional_chaining_9", + "expr": "has(optional.of({'c': {'entry': 'hello world'}}).c) && !has(optional.of({'c': {'entry': 'hello world'}}).c.missing)", + "value": { + "boolValue": true + } + }, + { + "name": "optional_chaining_10", + "expr": "optional.ofNonZeroValue({'c': {'dashed-index': 'goodbye'}}.a.z).orValue({'c': {'dashed-index': 'goodbye'}}.c['dashed-index'])", + "evalError": { + "errors": [ + { + "message": "no such key" + } + ] + } + }, + { + "name": "optional_chaining_11", + "expr": "{'c': {'dashed-index': 'goodbye'}}.?c.missing.or({'c': {'dashed-index': 'goodbye'}}.?c['dashed-index']).orValue('').size()", + "value": { + "int64Value": "7" + } + }, + { + "name": "optional_chaining_12", + "expr": "{?'nested_map': optional.ofNonZeroValue({?'map': {'c': {'dashed-index': 'goodbye'}}.?c})}", + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "nested_map" + }, + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "map" + }, + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "dashed-index" + }, + "value": { + "stringValue": "goodbye" + } + } + ] + } + } + } + ] + } + } + } + ] + } + } + }, + { + "name": "optional_chaining_13", + "expr": "{?'nested_map': optional.ofNonZeroValue({?'map': {}.?c}), 'singleton': true}", + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "singleton" + }, + "value": { + "boolValue": true + } + } + ] + } + } + }, + { + "name": "optional_chaining_14", + "expr": "[?{}.?c, ?optional.of(42), ?optional.none()]", + "value": { + "listValue": { + "values": [ + { + "int64Value": "42" + } + ] + } + } + }, + { + "name": "optional_chaining_15", + "expr": "[?optional.ofNonZeroValue({'c': []}.?c.orValue(dyn({})))]", + "value": { + "listValue": {} + } + }, + { + "name": "optional_chaining_16", + "expr": "optional.ofNonZeroValue({?'nested_map': optional.ofNonZeroValue({?'map': optional.of({}).?c})}).hasValue()", + "value": { + "boolValue": false + } + }, + { + "name": "has_optional_ofNonZeroValue_struct_optional_ofNonZeroValue_map_optindex_field", + "expr": "has(TestAllTypes{?single_double_wrapper: optional.ofNonZeroValue(0.0)}.single_double_wrapper)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": false + } + }, + { + "name": "optional_ofNonZeroValue_struct_optional_ofNonZeroValue_map_optindex_field", + "expr": "optional.ofNonZeroValue(TestAllTypes{?single_double_wrapper: optional.ofNonZeroValue(0.0)}).hasValue()", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": false + } + }, + { + "name": "struct_map_optindex_field", + "expr": "TestAllTypes{?map_string_string: {'nested': {}}[?'nested']}.map_string_string", + "container": "google.api.expr.test.v1.proto2", + "value": { + "mapValue": {} + } + }, + { + "name": "struct_optional_ofNonZeroValue_map_optindex_field", + "expr": "TestAllTypes{?map_string_string: optional.ofNonZeroValue({'nested': {}}[?'nested'].orValue({}))}.map_string_string", + "container": "google.api.expr.test.v1.proto2", + "value": { + "mapValue": {} + } + }, + { + "name": "struct_map_optindex_field_nested", + "expr": "TestAllTypes{?map_string_string: {'nested': {'hello': 'world'}}[?'nested']}.map_string_string", + "container": "google.api.expr.test.v1.proto2", + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "hello" + }, + "value": { + "stringValue": "world" + } + } + ] + } + } + }, + { + "name": "struct_list_optindex_field", + "expr": "TestAllTypes{repeated_string: ['greetings', ?{'nested': {'hello': 'world'}}.nested.?hello]}.repeated_string", + "container": "google.api.expr.test.v1.proto2", + "value": { + "listValue": { + "values": [ + { + "stringValue": "greetings" + }, + { + "stringValue": "world" + } + ] + } + } + }, + { + "name": "optional_empty_map_optindex_hasValue", + "expr": "optional.of({}).?c.hasValue()", + "value": { + "boolValue": false + } + }, + { + "name": "empty_struct_optindex_hasValue", + "expr": "TestAllTypes{}.?repeated_string.hasValue()", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": false + } + }, + { + "name": "optional_empty_struct_optindex_hasValue", + "expr": "optional.of(TestAllTypes{}).?repeated_string.hasValue()", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": false + } + }, + { + "name": "optional_none_optselect_hasValue", + "expr": "optional.none().?repeated_string.hasValue()", + "value": { + "boolValue": false + } + }, + { + "name": "struct_optindex_value", + "expr": "TestAllTypes{repeated_string: ['foo']}.?repeated_string.value()", + "container": "google.api.expr.test.v1.proto2", + "value": { + "listValue": { + "values": [ + { + "stringValue": "foo" + } + ] + } + } + }, + { + "name": "optional_struct_optindex_value", + "expr": "optional.of(TestAllTypes{repeated_string: ['foo']}).?repeated_string.value()", + "container": "google.api.expr.test.v1.proto2", + "value": { + "listValue": { + "values": [ + { + "stringValue": "foo" + } + ] + } + } + }, + { + "name": "optional_struct_optindex_index_value", + "expr": "optional.of(TestAllTypes{repeated_string: ['foo']}).?repeated_string[0].value()", + "container": "google.api.expr.test.v1.proto2", + "value": { + "stringValue": "foo" + } + }, + { + "name": "empty_list_optindex_hasValue", + "expr": "[][?0].hasValue()", + "value": { + "boolValue": false + } + }, + { + "name": "optional_empty_list_optindex_hasValue", + "expr": "optional.of([])[?0].hasValue()", + "value": { + "boolValue": false + } + }, + { + "name": "optional_none_optindex_hasValue", + "expr": "optional.none()[?0].hasValue()", + "value": { + "boolValue": false + } + }, + { + "name": "list_optindex_value", + "expr": "['foo'][?0].value()", + "value": { + "stringValue": "foo" + } + }, + { + "name": "optional_list_optindex_value", + "expr": "optional.of(['foo'])[?0].value()", + "value": { + "stringValue": "foo" + } + }, + { + "name": "map_key_mixed_type_optindex_value", + "expr": "{true: 1, 2: 2, 5u: 3}[?true].value()", + "value": { + "int64Value": "1" + } + }, + { + "name": "map_key_mixed_numbers_double_key_optindex_value", + "expr": "{1u: 1.0, 2: 2.0, 3u: 3.0}[?3.0].value()", + "value": { + "doubleValue": 3 + } + }, + { + "name": "map_key_mixed_numbers_uint_key_optindex_value", + "expr": "{1u: 1.0, 2: 2.0, 3u: 3.0}[?2u].value()", + "value": { + "doubleValue": 2 + } + }, + { + "name": "map_key_mixed_numbers_int_key_optindex_value", + "expr": "{1u: 1.0, 2: 2.0, 3u: 3.0}[?1].value()", + "value": { + "doubleValue": 1 + } + }, + { + "name": "optional_eq_none_none", + "expr": "optional.none() == optional.none()", + "value": { + "boolValue": true + } + }, + { + "name": "optional_eq_none_int", + "expr": "optional.none() == optional.of(1)", + "value": { + "boolValue": false + } + }, + { + "name": "optional_eq_int_none", + "expr": "optional.of(1) == optional.none()", + "value": { + "boolValue": false + } + }, + { + "name": "optional_eq_int_int", + "expr": "optional.of(1) == optional.of(1)", + "value": { + "boolValue": true + } + }, + { + "name": "optional_ne_none_none", + "expr": "optional.none() != optional.none()", + "value": { + "boolValue": false + } + }, + { + "name": "optional_ne_none_int", + "expr": "optional.none() != optional.of(1)", + "value": { + "boolValue": true + } + }, + { + "name": "optional_ne_int_none", + "expr": "optional.of(1) != optional.none()", + "value": { + "boolValue": true + } + }, + { + "name": "optional_ne_int_int", + "expr": "optional.of(1) != optional.of(1)", + "value": { + "boolValue": false + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/optionals.textproto b/packages/cel/src/lib/conformance/testdata/optionals.textproto new file mode 100644 index 0000000..5e532d7 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/optionals.textproto @@ -0,0 +1,433 @@ +name: "optionals" +description: "Tests for optionals." +section: { + name: "optionals" + test { + name: "null" + expr: "optional.of(null).hasValue()" + value: { bool_value: true } + } + test { + name: "null_non_zero_value" + expr: "optional.ofNonZeroValue(null).hasValue()" + value: { bool_value: false } + } + test { + name: "none_or_none_or_value" + expr: "optional.none().or(optional.none()).orValue(42)" + value: { int64_value: 42 } + } + test { + name: "none_optMap_hasValue" + expr: "optional.none().optMap(y, y + 1).hasValue()" + value: { bool_value: false } + } + test { + name: "empty_map_optFlatMap_hasValue" + expr: "{}.?key.optFlatMap(k, k.?subkey).hasValue()" + value: { bool_value: false } + } + test { + name: "map_empty_submap_optFlatMap_hasValue" + expr: "{'key': {}}.?key.optFlatMap(k, k.?subkey).hasValue()" + value: { bool_value: false } + } + test { + name: "map_null_entry_hasValue" + expr: "{'null_key': dyn(null)}.?null_key.hasValue()" + value: { bool_value: true } + } + test { + name: "map_null_entry_no_such_key" + expr: "{'null_key': dyn(null)}.?null_key.invalid.hasValue()" + eval_error: { + errors: { message: "no such key" } + } + } + test { + name: "map_absent_key_absent_field_none" + expr: "{true: dyn(0)}[?false].absent.hasValue()" + value: { bool_value: false } + } + test { + name: "map_present_key_invalid_field" + expr: "{true: dyn(0)}[?true].absent.hasValue()" + eval_error: { + errors: { message: "no such key" } + } + } + test { + name: "map_undefined_entry_hasValue" + expr: "{}.?null_key.invalid.hasValue()" + value: { bool_value: false } + } + test { + name: "map_submap_subkey_optFlatMap_value" + expr: "{'key': {'subkey': 'subvalue'}}.?key.optFlatMap(k, k.?subkey).value()" + value: { string_value: "subvalue" } + } + test { + name: "map_submap_optFlatMap_value" + expr: "{'key': {'subkey': ''}}.?key.optFlatMap(k, k.?subkey).value()" + value: { string_value: "" } + } + test { + name: "map_optindex_optFlatMap_optional_ofNonZeroValue_hasValue" + expr: "{'key': {'subkey': ''}}.?key.optFlatMap(k, optional.ofNonZeroValue(k.subkey)).hasValue()" + value: { bool_value: false } + } + test { + name: "optional_of_optMap_value" + expr: "optional.of(42).optMap(y, y + 1).value()" + value: { int64_value: 43 } + } + test { + name: "optional_ofNonZeroValue_or_optional_value" + expr: "optional.ofNonZeroValue(42).or(optional.of(20)).value() == 42" + value: { bool_value: true } + } + test { + name: "ternary_optional_hasValue" + expr: "(has({}.x) ? optional.of({}.x) : optional.none()).hasValue()" + value: { bool_value: false } + } + test { + name: "map_optindex_hasValue" + expr: "{}.?x.hasValue()" + value: { bool_value: false } + } + test { + name: "has_map_optindex" + expr: "has({}.?x.y)" + value: { bool_value: false } + } + test { + name: "has_map_optindex_field" + expr: "has({'x': {'y': 'z'}}.?x.y)" + value: { bool_value: true } + } + test { + name: "type" + expr: "type(optional.none()) == optional_type" + value: { bool_value: true } + } + test { + name: "optional_chaining_1" + expr: "optional.ofNonZeroValue('').or(optional.of({'c': {'dashed-index': 'goodbye'}}.c['dashed-index'])).orValue('default value')" + value: { string_value: "goodbye" } + } + test { + name: "optional_chaining_2" + expr: "{'c': {'dashed-index': 'goodbye'}}.c[?'dashed-index'].orValue('default value')" + value: { string_value: "goodbye" } + } + test { + name: "optional_chaining_3" + expr: "{'c': {}}.c[?'missing-index'].orValue('default value')" + value: { string_value: "default value" } + } + test { + name: "optional_chaining_4" + expr: "optional.of({'c': {'index': 'goodbye'}}).c.index.orValue('default value')" + value: { string_value: "goodbye" } + } + test { + name: "optional_chaining_5" + expr: "optional.of({'c': {}}).c.missing.or(optional.none()[0]).orValue('default value')" + value: { string_value: "default value" } + } + test { + name: "optional_chaining_6" + expr: "optional.of({'c': {}}).c.missing.or(optional.of(['list-value'])[0]).orValue('default value')" + value: { string_value: "list-value" } + } + test { + name: "optional_chaining_7" + expr: "optional.of({'c': {'index': 'goodbye'}}).c['index'].orValue('default value')" + value: { string_value: "goodbye" } + } + test { + name: "optional_chaining_8" + expr: "optional.of({'c': {}}).c['missing'].orValue('default value')" + value: { string_value: "default value" } + } + test { + name: "optional_chaining_9" + expr: "has(optional.of({'c': {'entry': 'hello world'}}).c) && !has(optional.of({'c': {'entry': 'hello world'}}).c.missing)" + value: { bool_value: true } + } + test { + name: "optional_chaining_10" + expr: "optional.ofNonZeroValue({'c': {'dashed-index': 'goodbye'}}.a.z).orValue({'c': {'dashed-index': 'goodbye'}}.c['dashed-index'])" + eval_error: { + errors: { message: "no such key" } + } + } + test { + name: "optional_chaining_11" + expr: "{'c': {'dashed-index': 'goodbye'}}.?c.missing.or({'c': {'dashed-index': 'goodbye'}}.?c['dashed-index']).orValue('').size()" + value: { int64_value: 7 } + } + test { + name: "optional_chaining_12" + expr: "{?'nested_map': optional.ofNonZeroValue({?'map': {'c': {'dashed-index': 'goodbye'}}.?c})}" + value: { + map_value: { + entries { + key: { string_value: "nested_map" } + value: { + map_value: { + entries { + key: { string_value: "map" } + value: { + map_value: { + entries { + key: { string_value: "dashed-index" } + value: { string_value: "goodbye" } + } + } + } + } + } + } + } + } + } + } + test { + name: "optional_chaining_13" + expr: "{?'nested_map': optional.ofNonZeroValue({?'map': {}.?c}), 'singleton': true}" + value: { + map_value: { + entries { + key: { string_value: "singleton" } + value: { bool_value: true } + } + } + } + } + test { + name: "optional_chaining_14" + expr: "[?{}.?c, ?optional.of(42), ?optional.none()]" + value: { list_value: { values: { int64_value: 42 } } } + } + test { + name: "optional_chaining_15" + expr: "[?optional.ofNonZeroValue({'c': []}.?c.orValue(dyn({})))]" + value: { list_value: {} } + } + test { + name: "optional_chaining_16" + expr: "optional.ofNonZeroValue({?'nested_map': optional.ofNonZeroValue({?'map': optional.of({}).?c})}).hasValue()" + value: { bool_value: false } + } + test { + name: "has_optional_ofNonZeroValue_struct_optional_ofNonZeroValue_map_optindex_field" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestAllTypes{?single_double_wrapper: optional.ofNonZeroValue(0.0)}.single_double_wrapper)" + value: { bool_value: false } + } + test { + name: "optional_ofNonZeroValue_struct_optional_ofNonZeroValue_map_optindex_field" + container: "google.api.expr.test.v1.proto2" + expr: "optional.ofNonZeroValue(TestAllTypes{?single_double_wrapper: optional.ofNonZeroValue(0.0)}).hasValue()" + value: { bool_value: false } + } + test { + name: "struct_map_optindex_field" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{?map_string_string: {'nested': {}}[?'nested']}.map_string_string" + value: { map_value: {} } + } + test { + name: "struct_optional_ofNonZeroValue_map_optindex_field" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{?map_string_string: optional.ofNonZeroValue({'nested': {}}[?'nested'].orValue({}))}.map_string_string" + value: { map_value: {} } + } + test { + name: "struct_map_optindex_field_nested" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{?map_string_string: {'nested': {'hello': 'world'}}[?'nested']}.map_string_string" + value: { + map_value: { + entries { + key: { string_value: "hello" } + value: { string_value: "world" } + } + } + } + } + test { + name: "struct_list_optindex_field" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{repeated_string: ['greetings', ?{'nested': {'hello': 'world'}}.nested.?hello]}.repeated_string" + value: { + list_value: { + values { + string_value: "greetings" + } + values { + string_value: "world" + } + } + } + } + test { + name: "optional_empty_map_optindex_hasValue" + expr: "optional.of({}).?c.hasValue()" + value: { + bool_value: false + } + } + test { + name: "empty_struct_optindex_hasValue" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.?repeated_string.hasValue()" + value: { + bool_value: false + } + } + test { + name: "optional_empty_struct_optindex_hasValue" + container: "google.api.expr.test.v1.proto2" + expr: "optional.of(TestAllTypes{}).?repeated_string.hasValue()" + value: { + bool_value: false + } + } + test { + name: "optional_none_optselect_hasValue" + expr: "optional.none().?repeated_string.hasValue()" + value: { + bool_value: false + } + } + test { + name: "struct_optindex_value" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{repeated_string: ['foo']}.?repeated_string.value()" + value: { + list_value: { + values { + string_value: "foo" + } + } + } + } + test { + name: "optional_struct_optindex_value" + container: "google.api.expr.test.v1.proto2" + expr: "optional.of(TestAllTypes{repeated_string: ['foo']}).?repeated_string.value()" + value: { + list_value: { + values { + string_value: "foo" + } + } + } + } + test { + name: "optional_struct_optindex_index_value" + container: "google.api.expr.test.v1.proto2" + expr: "optional.of(TestAllTypes{repeated_string: ['foo']}).?repeated_string[0].value()" + value: { + string_value: "foo" + } + } + test { + name: "empty_list_optindex_hasValue" + expr: "[][?0].hasValue()" + value: { + bool_value: false + } + } + test { + name: "optional_empty_list_optindex_hasValue" + expr: "optional.of([])[?0].hasValue()" + value: { + bool_value: false + } + } + test { + name: "optional_none_optindex_hasValue" + expr: "optional.none()[?0].hasValue()" + value: { + bool_value: false + } + } + test { + name: "list_optindex_value" + expr: "['foo'][?0].value()" + value: { + string_value: "foo" + } + } + test { + name: "optional_list_optindex_value" + expr: "optional.of(['foo'])[?0].value()" + value: { + string_value: "foo" + } + } + test { + name: "map_key_mixed_type_optindex_value" + expr: "{true: 1, 2: 2, 5u: 3}[?true].value()" + value: { int64_value: 1 } + } + test { + name: "map_key_mixed_numbers_double_key_optindex_value" + expr: "{1u: 1.0, 2: 2.0, 3u: 3.0}[?3.0].value()" + value: { double_value: 3.0 } + } + test { + name: "map_key_mixed_numbers_uint_key_optindex_value" + expr: "{1u: 1.0, 2: 2.0, 3u: 3.0}[?2u].value()" + value: { double_value: 2.0 } + } + test { + name: "map_key_mixed_numbers_int_key_optindex_value" + expr: "{1u: 1.0, 2: 2.0, 3u: 3.0}[?1].value()" + value: { double_value: 1.0 } + } + test { + name: "optional_eq_none_none" + expr: "optional.none() == optional.none()" + value: { bool_value: true } + } + test { + name: "optional_eq_none_int" + expr: "optional.none() == optional.of(1)" + value: { bool_value: false } + } + test { + name: "optional_eq_int_none" + expr: "optional.of(1) == optional.none()" + value: { bool_value: false } + } + test { + name: "optional_eq_int_int" + expr: "optional.of(1) == optional.of(1)" + value: { bool_value: true } + } + test { + name: "optional_ne_none_none" + expr: "optional.none() != optional.none()" + value: { bool_value: false } + } + test { + name: "optional_ne_none_int" + expr: "optional.none() != optional.of(1)" + value: { bool_value: true } + } + test { + name: "optional_ne_int_none" + expr: "optional.of(1) != optional.none()" + value: { bool_value: true } + } + test { + name: "optional_ne_int_int" + expr: "optional.of(1) != optional.of(1)" + value: { bool_value: false } + } +} diff --git a/packages/cel/src/lib/conformance/testdata/parse.json b/packages/cel/src/lib/conformance/testdata/parse.json new file mode 100755 index 0000000..b777f4f --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/parse.json @@ -0,0 +1,192 @@ +{ + "name": "parse", + "description": "End-to-end parsing tests.", + "section": [ + { + "name": "nest", + "description": "Deep parse trees which all implementations must support.", + "test": [ + { + "name": "list_index", + "description": "Member = Member '[' Expr ']'. Nested indices are supported up to 12 times.", + "expr": "a[a[a[a[a[a[a[a[a[a[a[a[0]]]]]]]]]]]]", + "typeEnv": [ + { + "name": "a", + "ident": { + "type": { + "listType": { + "elemType": { + "primitive": "INT64" + } + } + } + } + } + ], + "bindings": { + "a": { + "value": { + "listValue": { + "values": [ + { + "int64Value": "0" + } + ] + } + } + } + }, + "value": { + "int64Value": "0" + } + }, + { + "name": "message_literal", + "description": "Member = Member '{' [FieldInits] '}'. Nested messages supported up to 12 levels deep.", + "expr": "NestedTestAllTypes{child: NestedTestAllTypes{child: NestedTestAllTypes{child: NestedTestAllTypes{child: NestedTestAllTypes{child: NestedTestAllTypes{child: NestedTestAllTypes{child: NestedTestAllTypes{child: NestedTestAllTypes{child: NestedTestAllTypes{child: NestedTestAllTypes{payload: TestAllTypes{single_int64: 137}}}}}}}}}}}}.payload.single_int64", + "container": "google.api.expr.test.v1.proto3", + "value": { + "int64Value": "0" + } + }, + { + "name": "funcall", + "description": "Primary = ['.'] IDENT ['(' [ExprList] ')']. Nested function calls supported up to 12 levels deep.", + "expr": "int(uint(int(uint(int(uint(int(uint(int(uint(int(uint(7))))))))))))", + "value": { + "int64Value": "7" + } + }, + { + "name": "list_literal", + "description": "Primary = '[' [ExprList] ']'. Nested list literals up to 12 levels deep.", + "expr": "size([[[[[[[[[[[[0]]]]]]]]]]]])", + "value": { + "int64Value": "1" + } + }, + { + "name": "map_literal", + "description": "Primary = '{' [MapInits] '}'. Nested map literals up to 12 levels deep.", + "expr": "size({0: {0: {0: {0: {0: {0: {0: {0: {0: {0: {0: {0: 'foo'}}}}}}}}}}}})", + "value": { + "int64Value": "1" + } + }, + { + "name": "parens", + "description": "Primary = '(' Expr ')'", + "expr": "((((((((((((((((((((((((((((((((7))))))))))))))))))))))))))))))))", + "value": { + "int64Value": "7" + } + } + ] + }, + { + "name": "repeat", + "description": "Repetitive parse trees which all implementations must support.", + "test": [ + { + "name": "conditional", + "description": "Expr = ConditionalOr ['?' ConditionalOr ':' Expr]. Chained ternary operators up to 24 levels.", + "expr": "true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : false", + "value": { + "boolValue": true + } + }, + { + "name": "or", + "description": "ConditionalOr = [ConditionalOr '||'] ConditionalAnd. Logical OR statements with 32 conditions.", + "expr": "false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || true", + "value": { + "boolValue": true + } + }, + { + "name": "and", + "description": "ConditionalAnd = [ConditionalAnd '&&'] Relation. Logical AND statements with 32 conditions.", + "expr": "true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && false", + "value": { + "boolValue": false + } + }, + { + "name": "add_sub", + "description": "Addition = [Addition ('+' | '-')] Multiplication. Addition operators are supported up to 24 times consecutively.", + "expr": "3 - 3 + 3 - 3 + 3 - 3 + 3 - 3 + 3 - 3 + 3 - 3 + 3 - 3 + 3 - 3 + 3 - 3 + 3 - 3 + 3 - 3 + 3 - 3 + 3", + "value": { + "int64Value": "3" + } + }, + { + "name": "mul_div", + "description": "Multiplication = [Multiplication ('*' | '/' | '%')] Unary. Multiplication operators are supported up to 24 times consecutively.", + "expr": "4 * 4 / 4 * 4 / 4 * 4 / 4 * 4 / 4 * 4 / 4 * 4 / 4 * 4 / 4 * 4 / 4 * 4 / 4 * 4 / 4 * 4 / 4 * 4 / 4", + "value": { + "int64Value": "4" + } + }, + { + "name": "not", + "description": "Unary = '!' {'!'} Member", + "expr": "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!true", + "value": { + "boolValue": true + } + }, + { + "name": "unary_neg", + "description": "Unary = '-' {'-'} Member", + "expr": "--------------------------------19", + "value": { + "int64Value": "19" + } + }, + { + "name": "select", + "description": "Member = Member '.' IDENT ['(' [ExprList] ')']. Selection is supported up to 12 times consecutively.", + "expr": "NestedTestAllTypes{}.child.child.child.child.child.child.child.child.child.child.payload.single_int32", + "container": "google.api.expr.test.v1.proto3", + "value": { + "int64Value": "0" + } + }, + { + "name": "index", + "description": "Member = Member '[' Expr ']'. Indexing is supported up to 12 times consecutively.", + "expr": "[[[[[[[[[[[['foo']]]]]]]]]]]][0][0][0][0][0][0][0][0][0][0][0][0]", + "value": { + "stringValue": "foo" + } + }, + { + "name": "list_literal", + "description": "Primary = '[' [ExprList] ']'. List literals with up to 32 elements.", + "expr": "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31][17]", + "value": { + "int64Value": "17" + } + }, + { + "name": "map_literal", + "description": "Primary = '{' [MapInits] '}'. Map literals with up to 32 entries.", + "expr": "{0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five', 6: 'six', 7: 'seven', 8: 'eight', 9: 'nine', 10: 'ten', 11: 'eleven', 12: 'twelve', 13: 'thirteen', 14: 'fourteen', 15: 'fifteen', 16: 'sixteen', 17: 'seventeen', 18: 'eighteen', 19: 'nineteen', 20: 'twenty', 21: 'twenty-one', 22: 'twenty-two', 23: 'twenty-three', 24: 'twenty-four', 25: 'twenty-five', 26: 'twenty-six', 27: 'twenty-seven', 28: 'twenty-eight', 29: 'twenty-nine', 30: 'thirty', 31: 'thirty-one'}[17]", + "value": { + "stringValue": "seventeen" + } + }, + { + "name": "message_literal", + "description": "Member = Member '{' [FieldInits] '}'. Message literals with up to 32 fields.", + "expr": "TestAllTypes{single_int32: 5, single_int64: 10, single_uint32: 15u, single_uint64: 20u, single_sint32: 25, single_sint64: 30, single_fixed32: 35u, single_fixed64: 40u, single_float: 45.0, single_double: 50.0, single_bool: true, single_string: 'sixty', single_bytes: b'sixty-five', single_value: 70.0, single_int64_wrapper: 75, single_int32_wrapper: 80, single_double_wrapper: 85.0, single_float_wrapper: 90.0, single_uint64_wrapper: 95u, single_uint32_wrapper: 100u, single_string_wrapper: 'one hundred five', single_bool_wrapper: true, repeated_int32: [115], repeated_int64: [120], repeated_uint32: [125u], repeated_uint64: [130u], repeated_sint32: [135], repeated_sint64: [140], repeated_fixed32: [145u], repeated_fixed64: [150u], repeated_sfixed32: [155], repeated_float: [160.0]}.single_sint64", + "container": "google.api.expr.test.v1.proto3", + "value": { + "int64Value": "30" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/parse.textproto b/packages/cel/src/lib/conformance/testdata/parse.textproto new file mode 100644 index 0000000..f5749f2 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/parse.textproto @@ -0,0 +1,129 @@ +name: "parse" +description: "End-to-end parsing tests." +section { + name: "nest" + description: "Deep parse trees which all implementations must support." + test { + name: "list_index" + description: "Member = Member '[' Expr ']'. Nested indices are supported up to 12 times." + expr: "a[a[a[a[a[a[a[a[a[a[a[a[0]]]]]]]]]]]]" + type_env { + name: "a" + ident { type { list_type { elem_type { primitive: INT64 } } } } + } + bindings { + key: "a" + value { value { list_value { values { int64_value: 0 } } } } + } + value { int64_value: 0 } + } + test { + name: "message_literal" + description: "Member = Member '{' [FieldInits] '}'. Nested messages supported up to 12 levels deep." + container: "google.api.expr.test.v1.proto3" + expr: "NestedTestAllTypes{child: NestedTestAllTypes{child: NestedTestAllTypes{child: NestedTestAllTypes{child: NestedTestAllTypes{child: NestedTestAllTypes{child: NestedTestAllTypes{child: NestedTestAllTypes{child: NestedTestAllTypes{child: NestedTestAllTypes{child: NestedTestAllTypes{payload: TestAllTypes{single_int64: 137}}}}}}}}}}}}.payload.single_int64" + value { int64_value: 0 } + } + test { + name: "funcall" + description: "Primary = ['.'] IDENT ['(' [ExprList] ')']. Nested function calls supported up to 12 levels deep." + expr: "int(uint(int(uint(int(uint(int(uint(int(uint(int(uint(7))))))))))))" + value { int64_value: 7 } + } + test { + name: "list_literal" + description: "Primary = '[' [ExprList] ']'. Nested list literals up to 12 levels deep." + expr: "size([[[[[[[[[[[[0]]]]]]]]]]]])" + value { int64_value: 1 } + } + test { + name: "map_literal" + description: "Primary = '{' [MapInits] '}'. Nested map literals up to 12 levels deep." + expr: "size({0: {0: {0: {0: {0: {0: {0: {0: {0: {0: {0: {0: 'foo'}}}}}}}}}}}})" + value { int64_value: 1 } + } + test { + name: "parens" + description: "Primary = '(' Expr ')'" + expr: "((((((((((((((((((((((((((((((((7))))))))))))))))))))))))))))))))" + value { int64_value: 7 } + } +} +section { + name: "repeat" + description: "Repetitive parse trees which all implementations must support." + test { + name: "conditional" + description: "Expr = ConditionalOr ['?' ConditionalOr ':' Expr]. Chained ternary operators up to 24 levels." + expr: "true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : true ? true : false" + value { bool_value: true } + } + test { + name: "or" + description: "ConditionalOr = [ConditionalOr '||'] ConditionalAnd. Logical OR statements with 32 conditions." + expr: "false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || false || true" + value { bool_value: true } + } + test { + name: "and" + description: "ConditionalAnd = [ConditionalAnd '&&'] Relation. Logical AND statements with 32 conditions." + expr: "true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && true && false" + value { bool_value: false } + } + test { + name: "add_sub" + description: "Addition = [Addition ('+' | '-')] Multiplication. Addition operators are supported up to 24 times consecutively." + expr: "3 - 3 + 3 - 3 + 3 - 3 + 3 - 3 + 3 - 3 + 3 - 3 + 3 - 3 + 3 - 3 + 3 - 3 + 3 - 3 + 3 - 3 + 3 - 3 + 3" + value { int64_value: 3 } + } + test { + name: "mul_div" + description: "Multiplication = [Multiplication ('*' | '/' | '%')] Unary. Multiplication operators are supported up to 24 times consecutively." + expr: "4 * 4 / 4 * 4 / 4 * 4 / 4 * 4 / 4 * 4 / 4 * 4 / 4 * 4 / 4 * 4 / 4 * 4 / 4 * 4 / 4 * 4 / 4 * 4 / 4" + value { int64_value: 4 } + } + test { + name: "not" + description: "Unary = '!' {'!'} Member" + expr: "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!true" + value { bool_value: true } + } + test { + name: "unary_neg" + description: "Unary = '-' {'-'} Member" + expr: "--------------------------------19" + value { int64_value: 19 } + } + test { + name: "select" + description: "Member = Member '.' IDENT ['(' [ExprList] ')']. Selection is supported up to 12 times consecutively." + container: "google.api.expr.test.v1.proto3" + expr: "NestedTestAllTypes{}.child.child.child.child.child.child.child.child.child.child.payload.single_int32" + value { int64_value: 0 } + } + test { + name: "index" + description: "Member = Member '[' Expr ']'. Indexing is supported up to 12 times consecutively." + expr: "[[[[[[[[[[[['foo']]]]]]]]]]]][0][0][0][0][0][0][0][0][0][0][0][0]" + value { string_value: "foo" } + } + test { + name: "list_literal" + description: "Primary = '[' [ExprList] ']'. List literals with up to 32 elements." + expr: "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31][17]" + value { int64_value: 17 } + } + test { + name: "map_literal" + description: "Primary = '{' [MapInits] '}'. Map literals with up to 32 entries." + expr: "{0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five', 6: 'six', 7: 'seven', 8: 'eight', 9: 'nine', 10: 'ten', 11: 'eleven', 12: 'twelve', 13: 'thirteen', 14: 'fourteen', 15: 'fifteen', 16: 'sixteen', 17: 'seventeen', 18: 'eighteen', 19: 'nineteen', 20: 'twenty', 21: 'twenty-one', 22: 'twenty-two', 23: 'twenty-three', 24: 'twenty-four', 25: 'twenty-five', 26: 'twenty-six', 27: 'twenty-seven', 28: 'twenty-eight', 29: 'twenty-nine', 30: 'thirty', 31: 'thirty-one'}[17]" + value { string_value: 'seventeen' } + } + test { + name: "message_literal" + description: "Member = Member '{' [FieldInits] '}'. Message literals with up to 32 fields." + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_int32: 5, single_int64: 10, single_uint32: 15u, single_uint64: 20u, single_sint32: 25, single_sint64: 30, single_fixed32: 35u, single_fixed64: 40u, single_float: 45.0, single_double: 50.0, single_bool: true, single_string: 'sixty', single_bytes: b'sixty-five', single_value: 70.0, single_int64_wrapper: 75, single_int32_wrapper: 80, single_double_wrapper: 85.0, single_float_wrapper: 90.0, single_uint64_wrapper: 95u, single_uint32_wrapper: 100u, single_string_wrapper: 'one hundred five', single_bool_wrapper: true, repeated_int32: [115], repeated_int64: [120], repeated_uint32: [125u], repeated_uint64: [130u], repeated_sint32: [135], repeated_sint64: [140], repeated_fixed32: [145u], repeated_fixed64: [150u], repeated_sfixed32: [155], repeated_float: [160.0]}.single_sint64" + value { int64_value: 30 } + } +} diff --git a/packages/cel/src/lib/conformance/testdata/plumbing.json b/packages/cel/src/lib/conformance/testdata/plumbing.json new file mode 100755 index 0000000..9562e41 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/plumbing.json @@ -0,0 +1,110 @@ +{ + "name": "plumbing", + "description": "Check that the ConformanceService server can accept all arguments and return all responses.", + "section": [ + { + "name": "min", + "description": "Minimal programs.", + "test": [ + { + "name": "min_program", + "description": "Smallest functionality: expr in, result out.", + "expr": "17", + "value": { + "int64Value": "17" + } + } + ] + }, + { + "name": "eval_results", + "description": "All evaluation result kinds.", + "test": [ + { + "name": "error_result", + "description": "Check that error results go through.", + "expr": "1 / 0", + "evalError": { + "errors": [ + { + "message": "foo" + } + ] + } + }, + { + "name": "eval_map_results", + "description": "Check that map literals results are order independent.", + "expr": "{\"k1\":\"v1\",\"k\":\"v\"}", + "value": { + "mapValue": { + "entries": [ + { + "key": { + "stringValue": "k" + }, + "value": { + "stringValue": "v" + } + }, + { + "key": { + "stringValue": "k1" + }, + "value": { + "stringValue": "v1" + } + } + ] + } + } + } + ] + }, + { + "name": "check_inputs", + "description": "All inputs to Check phase.", + "test": [ + { + "name": "skip_check", + "description": "Make sure we can skip type checking.", + "expr": "[17, 'pancakes']", + "disableCheck": true, + "value": { + "listValue": { + "values": [ + { + "int64Value": "17" + }, + { + "stringValue": "pancakes" + } + ] + } + } + } + ] + }, + { + "name": "eval_inputs", + "description": "All inputs to Eval phase.", + "test": [ + { + "name": "one_ignored_value_arg", + "description": "Check that value bindings can be given, even if ignored.", + "expr": "'foo'", + "bindings": { + "x": { + "value": { + "int64Value": "17" + } + } + }, + "value": { + "stringValue": "foo" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/plumbing.textproto b/packages/cel/src/lib/conformance/testdata/plumbing.textproto new file mode 100644 index 0000000..2f58b3c --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/plumbing.textproto @@ -0,0 +1,71 @@ +name: "plumbing" +description: "Check that the ConformanceService server can accept all arguments and return all responses." +section { + name: "min" + description: "Minimal programs." + test { + name: "min_program" + description: "Smallest functionality: expr in, result out." + expr: "17" + value: { int64_value: 17 } + } +} +section { + name: "eval_results" + description: "All evaluation result kinds." + test { + name: "error_result" + description: "Check that error results go through." + expr: "1 / 0" + eval_error: { + errors: { message: "foo" } + } + } + test { + name: "eval_map_results" + description: "Check that map literals results are order independent." + expr: '{"k1":"v1","k":"v"}' + value: { + map_value { + entries { + key: { string_value: "k" } + value: { string_value: "v" } + } + entries { + key: { string_value: "k1" } + value: { string_value: "v1" } + } + } + } + } +} +section { + name: "check_inputs" + description: "All inputs to Check phase." + test { + name: "skip_check" + description: "Make sure we can skip type checking." + expr: "[17, 'pancakes']" + disable_check: true + value: { + list_value { + values: { int64_value: 17 } + values: { string_value: "pancakes" } + } + } + } +} +section { + name: "eval_inputs" + description: "All inputs to Eval phase." + test { + name: "one_ignored_value_arg" + description: "Check that value bindings can be given, even if ignored." + expr: "'foo'" + bindings: { + key: "x" + value: { value: { int64_value: 17 } } + } + value: { string_value: "foo" } + } +} diff --git a/packages/cel/src/lib/conformance/testdata/proto2.json b/packages/cel/src/lib/conformance/testdata/proto2.json new file mode 100755 index 0000000..c7984be --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/proto2.json @@ -0,0 +1,902 @@ +{ + "name": "proto2", + "description": "Protocol buffer version 2 tests. See notes for the available set of protos for tests.", + "section": [ + { + "name": "literal_singular", + "description": "Literals with singular fields set.", + "test": [ + { + "name": "int64_nocontainer", + "expr": "google.api.expr.test.v1.proto2.TestAllTypes{single_int64: 17}", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleInt64": "17" + } + } + }, + { + "name": "int32", + "expr": "TestAllTypes{single_int32: -34}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleInt32": -34 + } + } + }, + { + "name": "int32_eq_uint", + "expr": "Int32Value{value: 34} == dyn(UInt64Value{value: 34u})", + "container": "google.protobuf", + "value": { + "boolValue": true + } + }, + { + "name": "not_int32_eq_uint", + "expr": "Int32Value{value: 34} == dyn(UInt64Value{value: 18446744073709551615u})", + "container": "google.protobuf", + "value": { + "boolValue": false + } + }, + { + "name": "int32_eq_double", + "expr": "Int32Value{value: 34} == dyn(DoubleValue{value: 34.0})", + "container": "google.protobuf", + "value": { + "boolValue": true + } + }, + { + "name": "not_int32_eq_double", + "expr": "Int32Value{value: 34} == dyn(DoubleValue{value: -9223372036854775809.0})", + "container": "google.protobuf", + "value": { + "boolValue": false + } + }, + { + "name": "int64", + "expr": "TestAllTypes{single_int64: 17}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleInt64": "17" + } + } + }, + { + "name": "uint32", + "expr": "TestAllTypes{single_uint32: 1u}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleUint32": 1 + } + } + }, + { + "name": "uint32_eq_int", + "expr": "UInt32Value{value: 34u} == dyn(Int64Value{value: 34})", + "container": "google.protobuf", + "value": { + "boolValue": true + } + }, + { + "name": "not_uint32_eq_int", + "expr": "UInt32Value{value: 34u} == dyn(Int64Value{value: -1})", + "container": "google.protobuf", + "value": { + "boolValue": false + } + }, + { + "name": "uint32_eq_double", + "expr": "UInt32Value{value: 34u} == dyn(DoubleValue{value: 34.0})", + "container": "google.protobuf", + "value": { + "boolValue": true + } + }, + { + "name": "not_uint32_eq_double", + "expr": "UInt32Value{value: 34u} == dyn(DoubleValue{value: 18446744073709551616.0})", + "container": "google.protobuf", + "value": { + "boolValue": false + } + }, + { + "name": "uint64", + "expr": "TestAllTypes{single_uint64: 9999u}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleUint64": "9999" + } + } + }, + { + "name": "sint32", + "expr": "TestAllTypes{single_sint32: -3}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleSint32": -3 + } + } + }, + { + "name": "sint64", + "expr": "TestAllTypes{single_sint64: 255}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleSint64": "255" + } + } + }, + { + "name": "fixed32", + "expr": "TestAllTypes{single_fixed32: 43u}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleFixed32": 43 + } + } + }, + { + "name": "fixed64", + "expr": "TestAllTypes{single_fixed64: 1880u}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleFixed64": "1880" + } + } + }, + { + "name": "sfixed32", + "expr": "TestAllTypes{single_sfixed32: -404}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleSfixed32": -404 + } + } + }, + { + "name": "sfixed64", + "expr": "TestAllTypes{single_sfixed64: -1}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleSfixed64": "-1" + } + } + }, + { + "name": "float", + "expr": "TestAllTypes{single_float: 3.1416}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleFloat": 3.1416 + } + } + }, + { + "name": "float_eq_int", + "expr": "FloatValue{value: 3.0} == dyn(Int64Value{value: 3})", + "container": "google.protobuf", + "value": { + "boolValue": true + } + }, + { + "name": "not_float_eq_int", + "expr": "FloatValue{value: -1.14} == dyn(Int64Value{value: -1})", + "container": "google.protobuf", + "value": { + "boolValue": false + } + }, + { + "name": "float_eq_uint", + "expr": "FloatValue{value: 34.0} == dyn(UInt64Value{value: 34u})", + "container": "google.protobuf", + "value": { + "boolValue": true + } + }, + { + "name": "not_float_eq_uint", + "expr": "FloatValue{value: -1.0} == dyn(UInt64Value{value: 18446744073709551615u})", + "container": "google.protobuf", + "value": { + "boolValue": false + } + }, + { + "name": "double", + "expr": "TestAllTypes{single_double: 6.022e23}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleDouble": 6.022e+23 + } + } + }, + { + "name": "bool", + "expr": "TestAllTypes{single_bool: true}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleBool": true + } + } + }, + { + "name": "string", + "expr": "TestAllTypes{single_string: 'foo'}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleString": "foo" + } + } + }, + { + "name": "bytes", + "expr": "TestAllTypes{single_bytes: b'\\377'}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleBytes": "/w==" + } + } + } + ] + }, + { + "name": "literal_wellknown", + "description": "Literals with well-known fields set.", + "test": [ + { + "name": "any", + "expr": "TestAllTypes{single_any: TestAllTypes{single_int32: 1}}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleAny": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleInt32": 1 + } + } + } + }, + { + "name": "duration", + "expr": "TestAllTypes{single_duration: duration('123s')}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleDuration": "123s" + } + } + }, + { + "name": "timestamp", + "expr": "TestAllTypes{single_timestamp: timestamp('2009-02-13T23:31:30Z')}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleTimestamp": "2009-02-13T23:31:30Z" + } + } + }, + { + "name": "struct", + "expr": "TestAllTypes{single_struct: {'one': 1, 'two': 2}}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleStruct": { + "one": 1, + "two": 2 + } + } + } + }, + { + "name": "value", + "expr": "TestAllTypes{single_value: 'foo'}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleValue": "foo" + } + } + }, + { + "name": "int64_wrapper", + "expr": "TestAllTypes{single_int64_wrapper: -321}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleInt64Wrapper": "-321" + } + } + }, + { + "name": "int32_wrapper", + "expr": "TestAllTypes{single_int32_wrapper: -456}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleInt32Wrapper": -456 + } + } + }, + { + "name": "double_wrapper", + "expr": "TestAllTypes{single_double_wrapper: 2.71828}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleDoubleWrapper": 2.71828 + } + } + }, + { + "name": "float_wrapper", + "expr": "TestAllTypes{single_float_wrapper: 2.99792e8}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleFloatWrapper": 299792000 + } + } + }, + { + "name": "uint64_wrapper", + "expr": "TestAllTypes{single_uint64_wrapper: 8675309u}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleUint64Wrapper": "8675309" + } + } + }, + { + "name": "uint32_wrapper", + "expr": "TestAllTypes{single_uint32_wrapper: 987u}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleUint32Wrapper": 987 + } + } + }, + { + "name": "string_wrapper", + "expr": "TestAllTypes{single_string_wrapper: 'hubba'}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleStringWrapper": "hubba" + } + } + }, + { + "name": "bool_wrapper", + "expr": "TestAllTypes{single_bool_wrapper: true}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleBoolWrapper": true + } + } + }, + { + "name": "bytes_wrapper", + "expr": "TestAllTypes{single_bytes_wrapper: b'\\301\\103'}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleBytesWrapper": "wUM=" + } + } + } + ] + }, + { + "name": "singular_bind", + "description": "Binding the singlular fields.", + "test": [ + { + "name": "int32", + "expr": "x.single_int32", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto2.TestAllTypes" + } + } + } + ], + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleInt32": 17 + } + } + } + }, + "value": { + "int64Value": "17" + } + }, + { + "name": "int64", + "expr": "x.single_int64", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto2.TestAllTypes" + } + } + } + ], + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "singleInt64": "-99" + } + } + } + }, + "value": { + "int64Value": "-99" + } + } + ] + }, + { + "name": "empty_field", + "description": "Tests on empty fields.", + "test": [ + { + "name": "scalar_with_default", + "expr": "TestAllTypes{}.single_int32", + "container": "google.api.expr.test.v1.proto2", + "value": { + "int64Value": "-32" + } + }, + { + "name": "scalar_no_default", + "expr": "TestAllTypes{}.single_fixed32", + "container": "google.api.expr.test.v1.proto2", + "value": { + "uint64Value": "0" + } + }, + { + "name": "nested_message", + "expr": "TestAllTypes{}.single_nested_message", + "container": "google.api.expr.test.v1.proto2", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes.NestedMessage" + } + } + }, + { + "name": "nested_message_subfield", + "expr": "TestAllTypes{}.single_nested_message.bb", + "container": "google.api.expr.test.v1.proto2", + "value": { + "int64Value": "0" + } + }, + { + "name": "wkt", + "expr": "TestAllTypes{}.single_int64_wrapper", + "container": "google.api.expr.test.v1.proto2", + "value": { + "nullValue": null + } + }, + { + "name": "repeated_scalar", + "expr": "TestAllTypes{}.repeated_int64", + "container": "google.api.expr.test.v1.proto2", + "value": { + "listValue": {} + } + }, + { + "name": "repeated_nested", + "expr": "TestAllTypes{}.repeated_nested_message", + "container": "google.api.expr.test.v1.proto2", + "value": { + "listValue": {} + } + }, + { + "name": "map", + "expr": "TestAllTypes{}.map_string_string", + "container": "google.api.expr.test.v1.proto2", + "value": { + "mapValue": {} + } + } + ] + }, + { + "name": "has", + "description": "Tests for the has() macro on proto2 messages.", + "test": [ + { + "name": "undefined", + "expr": "has(TestAllTypes{}.no_such_field)", + "disableCheck": true, + "container": "google.api.expr.test.v1.proto2", + "evalError": { + "errors": [ + { + "message": "no_such_field" + } + ] + } + }, + { + "name": "repeated_none_implicit", + "expr": "has(TestAllTypes{}.repeated_int32)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": false + } + }, + { + "name": "repeated_none_explicit", + "expr": "has(TestAllTypes{repeated_int32: []}.repeated_int32)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": false + } + }, + { + "name": "repeated_one", + "expr": "has(TestAllTypes{repeated_int32: [1]}.repeated_int32)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "repeated_many", + "expr": "has(TestAllTypes{repeated_int32: [1, 2, 3]}.repeated_int32)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "map_none_implicit", + "expr": "has(TestAllTypes{}.map_string_string)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": false + } + }, + { + "name": "map_none_explicit", + "expr": "has(TestAllTypes{map_string_string: {}}.map_string_string)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": false + } + }, + { + "name": "map_one_default", + "expr": "has(TestAllTypes{map_string_string: {'MT': ''}}.map_string_string)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "map_one", + "expr": "has(TestAllTypes{map_string_string: {'one': 'uno'}}.map_string_string)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "map_many", + "expr": "has(TestAllTypes{map_string_string: {'one': 'uno', 'two': 'dos'}}.map_string_string)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "required", + "expr": "has(TestRequired{required_int32: 4}.required_int32)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "optional_unset_no_default", + "expr": "has(TestAllTypes{}.single_sint32)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": false + } + }, + { + "name": "optional_set_no_default", + "expr": "has(TestAllTypes{single_sint32: -4}.single_sint32)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "optional_unset_with_default", + "expr": "has(TestAllTypes{}.single_int32)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": false + } + }, + { + "name": "optional_set_with_default", + "expr": "has(TestAllTypes{single_int32: 16}.single_int32)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "optional_set_to_default", + "expr": "has(TestAllTypes{single_int32: -32}.single_int32)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "optional_message_unset", + "expr": "has(TestAllTypes{}.standalone_message)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": false + } + }, + { + "name": "optional_message_set", + "expr": "has(TestAllTypes{standalone_message: TestAllTypes.NestedMessage{}}.standalone_message)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "optional_enum_unset", + "expr": "has(TestAllTypes{}.standalone_enum)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": false + } + }, + { + "name": "optional_enum_set", + "expr": "has(TestAllTypes{standalone_enum: TestAllTypes.NestedEnum.BAR}.standalone_enum)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "optional_enum_set_zero", + "expr": "has(TestAllTypes{standalone_enum: TestAllTypes.NestedEnum.FOO}.standalone_enum)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "oneof_unset", + "expr": "has(TestAllTypes{}.single_nested_message)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": false + } + }, + { + "name": "oneof_other_set", + "expr": "has(TestAllTypes{single_nested_enum: TestAllTypes.NestedEnum.BAZ}.single_nested_message)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": false + } + }, + { + "name": "oneof_set", + "expr": "has(TestAllTypes{single_nested_message: TestAllTypes.NestedMessage{}}.single_nested_message)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "oneof_set_default", + "expr": "has(TestAllTypes{single_nested_enum: TestAllTypes.NestedEnum.FOO}.single_nested_enum)", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "set_null", + "test": [ + { + "name": "single_message", + "expr": "TestAllTypes{single_nested_message: null} == TestAllTypes{}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "single_any", + "expr": "TestAllTypes{single_any: null}.single_any", + "container": "google.api.expr.test.v1.proto2", + "value": { + "nullValue": null + } + }, + { + "name": "single_value", + "expr": "TestAllTypes{single_value: null}.single_value", + "container": "google.api.expr.test.v1.proto2", + "value": { + "nullValue": null + } + }, + { + "name": "single_duration", + "expr": "TestAllTypes{single_duration: null} == TestAllTypes{}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "single_timestamp", + "expr": "TestAllTypes{single_timestamp: null} == TestAllTypes{}", + "container": "google.api.expr.test.v1.proto2", + "value": { + "boolValue": true + } + }, + { + "name": "single_scalar", + "expr": "TestAllTypes{single_bool: null} == TestAllTypes{}", + "disableCheck": true, + "container": "google.api.expr.test.v1.proto2", + "evalError": { + "errors": [ + { + "message": "unsupported field type" + } + ] + } + }, + { + "name": "repeated", + "expr": "TestAllTypes{repeated_int32: null} == TestAllTypes{}", + "disableCheck": true, + "container": "google.api.expr.test.v1.proto2", + "evalError": { + "errors": [ + { + "message": "unsupported field type" + } + ] + } + }, + { + "name": "map", + "expr": "TestAllTypes{map_string_string: null} == TestAllTypes{}", + "disableCheck": true, + "container": "google.api.expr.test.v1.proto2", + "evalError": { + "errors": [ + { + "message": "unsupported field type" + } + ] + } + }, + { + "name": "list_value", + "expr": "TestAllTypes{list_value: null} == TestAllTypes{}", + "disableCheck": true, + "container": "google.api.expr.test.v1.proto2", + "evalError": { + "errors": [ + { + "message": "unsupported field type" + } + ] + } + }, + { + "name": "single_struct", + "expr": "TestAllTypes{single_struct: null} == TestAllTypes{}", + "disableCheck": true, + "container": "google.api.expr.test.v1.proto2", + "evalError": { + "errors": [ + { + "message": "unsupported field type" + } + ] + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/proto2.textproto b/packages/cel/src/lib/conformance/testdata/proto2.textproto new file mode 100644 index 0000000..49f1f73 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/proto2.textproto @@ -0,0 +1,844 @@ +name: "proto2" +description: "Protocol buffer version 2 tests. See notes for the available set of protos for tests." + +section { + name: "literal_singular" + description: "Literals with singular fields set." + + test { + name: "int64_nocontainer" + expr: "google.api.expr.test.v1.proto2.TestAllTypes{single_int64: 17}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_int64: 17 } + } + } + } + + test { + name: "int32" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_int32: -34}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_int32: -34 } + } + } + } + + test { + name: "int32_eq_uint" + container: "google.protobuf" + expr: "Int32Value{value: 34} == dyn(UInt64Value{value: 34u})" + value { bool_value: true } + } + + test { + name: "not_int32_eq_uint" + container: "google.protobuf" + expr: "Int32Value{value: 34} == dyn(UInt64Value{value: 18446744073709551615u})" + value { bool_value: false } + } + + test { + name: "int32_eq_double" + container: "google.protobuf" + expr: "Int32Value{value: 34} == dyn(DoubleValue{value: 34.0})" + value { bool_value: true } + } + + test { + name: "not_int32_eq_double" + container: "google.protobuf" + expr: "Int32Value{value: 34} == dyn(DoubleValue{value: -9223372036854775809.0})" + value { bool_value: false } + } + + test { + name: "int64" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_int64: 17}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_int64: 17 } + } + } + } + + test { + name: "uint32" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_uint32: 1u}" + value { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_uint32: 1 } + } + } + } + + test { + name: "uint32_eq_int" + container: "google.protobuf" + expr: "UInt32Value{value: 34u} == dyn(Int64Value{value: 34})" + value { bool_value: true } + } + + test { + name: "not_uint32_eq_int" + container: "google.protobuf" + expr: "UInt32Value{value: 34u} == dyn(Int64Value{value: -1})" + value { bool_value: false } + } + + test { + name: "uint32_eq_double" + container: "google.protobuf" + expr: "UInt32Value{value: 34u} == dyn(DoubleValue{value: 34.0})" + value { bool_value: true } + } + + test { + name: "not_uint32_eq_double" + container: "google.protobuf" + expr: "UInt32Value{value: 34u} == dyn(DoubleValue{value: 18446744073709551616.0})" + value { bool_value: false } + } + + test { + name: "uint64" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_uint64: 9999u}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_uint64: 9999 } + } + } + } + + test { + name: "sint32" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_sint32: -3}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_sint32: -3 } + } + } + } + + test { + name: "sint64" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_sint64: 255}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_sint64: 255 } + } + } + } + + test { + name: "fixed32" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_fixed32: 43u}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_fixed32: 43 } + } + } + } + + test { + name: "fixed64" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_fixed64: 1880u}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_fixed64: 1880 } + } + } + } + + test { + name: "sfixed32" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_sfixed32: -404}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_sfixed32: -404 } + } + } + } + + test { + name: "sfixed64" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_sfixed64: -1}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_sfixed64: -1 } + } + } + } + + test { + name: "float" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_float: 3.1416}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_float: 3.1416 } + } + } + } + + test { + name: "float_eq_int" + container: "google.protobuf" + expr: "FloatValue{value: 3.0} == dyn(Int64Value{value: 3})" + value { bool_value: true } + } + + test { + name: "not_float_eq_int" + container: "google.protobuf" + expr: "FloatValue{value: -1.14} == dyn(Int64Value{value: -1})" + value { bool_value: false } + } + + test { + name: "float_eq_uint" + container: "google.protobuf" + expr: "FloatValue{value: 34.0} == dyn(UInt64Value{value: 34u})" + value { bool_value: true } + } + + test { + name: "not_float_eq_uint" + container: "google.protobuf" + expr: "FloatValue{value: -1.0} == dyn(UInt64Value{value: 18446744073709551615u})" + value { bool_value: false } + } + + test { + name: "double" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_double: 6.022e23}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_double: 6.022e23 } + } + } + } + + test { + name: "bool" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_bool: true}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_bool: true } + } + } + } + + test { + name: "string" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_string: 'foo'}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_string: 'foo' } + } + } + } + + test { + name: "bytes" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_bytes: b'\\377'}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_bytes: '\377' } + } + } + } +} + +section { + name: "literal_wellknown" + description: "Literals with well-known fields set." + + test { + name: "any" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_any: TestAllTypes{single_int32: 1}}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + single_any { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + single_int32: 1 + } + } + } + } + } + } + + test { + name: "duration" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_duration: duration('123s')}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + single_duration { + seconds: 123 + } + } + } + } + } + + test { + name: "timestamp" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_timestamp: timestamp('2009-02-13T23:31:30Z')}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + single_timestamp { + seconds: 1234567890 + } + } + } + } + } + + test { + name: "struct" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_struct: {'one': 1, 'two': 2}}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + single_struct { + fields { + key: "one" + value { number_value: 1.0 } + } + fields { + key: "two" + value { number_value: 2.0 } + } + } + } + } + } + } + + test { + name: "value" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_value: 'foo'}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + single_value { + string_value: "foo" + } + } + } + } + } + + test { + name: "int64_wrapper" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_int64_wrapper: -321}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + single_int64_wrapper { + value: -321 + } + } + } + } + } + + test { + name: "int32_wrapper" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_int32_wrapper: -456}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + single_int32_wrapper { + value: -456 + } + } + } + } + } + + test { + name: "double_wrapper" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_double_wrapper: 2.71828}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + single_double_wrapper { + value: 2.71828 + } + } + } + } + } + + test { + name: "float_wrapper" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_float_wrapper: 2.99792e8}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + single_float_wrapper { + value: 2.99792e8 + } + } + } + } + } + + test { + name: "uint64_wrapper" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_uint64_wrapper: 8675309u}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + single_uint64_wrapper { + value: 8675309 + } + } + } + } + } + + test { + name: "uint32_wrapper" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_uint32_wrapper: 987u}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + single_uint32_wrapper { + value: 987 + } + } + } + } + } + + test { + name: "string_wrapper" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_string_wrapper: 'hubba'}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + single_string_wrapper { + value: "hubba" + } + } + } + } + } + + test { + name: "bool_wrapper" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_bool_wrapper: true}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + single_bool_wrapper { + value: true + } + } + } + } + } + + test { + name: "bytes_wrapper" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_bytes_wrapper: b'\\301\\103'}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + single_bytes_wrapper { + value: "\301\103" + } + } + } + } + } + +} + +section { + name: "singular_bind" + description: "Binding the singlular fields." + + test { + name: "int32" + expr: "x.single_int32" + type_env: { + name: "x" + ident: { type: { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } } + } + bindings: { + key: "x" + value: { value: { object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_int32: 17 } + }}} + } + value: { int64_value: 17 } + } + + test { + name: "int64" + expr: "x.single_int64" + type_env: { + name: "x" + ident { type { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } } + } + bindings: { + key: "x" + value: { value: { object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] + { single_int64: -99 } + }}} + } + value: { int64_value: -99 } + } +} + +section { + name: "empty_field" + description: "Tests on empty fields." + + test { + name: "scalar_with_default" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.single_int32" + value: { int64_value: -32 } + } + + test { + name: "scalar_no_default" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.single_fixed32" + value: { uint64_value: 0 } + } + + test { + name: "nested_message" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.single_nested_message" + value: { object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes.NestedMessage] + { }}} + } + + test { + name: "nested_message_subfield" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.single_nested_message.bb" + value: { int64_value: 0 } + } + + test { + name: "wkt" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.single_int64_wrapper" + value: { null_value: NULL_VALUE } + } + + test { + name: "repeated_scalar" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.repeated_int64" + value: { list_value: {} } + } + + test { + name: "repeated_nested" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.repeated_nested_message" + value: { list_value: {} } + } + + test { + name: "map" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.map_string_string" + value: { map_value: {} } + } +} +section { + name: "has" + description: "Tests for the has() macro on proto2 messages." + test { + name: "undefined" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestAllTypes{}.no_such_field)" + disable_check: true + eval_error: { + errors: { message: "no_such_field" } + } + } + test { + name: "repeated_none_implicit" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestAllTypes{}.repeated_int32)" + value { bool_value: false } + } + test { + name: "repeated_none_explicit" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestAllTypes{repeated_int32: []}.repeated_int32)" + value { bool_value: false } + } + test { + name: "repeated_one" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestAllTypes{repeated_int32: [1]}.repeated_int32)" + value { bool_value: true } + } + test { + name: "repeated_many" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestAllTypes{repeated_int32: [1, 2, 3]}.repeated_int32)" + value { bool_value: true } + } + test { + name: "map_none_implicit" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestAllTypes{}.map_string_string)" + value { bool_value: false } + } + test { + name: "map_none_explicit" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestAllTypes{map_string_string: {}}.map_string_string)" + value { bool_value: false } + } + test { + name: "map_one_default" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestAllTypes{map_string_string: {'MT': ''}}.map_string_string)" + value { bool_value: true } + } + test { + name: "map_one" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestAllTypes{map_string_string: {'one': 'uno'}}.map_string_string)" + value { bool_value: true } + } + test { + name: "map_many" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestAllTypes{map_string_string: {'one': 'uno', 'two': 'dos'}}.map_string_string)" + value { bool_value: true } + } + test { + name: "required" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestRequired{required_int32: 4}.required_int32)" + value { bool_value: true } + } + test { + name: "optional_unset_no_default" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestAllTypes{}.single_sint32)" + value { bool_value: false } + } + test { + name: "optional_set_no_default" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestAllTypes{single_sint32: -4}.single_sint32)" + value { bool_value: true } + } + test { + name: "optional_unset_with_default" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestAllTypes{}.single_int32)" + value { bool_value: false } + } + test { + name: "optional_set_with_default" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestAllTypes{single_int32: 16}.single_int32)" + value { bool_value: true } + } + test { + name: "optional_set_to_default" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestAllTypes{single_int32: -32}.single_int32)" + value { bool_value: true } + } + test { + name: "optional_message_unset" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestAllTypes{}.standalone_message)" + value { bool_value: false } + } + test { + name: "optional_message_set" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestAllTypes{standalone_message: TestAllTypes.NestedMessage{}}.standalone_message)" + value { bool_value: true } + } + test { + name: "optional_enum_unset" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestAllTypes{}.standalone_enum)" + value { bool_value: false } + } + test { + name: "optional_enum_set" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestAllTypes{standalone_enum: TestAllTypes.NestedEnum.BAR}.standalone_enum)" + value { bool_value: true } + } + test { + name: "optional_enum_set_zero" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestAllTypes{standalone_enum: TestAllTypes.NestedEnum.FOO}.standalone_enum)" + value { bool_value: true } + } + test { + name: "oneof_unset" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestAllTypes{}.single_nested_message)" + value { bool_value: false } + } + test { + name: "oneof_other_set" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestAllTypes{single_nested_enum: TestAllTypes.NestedEnum.BAZ}.single_nested_message)" + value { bool_value: false } + } + test { + name: "oneof_set" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestAllTypes{single_nested_message: TestAllTypes.NestedMessage{}}.single_nested_message)" + value { bool_value: true } + } + test { + name: "oneof_set_default" + container: "google.api.expr.test.v1.proto2" + expr: "has(TestAllTypes{single_nested_enum: TestAllTypes.NestedEnum.FOO}.single_nested_enum)" + value { bool_value: true } + } +} +section { + name:"set_null" + test { + name: "single_message" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_nested_message: null} == TestAllTypes{}" + value: { bool_value: true } + } + test { + name: "single_any" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_any: null}.single_any" + value { null_value: NULL_VALUE } + } + test { + name: "single_value" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_value: null}.single_value" + value { null_value: NULL_VALUE } + } + test { + name: "single_duration" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_duration: null} == TestAllTypes{}" + value: { bool_value: true } + } + test { + name: "single_timestamp" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_timestamp: null} == TestAllTypes{}" + value: { bool_value: true } + } + test { + name: "single_scalar" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_bool: null} == TestAllTypes{}" + disable_check: true + eval_error: { + errors: { message: "unsupported field type" } + } + } + test { + name: "repeated" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{repeated_int32: null} == TestAllTypes{}" + disable_check: true + eval_error: { + errors: { message: "unsupported field type" } + } + } + test { + name: "map" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{map_string_string: null} == TestAllTypes{}" + disable_check: true + eval_error: { + errors: { message: "unsupported field type" } + } + } + test { + name: "list_value" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{list_value: null} == TestAllTypes{}" + disable_check: true + eval_error: { + errors: { message: "unsupported field type" } + } + } + test { + name: "single_struct" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{single_struct: null} == TestAllTypes{}" + disable_check: true + eval_error: { + errors: { message: "unsupported field type" } + } + } +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/proto2_ext.json b/packages/cel/src/lib/conformance/testdata/proto2_ext.json new file mode 100755 index 0000000..a1f6d7a --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/proto2_ext.json @@ -0,0 +1,476 @@ +{ + "name": "proto2_ext", + "description": "Tests for the proto extension library.", + "section": [ + { + "name": "has_ext", + "test": [ + { + "name": "package_scoped_int32", + "expr": "proto.hasExt(msg, google.api.expr.test.v1.proto2.int32_ext)", + "typeEnv": [ + { + "name": "msg", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto2.TestAllTypes" + } + } + } + ], + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "[google.api.expr.test.v1.proto2.int32_ext]": 42 + } + } + } + } + }, + { + "name": "package_scoped_nested_ext", + "expr": "proto.hasExt(msg, google.api.expr.test.v1.proto2.nested_ext)", + "typeEnv": [ + { + "name": "msg", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto2.TestAllTypes" + } + } + } + ], + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "[google.api.expr.test.v1.proto2.nested_ext]": {} + } + } + } + } + }, + { + "name": "package_scoped_test_all_types_ext", + "expr": "proto.hasExt(msg, google.api.expr.test.v1.proto2.test_all_types_ext)", + "typeEnv": [ + { + "name": "msg", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto2.TestAllTypes" + } + } + } + ], + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "[google.api.expr.test.v1.proto2.test_all_types_ext]": {} + } + } + } + } + }, + { + "name": "package_scoped_test_all_types_nested_enum_ext", + "expr": "proto.hasExt(msg, google.api.expr.test.v1.proto2.nested_enum_ext)", + "typeEnv": [ + { + "name": "msg", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto2.TestAllTypes" + } + } + } + ], + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "[google.api.expr.test.v1.proto2.nested_enum_ext]": "BAR" + } + } + } + } + }, + { + "name": "package_scoped_repeated_test_all_types", + "expr": "proto.hasExt(msg, google.api.expr.test.v1.proto2.repeated_test_all_types)", + "typeEnv": [ + { + "name": "msg", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto2.TestAllTypes" + } + } + } + ], + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "[google.api.expr.test.v1.proto2.repeated_test_all_types]": [ + { + "singleInt64": "1" + }, + { + "singleBool": true + } + ] + } + } + } + } + }, + { + "name": "message_scoped_int64", + "expr": "proto.hasExt(msg, google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.int64_ext)", + "typeEnv": [ + { + "name": "msg", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto2.TestAllTypes" + } + } + } + ], + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "[google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.int64_ext]": "42" + } + } + } + } + }, + { + "name": "message_scoped_nested_ext", + "expr": "proto.hasExt(msg, google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.message_scoped_nested_ext)", + "typeEnv": [ + { + "name": "msg", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto2.TestAllTypes" + } + } + } + ], + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "[google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.message_scoped_nested_ext]": {} + } + } + } + } + }, + { + "name": "message_scoped_nested_enum_ext", + "expr": "proto.hasExt(msg, google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.nested_enum_ext)", + "typeEnv": [ + { + "name": "msg", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto2.TestAllTypes" + } + } + } + ], + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "[google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.nested_enum_ext]": "BAR" + } + } + } + } + }, + { + "name": "message_scoped_repeated_test_all_types", + "expr": "proto.hasExt(msg, google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.message_scoped_repeated_test_all_types)", + "typeEnv": [ + { + "name": "msg", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto2.TestAllTypes" + } + } + } + ], + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "[google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.message_scoped_repeated_test_all_types]": [ + { + "singleInt64": "1" + }, + { + "singleBool": true + } + ] + } + } + } + } + } + ] + }, + { + "name": "get_ext", + "test": [ + { + "name": "package_scoped_int32", + "expr": "proto.getExt(msg, google.api.expr.test.v1.proto2.int32_ext) == 42", + "typeEnv": [ + { + "name": "msg", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto2.TestAllTypes" + } + } + } + ], + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "[google.api.expr.test.v1.proto2.int32_ext]": 42 + } + } + } + } + }, + { + "name": "package_scoped_nested_ext", + "expr": "proto.getExt(msg, google.api.expr.test.v1.proto2.nested_ext) == google.api.expr.test.v1.proto2.TestAllTypes{}", + "typeEnv": [ + { + "name": "msg", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto2.TestAllTypes" + } + } + } + ], + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "[google.api.expr.test.v1.proto2.nested_ext]": {} + } + } + } + } + }, + { + "name": "package_scoped_test_all_types_ext", + "expr": "proto.getExt(msg, google.api.expr.test.v1.proto2.test_all_types_ext) == google.api.expr.test.v1.proto2.TestAllTypes{}", + "typeEnv": [ + { + "name": "msg", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto2.TestAllTypes" + } + } + } + ], + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "[google.api.expr.test.v1.proto2.test_all_types_ext]": {} + } + } + } + } + }, + { + "name": "package_scoped_test_all_types_nested_enum_ext", + "expr": "proto.getExt(msg, google.api.expr.test.v1.proto2.nested_enum_ext) == google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum.BAR", + "typeEnv": [ + { + "name": "msg", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto2.TestAllTypes" + } + } + } + ], + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "[google.api.expr.test.v1.proto2.nested_enum_ext]": "BAR" + } + } + } + } + }, + { + "name": "package_scoped_repeated_test_all_types", + "expr": "proto.getExt(msg, google.api.expr.test.v1.proto2.repeated_test_all_types) == [google.api.expr.test.v1.proto2.TestAllTypes{single_int64: 1}, google.api.expr.test.v1.proto2.TestAllTypes{single_bool: true}]", + "typeEnv": [ + { + "name": "msg", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto2.TestAllTypes" + } + } + } + ], + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "[google.api.expr.test.v1.proto2.repeated_test_all_types]": [ + { + "singleInt64": "1" + }, + { + "singleBool": true + } + ] + } + } + } + } + }, + { + "name": "message_scoped_int64", + "expr": "proto.getExt(msg, google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.int64_ext) == 42", + "typeEnv": [ + { + "name": "msg", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto2.TestAllTypes" + } + } + } + ], + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "[google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.int64_ext]": "42" + } + } + } + } + }, + { + "name": "message_scoped_nested_ext", + "expr": "proto.getExt(msg, google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.message_scoped_nested_ext) == google.api.expr.test.v1.proto2.TestAllTypes{}", + "typeEnv": [ + { + "name": "msg", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto2.TestAllTypes" + } + } + } + ], + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "[google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.message_scoped_nested_ext]": {} + } + } + } + } + }, + { + "name": "message_scoped_nested_enum_ext", + "expr": "proto.getExt(msg, google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.nested_enum_ext) == google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum.BAR", + "typeEnv": [ + { + "name": "msg", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto2.TestAllTypes" + } + } + } + ], + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "[google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.nested_enum_ext]": "BAR" + } + } + } + } + }, + { + "name": "message_scoped_repeated_test_all_types", + "expr": "proto.getExt(msg, google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.message_scoped_repeated_test_all_types) == [google.api.expr.test.v1.proto2.TestAllTypes{single_int64: 1}, google.api.expr.test.v1.proto2.TestAllTypes{single_bool: true}]", + "typeEnv": [ + { + "name": "msg", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto2.TestAllTypes" + } + } + } + ], + "bindings": { + "msg": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes", + "[google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.message_scoped_repeated_test_all_types]": [ + { + "singleInt64": "1" + }, + { + "singleBool": true + } + ] + } + } + } + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/proto2_ext.textproto b/packages/cel/src/lib/conformance/testdata/proto2_ext.textproto new file mode 100644 index 0000000..30ebd53 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/proto2_ext.textproto @@ -0,0 +1,370 @@ +name: "proto2_ext" +description: "Tests for the proto extension library." +section: { + name: "has_ext" + test: { + name: "package_scoped_int32" + expr: "proto.hasExt(msg, google.api.expr.test.v1.proto2.int32_ext)" + type_env: { + name: "msg" + ident: { type: { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } } + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes]: { + [google.api.expr.test.v1.proto2.int32_ext]: 42 + } + } + } + } + } + } + test: { + name: "package_scoped_nested_ext" + expr: "proto.hasExt(msg, google.api.expr.test.v1.proto2.nested_ext)" + type_env: { + name: "msg" + ident: { type: { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } } + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes]: { + [google.api.expr.test.v1.proto2.nested_ext]: {} + } + } + } + } + } + } + test: { + name: "package_scoped_test_all_types_ext" + expr: "proto.hasExt(msg, google.api.expr.test.v1.proto2.test_all_types_ext)" + type_env: { + name: "msg" + ident: { type: { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } } + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes]: { + [google.api.expr.test.v1.proto2.test_all_types_ext]: {} + } + } + } + } + } + } + test: { + name: "package_scoped_test_all_types_nested_enum_ext" + expr: "proto.hasExt(msg, google.api.expr.test.v1.proto2.nested_enum_ext)" + type_env: { + name: "msg" + ident: { type: { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } } + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes]: { + [google.api.expr.test.v1.proto2.nested_enum_ext]: BAR + } + } + } + } + } + } + test: { + name: "package_scoped_repeated_test_all_types" + expr: "proto.hasExt(msg, google.api.expr.test.v1.proto2.repeated_test_all_types)" + type_env: { + name: "msg" + ident: { type: { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } } + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes]: { + [google.api.expr.test.v1.proto2.repeated_test_all_types]: [ { single_int64: 1 }, { single_bool: true } ] + } + } + } + } + } + } + test: { + name: "message_scoped_int64" + expr: "proto.hasExt(msg, google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.int64_ext)" + type_env: { + name: "msg" + ident: { type: { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } } + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes]: { + [google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.int64_ext]: 42 + } + } + } + } + } + } + test: { + name: "message_scoped_nested_ext" + expr: "proto.hasExt(msg, google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.message_scoped_nested_ext)" + type_env: { + name: "msg" + ident: { type: { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } } + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes]: { + [google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.message_scoped_nested_ext]: {} + } + } + } + } + } + } + test: { + name: "message_scoped_nested_enum_ext" + expr: "proto.hasExt(msg, google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.nested_enum_ext)" + type_env: { + name: "msg" + ident: { type: { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } } + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes]: { + [google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.nested_enum_ext]: BAR + } + } + } + } + } + } + test: { + name: "message_scoped_repeated_test_all_types" + expr: "proto.hasExt(msg, google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.message_scoped_repeated_test_all_types)" + type_env: { + name: "msg" + ident: { type: { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } } + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes]: { + [google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.message_scoped_repeated_test_all_types]: [ { single_int64: 1 }, { single_bool: true } ] + } + } + } + } + } + } +} + +section: { + name: "get_ext" + test: { + name: "package_scoped_int32" + expr: "proto.getExt(msg, google.api.expr.test.v1.proto2.int32_ext) == 42" + type_env: { + name: "msg" + ident: { type: { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } } + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes]: { + [google.api.expr.test.v1.proto2.int32_ext]: 42 + } + } + } + } + } + } + test: { + name: "package_scoped_nested_ext" + expr: "proto.getExt(msg, google.api.expr.test.v1.proto2.nested_ext) == google.api.expr.test.v1.proto2.TestAllTypes{}" + type_env: { + name: "msg" + ident: { type: { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } } + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes]: { + [google.api.expr.test.v1.proto2.nested_ext]: {} + } + } + } + } + } + } + test: { + name: "package_scoped_test_all_types_ext" + expr: "proto.getExt(msg, google.api.expr.test.v1.proto2.test_all_types_ext) == google.api.expr.test.v1.proto2.TestAllTypes{}" + type_env: { + name: "msg" + ident: { type: { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } } + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes]: { + [google.api.expr.test.v1.proto2.test_all_types_ext]: {} + } + } + } + } + } + } + test: { + name: "package_scoped_test_all_types_nested_enum_ext" + expr: "proto.getExt(msg, google.api.expr.test.v1.proto2.nested_enum_ext) == google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum.BAR" + type_env: { + name: "msg" + ident: { type: { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } } + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes]: { + [google.api.expr.test.v1.proto2.nested_enum_ext]: BAR + } + } + } + } + } + } + test: { + name: "package_scoped_repeated_test_all_types" + expr: "proto.getExt(msg, google.api.expr.test.v1.proto2.repeated_test_all_types) == [google.api.expr.test.v1.proto2.TestAllTypes{single_int64: 1}, google.api.expr.test.v1.proto2.TestAllTypes{single_bool: true}]" + type_env: { + name: "msg" + ident: { type: { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } } + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes]: { + [google.api.expr.test.v1.proto2.repeated_test_all_types]: [ { single_int64: 1 }, { single_bool: true } ] + } + } + } + } + } + } + test: { + name: "message_scoped_int64" + expr: "proto.getExt(msg, google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.int64_ext) == 42" + type_env: { + name: "msg" + ident: { type: { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } } + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes]: { + [google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.int64_ext]: 42 + } + } + } + } + } + } + test: { + name: "message_scoped_nested_ext" + expr: "proto.getExt(msg, google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.message_scoped_nested_ext) == google.api.expr.test.v1.proto2.TestAllTypes{}" + type_env: { + name: "msg" + ident: { type: { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } } + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes]: { + [google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.message_scoped_nested_ext]: {} + } + } + } + } + } + } + test: { + name: "message_scoped_nested_enum_ext" + expr: "proto.getExt(msg, google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.nested_enum_ext) == google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum.BAR" + type_env: { + name: "msg" + ident: { type: { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } } + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes]: { + [google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.nested_enum_ext]: BAR + } + } + } + } + } + } + test: { + name: "message_scoped_repeated_test_all_types" + expr: "proto.getExt(msg, google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.message_scoped_repeated_test_all_types) == [google.api.expr.test.v1.proto2.TestAllTypes{single_int64: 1}, google.api.expr.test.v1.proto2.TestAllTypes{single_bool: true}]" + type_env: { + name: "msg" + ident: { type: { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } } + } + bindings: { + key: "msg" + value: { + value: { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes]: { + [google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.message_scoped_repeated_test_all_types]: [ { single_int64: 1 }, { single_bool: true } ] + } + } + } + } + } + } +} + diff --git a/packages/cel/src/lib/conformance/testdata/proto3.json b/packages/cel/src/lib/conformance/testdata/proto3.json new file mode 100755 index 0000000..a60af11 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/proto3.json @@ -0,0 +1,782 @@ +{ + "name": "proto3", + "description": "Protocol buffer version 3 tests. See notes for the available set of protos for tests.", + "section": [ + { + "name": "literal_singular", + "description": "Literals with singular fields set.", + "test": [ + { + "name": "int64_nocontainer", + "expr": "google.api.expr.test.v1.proto3.TestAllTypes{single_int64: 17}", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt64": "17" + } + } + }, + { + "name": "int32", + "expr": "TestAllTypes{single_int32: -34}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt32": -34 + } + } + }, + { + "name": "int64", + "expr": "TestAllTypes{single_int64: 17}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt64": "17" + } + } + }, + { + "name": "uint32", + "expr": "TestAllTypes{single_uint32: 1u}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleUint32": 1 + } + } + }, + { + "name": "uint64", + "expr": "TestAllTypes{single_uint64: 9999u}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleUint64": "9999" + } + } + }, + { + "name": "sint32", + "expr": "TestAllTypes{single_sint32: -3}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleSint32": -3 + } + } + }, + { + "name": "sint64", + "expr": "TestAllTypes{single_sint64: 255}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleSint64": "255" + } + } + }, + { + "name": "fixed32", + "expr": "TestAllTypes{single_fixed32: 43u}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleFixed32": 43 + } + } + }, + { + "name": "fixed64", + "expr": "TestAllTypes{single_fixed64: 1880u}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleFixed64": "1880" + } + } + }, + { + "name": "sfixed32", + "expr": "TestAllTypes{single_sfixed32: -404}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleSfixed32": -404 + } + } + }, + { + "name": "sfixed64", + "expr": "TestAllTypes{single_sfixed64: -1}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleSfixed64": "-1" + } + } + }, + { + "name": "float", + "expr": "TestAllTypes{single_float: 3.1416}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleFloat": 3.1416 + } + } + }, + { + "name": "double", + "expr": "TestAllTypes{single_double: 6.022e23}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleDouble": 6.022e+23 + } + } + }, + { + "name": "bool", + "expr": "TestAllTypes{single_bool: true}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleBool": true + } + } + }, + { + "name": "string", + "expr": "TestAllTypes{single_string: 'foo'}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleString": "foo" + } + } + }, + { + "name": "bytes", + "expr": "TestAllTypes{single_bytes: b'\\377'}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleBytes": "/w==" + } + } + } + ] + }, + { + "name": "literal_wellknown", + "description": "Literals with well-known fields set.", + "test": [ + { + "name": "any", + "expr": "TestAllTypes{single_any: TestAllTypes{single_int32: 1}}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleAny": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt32": 1 + } + } + } + }, + { + "name": "duration", + "expr": "TestAllTypes{single_duration: duration('123s')}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleDuration": "123s" + } + } + }, + { + "name": "timestamp", + "expr": "TestAllTypes{single_timestamp: timestamp('2009-02-13T23:31:30Z')}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleTimestamp": "2009-02-13T23:31:30Z" + } + } + }, + { + "name": "struct", + "expr": "TestAllTypes{single_struct: {'one': 1, 'two': 2}}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleStruct": { + "one": 1, + "two": 2 + } + } + } + }, + { + "name": "value", + "expr": "TestAllTypes{single_value: 'foo'}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleValue": "foo" + } + } + }, + { + "name": "int64_wrapper", + "expr": "TestAllTypes{single_int64_wrapper: -321}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt64Wrapper": "-321" + } + } + }, + { + "name": "int32_wrapper", + "expr": "TestAllTypes{single_int32_wrapper: -456}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt32Wrapper": -456 + } + } + }, + { + "name": "double_wrapper", + "expr": "TestAllTypes{single_double_wrapper: 2.71828}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleDoubleWrapper": 2.71828 + } + } + }, + { + "name": "float_wrapper", + "expr": "TestAllTypes{single_float_wrapper: 2.99792e8}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleFloatWrapper": 299792000 + } + } + }, + { + "name": "uint64_wrapper", + "expr": "TestAllTypes{single_uint64_wrapper: 8675309u}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleUint64Wrapper": "8675309" + } + } + }, + { + "name": "uint32_wrapper", + "expr": "TestAllTypes{single_uint32_wrapper: 987u}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleUint32Wrapper": 987 + } + } + }, + { + "name": "string_wrapper", + "expr": "TestAllTypes{single_string_wrapper: 'hubba'}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleStringWrapper": "hubba" + } + } + }, + { + "name": "bool_wrapper", + "expr": "TestAllTypes{single_bool_wrapper: true}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleBoolWrapper": true + } + } + }, + { + "name": "bytes_wrapper", + "expr": "TestAllTypes{single_bytes_wrapper: b'\\301\\103'}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleBytesWrapper": "wUM=" + } + } + } + ] + }, + { + "name": "singular_bind", + "description": "Binding the singlular fields.", + "test": [ + { + "name": "int32", + "expr": "x.single_int32", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto3.TestAllTypes" + } + } + } + ], + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt32": 17 + } + } + } + }, + "value": { + "int64Value": "17" + } + }, + { + "name": "int64", + "expr": "x.single_int64", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.api.expr.test.v1.proto3.TestAllTypes" + } + } + } + ], + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes", + "singleInt64": "-99" + } + } + } + }, + "value": { + "int64Value": "-99" + } + } + ] + }, + { + "name": "empty_field", + "description": "Tests on empty fields.", + "test": [ + { + "name": "scalar", + "expr": "TestAllTypes{}.single_fixed32", + "container": "google.api.expr.test.v1.proto3", + "value": { + "uint64Value": "0" + } + }, + { + "name": "nested_message", + "expr": "TestAllTypes{}.single_nested_message", + "container": "google.api.expr.test.v1.proto3", + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage" + } + } + }, + { + "name": "nested_message_subfield", + "expr": "TestAllTypes{}.single_nested_message.bb", + "container": "google.api.expr.test.v1.proto3", + "value": { + "int64Value": "0" + } + }, + { + "name": "wkt", + "expr": "TestAllTypes{}.single_int64_wrapper", + "container": "google.api.expr.test.v1.proto3", + "value": { + "nullValue": null + } + }, + { + "name": "repeated_scalar", + "expr": "TestAllTypes{}.repeated_int64", + "container": "google.api.expr.test.v1.proto3", + "value": { + "listValue": {} + } + }, + { + "name": "repeated_nested", + "expr": "TestAllTypes{}.repeated_nested_message", + "container": "google.api.expr.test.v1.proto3", + "value": { + "listValue": {} + } + }, + { + "name": "map", + "expr": "TestAllTypes{}.map_string_string", + "container": "google.api.expr.test.v1.proto3", + "value": { + "mapValue": {} + } + } + ] + }, + { + "name": "has", + "description": "Tests for the has() macro on proto3 messages.", + "test": [ + { + "name": "undefined", + "expr": "has(TestAllTypes{}.no_such_field)", + "disableCheck": true, + "container": "google.api.expr.test.v1.proto3", + "evalError": { + "errors": [ + { + "message": "no_such_field" + } + ] + } + }, + { + "name": "repeated_none_implicit", + "expr": "has(TestAllTypes{}.repeated_int32)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": false + } + }, + { + "name": "repeated_none_explicit", + "expr": "has(TestAllTypes{repeated_int32: []}.repeated_int32)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": false + } + }, + { + "name": "repeated_one", + "expr": "has(TestAllTypes{repeated_int32: [1]}.repeated_int32)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "repeated_many", + "expr": "has(TestAllTypes{repeated_int32: [1, 2, 3]}.repeated_int32)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "map_none_implicit", + "expr": "has(TestAllTypes{}.map_string_string)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": false + } + }, + { + "name": "map_none_explicit", + "expr": "has(TestAllTypes{map_string_string: {}}.map_string_string)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": false + } + }, + { + "name": "map_one_default", + "expr": "has(TestAllTypes{map_string_string: {'MT': ''}}.map_string_string)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "map_one", + "expr": "has(TestAllTypes{map_string_string: {'one': 'uno'}}.map_string_string)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "map_many", + "expr": "has(TestAllTypes{map_string_string: {'one': 'uno', 'two': 'dos'}}.map_string_string)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "single_unset", + "expr": "has(TestAllTypes{}.single_int32)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": false + } + }, + { + "name": "single_set", + "expr": "has(TestAllTypes{single_int32: 16}.single_int32)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "single_set_to_default", + "expr": "has(TestAllTypes{single_int32: 0}.single_int32)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": false + } + }, + { + "name": "single_message_unset", + "expr": "has(TestAllTypes{}.standalone_message)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": false + } + }, + { + "name": "single_message_set", + "expr": "has(TestAllTypes{standalone_message: TestAllTypes.NestedMessage{bb: 123}}.standalone_message)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "single_message_set_to_default", + "expr": "has(TestAllTypes{standalone_message: TestAllTypes.NestedMessage{}}.standalone_message)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "single_enum_unset", + "expr": "has(TestAllTypes{}.standalone_enum)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": false + } + }, + { + "name": "single_enum_set", + "expr": "has(TestAllTypes{standalone_enum: TestAllTypes.NestedEnum.BAR}.standalone_enum)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "single_enum_set_zero", + "expr": "has(TestAllTypes{standalone_enum: TestAllTypes.NestedEnum.FOO}.standalone_enum)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": false + } + }, + { + "name": "oneof_unset", + "expr": "has(TestAllTypes{}.single_nested_message)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": false + } + }, + { + "name": "oneof_other_set", + "expr": "has(TestAllTypes{single_nested_enum: TestAllTypes.NestedEnum.BAZ}.single_nested_message)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": false + } + }, + { + "name": "oneof_set", + "expr": "has(TestAllTypes{single_nested_message: TestAllTypes.NestedMessage{}}.single_nested_message)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "oneof_set_default", + "expr": "has(TestAllTypes{single_nested_enum: TestAllTypes.NestedEnum.FOO}.single_nested_enum)", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "set_null", + "test": [ + { + "name": "single_message", + "expr": "TestAllTypes{single_nested_message: null} == TestAllTypes{}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "single_any", + "expr": "TestAllTypes{single_any: null}.single_any", + "container": "google.api.expr.test.v1.proto3", + "value": { + "nullValue": null + } + }, + { + "name": "single_value", + "expr": "TestAllTypes{single_value: null}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "nullValue": null + } + }, + { + "name": "single_duration", + "expr": "TestAllTypes{single_duration: null} == TestAllTypes{}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "single_timestamp", + "expr": "TestAllTypes{single_timestamp: null} == TestAllTypes{}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "single_scalar", + "expr": "TestAllTypes{single_bool: null} == TestAllTypes{}", + "disableCheck": true, + "container": "google.api.expr.test.v1.proto3", + "evalError": { + "errors": [ + { + "message": "unsupported field type" + } + ] + } + }, + { + "name": "repeated", + "expr": "TestAllTypes{repeated_int32: null} == TestAllTypes{}", + "disableCheck": true, + "container": "google.api.expr.test.v1.proto3", + "evalError": { + "errors": [ + { + "message": "unsupported field type" + } + ] + } + }, + { + "name": "map", + "expr": "TestAllTypes{map_string_string: null} == TestAllTypes{}", + "disableCheck": true, + "container": "google.api.expr.test.v1.proto3", + "evalError": { + "errors": [ + { + "message": "unsupported field type" + } + ] + } + }, + { + "name": "list_value", + "expr": "TestAllTypes{list_value: null} == TestAllTypes{}", + "disableCheck": true, + "container": "google.api.expr.test.v1.proto3", + "evalError": { + "errors": [ + { + "message": "unsupported field type" + } + ] + } + }, + { + "name": "single_struct", + "expr": "TestAllTypes{single_struct: null} == TestAllTypes{}", + "disableCheck": true, + "container": "google.api.expr.test.v1.proto3", + "evalError": { + "errors": [ + { + "message": "unsupported field type" + } + ] + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/proto3.textproto b/packages/cel/src/lib/conformance/testdata/proto3.textproto new file mode 100644 index 0000000..2d1fcbf --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/proto3.textproto @@ -0,0 +1,746 @@ +name: "proto3" +description: "Protocol buffer version 3 tests. See notes for the available set of protos for tests." + +section { + name: "literal_singular" + description: "Literals with singular fields set." + + test { + name: "int64_nocontainer" + expr: "google.api.expr.test.v1.proto3.TestAllTypes{single_int64: 17}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_int64: 17 } + } + } + } + + test { + name: "int32" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_int32: -34}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_int32: -34 } + } + } + } + + test { + name: "int64" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_int64: 17}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_int64: 17 } + } + } + } + + test { + name: "uint32" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_uint32: 1u}" + value { + object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_uint32: 1 } + } + } + } + + test { + name: "uint64" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_uint64: 9999u}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_uint64: 9999 } + } + } + } + + test { + name: "sint32" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_sint32: -3}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_sint32: -3 } + } + } + } + + test { + name: "sint64" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_sint64: 255}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_sint64: 255 } + } + } + } + + test { + name: "fixed32" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_fixed32: 43u}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_fixed32: 43 } + } + } + } + + test { + name: "fixed64" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_fixed64: 1880u}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_fixed64: 1880 } + } + } + } + + test { + name: "sfixed32" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_sfixed32: -404}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_sfixed32: -404 } + } + } + } + + test { + name: "sfixed64" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_sfixed64: -1}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_sfixed64: -1 } + } + } + } + + test { + name: "float" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_float: 3.1416}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_float: 3.1416 } + } + } + } + + test { + name: "double" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_double: 6.022e23}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_double: 6.022e23 } + } + } + } + + test { + name: "bool" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_bool: true}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_bool: true } + } + } + } + + test { + name: "string" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_string: 'foo'}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_string: 'foo' } + } + } + } + + test { + name: "bytes" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_bytes: b'\\377'}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_bytes: '\377' } + } + } + } +} + +section { + name: "literal_wellknown" + description: "Literals with well-known fields set." + + test { + name: "any" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_any: TestAllTypes{single_int32: 1}}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_any { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_int32: 1 + } + } + } + } + } + } + + test { + name: "duration" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_duration: duration('123s')}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_duration { + seconds: 123 + } + } + } + } + } + + test { + name: "timestamp" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_timestamp: timestamp('2009-02-13T23:31:30Z')}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_timestamp { + seconds: 1234567890 + } + } + } + } + } + + test { + name: "struct" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_struct: {'one': 1, 'two': 2}}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_struct { + fields { + key: "one" + value { number_value: 1.0 } + } + fields { + key: "two" + value { number_value: 2.0 } + } + } + } + } + } + } + + test { + name: "value" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: 'foo'}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_value { + string_value: "foo" + } + } + } + } + } + + test { + name: "int64_wrapper" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_int64_wrapper: -321}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_int64_wrapper { + value: -321 + } + } + } + } + } + + test { + name: "int32_wrapper" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_int32_wrapper: -456}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_int32_wrapper { + value: -456 + } + } + } + } + } + + test { + name: "double_wrapper" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_double_wrapper: 2.71828}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_double_wrapper { + value: 2.71828 + } + } + } + } + } + + test { + name: "float_wrapper" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_float_wrapper: 2.99792e8}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_float_wrapper { + value: 2.99792e8 + } + } + } + } + } + + + test { + name: "uint64_wrapper" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_uint64_wrapper: 8675309u}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_uint64_wrapper { + value: 8675309 + } + } + } + } + } + + + test { + name: "uint32_wrapper" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_uint32_wrapper: 987u}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_uint32_wrapper { + value: 987 + } + } + } + } + } + + + test { + name: "string_wrapper" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_string_wrapper: 'hubba'}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_string_wrapper { + value: "hubba" + } + } + } + } + } + + + test { + name: "bool_wrapper" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_bool_wrapper: true}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_bool_wrapper { + value: true + } + } + } + } + } + + + test { + name: "bytes_wrapper" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_bytes_wrapper: b'\\301\\103'}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + single_bytes_wrapper { + value: "\301\103" + } + } + } + } + } + +} + +section { + name: "singular_bind" + description: "Binding the singlular fields." + + test { + name: "int32" + expr: "x.single_int32" + type_env: { + name: "x" + ident: { type: { message_type: "google.api.expr.test.v1.proto3.TestAllTypes" } } + } + bindings: { + key: "x" + value: { value: { object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_int32: 17 } + }}} + } + value: { int64_value: 17 } + } + + test { + name: "int64" + expr: "x.single_int64" + type_env: { + name: "x" + ident { type { message_type: "google.api.expr.test.v1.proto3.TestAllTypes" } } + } + bindings: { + key: "x" + value: { value: { object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] + { single_int64: -99 } + }}} + } + value: { int64_value: -99 } + } +} + +section { + name: "empty_field" + description: "Tests on empty fields." + + test { + name: "scalar" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.single_fixed32" + value: { uint64_value: 0 } + } + + test { + name: "nested_message" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.single_nested_message" + value: { object_value: { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage] + { }}} + } + + test { + name: "nested_message_subfield" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.single_nested_message.bb" + value: { int64_value: 0 } + } + + test { + name: "wkt" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.single_int64_wrapper" + value: { null_value: NULL_VALUE } + } + + test { + name: "repeated_scalar" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.repeated_int64" + value: { list_value: {} } + } + + test { + name: "repeated_nested" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.repeated_nested_message" + value: { list_value: {} } + } + + test { + name: "map" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.map_string_string" + value: { map_value: {} } + } +} +section { + name: "has" + description: "Tests for the has() macro on proto3 messages." + test { + name: "undefined" + container: "google.api.expr.test.v1.proto3" + expr: "has(TestAllTypes{}.no_such_field)" + disable_check: true + eval_error: { + errors: { message: "no_such_field" } + } + } + test { + name: "repeated_none_implicit" + container: "google.api.expr.test.v1.proto3" + expr: "has(TestAllTypes{}.repeated_int32)" + value { bool_value: false } + } + test { + name: "repeated_none_explicit" + container: "google.api.expr.test.v1.proto3" + expr: "has(TestAllTypes{repeated_int32: []}.repeated_int32)" + value { bool_value: false } + } + test { + name: "repeated_one" + container: "google.api.expr.test.v1.proto3" + expr: "has(TestAllTypes{repeated_int32: [1]}.repeated_int32)" + value { bool_value: true } + } + test { + name: "repeated_many" + container: "google.api.expr.test.v1.proto3" + expr: "has(TestAllTypes{repeated_int32: [1, 2, 3]}.repeated_int32)" + value { bool_value: true } + } + test { + name: "map_none_implicit" + container: "google.api.expr.test.v1.proto3" + expr: "has(TestAllTypes{}.map_string_string)" + value { bool_value: false } + } + test { + name: "map_none_explicit" + container: "google.api.expr.test.v1.proto3" + expr: "has(TestAllTypes{map_string_string: {}}.map_string_string)" + value { bool_value: false } + } + test { + name: "map_one_default" + container: "google.api.expr.test.v1.proto3" + expr: "has(TestAllTypes{map_string_string: {'MT': ''}}.map_string_string)" + value { bool_value: true } + } + test { + name: "map_one" + container: "google.api.expr.test.v1.proto3" + expr: "has(TestAllTypes{map_string_string: {'one': 'uno'}}.map_string_string)" + value { bool_value: true } + } + test { + name: "map_many" + container: "google.api.expr.test.v1.proto3" + expr: "has(TestAllTypes{map_string_string: {'one': 'uno', 'two': 'dos'}}.map_string_string)" + value { bool_value: true } + } + test { + name: "single_unset" + container: "google.api.expr.test.v1.proto3" + expr: "has(TestAllTypes{}.single_int32)" + value { bool_value: false } + } + test { + name: "single_set" + container: "google.api.expr.test.v1.proto3" + expr: "has(TestAllTypes{single_int32: 16}.single_int32)" + value { bool_value: true } + } + test { + name: "single_set_to_default" + container: "google.api.expr.test.v1.proto3" + expr: "has(TestAllTypes{single_int32: 0}.single_int32)" + value { bool_value: false } + } + test { + name: "single_message_unset" + container: "google.api.expr.test.v1.proto3" + expr: "has(TestAllTypes{}.standalone_message)" + value { bool_value: false } + } + test { + name: "single_message_set" + container: "google.api.expr.test.v1.proto3" + expr: "has(TestAllTypes{standalone_message: TestAllTypes.NestedMessage{bb: 123}}.standalone_message)" + value { bool_value: true } + } + test { + name: "single_message_set_to_default" + container: "google.api.expr.test.v1.proto3" + expr: "has(TestAllTypes{standalone_message: TestAllTypes.NestedMessage{}}.standalone_message)" + value { bool_value: true } + } + test { + name: "single_enum_unset" + container: "google.api.expr.test.v1.proto3" + expr: "has(TestAllTypes{}.standalone_enum)" + value { bool_value: false } + } + test { + name: "single_enum_set" + container: "google.api.expr.test.v1.proto3" + expr: "has(TestAllTypes{standalone_enum: TestAllTypes.NestedEnum.BAR}.standalone_enum)" + value { bool_value: true } + } + test { + name: "single_enum_set_zero" + container: "google.api.expr.test.v1.proto3" + expr: "has(TestAllTypes{standalone_enum: TestAllTypes.NestedEnum.FOO}.standalone_enum)" + value { bool_value: false } + } + test { + name: "oneof_unset" + container: "google.api.expr.test.v1.proto3" + expr: "has(TestAllTypes{}.single_nested_message)" + value { bool_value: false } + } + test { + name: "oneof_other_set" + container: "google.api.expr.test.v1.proto3" + expr: "has(TestAllTypes{single_nested_enum: TestAllTypes.NestedEnum.BAZ}.single_nested_message)" + value { bool_value: false } + } + test { + name: "oneof_set" + container: "google.api.expr.test.v1.proto3" + expr: "has(TestAllTypes{single_nested_message: TestAllTypes.NestedMessage{}}.single_nested_message)" + value { bool_value: true } + } + test { + name: "oneof_set_default" + container: "google.api.expr.test.v1.proto3" + expr: "has(TestAllTypes{single_nested_enum: TestAllTypes.NestedEnum.FOO}.single_nested_enum)" + value { bool_value: true } + } +} +section { + name:"set_null" + test { + name: "single_message" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_nested_message: null} == TestAllTypes{}" + value: { bool_value: true } + } + test { + name: "single_any" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_any: null}.single_any" + value { null_value: NULL_VALUE } + } + test { + name: "single_value" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: null}.single_value" + value { null_value: NULL_VALUE } + } + test { + name: "single_duration" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_duration: null} == TestAllTypes{}" + value: { bool_value: true } + } + test { + name: "single_timestamp" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_timestamp: null} == TestAllTypes{}" + value: { bool_value: true } + } + test { + name: "single_scalar" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_bool: null} == TestAllTypes{}" + disable_check: true + eval_error: { + errors: { message: "unsupported field type" } + } + } + test { + name: "repeated" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{repeated_int32: null} == TestAllTypes{}" + disable_check: true + eval_error: { + errors: { message: "unsupported field type" } + } + } + test { + name: "map" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{map_string_string: null} == TestAllTypes{}" + disable_check: true + eval_error: { + errors: { message: "unsupported field type" } + } + } + test { + name: "list_value" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{list_value: null} == TestAllTypes{}" + disable_check: true + eval_error: { + errors: { message: "unsupported field type" } + } + } + test { + name: "single_struct" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_struct: null} == TestAllTypes{}" + disable_check: true + eval_error: { + errors: { message: "unsupported field type" } + } + } +} diff --git a/packages/cel/src/lib/conformance/testdata/string.json b/packages/cel/src/lib/conformance/testdata/string.json new file mode 100755 index 0000000..94ed79b --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/string.json @@ -0,0 +1,405 @@ +{ + "name": "string", + "description": "Tests for string and bytes operations.", + "section": [ + { + "name": "size", + "description": "Tests for the size() function.", + "test": [ + { + "name": "empty", + "expr": "size('')", + "value": { + "int64Value": "0" + } + }, + { + "name": "one_ascii", + "expr": "size('A')", + "value": { + "int64Value": "1" + } + }, + { + "name": "one_unicode", + "expr": "size('ÿ')", + "value": { + "int64Value": "1" + } + }, + { + "name": "ascii", + "expr": "size('four')", + "value": { + "int64Value": "4" + } + }, + { + "name": "unicode", + "expr": "size('πέντε')", + "value": { + "int64Value": "5" + } + }, + { + "name": "bytes_empty", + "expr": "size(b'')", + "value": { + "int64Value": "0" + } + }, + { + "name": "bytes", + "expr": "size(b'abc')", + "value": { + "int64Value": "3" + } + } + ] + }, + { + "name": "starts_with", + "description": "Tests for the startsWith() function.", + "test": [ + { + "name": "basic_true", + "expr": "'foobar'.startsWith('foo')", + "value": { + "boolValue": true + } + }, + { + "name": "basic_false", + "expr": "'foobar'.startsWith('bar')", + "value": { + "boolValue": false + } + }, + { + "name": "empty_target", + "expr": "''.startsWith('foo')", + "value": { + "boolValue": false + } + }, + { + "name": "empty_arg", + "expr": "'foobar'.startsWith('')", + "value": { + "boolValue": true + } + }, + { + "name": "empty_empty", + "expr": "''.startsWith('')", + "value": { + "boolValue": true + } + }, + { + "name": "unicode", + "expr": "'завтра'.startsWith('за')", + "value": { + "boolValue": true + } + }, + { + "name": "unicode_smp", + "expr": "'🐱😀😛'.startsWith('🐱')", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "ends_with", + "description": "Tests for the endsWith() function.", + "test": [ + { + "name": "basic_true", + "expr": "'foobar'.endsWith('bar')", + "value": { + "boolValue": true + } + }, + { + "name": "basic_false", + "expr": "'foobar'.endsWith('foo')", + "value": { + "boolValue": false + } + }, + { + "name": "empty_target", + "expr": "''.endsWith('foo')", + "value": { + "boolValue": false + } + }, + { + "name": "empty_arg", + "expr": "'foobar'.endsWith('')", + "value": { + "boolValue": true + } + }, + { + "name": "empty_empty", + "expr": "''.endsWith('')", + "value": { + "boolValue": true + } + }, + { + "name": "unicode", + "expr": "'forté'.endsWith('té')", + "value": { + "boolValue": true + } + }, + { + "name": "unicode_smp", + "expr": "'🐱😀😛'.endsWith('😛')", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "matches", + "description": "Tests for regexp matching. For now, we will only test the subset of regular languages.", + "test": [ + { + "name": "basic", + "expr": "'hubba'.matches('ubb')", + "value": { + "boolValue": true + } + }, + { + "name": "empty_target", + "expr": "''.matches('foo|bar')", + "value": { + "boolValue": false + } + }, + { + "name": "empty_arg", + "expr": "'cows'.matches('')", + "value": { + "boolValue": true + } + }, + { + "name": "empty_empty", + "expr": "''.matches('')", + "value": { + "boolValue": true + } + }, + { + "name": "re_concat", + "expr": "'abcd'.matches('bc')", + "value": { + "boolValue": true + } + }, + { + "name": "re_alt", + "expr": "'grey'.matches('gr(a|e)y')", + "value": { + "boolValue": true + } + }, + { + "name": "re_rep", + "expr": "'banana'.matches('ba(na)*')", + "value": { + "boolValue": true + } + }, + { + "name": "unicode", + "expr": "'mañana'.matches('a+ñ+a+')", + "value": { + "boolValue": true + } + }, + { + "name": "unicode_smp", + "expr": "'🐱😀😀'.matches('(a|😀){2}')", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "concatentation", + "description": "Tests for string concatenation.", + "test": [ + { + "name": "concat_true", + "expr": "'he' + 'llo'", + "value": { + "stringValue": "hello" + } + }, + { + "name": "concat_with_spaces", + "expr": "'hello' + ' ' == 'hello'", + "value": { + "boolValue": false + } + }, + { + "name": "concat_empty_string_beginning", + "expr": "'' + 'abc'", + "value": { + "stringValue": "abc" + } + }, + { + "name": "concat_empty_string_end", + "expr": "'abc' + ''", + "value": { + "stringValue": "abc" + } + }, + { + "name": "concat_empty_with_empty", + "expr": "'' + ''", + "value": { + "stringValue": "" + } + }, + { + "name": "unicode_unicode", + "expr": "'¢' + 'ÿ' + 'Ȁ'", + "value": { + "stringValue": "¢ÿȀ" + } + }, + { + "name": "ascii_unicode", + "expr": "'r' + 'ô' + 'le'", + "value": { + "stringValue": "rôle" + } + }, + { + "name": "ascii_unicode_unicode_smp", + "expr": "'a' + 'ÿ' + '🐱'", + "value": { + "stringValue": "aÿ🐱" + } + }, + { + "name": "empty_unicode", + "expr": "'' + 'Ω' + ''", + "value": { + "stringValue": "Ω" + } + } + ] + }, + { + "name": "contains", + "description": "Tests for contains.", + "test": [ + { + "name": "contains_true", + "expr": "'hello'.contains('he')", + "value": { + "boolValue": true + } + }, + { + "name": "contains_empty", + "expr": "'hello'.contains('')", + "value": { + "boolValue": true + } + }, + { + "name": "contains_false", + "expr": "'hello'.contains('ol')", + "value": { + "boolValue": false + } + }, + { + "name": "contains_multiple", + "expr": "'abababc'.contains('ababc')", + "value": { + "boolValue": true + } + }, + { + "name": "contains_unicode", + "expr": "'Straße'.contains('aß')", + "value": { + "boolValue": true + } + }, + { + "name": "contains_unicode_smp", + "expr": "'🐱😀😁'.contains('😀')", + "value": { + "boolValue": true + } + }, + { + "name": "empty_contains", + "expr": "''.contains('something')", + "value": { + "boolValue": false + } + }, + { + "name": "empty_empty", + "expr": "''.contains('')", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "bytes_concat", + "description": "Tests for bytes concatenation.", + "test": [ + { + "name": "concat", + "expr": "b'abc' + b'def'", + "value": { + "bytesValue": "YWJjZGVm" + } + }, + { + "name": "left_unit", + "expr": "b'' + b'\\xffoo'", + "value": { + "bytesValue": "/29v" + } + }, + { + "name": "right_unit", + "expr": "b'zxy' + b''", + "value": { + "bytesValue": "enh5" + } + }, + { + "name": "empty_empty", + "expr": "b'' + b''", + "value": { + "bytesValue": "" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/string.textproto b/packages/cel/src/lib/conformance/testdata/string.textproto new file mode 100644 index 0000000..5458080 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/string.textproto @@ -0,0 +1,285 @@ +name: "string" +description: "Tests for string and bytes operations." +section { + name: "size" + description: "Tests for the size() function." + test { + name: "empty" + expr: "size('')" + value: { int64_value: 0 } + } + test { + name: "one_ascii" + expr: "size('A')" + value: { int64_value: 1 } + } + test { + name: "one_unicode" + expr: "size('ÿ')" + value: { int64_value: 1 } + } + test { + name: "ascii" + expr: "size('four')" + value: { int64_value: 4 } + } + test { + name: "unicode" + expr: "size('πέντε')" + value: { int64_value: 5 } + } + test { + name: "bytes_empty" + expr: "size(b'')" + value: { int64_value: 0 } + } + test { + name: "bytes" + expr: "size(b'abc')" + value: { int64_value: 3 } + } +} +section { + name: "starts_with" + description: "Tests for the startsWith() function." + test { + name: "basic_true" + expr: "'foobar'.startsWith('foo')" + value: { bool_value: true } + } + test { + name: "basic_false" + expr: "'foobar'.startsWith('bar')" + value: { bool_value: false } + } + test { + name: "empty_target" + expr: "''.startsWith('foo')" + value: { bool_value: false } + } + test { + name: "empty_arg" + expr: "'foobar'.startsWith('')" + value: { bool_value: true } + } + test { + name: "empty_empty" + expr: "''.startsWith('')" + value: { bool_value: true } + } + test { + name: "unicode" + expr: "'завтра'.startsWith('за')" + value: { bool_value: true } + } + test { + name: "unicode_smp" + expr: "'\U0001F431\U0001F600\U0001F61B'.startsWith('\U0001F431')" + value: { bool_value: true } + } +} +section { + name: "ends_with" + description: "Tests for the endsWith() function." + test { + name: "basic_true" + expr: "'foobar'.endsWith('bar')" + value: { bool_value: true } + } + test { + name: "basic_false" + expr: "'foobar'.endsWith('foo')" + value: { bool_value: false } + } + test { + name: "empty_target" + expr: "''.endsWith('foo')" + value: { bool_value: false } + } + test { + name: "empty_arg" + expr: "'foobar'.endsWith('')" + value: { bool_value: true } + } + test { + name: "empty_empty" + expr: "''.endsWith('')" + value: { bool_value: true } + } + test { + name: "unicode" + expr: "'forté'.endsWith('té')" + value: { bool_value: true } + } + test { + name: "unicode_smp" + expr: "'\U0001F431\U0001F600\U0001F61B'.endsWith('\U0001F61B')" + value: { bool_value: true } + } +} +section { + name: "matches" + description: "Tests for regexp matching. For now, we will only test the subset of regular languages." + test { + name: "basic" + expr: "'hubba'.matches('ubb')" + value: { bool_value: true } + } + test { + name: "empty_target" + expr: "''.matches('foo|bar')" + value: { bool_value: false } + } + test { + name: "empty_arg" + expr: "'cows'.matches('')" + value: { bool_value: true } + } + test { + name: "empty_empty" + expr: "''.matches('')" + value: { bool_value: true } + } + test { + name: "re_concat" + expr: "'abcd'.matches('bc')" + value: { bool_value: true } + } + test { + name: "re_alt" + expr: "'grey'.matches('gr(a|e)y')" + value: { bool_value: true } + } + test { + name: "re_rep" + expr: "'banana'.matches('ba(na)*')" + value: { bool_value: true } + } + test { + name: "unicode" + expr: "'mañana'.matches('a+ñ+a+')" + value: { bool_value: true } + } + test { + name: "unicode_smp" + expr: "'\U0001F431\U0001F600\U0001F600'.matches('(a|\U0001F600){2}')" + value: { bool_value: true } + } +} +section { + name: "concatentation" + description: "Tests for string concatenation." + test { + name: "concat_true" + expr: "'he' + 'llo'" + value: { string_value: "hello" } + } + test { + name: "concat_with_spaces" + expr: "'hello' + ' ' == 'hello'" + value: { bool_value: false } + } + test { + name: "concat_empty_string_beginning" + expr: "'' + 'abc'" + value: { string_value: "abc" } + } + test { + name: "concat_empty_string_end" + expr: "'abc' + ''" + value: { string_value: "abc" } + } + test { + name: "concat_empty_with_empty" + expr: "'' + ''" + value: { string_value: "" } + } + test { + name: "unicode_unicode" + expr: "'¢' + 'ÿ' + 'Ȁ'" + value: { string_value: "¢ÿȀ" } + } + test { + name: "ascii_unicode" + expr: "'r' + 'ô' + 'le'" + value: { string_value: "rôle" } + } + test { + name: "ascii_unicode_unicode_smp" + expr: "'a' + 'ÿ' + '\U0001F431'" + value: { string_value: "aÿ\xf0\x9f\x90\xb1" } + } + test { + name: "empty_unicode" + expr: "'' + 'Ω' + ''" + value: { string_value: "Ω" } + } +} +section { + name: "contains" + description: "Tests for contains." + test { + name: "contains_true" + expr: "'hello'.contains('he')" + value: { bool_value: true } + } + test { + name: "contains_empty" + expr: "'hello'.contains('')" + value: { bool_value: true } + } + test { + name: "contains_false" + expr: "'hello'.contains('ol')" + value: { bool_value: false } + } + test { + name: "contains_multiple" + expr: "'abababc'.contains('ababc')" + value: { bool_value: true } + } + test { + name: "contains_unicode" + expr: "'Straße'.contains('aß')" + value: { bool_value: true } + } + test { + name: "contains_unicode_smp" + expr: "'\U0001F431\U0001F600\U0001F601'.contains('\U0001F600')" + value: { bool_value: true } + } + test { + name: "empty_contains" + expr: "''.contains('something')" + value: { bool_value: false } + } + test { + name: "empty_empty" + expr: "''.contains('')" + value: { bool_value: true } + } +} +section { + name: "bytes_concat" + description: "Tests for bytes concatenation." + test { + name: "concat" + expr: "b'abc' + b'def'" + value: { bytes_value: "abcdef" } + } + test { + name: "left_unit" + expr: "b'' + b'\\xffoo'" + value: { bytes_value: "\377oo" } + } + test { + name: "right_unit" + expr: "b'zxy' + b''" + value: { bytes_value: "zxy" } + } + test { + name: "empty_empty" + expr: "b'' + b''" + value: { bytes_value: "" } + } +} diff --git a/packages/cel/src/lib/conformance/testdata/string_ext.json b/packages/cel/src/lib/conformance/testdata/string_ext.json new file mode 100755 index 0000000..244b8c8 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/string_ext.json @@ -0,0 +1,1591 @@ +{ + "name": "string_ext", + "description": "Tests for the strings extension library.", + "section": [ + { + "name": "char_at", + "test": [ + { + "name": "middle_index", + "expr": "'tacocat'.charAt(3)", + "value": { + "stringValue": "o" + } + }, + { + "name": "end_index", + "expr": "'tacocat'.charAt(7)", + "value": { + "stringValue": "" + } + }, + { + "name": "multiple", + "expr": "'©αT'.charAt(0) == '©' && '©αT'.charAt(1) == 'α' && '©αT'.charAt(2) == 'T'" + } + ] + }, + { + "name": "index_of", + "test": [ + { + "name": "empty_index", + "expr": "'tacocat'.indexOf('')", + "value": { + "int64Value": "0" + } + }, + { + "name": "string_index", + "expr": "'tacocat'.indexOf('ac')", + "value": { + "int64Value": "1" + } + }, + { + "name": "nomatch", + "expr": "'tacocat'.indexOf('none') == -1" + }, + { + "name": "empty_index", + "expr": "'tacocat'.indexOf('', 3) == 3" + }, + { + "name": "char_index", + "expr": "'tacocat'.indexOf('a', 3) == 5" + }, + { + "name": "string_index", + "expr": "'tacocat'.indexOf('at', 3) == 5" + }, + { + "name": "unicode_char", + "expr": "'ta©o©αT'.indexOf('©') == 2" + }, + { + "name": "unicode_char_index", + "expr": "'ta©o©αT'.indexOf('©', 3) == 4" + }, + { + "name": "unicode_string_index", + "expr": "'ta©o©αT'.indexOf('©αT', 3) == 4" + }, + { + "name": "unicode_string_nomatch_index", + "expr": "'ta©o©αT'.indexOf('©α', 5) == -1" + }, + { + "name": "char_index", + "expr": "'ijk'.indexOf('k') == 2" + }, + { + "name": "string_with_space_fullmatch", + "expr": "'hello wello'.indexOf('hello wello') == 0" + }, + { + "name": "string_with_space_index", + "expr": "'hello wello'.indexOf('ello', 6) == 7" + }, + { + "name": "string_nomatch_index", + "expr": "'hello wello'.indexOf('elbo room!!') == -1" + } + ] + }, + { + "name": "last_index_of", + "test": [ + { + "name": "empty", + "expr": "'tacocat'.lastIndexOf('') == 7" + }, + { + "name": "string", + "expr": "'tacocat'.lastIndexOf('at') == 5" + }, + { + "name": "string_nomatch", + "expr": "'tacocat'.lastIndexOf('none') == -1" + }, + { + "name": "empty_index", + "expr": "'tacocat'.lastIndexOf('', 3) == 3" + }, + { + "name": "char_index", + "expr": "'tacocat'.lastIndexOf('a', 3) == 1" + }, + { + "name": "unicode_char", + "expr": "'ta©o©αT'.lastIndexOf('©') == 4" + }, + { + "name": "unicode_char_index", + "expr": "'ta©o©αT'.lastIndexOf('©', 3) == 2" + }, + { + "name": "unicode_string_index", + "expr": "'ta©o©αT'.lastIndexOf('©α', 4) == 4" + }, + { + "name": "string_with_space_string_index", + "expr": "'hello wello'.lastIndexOf('ello', 6) == 1" + }, + { + "name": "string_with_space_string_nomatch", + "expr": "'hello wello'.lastIndexOf('low') == -1" + }, + { + "name": "string_with_space_string_with_space_nomatch", + "expr": "'hello wello'.lastIndexOf('elbo room!!') == -1" + }, + { + "name": "string_with_space_fullmatch", + "expr": "'hello wello'.lastIndexOf('hello wello') == 0" + }, + { + "name": "repeated_string", + "expr": "'bananananana'.lastIndexOf('nana', 7) == 6" + } + ] + }, + { + "name": "ascii_casing", + "test": [ + { + "name": "lowerascii", + "expr": "'TacoCat'.lowerAscii() == 'tacocat'" + }, + { + "name": "lowerascii_unicode", + "expr": "'TacoCÆt'.lowerAscii() == 'tacocÆt'" + }, + { + "name": "lowerascii_unicode_with_space", + "expr": "'TacoCÆt Xii'.lowerAscii() == 'tacocÆt xii'" + }, + { + "name": "upperascii", + "expr": "'tacoCat'.upperAscii() == 'TACOCAT'" + }, + { + "name": "upperascii_unicode", + "expr": "'tacoCαt'.upperAscii() == 'TACOCαT'" + }, + { + "name": "upperascii_unicode_with_space", + "expr": "'TacoCÆt Xii'.upperAscii() == 'TACOCÆT XII'" + } + ] + }, + { + "name": "replace", + "test": [ + { + "name": "no_placeholder", + "expr": "'12 days 12 hours'.replace('{0}', '2') == '12 days 12 hours'" + }, + { + "name": "basic", + "expr": "'{0} days {0} hours'.replace('{0}', '2') == '2 days 2 hours'" + }, + { + "name": "chained", + "expr": "'{0} days {0} hours'.replace('{0}', '2', 1).replace('{0}', '23') == '2 days 23 hours'" + }, + { + "name": "unicode", + "expr": "'1 ©αT taco'.replace('αT', 'o©α') == '1 ©o©α taco'" + } + ] + }, + { + "name": "split", + "test": [ + { + "name": "empty", + "expr": "'hello world'.split(' ') == ['hello', 'world']" + }, + { + "name": "zero_limit", + "expr": "'hello world events!'.split(' ', 0) == []" + }, + { + "name": "one_limit", + "expr": "'hello world events!'.split(' ', 1) == ['hello world events!']" + }, + { + "name": "unicode_negative_limit", + "expr": "'o©o©o©o'.split('©', -1) == ['o', 'o', 'o', 'o']" + } + ] + }, + { + "name": "substring", + "test": [ + { + "name": "start", + "expr": "'tacocat'.substring(4) == 'cat'" + }, + { + "name": "start_with_max_length", + "expr": "'tacocat'.substring(7) == ''" + }, + { + "name": "start_and_end", + "expr": "'tacocat'.substring(0, 4) == 'taco'" + }, + { + "name": "start_and_end_equal_value", + "expr": "'tacocat'.substring(4, 4) == ''" + }, + { + "name": "unicode_start_and_end", + "expr": "'ta©o©αT'.substring(2, 6) == '©o©α'" + }, + { + "name": "unicode_start_and_end_equal_value", + "expr": "'ta©o©αT'.substring(7, 7) == ''" + } + ] + }, + { + "name": "trim", + "test": [ + { + "name": "blank_spaces_escaped_chars", + "expr": "' \\f\\n\\r\\t\\vtext '.trim() == 'text'" + }, + { + "name": "unicode_space_chars_1", + "expr": "'\\u0085\\u00a0\\u1680text'.trim() == 'text'" + }, + { + "name": "unicode_space_chars_2", + "expr": "'text\\u2000\\u2001\\u2002\\u2003\\u2004\\u2004\\u2006\\u2007\\u2008\\u2009'.trim() == 'text'" + }, + { + "name": "unicode_space_chars_3", + "expr": "'\\u200atext\\u2028\\u2029\\u202F\\u205F\\u3000'.trim() == 'text'" + }, + { + "name": "unicode_no_trim", + "expr": "'\\u180etext\\u200b\\u200c\\u200d\\u2060\\ufeff'.trim() == '\\u180etext\\u200b\\u200c\\u200d\\u2060\\ufeff'" + } + ] + }, + { + "name": "join", + "test": [ + { + "name": "empty_separator", + "expr": "['x', 'y'].join() == 'xy'" + }, + { + "name": "dash_separator", + "expr": "['x', 'y'].join('-') == 'x-y'" + }, + { + "name": "empty_string_empty_separator", + "expr": "[].join() == ''" + }, + { + "name": "empty_string_dash_separator", + "expr": "[].join('-') == ''" + } + ] + }, + { + "name": "quote", + "test": [ + { + "name": "multiline", + "expr": "strings.quote(\"first\\nsecond\") == \"\\\"first\\\\nsecond\\\"\"" + }, + { + "name": "escaped", + "expr": "strings.quote(\"bell\\a\") == \"\\\"bell\\\\a\\\"\"" + }, + { + "name": "backspace", + "expr": "strings.quote(\"\\bbackspace\") == \"\\\"\\\\bbackspace\\\"\"" + }, + { + "name": "form_feed", + "expr": "strings.quote(\"\\fform feed\") == \"\\\"\\\\fform feed\\\"\"" + }, + { + "name": "carriage_return", + "expr": "strings.quote(\"carriage \\r return\") == \"\\\"carriage \\\\r return\\\"\"" + }, + { + "name": "horizontal_tab", + "expr": "strings.quote(\"horizontal tab\\t\") == \"\\\"horizontal tab\\\\t\\\"\"" + }, + { + "name": "vertical_tab", + "expr": "strings.quote(\"vertical \\v tab\") == \"\\\"vertical \\\\v tab\\\"\"" + }, + { + "name": "double_slash", + "expr": "strings.quote(\"double \\\\\\\\ slash\") == \"\\\"double \\\\\\\\\\\\\\\\ slash\\\"\"" + }, + { + "name": "two_escape_sequences", + "expr": "strings.quote(\"two escape sequences \\\\a\\\\n\") == \"\\\"two escape sequences \\\\\\\\a\\\\\\\\n\\\"\"" + }, + { + "name": "verbatim", + "expr": "strings.quote(\"verbatim\") == \"\\\"verbatim\\\"\"" + }, + { + "name": "ends_with", + "expr": "strings.quote(\"ends with \\\\\") == \"\\\"ends with \\\\\\\\\\\"\"" + }, + { + "name": "starts_with", + "expr": "strings.quote(\"\\\\ starts with\") == \"\\\"\\\\\\\\ starts with\\\"\"" + }, + { + "name": "printable_unicode", + "expr": "strings.quote(\"printable unicode😀\") == \"\\\"printable unicode😀\\\"\"" + }, + { + "name": "mid_string_quote", + "expr": "strings.quote(\"mid string \\\" quote\") == \"\\\"mid string \\\\\\\" quote\\\"\"" + }, + { + "name": "single_quote_with_double_quote", + "expr": "strings.quote('single-quote with \"double quote\"') == \"\\\"single-quote with \\\\\\\"double quote\\\\\\\"\\\"\"" + }, + { + "name": "size_unicode_char", + "expr": "strings.quote(\"size('ÿ')\") == \"\\\"size('ÿ')\\\"\"" + }, + { + "name": "size_unicode_string", + "expr": "strings.quote(\"size('πέντε')\") == \"\\\"size('πέντε')\\\"\"" + }, + { + "name": "unicode", + "expr": "strings.quote(\"завтра\") == \"\\\"завтра\\\"\"" + }, + { + "name": "unicode_code_points", + "expr": "strings.quote(\"\\U0001F431\\U0001F600\\U0001F61B\")", + "value": { + "stringValue": "\"🐱😀😛\"" + } + }, + { + "name": "unicode_2", + "expr": "strings.quote(\"ta©o©αT\") == \"\\\"ta©o©αT\\\"\"" + }, + { + "name": "empty_quote", + "expr": "strings.quote(\"\")", + "value": { + "stringValue": "\"\"" + } + } + ] + }, + { + "name": "format", + "test": [ + { + "name": "no-op", + "expr": "\"no substitution\".format([])", + "value": { + "stringValue": "no substitution" + } + }, + { + "name": "mid-string substitution", + "expr": "\"str is %s and some more\".format([\"filler\"])", + "value": { + "stringValue": "str is filler and some more" + } + }, + { + "name": "percent escaping", + "expr": "\"%% and also %%\".format([])", + "value": { + "stringValue": "% and also %" + } + }, + { + "name": "substution inside escaped percent signs", + "expr": "\"%%%s%%\".format([\"text\"])", + "value": { + "stringValue": "%text%" + } + }, + { + "name": "substitution with one escaped percent sign on the right", + "expr": "\"%s%%\".format([\"percent on the right\"])", + "value": { + "stringValue": "percent on the right%" + } + }, + { + "name": "substitution with one escaped percent sign on the left", + "expr": "\"%%%s\".format([\"percent on the left\"])", + "value": { + "stringValue": "%percent on the left" + } + }, + { + "name": "multiple substitutions", + "expr": "\"%d %d %d, %s %s %s, %d %d %d, %s %s %s\".format([1, 2, 3, \"A\", \"B\", \"C\", 4, 5, 6, \"D\", \"E\", \"F\"])", + "value": { + "stringValue": "1 2 3, A B C, 4 5 6, D E F" + } + }, + { + "name": "percent sign escape sequence support", + "expr": "\"%%escaped %s%%\".format([\"percent\"])", + "value": { + "stringValue": "%escaped percent%" + } + }, + { + "name": "fixed point formatting clause", + "expr": "\"%.3f\".format([1.2345])", + "value": { + "stringValue": "1.234" + } + }, + { + "name": "binary formatting clause", + "expr": "\"this is 5 in binary: %b\".format([5])", + "value": { + "stringValue": "this is 5 in binary: 101" + } + }, + { + "name": "uint support for binary formatting", + "expr": "\"unsigned 64 in binary: %b\".format([uint(64)])", + "value": { + "stringValue": "unsigned 64 in binary: 1000000" + } + }, + { + "name": "bool support for binary formatting", + "expr": "\"bit set from bool: %b\".format([true])", + "value": { + "stringValue": "bit set from bool: 1" + } + }, + { + "name": "octal formatting clause", + "expr": "\"%o\".format([11])", + "value": { + "stringValue": "13" + } + }, + { + "name": "uint support for octal formatting clause", + "expr": "\"this is an unsigned octal: %o\".format([uint(65535)])", + "value": { + "stringValue": "this is an unsigned octal: 177777" + } + }, + { + "name": "lowercase hexadecimal formatting clause", + "expr": "\"%x is 20 in hexadecimal\".format([30])", + "value": { + "stringValue": "1e is 20 in hexadecimal" + } + }, + { + "name": "uppercase hexadecimal formatting clause", + "expr": "\"%X is 20 in hexadecimal\".format([30])", + "value": { + "stringValue": "1E is 20 in hexadecimal" + } + }, + { + "name": "unsigned support for hexadecimal formatting clause", + "expr": "\"%X is 6000 in hexadecimal\".format([uint(6000)])", + "value": { + "stringValue": "1770 is 6000 in hexadecimal" + } + }, + { + "name": "string support with hexadecimal formatting clause", + "expr": "\"%x\".format([\"Hello world!\"])", + "value": { + "stringValue": "48656c6c6f20776f726c6421" + } + }, + { + "name": "string support with uppercase hexadecimal formatting clause", + "expr": "\"%X\".format([\"Hello world!\"])", + "value": { + "stringValue": "48656C6C6F20776F726C6421" + } + }, + { + "name": "byte support with hexadecimal formatting clause", + "expr": "\"%x\".format([b\"byte string\"])", + "value": { + "stringValue": "6279746520737472696e67" + } + }, + { + "name": "byte support with uppercase hexadecimal formatting clause", + "expr": "\"%X\".format([b\"byte string\"])", + "value": { + "stringValue": "6279746520737472696E67" + } + }, + { + "name": "scientific notation formatting clause", + "expr": "\"%.6e\".format([1052.032911275])", + "value": { + "stringValue": "1.052033 × 10⁰³" + } + }, + { + "name": "default precision for fixed-point clause", + "expr": "\"%f\".format([2.71828])", + "value": { + "stringValue": "2.718280" + } + }, + { + "name": "default precision for scientific notation", + "expr": "\"%e\".format([2.71828])", + "value": { + "stringValue": "2.718280 × 10⁰⁰" + } + }, + { + "name": "unicode output for scientific notation", + "expr": "\"unescaped unicode: %e, escaped unicode: %e\".format([2.71828, 2.71828])", + "value": { + "stringValue": "unescaped unicode: 2.718280 × 10⁰⁰, escaped unicode: 2.718280 × 10⁰⁰" + } + }, + { + "name": "NaN support for fixed-point", + "expr": "\"%f\".format([\"NaN\"])", + "value": { + "stringValue": "NaN" + } + }, + { + "name": "positive infinity support for fixed-point", + "expr": "\"%f\".format([\"Infinity\"])", + "value": { + "stringValue": "∞" + } + }, + { + "name": "negative infinity support for fixed-point", + "expr": "\"%f\".format([\"-Infinity\"])", + "value": { + "stringValue": "-∞" + } + }, + { + "name": "uint support for decimal clause", + "expr": "\"%d\".format([uint(64)])", + "value": { + "stringValue": "64" + } + }, + { + "name": "null support for string", + "expr": "\"null: %s\".format([null])", + "value": { + "stringValue": "null: null" + } + }, + { + "name": "int support for string", + "expr": "\"%s\".format([999999999999])", + "value": { + "stringValue": "999999999999" + } + }, + { + "name": "bytes support for string", + "expr": "\"some bytes: %s\".format([b\"xyz\"])", + "value": { + "stringValue": "some bytes: xyz" + } + }, + { + "name": "type() support for string", + "expr": "\"type is %s\".format([type(\"test string\")])", + "value": { + "stringValue": "type is string" + } + }, + { + "name": "timestamp support for string", + "expr": "\"%s\".format([timestamp(\"2023-02-03T23:31:20+00:00\")])", + "value": { + "stringValue": "2023-02-03T23:31:20Z" + } + }, + { + "name": "duration support for string", + "expr": "\"%s\".format([duration(\"1h45m47s\")])", + "value": { + "stringValue": "6347s" + } + }, + { + "name": "list support for string", + "expr": "\"%s\".format([[\"abc\", 3.14, null, [9, 8, 7, 6], timestamp(\"2023-02-03T23:31:20Z\")]])", + "value": { + "stringValue": "[\"abc\", 3.140000, null, [9, 8, 7, 6], timestamp(\"2023-02-03T23:31:20Z\")]" + } + }, + { + "name": "map support for string", + "expr": "\"%s\".format([{\"key1\": b\"xyz\", \"key5\": null, \"key2\": duration(\"2h\"), \"key4\": true, \"key3\": 2.71828}])", + "value": { + "stringValue": "{\"key1\":b\"xyz\", \"key2\":duration(\"7200s\"), \"key3\":2.718280, \"key4\":true, \"key5\":null}" + } + }, + { + "name": "map support (all key types)", + "expr": "\"map with multiple key types: %s\".format([{1: \"value1\", uint(2): \"value2\", true: double(\"NaN\")}])", + "value": { + "stringValue": "map with multiple key types: {1:\"value1\", 2:\"value2\", true:\"NaN\"}" + } + }, + { + "name": "boolean support for %s", + "expr": "\"true bool: %s, false bool: %s\".format([true, false])", + "value": { + "stringValue": "true bool: true, false bool: false" + } + }, + { + "name": "dyntype support for string formatting clause", + "expr": "\"dynamic string: %s\".format([dyn(\"a string\")])", + "value": { + "stringValue": "dynamic string: a string" + } + }, + { + "name": "dyntype support for numbers with string formatting clause", + "expr": "\"dynIntStr: %s dynDoubleStr: %s\".format([dyn(32), dyn(56.8)])", + "value": { + "stringValue": "dynIntStr: 32 dynDoubleStr: 56.8" + } + }, + { + "name": "dyntype support for integer formatting clause", + "expr": "\"dynamic int: %d\".format([dyn(128)])", + "value": { + "stringValue": "dynamic int: 128" + } + }, + { + "name": "dyntype support for integer formatting clause (unsigned)", + "expr": "\"dynamic unsigned int: %d\".format([dyn(256u)])", + "value": { + "stringValue": "dynamic unsigned int: 256" + } + }, + { + "name": "dyntype support for hex formatting clause", + "expr": "\"dynamic hex int: %x\".format([dyn(22)])", + "value": { + "stringValue": "dynamic hex int: 16" + } + }, + { + "name": "dyntype support for hex formatting clause (uppercase)", + "expr": "\"dynamic hex int: %X (uppercase)\".format([dyn(26)])", + "value": { + "stringValue": "dynamic hex int: 1A (uppercase)" + } + }, + { + "name": "dyntype support for unsigned hex formatting clause", + "expr": "\"dynamic hex int: %x (unsigned)\".format([dyn(500u)])", + "value": { + "stringValue": "dynamic hex int: 1f4 (unsigned)" + } + }, + { + "name": "dyntype support for fixed-point formatting clause", + "expr": "\"dynamic double: %.3f\".format([dyn(4.5)])", + "value": { + "stringValue": "dynamic double: 4.500" + } + }, + { + "name": "dyntype support for scientific notation", + "expr": "\"(dyntype) e: %e\".format([dyn(2.71828)])", + "value": { + "stringValue": "(dyntype) e: 2.718280 × 10⁰⁰" + } + }, + { + "name": "dyntype NaN/infinity support for fixed-point", + "expr": "\"NaN: %f, infinity: %f\".format([dyn(\"NaN\"), dyn(\"Infinity\")])", + "value": { + "stringValue": "NaN: NaN, infinity: ∞" + } + }, + { + "name": "dyntype support for timestamp", + "expr": "\"dyntype timestamp: %s\".format([dyn(timestamp(\"2009-11-10T23:00:00Z\"))])", + "value": { + "stringValue": "dyntype timestamp: 2009-11-10T23:00:00Z" + } + }, + { + "name": "dyntype support for duration", + "expr": "\"dyntype duration: %s\".format([dyn(duration(\"8747s\"))])", + "value": { + "stringValue": "dyntype duration: 8747s" + } + }, + { + "name": "dyntype support for lists", + "expr": "\"dyntype list: %s\".format([dyn([6, 4.2, \"a string\"])])", + "value": { + "stringValue": "dyntype list: [6, 4.200000, \"a string\"]" + } + }, + { + "name": "dyntype support for maps", + "expr": "\"dyntype map: %s\".format([{\"strKey\":\"x\", 6:duration(\"422s\"), true:42}])", + "value": { + "stringValue": "dyntype map: {\"strKey\":\"x\", 6:duration(\"422s\"), true:42}" + } + }, + { + "name": "message field support", + "expr": "\"message field msg.single_int32: %d, msg.single_double: %.1f\".format([2, 1.0])", + "value": { + "stringValue": "message field msg.single_int32: 2, msg.single_double: 1.0" + } + }, + { + "name": "string substitution in a string variable", + "expr": "str_var.format([\"filler\"])", + "typeEnv": [ + { + "name": "str_var", + "ident": { + "type": { + "primitive": "STRING" + } + } + } + ], + "bindings": { + "str_var": { + "value": { + "stringValue": "str is %s and some more" + } + } + }, + "value": { + "stringValue": "str is filler and some more" + } + }, + { + "name": "multiple substitutions in a string variable", + "expr": "str_var.format([1, 2, 3, \"A\", \"B\", \"C\", 4, 5, 6, \"D\", \"E\", \"F\"])", + "typeEnv": [ + { + "name": "str_var", + "ident": { + "type": { + "primitive": "STRING" + } + } + } + ], + "bindings": { + "str_var": { + "value": { + "stringValue": "%d %d %d, %s %s %s, %d %d %d, %s %s %s" + } + } + }, + "value": { + "stringValue": "1 2 3, A B C, 4 5 6, D E F" + } + }, + { + "name": "substution inside escaped percent signs in a string variable", + "expr": "str_var.format([\"text\"])", + "typeEnv": [ + { + "name": "str_var", + "ident": { + "type": { + "primitive": "STRING" + } + } + } + ], + "bindings": { + "str_var": { + "value": { + "stringValue": "%%%s%%" + } + } + }, + "value": { + "stringValue": "%text%" + } + }, + { + "name": "fixed point formatting clause in a string variable", + "expr": "str_var.format([1.2345])", + "typeEnv": [ + { + "name": "str_var", + "ident": { + "type": { + "primitive": "STRING" + } + } + } + ], + "bindings": { + "str_var": { + "value": { + "stringValue": "%.3f" + } + } + }, + "value": { + "stringValue": "1.234" + } + }, + { + "name": "binary formatting clause in a string variable", + "expr": "str_var.format([5])", + "typeEnv": [ + { + "name": "str_var", + "ident": { + "type": { + "primitive": "STRING" + } + } + } + ], + "bindings": { + "str_var": { + "value": { + "stringValue": "this is 5 in binary: %b" + } + } + }, + "value": { + "stringValue": "this is 5 in binary: 101" + } + }, + { + "name": "scientific notation formatting clause in a string variable", + "expr": "str_var.format([1052.032911275])", + "typeEnv": [ + { + "name": "str_var", + "ident": { + "type": { + "primitive": "STRING" + } + } + } + ], + "bindings": { + "str_var": { + "value": { + "stringValue": "%.6e" + } + } + }, + "value": { + "stringValue": "1.052033 × 10⁰³" + } + }, + { + "name": "default precision for fixed-point clause in a string variable", + "expr": "str_var.format([2.71828])", + "typeEnv": [ + { + "name": "str_var", + "ident": { + "type": { + "primitive": "STRING" + } + } + } + ], + "bindings": { + "str_var": { + "value": { + "stringValue": "%f" + } + } + }, + "value": { + "stringValue": "2.718280" + } + } + ] + }, + { + "name": "format_errors", + "test": [ + { + "name": "multiline", + "expr": "strings.quote(\"first\\nsecond\") == \"\\\"first\\\\nsecond\\\"\"" + }, + { + "name": "unrecognized formatting clause", + "expr": "\"%a\".format([1])", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "could not parse formatting clause: unrecognized formatting clause \"a\"" + } + ] + } + }, + { + "name": "out of bounds arg index", + "expr": "\"%d %d %d\".format([0, 1])", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "index 2 out of range" + } + ] + } + }, + { + "name": "string substitution is not allowed with binary clause", + "expr": "\"string is %b\".format([\"abc\"])", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "error during formatting: only integers and bools can be formatted as binary, was given string" + } + ] + } + }, + { + "name": "duration substitution not allowed with decimal clause", + "expr": "\"%d\".format([duration(\"30m2s\")])", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "error during formatting: decimal clause can only be used on integers, was given google.protobuf.Duration" + } + ] + } + }, + { + "name": "string substitution not allowed with octal clause", + "expr": "\"octal: %o\".format([\"a string\"])", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "error during formatting: octal clause can only be used on integers, was given string" + } + ] + } + }, + { + "name": "double substitution not allowed with hex clause", + "expr": "\"double is %x\".format([0.5])", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "error during formatting: only integers, byte buffers, and strings can be formatted as hex, was given double" + } + ] + } + }, + { + "name": "uppercase not allowed for scientific clause", + "expr": "\"double is %E\".format([0.5])", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "could not parse formatting clause: unrecognized formatting clause \"E\"" + } + ] + } + }, + { + "name": "object not allowed", + "expr": "\"object is %s\".format([google.api.expr.test.v1.proto3.TestAllTypes{}])", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "error during formatting: string clause can only be used on strings, bools, bytes, ints, doubles, maps, lists, types, durations, and timestamps, was given google.api.expr.test.v1.proto3.TestAllTypes" + } + ] + } + }, + { + "name": "object inside list", + "expr": "\"%s\".format([[1, 2, google.api.expr.test.v1.proto3.TestAllTypes{}]])", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "error during formatting: string clause can only be used on strings, bools, bytes, ints, doubles, maps, lists, types, durations, and timestamps, was given google.api.expr.test.v1.proto3.TestAllTypes" + } + ] + } + }, + { + "name": "object inside map", + "expr": "\"%s\".format([{1: \"a\", 2: google.api.expr.test.v1.proto3.TestAllTypes{}}])", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "error during formatting: string clause can only be used on strings, bools, bytes, ints, doubles, maps, lists, types, durations, and timestamps, was given google.api.expr.test.v1.proto3.TestAllTypes" + } + ] + } + }, + { + "name": "null not allowed for %d", + "expr": "\"null: %d\".format([null])", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "error during formatting: decimal clause can only be used on integers, was given null_type" + } + ] + } + }, + { + "name": "null not allowed for %e", + "expr": "\"null: %e\".format([null])", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "error during formatting: scientific clause can only be used on doubles, was given null_type" + } + ] + } + }, + { + "name": "null not allowed for %f", + "expr": "\"null: %f\".format([null])", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "error during formatting: fixed-point clause can only be used on doubles, was given null_type" + } + ] + } + }, + { + "name": "null not allowed for %x", + "expr": "\"null: %x\".format([null])", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "error during formatting: only integers, byte buffers, and strings can be formatted as hex, was given null_type" + } + ] + } + }, + { + "name": "null not allowed for %X", + "expr": "\"null: %X\".format([null])", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "error during formatting: only integers, byte buffers, and strings can be formatted as hex, was given null_type" + } + ] + } + }, + { + "name": "null not allowed for %b", + "expr": "\"null: %b\".format([null])", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "error during formatting: only integers and bools can be formatted as binary, was given null_type" + } + ] + } + }, + { + "name": "null not allowed for %o", + "expr": "\"null: %o\".format([null])", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "error during formatting: octal clause can only be used on integers, was given null_type" + } + ] + } + } + ] + }, + { + "name": "value_errors", + "test": [ + { + "name": "charat_out_of_range", + "expr": "'tacocat'.charAt(30) == ''", + "evalError": { + "errors": [ + { + "message": "index out of range: 30" + } + ] + } + }, + { + "name": "indexof_out_of_range", + "expr": "'tacocat'.indexOf('a', 30) == -1", + "evalError": { + "errors": [ + { + "message": "index out of range: 30" + } + ] + } + }, + { + "name": "lastindexof_negative_index", + "expr": "'tacocat'.lastIndexOf('a', -1) == -1", + "evalError": { + "errors": [ + { + "message": "index out of range: -1" + } + ] + } + }, + { + "name": "lastindexof_out_of_range", + "expr": "'tacocat'.lastIndexOf('a', 30) == -1", + "evalError": { + "errors": [ + { + "message": "index out of range: 30" + } + ] + } + }, + { + "name": "substring_out_of_range", + "expr": "'tacocat'.substring(40) == 'cat'", + "evalError": { + "errors": [ + { + "message": "index out of range: 40" + } + ] + } + }, + { + "name": "substring_negative_index", + "expr": "'tacocat'.substring(-1) == 'cat'", + "evalError": { + "errors": [ + { + "message": "index out of range: -1" + } + ] + } + }, + { + "name": "substring_end_index_out_of_range", + "expr": "'tacocat'.substring(1, 50) == 'cat'", + "evalError": { + "errors": [ + { + "message": "index out of range: 50" + } + ] + } + }, + { + "name": "substring_begin_index_out_of_range", + "expr": "'tacocat'.substring(49, 50) == 'cat'", + "evalError": { + "errors": [ + { + "message": "index out of range: 49" + } + ] + } + }, + { + "name": "substring_end_index_greater_than_begin_index", + "expr": "'tacocat'.substring(4, 3) == ''", + "evalError": { + "errors": [ + { + "message": "invalid substring range. start: 4, end: 3" + } + ] + } + } + ] + }, + { + "name": "type_errors", + "test": [ + { + "name": "charat_invalid_type", + "expr": "42.charAt(2) == ''", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "charat_invalid_argument", + "expr": "'hello'.charAt(true) == ''", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "indexof_unary_invalid_type", + "expr": "24.indexOf('2') == 0", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "indexof_unary_invalid_argument", + "expr": "'hello'.indexOf(true) == 1", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "indexof_binary_invalid_argument", + "expr": "42.indexOf('4', 0) == 0", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "indexof_binary_invalid_argument_2", + "expr": "'42'.indexOf(4, 0) == 0", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "indexof_binary_both_invalid_arguments", + "expr": "'42'.indexOf('4', '0') == 0", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "indexof_ternary_invalid_arguments", + "expr": "'42'.indexOf('4', 0, 1) == 0", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "split_invalid_type", + "expr": "42.split('2') == ['4']", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "replace_invalid_type", + "expr": "42.replace(2, 1) == '41'", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "replace_binary_invalid_argument", + "expr": "'42'.replace(2, 1) == '41'", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "replace_binary_invalid_argument_2", + "expr": "'42'.replace('2', 1) == '41'", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "replace_ternary_invalid_argument", + "expr": "42.replace('2', '1', 1) == '41'", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "replace_ternary_invalid_argument_2", + "expr": "'42'.replace(2, '1', 1) == '41'", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "replace_ternary_invalid_argument_3", + "expr": "'42'.replace('2', 1, 1) == '41'", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "replace_ternary_invalid_argument_4", + "expr": "'42'.replace('2', '1', '1') == '41'", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "replace_quaternary_invalid_argument", + "expr": "'42'.replace('2', '1', 1, false) == '41'", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "split_invalid_type_empty_arg", + "expr": "42.split('') == ['4', '2']", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "split_invalid_argument", + "expr": "'42'.split(2) == ['4']", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "split_binary_invalid_type", + "expr": "42.split('2', '1') == ['4']", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "split_binary_invalid_argument", + "expr": "'42'.split(2, 1) == ['4']", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "split_binary_invalid_argument_2", + "expr": "'42'.split('2', '1') == ['4']", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "split_ternary_invalid_argument", + "expr": "'42'.split('2', 1, 1) == ['4']", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "substring_ternary_invalid_argument", + "expr": "'hello'.substring(1, 2, 3) == ''", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "substring_binary_invalid_type", + "expr": "30.substring(true, 3) == ''", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "substring_binary_invalid_argument", + "expr": "'tacocat'.substring(true, 3) == ''", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + }, + { + "name": "substring_binary_invalid_argument_2", + "expr": "'tacocat'.substring(0, false) == ''", + "disableCheck": true, + "evalError": { + "errors": [ + { + "message": "no such overload" + } + ] + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/string_ext.textproto b/packages/cel/src/lib/conformance/testdata/string_ext.textproto new file mode 100644 index 0000000..a87c950 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/string_ext.textproto @@ -0,0 +1,1391 @@ +name: "string_ext" +description: "Tests for the strings extension library." +section: { + name: "char_at" + test: { + name: "middle_index" + expr: "'tacocat'.charAt(3)" + value: { + string_value: "o" + } + } + test: { + name: "end_index" + expr: "'tacocat'.charAt(7)" + value: { + string_value: "" + } + } + test: { + name: "multiple" + expr: "'©αT'.charAt(0) == '©' && '©αT'.charAt(1) == 'α' && '©αT'.charAt(2) == 'T'" + } +} +section: { + name: "index_of" + test: { + name: "empty_index" + expr: "'tacocat'.indexOf('')" + value: { + int64_value: 0 + } + } + test: { + name: "string_index" + expr: "'tacocat'.indexOf('ac')" + value: { + int64_value: 1 + } + } + test: { + name: "nomatch" + expr: "'tacocat'.indexOf('none') == -1" + } + test: { + name: "empty_index" + expr: "'tacocat'.indexOf('', 3) == 3" + } + test: { + name: "char_index" + expr: "'tacocat'.indexOf('a', 3) == 5" + } + test: { + name: "string_index" + expr: "'tacocat'.indexOf('at', 3) == 5" + } + test: { + name: "unicode_char" + expr: "'ta©o©αT'.indexOf('©') == 2" + } + test: { + name: "unicode_char_index" + expr: "'ta©o©αT'.indexOf('©', 3) == 4" + } + test: { + name: "unicode_string_index" + expr: "'ta©o©αT'.indexOf('©αT', 3) == 4" + } + test: { + name: "unicode_string_nomatch_index" + expr: "'ta©o©αT'.indexOf('©α', 5) == -1" + } + test: { + name: "char_index" + expr: "'ijk'.indexOf('k') == 2" + } + test: { + name: "string_with_space_fullmatch" + expr: "'hello wello'.indexOf('hello wello') == 0" + } + test: { + name: "string_with_space_index" + expr: "'hello wello'.indexOf('ello', 6) == 7" + } + test: { + name: "string_nomatch_index" + expr: "'hello wello'.indexOf('elbo room!!') == -1" + } +} +section: { + name: "last_index_of" + test: { + name: "empty" + expr: "'tacocat'.lastIndexOf('') == 7" + } + test: { + name: "string" + expr: "'tacocat'.lastIndexOf('at') == 5" + } + test: { + name: "string_nomatch" + expr: "'tacocat'.lastIndexOf('none') == -1" + } + test: { + name: "empty_index" + expr: "'tacocat'.lastIndexOf('', 3) == 3" + } + test: { + name: "char_index" + expr: "'tacocat'.lastIndexOf('a', 3) == 1" + } + test: { + name: "unicode_char" + expr: "'ta©o©αT'.lastIndexOf('©') == 4" + } + test: { + name: "unicode_char_index" + expr: "'ta©o©αT'.lastIndexOf('©', 3) == 2" + } + test: { + name: "unicode_string_index" + expr: "'ta©o©αT'.lastIndexOf('©α', 4) == 4" + } + test: { + name: "string_with_space_string_index" + expr: "'hello wello'.lastIndexOf('ello', 6) == 1" + } + test: { + name: "string_with_space_string_nomatch" + expr: "'hello wello'.lastIndexOf('low') == -1" + } + test: { + name: "string_with_space_string_with_space_nomatch" + expr: "'hello wello'.lastIndexOf('elbo room!!') == -1" + } + test: { + name: "string_with_space_fullmatch" + expr: "'hello wello'.lastIndexOf('hello wello') == 0" + } + test: { + name: "repeated_string" + expr: "'bananananana'.lastIndexOf('nana', 7) == 6" + } +} +section: { + name: "ascii_casing" + test: { + name: "lowerascii" + expr: "'TacoCat'.lowerAscii() == 'tacocat'" + } + test: { + name: "lowerascii_unicode" + expr: "'TacoCÆt'.lowerAscii() == 'tacocÆt'" + } + test: { + name: "lowerascii_unicode_with_space" + expr: "'TacoCÆt Xii'.lowerAscii() == 'tacocÆt xii'" + } + test: { + name: "upperascii" + expr: "'tacoCat'.upperAscii() == 'TACOCAT'" + } + test: { + name: "upperascii_unicode" + expr: "'tacoCαt'.upperAscii() == 'TACOCαT'" + } + test: { + name: "upperascii_unicode_with_space" + expr: "'TacoCÆt Xii'.upperAscii() == 'TACOCÆT XII'" + } +} +section: { + name: "replace" + test: { + name: "no_placeholder" + expr: "'12 days 12 hours'.replace('{0}', '2') == '12 days 12 hours'" + } + test: { + name: "basic" + expr: "'{0} days {0} hours'.replace('{0}', '2') == '2 days 2 hours'" + } + test: { + name: "chained" + expr: "'{0} days {0} hours'.replace('{0}', '2', 1).replace('{0}', '23') == '2 days 23 hours'" + } + test: { + name: "unicode" + expr: "'1 ©αT taco'.replace('αT', 'o©α') == '1 ©o©α taco'" + } +} +section: { + name: "split" + test: { + name: "empty" + expr: "'hello world'.split(' ') == ['hello', 'world']" + } + test: { + name: "zero_limit" + expr: "'hello world events!'.split(' ', 0) == []" + } + test: { + name: "one_limit" + expr: "'hello world events!'.split(' ', 1) == ['hello world events!']" + } + test: { + name: "unicode_negative_limit" + expr: "'o©o©o©o'.split('©', -1) == ['o', 'o', 'o', 'o']" + } +} +section: { + name: "substring" + test: { + name: "start" + expr: "'tacocat'.substring(4) == 'cat'" + } + test: { + name: "start_with_max_length" + expr: "'tacocat'.substring(7) == ''" + } + test: { + name: "start_and_end" + expr: "'tacocat'.substring(0, 4) == 'taco'" + } + test: { + name: "start_and_end_equal_value" + expr: "'tacocat'.substring(4, 4) == ''" + } + test: { + name: "unicode_start_and_end" + expr: "'ta©o©αT'.substring(2, 6) == '©o©α'" + } + test: { + name: "unicode_start_and_end_equal_value" + expr: "'ta©o©αT'.substring(7, 7) == ''" + } +} +section: { + name: "trim" + test: { + name: "blank_spaces_escaped_chars" + expr: "' \\f\\n\\r\\t\\vtext '.trim() == 'text'" + } + test: { + name: "unicode_space_chars_1" + expr: "'\\u0085\\u00a0\\u1680text'.trim() == 'text'" + } + test: { + name: "unicode_space_chars_2" + expr: "'text\\u2000\\u2001\\u2002\\u2003\\u2004\\u2004\\u2006\\u2007\\u2008\\u2009'.trim() == 'text'" + } + test: { + name: "unicode_space_chars_3" + expr: "'\\u200atext\\u2028\\u2029\\u202F\\u205F\\u3000'.trim() == 'text'" + } + test: { + name: "unicode_no_trim" + expr: "'\\u180etext\\u200b\\u200c\\u200d\\u2060\\ufeff'.trim() == '\\u180etext\\u200b\\u200c\\u200d\\u2060\\ufeff'" + } +} +section: { + name: "join" + test: { + name: "empty_separator" + expr: "['x', 'y'].join() == 'xy'" + } + test: { + name: "dash_separator" + expr: "['x', 'y'].join('-') == 'x-y'" + } + test: { + name: "empty_string_empty_separator" + expr: "[].join() == ''" + } + test: { + name: "empty_string_dash_separator" + expr: "[].join('-') == ''" + } +} +section: { + name: "quote" + test: { + name: "multiline" + expr: "strings.quote(\"first\\nsecond\") == \"\\\"first\\\\nsecond\\\"\"" + } + test: { + name: "escaped" + expr: "strings.quote(\"bell\\a\") == \"\\\"bell\\\\a\\\"\"" + } + test: { + name: "backspace" + expr: "strings.quote(\"\\bbackspace\") == \"\\\"\\\\bbackspace\\\"\"" + } + test: { + name: "form_feed" + expr: "strings.quote(\"\\fform feed\") == \"\\\"\\\\fform feed\\\"\"" + } + test: { + name: "carriage_return" + expr: "strings.quote(\"carriage \\r return\") == \"\\\"carriage \\\\r return\\\"\"" + } + test: { + name: "horizontal_tab" + expr: "strings.quote(\"horizontal tab\\t\") == \"\\\"horizontal tab\\\\t\\\"\"" + } + test: { + name: "vertical_tab" + expr: "strings.quote(\"vertical \\v tab\") == \"\\\"vertical \\\\v tab\\\"\"" + } + test: { + name: "double_slash" + expr: "strings.quote(\"double \\\\\\\\ slash\") == \"\\\"double \\\\\\\\\\\\\\\\ slash\\\"\"" + } + test: { + name: "two_escape_sequences" + expr: "strings.quote(\"two escape sequences \\\\a\\\\n\") == \"\\\"two escape sequences \\\\\\\\a\\\\\\\\n\\\"\"" + } + test: { + name: "verbatim" + expr: "strings.quote(\"verbatim\") == \"\\\"verbatim\\\"\"" + } + test: { + name: "ends_with" + expr: "strings.quote(\"ends with \\\\\") == \"\\\"ends with \\\\\\\\\\\"\"" + } + test: { + name: "starts_with" + expr: "strings.quote(\"\\\\ starts with\") == \"\\\"\\\\\\\\ starts with\\\"\"" + } + test: { + name: "printable_unicode" + expr: "strings.quote(\"printable unicode😀\") == \"\\\"printable unicode😀\\\"\"" + } + test: { + name: "mid_string_quote" + expr: "strings.quote(\"mid string \\\" quote\") == \"\\\"mid string \\\\\\\" quote\\\"\"" + } + test: { + name: "single_quote_with_double_quote" + expr: "strings.quote('single-quote with \"double quote\"') == \"\\\"single-quote with \\\\\\\"double quote\\\\\\\"\\\"\"" + } + test: { + name: "size_unicode_char" + expr: "strings.quote(\"size('ÿ')\") == \"\\\"size('ÿ')\\\"\"" + } + test: { + name: "size_unicode_string" + expr: "strings.quote(\"size('πέντε')\") == \"\\\"size('πέντε')\\\"\"" + } + test: { + name: "unicode" + expr: "strings.quote(\"завтра\") == \"\\\"завтра\\\"\"" + } + test: { + name: "unicode_code_points" + expr: "strings.quote(\"\\U0001F431\\U0001F600\\U0001F61B\")" + value: { + string_value: "\"🐱😀😛\"" + } + } + test: { + name: "unicode_2" + expr: "strings.quote(\"ta©o©αT\") == \"\\\"ta©o©αT\\\"\"" + } + test: { + name: "empty_quote" + expr: "strings.quote(\"\")" + value: { + string_value: "\"\"" + } + } +} +section: { + name: "format" + test: { + name: "no-op" + expr: '"no substitution".format([])' + value: { + string_value: 'no substitution', + } + } + test: { + name: "mid-string substitution" + expr: '"str is %s and some more".format(["filler"])' + value: { + string_value: 'str is filler and some more', + } + } + test: { + name: "percent escaping" + expr: '"%% and also %%".format([])' + value: { + string_value: '% and also %', + } + } + test: { + name: "substution inside escaped percent signs" + expr: '"%%%s%%".format(["text"])' + value: { + string_value: '%text%', + } + } + test: { + name: "substitution with one escaped percent sign on the right" + expr: '"%s%%".format(["percent on the right"])' + value: { + string_value: 'percent on the right%', + } + } + test: { + name: "substitution with one escaped percent sign on the left" + expr: '"%%%s".format(["percent on the left"])' + value: { + string_value: '%percent on the left', + } + } + test: { + name: "multiple substitutions" + expr: '"%d %d %d, %s %s %s, %d %d %d, %s %s %s".format([1, 2, 3, "A", "B", "C", 4, 5, 6, "D", "E", "F"])' + value: { + string_value: '1 2 3, A B C, 4 5 6, D E F', + } + } + test: { + name: "percent sign escape sequence support" + expr: '"%%escaped %s%%".format(["percent"])' + value: { + string_value: '%escaped percent%', + } + } + test: { + name: "fixed point formatting clause" + expr: '"%.3f".format([1.2345])' + value: { + string_value: '1.234', + } + } + test: { + name: "binary formatting clause" + expr: '"this is 5 in binary: %b".format([5])' + value: { + string_value: 'this is 5 in binary: 101', + } + } + test: { + name: "uint support for binary formatting" + expr: '"unsigned 64 in binary: %b".format([uint(64)])' + value: { + string_value: 'unsigned 64 in binary: 1000000', + } + } + test: { + name: "bool support for binary formatting" + expr: '"bit set from bool: %b".format([true])' + value: { + string_value: 'bit set from bool: 1', + } + } + test: { + name: "octal formatting clause" + expr: '"%o".format([11])' + value: { + string_value: '13', + } + } + test: { + name: "uint support for octal formatting clause" + expr: '"this is an unsigned octal: %o".format([uint(65535)])' + value: { + string_value: 'this is an unsigned octal: 177777', + } + } + test: { + name: "lowercase hexadecimal formatting clause" + expr: '"%x is 20 in hexadecimal".format([30])' + value: { + string_value: '1e is 20 in hexadecimal', + } + } + test: { + name: "uppercase hexadecimal formatting clause" + expr: '"%X is 20 in hexadecimal".format([30])' + value: { + string_value: '1E is 20 in hexadecimal', + } + } + test: { + name: "unsigned support for hexadecimal formatting clause" + expr: '"%X is 6000 in hexadecimal".format([uint(6000)])' + value: { + string_value: '1770 is 6000 in hexadecimal', + } + } + test: { + name: "string support with hexadecimal formatting clause" + expr: '"%x".format(["Hello world!"])' + value: { + string_value: '48656c6c6f20776f726c6421', + } + } + test: { + name: "string support with uppercase hexadecimal formatting clause" + expr: '"%X".format(["Hello world!"])' + value: { + string_value: '48656C6C6F20776F726C6421', + } + } + test: { + name: "byte support with hexadecimal formatting clause" + expr: '"%x".format([b"byte string"])' + value: { + string_value: '6279746520737472696e67', + } + } + test: { + name: "byte support with uppercase hexadecimal formatting clause" + expr: '"%X".format([b"byte string"])' + value: { + string_value: '6279746520737472696E67', + } + } + test: { + name: "scientific notation formatting clause" + expr: '"%.6e".format([1052.032911275])' + value: { + string_value: '1.052033 × 10⁰³', + } + } + test: { + name: "default precision for fixed-point clause" + expr: '"%f".format([2.71828])' + value: { + string_value: '2.718280', + } + } + test: { + name: "default precision for scientific notation" + expr: '"%e".format([2.71828])' + value: { + string_value: '2.718280 × 10⁰⁰', + } + } + test: { + name: "unicode output for scientific notation" + expr: '"unescaped unicode: %e, escaped unicode: %e".format([2.71828, 2.71828])' + value: { + string_value: 'unescaped unicode: 2.718280 × 10⁰⁰, escaped unicode: 2.718280\u202f\u00d7\u202f10\u2070\u2070', + } + } + test: { + name: "NaN support for fixed-point" + expr: '"%f".format(["NaN"])' + value: { + string_value: 'NaN', + } + } + test: { + name: "positive infinity support for fixed-point" + expr: '"%f".format(["Infinity"])' + value: { + string_value: '∞', + } + } + test: { + name: "negative infinity support for fixed-point" + expr: '"%f".format(["-Infinity"])' + value: { + string_value: '-∞', + } + } + test: { + name: "uint support for decimal clause" + expr: '"%d".format([uint(64)])' + value: { + string_value: '64', + } + } + test: { + name: "null support for string" + expr: '"null: %s".format([null])' + value: { + string_value: 'null: null', + } + } + test: { + name: "int support for string" + expr: '"%s".format([999999999999])' + value: { + string_value: '999999999999', + } + } + test: { + name: "bytes support for string" + expr: '"some bytes: %s".format([b"xyz"])' + value: { + string_value: 'some bytes: xyz', + } + } + test: { + name: "type() support for string" + expr: '"type is %s".format([type("test string")])' + value: { + string_value: 'type is string', + } + } + test: { + name: "timestamp support for string" + expr: '"%s".format([timestamp("2023-02-03T23:31:20+00:00")])' + value: { + string_value: '2023-02-03T23:31:20Z', + } + } + test: { + name: "duration support for string" + expr: '"%s".format([duration("1h45m47s")])' + value: { + string_value: '6347s', + } + } + test: { + name: "list support for string" + expr: '"%s".format([["abc", 3.14, null, [9, 8, 7, 6], timestamp("2023-02-03T23:31:20Z")]])' + value: { + string_value: '["abc", 3.140000, null, [9, 8, 7, 6], timestamp("2023-02-03T23:31:20Z")]', + } + } + test: { + name: "map support for string" + expr: '"%s".format([{"key1": b"xyz", "key5": null, "key2": duration("2h"), "key4": true, "key3": 2.71828}])' + value: { + string_value: '{"key1":b"xyz", "key2":duration("7200s"), "key3":2.718280, "key4":true, "key5":null}', + } + } + test: { + name: "map support (all key types)" + expr: '"map with multiple key types: %s".format([{1: "value1", uint(2): "value2", true: double("NaN")}])' + value: { + string_value: 'map with multiple key types: {1:"value1", 2:"value2", true:"NaN"}', + } + } + test: { + name: "boolean support for %s" + expr: '"true bool: %s, false bool: %s".format([true, false])' + value: { + string_value: 'true bool: true, false bool: false', + } + } + test: { + name: "dyntype support for string formatting clause" + expr: '"dynamic string: %s".format([dyn("a string")])' + value: { + string_value: 'dynamic string: a string', + } + } + test: { + name: "dyntype support for numbers with string formatting clause" + expr: '"dynIntStr: %s dynDoubleStr: %s".format([dyn(32), dyn(56.8)])' + value: { + string_value: 'dynIntStr: 32 dynDoubleStr: 56.8', + } + } + test: { + name: "dyntype support for integer formatting clause" + expr: '"dynamic int: %d".format([dyn(128)])' + value: { + string_value: 'dynamic int: 128', + } + } + test: { + name: "dyntype support for integer formatting clause (unsigned)" + expr: '"dynamic unsigned int: %d".format([dyn(256u)])' + value: { + string_value: 'dynamic unsigned int: 256', + } + } + test: { + name: "dyntype support for hex formatting clause" + expr: '"dynamic hex int: %x".format([dyn(22)])' + value: { + string_value: 'dynamic hex int: 16', + } + } + test: { + name: "dyntype support for hex formatting clause (uppercase)" + expr: '"dynamic hex int: %X (uppercase)".format([dyn(26)])' + value: { + string_value: 'dynamic hex int: 1A (uppercase)', + } + } + test: { + name: "dyntype support for unsigned hex formatting clause" + expr: '"dynamic hex int: %x (unsigned)".format([dyn(500u)])' + value: { + string_value: 'dynamic hex int: 1f4 (unsigned)', + } + } + test: { + name: "dyntype support for fixed-point formatting clause" + expr: '"dynamic double: %.3f".format([dyn(4.5)])' + value: { + string_value: 'dynamic double: 4.500', + } + } + test: { + name: "dyntype support for scientific notation" + expr: '"(dyntype) e: %e".format([dyn(2.71828)])' + value: { + string_value: '(dyntype) e: 2.718280 × 10⁰⁰', + } + } + test: { + name: "dyntype NaN/infinity support for fixed-point" + expr: '"NaN: %f, infinity: %f".format([dyn("NaN"), dyn("Infinity")])' + value: { + string_value: 'NaN: NaN, infinity: ∞', + } + } + test: { + name: "dyntype support for timestamp" + expr: '"dyntype timestamp: %s".format([dyn(timestamp("2009-11-10T23:00:00Z"))])' + value: { + string_value: 'dyntype timestamp: 2009-11-10T23:00:00Z', + } + } + test: { + name: "dyntype support for duration" + expr: '"dyntype duration: %s".format([dyn(duration("8747s"))])' + value: { + string_value: 'dyntype duration: 8747s', + } + } + test: { + name: "dyntype support for lists" + expr: '"dyntype list: %s".format([dyn([6, 4.2, "a string"])])' + value: { + string_value: 'dyntype list: [6, 4.200000, "a string"]', + } + } + test: { + name: "dyntype support for maps" + expr: '"dyntype map: %s".format([{"strKey":"x", 6:duration("422s"), true:42}])' + value: { + string_value: 'dyntype map: {"strKey":"x", 6:duration("422s"), true:42}', + } + } + test: { + name: "message field support" + expr: '"message field msg.single_int32: %d, msg.single_double: %.1f".format([2, 1.0])' + value: { + string_value: 'message field msg.single_int32: 2, msg.single_double: 1.0', + } + } + test: { + name: "string substitution in a string variable" + expr: 'str_var.format(["filler"])' + type_env: { + name: "str_var", + ident: { type: { primitive: STRING } } + } + bindings: { + key: "str_var" + value: { value: { string_value: "str is %s and some more" } } + } + value: { + string_value: 'str is filler and some more', + } + } + test: { + name: "multiple substitutions in a string variable" + expr: 'str_var.format([1, 2, 3, "A", "B", "C", 4, 5, 6, "D", "E", "F"])' + type_env: { + name: "str_var", + ident: { type: { primitive: STRING } } + } + bindings: { + key: "str_var" + value: { value: { string_value: "%d %d %d, %s %s %s, %d %d %d, %s %s %s" } } + } + value: { + string_value: '1 2 3, A B C, 4 5 6, D E F', + } + } + test: { + name: "substution inside escaped percent signs in a string variable" + expr: 'str_var.format(["text"])' + type_env: { + name: "str_var", + ident: { type: { primitive: STRING } } + } + bindings: { + key: "str_var" + value: { value: { string_value: "%%%s%%" } } + } + value: { + string_value: '%text%', + } + } + test: { + name: "fixed point formatting clause in a string variable" + expr: 'str_var.format([1.2345])' + type_env: { + name: "str_var", + ident: { type: { primitive: STRING } } + } + bindings: { + key: "str_var" + value: { value: { string_value: "%.3f" } } + } + value: { + string_value: '1.234', + } + } + test: { + name: "binary formatting clause in a string variable" + expr: 'str_var.format([5])' + type_env: { + name: "str_var", + ident: { type: { primitive: STRING } } + } + bindings: { + key: "str_var" + value: { value: { string_value: "this is 5 in binary: %b" } } + } + value: { + string_value: 'this is 5 in binary: 101', + } + } + test: { + name: "scientific notation formatting clause in a string variable" + expr: 'str_var.format([1052.032911275])' + type_env: { + name: "str_var", + ident: { type: { primitive: STRING } } + } + bindings: { + key: "str_var" + value: { value: { string_value: "%.6e" } } + } + value: { + string_value: '1.052033 × 10⁰³', + } + } + test: { + name: "default precision for fixed-point clause in a string variable" + expr: 'str_var.format([2.71828])' + type_env: { + name: "str_var", + ident: { type: { primitive: STRING } } + } + bindings: { + key: "str_var" + value: { value: { string_value: "%f" } } + } + value: { + string_value: '2.718280', + } + } +} +section: { + name: "format_errors" + test: { + name: "multiline" + expr: "strings.quote(\"first\\nsecond\") == \"\\\"first\\\\nsecond\\\"\"" + } + test: { + name: "unrecognized formatting clause" + expr: '"%a".format([1])' + disable_check: true + eval_error: { + errors: { + message: 'could not parse formatting clause: unrecognized formatting clause "a"' + } + } + } + test: { + name: "out of bounds arg index" + expr: '"%d %d %d".format([0, 1])' + disable_check: true + eval_error: { + errors: { + message: 'index 2 out of range' + } + } + } + test: { + name: "string substitution is not allowed with binary clause" + expr: '"string is %b".format(["abc"])' + disable_check: true + eval_error: { + errors: { + message: 'error during formatting: only integers and bools can be formatted as binary, was given string' + } + } + } + test: { + name: "duration substitution not allowed with decimal clause" + expr: '"%d".format([duration("30m2s")])' + disable_check: true + eval_error: { + errors: { + message: 'error during formatting: decimal clause can only be used on integers, was given google.protobuf.Duration' + } + } + } + test: { + name: "string substitution not allowed with octal clause" + expr: '"octal: %o".format(["a string"])' + disable_check: true + eval_error: { + errors: { + message: 'error during formatting: octal clause can only be used on integers, was given string' + } + } + } + test: { + name: "double substitution not allowed with hex clause" + expr: '"double is %x".format([0.5])' + disable_check: true + eval_error: { + errors: { + message: 'error during formatting: only integers, byte buffers, and strings can be formatted as hex, was given double' + } + } + } + test: { + name: "uppercase not allowed for scientific clause" + expr: '"double is %E".format([0.5])' + disable_check: true + eval_error: { + errors: { + message: 'could not parse formatting clause: unrecognized formatting clause "E"' + } + } + } + test: { + name: "object not allowed" + expr: '"object is %s".format([google.api.expr.test.v1.proto3.TestAllTypes{}])' + disable_check: true + eval_error: { + errors: { + message: 'error during formatting: string clause can only be used on strings, bools, bytes, ints, doubles, maps, lists, types, durations, and timestamps, was given google.api.expr.test.v1.proto3.TestAllTypes' + } + } + } + test: { + name: "object inside list" + expr: '"%s".format([[1, 2, google.api.expr.test.v1.proto3.TestAllTypes{}]])' + disable_check: true + eval_error: { + errors: { + message: 'error during formatting: string clause can only be used on strings, bools, bytes, ints, doubles, maps, lists, types, durations, and timestamps, was given google.api.expr.test.v1.proto3.TestAllTypes' + } + } + } + test: { + name: "object inside map" + expr: '"%s".format([{1: "a", 2: google.api.expr.test.v1.proto3.TestAllTypes{}}])' + disable_check: true + eval_error: { + errors: { + message: 'error during formatting: string clause can only be used on strings, bools, bytes, ints, doubles, maps, lists, types, durations, and timestamps, was given google.api.expr.test.v1.proto3.TestAllTypes' + } + } + } + test: { + name: "null not allowed for %d" + expr: '"null: %d".format([null])' + disable_check: true + eval_error: { + errors: { + message: 'error during formatting: decimal clause can only be used on integers, was given null_type' + } + } + } + test: { + name: "null not allowed for %e" + expr: '"null: %e".format([null])' + disable_check: true + eval_error: { + errors: { + message: 'error during formatting: scientific clause can only be used on doubles, was given null_type' + } + } + } + test: { + name: "null not allowed for %f" + expr: '"null: %f".format([null])' + disable_check: true + eval_error: { + errors: { + message: 'error during formatting: fixed-point clause can only be used on doubles, was given null_type' + } + } + } + test: { + name: "null not allowed for %x" + expr: '"null: %x".format([null])' + disable_check: true + eval_error: { + errors: { + message: 'error during formatting: only integers, byte buffers, and strings can be formatted as hex, was given null_type' + } + } + } + test: { + name: "null not allowed for %X" + expr: '"null: %X".format([null])' + disable_check: true + eval_error: { + errors: { + message: 'error during formatting: only integers, byte buffers, and strings can be formatted as hex, was given null_type' + } + } + } + test: { + name: "null not allowed for %b" + expr: '"null: %b".format([null])' + disable_check: true + eval_error: { + errors: { + message: 'error during formatting: only integers and bools can be formatted as binary, was given null_type' + } + } + } + test: { + name: "null not allowed for %o" + expr: '"null: %o".format([null])' + disable_check: true + eval_error: { + errors: { + message: 'error during formatting: octal clause can only be used on integers, was given null_type' + } + } + } +} +section: { + name: "value_errors" + test: { + name: "charat_out_of_range" + expr: "'tacocat'.charAt(30) == ''" + eval_error: { + errors: { + message: "index out of range: 30" + } + } + } + test: { + name: "indexof_out_of_range" + expr: "'tacocat'.indexOf('a', 30) == -1" + eval_error: { + errors: { + message: "index out of range: 30" + } + } + } + test: { + name: "lastindexof_negative_index" + expr: "'tacocat'.lastIndexOf('a', -1) == -1" + eval_error: { + errors: { + message: "index out of range: -1" + } + } + } + test: { + name: "lastindexof_out_of_range" + expr: "'tacocat'.lastIndexOf('a', 30) == -1" + eval_error: { + errors: { + message: "index out of range: 30" + } + } + } + test: { + name: "substring_out_of_range" + expr: "'tacocat'.substring(40) == 'cat'" + eval_error: { + errors: { + message: "index out of range: 40" + } + } + } + test: { + name: "substring_negative_index" + expr: "'tacocat'.substring(-1) == 'cat'" + eval_error: { + errors: { + message: "index out of range: -1" + } + } + } + test: { + name: "substring_end_index_out_of_range" + expr: "'tacocat'.substring(1, 50) == 'cat'" + eval_error: { + errors: { + message: "index out of range: 50" + } + } + } + test: { + name: "substring_begin_index_out_of_range" + expr: "'tacocat'.substring(49, 50) == 'cat'" + eval_error: { + errors: { + message: "index out of range: 49" + } + } + } + test: { + name: "substring_end_index_greater_than_begin_index" + expr: "'tacocat'.substring(4, 3) == ''" + eval_error: { + errors: { + message: "invalid substring range. start: 4, end: 3" + } + } + } +} +section: { + name: "type_errors" + test: { + name: "charat_invalid_type" + expr: "42.charAt(2) == ''" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "charat_invalid_argument" + expr: "'hello'.charAt(true) == ''" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "indexof_unary_invalid_type" + expr: "24.indexOf('2') == 0" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "indexof_unary_invalid_argument" + expr: "'hello'.indexOf(true) == 1" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "indexof_binary_invalid_argument" + expr: "42.indexOf('4', 0) == 0" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "indexof_binary_invalid_argument_2" + expr: "'42'.indexOf(4, 0) == 0" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "indexof_binary_both_invalid_arguments" + expr: "'42'.indexOf('4', '0') == 0" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "indexof_ternary_invalid_arguments" + expr: "'42'.indexOf('4', 0, 1) == 0" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "split_invalid_type" + expr: "42.split('2') == ['4']" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "replace_invalid_type" + expr: "42.replace(2, 1) == '41'" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "replace_binary_invalid_argument" + expr: "'42'.replace(2, 1) == '41'" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "replace_binary_invalid_argument_2" + expr: "'42'.replace('2', 1) == '41'" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "replace_ternary_invalid_argument" + expr: "42.replace('2', '1', 1) == '41'" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "replace_ternary_invalid_argument_2" + expr: "'42'.replace(2, '1', 1) == '41'" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "replace_ternary_invalid_argument_3" + expr: "'42'.replace('2', 1, 1) == '41'" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "replace_ternary_invalid_argument_4" + expr: "'42'.replace('2', '1', '1') == '41'" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "replace_quaternary_invalid_argument" + expr: "'42'.replace('2', '1', 1, false) == '41'" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "split_invalid_type_empty_arg" + expr: "42.split('') == ['4', '2']" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "split_invalid_argument" + expr: "'42'.split(2) == ['4']" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "split_binary_invalid_type" + expr: "42.split('2', '1') == ['4']" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "split_binary_invalid_argument" + expr: "'42'.split(2, 1) == ['4']" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "split_binary_invalid_argument_2" + expr: "'42'.split('2', '1') == ['4']" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "split_ternary_invalid_argument" + expr: "'42'.split('2', 1, 1) == ['4']" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "substring_ternary_invalid_argument" + expr: "'hello'.substring(1, 2, 3) == ''" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "substring_binary_invalid_type" + expr: "30.substring(true, 3) == ''" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "substring_binary_invalid_argument" + expr: "'tacocat'.substring(true, 3) == ''" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } + test: { + name: "substring_binary_invalid_argument_2" + expr: "'tacocat'.substring(0, false) == ''" + disable_check: true + eval_error: { + errors: { + message: "no such overload" + } + } + } +} + diff --git a/packages/cel/src/lib/conformance/testdata/timestamps.json b/packages/cel/src/lib/conformance/testdata/timestamps.json new file mode 100755 index 0000000..5d39b5e --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/timestamps.json @@ -0,0 +1,667 @@ +{ + "name": "timestamps", + "description": "Timestamp and duration tests.", + "section": [ + { + "name": "timestamp_conversions", + "description": "Conversions of timestamps to other types.", + "test": [ + { + "name": "toInt_timestamp", + "expr": "int(timestamp('2009-02-13T23:31:30Z'))", + "value": { + "int64Value": "1234567890" + } + }, + { + "name": "toString_timestamp", + "expr": "string(timestamp('2009-02-13T23:31:30Z'))", + "value": { + "stringValue": "2009-02-13T23:31:30Z" + } + }, + { + "name": "toString_timestamp_nanos", + "expr": "string(timestamp('9999-12-31T23:59:59.999999999Z'))", + "value": { + "stringValue": "9999-12-31T23:59:59.999999999Z" + } + }, + { + "name": "toType_timestamp", + "expr": "type(timestamp('2009-02-13T23:31:30Z'))", + "value": { + "typeValue": "google.protobuf.Timestamp" + } + } + ] + }, + { + "name": "duration_conversions", + "description": "Conversions of durations to other types.", + "test": [ + { + "name": "toString_duration", + "expr": "string(duration('1000000s'))", + "value": { + "stringValue": "1000000s" + } + }, + { + "name": "toType_duration", + "expr": "type(duration('1000000s'))", + "value": { + "typeValue": "google.protobuf.Duration" + } + } + ] + }, + { + "name": "timestamp_selectors", + "description": "Timestamp selection operators without timezones", + "test": [ + { + "name": "getDate", + "expr": "timestamp('2009-02-13T23:31:30Z').getDate()", + "value": { + "int64Value": "13" + } + }, + { + "name": "getDayOfMonth", + "expr": "timestamp('2009-02-13T23:31:30Z').getDayOfMonth()", + "value": { + "int64Value": "12" + } + }, + { + "name": "getDayOfWeek", + "expr": "timestamp('2009-02-13T23:31:30Z').getDayOfWeek()", + "value": { + "int64Value": "5" + } + }, + { + "name": "getDayOfYear", + "expr": "timestamp('2009-02-13T23:31:30Z').getDayOfYear()", + "value": { + "int64Value": "43" + } + }, + { + "name": "getFullYear", + "expr": "timestamp('2009-02-13T23:31:30Z').getFullYear()", + "value": { + "int64Value": "2009" + } + }, + { + "name": "getHours", + "expr": "timestamp('2009-02-13T23:31:30Z').getHours()", + "value": { + "int64Value": "23" + } + }, + { + "name": "getMilliseconds", + "expr": "timestamp('2009-02-13T23:31:20.123456789Z').getMilliseconds()", + "value": { + "int64Value": "123" + } + }, + { + "name": "getMinutes", + "expr": "timestamp('2009-02-13T23:31:30Z').getMinutes()", + "value": { + "int64Value": "31" + } + }, + { + "name": "getMonth", + "expr": "timestamp('2009-02-13T23:31:30Z').getMonth()", + "value": { + "int64Value": "1" + } + }, + { + "name": "getSeconds", + "expr": "timestamp('2009-02-13T23:31:30Z').getSeconds()", + "value": { + "int64Value": "30" + } + } + ] + }, + { + "name": "timestamp_selectors_tz", + "description": "Timestamp selection operators with timezones", + "test": [ + { + "name": "getDate", + "expr": "timestamp('2009-02-13T23:31:30Z').getDate('Australia/Sydney')", + "value": { + "int64Value": "14" + } + }, + { + "name": "getDayOfMonth_name_pos", + "expr": "timestamp('2009-02-13T23:31:30Z').getDayOfMonth('US/Central')", + "value": { + "int64Value": "12" + } + }, + { + "name": "getDayOfMonth_numerical_pos", + "expr": "timestamp('2009-02-13T23:31:30Z').getDayOfMonth('+11:00')", + "value": { + "int64Value": "13" + } + }, + { + "name": "getDayOfMonth_numerical_neg", + "expr": "timestamp('2009-02-13T02:00:00Z').getDayOfMonth('-02:30')", + "value": { + "int64Value": "11" + } + }, + { + "name": "getDayOfMonth_name_neg", + "expr": "timestamp('2009-02-13T02:00:00Z').getDayOfMonth('America/St_Johns')", + "value": { + "int64Value": "11" + } + }, + { + "name": "getDayOfWeek", + "expr": "timestamp('2009-02-13T23:31:30Z').getDayOfWeek('UTC')", + "value": { + "int64Value": "5" + } + }, + { + "name": "getDayOfYear", + "expr": "timestamp('2009-02-13T23:31:30Z').getDayOfYear('US/Central')", + "value": { + "int64Value": "43" + } + }, + { + "name": "getFullYear", + "expr": "timestamp('2009-02-13T23:31:30Z').getFullYear('-09:30')", + "value": { + "int64Value": "2009" + } + }, + { + "name": "getHours", + "expr": "timestamp('2009-02-13T23:31:30Z').getHours('02:00')", + "value": { + "int64Value": "1" + } + }, + { + "name": "getMinutes", + "expr": "timestamp('2009-02-13T23:31:30Z').getMinutes('Asia/Kathmandu')", + "value": { + "int64Value": "16" + } + }, + { + "name": "getMonth", + "expr": "timestamp('2009-02-13T23:31:30Z').getMonth('UTC')", + "value": { + "int64Value": "1" + } + }, + { + "name": "getSeconds", + "expr": "timestamp('2009-02-13T23:31:30Z').getSeconds('-00:00')", + "value": { + "int64Value": "30" + } + } + ] + }, + { + "name": "timestamp_equality", + "description": "Equality operations on timestamps.", + "test": [ + { + "name": "eq_same", + "expr": "timestamp('2009-02-13T23:31:30Z') == timestamp('2009-02-13T23:31:30Z')", + "value": { + "boolValue": true + } + }, + { + "name": "eq_diff", + "expr": "timestamp('2009-02-13T23:31:29Z') == timestamp('2009-02-13T23:31:30Z')", + "value": { + "boolValue": false + } + }, + { + "name": "neq_same", + "expr": "timestamp('1945-05-07T02:41:00Z') != timestamp('1945-05-07T02:41:00Z')", + "value": { + "boolValue": false + } + }, + { + "name": "neq_diff", + "expr": "timestamp('2000-01-01T00:00:00Z') != timestamp('2001-01-01T00:00:00Z')", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "duration_equality", + "description": "Equality tests for durations.", + "test": [ + { + "name": "eq_same", + "expr": "duration('123s') == duration('123s')", + "value": { + "boolValue": true + } + }, + { + "name": "eq_diff", + "expr": "duration('60s') == duration('3600s')", + "value": { + "boolValue": false + } + }, + { + "name": "neq_same", + "expr": "duration('604800s') != duration('604800s')", + "value": { + "boolValue": false + } + }, + { + "name": "neq_diff", + "expr": "duration('86400s') != duration('86164s')", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "timestamp_arithmetic", + "description": "Arithmetic operations on timestamps and/or durations.", + "test": [ + { + "name": "add_duration_to_time", + "expr": "timestamp('2009-02-13T23:00:00Z') + duration('240s') == timestamp('2009-02-13T23:04:00Z')", + "value": { + "boolValue": true + } + }, + { + "name": "add_time_to_duration", + "expr": "duration('120s') + timestamp('2009-02-13T23:01:00Z') == timestamp('2009-02-13T23:03:00Z')", + "value": { + "boolValue": true + } + }, + { + "name": "add_duration_to_duration", + "expr": "duration('600s') + duration('50s') == duration('650s')", + "value": { + "boolValue": true + } + }, + { + "name": "add_time_to_duration_nanos_negative", + "expr": "timestamp('0001-01-01T00:00:01.000000001Z') + duration('-999999999ns') == timestamp('0001-01-01T00:00:00.000000002Z')", + "value": { + "boolValue": true + } + }, + { + "name": "add_time_to_duration_nanos_positive", + "expr": "timestamp('0001-01-01T00:00:01.999999999Z') + duration('999999999ns') == timestamp('0001-01-01T00:00:02.999999998Z')", + "value": { + "boolValue": true + } + }, + { + "name": "subtract_duration_from_time", + "expr": "timestamp('2009-02-13T23:10:00Z') - duration('600s') == timestamp('2009-02-13T23:00:00Z')", + "value": { + "boolValue": true + } + }, + { + "name": "subtract_time_from_time", + "expr": "timestamp('2009-02-13T23:31:00Z') - timestamp('2009-02-13T23:29:00Z') == duration('120s')", + "value": { + "boolValue": true + } + }, + { + "name": "subtract_duration_from_duration", + "expr": "duration('900s') - duration('42s') == duration('858s')", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "comparisons", + "description": "Comparisons on timestamps and/or durations.", + "test": [ + { + "name": "leq_timestamp_true", + "expr": "timestamp('2009-02-13T23:00:00Z') <= timestamp('2009-02-13T23:00:00Z')", + "value": { + "boolValue": true + } + }, + { + "name": "leq_timestamp_false", + "expr": "timestamp('2009-02-13T23:00:00Z') <= timestamp('2009-02-13T22:59:59Z')", + "value": { + "boolValue": false + } + }, + { + "name": "leq_duration_true", + "expr": "duration('200s') <= duration('200s')", + "value": { + "boolValue": true + } + }, + { + "name": "leq_duration_false", + "expr": "duration('300s') <= duration('200s')", + "value": { + "boolValue": false + } + }, + { + "name": "less_timestamp_true", + "expr": "timestamp('2009-02-13T23:00:00Z') < timestamp('2009-03-13T23:00:00Z')", + "value": { + "boolValue": true + } + }, + { + "name": "less_duration_true", + "expr": "duration('200s') < duration('300s')", + "value": { + "boolValue": true + } + }, + { + "name": "geq_timestamp_true", + "expr": "timestamp('2009-02-13T23:00:00Z') >= timestamp('2009-02-13T23:00:00Z')", + "value": { + "boolValue": true + } + }, + { + "name": "geq_timestamp_false", + "expr": "timestamp('2009-02-13T22:58:00Z') >= timestamp('2009-02-13T23:00:00Z')", + "value": { + "boolValue": false + } + }, + { + "name": "geq_duration_true", + "expr": "duration('200s') >= duration('200s')", + "value": { + "boolValue": true + } + }, + { + "name": "geq_duration_false", + "expr": "duration('120s') >= duration('200s')", + "value": { + "boolValue": false + } + }, + { + "name": "greater_timestamp_true", + "expr": "timestamp('2009-02-13T23:59:00Z') > timestamp('2009-02-13T23:00:00Z')", + "value": { + "boolValue": true + } + }, + { + "name": "greater_duration_true", + "expr": "duration('300s') > duration('200s')", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "duration_converters", + "description": "Conversion functions on durations. Unlike timestamps, we don't, e.g. select the 'minutes' field - we convert the duration to integer minutes.", + "test": [ + { + "name": "get_hours", + "expr": "duration('10000s').getHours()", + "value": { + "int64Value": "2" + } + }, + { + "name": "get_milliseconds", + "description": "Obtain the milliseconds component of the duration. Note, this is not the same as converting the duration to milliseconds. This behavior will be deprecated.", + "expr": "x.getMilliseconds()", + "typeEnv": [ + { + "name": "x", + "ident": { + "type": { + "messageType": "google.protobuf.Duration" + } + } + } + ], + "bindings": { + "x": { + "value": { + "objectValue": { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "123.321456789s" + } + } + } + }, + "value": { + "int64Value": "321" + } + }, + { + "name": "get_minutes", + "expr": "duration('3730s').getMinutes()", + "value": { + "int64Value": "62" + } + }, + { + "name": "get_seconds", + "expr": "duration('3730s').getSeconds()", + "value": { + "int64Value": "3730" + } + } + ] + }, + { + "name": "timestamp_range", + "description": "Tests for out-of-range operations on timestamps.", + "test": [ + { + "name": "from_string_under", + "expr": "timestamp('0000-01-01T00:00:00Z')", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + }, + { + "name": "from_string_over", + "expr": "timestamp('10000-01-01T00:00:00Z')", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + }, + { + "name": "add_duration_under", + "expr": "timestamp('0001-01-01T00:00:00Z') + duration('-1s')", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + }, + { + "name": "add_duration_over", + "expr": "timestamp('9999-12-31T23:59:59Z') + duration('1s')", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + }, + { + "name": "add_duration_nanos_over", + "expr": "timestamp('9999-12-31T23:59:59.999999999Z') + duration('1ns')", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + }, + { + "name": "add_duration_nanos_under", + "expr": "timestamp('0001-01-01T00:00:00Z') + duration('-1ns')", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + }, + { + "name": "sub_time_duration_over", + "expr": "timestamp('9999-12-31T23:59:59Z') - timestamp('0001-01-01T00:00:00Z')", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + }, + { + "name": "sub_time_duration_under", + "expr": "timestamp('0001-01-01T00:00:00Z') - timestamp('9999-12-31T23:59:59Z')", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + } + ] + }, + { + "name": "duration_range", + "description": "Tests for out-of-range operations on durations.", + "test": [ + { + "name": "from_string_under", + "expr": "duration('-320000000000s')", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + }, + { + "name": "from_string_over", + "expr": "duration('320000000000s')", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + }, + { + "name": "add_under", + "expr": "duration('-200000000000s') + duration('-200000000000s')", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + }, + { + "name": "add_over", + "expr": "duration('200000000000s') + duration('200000000000s')", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + }, + { + "name": "sub_under", + "expr": "duration('-200000000000s') - duration('200000000000s')", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + }, + { + "name": "sub_over", + "expr": "duration('200000000000s') - duration('-200000000000s')", + "evalError": { + "errors": [ + { + "message": "range" + } + ] + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/timestamps.textproto b/packages/cel/src/lib/conformance/testdata/timestamps.textproto new file mode 100644 index 0000000..3fc0af6 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/timestamps.textproto @@ -0,0 +1,466 @@ +name: "timestamps" +description: "Timestamp and duration tests." +section { + name: "timestamp_conversions" + description: "Conversions of timestamps to other types." + test { + name: "toInt_timestamp" + expr: "int(timestamp('2009-02-13T23:31:30Z'))" + value: { int64_value: 1234567890 } + } + test { + name: "toString_timestamp" + expr: "string(timestamp('2009-02-13T23:31:30Z'))" + value: { string_value: "2009-02-13T23:31:30Z" } + } + test { + name: "toString_timestamp_nanos" + expr: "string(timestamp('9999-12-31T23:59:59.999999999Z'))" + value: { string_value: "9999-12-31T23:59:59.999999999Z" } + } + test { + name: "toType_timestamp" + expr: "type(timestamp('2009-02-13T23:31:30Z'))" + value: { type_value: "google.protobuf.Timestamp" } + } +} +section { + name: "duration_conversions" + description: "Conversions of durations to other types." + test { + name: "toString_duration" + expr: "string(duration('1000000s'))" + value: { string_value: "1000000s" } + } + test { + name: "toType_duration" + expr: "type(duration('1000000s'))" + value: { type_value: "google.protobuf.Duration" } + } +} + +section { + name: "timestamp_selectors" + description: "Timestamp selection operators without timezones" + # 1234567890 -> Fri 2009-02-13 23:31:30 UTC + test { + name: "getDate" + expr: "timestamp('2009-02-13T23:31:30Z').getDate()" + value: { int64_value: 13 } + } + test { + name: "getDayOfMonth" + expr: "timestamp('2009-02-13T23:31:30Z').getDayOfMonth()" + value: { int64_value: 12 } + } + test { + name: "getDayOfWeek" + expr: "timestamp('2009-02-13T23:31:30Z').getDayOfWeek()" + value: { int64_value: 5 } + } + test { + name: "getDayOfYear" + expr: "timestamp('2009-02-13T23:31:30Z').getDayOfYear()" + value: { int64_value: 43 } + } + test { + name: "getFullYear" + expr: "timestamp('2009-02-13T23:31:30Z').getFullYear()" + value: { int64_value: 2009 } + } + test { + name: "getHours" + expr: "timestamp('2009-02-13T23:31:30Z').getHours()" + value: { int64_value: 23 } + } + test { + name: "getMilliseconds" + expr: "timestamp('2009-02-13T23:31:20.123456789Z').getMilliseconds()" + value: { int64_value: 123 } + } + test { + name: "getMinutes" + expr: "timestamp('2009-02-13T23:31:30Z').getMinutes()" + value: { int64_value: 31 } + } + test { + name: "getMonth" + expr: "timestamp('2009-02-13T23:31:30Z').getMonth()" + value: { int64_value: 1 } + } + test { + name: "getSeconds" + expr: "timestamp('2009-02-13T23:31:30Z').getSeconds()" + value: { int64_value: 30 } + } +} +section { + name: "timestamp_selectors_tz" + description: "Timestamp selection operators with timezones" + # 1234567890 -> Fri 2009-02-13 23:31:30 UTC + test { + name: "getDate" + expr: "timestamp('2009-02-13T23:31:30Z').getDate('Australia/Sydney')" + value: { int64_value: 14 } + } + test { + name: "getDayOfMonth_name_pos" + expr: "timestamp('2009-02-13T23:31:30Z').getDayOfMonth('US/Central')" + value: { int64_value: 12 } + } + test { + name: "getDayOfMonth_numerical_pos" + expr: "timestamp('2009-02-13T23:31:30Z').getDayOfMonth('+11:00')" + value: { int64_value: 13 } + } + test { + name: "getDayOfMonth_numerical_neg" + expr: "timestamp('2009-02-13T02:00:00Z').getDayOfMonth('-02:30')" + value: { int64_value: 11 } + } + test { + name: "getDayOfMonth_name_neg" + expr: "timestamp('2009-02-13T02:00:00Z').getDayOfMonth('America/St_Johns')" + value: { int64_value: 11 } + } + test { + name: "getDayOfWeek" + expr: "timestamp('2009-02-13T23:31:30Z').getDayOfWeek('UTC')" + value: { int64_value: 5 } + } + test { + name: "getDayOfYear" + expr: "timestamp('2009-02-13T23:31:30Z').getDayOfYear('US/Central')" + value: { int64_value: 43 } + } + test { + name: "getFullYear" + expr: "timestamp('2009-02-13T23:31:30Z').getFullYear('-09:30')" + value: { int64_value: 2009 } + } + test { + name: "getHours" + expr: "timestamp('2009-02-13T23:31:30Z').getHours('02:00')" + value: { int64_value: 1 } + } + test { + name: "getMinutes" + expr: "timestamp('2009-02-13T23:31:30Z').getMinutes('Asia/Kathmandu')" + value: { int64_value: 16 } + } + test { + name: "getMonth" + expr: "timestamp('2009-02-13T23:31:30Z').getMonth('UTC')" + value: { int64_value: 1 } + } + test { + name: "getSeconds" + expr: "timestamp('2009-02-13T23:31:30Z').getSeconds('-00:00')" + value: { int64_value: 30 } + } +} +section { + name: "timestamp_equality" + description: "Equality operations on timestamps." + test { + name: "eq_same" + expr: "timestamp('2009-02-13T23:31:30Z') == timestamp('2009-02-13T23:31:30Z')" + value: { bool_value: true } + } + test { + name: "eq_diff" + expr: "timestamp('2009-02-13T23:31:29Z') == timestamp('2009-02-13T23:31:30Z')" + value: { bool_value: false } + } + test { + name: "neq_same" + expr: "timestamp('1945-05-07T02:41:00Z') != timestamp('1945-05-07T02:41:00Z')" + value: { bool_value: false } + } + test { + name: "neq_diff" + expr: "timestamp('2000-01-01T00:00:00Z') != timestamp('2001-01-01T00:00:00Z')" + value: { bool_value: true } + } +} +section { + name: "duration_equality" + description: "Equality tests for durations." + test { + name: "eq_same" + expr: "duration('123s') == duration('123s')" + value: { bool_value: true } + } + test { + name: "eq_diff" + expr: "duration('60s') == duration('3600s')" + value: { bool_value: false } + } + test { + name: "neq_same" + expr: "duration('604800s') != duration('604800s')" + value: { bool_value: false } + } + test { + name: "neq_diff" + expr: "duration('86400s') != duration('86164s')" + value: { bool_value: true } + } +} +section { + name: "timestamp_arithmetic" + description: "Arithmetic operations on timestamps and/or durations." + test { + name: "add_duration_to_time" + expr: "timestamp('2009-02-13T23:00:00Z') + duration('240s') == timestamp('2009-02-13T23:04:00Z')" + value: { bool_value: true} + } + test { + name: "add_time_to_duration" + expr: "duration('120s') + timestamp('2009-02-13T23:01:00Z') == timestamp('2009-02-13T23:03:00Z')" + value: { bool_value: true} + } + test { + name: "add_duration_to_duration" + expr: "duration('600s') + duration('50s') == duration('650s')" + value: { bool_value: true } + } + test { + name: "add_time_to_duration_nanos_negative" + expr: "timestamp('0001-01-01T00:00:01.000000001Z') + duration('-999999999ns') == timestamp('0001-01-01T00:00:00.000000002Z')" + value: { bool_value: true } + } + test { + name: "add_time_to_duration_nanos_positive" + expr: "timestamp('0001-01-01T00:00:01.999999999Z') + duration('999999999ns') == timestamp('0001-01-01T00:00:02.999999998Z')" + value: { bool_value: true } + } + test { + name: "subtract_duration_from_time" + expr: "timestamp('2009-02-13T23:10:00Z') - duration('600s') == timestamp('2009-02-13T23:00:00Z')" + value: { bool_value: true} + } + test { + name: "subtract_time_from_time" + expr: "timestamp('2009-02-13T23:31:00Z') - timestamp('2009-02-13T23:29:00Z') == duration('120s')" + value: { bool_value: true} + } + test { + name: "subtract_duration_from_duration" + expr: "duration('900s') - duration('42s') == duration('858s')" + value: { bool_value: true } + } +} +section { + name: "comparisons" + description: "Comparisons on timestamps and/or durations." + test { + name: "leq_timestamp_true" + expr: "timestamp('2009-02-13T23:00:00Z') <= timestamp('2009-02-13T23:00:00Z')" + value: { bool_value: true } + } + test { + name: "leq_timestamp_false" + expr: "timestamp('2009-02-13T23:00:00Z') <= timestamp('2009-02-13T22:59:59Z')" + value: { bool_value: false } + } + test { + name: "leq_duration_true" + expr: "duration('200s') <= duration('200s')" + value: { bool_value: true } + } + test { + name: "leq_duration_false" + expr: "duration('300s') <= duration('200s')" + value: { bool_value: false } + } + test { + name: "less_timestamp_true" + expr: "timestamp('2009-02-13T23:00:00Z') < timestamp('2009-03-13T23:00:00Z')" + value: { bool_value: true } + } + test { + name: "less_duration_true" + expr: "duration('200s') < duration('300s')" + value: { bool_value: true } + } + test { + name: "geq_timestamp_true" + expr: "timestamp('2009-02-13T23:00:00Z') >= timestamp('2009-02-13T23:00:00Z')" + value: { bool_value: true } + } + test { + name: "geq_timestamp_false" + expr: "timestamp('2009-02-13T22:58:00Z') >= timestamp('2009-02-13T23:00:00Z')" + value: { bool_value: false } + } + test { + name: "geq_duration_true" + expr: "duration('200s') >= duration('200s')" + value: { bool_value: true } + } + test { + name: "geq_duration_false" + expr: "duration('120s') >= duration('200s')" + value: { bool_value: false } + } + test { + name: "greater_timestamp_true" + expr: "timestamp('2009-02-13T23:59:00Z') > timestamp('2009-02-13T23:00:00Z')" + value: { bool_value: true } + } + test { + name: "greater_duration_true" + expr: "duration('300s') > duration('200s')" + value: { bool_value: true } + } +} +section { + name: "duration_converters" + description: "Conversion functions on durations. Unlike timestamps, we don't, e.g. select the 'minutes' field - we convert the duration to integer minutes." + test { + name: "get_hours" + expr: "duration('10000s').getHours()" + value: { int64_value: 2 } + } + test { + name: "get_milliseconds" + description: "Obtain the milliseconds component of the duration. Note, this is not the same as converting the duration to milliseconds. This behavior will be deprecated." + expr: "x.getMilliseconds()" + type_env { + name: "x" + ident: { type: { message_type: "google.protobuf.Duration" } } + } + bindings { + key: "x" + value { + value { + object_value { + [type.googleapis.com/google.protobuf.Duration] + { + seconds: 123 + nanos:321456789 + } + } + } + } + } + value: { int64_value: 321 } + } + test { + name: "get_minutes" + expr: "duration('3730s').getMinutes()" + value: { int64_value: 62 } + } + test { + name: "get_seconds" + expr: "duration('3730s').getSeconds()" + value: { int64_value: 3730 } + } +} +section { + name: "timestamp_range" + description: "Tests for out-of-range operations on timestamps." + test { + name: "from_string_under" + expr: "timestamp('0000-01-01T00:00:00Z')" + eval_error { + errors { message: "range" } + } + } + test { + name: "from_string_over" + expr: "timestamp('10000-01-01T00:00:00Z')" + eval_error { + errors { message: "range" } + } + } + test { + name: "add_duration_under" + expr: "timestamp('0001-01-01T00:00:00Z') + duration('-1s')" + eval_error { + errors { message: "range" } + } + } + test { + name: "add_duration_over" + expr: "timestamp('9999-12-31T23:59:59Z') + duration('1s')" + eval_error { + errors { message: "range" } + } + } + test { + name: "add_duration_nanos_over" + expr: "timestamp('9999-12-31T23:59:59.999999999Z') + duration('1ns')" + eval_error { + errors { message: "range" } + } + } + test { + name: "add_duration_nanos_under" + expr: "timestamp('0001-01-01T00:00:00Z') + duration('-1ns')" + eval_error { + errors { message: "range" } + } + } + test { + name: "sub_time_duration_over" + expr: "timestamp('9999-12-31T23:59:59Z') - timestamp('0001-01-01T00:00:00Z')" + eval_error { + errors { message: "range" } + } + } + test { + name: "sub_time_duration_under" + expr: "timestamp('0001-01-01T00:00:00Z') - timestamp('9999-12-31T23:59:59Z')" + eval_error { + errors { message: "range" } + } + } +} +section { + name: "duration_range" + description: "Tests for out-of-range operations on durations." + test { + name: "from_string_under" + expr: "duration('-320000000000s')" + eval_error { + errors { message: "range" } + } + } + test { + name: "from_string_over" + expr: "duration('320000000000s')" + eval_error { + errors { message: "range" } + } + } + test { + name: "add_under" + expr: "duration('-200000000000s') + duration('-200000000000s')" + eval_error { + errors { message: "range" } + } + } + test { + name: "add_over" + expr: "duration('200000000000s') + duration('200000000000s')" + eval_error { + errors { message: "range" } + } + } + test { + name: "sub_under" + expr: "duration('-200000000000s') - duration('200000000000s')" + eval_error { + errors { message: "range" } + } + } + test { + name: "sub_over" + expr: "duration('200000000000s') - duration('-200000000000s')" + eval_error { + errors { message: "range" } + } + } +} diff --git a/packages/cel/src/lib/conformance/testdata/unknowns.json b/packages/cel/src/lib/conformance/testdata/unknowns.json new file mode 100755 index 0000000..96e6a3f --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/unknowns.json @@ -0,0 +1,4 @@ +{ + "name": "unknowns", + "description": "Tests for evaluation with unknown inputs." +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/unknowns.textproto b/packages/cel/src/lib/conformance/testdata/unknowns.textproto new file mode 100644 index 0000000..4b17570 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/unknowns.textproto @@ -0,0 +1,2 @@ +name: "unknowns" +description: "Tests for evaluation with unknown inputs." diff --git a/packages/cel/src/lib/conformance/testdata/wrappers.json b/packages/cel/src/lib/conformance/testdata/wrappers.json new file mode 100755 index 0000000..d684f43 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/wrappers.json @@ -0,0 +1,374 @@ +{ + "name": "wrappers", + "description": "Conformance tests related to wrapper types.", + "section": [ + { + "name": "bool", + "test": [ + { + "name": "to_any", + "expr": "TestAllTypes{single_any: google.protobuf.BoolValue{value: true}}.single_any", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "to_json", + "expr": "TestAllTypes{single_value: google.protobuf.BoolValue{value: true}}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + }, + { + "name": "to_null", + "expr": "TestAllTypes{single_bool_wrapper: null} == TestAllTypes{}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "int32", + "test": [ + { + "name": "to_any", + "expr": "TestAllTypes{single_any: google.protobuf.Int32Value{value: 1}}.single_any", + "container": "google.api.expr.test.v1.proto3", + "value": { + "int64Value": "1" + } + }, + { + "name": "to_json", + "expr": "TestAllTypes{single_value: google.protobuf.Int32Value{value: 1}}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "doubleValue": 1 + } + }, + { + "name": "to_null", + "expr": "TestAllTypes{single_int32_wrapper: null} == TestAllTypes{}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "int64", + "test": [ + { + "name": "to_any", + "expr": "TestAllTypes{single_any: google.protobuf.Int64Value{value: 1}}.single_any", + "container": "google.api.expr.test.v1.proto3", + "value": { + "int64Value": "1" + } + }, + { + "name": "to_json_number", + "expr": "TestAllTypes{single_value: google.protobuf.Int64Value{value: 1}}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "doubleValue": 1 + } + }, + { + "name": "to_json_string", + "expr": "TestAllTypes{single_value: google.protobuf.Int64Value{value: 9223372036854775807}}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "stringValue": "9223372036854775807" + } + }, + { + "name": "to_null", + "expr": "TestAllTypes{single_int64_wrapper: null} == TestAllTypes{}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "uint32", + "test": [ + { + "name": "to_any", + "expr": "TestAllTypes{single_any: google.protobuf.UInt32Value{value: 1u}}.single_any", + "container": "google.api.expr.test.v1.proto3", + "value": { + "uint64Value": "1" + } + }, + { + "name": "to_json", + "expr": "TestAllTypes{single_value: google.protobuf.UInt32Value{value: 1u}}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "doubleValue": 1 + } + }, + { + "name": "to_null", + "expr": "TestAllTypes{single_uint32_wrapper: null} == TestAllTypes{}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "uint64", + "test": [ + { + "name": "to_any", + "expr": "TestAllTypes{single_any: google.protobuf.UInt64Value{value: 1u}}.single_any", + "container": "google.api.expr.test.v1.proto3", + "value": { + "uint64Value": "1" + } + }, + { + "name": "to_json_number", + "expr": "TestAllTypes{single_value: google.protobuf.UInt64Value{value: 1u}}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "doubleValue": 1 + } + }, + { + "name": "to_json_string", + "expr": "TestAllTypes{single_value: google.protobuf.UInt64Value{value: 18446744073709551615u}}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "stringValue": "18446744073709551615" + } + }, + { + "name": "to_null", + "expr": "TestAllTypes{single_uint64_wrapper: null} == TestAllTypes{}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "float", + "test": [ + { + "name": "to_any", + "expr": "TestAllTypes{single_any: google.protobuf.FloatValue{value: 1.0}}.single_any", + "container": "google.api.expr.test.v1.proto3", + "value": { + "doubleValue": 1 + } + }, + { + "name": "to_json", + "expr": "TestAllTypes{single_value: google.protobuf.FloatValue{value: 1.0}}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "doubleValue": 1 + } + }, + { + "name": "to_null", + "expr": "TestAllTypes{single_float_wrapper: null} == TestAllTypes{}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "double", + "test": [ + { + "name": "to_any", + "expr": "TestAllTypes{single_any: google.protobuf.DoubleValue{value: 1.0}}.single_any", + "container": "google.api.expr.test.v1.proto3", + "value": { + "doubleValue": 1 + } + }, + { + "name": "to_json", + "expr": "TestAllTypes{single_value: google.protobuf.DoubleValue{value: 1.0}}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "doubleValue": 1 + } + }, + { + "name": "to_null", + "expr": "TestAllTypes{single_double_wrapper: null} == TestAllTypes{}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "bytes", + "test": [ + { + "name": "to_any", + "expr": "TestAllTypes{single_any: google.protobuf.BytesValue{value: b'foo'}}.single_any", + "container": "google.api.expr.test.v1.proto3", + "value": { + "bytesValue": "Zm9v" + } + }, + { + "name": "to_json", + "expr": "TestAllTypes{single_value: google.protobuf.BytesValue{value: b'foo'}}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "stringValue": "Zm9v" + } + }, + { + "name": "to_null", + "expr": "TestAllTypes{single_bytes_wrapper: null} == TestAllTypes{}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "string", + "test": [ + { + "name": "to_any", + "expr": "TestAllTypes{single_any: google.protobuf.StringValue{value: 'foo'}}.single_any", + "container": "google.api.expr.test.v1.proto3", + "value": { + "stringValue": "foo" + } + }, + { + "name": "to_json", + "expr": "TestAllTypes{single_value: google.protobuf.StringValue{value: 'foo'}}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "stringValue": "foo" + } + }, + { + "name": "to_null", + "expr": "TestAllTypes{single_string_wrapper: null} == TestAllTypes{}", + "container": "google.api.expr.test.v1.proto3", + "value": { + "boolValue": true + } + } + ] + }, + { + "name": "value", + "test": [ + { + "name": "default_to_json", + "expr": "TestAllTypes{single_any: TestAllTypes{}.single_value}.single_any", + "container": "google.api.expr.test.v1.proto3", + "value": { + "nullValue": null + } + } + ] + }, + { + "name": "list_value", + "test": [ + { + "name": "literal_to_any", + "expr": "TestAllTypes{single_any: []}.single_any", + "container": "google.api.expr.test.v1.proto3", + "value": { + "listValue": {} + } + } + ] + }, + { + "name": "struct", + "test": [ + { + "name": "literal_to_any", + "expr": "TestAllTypes{single_any: {}}.single_any", + "container": "google.api.expr.test.v1.proto3", + "value": { + "mapValue": {} + } + } + ] + }, + { + "name": "field_mask", + "test": [ + { + "name": "to_json", + "expr": "TestAllTypes{single_value: google.protobuf.FieldMask{paths: ['foo', 'bar']}}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "stringValue": "foo,bar" + } + } + ] + }, + { + "name": "duration", + "test": [ + { + "name": "to_json", + "expr": "TestAllTypes{single_value: duration('1000000s')}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "stringValue": "1000000s" + } + } + ] + }, + { + "name": "timestamp", + "test": [ + { + "name": "to_json", + "expr": "TestAllTypes{single_value: timestamp('9999-12-31T23:59:59.999999999Z')}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "stringValue": "9999-12-31T23:59:59.999999999Z" + } + } + ] + }, + { + "name": "empty", + "test": [ + { + "name": "to_json", + "expr": "TestAllTypes{single_value: google.protobuf.Empty{}}.single_value", + "container": "google.api.expr.test.v1.proto3", + "value": { + "mapValue": {} + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/cel/src/lib/conformance/testdata/wrappers.textproto b/packages/cel/src/lib/conformance/testdata/wrappers.textproto new file mode 100644 index 0000000..2184442 --- /dev/null +++ b/packages/cel/src/lib/conformance/testdata/wrappers.textproto @@ -0,0 +1,371 @@ +name: "wrappers" +description: "Conformance tests related to wrapper types." + +# google.protobuf.BoolValue +section { + name: "bool" + test { + name: "to_any" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_any: google.protobuf.BoolValue{value: true}}.single_any" + value { + bool_value: true + } + } + test { + name: "to_json" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: google.protobuf.BoolValue{value: true}}.single_value" + value { + bool_value: true + } + } + test { + name: "to_null" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_bool_wrapper: null} == TestAllTypes{}" + value { + bool_value: true + } + } +} + +# google.protobuf.Int32Value +section { + name: "int32" + test { + name: "to_any" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_any: google.protobuf.Int32Value{value: 1}}.single_any" + value { + int64_value: 1 + } + } + test { + name: "to_json" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: google.protobuf.Int32Value{value: 1}}.single_value" + value { + double_value: 1 + } + } + test { + name: "to_null" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_int32_wrapper: null} == TestAllTypes{}" + value { + bool_value: true + } + } +} + +# google.protobuf.Int64Value +section { + name: "int64" + test { + name: "to_any" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_any: google.protobuf.Int64Value{value: 1}}.single_any" + value { + int64_value: 1 + } + } + test { + name: "to_json_number" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: google.protobuf.Int64Value{value: 1}}.single_value" + value { + double_value: 1 + } + } + test { + name: "to_json_string" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: google.protobuf.Int64Value{value: 9223372036854775807}}.single_value" + value { + string_value: "9223372036854775807" + } + } + test { + name: "to_null" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_int64_wrapper: null} == TestAllTypes{}" + value { + bool_value: true + } + } +} + +# google.protobuf.UInt32Value +section { + name: "uint32" + test { + name: "to_any" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_any: google.protobuf.UInt32Value{value: 1u}}.single_any" + value { + uint64_value: 1 + } + } + test { + name: "to_json" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: google.protobuf.UInt32Value{value: 1u}}.single_value" + value { + double_value: 1 + } + } + test { + name: "to_null" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_uint32_wrapper: null} == TestAllTypes{}" + value { + bool_value: true + } + } +} + +# google.protobuf.UInt64Value +section { + name: "uint64" + test { + name: "to_any" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_any: google.protobuf.UInt64Value{value: 1u}}.single_any" + value { + uint64_value: 1 + } + } + test { + name: "to_json_number" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: google.protobuf.UInt64Value{value: 1u}}.single_value" + value { + double_value: 1 + } + } + test { + name: "to_json_string" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: google.protobuf.UInt64Value{value: 18446744073709551615u}}.single_value" + value { + string_value: "18446744073709551615" + } + } + test { + name: "to_null" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_uint64_wrapper: null} == TestAllTypes{}" + value { + bool_value: true + } + } +} + +# google.protobuf.FloatValue +section { + name: "float" + test { + name: "to_any" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_any: google.protobuf.FloatValue{value: 1.0}}.single_any" + value { + double_value: 1 + } + } + test { + name: "to_json" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: google.protobuf.FloatValue{value: 1.0}}.single_value" + value { + double_value: 1 + } + } + test { + name: "to_null" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_float_wrapper: null} == TestAllTypes{}" + value { + bool_value: true + } + } +} + +# google.protobuf.DoubleValue +section { + name: "double" + test { + name: "to_any" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_any: google.protobuf.DoubleValue{value: 1.0}}.single_any" + value { + double_value: 1 + } + } + test { + name: "to_json" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: google.protobuf.DoubleValue{value: 1.0}}.single_value" + value { + double_value: 1 + } + } + test { + name: "to_null" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_double_wrapper: null} == TestAllTypes{}" + value { + bool_value: true + } + } +} + +# google.protobuf.BytesValue +section { + name: "bytes" + test { + name: "to_any" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_any: google.protobuf.BytesValue{value: b'foo'}}.single_any" + value { + bytes_value: "foo" + } + } + test { + name: "to_json" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: google.protobuf.BytesValue{value: b'foo'}}.single_value" + value { + string_value: "Zm9v" + } + } + test { + name: "to_null" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_bytes_wrapper: null} == TestAllTypes{}" + value { + bool_value: true + } + } +} + +# google.protobuf.StringValue +section { + name: "string" + test { + name: "to_any" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_any: google.protobuf.StringValue{value: 'foo'}}.single_any" + value { + string_value: "foo" + } + } + test { + name: "to_json" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: google.protobuf.StringValue{value: 'foo'}}.single_value" + value { + string_value: "foo" + } + } + test { + name: "to_null" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_string_wrapper: null} == TestAllTypes{}" + value { + bool_value: true + } + } +} + +# google.protobuf.Value +section { + name: "value" + test { + name: "default_to_json" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_any: TestAllTypes{}.single_value}.single_any" + value { + null_value: NULL_VALUE + } + } +} + +# google.protobuf.ListValue +section { + name: "list_value" + description: "" + test { + name: "literal_to_any" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_any: []}.single_any" + value { + list_value {} + } + } +} + +# google.protobuf.Struct +section { + name: "struct" + test { + name: "literal_to_any" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_any: {}}.single_any" + value { + map_value {} + } + } +} + +# google.protobuf.FieldMask +section { + name: "field_mask" + test { + name: "to_json" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: google.protobuf.FieldMask{paths: ['foo', 'bar']}}.single_value" + value { + string_value: "foo,bar" + } + } +} + +# google.protobuf.Duration +section { + name: "duration" + test { + name: "to_json" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: duration('1000000s')}.single_value" + value { + string_value: "1000000s" + } + } +} + +# google.protobuf.Timestamp +section { + name: "timestamp" + test { + name: "to_json" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: timestamp('9999-12-31T23:59:59.999999999Z')}.single_value" + value { + string_value: "9999-12-31T23:59:59.999999999Z" + } + } +} + +# google.protobuf.Empty +section { + name: "empty" + test { + name: "to_json" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{single_value: google.protobuf.Empty{}}.single_value" + value { + map_value {} + } + } +} diff --git a/packages/cel/src/lib/conformance/textproto-to-json.go b/packages/cel/src/lib/conformance/textproto-to-json.go new file mode 100644 index 0000000..7654308 --- /dev/null +++ b/packages/cel/src/lib/conformance/textproto-to-json.go @@ -0,0 +1,82 @@ +// Adapted from https://github.com/cloud-custodian/cel-python/blob/master/tools/mkgherkin.go + +package main + +/* + Converts Textproto (or protobuf) SimpleTest documents into json so it can be + loaded by protobuf-es classes. + + See go doc github.com/google/cel-spec/proto/test/v1/testpb SimpleTest +*/ + +import ( + "fmt" + "io/fs" + "io/ioutil" + "os" + "path/filepath" + + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/encoding/prototext" + + spb "cel.dev/expr/proto/test/v1/testpb" + + // The following are needed to link in these proto libraries + // which are needed dynamically, despite not being explicitly + // used in the Go source. + _ "cel.dev/expr/proto/test/v1/proto2/test_all_types" + _ "cel.dev/expr/proto/test/v1/proto3/test_all_types" +) + +func parseSimpleFile(filename string) (*spb.SimpleTestFile, error) { + bytes, err := ioutil.ReadFile(filename) + if err != nil { + return nil, err + } + var pb spb.SimpleTestFile + err = prototext.Unmarshal(bytes, &pb) + if err != nil { + return nil, err + } + return &pb, nil +} + +var json_formatter = protojson.MarshalOptions{ + Multiline: true, + UseProtoNames: false, + EmitUnpopulated: false, +} + +func json_testfile(testFile *spb.SimpleTestFile) { + jsonString, _ := json_formatter.Marshal(testFile) + filename := fmt.Sprintf("%s.json", testFile.Name) + ioutil.WriteFile(filepath.Join("testdata", filename), jsonString, os.ModePerm) +} + +func globMatchFiles(root, ext string) []string { + var a []string + filepath.WalkDir(root, func(s string, d fs.DirEntry, e error) error { + if e != nil { + return e + } + if filepath.Ext(d.Name()) == ext { + a = append(a, s) + } + return nil + }) + return a +} + +func main() { + arr := globMatchFiles("testdata", ".textproto") + + for i := 0; i < len(arr); i++ { + input_file := arr[i] + fmt.Fprintf(os.Stderr, "Writing %v\n", input_file) + pb, err := parseSimpleFile(input_file) + if err != nil { + panic(err) + } + json_testfile(pb) + } +} diff --git a/packages/cel/src/lib/constants.spec.ts b/packages/cel/src/lib/constants.spec.ts new file mode 100644 index 0000000..abcc206 --- /dev/null +++ b/packages/cel/src/lib/constants.spec.ts @@ -0,0 +1,402 @@ +import { + parseBytesConstant, + parseDoubleConstant, + parseIntConstant, + parseStringConstant, + parseUintConstant, +} from './constants'; +import { ParseException } from './exceptions'; + +describe('ConstantsTest', () => { + it('parseInt_base10Zero', () => { + const constant = parseIntConstant('0'); + expect(constant.constantKind.case).toEqual('int64Value'); + expect(constant.constantKind.value).toEqual(BigInt(0)); + }); + + it('parseInt_base10Max', () => { + const constant = parseIntConstant(Number.MAX_SAFE_INTEGER.toString()); + expect(constant.constantKind.case).toEqual('int64Value'); + expect(constant.constantKind.value).toEqual( + BigInt(Number.MAX_SAFE_INTEGER) + ); + }); + + it('parseInt_base10Min', () => { + const constant = parseIntConstant(Number.MIN_SAFE_INTEGER.toString()); + expect(constant.constantKind.case).toEqual('int64Value'); + expect(constant.constantKind.value).toEqual( + BigInt(Number.MIN_SAFE_INTEGER) + ); + }); + + it('parseInt_base16Zero', () => { + const constant = parseIntConstant('0x0'); + expect(constant.constantKind.case).toEqual('int64Value'); + expect(constant.constantKind.value).toEqual(BigInt(0)); + }); + + it('parseInt_base16Max', () => { + const constant = parseIntConstant( + `0x${Number.MAX_SAFE_INTEGER.toString(16)}` + ); + expect(constant.constantKind.case).toEqual('int64Value'); + expect(constant.constantKind.value).toEqual( + BigInt(Number.MAX_SAFE_INTEGER) + ); + }); + + it('parseInt_base16Min', () => { + const constant = parseIntConstant( + `-0x${(-1 * Number.MIN_SAFE_INTEGER).toString(16)}` + ); + expect(constant.constantKind.case).toEqual('int64Value'); + expect(constant.constantKind.value).toEqual( + BigInt(Number.MIN_SAFE_INTEGER) + ); + }); + + it('parseInt_base16ThrowsOnInvalidArgument', () => { + expect(() => parseIntConstant('0xz')).toThrow(ParseException); + }); + + it('parseInt_base10ThrowsOnInvalidArgument', () => { + expect(() => parseIntConstant('abcdef')).toThrow(ParseException); + }); + + it('parseUint_base10Zero', () => { + let constant = parseUintConstant('0u'); + expect(constant.constantKind.case).toEqual('uint64Value'); + expect(constant.constantKind.value).toEqual(BigInt(0)); + constant = parseUintConstant('0U'); + expect(constant.constantKind.case).toEqual('uint64Value'); + expect(constant.constantKind.value).toEqual(BigInt(0)); + }); + + it('parseUint_base10Max', () => { + let constant = parseUintConstant(`${Number.MAX_SAFE_INTEGER.toString()}u`); + expect(constant.constantKind.case).toEqual('uint64Value'); + expect(constant.constantKind.value).toEqual( + BigInt(Number.MAX_SAFE_INTEGER) + ); + constant = parseUintConstant(`${Number.MAX_SAFE_INTEGER.toString()}U`); + expect(constant.constantKind.case).toEqual('uint64Value'); + expect(constant.constantKind.value).toEqual( + BigInt(Number.MAX_SAFE_INTEGER) + ); + }); + + it('parseUint_base16Zero', () => { + let constant = parseUintConstant('0x0u'); + expect(constant.constantKind.case).toEqual('uint64Value'); + expect(constant.constantKind.value).toEqual(BigInt(0)); + constant = parseUintConstant('0x0U'); + expect(constant.constantKind.case).toEqual('uint64Value'); + expect(constant.constantKind.value).toEqual(BigInt(0)); + }); + + it('parseUint_base16Max', () => { + let constant = parseUintConstant( + `0x${Number.MAX_SAFE_INTEGER.toString(16)}u` + ); + expect(constant.constantKind.case).toEqual('uint64Value'); + expect(constant.constantKind.value).toEqual( + BigInt(Number.MAX_SAFE_INTEGER) + ); + constant = parseUintConstant(`0x${Number.MAX_SAFE_INTEGER.toString(16)}U`); + expect(constant.constantKind.case).toEqual('uint64Value'); + expect(constant.constantKind.value).toEqual( + BigInt(Number.MAX_SAFE_INTEGER) + ); + }); + + it('parseUint_base16ThrowsOnInvalidArgument', () => { + expect(() => parseUintConstant('0xzu')).toThrow(ParseException); + expect(() => parseUintConstant('0xzU')).toThrow(ParseException); + }); + + it('parseUint_base10ThrowsOnInvalidArgument', () => { + expect(() => parseUintConstant('abcdefu')).toThrow(ParseException); + expect(() => parseUintConstant('abcdefU')).toThrow(ParseException); + }); + + it('parseUint_throwsOnMissingSuffix', () => { + expect(() => parseUintConstant('0')).toThrow(ParseException); + expect(() => parseUintConstant('0x0')).toThrow(ParseException); + }); + + it('parseDouble_positiveZero', () => { + const constant = parseDoubleConstant('0.0'); + expect(constant.constantKind.case).toEqual('doubleValue'); + expect(constant.constantKind.value).toEqual(0); + }); + + it('parseDouble_negativeZero', () => { + const constant = parseDoubleConstant('-0.0'); + expect(constant.constantKind.case).toEqual('doubleValue'); + expect(constant.constantKind.value).toEqual(-0); + }); + + it('parseDouble_max', () => { + const constant = parseDoubleConstant(Number.MAX_VALUE.toString()); + expect(constant.constantKind.case).toEqual('doubleValue'); + expect(constant.constantKind.value).toEqual(Number.MAX_VALUE); + }); + + it('parseDouble_negativeMax', () => { + const constant = parseDoubleConstant((-1 * Number.MAX_VALUE).toString()); + expect(constant.constantKind.case).toEqual('doubleValue'); + expect(constant.constantKind.value).toEqual(-1 * Number.MAX_VALUE); + }); + + it('parseDouble_min', () => { + const constant = parseDoubleConstant(Number.MIN_VALUE.toString()); + expect(constant.constantKind.case).toEqual('doubleValue'); + expect(constant.constantKind.value).toEqual(Number.MIN_VALUE); + }); + + it('parseDouble_throwsOnInvalidArgument', () => { + expect(() => parseDoubleConstant('abcd')).toThrow(ParseException); + }); + + it('parseString_throwsOnInvalidArgument', () => { + expect(() => parseStringConstant(``)).toThrow(ParseException); + expect(() => parseStringConstant(`"" '"`)).toThrow(ParseException); + expect(() => parseStringConstant(`''''`)).toThrow(ParseException); + }); + + it('parseString_escapeSequence', () => { + testQuotedString( + '\\a\\b\\f\\n\\r\\t\\v\\`\\\'\\"\\?\\\\', + '\u0007\b\f\n\r\t\u000b`\'"?\\' + ); + }); + + it('parseString_normalizesNewlines', () => { + testQuotedString('\r\n\r\n\n', '\n\n\n'); + }); + + it('parseString_throwsOnInvalidEscapeSequence', () => { + expect(() => parseStringConstant('"\\z"')).toThrow(ParseException); + expect(() => parseStringConstant('"\\\\\\"')).toThrow(ParseException); + }); + + it('parseString_throwsOnInvalidOctalEscapeSequence', () => { + expect(() => parseStringConstant('"\\0"')).toThrow(ParseException); + expect(() => parseStringConstant('"\\029"')).toThrow(ParseException); + }); + + it('parseString_hexEscapeSequence', () => { + // TODO: this doesn't work because of the double escapes. the same test with single escapes works + // it somehow ends up with "hx65lx6co" instead of "hello" + // testQuotedString('\\x68\\x65\\x6c\\x6c\\x6f', 'hello'); + testQuotedString('\x68\x65\x6c\x6c\x6f', 'hello'); + }); + + it('parseString_throwsOnInvalidHexEscapeSequence', () => { + expect(() => parseStringConstant('"\\x9"')).toThrow(ParseException); + expect(() => parseStringConstant('"\\x9g"')).toThrow(ParseException); + }); + + it('parseString_shortUnicodeEscapeSequence', () => { + // TODO: this doesn't work because of the double escapes. the same test with single escapes works + // it somehow ends up with "hu0065lu006co" instead of "hello" + // testQuotedString('\\u0068\\u0065\\u006c\\u006c\\u006f', 'hello'); + testQuotedString('\u0068\u0065\u006c\u006c\u006f', 'hello'); + }); + + it('parseString_throwsOnInvalidShortUnicodeEscapeSequence', () => { + expect(() => parseStringConstant('"\\u009"')).toThrow(ParseException); + expect(() => parseStringConstant('"\\u009g"')).toThrow(ParseException); + }); + + // TODO: this doesn't work because of the double escapes. the same test with single escapes works + // it somehow ends up with "hU00000065lU0000006co" instead of "hello" + // it('parseString_longUnicodeEscapeSequence', () => { + // testQuotedString( + // '\\U00000068\\U00000065\\U0000006c\\U0000006c\\U0000006f', + // 'hello' + // ); + // }); + + it('parseString_throwsOnInvalidLongUnicodeEscapeSequence', () => { + expect(() => parseStringConstant('"\\U0000009"')).toThrow(ParseException); + expect(() => parseStringConstant('"\\U0000009g"')).toThrow(ParseException); + }); + + it('parseString_throwsOnInvalidCodePoint', () => { + expect(() => parseStringConstant('"\\uD900"')).toThrow(ParseException); + expect(() => parseStringConstant('"\\uDD00"')).toThrow(ParseException); + expect(() => parseStringConstant('"\\uDD0"')).toThrow(ParseException); + expect(() => parseStringConstant('"\\U0000D900"')).toThrow(ParseException); + expect(() => parseStringConstant('"\\U0000DD00"')).toThrow(ParseException); + expect(() => parseStringConstant('"\\U00110000"')).toThrow(ParseException); + }); + + function testString(actual: string, expected: string) { + const constant = parseStringConstant(actual); + expect(constant.constantKind.case).toEqual('stringValue'); + expect(constant.constantKind.value).toEqual(expected); + } + + function testQuotedString(actual: string, expected: string) { + testString('"' + actual + '"', expected); + testString("'" + actual + "'", expected); + testString('"""' + actual + '"""', expected); + testString("'''" + actual + "'''", expected); + } + + it('parseBytes_throwsOnInvalidArgument', () => { + expect(() => parseBytesConstant('')).toThrow(ParseException); + expect(() => parseBytesConstant('b')).toThrow(ParseException); + expect(() => parseBytesConstant('b" \'')).toThrow(ParseException); + expect(() => parseBytesConstant("b''''")).toThrow(ParseException); + }); + + it('parseBytes_escapeSequence', () => { + testQuotedBytes( + '\\a\\b\\f\\n\\r\\t\\v\\`\\\'\\"\\?\\\\', + '\u0007\b\f\n\r\t\u000b`\'"?\\' + ); + }); + + it('parseBytes_normalizesNewlines', () => { + testQuotedBytes('\r\n\r\n\n', '\n\n\n'); + }); + + it('parseBytes_throwsOnInvalidEscapeSequence', () => { + expect(() => parseBytesConstant('"\\z"')).toThrow(ParseException); + expect(() => parseBytesConstant('"\\\\\\"')).toThrow(ParseException); + }); + + // TODO: this doesn't work. I'm guessing it's the same double escape issue + // it('parseBytes_octalEscapeSequence', () => { + // testQuotedBytes('\\150\\145\\154\\154\\157', 'hello'); + // }); + + it('parseBytes_throwsOnInvalidOctalEscapeSequence', () => { + expect(() => parseBytesConstant('"\\0"')).toThrow(ParseException); + expect(() => parseBytesConstant('"\\029"')).toThrow(ParseException); + }); + + it('parseBytes_hexEscapeSequence', () => { + // TODO: this doesn't work because of the double escapes. The same test with single escapes works + // testQuotedBytes("\\x68\\x65\\x6c\\x6c\\x6f", "hello"); + testQuotedBytes('\x68\x65\x6c\x6c\x6f', 'hello'); + }); + + it('parseBytes_throwsOnInvalidHexEscapeSequence', () => { + expect(() => parseBytesConstant('"\\x9"')).toThrow(ParseException); + expect(() => parseBytesConstant('"\\x9g"')).toThrow(ParseException); + }); + + it('parseBytes_throwsOnShortUnicodeEscapeSequence', () => { + expect(() => + parseBytesConstant('b"\\u0068\\u0065\\u006c\\u006c\\u006f"') + ).toThrow(ParseException); + }); + + it('parseBytes_throwsOnLongUnicodeEscapeSequence', () => { + expect(() => + parseBytesConstant( + 'b"\\U00000068\\U00000065\\U0000006c\\U0000006c\\U0000006f"' + ) + ).toThrow(ParseException); + }); + + it('parseBytes_multibyteCodePoints', () => { + const input = `a\u0080\u0800${(0x10000).toString(16)}`; + testQuotedBytes(input, input); + }); + + function testBytes(actual: string, expected: string) { + const constant = parseBytesConstant(actual); + expect(constant.constantKind.case).toEqual('bytesValue'); + expect(constant.constantKind.value).toEqual( + new TextEncoder().encode(expected) + ); + } + + function testQuotedBytes(actual: string, expected: string) { + testBytes('b"' + actual + '"', expected); + testBytes("b'" + actual + "'", expected); + testBytes('b"""' + actual + '"""', expected); + testBytes("b'''" + actual + "'''", expected); + } + + it('parseRawString_escapeSequence', () => { + // In raw strings, escape sequences are returned as is. + testRawQuotedString( + '\\a\\b\\f\\n\\r\\t\\v\\`\\\'\\"\\?\\\\', + '\\a\\b\\f\\n\\r\\t\\v\\`\\\'\\"\\?\\\\' + ); + }); + + function testRawString(actual: string, expected: string) { + const constant = parseStringConstant(actual); + expect(constant.constantKind.case).toEqual('stringValue'); + expect(constant.constantKind.value).toEqual(expected); + } + + function testRawQuotedString(actual: string, expected: string) { + testRawString('r"' + actual + '"', expected); + testRawString('R"' + actual + '"', expected); + testRawString("r'" + actual + "'", expected); + testRawString("R'" + actual + "'", expected); + testRawString('r"""' + actual + '"""', expected); + testRawString('R"""' + actual + '"""', expected); + testRawString("r'''" + actual + "'''", expected); + testRawString("R'''" + actual + "'''", expected); + } + + it('parseRawBytes_escapeSequence', () => { + // In raw strings, escape sequences are returned as is. + testRawQuotedBytes( + '\\a\\b\\f\\n\\r\\t\\v\\`\\\'\\"\\?\\\\', + '\\a\\b\\f\\n\\r\\t\\v\\`\\\'\\"\\?\\\\' + ); + }); + + function testRawBytes(actual: string, expected: string) { + const constant = parseBytesConstant(actual); + expect(constant.constantKind.case).toEqual('bytesValue'); + expect(constant.constantKind.value).toEqual( + new TextEncoder().encode(expected) + ); + } + + function testRawQuotedBytes(actual: string, expected: string) { + testRawBytes('br"' + actual + '"', expected); + testRawBytes('rb"' + actual + '"', expected); + testRawBytes('bR"' + actual + '"', expected); + testRawBytes('Rb"' + actual + '"', expected); + testRawBytes('Br"' + actual + '"', expected); + testRawBytes('rB"' + actual + '"', expected); + testRawBytes('BR"' + actual + '"', expected); + testRawBytes('RB"' + actual + '"', expected); + testRawBytes("br'" + actual + "'", expected); + testRawBytes("rb'" + actual + "'", expected); + testRawBytes("bR'" + actual + "'", expected); + testRawBytes("Rb'" + actual + "'", expected); + testRawBytes("Br'" + actual + "'", expected); + testRawBytes("rB'" + actual + "'", expected); + testRawBytes("BR'" + actual + "'", expected); + testRawBytes("RB'" + actual + "'", expected); + testRawBytes('br"""' + actual + '"""', expected); + testRawBytes('rb"""' + actual + '"""', expected); + testRawBytes('bR"""' + actual + '"""', expected); + testRawBytes('Rb"""' + actual + '"""', expected); + testRawBytes('Br"""' + actual + '"""', expected); + testRawBytes('rB"""' + actual + '"""', expected); + testRawBytes('BR"""' + actual + '"""', expected); + testRawBytes('RB"""' + actual + '"""', expected); + testRawBytes("br'''" + actual + "'''", expected); + testRawBytes("rb'''" + actual + "'''", expected); + testRawBytes("bR'''" + actual + "'''", expected); + testRawBytes("Rb'''" + actual + "'''", expected); + testRawBytes("Br'''" + actual + "'''", expected); + testRawBytes("rB'''" + actual + "'''", expected); + testRawBytes("BR'''" + actual + "'''", expected); + testRawBytes("RB'''" + actual + "'''", expected); + } +}); diff --git a/packages/cel/src/lib/constants.ts b/packages/cel/src/lib/constants.ts new file mode 100644 index 0000000..93380e6 --- /dev/null +++ b/packages/cel/src/lib/constants.ts @@ -0,0 +1,744 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +import { ConstantSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { ParseException } from './exceptions'; + +const DOUBLE_QUOTE = `"`; +const SINGLE_QUOTE = `'`; +const TRIPLE_DOUBLE_QUOTE = `"""`; +const TRIPLE_SINGLE_QUOTE = `'''`; +const MAX_SCRATCH_CODE_POINTS = 8; +const MIN_CODE_POINT = 0; +const MAX_CODE_POINT = 0x10ffff; +const MIN_SURROGATE = 0xd800; +const MAX_SURROGATE = 0xdfff; + +export const FALSE = false; +export const TRUE = true; +export const ERROR = '<>'; +export const ACCUMULATOR_VAR = '__result__'; + +/** + * Parse an integer literal to a Constant. + * + * @param text the text to parse + * @returns a Constant representing the parsed integer + */ +export function parseIntConstant(text: string) { + const isNegative = text.startsWith('-'); + if (isNegative) { + text = text.substring(1); + } + let value: bigint; + try { + value = BigInt(text); + if (isNegative) { + value = -value; + } + } catch (e) { + throw new ParseException( + e instanceof Error ? e.message : 'Integer literal is malformed', + 0 + ); + } + return create(ConstantSchema, { + constantKind: { + case: 'int64Value', + value, + }, + }); +} + +/** + * Parse an unsigned integer literal to a Constant. + * + * @param text the text to parse + * @returns a Constant representing the parsed unsigned integer + */ +export function parseUintConstant(text: string) { + if (!text.endsWith('u') && !text.endsWith('U')) { + throw new ParseException( + "Unsigned integer literal is missing trailing 'u' suffix", + 0 + ); + } + text = text.substring(0, text.length - 1); + + const isNegative = text.startsWith('-'); + if (isNegative) { + text = text.substring(1); + } + let value: bigint; + try { + value = BigInt(text); + if (isNegative) { + value = -value; + } + } catch (e) { + throw new ParseException( + e instanceof Error ? e.message : 'Unsigned integer literal is malformed', + 0 + ); + } + return create(ConstantSchema, { + constantKind: { + case: 'uint64Value', + value, + }, + }); +} + +/** + * Parse a double literal to a Constant. + * + * @param text the text to parse + * @returns a Constant representing the parsed double + */ +export function parseDoubleConstant(text: string) { + let value: number; + + try { + value = parseFloat(text); + if (isNaN(value)) { + throw new ParseException('Double literal is malformed', 0); + } + } catch (e) { + throw new ParseException( + e instanceof Error ? e.message : 'Double literal is malformed', + 0 + ); + } + return create(ConstantSchema, { + constantKind: { + case: 'doubleValue', + value, + }, + }); +} + +function nextInts( + iterator: IterableIterator, + count: number, + scratch: number[] +): boolean { + if (count > scratch.length) { + throw new ParseException('Count exceeds scratch array length', 0); + } + let index = 0; + let next = iterator.next(); + while (!next.done && index < count) { + scratch[index++] = next.value.codePointAt(0)!; + next = iterator.next(); + } + return index === count; +} + +function isOctalDigit(codePoint: number): boolean { + return codePoint >= '0'.charCodeAt(0) && codePoint <= '7'.charCodeAt(0); +} + +function areOctalDigits(codePoints: number[], count: number): boolean { + checkArgument(count <= codePoints.length); + for (let index = 0; index < count; index++) { + if (!isOctalDigit(codePoints[index])) { + return false; + } + } + return true; +} + +function isHexDigit(codePoint: number): boolean { + return ( + (codePoint >= 'a'.charCodeAt(0) && codePoint <= 'f'.charCodeAt(0)) || + (codePoint >= 'A'.charCodeAt(0) && codePoint <= 'F'.charCodeAt(0)) || + (codePoint >= '0'.charCodeAt(0) && codePoint <= '9'.charCodeAt(0)) + ); +} + +function areHexDigits(codePoints: number[], count: number): boolean { + checkArgument(count <= codePoints.length); + for (let index = 0; index < count; index++) { + if (!isHexDigit(codePoints[index])) { + return false; + } + } + return true; +} + +function isDigit(codePoint: number): boolean { + return codePoint >= '0'.charCodeAt(0) && codePoint <= '9'.charCodeAt(0); +} + +function toLowerCase(codePoint: number): number { + return codePoint >= 'A'.charCodeAt(0) && codePoint <= 'Z'.charCodeAt(0) + ? codePoint - 'A'.charCodeAt(0) + 'a'.charCodeAt(0) + : codePoint; +} + +function checkArgument(condition: boolean): void { + if (!condition) { + throw new ParseException('Invalid argument', 0); + } +} + +function checkForClosingQuote(text: string, quote: string): void { + if (quote.length === 0) { + return; + } + if (text.length < quote.length) { + throw new ParseException( + `String literal missing terminating quote ${quote}`, + 0 + ); + } + let position = 0; + let isClosed = false; + while (position + quote.length <= text.length) { + const codeUnit = text.charAt(position); + if (codeUnit !== '\\') { + if (text.substring(position).startsWith(quote)) { + isClosed = position + quote.length === text.length; + break; + } + } else { + position++; + } + position++; + } + if (!isClosed) { + throw new ParseException( + `String literal contains unescaped terminating quote ${quote}`, + position + ); + } +} + +function unhex(value: number, nextValue: number): number { + if (isDigit(nextValue)) { + return value * 16 + (nextValue - '0'.charCodeAt(0)); + } else { + return value * 16 + (toLowerCase(nextValue) - 'a'.charCodeAt(0) + 10); + } +} + +function unhexFromArray(codePoints: number[], length: number): number { + let value = 0; + + for (let index = 0; index < length; index++) { + value = unhex(value, codePoints[index]); + } + + return value; +} + +// function unhex(value: number | number[], nextValue?: number): number { +// if (Array.isArray(value)) { +// let result = 0; +// for (let index = 0; index < value.length; index++) { +// result = unhex(result, value[index]); +// } +// return result; +// } else { +// if (isDigit(nextValue!)) { +// return value * 16 + (nextValue! - '0'.charCodeAt(0)); +// } else { +// return ( +// value * 16 + +// (nextValue!.toString().toLowerCase().charCodeAt(0) - +// 'a'.charCodeAt(0) + +// 10) +// ); +// } +// } +// } + +export class ByteString { + private readonly data: Uint8Array; + + private constructor(data: Uint8Array) { + this.data = data; + } + + static copyFrom(bytes: Uint8Array): ByteString { + const copiedBytes = new Uint8Array(bytes); + return new ByteString(copiedBytes); + } + + static newOutput(initialCapacity: number): Output { + return new Output(initialCapacity); + } + + toUint8Array(): Uint8Array { + return new Uint8Array(this.data); + } + + toString(encoding: BufferEncoding = 'utf-8'): string { + const buffer = Buffer.from(this.data); + return buffer.toString(encoding); + } +} + +class Output { + private buffer: Uint8Array = new Uint8Array(); + + constructor(private initialCapacity: number) {} + + write(value: number): void { + const newBuffer = new Uint8Array(this.buffer.length + 1); + newBuffer.set(this.buffer); + newBuffer[this.buffer.length] = value; + this.buffer = newBuffer; + } + + toByteString(): ByteString { + return ByteString.copyFrom(this.buffer); + } +} + +export class StringBuilder { + private value: string; + + constructor(initialValue = '') { + this.value = initialValue; + } + + append(str: string): void { + this.value += str; + } + + appendCodePoint(codePoint: number): void { + this.value += String.fromCodePoint(codePoint); + } + + toString(): string { + return this.value; + } +} + +interface DecodeBuffer { + appendByte(b: number): void; + appendCodePoint(codePoint: number): void; + toDecodedValue(): T; +} + +class DecodeByteStringBuffer implements DecodeBuffer { + private readonly output: Output; + + constructor(initialCapacity: number) { + this.output = ByteString.newOutput(initialCapacity); + } + + appendByte(b: number): void { + this.output.write(b); + } + + appendCodePoint(codePoint: number): void { + if (codePoint < MIN_CODE_POINT || codePoint > MAX_CODE_POINT) { + throw new ParseException('Invalid code point', 0); + } + + if (codePoint < 0x80) { + this.output.write(codePoint); + } else if (codePoint < 0x800) { + this.output.write((0xf << 6) | (codePoint >>> 6)); + this.output.write(0x80 | (0x3f & codePoint)); + } else if (codePoint < 0x10000) { + this.output.write((0xf << 5) | (codePoint >>> 12)); + this.output.write(0x80 | (0x3f & (codePoint >>> 6))); + this.output.write(0x80 | (0x3f & codePoint)); + } else { + this.output.write((0xf << 4) | (codePoint >>> 18)); + this.output.write(0x80 | (0x3f & (codePoint >>> 12))); + this.output.write(0x80 | (0x3f & (codePoint >>> 6))); + this.output.write(0x80 | (0x3f & codePoint)); + } + } + + toDecodedValue(): ByteString { + return this.output.toByteString(); + } +} + +class DecodeStringBuffer implements DecodeBuffer { + private readonly builder: StringBuilder; + + constructor() { + this.builder = new StringBuilder(); + } + + appendByte(b: number): void { + this.builder.appendCodePoint(b & 0xff); + } + + appendCodePoint(codePoint: number): void { + if (codePoint < MIN_CODE_POINT || codePoint > MAX_CODE_POINT) { + throw new ParseException('Invalid code point', 0); + } + this.builder.appendCodePoint(codePoint); + } + + toDecodedValue(): string { + return this.builder.toString(); + } +} + +function decodeString( + offset: number, + text: string, + buffer: DecodeBuffer, + isRawLiteral: boolean, + isBytesLiteral: boolean +): void { + let skipNewline = false; + const iterator = text[Symbol.iterator](); + let scratchCodePoints: number[] | null = null; + + // eslint-disable-next-line no-constant-condition + while (true) { + const seqOffset = offset; // Save offset for the start of this sequence. + const result = iterator.next(); + + if (result.done) { + break; + } + + const codePoint = result.value; + offset++; + + if (codePoint !== '\\') { + if (codePoint !== '\r') { + if (codePoint === '\n' && skipNewline) { + skipNewline = false; + continue; + } + skipNewline = false; + buffer.appendCodePoint(codePoint.codePointAt(0)!); + } else { + // Normalize '\r' and '\r\n' to '\n'. + buffer.appendCodePoint('\n'.codePointAt(0)!); + skipNewline = true; + } + } else { + // An escape sequence. + skipNewline = false; + + const nextResult = iterator.next(); + if (nextResult.done) { + throw new ParseException( + isRawLiteral + ? 'Raw literals cannot end with an odd number of \\' + : isBytesLiteral + ? 'Bytes literal cannot end with \\' + : 'String literal cannot end with \\', + seqOffset + ); + } + + const nextCodePoint = nextResult.value; + offset++; + + if (isRawLiteral) { + // For raw literals, all escapes are valid and those characters come through literally in the string. + buffer.appendCodePoint('\\'.codePointAt(0)!); + buffer.appendCodePoint(nextCodePoint.codePointAt(0)!); + continue; + } + + switch (nextCodePoint) { + case 'a': + buffer.appendByte(7); + break; + case 'b': + buffer.appendByte('\b'.codePointAt(0)!); + break; + case 'f': + buffer.appendByte('\f'.codePointAt(0)!); + break; + case 'n': + buffer.appendByte('\n'.codePointAt(0)!); + break; + case 'r': + buffer.appendByte('\r'.codePointAt(0)!); + break; + case 't': + buffer.appendByte('\t'.codePointAt(0)!); + break; + case 'v': + buffer.appendByte(11); + break; + case '"': + buffer.appendByte('"'.codePointAt(0)!); + break; + case "'": + buffer.appendByte("'".codePointAt(0)!); + break; + case '\\': + buffer.appendByte('\\'.codePointAt(0)!); + break; + case '?': + buffer.appendByte('?'.codePointAt(0)!); + break; + case '`': + buffer.appendByte('`'.codePointAt(0)!); + break; + case '0': + case '1': + case '2': + case '3': + { + if (scratchCodePoints === null) { + scratchCodePoints = new Array(MAX_SCRATCH_CODE_POINTS); + } + // There needs to be 2 octal digits. + if ( + !nextInts(iterator, 2, scratchCodePoints) || + !areOctalDigits(scratchCodePoints, 2) + ) { + throw new ParseException( + 'Invalid octal escape sequence', + seqOffset + ); + } + let octalValue = + nextCodePoint.codePointAt(0)! - '0'.codePointAt(0)!; + octalValue = + octalValue * 8 + (scratchCodePoints[0] - '0'.codePointAt(0)!); + octalValue = + octalValue * 8 + (scratchCodePoints[1] - '0'.codePointAt(0)!); + buffer.appendByte(octalValue); + offset += 2; + } + break; + case 'x': + case 'X': + { + if (scratchCodePoints === null) { + scratchCodePoints = new Array(MAX_SCRATCH_CODE_POINTS); + } + // There needs to be 2 hex digits. + if ( + !nextInts(iterator, 2, scratchCodePoints) || + !areHexDigits(scratchCodePoints, 2) + ) { + throw new ParseException( + 'Invalid hex escape sequence', + seqOffset + ); + } + const value = unhexFromArray(scratchCodePoints, 2); + buffer.appendByte(value); + offset += 2; + } + break; + case 'u': + { + if (isBytesLiteral) { + throw new ParseException( + 'Illegal escape sequence: Unicode escape sequences cannot be used in bytes literal', + seqOffset + ); + } + if (scratchCodePoints === null) { + scratchCodePoints = new Array(MAX_SCRATCH_CODE_POINTS); + } + // There needs to be 4 hex digits. + if ( + !nextInts(iterator, 4, scratchCodePoints) || + !areHexDigits(scratchCodePoints, 4) + ) { + throw new ParseException( + 'Invalid unicode escape sequence', + seqOffset + ); + } + const value = unhexFromArray(scratchCodePoints, 4); + if ( + value < MIN_CODE_POINT || + value > MAX_CODE_POINT || + (value >= MIN_SURROGATE && value <= MAX_SURROGATE) + ) { + throw new ParseException('Invalid unicode code point', seqOffset); + } + buffer.appendCodePoint(value); + offset += 4; + } + break; + case 'U': + { + if (isBytesLiteral) { + throw new ParseException( + 'Illegal escape sequence: Unicode escape sequences cannot be used in bytes literal', + offset + ); + } + if (scratchCodePoints === null) { + scratchCodePoints = new Array(MAX_SCRATCH_CODE_POINTS); + } + // There needs to be 8 hex digits. + if ( + !nextInts(iterator, 8, scratchCodePoints) || + !areHexDigits(scratchCodePoints, 8) + ) { + throw new ParseException( + 'Invalid unicode escape sequence', + seqOffset + ); + } + const value = unhexFromArray(scratchCodePoints, 8); + if ( + value < MIN_CODE_POINT || + value > MAX_CODE_POINT || + (value >= MIN_SURROGATE && value <= MAX_SURROGATE) + ) { + throw new ParseException('Invalid unicode code point', seqOffset); + } + buffer.appendCodePoint(value); + offset += 8; + } + break; + default: + throw new ParseException('Illegal escape sequence', seqOffset); + } + } + } +} + +export function parseStringConstant(text: string) { + let offset = 0; + let isRawLiteral = false; + + if (text.startsWith('r') || text.startsWith('R')) { + isRawLiteral = true; + text = text.substring(1); + offset++; + } + + let quote: string; + if (text.startsWith(TRIPLE_DOUBLE_QUOTE)) { + quote = TRIPLE_DOUBLE_QUOTE; + text = text.substring(quote.length); + } else if (text.startsWith(TRIPLE_SINGLE_QUOTE)) { + quote = TRIPLE_SINGLE_QUOTE; + text = text.substring(quote.length); + } else if (text.startsWith(DOUBLE_QUOTE)) { + quote = DOUBLE_QUOTE; + text = text.substring(quote.length); + } else if (text.startsWith(SINGLE_QUOTE)) { + quote = SINGLE_QUOTE; + text = text.substring(quote.length); + } else { + throw new ParseException( + 'String literal is missing surrounding single or double quotes', + 0 + ); + } + + checkForClosingQuote(text, quote); + offset += quote.length; + text = text.substring(0, text.length - quote.length); + + const buffer = new DecodeStringBuffer(); + decodeString(offset, text, buffer, isRawLiteral, false); + + return create(ConstantSchema, { + constantKind: { + case: 'stringValue', + value: buffer.toDecodedValue(), + }, + }); +} + +export function parseBytesConstant(text: string) { + let isRawLiteral = false; + let offset = 0; + + if (text.startsWith('r') || text.startsWith('R')) { + isRawLiteral = true; + text = text.substring(1); + offset++; + + if (!text.startsWith('b') && !text.startsWith('B')) { + throw new ParseException( + "Bytes literal is missing leading 'b' or 'B' prefix", + 0 + ); + } + + text = text.substring(1); + offset++; + } else { + if (!text.startsWith('b') && !text.startsWith('B')) { + throw new ParseException( + "Bytes literal is missing leading 'b' or 'B' prefix", + 0 + ); + } + + text = text.substring(1); + offset++; + + if (text.startsWith('r') || text.startsWith('R')) { + isRawLiteral = true; + text = text.substring(1); + offset++; + } + } + + let quote: string; + if (text.startsWith(TRIPLE_DOUBLE_QUOTE)) { + quote = TRIPLE_DOUBLE_QUOTE; + text = text.substring(quote.length); + } else if (text.startsWith(TRIPLE_SINGLE_QUOTE)) { + quote = TRIPLE_SINGLE_QUOTE; + text = text.substring(quote.length); + } else if (text.startsWith(DOUBLE_QUOTE)) { + quote = DOUBLE_QUOTE; + text = text.substring(quote.length); + } else if (text.startsWith(SINGLE_QUOTE)) { + quote = SINGLE_QUOTE; + text = text.substring(quote.length); + } else { + throw new ParseException( + 'Bytes literal is missing surrounding single or double quotes', + 0 + ); + } + + checkForClosingQuote(text, quote); + offset += quote.length; + text = text.substring(0, text.length - quote.length); + + const buffer = new DecodeByteStringBuffer(text.length); + decodeString(offset, text, buffer, isRawLiteral, true); + + return create(ConstantSchema, { + constantKind: { + case: 'bytesValue', + value: buffer.toDecodedValue().toUint8Array(), + }, + }); +} + +export const RESERVED_IDS = new Set([ + 'as', + 'break', + 'const', + 'continue', + 'else', + 'false', + 'for', + 'function', + 'if', + 'import', + 'in', + 'let', + 'loop', + 'package', + 'namespace', + 'null', + 'return', + 'true', + 'var', + 'void', + 'while', +]); diff --git a/packages/cel/src/lib/environment.ts b/packages/cel/src/lib/environment.ts new file mode 100644 index 0000000..8b09d8b --- /dev/null +++ b/packages/cel/src/lib/environment.ts @@ -0,0 +1,69 @@ +import { Decl } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { + DescEnum, + DescExtension, + DescMessage, + DescService, + MutableRegistry, + Registry, + createMutableRegistry, +} from '@bufbuild/protobuf'; +import { CharStream, CommonTokenStream } from 'antlr4'; +import CELLexer from './gen/CELLexer'; +import CELParser, { StartContext } from './gen/CELParser'; + +export interface CELEnvironmentOptions { + container?: string; + registry?: MutableRegistry; + declarations?: Decl[]; +} + +export class CELEnvironment { + public readonly container?: string; + public readonly registry: MutableRegistry; + public readonly declarations: Decl[]; + + constructor(options?: CELEnvironmentOptions) { + this.container = options?.container; + this.registry = options?.registry ?? createMutableRegistry(); + this.declarations = options?.declarations ?? []; + } + + compile(input: string, check = false): StartContext { + const chars = new CharStream(input); + const lexer = new CELLexer(chars); + const tokens = new CommonTokenStream(lexer); + const parser = new CELParser(tokens); + const tree = parser.start(); + if (tree.exception) throw tree.exception; + if (check) this.check(tree); + return tree; + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + check(ast: StartContext) { + // TODO: implement + } + + addDeclaration(decl: Decl) { + this.declarations.push(decl); + } + + addDescriptor( + descriptor: DescMessage | DescEnum | DescExtension | DescService + ) { + this.registry.add(descriptor); + } + + mergeDeclarations(decls: Decl[]) { + for (const decl of decls) { + this.addDeclaration(decl); + } + } + + mergeRegistry(registry: Registry) { + for (const descriptor of registry) { + this.addDescriptor(descriptor); + } + } +} diff --git a/packages/cel/src/lib/exceptions.ts b/packages/cel/src/lib/exceptions.ts new file mode 100644 index 0000000..352df9f --- /dev/null +++ b/packages/cel/src/lib/exceptions.ts @@ -0,0 +1,17 @@ +/** + * Signals that an error has been reached unexpectedly while parsing. + */ +export class ParseException extends Error { + constructor(public override message: string, public offset: number) { + super(message); + } +} + +/** + * Signals that a null value was encountered unexpectedly while parsing. + */ +export class NullException extends Error { + constructor(public override message: string) { + super(message); + } +} diff --git a/packages/cel/src/lib/gen/CEL.g4 b/packages/cel/src/lib/gen/CEL.g4 new file mode 100644 index 0000000..6494452 --- /dev/null +++ b/packages/cel/src/lib/gen/CEL.g4 @@ -0,0 +1,191 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. + +grammar CEL; + +// Grammar Rules ============= + +start: e = expr EOF; + +expr: + e = conditionalOr (op = '?' e1 = conditionalOr ':' e2 = expr)?; + +conditionalOr: + e = conditionalAnd (ops += '||' e1 += conditionalAnd)*; + +conditionalAnd: e = relation (ops += '&&' e1 += relation)*; + +relation: + calc + | relation op = ( + '<' + | '<=' + | '>=' + | '>' + | '==' + | '!=' + | 'in' + ) relation; + +calc: + unary + | calc op = ('*' | '/' | '%') calc + | calc op = ('+' | '-') calc; + +unary: + member # MemberExpr + | (ops += '!')+ member # LogicalNot + | (ops += '-')+ member # Negate; + +member: + primary # PrimaryExpr + | member op = '.' (opt = '?')? id = IDENTIFIER # Select + | member op = '.' id = IDENTIFIER open = '(' args = exprList? ')' # MemberCall + | member op = '[' (opt = '?')? index = expr ']' # Index; + +primary: + leadingDot = '.'? id = IDENTIFIER ( + op = '(' args = exprList? ')' + )? # IdentOrGlobalCall + | '(' e = expr ')' # Nested + | op = '[' elems = listInit? ','? ']' # CreateList + | op = '{' entries = mapInitializerList? ','? '}' # CreateStruct + | leadingDot = '.'? ids += IDENTIFIER ( + ops += '.' ids += IDENTIFIER + )* op = '{' entries = fieldInitializerList? ','? '}' # CreateMessage + | literal # ConstantLiteral; + +exprList: e += expr (',' e += expr)*; + +listInit: elems += optExpr (',' elems += optExpr)*; + +fieldInitializerList: + fields += optField cols += ':' values += expr ( + ',' fields += optField cols += ':' values += expr + )*; + +optField: (opt = '?')? IDENTIFIER; + +mapInitializerList: + keys += optExpr cols += ':' values += expr ( + ',' keys += optExpr cols += ':' values += expr + )*; + +optExpr: (opt = '?')? e = expr; + +literal: + sign = MINUS? tok = NUM_INT # Int + | tok = NUM_UINT # Uint + | sign = MINUS? tok = NUM_FLOAT # Double + | tok = STRING # String + | tok = BYTES # Bytes + | tok = CEL_TRUE # BoolTrue + | tok = CEL_FALSE # BoolFalse + | tok = NUL # Null; + +// Lexer Rules =========== + +EQUALS: '=='; +NOT_EQUALS: '!='; +IN: 'in'; +LESS: '<'; +LESS_EQUALS: '<='; +GREATER_EQUALS: '>='; +GREATER: '>'; +LOGICAL_AND: '&&'; +LOGICAL_OR: '||'; + +LBRACKET: '['; +RPRACKET: ']'; +LBRACE: '{'; +RBRACE: '}'; +LPAREN: '('; +RPAREN: ')'; +DOT: '.'; +COMMA: ','; +MINUS: '-'; +EXCLAM: '!'; +QUESTIONMARK: '?'; +COLON: ':'; +PLUS: '+'; +STAR: '*'; +SLASH: '/'; +PERCENT: '%'; +CEL_TRUE: 'true'; +CEL_FALSE: 'false'; +NUL: 'null'; + +fragment BACKSLASH: '\\'; +fragment LETTER: 'A' ..'Z' | 'a' ..'z'; +fragment DIGIT: '0' ..'9'; +fragment EXPONENT: ('e' | 'E') ( '+' | '-')? DIGIT+; +fragment HEXDIGIT: ('0' ..'9' | 'a' ..'f' | 'A' ..'F'); +fragment RAW: 'r' | 'R'; + +fragment ESC_SEQ: + ESC_CHAR_SEQ + | ESC_BYTE_SEQ + | ESC_UNI_SEQ + | ESC_OCT_SEQ; + +fragment ESC_CHAR_SEQ: + BACKSLASH ( + 'a' + | 'b' + | 'f' + | 'n' + | 'r' + | 't' + | 'v' + | '"' + | '\'' + | '\\' + | '?' + | '`' + ); + +fragment ESC_OCT_SEQ: + BACKSLASH ('0' ..'3') ('0' ..'7') ('0' ..'7'); + +fragment ESC_BYTE_SEQ: BACKSLASH ( 'x' | 'X') HEXDIGIT HEXDIGIT; + +fragment ESC_UNI_SEQ: + BACKSLASH 'u' HEXDIGIT HEXDIGIT HEXDIGIT HEXDIGIT + | BACKSLASH 'U' HEXDIGIT HEXDIGIT HEXDIGIT HEXDIGIT HEXDIGIT HEXDIGIT HEXDIGIT HEXDIGIT; + +WHITESPACE: ('\t' | ' ' | '\r' | '\n' | '\u000C')+ -> channel(HIDDEN); +COMMENT: '//' (~'\n')* -> channel(HIDDEN); + +NUM_FLOAT: ( + DIGIT+ ('.' DIGIT+) EXPONENT? + | DIGIT+ EXPONENT + | '.' DIGIT+ EXPONENT? + ); + +NUM_INT: ( DIGIT+ | '0x' HEXDIGIT+); + +NUM_UINT: DIGIT+ ( 'u' | 'U') | '0x' HEXDIGIT+ ( 'u' | 'U'); + +STRING: + '"' (ESC_SEQ | ~('\\' | '"' | '\n' | '\r'))* '"' + | '\'' (ESC_SEQ | ~('\\' | '\'' | '\n' | '\r'))* '\'' + | '"""' (ESC_SEQ | ~('\\'))*? '"""' + | '\'\'\'' (ESC_SEQ | ~('\\'))*? '\'\'\'' + | RAW '"' ~('"' | '\n' | '\r')* '"' + | RAW '\'' ~('\'' | '\n' | '\r')* '\'' + | RAW '"""' .*? '"""' + | RAW '\'\'\'' .*? '\'\'\''; + +BYTES: ('b' | 'B') STRING; + +IDENTIFIER: (LETTER | '_') ( LETTER | DIGIT | '_')*; \ No newline at end of file diff --git a/packages/cel/src/lib/gen/CEL.interp b/packages/cel/src/lib/gen/CEL.interp new file mode 100644 index 0000000..75b8bb3 --- /dev/null +++ b/packages/cel/src/lib/gen/CEL.interp @@ -0,0 +1,99 @@ +token literal names: +null +'==' +'!=' +'in' +'<' +'<=' +'>=' +'>' +'&&' +'||' +'[' +']' +'{' +'}' +'(' +')' +'.' +',' +'-' +'!' +'?' +':' +'+' +'*' +'/' +'%' +'true' +'false' +'null' +null +null +null +null +null +null +null +null + +token symbolic names: +null +EQUALS +NOT_EQUALS +IN +LESS +LESS_EQUALS +GREATER_EQUALS +GREATER +LOGICAL_AND +LOGICAL_OR +LBRACKET +RPRACKET +LBRACE +RBRACE +LPAREN +RPAREN +DOT +COMMA +MINUS +EXCLAM +QUESTIONMARK +COLON +PLUS +STAR +SLASH +PERCENT +CEL_TRUE +CEL_FALSE +NUL +WHITESPACE +COMMENT +NUM_FLOAT +NUM_INT +NUM_UINT +STRING +BYTES +IDENTIFIER + +rule names: +start +expr +conditionalOr +conditionalAnd +relation +calc +unary +member +primary +exprList +listInit +fieldInitializerList +optField +mapInitializerList +optExpr +literal + + +atn: +[4, 1, 36, 251, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 42, 8, 1, 1, 2, 1, 2, 1, 2, 5, 2, 47, 8, 2, 10, 2, 12, 2, 50, 9, 2, 1, 3, 1, 3, 1, 3, 5, 3, 55, 8, 3, 10, 3, 12, 3, 58, 9, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 5, 4, 66, 8, 4, 10, 4, 12, 4, 69, 9, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 80, 8, 5, 10, 5, 12, 5, 83, 9, 5, 1, 6, 1, 6, 4, 6, 87, 8, 6, 11, 6, 12, 6, 88, 1, 6, 1, 6, 4, 6, 93, 8, 6, 11, 6, 12, 6, 94, 1, 6, 3, 6, 98, 8, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 106, 8, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 114, 8, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 120, 8, 7, 1, 7, 1, 7, 1, 7, 5, 7, 125, 8, 7, 10, 7, 12, 7, 128, 9, 7, 1, 8, 3, 8, 131, 8, 8, 1, 8, 1, 8, 1, 8, 3, 8, 136, 8, 8, 1, 8, 3, 8, 139, 8, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 3, 8, 147, 8, 8, 1, 8, 3, 8, 150, 8, 8, 1, 8, 1, 8, 1, 8, 3, 8, 155, 8, 8, 1, 8, 3, 8, 158, 8, 8, 1, 8, 1, 8, 3, 8, 162, 8, 8, 1, 8, 1, 8, 1, 8, 5, 8, 167, 8, 8, 10, 8, 12, 8, 170, 9, 8, 1, 8, 1, 8, 3, 8, 174, 8, 8, 1, 8, 3, 8, 177, 8, 8, 1, 8, 1, 8, 3, 8, 181, 8, 8, 1, 9, 1, 9, 1, 9, 5, 9, 186, 8, 9, 10, 9, 12, 9, 189, 9, 9, 1, 10, 1, 10, 1, 10, 5, 10, 194, 8, 10, 10, 10, 12, 10, 197, 9, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 5, 11, 207, 8, 11, 10, 11, 12, 11, 210, 9, 11, 1, 12, 3, 12, 213, 8, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 5, 13, 225, 8, 13, 10, 13, 12, 13, 228, 9, 13, 1, 14, 3, 14, 231, 8, 14, 1, 14, 1, 14, 1, 15, 3, 15, 236, 8, 15, 1, 15, 1, 15, 1, 15, 3, 15, 241, 8, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 3, 15, 249, 8, 15, 1, 15, 0, 3, 8, 10, 14, 16, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 0, 3, 1, 0, 1, 7, 1, 0, 23, 25, 2, 0, 18, 18, 22, 22, 281, 0, 32, 1, 0, 0, 0, 2, 35, 1, 0, 0, 0, 4, 43, 1, 0, 0, 0, 6, 51, 1, 0, 0, 0, 8, 59, 1, 0, 0, 0, 10, 70, 1, 0, 0, 0, 12, 97, 1, 0, 0, 0, 14, 99, 1, 0, 0, 0, 16, 180, 1, 0, 0, 0, 18, 182, 1, 0, 0, 0, 20, 190, 1, 0, 0, 0, 22, 198, 1, 0, 0, 0, 24, 212, 1, 0, 0, 0, 26, 216, 1, 0, 0, 0, 28, 230, 1, 0, 0, 0, 30, 248, 1, 0, 0, 0, 32, 33, 3, 2, 1, 0, 33, 34, 5, 0, 0, 1, 34, 1, 1, 0, 0, 0, 35, 41, 3, 4, 2, 0, 36, 37, 5, 20, 0, 0, 37, 38, 3, 4, 2, 0, 38, 39, 5, 21, 0, 0, 39, 40, 3, 2, 1, 0, 40, 42, 1, 0, 0, 0, 41, 36, 1, 0, 0, 0, 41, 42, 1, 0, 0, 0, 42, 3, 1, 0, 0, 0, 43, 48, 3, 6, 3, 0, 44, 45, 5, 9, 0, 0, 45, 47, 3, 6, 3, 0, 46, 44, 1, 0, 0, 0, 47, 50, 1, 0, 0, 0, 48, 46, 1, 0, 0, 0, 48, 49, 1, 0, 0, 0, 49, 5, 1, 0, 0, 0, 50, 48, 1, 0, 0, 0, 51, 56, 3, 8, 4, 0, 52, 53, 5, 8, 0, 0, 53, 55, 3, 8, 4, 0, 54, 52, 1, 0, 0, 0, 55, 58, 1, 0, 0, 0, 56, 54, 1, 0, 0, 0, 56, 57, 1, 0, 0, 0, 57, 7, 1, 0, 0, 0, 58, 56, 1, 0, 0, 0, 59, 60, 6, 4, -1, 0, 60, 61, 3, 10, 5, 0, 61, 67, 1, 0, 0, 0, 62, 63, 10, 1, 0, 0, 63, 64, 7, 0, 0, 0, 64, 66, 3, 8, 4, 2, 65, 62, 1, 0, 0, 0, 66, 69, 1, 0, 0, 0, 67, 65, 1, 0, 0, 0, 67, 68, 1, 0, 0, 0, 68, 9, 1, 0, 0, 0, 69, 67, 1, 0, 0, 0, 70, 71, 6, 5, -1, 0, 71, 72, 3, 12, 6, 0, 72, 81, 1, 0, 0, 0, 73, 74, 10, 2, 0, 0, 74, 75, 7, 1, 0, 0, 75, 80, 3, 10, 5, 3, 76, 77, 10, 1, 0, 0, 77, 78, 7, 2, 0, 0, 78, 80, 3, 10, 5, 2, 79, 73, 1, 0, 0, 0, 79, 76, 1, 0, 0, 0, 80, 83, 1, 0, 0, 0, 81, 79, 1, 0, 0, 0, 81, 82, 1, 0, 0, 0, 82, 11, 1, 0, 0, 0, 83, 81, 1, 0, 0, 0, 84, 98, 3, 14, 7, 0, 85, 87, 5, 19, 0, 0, 86, 85, 1, 0, 0, 0, 87, 88, 1, 0, 0, 0, 88, 86, 1, 0, 0, 0, 88, 89, 1, 0, 0, 0, 89, 90, 1, 0, 0, 0, 90, 98, 3, 14, 7, 0, 91, 93, 5, 18, 0, 0, 92, 91, 1, 0, 0, 0, 93, 94, 1, 0, 0, 0, 94, 92, 1, 0, 0, 0, 94, 95, 1, 0, 0, 0, 95, 96, 1, 0, 0, 0, 96, 98, 3, 14, 7, 0, 97, 84, 1, 0, 0, 0, 97, 86, 1, 0, 0, 0, 97, 92, 1, 0, 0, 0, 98, 13, 1, 0, 0, 0, 99, 100, 6, 7, -1, 0, 100, 101, 3, 16, 8, 0, 101, 126, 1, 0, 0, 0, 102, 103, 10, 3, 0, 0, 103, 105, 5, 16, 0, 0, 104, 106, 5, 20, 0, 0, 105, 104, 1, 0, 0, 0, 105, 106, 1, 0, 0, 0, 106, 107, 1, 0, 0, 0, 107, 125, 5, 36, 0, 0, 108, 109, 10, 2, 0, 0, 109, 110, 5, 16, 0, 0, 110, 111, 5, 36, 0, 0, 111, 113, 5, 14, 0, 0, 112, 114, 3, 18, 9, 0, 113, 112, 1, 0, 0, 0, 113, 114, 1, 0, 0, 0, 114, 115, 1, 0, 0, 0, 115, 125, 5, 15, 0, 0, 116, 117, 10, 1, 0, 0, 117, 119, 5, 10, 0, 0, 118, 120, 5, 20, 0, 0, 119, 118, 1, 0, 0, 0, 119, 120, 1, 0, 0, 0, 120, 121, 1, 0, 0, 0, 121, 122, 3, 2, 1, 0, 122, 123, 5, 11, 0, 0, 123, 125, 1, 0, 0, 0, 124, 102, 1, 0, 0, 0, 124, 108, 1, 0, 0, 0, 124, 116, 1, 0, 0, 0, 125, 128, 1, 0, 0, 0, 126, 124, 1, 0, 0, 0, 126, 127, 1, 0, 0, 0, 127, 15, 1, 0, 0, 0, 128, 126, 1, 0, 0, 0, 129, 131, 5, 16, 0, 0, 130, 129, 1, 0, 0, 0, 130, 131, 1, 0, 0, 0, 131, 132, 1, 0, 0, 0, 132, 138, 5, 36, 0, 0, 133, 135, 5, 14, 0, 0, 134, 136, 3, 18, 9, 0, 135, 134, 1, 0, 0, 0, 135, 136, 1, 0, 0, 0, 136, 137, 1, 0, 0, 0, 137, 139, 5, 15, 0, 0, 138, 133, 1, 0, 0, 0, 138, 139, 1, 0, 0, 0, 139, 181, 1, 0, 0, 0, 140, 141, 5, 14, 0, 0, 141, 142, 3, 2, 1, 0, 142, 143, 5, 15, 0, 0, 143, 181, 1, 0, 0, 0, 144, 146, 5, 10, 0, 0, 145, 147, 3, 20, 10, 0, 146, 145, 1, 0, 0, 0, 146, 147, 1, 0, 0, 0, 147, 149, 1, 0, 0, 0, 148, 150, 5, 17, 0, 0, 149, 148, 1, 0, 0, 0, 149, 150, 1, 0, 0, 0, 150, 151, 1, 0, 0, 0, 151, 181, 5, 11, 0, 0, 152, 154, 5, 12, 0, 0, 153, 155, 3, 26, 13, 0, 154, 153, 1, 0, 0, 0, 154, 155, 1, 0, 0, 0, 155, 157, 1, 0, 0, 0, 156, 158, 5, 17, 0, 0, 157, 156, 1, 0, 0, 0, 157, 158, 1, 0, 0, 0, 158, 159, 1, 0, 0, 0, 159, 181, 5, 13, 0, 0, 160, 162, 5, 16, 0, 0, 161, 160, 1, 0, 0, 0, 161, 162, 1, 0, 0, 0, 162, 163, 1, 0, 0, 0, 163, 168, 5, 36, 0, 0, 164, 165, 5, 16, 0, 0, 165, 167, 5, 36, 0, 0, 166, 164, 1, 0, 0, 0, 167, 170, 1, 0, 0, 0, 168, 166, 1, 0, 0, 0, 168, 169, 1, 0, 0, 0, 169, 171, 1, 0, 0, 0, 170, 168, 1, 0, 0, 0, 171, 173, 5, 12, 0, 0, 172, 174, 3, 22, 11, 0, 173, 172, 1, 0, 0, 0, 173, 174, 1, 0, 0, 0, 174, 176, 1, 0, 0, 0, 175, 177, 5, 17, 0, 0, 176, 175, 1, 0, 0, 0, 176, 177, 1, 0, 0, 0, 177, 178, 1, 0, 0, 0, 178, 181, 5, 13, 0, 0, 179, 181, 3, 30, 15, 0, 180, 130, 1, 0, 0, 0, 180, 140, 1, 0, 0, 0, 180, 144, 1, 0, 0, 0, 180, 152, 1, 0, 0, 0, 180, 161, 1, 0, 0, 0, 180, 179, 1, 0, 0, 0, 181, 17, 1, 0, 0, 0, 182, 187, 3, 2, 1, 0, 183, 184, 5, 17, 0, 0, 184, 186, 3, 2, 1, 0, 185, 183, 1, 0, 0, 0, 186, 189, 1, 0, 0, 0, 187, 185, 1, 0, 0, 0, 187, 188, 1, 0, 0, 0, 188, 19, 1, 0, 0, 0, 189, 187, 1, 0, 0, 0, 190, 195, 3, 28, 14, 0, 191, 192, 5, 17, 0, 0, 192, 194, 3, 28, 14, 0, 193, 191, 1, 0, 0, 0, 194, 197, 1, 0, 0, 0, 195, 193, 1, 0, 0, 0, 195, 196, 1, 0, 0, 0, 196, 21, 1, 0, 0, 0, 197, 195, 1, 0, 0, 0, 198, 199, 3, 24, 12, 0, 199, 200, 5, 21, 0, 0, 200, 208, 3, 2, 1, 0, 201, 202, 5, 17, 0, 0, 202, 203, 3, 24, 12, 0, 203, 204, 5, 21, 0, 0, 204, 205, 3, 2, 1, 0, 205, 207, 1, 0, 0, 0, 206, 201, 1, 0, 0, 0, 207, 210, 1, 0, 0, 0, 208, 206, 1, 0, 0, 0, 208, 209, 1, 0, 0, 0, 209, 23, 1, 0, 0, 0, 210, 208, 1, 0, 0, 0, 211, 213, 5, 20, 0, 0, 212, 211, 1, 0, 0, 0, 212, 213, 1, 0, 0, 0, 213, 214, 1, 0, 0, 0, 214, 215, 5, 36, 0, 0, 215, 25, 1, 0, 0, 0, 216, 217, 3, 28, 14, 0, 217, 218, 5, 21, 0, 0, 218, 226, 3, 2, 1, 0, 219, 220, 5, 17, 0, 0, 220, 221, 3, 28, 14, 0, 221, 222, 5, 21, 0, 0, 222, 223, 3, 2, 1, 0, 223, 225, 1, 0, 0, 0, 224, 219, 1, 0, 0, 0, 225, 228, 1, 0, 0, 0, 226, 224, 1, 0, 0, 0, 226, 227, 1, 0, 0, 0, 227, 27, 1, 0, 0, 0, 228, 226, 1, 0, 0, 0, 229, 231, 5, 20, 0, 0, 230, 229, 1, 0, 0, 0, 230, 231, 1, 0, 0, 0, 231, 232, 1, 0, 0, 0, 232, 233, 3, 2, 1, 0, 233, 29, 1, 0, 0, 0, 234, 236, 5, 18, 0, 0, 235, 234, 1, 0, 0, 0, 235, 236, 1, 0, 0, 0, 236, 237, 1, 0, 0, 0, 237, 249, 5, 32, 0, 0, 238, 249, 5, 33, 0, 0, 239, 241, 5, 18, 0, 0, 240, 239, 1, 0, 0, 0, 240, 241, 1, 0, 0, 0, 241, 242, 1, 0, 0, 0, 242, 249, 5, 31, 0, 0, 243, 249, 5, 34, 0, 0, 244, 249, 5, 35, 0, 0, 245, 249, 5, 26, 0, 0, 246, 249, 5, 27, 0, 0, 247, 249, 5, 28, 0, 0, 248, 235, 1, 0, 0, 0, 248, 238, 1, 0, 0, 0, 248, 240, 1, 0, 0, 0, 248, 243, 1, 0, 0, 0, 248, 244, 1, 0, 0, 0, 248, 245, 1, 0, 0, 0, 248, 246, 1, 0, 0, 0, 248, 247, 1, 0, 0, 0, 249, 31, 1, 0, 0, 0, 35, 41, 48, 56, 67, 79, 81, 88, 94, 97, 105, 113, 119, 124, 126, 130, 135, 138, 146, 149, 154, 157, 161, 168, 173, 176, 180, 187, 195, 208, 212, 226, 230, 235, 240, 248] \ No newline at end of file diff --git a/packages/cel/src/lib/gen/CEL.tokens b/packages/cel/src/lib/gen/CEL.tokens new file mode 100644 index 0000000..b305bda --- /dev/null +++ b/packages/cel/src/lib/gen/CEL.tokens @@ -0,0 +1,64 @@ +EQUALS=1 +NOT_EQUALS=2 +IN=3 +LESS=4 +LESS_EQUALS=5 +GREATER_EQUALS=6 +GREATER=7 +LOGICAL_AND=8 +LOGICAL_OR=9 +LBRACKET=10 +RPRACKET=11 +LBRACE=12 +RBRACE=13 +LPAREN=14 +RPAREN=15 +DOT=16 +COMMA=17 +MINUS=18 +EXCLAM=19 +QUESTIONMARK=20 +COLON=21 +PLUS=22 +STAR=23 +SLASH=24 +PERCENT=25 +CEL_TRUE=26 +CEL_FALSE=27 +NUL=28 +WHITESPACE=29 +COMMENT=30 +NUM_FLOAT=31 +NUM_INT=32 +NUM_UINT=33 +STRING=34 +BYTES=35 +IDENTIFIER=36 +'=='=1 +'!='=2 +'in'=3 +'<'=4 +'<='=5 +'>='=6 +'>'=7 +'&&'=8 +'||'=9 +'['=10 +']'=11 +'{'=12 +'}'=13 +'('=14 +')'=15 +'.'=16 +','=17 +'-'=18 +'!'=19 +'?'=20 +':'=21 +'+'=22 +'*'=23 +'/'=24 +'%'=25 +'true'=26 +'false'=27 +'null'=28 diff --git a/packages/cel/src/lib/gen/CELLexer.interp b/packages/cel/src/lib/gen/CELLexer.interp new file mode 100644 index 0000000..26e7f47 --- /dev/null +++ b/packages/cel/src/lib/gen/CELLexer.interp @@ -0,0 +1,136 @@ +token literal names: +null +'==' +'!=' +'in' +'<' +'<=' +'>=' +'>' +'&&' +'||' +'[' +']' +'{' +'}' +'(' +')' +'.' +',' +'-' +'!' +'?' +':' +'+' +'*' +'/' +'%' +'true' +'false' +'null' +null +null +null +null +null +null +null +null + +token symbolic names: +null +EQUALS +NOT_EQUALS +IN +LESS +LESS_EQUALS +GREATER_EQUALS +GREATER +LOGICAL_AND +LOGICAL_OR +LBRACKET +RPRACKET +LBRACE +RBRACE +LPAREN +RPAREN +DOT +COMMA +MINUS +EXCLAM +QUESTIONMARK +COLON +PLUS +STAR +SLASH +PERCENT +CEL_TRUE +CEL_FALSE +NUL +WHITESPACE +COMMENT +NUM_FLOAT +NUM_INT +NUM_UINT +STRING +BYTES +IDENTIFIER + +rule names: +EQUALS +NOT_EQUALS +IN +LESS +LESS_EQUALS +GREATER_EQUALS +GREATER +LOGICAL_AND +LOGICAL_OR +LBRACKET +RPRACKET +LBRACE +RBRACE +LPAREN +RPAREN +DOT +COMMA +MINUS +EXCLAM +QUESTIONMARK +COLON +PLUS +STAR +SLASH +PERCENT +CEL_TRUE +CEL_FALSE +NUL +BACKSLASH +LETTER +DIGIT +EXPONENT +HEXDIGIT +RAW +ESC_SEQ +ESC_CHAR_SEQ +ESC_OCT_SEQ +ESC_BYTE_SEQ +ESC_UNI_SEQ +WHITESPACE +COMMENT +NUM_FLOAT +NUM_INT +NUM_UINT +STRING +BYTES +IDENTIFIER + +channel names: +DEFAULT_TOKEN_CHANNEL +HIDDEN + +mode names: +DEFAULT_MODE + +atn: +[4, 0, 36, 423, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, 23, 1, 23, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 31, 1, 31, 3, 31, 177, 8, 31, 1, 31, 4, 31, 180, 8, 31, 11, 31, 12, 31, 181, 1, 32, 1, 32, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 1, 34, 3, 34, 192, 8, 34, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 225, 8, 38, 1, 39, 4, 39, 228, 8, 39, 11, 39, 12, 39, 229, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 5, 40, 238, 8, 40, 10, 40, 12, 40, 241, 9, 40, 1, 40, 1, 40, 1, 41, 4, 41, 246, 8, 41, 11, 41, 12, 41, 247, 1, 41, 1, 41, 4, 41, 252, 8, 41, 11, 41, 12, 41, 253, 1, 41, 3, 41, 257, 8, 41, 1, 41, 4, 41, 260, 8, 41, 11, 41, 12, 41, 261, 1, 41, 1, 41, 1, 41, 1, 41, 4, 41, 268, 8, 41, 11, 41, 12, 41, 269, 1, 41, 3, 41, 273, 8, 41, 3, 41, 275, 8, 41, 1, 42, 4, 42, 278, 8, 42, 11, 42, 12, 42, 279, 1, 42, 1, 42, 1, 42, 1, 42, 4, 42, 286, 8, 42, 11, 42, 12, 42, 287, 3, 42, 290, 8, 42, 1, 43, 4, 43, 293, 8, 43, 11, 43, 12, 43, 294, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 4, 43, 303, 8, 43, 11, 43, 12, 43, 304, 1, 43, 1, 43, 3, 43, 309, 8, 43, 1, 44, 1, 44, 1, 44, 5, 44, 314, 8, 44, 10, 44, 12, 44, 317, 9, 44, 1, 44, 1, 44, 1, 44, 1, 44, 5, 44, 323, 8, 44, 10, 44, 12, 44, 326, 9, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 5, 44, 335, 8, 44, 10, 44, 12, 44, 338, 9, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 5, 44, 349, 8, 44, 10, 44, 12, 44, 352, 9, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 5, 44, 360, 8, 44, 10, 44, 12, 44, 363, 9, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 5, 44, 370, 8, 44, 10, 44, 12, 44, 373, 9, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 5, 44, 383, 8, 44, 10, 44, 12, 44, 386, 9, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 5, 44, 398, 8, 44, 10, 44, 12, 44, 401, 9, 44, 1, 44, 1, 44, 1, 44, 1, 44, 3, 44, 407, 8, 44, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 3, 46, 414, 8, 46, 1, 46, 1, 46, 1, 46, 5, 46, 419, 8, 46, 10, 46, 12, 46, 422, 9, 46, 4, 336, 350, 384, 399, 0, 47, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 0, 59, 0, 61, 0, 63, 0, 65, 0, 67, 0, 69, 0, 71, 0, 73, 0, 75, 0, 77, 0, 79, 29, 81, 30, 83, 31, 85, 32, 87, 33, 89, 34, 91, 35, 93, 36, 1, 0, 16, 2, 0, 65, 90, 97, 122, 2, 0, 69, 69, 101, 101, 2, 0, 43, 43, 45, 45, 3, 0, 48, 57, 65, 70, 97, 102, 2, 0, 82, 82, 114, 114, 10, 0, 34, 34, 39, 39, 63, 63, 92, 92, 96, 98, 102, 102, 110, 110, 114, 114, 116, 116, 118, 118, 2, 0, 88, 88, 120, 120, 3, 0, 9, 10, 12, 13, 32, 32, 1, 0, 10, 10, 2, 0, 85, 85, 117, 117, 4, 0, 10, 10, 13, 13, 34, 34, 92, 92, 4, 0, 10, 10, 13, 13, 39, 39, 92, 92, 1, 0, 92, 92, 3, 0, 10, 10, 13, 13, 34, 34, 3, 0, 10, 10, 13, 13, 39, 39, 2, 0, 66, 66, 98, 98, 456, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 89, 1, 0, 0, 0, 0, 91, 1, 0, 0, 0, 0, 93, 1, 0, 0, 0, 1, 95, 1, 0, 0, 0, 3, 98, 1, 0, 0, 0, 5, 101, 1, 0, 0, 0, 7, 104, 1, 0, 0, 0, 9, 106, 1, 0, 0, 0, 11, 109, 1, 0, 0, 0, 13, 112, 1, 0, 0, 0, 15, 114, 1, 0, 0, 0, 17, 117, 1, 0, 0, 0, 19, 120, 1, 0, 0, 0, 21, 122, 1, 0, 0, 0, 23, 124, 1, 0, 0, 0, 25, 126, 1, 0, 0, 0, 27, 128, 1, 0, 0, 0, 29, 130, 1, 0, 0, 0, 31, 132, 1, 0, 0, 0, 33, 134, 1, 0, 0, 0, 35, 136, 1, 0, 0, 0, 37, 138, 1, 0, 0, 0, 39, 140, 1, 0, 0, 0, 41, 142, 1, 0, 0, 0, 43, 144, 1, 0, 0, 0, 45, 146, 1, 0, 0, 0, 47, 148, 1, 0, 0, 0, 49, 150, 1, 0, 0, 0, 51, 152, 1, 0, 0, 0, 53, 157, 1, 0, 0, 0, 55, 163, 1, 0, 0, 0, 57, 168, 1, 0, 0, 0, 59, 170, 1, 0, 0, 0, 61, 172, 1, 0, 0, 0, 63, 174, 1, 0, 0, 0, 65, 183, 1, 0, 0, 0, 67, 185, 1, 0, 0, 0, 69, 191, 1, 0, 0, 0, 71, 193, 1, 0, 0, 0, 73, 196, 1, 0, 0, 0, 75, 201, 1, 0, 0, 0, 77, 224, 1, 0, 0, 0, 79, 227, 1, 0, 0, 0, 81, 233, 1, 0, 0, 0, 83, 274, 1, 0, 0, 0, 85, 289, 1, 0, 0, 0, 87, 308, 1, 0, 0, 0, 89, 406, 1, 0, 0, 0, 91, 408, 1, 0, 0, 0, 93, 413, 1, 0, 0, 0, 95, 96, 5, 61, 0, 0, 96, 97, 5, 61, 0, 0, 97, 2, 1, 0, 0, 0, 98, 99, 5, 33, 0, 0, 99, 100, 5, 61, 0, 0, 100, 4, 1, 0, 0, 0, 101, 102, 5, 105, 0, 0, 102, 103, 5, 110, 0, 0, 103, 6, 1, 0, 0, 0, 104, 105, 5, 60, 0, 0, 105, 8, 1, 0, 0, 0, 106, 107, 5, 60, 0, 0, 107, 108, 5, 61, 0, 0, 108, 10, 1, 0, 0, 0, 109, 110, 5, 62, 0, 0, 110, 111, 5, 61, 0, 0, 111, 12, 1, 0, 0, 0, 112, 113, 5, 62, 0, 0, 113, 14, 1, 0, 0, 0, 114, 115, 5, 38, 0, 0, 115, 116, 5, 38, 0, 0, 116, 16, 1, 0, 0, 0, 117, 118, 5, 124, 0, 0, 118, 119, 5, 124, 0, 0, 119, 18, 1, 0, 0, 0, 120, 121, 5, 91, 0, 0, 121, 20, 1, 0, 0, 0, 122, 123, 5, 93, 0, 0, 123, 22, 1, 0, 0, 0, 124, 125, 5, 123, 0, 0, 125, 24, 1, 0, 0, 0, 126, 127, 5, 125, 0, 0, 127, 26, 1, 0, 0, 0, 128, 129, 5, 40, 0, 0, 129, 28, 1, 0, 0, 0, 130, 131, 5, 41, 0, 0, 131, 30, 1, 0, 0, 0, 132, 133, 5, 46, 0, 0, 133, 32, 1, 0, 0, 0, 134, 135, 5, 44, 0, 0, 135, 34, 1, 0, 0, 0, 136, 137, 5, 45, 0, 0, 137, 36, 1, 0, 0, 0, 138, 139, 5, 33, 0, 0, 139, 38, 1, 0, 0, 0, 140, 141, 5, 63, 0, 0, 141, 40, 1, 0, 0, 0, 142, 143, 5, 58, 0, 0, 143, 42, 1, 0, 0, 0, 144, 145, 5, 43, 0, 0, 145, 44, 1, 0, 0, 0, 146, 147, 5, 42, 0, 0, 147, 46, 1, 0, 0, 0, 148, 149, 5, 47, 0, 0, 149, 48, 1, 0, 0, 0, 150, 151, 5, 37, 0, 0, 151, 50, 1, 0, 0, 0, 152, 153, 5, 116, 0, 0, 153, 154, 5, 114, 0, 0, 154, 155, 5, 117, 0, 0, 155, 156, 5, 101, 0, 0, 156, 52, 1, 0, 0, 0, 157, 158, 5, 102, 0, 0, 158, 159, 5, 97, 0, 0, 159, 160, 5, 108, 0, 0, 160, 161, 5, 115, 0, 0, 161, 162, 5, 101, 0, 0, 162, 54, 1, 0, 0, 0, 163, 164, 5, 110, 0, 0, 164, 165, 5, 117, 0, 0, 165, 166, 5, 108, 0, 0, 166, 167, 5, 108, 0, 0, 167, 56, 1, 0, 0, 0, 168, 169, 5, 92, 0, 0, 169, 58, 1, 0, 0, 0, 170, 171, 7, 0, 0, 0, 171, 60, 1, 0, 0, 0, 172, 173, 2, 48, 57, 0, 173, 62, 1, 0, 0, 0, 174, 176, 7, 1, 0, 0, 175, 177, 7, 2, 0, 0, 176, 175, 1, 0, 0, 0, 176, 177, 1, 0, 0, 0, 177, 179, 1, 0, 0, 0, 178, 180, 3, 61, 30, 0, 179, 178, 1, 0, 0, 0, 180, 181, 1, 0, 0, 0, 181, 179, 1, 0, 0, 0, 181, 182, 1, 0, 0, 0, 182, 64, 1, 0, 0, 0, 183, 184, 7, 3, 0, 0, 184, 66, 1, 0, 0, 0, 185, 186, 7, 4, 0, 0, 186, 68, 1, 0, 0, 0, 187, 192, 3, 71, 35, 0, 188, 192, 3, 75, 37, 0, 189, 192, 3, 77, 38, 0, 190, 192, 3, 73, 36, 0, 191, 187, 1, 0, 0, 0, 191, 188, 1, 0, 0, 0, 191, 189, 1, 0, 0, 0, 191, 190, 1, 0, 0, 0, 192, 70, 1, 0, 0, 0, 193, 194, 3, 57, 28, 0, 194, 195, 7, 5, 0, 0, 195, 72, 1, 0, 0, 0, 196, 197, 3, 57, 28, 0, 197, 198, 2, 48, 51, 0, 198, 199, 2, 48, 55, 0, 199, 200, 2, 48, 55, 0, 200, 74, 1, 0, 0, 0, 201, 202, 3, 57, 28, 0, 202, 203, 7, 6, 0, 0, 203, 204, 3, 65, 32, 0, 204, 205, 3, 65, 32, 0, 205, 76, 1, 0, 0, 0, 206, 207, 3, 57, 28, 0, 207, 208, 5, 117, 0, 0, 208, 209, 3, 65, 32, 0, 209, 210, 3, 65, 32, 0, 210, 211, 3, 65, 32, 0, 211, 212, 3, 65, 32, 0, 212, 225, 1, 0, 0, 0, 213, 214, 3, 57, 28, 0, 214, 215, 5, 85, 0, 0, 215, 216, 3, 65, 32, 0, 216, 217, 3, 65, 32, 0, 217, 218, 3, 65, 32, 0, 218, 219, 3, 65, 32, 0, 219, 220, 3, 65, 32, 0, 220, 221, 3, 65, 32, 0, 221, 222, 3, 65, 32, 0, 222, 223, 3, 65, 32, 0, 223, 225, 1, 0, 0, 0, 224, 206, 1, 0, 0, 0, 224, 213, 1, 0, 0, 0, 225, 78, 1, 0, 0, 0, 226, 228, 7, 7, 0, 0, 227, 226, 1, 0, 0, 0, 228, 229, 1, 0, 0, 0, 229, 227, 1, 0, 0, 0, 229, 230, 1, 0, 0, 0, 230, 231, 1, 0, 0, 0, 231, 232, 6, 39, 0, 0, 232, 80, 1, 0, 0, 0, 233, 234, 5, 47, 0, 0, 234, 235, 5, 47, 0, 0, 235, 239, 1, 0, 0, 0, 236, 238, 8, 8, 0, 0, 237, 236, 1, 0, 0, 0, 238, 241, 1, 0, 0, 0, 239, 237, 1, 0, 0, 0, 239, 240, 1, 0, 0, 0, 240, 242, 1, 0, 0, 0, 241, 239, 1, 0, 0, 0, 242, 243, 6, 40, 0, 0, 243, 82, 1, 0, 0, 0, 244, 246, 3, 61, 30, 0, 245, 244, 1, 0, 0, 0, 246, 247, 1, 0, 0, 0, 247, 245, 1, 0, 0, 0, 247, 248, 1, 0, 0, 0, 248, 249, 1, 0, 0, 0, 249, 251, 5, 46, 0, 0, 250, 252, 3, 61, 30, 0, 251, 250, 1, 0, 0, 0, 252, 253, 1, 0, 0, 0, 253, 251, 1, 0, 0, 0, 253, 254, 1, 0, 0, 0, 254, 256, 1, 0, 0, 0, 255, 257, 3, 63, 31, 0, 256, 255, 1, 0, 0, 0, 256, 257, 1, 0, 0, 0, 257, 275, 1, 0, 0, 0, 258, 260, 3, 61, 30, 0, 259, 258, 1, 0, 0, 0, 260, 261, 1, 0, 0, 0, 261, 259, 1, 0, 0, 0, 261, 262, 1, 0, 0, 0, 262, 263, 1, 0, 0, 0, 263, 264, 3, 63, 31, 0, 264, 275, 1, 0, 0, 0, 265, 267, 5, 46, 0, 0, 266, 268, 3, 61, 30, 0, 267, 266, 1, 0, 0, 0, 268, 269, 1, 0, 0, 0, 269, 267, 1, 0, 0, 0, 269, 270, 1, 0, 0, 0, 270, 272, 1, 0, 0, 0, 271, 273, 3, 63, 31, 0, 272, 271, 1, 0, 0, 0, 272, 273, 1, 0, 0, 0, 273, 275, 1, 0, 0, 0, 274, 245, 1, 0, 0, 0, 274, 259, 1, 0, 0, 0, 274, 265, 1, 0, 0, 0, 275, 84, 1, 0, 0, 0, 276, 278, 3, 61, 30, 0, 277, 276, 1, 0, 0, 0, 278, 279, 1, 0, 0, 0, 279, 277, 1, 0, 0, 0, 279, 280, 1, 0, 0, 0, 280, 290, 1, 0, 0, 0, 281, 282, 5, 48, 0, 0, 282, 283, 5, 120, 0, 0, 283, 285, 1, 0, 0, 0, 284, 286, 3, 65, 32, 0, 285, 284, 1, 0, 0, 0, 286, 287, 1, 0, 0, 0, 287, 285, 1, 0, 0, 0, 287, 288, 1, 0, 0, 0, 288, 290, 1, 0, 0, 0, 289, 277, 1, 0, 0, 0, 289, 281, 1, 0, 0, 0, 290, 86, 1, 0, 0, 0, 291, 293, 3, 61, 30, 0, 292, 291, 1, 0, 0, 0, 293, 294, 1, 0, 0, 0, 294, 292, 1, 0, 0, 0, 294, 295, 1, 0, 0, 0, 295, 296, 1, 0, 0, 0, 296, 297, 7, 9, 0, 0, 297, 309, 1, 0, 0, 0, 298, 299, 5, 48, 0, 0, 299, 300, 5, 120, 0, 0, 300, 302, 1, 0, 0, 0, 301, 303, 3, 65, 32, 0, 302, 301, 1, 0, 0, 0, 303, 304, 1, 0, 0, 0, 304, 302, 1, 0, 0, 0, 304, 305, 1, 0, 0, 0, 305, 306, 1, 0, 0, 0, 306, 307, 7, 9, 0, 0, 307, 309, 1, 0, 0, 0, 308, 292, 1, 0, 0, 0, 308, 298, 1, 0, 0, 0, 309, 88, 1, 0, 0, 0, 310, 315, 5, 34, 0, 0, 311, 314, 3, 69, 34, 0, 312, 314, 8, 10, 0, 0, 313, 311, 1, 0, 0, 0, 313, 312, 1, 0, 0, 0, 314, 317, 1, 0, 0, 0, 315, 313, 1, 0, 0, 0, 315, 316, 1, 0, 0, 0, 316, 318, 1, 0, 0, 0, 317, 315, 1, 0, 0, 0, 318, 407, 5, 34, 0, 0, 319, 324, 5, 39, 0, 0, 320, 323, 3, 69, 34, 0, 321, 323, 8, 11, 0, 0, 322, 320, 1, 0, 0, 0, 322, 321, 1, 0, 0, 0, 323, 326, 1, 0, 0, 0, 324, 322, 1, 0, 0, 0, 324, 325, 1, 0, 0, 0, 325, 327, 1, 0, 0, 0, 326, 324, 1, 0, 0, 0, 327, 407, 5, 39, 0, 0, 328, 329, 5, 34, 0, 0, 329, 330, 5, 34, 0, 0, 330, 331, 5, 34, 0, 0, 331, 336, 1, 0, 0, 0, 332, 335, 3, 69, 34, 0, 333, 335, 8, 12, 0, 0, 334, 332, 1, 0, 0, 0, 334, 333, 1, 0, 0, 0, 335, 338, 1, 0, 0, 0, 336, 337, 1, 0, 0, 0, 336, 334, 1, 0, 0, 0, 337, 339, 1, 0, 0, 0, 338, 336, 1, 0, 0, 0, 339, 340, 5, 34, 0, 0, 340, 341, 5, 34, 0, 0, 341, 407, 5, 34, 0, 0, 342, 343, 5, 39, 0, 0, 343, 344, 5, 39, 0, 0, 344, 345, 5, 39, 0, 0, 345, 350, 1, 0, 0, 0, 346, 349, 3, 69, 34, 0, 347, 349, 8, 12, 0, 0, 348, 346, 1, 0, 0, 0, 348, 347, 1, 0, 0, 0, 349, 352, 1, 0, 0, 0, 350, 351, 1, 0, 0, 0, 350, 348, 1, 0, 0, 0, 351, 353, 1, 0, 0, 0, 352, 350, 1, 0, 0, 0, 353, 354, 5, 39, 0, 0, 354, 355, 5, 39, 0, 0, 355, 407, 5, 39, 0, 0, 356, 357, 3, 67, 33, 0, 357, 361, 5, 34, 0, 0, 358, 360, 8, 13, 0, 0, 359, 358, 1, 0, 0, 0, 360, 363, 1, 0, 0, 0, 361, 359, 1, 0, 0, 0, 361, 362, 1, 0, 0, 0, 362, 364, 1, 0, 0, 0, 363, 361, 1, 0, 0, 0, 364, 365, 5, 34, 0, 0, 365, 407, 1, 0, 0, 0, 366, 367, 3, 67, 33, 0, 367, 371, 5, 39, 0, 0, 368, 370, 8, 14, 0, 0, 369, 368, 1, 0, 0, 0, 370, 373, 1, 0, 0, 0, 371, 369, 1, 0, 0, 0, 371, 372, 1, 0, 0, 0, 372, 374, 1, 0, 0, 0, 373, 371, 1, 0, 0, 0, 374, 375, 5, 39, 0, 0, 375, 407, 1, 0, 0, 0, 376, 377, 3, 67, 33, 0, 377, 378, 5, 34, 0, 0, 378, 379, 5, 34, 0, 0, 379, 380, 5, 34, 0, 0, 380, 384, 1, 0, 0, 0, 381, 383, 9, 0, 0, 0, 382, 381, 1, 0, 0, 0, 383, 386, 1, 0, 0, 0, 384, 385, 1, 0, 0, 0, 384, 382, 1, 0, 0, 0, 385, 387, 1, 0, 0, 0, 386, 384, 1, 0, 0, 0, 387, 388, 5, 34, 0, 0, 388, 389, 5, 34, 0, 0, 389, 390, 5, 34, 0, 0, 390, 407, 1, 0, 0, 0, 391, 392, 3, 67, 33, 0, 392, 393, 5, 39, 0, 0, 393, 394, 5, 39, 0, 0, 394, 395, 5, 39, 0, 0, 395, 399, 1, 0, 0, 0, 396, 398, 9, 0, 0, 0, 397, 396, 1, 0, 0, 0, 398, 401, 1, 0, 0, 0, 399, 400, 1, 0, 0, 0, 399, 397, 1, 0, 0, 0, 400, 402, 1, 0, 0, 0, 401, 399, 1, 0, 0, 0, 402, 403, 5, 39, 0, 0, 403, 404, 5, 39, 0, 0, 404, 405, 5, 39, 0, 0, 405, 407, 1, 0, 0, 0, 406, 310, 1, 0, 0, 0, 406, 319, 1, 0, 0, 0, 406, 328, 1, 0, 0, 0, 406, 342, 1, 0, 0, 0, 406, 356, 1, 0, 0, 0, 406, 366, 1, 0, 0, 0, 406, 376, 1, 0, 0, 0, 406, 391, 1, 0, 0, 0, 407, 90, 1, 0, 0, 0, 408, 409, 7, 15, 0, 0, 409, 410, 3, 89, 44, 0, 410, 92, 1, 0, 0, 0, 411, 414, 3, 59, 29, 0, 412, 414, 5, 95, 0, 0, 413, 411, 1, 0, 0, 0, 413, 412, 1, 0, 0, 0, 414, 420, 1, 0, 0, 0, 415, 419, 3, 59, 29, 0, 416, 419, 3, 61, 30, 0, 417, 419, 5, 95, 0, 0, 418, 415, 1, 0, 0, 0, 418, 416, 1, 0, 0, 0, 418, 417, 1, 0, 0, 0, 419, 422, 1, 0, 0, 0, 420, 418, 1, 0, 0, 0, 420, 421, 1, 0, 0, 0, 421, 94, 1, 0, 0, 0, 422, 420, 1, 0, 0, 0, 36, 0, 176, 181, 191, 224, 229, 239, 247, 253, 256, 261, 269, 272, 274, 279, 287, 289, 294, 304, 308, 313, 315, 322, 324, 334, 336, 348, 350, 361, 371, 384, 399, 406, 413, 418, 420, 1, 0, 1, 0] \ No newline at end of file diff --git a/packages/cel/src/lib/gen/CELLexer.tokens b/packages/cel/src/lib/gen/CELLexer.tokens new file mode 100644 index 0000000..b305bda --- /dev/null +++ b/packages/cel/src/lib/gen/CELLexer.tokens @@ -0,0 +1,64 @@ +EQUALS=1 +NOT_EQUALS=2 +IN=3 +LESS=4 +LESS_EQUALS=5 +GREATER_EQUALS=6 +GREATER=7 +LOGICAL_AND=8 +LOGICAL_OR=9 +LBRACKET=10 +RPRACKET=11 +LBRACE=12 +RBRACE=13 +LPAREN=14 +RPAREN=15 +DOT=16 +COMMA=17 +MINUS=18 +EXCLAM=19 +QUESTIONMARK=20 +COLON=21 +PLUS=22 +STAR=23 +SLASH=24 +PERCENT=25 +CEL_TRUE=26 +CEL_FALSE=27 +NUL=28 +WHITESPACE=29 +COMMENT=30 +NUM_FLOAT=31 +NUM_INT=32 +NUM_UINT=33 +STRING=34 +BYTES=35 +IDENTIFIER=36 +'=='=1 +'!='=2 +'in'=3 +'<'=4 +'<='=5 +'>='=6 +'>'=7 +'&&'=8 +'||'=9 +'['=10 +']'=11 +'{'=12 +'}'=13 +'('=14 +')'=15 +'.'=16 +','=17 +'-'=18 +'!'=19 +'?'=20 +':'=21 +'+'=22 +'*'=23 +'/'=24 +'%'=25 +'true'=26 +'false'=27 +'null'=28 diff --git a/packages/cel/src/lib/gen/CELLexer.ts b/packages/cel/src/lib/gen/CELLexer.ts new file mode 100644 index 0000000..0809a48 --- /dev/null +++ b/packages/cel/src/lib/gen/CELLexer.ts @@ -0,0 +1,285 @@ +// Generated from packages/cel/src/lib/gen/CEL.g4 by ANTLR 4.13.1 +// noinspection ES6UnusedImports,JSUnusedGlobalSymbols,JSUnusedLocalSymbols +import { + ATN, + ATNDeserializer, + CharStream, + DecisionState, DFA, + Lexer, + LexerATNSimulator, + RuleContext, + PredictionContextCache, + Token +} from "antlr4"; +export default class CELLexer extends Lexer { + public static readonly EQUALS = 1; + public static readonly NOT_EQUALS = 2; + public static readonly IN = 3; + public static readonly LESS = 4; + public static readonly LESS_EQUALS = 5; + public static readonly GREATER_EQUALS = 6; + public static readonly GREATER = 7; + public static readonly LOGICAL_AND = 8; + public static readonly LOGICAL_OR = 9; + public static readonly LBRACKET = 10; + public static readonly RPRACKET = 11; + public static readonly LBRACE = 12; + public static readonly RBRACE = 13; + public static readonly LPAREN = 14; + public static readonly RPAREN = 15; + public static readonly DOT = 16; + public static readonly COMMA = 17; + public static readonly MINUS = 18; + public static readonly EXCLAM = 19; + public static readonly QUESTIONMARK = 20; + public static readonly COLON = 21; + public static readonly PLUS = 22; + public static readonly STAR = 23; + public static readonly SLASH = 24; + public static readonly PERCENT = 25; + public static readonly CEL_TRUE = 26; + public static readonly CEL_FALSE = 27; + public static readonly NUL = 28; + public static readonly WHITESPACE = 29; + public static readonly COMMENT = 30; + public static readonly NUM_FLOAT = 31; + public static readonly NUM_INT = 32; + public static readonly NUM_UINT = 33; + public static readonly STRING = 34; + public static readonly BYTES = 35; + public static readonly IDENTIFIER = 36; + public static readonly EOF = Token.EOF; + + public static readonly channelNames: string[] = [ "DEFAULT_TOKEN_CHANNEL", "HIDDEN" ]; + public static readonly literalNames: (string | null)[] = [ null, "'=='", + "'!='", "'in'", + "'<'", "'<='", + "'>='", "'>'", + "'&&'", "'||'", + "'['", "']'", + "'{'", "'}'", + "'('", "')'", + "'.'", "','", + "'-'", "'!'", + "'?'", "':'", + "'+'", "'*'", + "'/'", "'%'", + "'true'", "'false'", + "'null'" ]; + public static readonly symbolicNames: (string | null)[] = [ null, "EQUALS", + "NOT_EQUALS", + "IN", "LESS", + "LESS_EQUALS", + "GREATER_EQUALS", + "GREATER", + "LOGICAL_AND", + "LOGICAL_OR", + "LBRACKET", + "RPRACKET", + "LBRACE", "RBRACE", + "LPAREN", "RPAREN", + "DOT", "COMMA", + "MINUS", "EXCLAM", + "QUESTIONMARK", + "COLON", "PLUS", + "STAR", "SLASH", + "PERCENT", + "CEL_TRUE", + "CEL_FALSE", + "NUL", "WHITESPACE", + "COMMENT", + "NUM_FLOAT", + "NUM_INT", + "NUM_UINT", + "STRING", "BYTES", + "IDENTIFIER" ]; + public static readonly modeNames: string[] = [ "DEFAULT_MODE", ]; + + public static readonly ruleNames: string[] = [ + "EQUALS", "NOT_EQUALS", "IN", "LESS", "LESS_EQUALS", "GREATER_EQUALS", + "GREATER", "LOGICAL_AND", "LOGICAL_OR", "LBRACKET", "RPRACKET", "LBRACE", + "RBRACE", "LPAREN", "RPAREN", "DOT", "COMMA", "MINUS", "EXCLAM", "QUESTIONMARK", + "COLON", "PLUS", "STAR", "SLASH", "PERCENT", "CEL_TRUE", "CEL_FALSE", + "NUL", "BACKSLASH", "LETTER", "DIGIT", "EXPONENT", "HEXDIGIT", "RAW", + "ESC_SEQ", "ESC_CHAR_SEQ", "ESC_OCT_SEQ", "ESC_BYTE_SEQ", "ESC_UNI_SEQ", + "WHITESPACE", "COMMENT", "NUM_FLOAT", "NUM_INT", "NUM_UINT", "STRING", + "BYTES", "IDENTIFIER", + ]; + + + constructor(input: CharStream) { + super(input); + this._interp = new LexerATNSimulator(this, CELLexer._ATN, CELLexer.DecisionsToDFA, new PredictionContextCache()); + } + + public get grammarFileName(): string { return "CEL.g4"; } + + public get literalNames(): (string | null)[] { return CELLexer.literalNames; } + public get symbolicNames(): (string | null)[] { return CELLexer.symbolicNames; } + public get ruleNames(): string[] { return CELLexer.ruleNames; } + + public get serializedATN(): number[] { return CELLexer._serializedATN; } + + public get channelNames(): string[] { return CELLexer.channelNames; } + + public get modeNames(): string[] { return CELLexer.modeNames; } + + public static readonly _serializedATN: number[] = [4,0,36,423,6,-1,2,0, + 7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,6,2,7,7,7,2,8,7,8,2,9, + 7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,13,7,13,2,14,7,14,2,15,7,15,2,16,7, + 16,2,17,7,17,2,18,7,18,2,19,7,19,2,20,7,20,2,21,7,21,2,22,7,22,2,23,7,23, + 2,24,7,24,2,25,7,25,2,26,7,26,2,27,7,27,2,28,7,28,2,29,7,29,2,30,7,30,2, + 31,7,31,2,32,7,32,2,33,7,33,2,34,7,34,2,35,7,35,2,36,7,36,2,37,7,37,2,38, + 7,38,2,39,7,39,2,40,7,40,2,41,7,41,2,42,7,42,2,43,7,43,2,44,7,44,2,45,7, + 45,2,46,7,46,1,0,1,0,1,0,1,1,1,1,1,1,1,2,1,2,1,2,1,3,1,3,1,4,1,4,1,4,1, + 5,1,5,1,5,1,6,1,6,1,7,1,7,1,7,1,8,1,8,1,8,1,9,1,9,1,10,1,10,1,11,1,11,1, + 12,1,12,1,13,1,13,1,14,1,14,1,15,1,15,1,16,1,16,1,17,1,17,1,18,1,18,1,19, + 1,19,1,20,1,20,1,21,1,21,1,22,1,22,1,23,1,23,1,24,1,24,1,25,1,25,1,25,1, + 25,1,25,1,26,1,26,1,26,1,26,1,26,1,26,1,27,1,27,1,27,1,27,1,27,1,28,1,28, + 1,29,1,29,1,30,1,30,1,31,1,31,3,31,177,8,31,1,31,4,31,180,8,31,11,31,12, + 31,181,1,32,1,32,1,33,1,33,1,34,1,34,1,34,1,34,3,34,192,8,34,1,35,1,35, + 1,35,1,36,1,36,1,36,1,36,1,36,1,37,1,37,1,37,1,37,1,37,1,38,1,38,1,38,1, + 38,1,38,1,38,1,38,1,38,1,38,1,38,1,38,1,38,1,38,1,38,1,38,1,38,1,38,1,38, + 3,38,225,8,38,1,39,4,39,228,8,39,11,39,12,39,229,1,39,1,39,1,40,1,40,1, + 40,1,40,5,40,238,8,40,10,40,12,40,241,9,40,1,40,1,40,1,41,4,41,246,8,41, + 11,41,12,41,247,1,41,1,41,4,41,252,8,41,11,41,12,41,253,1,41,3,41,257,8, + 41,1,41,4,41,260,8,41,11,41,12,41,261,1,41,1,41,1,41,1,41,4,41,268,8,41, + 11,41,12,41,269,1,41,3,41,273,8,41,3,41,275,8,41,1,42,4,42,278,8,42,11, + 42,12,42,279,1,42,1,42,1,42,1,42,4,42,286,8,42,11,42,12,42,287,3,42,290, + 8,42,1,43,4,43,293,8,43,11,43,12,43,294,1,43,1,43,1,43,1,43,1,43,1,43,4, + 43,303,8,43,11,43,12,43,304,1,43,1,43,3,43,309,8,43,1,44,1,44,1,44,5,44, + 314,8,44,10,44,12,44,317,9,44,1,44,1,44,1,44,1,44,5,44,323,8,44,10,44,12, + 44,326,9,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,5,44,335,8,44,10,44,12,44, + 338,9,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,5,44,349,8,44,10, + 44,12,44,352,9,44,1,44,1,44,1,44,1,44,1,44,1,44,5,44,360,8,44,10,44,12, + 44,363,9,44,1,44,1,44,1,44,1,44,1,44,5,44,370,8,44,10,44,12,44,373,9,44, + 1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,5,44,383,8,44,10,44,12,44,386,9, + 44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,5,44,398,8,44,10,44, + 12,44,401,9,44,1,44,1,44,1,44,1,44,3,44,407,8,44,1,45,1,45,1,45,1,46,1, + 46,3,46,414,8,46,1,46,1,46,1,46,5,46,419,8,46,10,46,12,46,422,9,46,4,336, + 350,384,399,0,47,1,1,3,2,5,3,7,4,9,5,11,6,13,7,15,8,17,9,19,10,21,11,23, + 12,25,13,27,14,29,15,31,16,33,17,35,18,37,19,39,20,41,21,43,22,45,23,47, + 24,49,25,51,26,53,27,55,28,57,0,59,0,61,0,63,0,65,0,67,0,69,0,71,0,73,0, + 75,0,77,0,79,29,81,30,83,31,85,32,87,33,89,34,91,35,93,36,1,0,16,2,0,65, + 90,97,122,2,0,69,69,101,101,2,0,43,43,45,45,3,0,48,57,65,70,97,102,2,0, + 82,82,114,114,10,0,34,34,39,39,63,63,92,92,96,98,102,102,110,110,114,114, + 116,116,118,118,2,0,88,88,120,120,3,0,9,10,12,13,32,32,1,0,10,10,2,0,85, + 85,117,117,4,0,10,10,13,13,34,34,92,92,4,0,10,10,13,13,39,39,92,92,1,0, + 92,92,3,0,10,10,13,13,34,34,3,0,10,10,13,13,39,39,2,0,66,66,98,98,456,0, + 1,1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0,0,7,1,0,0,0,0,9,1,0,0,0,0,11,1,0,0,0, + 0,13,1,0,0,0,0,15,1,0,0,0,0,17,1,0,0,0,0,19,1,0,0,0,0,21,1,0,0,0,0,23,1, + 0,0,0,0,25,1,0,0,0,0,27,1,0,0,0,0,29,1,0,0,0,0,31,1,0,0,0,0,33,1,0,0,0, + 0,35,1,0,0,0,0,37,1,0,0,0,0,39,1,0,0,0,0,41,1,0,0,0,0,43,1,0,0,0,0,45,1, + 0,0,0,0,47,1,0,0,0,0,49,1,0,0,0,0,51,1,0,0,0,0,53,1,0,0,0,0,55,1,0,0,0, + 0,79,1,0,0,0,0,81,1,0,0,0,0,83,1,0,0,0,0,85,1,0,0,0,0,87,1,0,0,0,0,89,1, + 0,0,0,0,91,1,0,0,0,0,93,1,0,0,0,1,95,1,0,0,0,3,98,1,0,0,0,5,101,1,0,0,0, + 7,104,1,0,0,0,9,106,1,0,0,0,11,109,1,0,0,0,13,112,1,0,0,0,15,114,1,0,0, + 0,17,117,1,0,0,0,19,120,1,0,0,0,21,122,1,0,0,0,23,124,1,0,0,0,25,126,1, + 0,0,0,27,128,1,0,0,0,29,130,1,0,0,0,31,132,1,0,0,0,33,134,1,0,0,0,35,136, + 1,0,0,0,37,138,1,0,0,0,39,140,1,0,0,0,41,142,1,0,0,0,43,144,1,0,0,0,45, + 146,1,0,0,0,47,148,1,0,0,0,49,150,1,0,0,0,51,152,1,0,0,0,53,157,1,0,0,0, + 55,163,1,0,0,0,57,168,1,0,0,0,59,170,1,0,0,0,61,172,1,0,0,0,63,174,1,0, + 0,0,65,183,1,0,0,0,67,185,1,0,0,0,69,191,1,0,0,0,71,193,1,0,0,0,73,196, + 1,0,0,0,75,201,1,0,0,0,77,224,1,0,0,0,79,227,1,0,0,0,81,233,1,0,0,0,83, + 274,1,0,0,0,85,289,1,0,0,0,87,308,1,0,0,0,89,406,1,0,0,0,91,408,1,0,0,0, + 93,413,1,0,0,0,95,96,5,61,0,0,96,97,5,61,0,0,97,2,1,0,0,0,98,99,5,33,0, + 0,99,100,5,61,0,0,100,4,1,0,0,0,101,102,5,105,0,0,102,103,5,110,0,0,103, + 6,1,0,0,0,104,105,5,60,0,0,105,8,1,0,0,0,106,107,5,60,0,0,107,108,5,61, + 0,0,108,10,1,0,0,0,109,110,5,62,0,0,110,111,5,61,0,0,111,12,1,0,0,0,112, + 113,5,62,0,0,113,14,1,0,0,0,114,115,5,38,0,0,115,116,5,38,0,0,116,16,1, + 0,0,0,117,118,5,124,0,0,118,119,5,124,0,0,119,18,1,0,0,0,120,121,5,91,0, + 0,121,20,1,0,0,0,122,123,5,93,0,0,123,22,1,0,0,0,124,125,5,123,0,0,125, + 24,1,0,0,0,126,127,5,125,0,0,127,26,1,0,0,0,128,129,5,40,0,0,129,28,1,0, + 0,0,130,131,5,41,0,0,131,30,1,0,0,0,132,133,5,46,0,0,133,32,1,0,0,0,134, + 135,5,44,0,0,135,34,1,0,0,0,136,137,5,45,0,0,137,36,1,0,0,0,138,139,5,33, + 0,0,139,38,1,0,0,0,140,141,5,63,0,0,141,40,1,0,0,0,142,143,5,58,0,0,143, + 42,1,0,0,0,144,145,5,43,0,0,145,44,1,0,0,0,146,147,5,42,0,0,147,46,1,0, + 0,0,148,149,5,47,0,0,149,48,1,0,0,0,150,151,5,37,0,0,151,50,1,0,0,0,152, + 153,5,116,0,0,153,154,5,114,0,0,154,155,5,117,0,0,155,156,5,101,0,0,156, + 52,1,0,0,0,157,158,5,102,0,0,158,159,5,97,0,0,159,160,5,108,0,0,160,161, + 5,115,0,0,161,162,5,101,0,0,162,54,1,0,0,0,163,164,5,110,0,0,164,165,5, + 117,0,0,165,166,5,108,0,0,166,167,5,108,0,0,167,56,1,0,0,0,168,169,5,92, + 0,0,169,58,1,0,0,0,170,171,7,0,0,0,171,60,1,0,0,0,172,173,2,48,57,0,173, + 62,1,0,0,0,174,176,7,1,0,0,175,177,7,2,0,0,176,175,1,0,0,0,176,177,1,0, + 0,0,177,179,1,0,0,0,178,180,3,61,30,0,179,178,1,0,0,0,180,181,1,0,0,0,181, + 179,1,0,0,0,181,182,1,0,0,0,182,64,1,0,0,0,183,184,7,3,0,0,184,66,1,0,0, + 0,185,186,7,4,0,0,186,68,1,0,0,0,187,192,3,71,35,0,188,192,3,75,37,0,189, + 192,3,77,38,0,190,192,3,73,36,0,191,187,1,0,0,0,191,188,1,0,0,0,191,189, + 1,0,0,0,191,190,1,0,0,0,192,70,1,0,0,0,193,194,3,57,28,0,194,195,7,5,0, + 0,195,72,1,0,0,0,196,197,3,57,28,0,197,198,2,48,51,0,198,199,2,48,55,0, + 199,200,2,48,55,0,200,74,1,0,0,0,201,202,3,57,28,0,202,203,7,6,0,0,203, + 204,3,65,32,0,204,205,3,65,32,0,205,76,1,0,0,0,206,207,3,57,28,0,207,208, + 5,117,0,0,208,209,3,65,32,0,209,210,3,65,32,0,210,211,3,65,32,0,211,212, + 3,65,32,0,212,225,1,0,0,0,213,214,3,57,28,0,214,215,5,85,0,0,215,216,3, + 65,32,0,216,217,3,65,32,0,217,218,3,65,32,0,218,219,3,65,32,0,219,220,3, + 65,32,0,220,221,3,65,32,0,221,222,3,65,32,0,222,223,3,65,32,0,223,225,1, + 0,0,0,224,206,1,0,0,0,224,213,1,0,0,0,225,78,1,0,0,0,226,228,7,7,0,0,227, + 226,1,0,0,0,228,229,1,0,0,0,229,227,1,0,0,0,229,230,1,0,0,0,230,231,1,0, + 0,0,231,232,6,39,0,0,232,80,1,0,0,0,233,234,5,47,0,0,234,235,5,47,0,0,235, + 239,1,0,0,0,236,238,8,8,0,0,237,236,1,0,0,0,238,241,1,0,0,0,239,237,1,0, + 0,0,239,240,1,0,0,0,240,242,1,0,0,0,241,239,1,0,0,0,242,243,6,40,0,0,243, + 82,1,0,0,0,244,246,3,61,30,0,245,244,1,0,0,0,246,247,1,0,0,0,247,245,1, + 0,0,0,247,248,1,0,0,0,248,249,1,0,0,0,249,251,5,46,0,0,250,252,3,61,30, + 0,251,250,1,0,0,0,252,253,1,0,0,0,253,251,1,0,0,0,253,254,1,0,0,0,254,256, + 1,0,0,0,255,257,3,63,31,0,256,255,1,0,0,0,256,257,1,0,0,0,257,275,1,0,0, + 0,258,260,3,61,30,0,259,258,1,0,0,0,260,261,1,0,0,0,261,259,1,0,0,0,261, + 262,1,0,0,0,262,263,1,0,0,0,263,264,3,63,31,0,264,275,1,0,0,0,265,267,5, + 46,0,0,266,268,3,61,30,0,267,266,1,0,0,0,268,269,1,0,0,0,269,267,1,0,0, + 0,269,270,1,0,0,0,270,272,1,0,0,0,271,273,3,63,31,0,272,271,1,0,0,0,272, + 273,1,0,0,0,273,275,1,0,0,0,274,245,1,0,0,0,274,259,1,0,0,0,274,265,1,0, + 0,0,275,84,1,0,0,0,276,278,3,61,30,0,277,276,1,0,0,0,278,279,1,0,0,0,279, + 277,1,0,0,0,279,280,1,0,0,0,280,290,1,0,0,0,281,282,5,48,0,0,282,283,5, + 120,0,0,283,285,1,0,0,0,284,286,3,65,32,0,285,284,1,0,0,0,286,287,1,0,0, + 0,287,285,1,0,0,0,287,288,1,0,0,0,288,290,1,0,0,0,289,277,1,0,0,0,289,281, + 1,0,0,0,290,86,1,0,0,0,291,293,3,61,30,0,292,291,1,0,0,0,293,294,1,0,0, + 0,294,292,1,0,0,0,294,295,1,0,0,0,295,296,1,0,0,0,296,297,7,9,0,0,297,309, + 1,0,0,0,298,299,5,48,0,0,299,300,5,120,0,0,300,302,1,0,0,0,301,303,3,65, + 32,0,302,301,1,0,0,0,303,304,1,0,0,0,304,302,1,0,0,0,304,305,1,0,0,0,305, + 306,1,0,0,0,306,307,7,9,0,0,307,309,1,0,0,0,308,292,1,0,0,0,308,298,1,0, + 0,0,309,88,1,0,0,0,310,315,5,34,0,0,311,314,3,69,34,0,312,314,8,10,0,0, + 313,311,1,0,0,0,313,312,1,0,0,0,314,317,1,0,0,0,315,313,1,0,0,0,315,316, + 1,0,0,0,316,318,1,0,0,0,317,315,1,0,0,0,318,407,5,34,0,0,319,324,5,39,0, + 0,320,323,3,69,34,0,321,323,8,11,0,0,322,320,1,0,0,0,322,321,1,0,0,0,323, + 326,1,0,0,0,324,322,1,0,0,0,324,325,1,0,0,0,325,327,1,0,0,0,326,324,1,0, + 0,0,327,407,5,39,0,0,328,329,5,34,0,0,329,330,5,34,0,0,330,331,5,34,0,0, + 331,336,1,0,0,0,332,335,3,69,34,0,333,335,8,12,0,0,334,332,1,0,0,0,334, + 333,1,0,0,0,335,338,1,0,0,0,336,337,1,0,0,0,336,334,1,0,0,0,337,339,1,0, + 0,0,338,336,1,0,0,0,339,340,5,34,0,0,340,341,5,34,0,0,341,407,5,34,0,0, + 342,343,5,39,0,0,343,344,5,39,0,0,344,345,5,39,0,0,345,350,1,0,0,0,346, + 349,3,69,34,0,347,349,8,12,0,0,348,346,1,0,0,0,348,347,1,0,0,0,349,352, + 1,0,0,0,350,351,1,0,0,0,350,348,1,0,0,0,351,353,1,0,0,0,352,350,1,0,0,0, + 353,354,5,39,0,0,354,355,5,39,0,0,355,407,5,39,0,0,356,357,3,67,33,0,357, + 361,5,34,0,0,358,360,8,13,0,0,359,358,1,0,0,0,360,363,1,0,0,0,361,359,1, + 0,0,0,361,362,1,0,0,0,362,364,1,0,0,0,363,361,1,0,0,0,364,365,5,34,0,0, + 365,407,1,0,0,0,366,367,3,67,33,0,367,371,5,39,0,0,368,370,8,14,0,0,369, + 368,1,0,0,0,370,373,1,0,0,0,371,369,1,0,0,0,371,372,1,0,0,0,372,374,1,0, + 0,0,373,371,1,0,0,0,374,375,5,39,0,0,375,407,1,0,0,0,376,377,3,67,33,0, + 377,378,5,34,0,0,378,379,5,34,0,0,379,380,5,34,0,0,380,384,1,0,0,0,381, + 383,9,0,0,0,382,381,1,0,0,0,383,386,1,0,0,0,384,385,1,0,0,0,384,382,1,0, + 0,0,385,387,1,0,0,0,386,384,1,0,0,0,387,388,5,34,0,0,388,389,5,34,0,0,389, + 390,5,34,0,0,390,407,1,0,0,0,391,392,3,67,33,0,392,393,5,39,0,0,393,394, + 5,39,0,0,394,395,5,39,0,0,395,399,1,0,0,0,396,398,9,0,0,0,397,396,1,0,0, + 0,398,401,1,0,0,0,399,400,1,0,0,0,399,397,1,0,0,0,400,402,1,0,0,0,401,399, + 1,0,0,0,402,403,5,39,0,0,403,404,5,39,0,0,404,405,5,39,0,0,405,407,1,0, + 0,0,406,310,1,0,0,0,406,319,1,0,0,0,406,328,1,0,0,0,406,342,1,0,0,0,406, + 356,1,0,0,0,406,366,1,0,0,0,406,376,1,0,0,0,406,391,1,0,0,0,407,90,1,0, + 0,0,408,409,7,15,0,0,409,410,3,89,44,0,410,92,1,0,0,0,411,414,3,59,29,0, + 412,414,5,95,0,0,413,411,1,0,0,0,413,412,1,0,0,0,414,420,1,0,0,0,415,419, + 3,59,29,0,416,419,3,61,30,0,417,419,5,95,0,0,418,415,1,0,0,0,418,416,1, + 0,0,0,418,417,1,0,0,0,419,422,1,0,0,0,420,418,1,0,0,0,420,421,1,0,0,0,421, + 94,1,0,0,0,422,420,1,0,0,0,36,0,176,181,191,224,229,239,247,253,256,261, + 269,272,274,279,287,289,294,304,308,313,315,322,324,334,336,348,350,361, + 371,384,399,406,413,418,420,1,0,1,0]; + + private static __ATN: ATN; + public static get _ATN(): ATN { + if (!CELLexer.__ATN) { + CELLexer.__ATN = new ATNDeserializer().deserialize(CELLexer._serializedATN); + } + + return CELLexer.__ATN; + } + + + static DecisionsToDFA = CELLexer._ATN.decisionToState.map( (ds: DecisionState, index: number) => new DFA(ds, index) ); +} \ No newline at end of file diff --git a/packages/cel/src/lib/gen/CELListener.ts b/packages/cel/src/lib/gen/CELListener.ts new file mode 100644 index 0000000..fe979cb --- /dev/null +++ b/packages/cel/src/lib/gen/CELListener.ts @@ -0,0 +1,419 @@ +// Generated from packages/cel/src/lib/gen/CEL.g4 by ANTLR 4.13.1 + +import {ParseTreeListener} from "antlr4"; + + +import { StartContext } from "./CELParser"; +import { ExprContext } from "./CELParser"; +import { ConditionalOrContext } from "./CELParser"; +import { ConditionalAndContext } from "./CELParser"; +import { RelationContext } from "./CELParser"; +import { CalcContext } from "./CELParser"; +import { MemberExprContext } from "./CELParser"; +import { LogicalNotContext } from "./CELParser"; +import { NegateContext } from "./CELParser"; +import { MemberCallContext } from "./CELParser"; +import { SelectContext } from "./CELParser"; +import { PrimaryExprContext } from "./CELParser"; +import { IndexContext } from "./CELParser"; +import { IdentOrGlobalCallContext } from "./CELParser"; +import { NestedContext } from "./CELParser"; +import { CreateListContext } from "./CELParser"; +import { CreateStructContext } from "./CELParser"; +import { CreateMessageContext } from "./CELParser"; +import { ConstantLiteralContext } from "./CELParser"; +import { ExprListContext } from "./CELParser"; +import { ListInitContext } from "./CELParser"; +import { FieldInitializerListContext } from "./CELParser"; +import { OptFieldContext } from "./CELParser"; +import { MapInitializerListContext } from "./CELParser"; +import { OptExprContext } from "./CELParser"; +import { IntContext } from "./CELParser"; +import { UintContext } from "./CELParser"; +import { DoubleContext } from "./CELParser"; +import { StringContext } from "./CELParser"; +import { BytesContext } from "./CELParser"; +import { BoolTrueContext } from "./CELParser"; +import { BoolFalseContext } from "./CELParser"; +import { NullContext } from "./CELParser"; + + +/** + * This interface defines a complete listener for a parse tree produced by + * `CELParser`. + */ +export default class CELListener extends ParseTreeListener { + /** + * Enter a parse tree produced by `CELParser.start`. + * @param ctx the parse tree + */ + enterStart?: (ctx: StartContext) => void; + /** + * Exit a parse tree produced by `CELParser.start`. + * @param ctx the parse tree + */ + exitStart?: (ctx: StartContext) => void; + /** + * Enter a parse tree produced by `CELParser.expr`. + * @param ctx the parse tree + */ + enterExpr?: (ctx: ExprContext) => void; + /** + * Exit a parse tree produced by `CELParser.expr`. + * @param ctx the parse tree + */ + exitExpr?: (ctx: ExprContext) => void; + /** + * Enter a parse tree produced by `CELParser.conditionalOr`. + * @param ctx the parse tree + */ + enterConditionalOr?: (ctx: ConditionalOrContext) => void; + /** + * Exit a parse tree produced by `CELParser.conditionalOr`. + * @param ctx the parse tree + */ + exitConditionalOr?: (ctx: ConditionalOrContext) => void; + /** + * Enter a parse tree produced by `CELParser.conditionalAnd`. + * @param ctx the parse tree + */ + enterConditionalAnd?: (ctx: ConditionalAndContext) => void; + /** + * Exit a parse tree produced by `CELParser.conditionalAnd`. + * @param ctx the parse tree + */ + exitConditionalAnd?: (ctx: ConditionalAndContext) => void; + /** + * Enter a parse tree produced by `CELParser.relation`. + * @param ctx the parse tree + */ + enterRelation?: (ctx: RelationContext) => void; + /** + * Exit a parse tree produced by `CELParser.relation`. + * @param ctx the parse tree + */ + exitRelation?: (ctx: RelationContext) => void; + /** + * Enter a parse tree produced by `CELParser.calc`. + * @param ctx the parse tree + */ + enterCalc?: (ctx: CalcContext) => void; + /** + * Exit a parse tree produced by `CELParser.calc`. + * @param ctx the parse tree + */ + exitCalc?: (ctx: CalcContext) => void; + /** + * Enter a parse tree produced by the `MemberExpr` + * labeled alternative in `CELParser.unary`. + * @param ctx the parse tree + */ + enterMemberExpr?: (ctx: MemberExprContext) => void; + /** + * Exit a parse tree produced by the `MemberExpr` + * labeled alternative in `CELParser.unary`. + * @param ctx the parse tree + */ + exitMemberExpr?: (ctx: MemberExprContext) => void; + /** + * Enter a parse tree produced by the `LogicalNot` + * labeled alternative in `CELParser.unary`. + * @param ctx the parse tree + */ + enterLogicalNot?: (ctx: LogicalNotContext) => void; + /** + * Exit a parse tree produced by the `LogicalNot` + * labeled alternative in `CELParser.unary`. + * @param ctx the parse tree + */ + exitLogicalNot?: (ctx: LogicalNotContext) => void; + /** + * Enter a parse tree produced by the `Negate` + * labeled alternative in `CELParser.unary`. + * @param ctx the parse tree + */ + enterNegate?: (ctx: NegateContext) => void; + /** + * Exit a parse tree produced by the `Negate` + * labeled alternative in `CELParser.unary`. + * @param ctx the parse tree + */ + exitNegate?: (ctx: NegateContext) => void; + /** + * Enter a parse tree produced by the `MemberCall` + * labeled alternative in `CELParser.member`. + * @param ctx the parse tree + */ + enterMemberCall?: (ctx: MemberCallContext) => void; + /** + * Exit a parse tree produced by the `MemberCall` + * labeled alternative in `CELParser.member`. + * @param ctx the parse tree + */ + exitMemberCall?: (ctx: MemberCallContext) => void; + /** + * Enter a parse tree produced by the `Select` + * labeled alternative in `CELParser.member`. + * @param ctx the parse tree + */ + enterSelect?: (ctx: SelectContext) => void; + /** + * Exit a parse tree produced by the `Select` + * labeled alternative in `CELParser.member`. + * @param ctx the parse tree + */ + exitSelect?: (ctx: SelectContext) => void; + /** + * Enter a parse tree produced by the `PrimaryExpr` + * labeled alternative in `CELParser.member`. + * @param ctx the parse tree + */ + enterPrimaryExpr?: (ctx: PrimaryExprContext) => void; + /** + * Exit a parse tree produced by the `PrimaryExpr` + * labeled alternative in `CELParser.member`. + * @param ctx the parse tree + */ + exitPrimaryExpr?: (ctx: PrimaryExprContext) => void; + /** + * Enter a parse tree produced by the `Index` + * labeled alternative in `CELParser.member`. + * @param ctx the parse tree + */ + enterIndex?: (ctx: IndexContext) => void; + /** + * Exit a parse tree produced by the `Index` + * labeled alternative in `CELParser.member`. + * @param ctx the parse tree + */ + exitIndex?: (ctx: IndexContext) => void; + /** + * Enter a parse tree produced by the `IdentOrGlobalCall` + * labeled alternative in `CELParser.primary`. + * @param ctx the parse tree + */ + enterIdentOrGlobalCall?: (ctx: IdentOrGlobalCallContext) => void; + /** + * Exit a parse tree produced by the `IdentOrGlobalCall` + * labeled alternative in `CELParser.primary`. + * @param ctx the parse tree + */ + exitIdentOrGlobalCall?: (ctx: IdentOrGlobalCallContext) => void; + /** + * Enter a parse tree produced by the `Nested` + * labeled alternative in `CELParser.primary`. + * @param ctx the parse tree + */ + enterNested?: (ctx: NestedContext) => void; + /** + * Exit a parse tree produced by the `Nested` + * labeled alternative in `CELParser.primary`. + * @param ctx the parse tree + */ + exitNested?: (ctx: NestedContext) => void; + /** + * Enter a parse tree produced by the `CreateList` + * labeled alternative in `CELParser.primary`. + * @param ctx the parse tree + */ + enterCreateList?: (ctx: CreateListContext) => void; + /** + * Exit a parse tree produced by the `CreateList` + * labeled alternative in `CELParser.primary`. + * @param ctx the parse tree + */ + exitCreateList?: (ctx: CreateListContext) => void; + /** + * Enter a parse tree produced by the `CreateStruct` + * labeled alternative in `CELParser.primary`. + * @param ctx the parse tree + */ + enterCreateStruct?: (ctx: CreateStructContext) => void; + /** + * Exit a parse tree produced by the `CreateStruct` + * labeled alternative in `CELParser.primary`. + * @param ctx the parse tree + */ + exitCreateStruct?: (ctx: CreateStructContext) => void; + /** + * Enter a parse tree produced by the `CreateMessage` + * labeled alternative in `CELParser.primary`. + * @param ctx the parse tree + */ + enterCreateMessage?: (ctx: CreateMessageContext) => void; + /** + * Exit a parse tree produced by the `CreateMessage` + * labeled alternative in `CELParser.primary`. + * @param ctx the parse tree + */ + exitCreateMessage?: (ctx: CreateMessageContext) => void; + /** + * Enter a parse tree produced by the `ConstantLiteral` + * labeled alternative in `CELParser.primary`. + * @param ctx the parse tree + */ + enterConstantLiteral?: (ctx: ConstantLiteralContext) => void; + /** + * Exit a parse tree produced by the `ConstantLiteral` + * labeled alternative in `CELParser.primary`. + * @param ctx the parse tree + */ + exitConstantLiteral?: (ctx: ConstantLiteralContext) => void; + /** + * Enter a parse tree produced by `CELParser.exprList`. + * @param ctx the parse tree + */ + enterExprList?: (ctx: ExprListContext) => void; + /** + * Exit a parse tree produced by `CELParser.exprList`. + * @param ctx the parse tree + */ + exitExprList?: (ctx: ExprListContext) => void; + /** + * Enter a parse tree produced by `CELParser.listInit`. + * @param ctx the parse tree + */ + enterListInit?: (ctx: ListInitContext) => void; + /** + * Exit a parse tree produced by `CELParser.listInit`. + * @param ctx the parse tree + */ + exitListInit?: (ctx: ListInitContext) => void; + /** + * Enter a parse tree produced by `CELParser.fieldInitializerList`. + * @param ctx the parse tree + */ + enterFieldInitializerList?: (ctx: FieldInitializerListContext) => void; + /** + * Exit a parse tree produced by `CELParser.fieldInitializerList`. + * @param ctx the parse tree + */ + exitFieldInitializerList?: (ctx: FieldInitializerListContext) => void; + /** + * Enter a parse tree produced by `CELParser.optField`. + * @param ctx the parse tree + */ + enterOptField?: (ctx: OptFieldContext) => void; + /** + * Exit a parse tree produced by `CELParser.optField`. + * @param ctx the parse tree + */ + exitOptField?: (ctx: OptFieldContext) => void; + /** + * Enter a parse tree produced by `CELParser.mapInitializerList`. + * @param ctx the parse tree + */ + enterMapInitializerList?: (ctx: MapInitializerListContext) => void; + /** + * Exit a parse tree produced by `CELParser.mapInitializerList`. + * @param ctx the parse tree + */ + exitMapInitializerList?: (ctx: MapInitializerListContext) => void; + /** + * Enter a parse tree produced by `CELParser.optExpr`. + * @param ctx the parse tree + */ + enterOptExpr?: (ctx: OptExprContext) => void; + /** + * Exit a parse tree produced by `CELParser.optExpr`. + * @param ctx the parse tree + */ + exitOptExpr?: (ctx: OptExprContext) => void; + /** + * Enter a parse tree produced by the `Int` + * labeled alternative in `CELParser.literal`. + * @param ctx the parse tree + */ + enterInt?: (ctx: IntContext) => void; + /** + * Exit a parse tree produced by the `Int` + * labeled alternative in `CELParser.literal`. + * @param ctx the parse tree + */ + exitInt?: (ctx: IntContext) => void; + /** + * Enter a parse tree produced by the `Uint` + * labeled alternative in `CELParser.literal`. + * @param ctx the parse tree + */ + enterUint?: (ctx: UintContext) => void; + /** + * Exit a parse tree produced by the `Uint` + * labeled alternative in `CELParser.literal`. + * @param ctx the parse tree + */ + exitUint?: (ctx: UintContext) => void; + /** + * Enter a parse tree produced by the `Double` + * labeled alternative in `CELParser.literal`. + * @param ctx the parse tree + */ + enterDouble?: (ctx: DoubleContext) => void; + /** + * Exit a parse tree produced by the `Double` + * labeled alternative in `CELParser.literal`. + * @param ctx the parse tree + */ + exitDouble?: (ctx: DoubleContext) => void; + /** + * Enter a parse tree produced by the `String` + * labeled alternative in `CELParser.literal`. + * @param ctx the parse tree + */ + enterString?: (ctx: StringContext) => void; + /** + * Exit a parse tree produced by the `String` + * labeled alternative in `CELParser.literal`. + * @param ctx the parse tree + */ + exitString?: (ctx: StringContext) => void; + /** + * Enter a parse tree produced by the `Bytes` + * labeled alternative in `CELParser.literal`. + * @param ctx the parse tree + */ + enterBytes?: (ctx: BytesContext) => void; + /** + * Exit a parse tree produced by the `Bytes` + * labeled alternative in `CELParser.literal`. + * @param ctx the parse tree + */ + exitBytes?: (ctx: BytesContext) => void; + /** + * Enter a parse tree produced by the `BoolTrue` + * labeled alternative in `CELParser.literal`. + * @param ctx the parse tree + */ + enterBoolTrue?: (ctx: BoolTrueContext) => void; + /** + * Exit a parse tree produced by the `BoolTrue` + * labeled alternative in `CELParser.literal`. + * @param ctx the parse tree + */ + exitBoolTrue?: (ctx: BoolTrueContext) => void; + /** + * Enter a parse tree produced by the `BoolFalse` + * labeled alternative in `CELParser.literal`. + * @param ctx the parse tree + */ + enterBoolFalse?: (ctx: BoolFalseContext) => void; + /** + * Exit a parse tree produced by the `BoolFalse` + * labeled alternative in `CELParser.literal`. + * @param ctx the parse tree + */ + exitBoolFalse?: (ctx: BoolFalseContext) => void; + /** + * Enter a parse tree produced by the `Null` + * labeled alternative in `CELParser.literal`. + * @param ctx the parse tree + */ + enterNull?: (ctx: NullContext) => void; + /** + * Exit a parse tree produced by the `Null` + * labeled alternative in `CELParser.literal`. + * @param ctx the parse tree + */ + exitNull?: (ctx: NullContext) => void; +} + diff --git a/packages/cel/src/lib/gen/CELParser.ts b/packages/cel/src/lib/gen/CELParser.ts new file mode 100644 index 0000000..b68831b --- /dev/null +++ b/packages/cel/src/lib/gen/CELParser.ts @@ -0,0 +1,2774 @@ +// Generated from packages/cel/src/lib/gen/CEL.g4 by ANTLR 4.13.1 +// noinspection ES6UnusedImports,JSUnusedGlobalSymbols,JSUnusedLocalSymbols + +import { + ATN, + ATNDeserializer, DecisionState, DFA, FailedPredicateException, + RecognitionException, NoViableAltException, BailErrorStrategy, + Parser, ParserATNSimulator, + RuleContext, ParserRuleContext, PredictionMode, PredictionContextCache, + TerminalNode, RuleNode, + Token, TokenStream, + Interval, IntervalSet +} from 'antlr4'; +import CELListener from "./CELListener.js"; +import CELVisitor from "./CELVisitor.js"; + +// for running tests with parameters, TODO: discuss strategy for typed parameters in CI +// eslint-disable-next-line no-unused-vars +type int = number; + +export default class CELParser extends Parser { + public static readonly EQUALS = 1; + public static readonly NOT_EQUALS = 2; + public static readonly IN = 3; + public static readonly LESS = 4; + public static readonly LESS_EQUALS = 5; + public static readonly GREATER_EQUALS = 6; + public static readonly GREATER = 7; + public static readonly LOGICAL_AND = 8; + public static readonly LOGICAL_OR = 9; + public static readonly LBRACKET = 10; + public static readonly RPRACKET = 11; + public static readonly LBRACE = 12; + public static readonly RBRACE = 13; + public static readonly LPAREN = 14; + public static readonly RPAREN = 15; + public static readonly DOT = 16; + public static readonly COMMA = 17; + public static readonly MINUS = 18; + public static readonly EXCLAM = 19; + public static readonly QUESTIONMARK = 20; + public static readonly COLON = 21; + public static readonly PLUS = 22; + public static readonly STAR = 23; + public static readonly SLASH = 24; + public static readonly PERCENT = 25; + public static readonly CEL_TRUE = 26; + public static readonly CEL_FALSE = 27; + public static readonly NUL = 28; + public static readonly WHITESPACE = 29; + public static readonly COMMENT = 30; + public static readonly NUM_FLOAT = 31; + public static readonly NUM_INT = 32; + public static readonly NUM_UINT = 33; + public static readonly STRING = 34; + public static readonly BYTES = 35; + public static readonly IDENTIFIER = 36; + public static readonly EOF = Token.EOF; + public static readonly RULE_start = 0; + public static readonly RULE_expr = 1; + public static readonly RULE_conditionalOr = 2; + public static readonly RULE_conditionalAnd = 3; + public static readonly RULE_relation = 4; + public static readonly RULE_calc = 5; + public static readonly RULE_unary = 6; + public static readonly RULE_member = 7; + public static readonly RULE_primary = 8; + public static readonly RULE_exprList = 9; + public static readonly RULE_listInit = 10; + public static readonly RULE_fieldInitializerList = 11; + public static readonly RULE_optField = 12; + public static readonly RULE_mapInitializerList = 13; + public static readonly RULE_optExpr = 14; + public static readonly RULE_literal = 15; + public static readonly literalNames: (string | null)[] = [ null, "'=='", + "'!='", "'in'", + "'<'", "'<='", + "'>='", "'>'", + "'&&'", "'||'", + "'['", "']'", + "'{'", "'}'", + "'('", "')'", + "'.'", "','", + "'-'", "'!'", + "'?'", "':'", + "'+'", "'*'", + "'/'", "'%'", + "'true'", "'false'", + "'null'" ]; + public static readonly symbolicNames: (string | null)[] = [ null, "EQUALS", + "NOT_EQUALS", + "IN", "LESS", + "LESS_EQUALS", + "GREATER_EQUALS", + "GREATER", + "LOGICAL_AND", + "LOGICAL_OR", + "LBRACKET", + "RPRACKET", + "LBRACE", "RBRACE", + "LPAREN", "RPAREN", + "DOT", "COMMA", + "MINUS", "EXCLAM", + "QUESTIONMARK", + "COLON", "PLUS", + "STAR", "SLASH", + "PERCENT", + "CEL_TRUE", + "CEL_FALSE", + "NUL", "WHITESPACE", + "COMMENT", + "NUM_FLOAT", + "NUM_INT", + "NUM_UINT", + "STRING", "BYTES", + "IDENTIFIER" ]; + // tslint:disable:no-trailing-whitespace + public static readonly ruleNames: string[] = [ + "start", "expr", "conditionalOr", "conditionalAnd", "relation", "calc", + "unary", "member", "primary", "exprList", "listInit", "fieldInitializerList", + "optField", "mapInitializerList", "optExpr", "literal", + ]; + public get grammarFileName(): string { return "CEL.g4"; } + public get literalNames(): (string | null)[] { return CELParser.literalNames; } + public get symbolicNames(): (string | null)[] { return CELParser.symbolicNames; } + public get ruleNames(): string[] { return CELParser.ruleNames; } + public get serializedATN(): number[] { return CELParser._serializedATN; } + + protected createFailedPredicateException(predicate?: string, message?: string): FailedPredicateException { + return new FailedPredicateException(this, predicate, message); + } + + constructor(input: TokenStream) { + super(input); + this._interp = new ParserATNSimulator(this, CELParser._ATN, CELParser.DecisionsToDFA, new PredictionContextCache()); + } + // @RuleVersion(0) + public start(): StartContext { + let localctx: StartContext = new StartContext(this, this._ctx, this.state); + this.enterRule(localctx, 0, CELParser.RULE_start); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 32; + localctx._e = this.expr(); + this.state = 33; + this.match(CELParser.EOF); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public expr(): ExprContext { + let localctx: ExprContext = new ExprContext(this, this._ctx, this.state); + this.enterRule(localctx, 2, CELParser.RULE_expr); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 35; + localctx._e = this.conditionalOr(); + this.state = 41; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la===20) { + { + this.state = 36; + localctx._op = this.match(CELParser.QUESTIONMARK); + this.state = 37; + localctx._e1 = this.conditionalOr(); + this.state = 38; + this.match(CELParser.COLON); + this.state = 39; + localctx._e2 = this.expr(); + } + } + + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public conditionalOr(): ConditionalOrContext { + let localctx: ConditionalOrContext = new ConditionalOrContext(this, this._ctx, this.state); + this.enterRule(localctx, 4, CELParser.RULE_conditionalOr); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 43; + localctx._e = this.conditionalAnd(); + this.state = 48; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===9) { + { + { + this.state = 44; + localctx._s9 = this.match(CELParser.LOGICAL_OR); + localctx._ops.push(localctx._s9); + this.state = 45; + localctx._conditionalAnd = this.conditionalAnd(); + localctx._e1.push(localctx._conditionalAnd); + } + } + this.state = 50; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public conditionalAnd(): ConditionalAndContext { + let localctx: ConditionalAndContext = new ConditionalAndContext(this, this._ctx, this.state); + this.enterRule(localctx, 6, CELParser.RULE_conditionalAnd); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 51; + localctx._e = this.relation(0); + this.state = 56; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===8) { + { + { + this.state = 52; + localctx._s8 = this.match(CELParser.LOGICAL_AND); + localctx._ops.push(localctx._s8); + this.state = 53; + localctx._relation = this.relation(0); + localctx._e1.push(localctx._relation); + } + } + this.state = 58; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + + public relation(): RelationContext; + public relation(_p: number): RelationContext; + // @RuleVersion(0) + public relation(_p?: number): RelationContext { + if (_p === undefined) { + _p = 0; + } + + let _parentctx: ParserRuleContext = this._ctx; + let _parentState: number = this.state; + let localctx: RelationContext = new RelationContext(this, this._ctx, _parentState); + let _prevctx: RelationContext = localctx; + let _startState: number = 8; + this.enterRecursionRule(localctx, 8, CELParser.RULE_relation, _p); + let _la: number; + try { + let _alt: number; + this.enterOuterAlt(localctx, 1); + { + { + this.state = 60; + this.calc(0); + } + this._ctx.stop = this._input.LT(-1); + this.state = 67; + this._errHandler.sync(this); + _alt = this._interp.adaptivePredict(this._input, 3, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + if (this._parseListeners != null) { + this.triggerExitRuleEvent(); + } + _prevctx = localctx; + { + { + localctx = new RelationContext(this, _parentctx, _parentState); + this.pushNewRecursionContext(localctx, _startState, CELParser.RULE_relation); + this.state = 62; + if (!(this.precpred(this._ctx, 1))) { + throw this.createFailedPredicateException("this.precpred(this._ctx, 1)"); + } + this.state = 63; + localctx._op = this._input.LT(1); + _la = this._input.LA(1); + if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 254) !== 0))) { + localctx._op = this._errHandler.recoverInline(this); + } + else { + this._errHandler.reportMatch(this); + this.consume(); + } + this.state = 64; + this.relation(2); + } + } + } + this.state = 69; + this._errHandler.sync(this); + _alt = this._interp.adaptivePredict(this._input, 3, this._ctx); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.unrollRecursionContexts(_parentctx); + } + return localctx; + } + + public calc(): CalcContext; + public calc(_p: number): CalcContext; + // @RuleVersion(0) + public calc(_p?: number): CalcContext { + if (_p === undefined) { + _p = 0; + } + + let _parentctx: ParserRuleContext = this._ctx; + let _parentState: number = this.state; + let localctx: CalcContext = new CalcContext(this, this._ctx, _parentState); + let _prevctx: CalcContext = localctx; + let _startState: number = 10; + this.enterRecursionRule(localctx, 10, CELParser.RULE_calc, _p); + let _la: number; + try { + let _alt: number; + this.enterOuterAlt(localctx, 1); + { + { + this.state = 71; + this.unary(); + } + this._ctx.stop = this._input.LT(-1); + this.state = 81; + this._errHandler.sync(this); + _alt = this._interp.adaptivePredict(this._input, 5, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + if (this._parseListeners != null) { + this.triggerExitRuleEvent(); + } + _prevctx = localctx; + { + this.state = 79; + this._errHandler.sync(this); + switch ( this._interp.adaptivePredict(this._input, 4, this._ctx) ) { + case 1: + { + localctx = new CalcContext(this, _parentctx, _parentState); + this.pushNewRecursionContext(localctx, _startState, CELParser.RULE_calc); + this.state = 73; + if (!(this.precpred(this._ctx, 2))) { + throw this.createFailedPredicateException("this.precpred(this._ctx, 2)"); + } + this.state = 74; + localctx._op = this._input.LT(1); + _la = this._input.LA(1); + if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 58720256) !== 0))) { + localctx._op = this._errHandler.recoverInline(this); + } + else { + this._errHandler.reportMatch(this); + this.consume(); + } + this.state = 75; + this.calc(3); + } + break; + case 2: + { + localctx = new CalcContext(this, _parentctx, _parentState); + this.pushNewRecursionContext(localctx, _startState, CELParser.RULE_calc); + this.state = 76; + if (!(this.precpred(this._ctx, 1))) { + throw this.createFailedPredicateException("this.precpred(this._ctx, 1)"); + } + this.state = 77; + localctx._op = this._input.LT(1); + _la = this._input.LA(1); + if(!(_la===18 || _la===22)) { + localctx._op = this._errHandler.recoverInline(this); + } + else { + this._errHandler.reportMatch(this); + this.consume(); + } + this.state = 78; + this.calc(2); + } + break; + } + } + } + this.state = 83; + this._errHandler.sync(this); + _alt = this._interp.adaptivePredict(this._input, 5, this._ctx); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.unrollRecursionContexts(_parentctx); + } + return localctx; + } + // @RuleVersion(0) + public unary(): UnaryContext { + let localctx: UnaryContext = new UnaryContext(this, this._ctx, this.state); + this.enterRule(localctx, 12, CELParser.RULE_unary); + let _la: number; + try { + let _alt: number; + this.state = 97; + this._errHandler.sync(this); + switch ( this._interp.adaptivePredict(this._input, 8, this._ctx) ) { + case 1: + localctx = new MemberExprContext(this, localctx); + this.enterOuterAlt(localctx, 1); + { + this.state = 84; + this.member(0); + } + break; + case 2: + localctx = new LogicalNotContext(this, localctx); + this.enterOuterAlt(localctx, 2); + { + this.state = 86; + this._errHandler.sync(this); + _la = this._input.LA(1); + do { + { + { + this.state = 85; + (localctx as LogicalNotContext)._s19 = this.match(CELParser.EXCLAM); + (localctx as LogicalNotContext)._ops.push((localctx as LogicalNotContext)._s19); + } + } + this.state = 88; + this._errHandler.sync(this); + _la = this._input.LA(1); + } while (_la===19); + this.state = 90; + this.member(0); + } + break; + case 3: + localctx = new NegateContext(this, localctx); + this.enterOuterAlt(localctx, 3); + { + this.state = 92; + this._errHandler.sync(this); + _alt = 1; + do { + switch (_alt) { + case 1: + { + { + this.state = 91; + (localctx as NegateContext)._s18 = this.match(CELParser.MINUS); + (localctx as NegateContext)._ops.push((localctx as NegateContext)._s18); + } + } + break; + default: + throw new NoViableAltException(this); + } + this.state = 94; + this._errHandler.sync(this); + _alt = this._interp.adaptivePredict(this._input, 7, this._ctx); + } while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER); + this.state = 96; + this.member(0); + } + break; + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + + public member(): MemberContext; + public member(_p: number): MemberContext; + // @RuleVersion(0) + public member(_p?: number): MemberContext { + if (_p === undefined) { + _p = 0; + } + + let _parentctx: ParserRuleContext = this._ctx; + let _parentState: number = this.state; + let localctx: MemberContext = new MemberContext(this, this._ctx, _parentState); + let _prevctx: MemberContext = localctx; + let _startState: number = 14; + this.enterRecursionRule(localctx, 14, CELParser.RULE_member, _p); + let _la: number; + try { + let _alt: number; + this.enterOuterAlt(localctx, 1); + { + { + localctx = new PrimaryExprContext(this, localctx); + this._ctx = localctx; + _prevctx = localctx; + + this.state = 100; + this.primary(); + } + this._ctx.stop = this._input.LT(-1); + this.state = 126; + this._errHandler.sync(this); + _alt = this._interp.adaptivePredict(this._input, 13, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + if (this._parseListeners != null) { + this.triggerExitRuleEvent(); + } + _prevctx = localctx; + { + this.state = 124; + this._errHandler.sync(this); + switch ( this._interp.adaptivePredict(this._input, 12, this._ctx) ) { + case 1: + { + localctx = new SelectContext(this, new MemberContext(this, _parentctx, _parentState)); + this.pushNewRecursionContext(localctx, _startState, CELParser.RULE_member); + this.state = 102; + if (!(this.precpred(this._ctx, 3))) { + throw this.createFailedPredicateException("this.precpred(this._ctx, 3)"); + } + this.state = 103; + (localctx as SelectContext)._op = this.match(CELParser.DOT); + this.state = 105; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la===20) { + { + this.state = 104; + (localctx as SelectContext)._opt = this.match(CELParser.QUESTIONMARK); + } + } + + this.state = 107; + (localctx as SelectContext)._id = this.match(CELParser.IDENTIFIER); + } + break; + case 2: + { + localctx = new MemberCallContext(this, new MemberContext(this, _parentctx, _parentState)); + this.pushNewRecursionContext(localctx, _startState, CELParser.RULE_member); + this.state = 108; + if (!(this.precpred(this._ctx, 2))) { + throw this.createFailedPredicateException("this.precpred(this._ctx, 2)"); + } + this.state = 109; + (localctx as MemberCallContext)._op = this.match(CELParser.DOT); + this.state = 110; + (localctx as MemberCallContext)._id = this.match(CELParser.IDENTIFIER); + this.state = 111; + (localctx as MemberCallContext)._open = this.match(CELParser.LPAREN); + this.state = 113; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (((((_la - 10)) & ~0x1F) === 0 && ((1 << (_la - 10)) & 132580181) !== 0)) { + { + this.state = 112; + (localctx as MemberCallContext)._args = this.exprList(); + } + } + + this.state = 115; + this.match(CELParser.RPAREN); + } + break; + case 3: + { + localctx = new IndexContext(this, new MemberContext(this, _parentctx, _parentState)); + this.pushNewRecursionContext(localctx, _startState, CELParser.RULE_member); + this.state = 116; + if (!(this.precpred(this._ctx, 1))) { + throw this.createFailedPredicateException("this.precpred(this._ctx, 1)"); + } + this.state = 117; + (localctx as IndexContext)._op = this.match(CELParser.LBRACKET); + this.state = 119; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la===20) { + { + this.state = 118; + (localctx as IndexContext)._opt = this.match(CELParser.QUESTIONMARK); + } + } + + this.state = 121; + (localctx as IndexContext)._index = this.expr(); + this.state = 122; + this.match(CELParser.RPRACKET); + } + break; + } + } + } + this.state = 128; + this._errHandler.sync(this); + _alt = this._interp.adaptivePredict(this._input, 13, this._ctx); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.unrollRecursionContexts(_parentctx); + } + return localctx; + } + // @RuleVersion(0) + public primary(): PrimaryContext { + let localctx: PrimaryContext = new PrimaryContext(this, this._ctx, this.state); + this.enterRule(localctx, 16, CELParser.RULE_primary); + let _la: number; + try { + this.state = 180; + this._errHandler.sync(this); + switch ( this._interp.adaptivePredict(this._input, 25, this._ctx) ) { + case 1: + localctx = new IdentOrGlobalCallContext(this, localctx); + this.enterOuterAlt(localctx, 1); + { + this.state = 130; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la===16) { + { + this.state = 129; + (localctx as IdentOrGlobalCallContext)._leadingDot = this.match(CELParser.DOT); + } + } + + this.state = 132; + (localctx as IdentOrGlobalCallContext)._id = this.match(CELParser.IDENTIFIER); + this.state = 138; + this._errHandler.sync(this); + switch ( this._interp.adaptivePredict(this._input, 16, this._ctx) ) { + case 1: + { + this.state = 133; + (localctx as IdentOrGlobalCallContext)._op = this.match(CELParser.LPAREN); + this.state = 135; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (((((_la - 10)) & ~0x1F) === 0 && ((1 << (_la - 10)) & 132580181) !== 0)) { + { + this.state = 134; + (localctx as IdentOrGlobalCallContext)._args = this.exprList(); + } + } + + this.state = 137; + this.match(CELParser.RPAREN); + } + break; + } + } + break; + case 2: + localctx = new NestedContext(this, localctx); + this.enterOuterAlt(localctx, 2); + { + this.state = 140; + this.match(CELParser.LPAREN); + this.state = 141; + (localctx as NestedContext)._e = this.expr(); + this.state = 142; + this.match(CELParser.RPAREN); + } + break; + case 3: + localctx = new CreateListContext(this, localctx); + this.enterOuterAlt(localctx, 3); + { + this.state = 144; + (localctx as CreateListContext)._op = this.match(CELParser.LBRACKET); + this.state = 146; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (((((_la - 10)) & ~0x1F) === 0 && ((1 << (_la - 10)) & 132581205) !== 0)) { + { + this.state = 145; + (localctx as CreateListContext)._elems = this.listInit(); + } + } + + this.state = 149; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la===17) { + { + this.state = 148; + this.match(CELParser.COMMA); + } + } + + this.state = 151; + this.match(CELParser.RPRACKET); + } + break; + case 4: + localctx = new CreateStructContext(this, localctx); + this.enterOuterAlt(localctx, 4); + { + this.state = 152; + (localctx as CreateStructContext)._op = this.match(CELParser.LBRACE); + this.state = 154; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (((((_la - 10)) & ~0x1F) === 0 && ((1 << (_la - 10)) & 132581205) !== 0)) { + { + this.state = 153; + (localctx as CreateStructContext)._entries = this.mapInitializerList(); + } + } + + this.state = 157; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la===17) { + { + this.state = 156; + this.match(CELParser.COMMA); + } + } + + this.state = 159; + this.match(CELParser.RBRACE); + } + break; + case 5: + localctx = new CreateMessageContext(this, localctx); + this.enterOuterAlt(localctx, 5); + { + this.state = 161; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la===16) { + { + this.state = 160; + (localctx as CreateMessageContext)._leadingDot = this.match(CELParser.DOT); + } + } + + this.state = 163; + (localctx as CreateMessageContext)._IDENTIFIER = this.match(CELParser.IDENTIFIER); + (localctx as CreateMessageContext)._ids.push((localctx as CreateMessageContext)._IDENTIFIER); + this.state = 168; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===16) { + { + { + this.state = 164; + (localctx as CreateMessageContext)._s16 = this.match(CELParser.DOT); + (localctx as CreateMessageContext)._ops.push((localctx as CreateMessageContext)._s16); + this.state = 165; + (localctx as CreateMessageContext)._IDENTIFIER = this.match(CELParser.IDENTIFIER); + (localctx as CreateMessageContext)._ids.push((localctx as CreateMessageContext)._IDENTIFIER); + } + } + this.state = 170; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 171; + (localctx as CreateMessageContext)._op = this.match(CELParser.LBRACE); + this.state = 173; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la===20 || _la===36) { + { + this.state = 172; + (localctx as CreateMessageContext)._entries = this.fieldInitializerList(); + } + } + + this.state = 176; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la===17) { + { + this.state = 175; + this.match(CELParser.COMMA); + } + } + + this.state = 178; + this.match(CELParser.RBRACE); + } + break; + case 6: + localctx = new ConstantLiteralContext(this, localctx); + this.enterOuterAlt(localctx, 6); + { + this.state = 179; + this.literal(); + } + break; + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public exprList(): ExprListContext { + let localctx: ExprListContext = new ExprListContext(this, this._ctx, this.state); + this.enterRule(localctx, 18, CELParser.RULE_exprList); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 182; + localctx._expr = this.expr(); + localctx._e.push(localctx._expr); + this.state = 187; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===17) { + { + { + this.state = 183; + this.match(CELParser.COMMA); + this.state = 184; + localctx._expr = this.expr(); + localctx._e.push(localctx._expr); + } + } + this.state = 189; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public listInit(): ListInitContext { + let localctx: ListInitContext = new ListInitContext(this, this._ctx, this.state); + this.enterRule(localctx, 20, CELParser.RULE_listInit); + try { + let _alt: number; + this.enterOuterAlt(localctx, 1); + { + this.state = 190; + localctx._optExpr = this.optExpr(); + localctx._elems.push(localctx._optExpr); + this.state = 195; + this._errHandler.sync(this); + _alt = this._interp.adaptivePredict(this._input, 27, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 191; + this.match(CELParser.COMMA); + this.state = 192; + localctx._optExpr = this.optExpr(); + localctx._elems.push(localctx._optExpr); + } + } + } + this.state = 197; + this._errHandler.sync(this); + _alt = this._interp.adaptivePredict(this._input, 27, this._ctx); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public fieldInitializerList(): FieldInitializerListContext { + let localctx: FieldInitializerListContext = new FieldInitializerListContext(this, this._ctx, this.state); + this.enterRule(localctx, 22, CELParser.RULE_fieldInitializerList); + try { + let _alt: number; + this.enterOuterAlt(localctx, 1); + { + this.state = 198; + localctx._optField = this.optField(); + localctx._fields.push(localctx._optField); + this.state = 199; + localctx._s21 = this.match(CELParser.COLON); + localctx._cols.push(localctx._s21); + this.state = 200; + localctx._expr = this.expr(); + localctx._values.push(localctx._expr); + this.state = 208; + this._errHandler.sync(this); + _alt = this._interp.adaptivePredict(this._input, 28, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 201; + this.match(CELParser.COMMA); + this.state = 202; + localctx._optField = this.optField(); + localctx._fields.push(localctx._optField); + this.state = 203; + localctx._s21 = this.match(CELParser.COLON); + localctx._cols.push(localctx._s21); + this.state = 204; + localctx._expr = this.expr(); + localctx._values.push(localctx._expr); + } + } + } + this.state = 210; + this._errHandler.sync(this); + _alt = this._interp.adaptivePredict(this._input, 28, this._ctx); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public optField(): OptFieldContext { + let localctx: OptFieldContext = new OptFieldContext(this, this._ctx, this.state); + this.enterRule(localctx, 24, CELParser.RULE_optField); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 212; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la===20) { + { + this.state = 211; + localctx._opt = this.match(CELParser.QUESTIONMARK); + } + } + + this.state = 214; + this.match(CELParser.IDENTIFIER); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public mapInitializerList(): MapInitializerListContext { + let localctx: MapInitializerListContext = new MapInitializerListContext(this, this._ctx, this.state); + this.enterRule(localctx, 26, CELParser.RULE_mapInitializerList); + try { + let _alt: number; + this.enterOuterAlt(localctx, 1); + { + this.state = 216; + localctx._optExpr = this.optExpr(); + localctx._keys.push(localctx._optExpr); + this.state = 217; + localctx._s21 = this.match(CELParser.COLON); + localctx._cols.push(localctx._s21); + this.state = 218; + localctx._expr = this.expr(); + localctx._values.push(localctx._expr); + this.state = 226; + this._errHandler.sync(this); + _alt = this._interp.adaptivePredict(this._input, 30, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 219; + this.match(CELParser.COMMA); + this.state = 220; + localctx._optExpr = this.optExpr(); + localctx._keys.push(localctx._optExpr); + this.state = 221; + localctx._s21 = this.match(CELParser.COLON); + localctx._cols.push(localctx._s21); + this.state = 222; + localctx._expr = this.expr(); + localctx._values.push(localctx._expr); + } + } + } + this.state = 228; + this._errHandler.sync(this); + _alt = this._interp.adaptivePredict(this._input, 30, this._ctx); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public optExpr(): OptExprContext { + let localctx: OptExprContext = new OptExprContext(this, this._ctx, this.state); + this.enterRule(localctx, 28, CELParser.RULE_optExpr); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 230; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la===20) { + { + this.state = 229; + localctx._opt = this.match(CELParser.QUESTIONMARK); + } + } + + this.state = 232; + localctx._e = this.expr(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public literal(): LiteralContext { + let localctx: LiteralContext = new LiteralContext(this, this._ctx, this.state); + this.enterRule(localctx, 30, CELParser.RULE_literal); + let _la: number; + try { + this.state = 248; + this._errHandler.sync(this); + switch ( this._interp.adaptivePredict(this._input, 34, this._ctx) ) { + case 1: + localctx = new IntContext(this, localctx); + this.enterOuterAlt(localctx, 1); + { + this.state = 235; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la===18) { + { + this.state = 234; + (localctx as IntContext)._sign = this.match(CELParser.MINUS); + } + } + + this.state = 237; + (localctx as IntContext)._tok = this.match(CELParser.NUM_INT); + } + break; + case 2: + localctx = new UintContext(this, localctx); + this.enterOuterAlt(localctx, 2); + { + this.state = 238; + (localctx as UintContext)._tok = this.match(CELParser.NUM_UINT); + } + break; + case 3: + localctx = new DoubleContext(this, localctx); + this.enterOuterAlt(localctx, 3); + { + this.state = 240; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la===18) { + { + this.state = 239; + (localctx as DoubleContext)._sign = this.match(CELParser.MINUS); + } + } + + this.state = 242; + (localctx as DoubleContext)._tok = this.match(CELParser.NUM_FLOAT); + } + break; + case 4: + localctx = new StringContext(this, localctx); + this.enterOuterAlt(localctx, 4); + { + this.state = 243; + (localctx as StringContext)._tok = this.match(CELParser.STRING); + } + break; + case 5: + localctx = new BytesContext(this, localctx); + this.enterOuterAlt(localctx, 5); + { + this.state = 244; + (localctx as BytesContext)._tok = this.match(CELParser.BYTES); + } + break; + case 6: + localctx = new BoolTrueContext(this, localctx); + this.enterOuterAlt(localctx, 6); + { + this.state = 245; + (localctx as BoolTrueContext)._tok = this.match(CELParser.CEL_TRUE); + } + break; + case 7: + localctx = new BoolFalseContext(this, localctx); + this.enterOuterAlt(localctx, 7); + { + this.state = 246; + (localctx as BoolFalseContext)._tok = this.match(CELParser.CEL_FALSE); + } + break; + case 8: + localctx = new NullContext(this, localctx); + this.enterOuterAlt(localctx, 8); + { + this.state = 247; + (localctx as NullContext)._tok = this.match(CELParser.NUL); + } + break; + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + + public sempred(localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { + switch (ruleIndex) { + case 4: + return this.relation_sempred(localctx as RelationContext, predIndex); + case 5: + return this.calc_sempred(localctx as CalcContext, predIndex); + case 7: + return this.member_sempred(localctx as MemberContext, predIndex); + } + return true; + } + private relation_sempred(localctx: RelationContext, predIndex: number): boolean { + switch (predIndex) { + case 0: + return this.precpred(this._ctx, 1); + } + return true; + } + private calc_sempred(localctx: CalcContext, predIndex: number): boolean { + switch (predIndex) { + case 1: + return this.precpred(this._ctx, 2); + case 2: + return this.precpred(this._ctx, 1); + } + return true; + } + private member_sempred(localctx: MemberContext, predIndex: number): boolean { + switch (predIndex) { + case 3: + return this.precpred(this._ctx, 3); + case 4: + return this.precpred(this._ctx, 2); + case 5: + return this.precpred(this._ctx, 1); + } + return true; + } + + public static readonly _serializedATN: number[] = [4,1,36,251,2,0,7,0,2, + 1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,6,2,7,7,7,2,8,7,8,2,9,7,9,2, + 10,7,10,2,11,7,11,2,12,7,12,2,13,7,13,2,14,7,14,2,15,7,15,1,0,1,0,1,0,1, + 1,1,1,1,1,1,1,1,1,1,1,3,1,42,8,1,1,2,1,2,1,2,5,2,47,8,2,10,2,12,2,50,9, + 2,1,3,1,3,1,3,5,3,55,8,3,10,3,12,3,58,9,3,1,4,1,4,1,4,1,4,1,4,1,4,5,4,66, + 8,4,10,4,12,4,69,9,4,1,5,1,5,1,5,1,5,1,5,1,5,1,5,1,5,1,5,5,5,80,8,5,10, + 5,12,5,83,9,5,1,6,1,6,4,6,87,8,6,11,6,12,6,88,1,6,1,6,4,6,93,8,6,11,6,12, + 6,94,1,6,3,6,98,8,6,1,7,1,7,1,7,1,7,1,7,1,7,3,7,106,8,7,1,7,1,7,1,7,1,7, + 1,7,1,7,3,7,114,8,7,1,7,1,7,1,7,1,7,3,7,120,8,7,1,7,1,7,1,7,5,7,125,8,7, + 10,7,12,7,128,9,7,1,8,3,8,131,8,8,1,8,1,8,1,8,3,8,136,8,8,1,8,3,8,139,8, + 8,1,8,1,8,1,8,1,8,1,8,1,8,3,8,147,8,8,1,8,3,8,150,8,8,1,8,1,8,1,8,3,8,155, + 8,8,1,8,3,8,158,8,8,1,8,1,8,3,8,162,8,8,1,8,1,8,1,8,5,8,167,8,8,10,8,12, + 8,170,9,8,1,8,1,8,3,8,174,8,8,1,8,3,8,177,8,8,1,8,1,8,3,8,181,8,8,1,9,1, + 9,1,9,5,9,186,8,9,10,9,12,9,189,9,9,1,10,1,10,1,10,5,10,194,8,10,10,10, + 12,10,197,9,10,1,11,1,11,1,11,1,11,1,11,1,11,1,11,1,11,5,11,207,8,11,10, + 11,12,11,210,9,11,1,12,3,12,213,8,12,1,12,1,12,1,13,1,13,1,13,1,13,1,13, + 1,13,1,13,1,13,5,13,225,8,13,10,13,12,13,228,9,13,1,14,3,14,231,8,14,1, + 14,1,14,1,15,3,15,236,8,15,1,15,1,15,1,15,3,15,241,8,15,1,15,1,15,1,15, + 1,15,1,15,1,15,3,15,249,8,15,1,15,0,3,8,10,14,16,0,2,4,6,8,10,12,14,16, + 18,20,22,24,26,28,30,0,3,1,0,1,7,1,0,23,25,2,0,18,18,22,22,281,0,32,1,0, + 0,0,2,35,1,0,0,0,4,43,1,0,0,0,6,51,1,0,0,0,8,59,1,0,0,0,10,70,1,0,0,0,12, + 97,1,0,0,0,14,99,1,0,0,0,16,180,1,0,0,0,18,182,1,0,0,0,20,190,1,0,0,0,22, + 198,1,0,0,0,24,212,1,0,0,0,26,216,1,0,0,0,28,230,1,0,0,0,30,248,1,0,0,0, + 32,33,3,2,1,0,33,34,5,0,0,1,34,1,1,0,0,0,35,41,3,4,2,0,36,37,5,20,0,0,37, + 38,3,4,2,0,38,39,5,21,0,0,39,40,3,2,1,0,40,42,1,0,0,0,41,36,1,0,0,0,41, + 42,1,0,0,0,42,3,1,0,0,0,43,48,3,6,3,0,44,45,5,9,0,0,45,47,3,6,3,0,46,44, + 1,0,0,0,47,50,1,0,0,0,48,46,1,0,0,0,48,49,1,0,0,0,49,5,1,0,0,0,50,48,1, + 0,0,0,51,56,3,8,4,0,52,53,5,8,0,0,53,55,3,8,4,0,54,52,1,0,0,0,55,58,1,0, + 0,0,56,54,1,0,0,0,56,57,1,0,0,0,57,7,1,0,0,0,58,56,1,0,0,0,59,60,6,4,-1, + 0,60,61,3,10,5,0,61,67,1,0,0,0,62,63,10,1,0,0,63,64,7,0,0,0,64,66,3,8,4, + 2,65,62,1,0,0,0,66,69,1,0,0,0,67,65,1,0,0,0,67,68,1,0,0,0,68,9,1,0,0,0, + 69,67,1,0,0,0,70,71,6,5,-1,0,71,72,3,12,6,0,72,81,1,0,0,0,73,74,10,2,0, + 0,74,75,7,1,0,0,75,80,3,10,5,3,76,77,10,1,0,0,77,78,7,2,0,0,78,80,3,10, + 5,2,79,73,1,0,0,0,79,76,1,0,0,0,80,83,1,0,0,0,81,79,1,0,0,0,81,82,1,0,0, + 0,82,11,1,0,0,0,83,81,1,0,0,0,84,98,3,14,7,0,85,87,5,19,0,0,86,85,1,0,0, + 0,87,88,1,0,0,0,88,86,1,0,0,0,88,89,1,0,0,0,89,90,1,0,0,0,90,98,3,14,7, + 0,91,93,5,18,0,0,92,91,1,0,0,0,93,94,1,0,0,0,94,92,1,0,0,0,94,95,1,0,0, + 0,95,96,1,0,0,0,96,98,3,14,7,0,97,84,1,0,0,0,97,86,1,0,0,0,97,92,1,0,0, + 0,98,13,1,0,0,0,99,100,6,7,-1,0,100,101,3,16,8,0,101,126,1,0,0,0,102,103, + 10,3,0,0,103,105,5,16,0,0,104,106,5,20,0,0,105,104,1,0,0,0,105,106,1,0, + 0,0,106,107,1,0,0,0,107,125,5,36,0,0,108,109,10,2,0,0,109,110,5,16,0,0, + 110,111,5,36,0,0,111,113,5,14,0,0,112,114,3,18,9,0,113,112,1,0,0,0,113, + 114,1,0,0,0,114,115,1,0,0,0,115,125,5,15,0,0,116,117,10,1,0,0,117,119,5, + 10,0,0,118,120,5,20,0,0,119,118,1,0,0,0,119,120,1,0,0,0,120,121,1,0,0,0, + 121,122,3,2,1,0,122,123,5,11,0,0,123,125,1,0,0,0,124,102,1,0,0,0,124,108, + 1,0,0,0,124,116,1,0,0,0,125,128,1,0,0,0,126,124,1,0,0,0,126,127,1,0,0,0, + 127,15,1,0,0,0,128,126,1,0,0,0,129,131,5,16,0,0,130,129,1,0,0,0,130,131, + 1,0,0,0,131,132,1,0,0,0,132,138,5,36,0,0,133,135,5,14,0,0,134,136,3,18, + 9,0,135,134,1,0,0,0,135,136,1,0,0,0,136,137,1,0,0,0,137,139,5,15,0,0,138, + 133,1,0,0,0,138,139,1,0,0,0,139,181,1,0,0,0,140,141,5,14,0,0,141,142,3, + 2,1,0,142,143,5,15,0,0,143,181,1,0,0,0,144,146,5,10,0,0,145,147,3,20,10, + 0,146,145,1,0,0,0,146,147,1,0,0,0,147,149,1,0,0,0,148,150,5,17,0,0,149, + 148,1,0,0,0,149,150,1,0,0,0,150,151,1,0,0,0,151,181,5,11,0,0,152,154,5, + 12,0,0,153,155,3,26,13,0,154,153,1,0,0,0,154,155,1,0,0,0,155,157,1,0,0, + 0,156,158,5,17,0,0,157,156,1,0,0,0,157,158,1,0,0,0,158,159,1,0,0,0,159, + 181,5,13,0,0,160,162,5,16,0,0,161,160,1,0,0,0,161,162,1,0,0,0,162,163,1, + 0,0,0,163,168,5,36,0,0,164,165,5,16,0,0,165,167,5,36,0,0,166,164,1,0,0, + 0,167,170,1,0,0,0,168,166,1,0,0,0,168,169,1,0,0,0,169,171,1,0,0,0,170,168, + 1,0,0,0,171,173,5,12,0,0,172,174,3,22,11,0,173,172,1,0,0,0,173,174,1,0, + 0,0,174,176,1,0,0,0,175,177,5,17,0,0,176,175,1,0,0,0,176,177,1,0,0,0,177, + 178,1,0,0,0,178,181,5,13,0,0,179,181,3,30,15,0,180,130,1,0,0,0,180,140, + 1,0,0,0,180,144,1,0,0,0,180,152,1,0,0,0,180,161,1,0,0,0,180,179,1,0,0,0, + 181,17,1,0,0,0,182,187,3,2,1,0,183,184,5,17,0,0,184,186,3,2,1,0,185,183, + 1,0,0,0,186,189,1,0,0,0,187,185,1,0,0,0,187,188,1,0,0,0,188,19,1,0,0,0, + 189,187,1,0,0,0,190,195,3,28,14,0,191,192,5,17,0,0,192,194,3,28,14,0,193, + 191,1,0,0,0,194,197,1,0,0,0,195,193,1,0,0,0,195,196,1,0,0,0,196,21,1,0, + 0,0,197,195,1,0,0,0,198,199,3,24,12,0,199,200,5,21,0,0,200,208,3,2,1,0, + 201,202,5,17,0,0,202,203,3,24,12,0,203,204,5,21,0,0,204,205,3,2,1,0,205, + 207,1,0,0,0,206,201,1,0,0,0,207,210,1,0,0,0,208,206,1,0,0,0,208,209,1,0, + 0,0,209,23,1,0,0,0,210,208,1,0,0,0,211,213,5,20,0,0,212,211,1,0,0,0,212, + 213,1,0,0,0,213,214,1,0,0,0,214,215,5,36,0,0,215,25,1,0,0,0,216,217,3,28, + 14,0,217,218,5,21,0,0,218,226,3,2,1,0,219,220,5,17,0,0,220,221,3,28,14, + 0,221,222,5,21,0,0,222,223,3,2,1,0,223,225,1,0,0,0,224,219,1,0,0,0,225, + 228,1,0,0,0,226,224,1,0,0,0,226,227,1,0,0,0,227,27,1,0,0,0,228,226,1,0, + 0,0,229,231,5,20,0,0,230,229,1,0,0,0,230,231,1,0,0,0,231,232,1,0,0,0,232, + 233,3,2,1,0,233,29,1,0,0,0,234,236,5,18,0,0,235,234,1,0,0,0,235,236,1,0, + 0,0,236,237,1,0,0,0,237,249,5,32,0,0,238,249,5,33,0,0,239,241,5,18,0,0, + 240,239,1,0,0,0,240,241,1,0,0,0,241,242,1,0,0,0,242,249,5,31,0,0,243,249, + 5,34,0,0,244,249,5,35,0,0,245,249,5,26,0,0,246,249,5,27,0,0,247,249,5,28, + 0,0,248,235,1,0,0,0,248,238,1,0,0,0,248,240,1,0,0,0,248,243,1,0,0,0,248, + 244,1,0,0,0,248,245,1,0,0,0,248,246,1,0,0,0,248,247,1,0,0,0,249,31,1,0, + 0,0,35,41,48,56,67,79,81,88,94,97,105,113,119,124,126,130,135,138,146,149, + 154,157,161,168,173,176,180,187,195,208,212,226,230,235,240,248]; + + private static __ATN: ATN; + public static get _ATN(): ATN { + if (!CELParser.__ATN) { + CELParser.__ATN = new ATNDeserializer().deserialize(CELParser._serializedATN); + } + + return CELParser.__ATN; + } + + + static DecisionsToDFA = CELParser._ATN.decisionToState.map( (ds: DecisionState, index: number) => new DFA(ds, index) ); + +} + +export class StartContext extends ParserRuleContext { + public _e!: ExprContext; + constructor(parser?: CELParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public EOF(): TerminalNode { + return this.getToken(CELParser.EOF, 0); + } + public expr(): ExprContext { + return this.getTypedRuleContext(ExprContext, 0) as ExprContext; + } + public get ruleIndex(): number { + return CELParser.RULE_start; + } + public enterRule(listener: CELListener): void { + if(listener.enterStart) { + listener.enterStart(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitStart) { + listener.exitStart(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitStart) { + return visitor.visitStart(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ExprContext extends ParserRuleContext { + public _e!: ConditionalOrContext; + public _op!: Token; + public _e1!: ConditionalOrContext; + public _e2!: ExprContext; + constructor(parser?: CELParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public conditionalOr_list(): ConditionalOrContext[] { + return this.getTypedRuleContexts(ConditionalOrContext) as ConditionalOrContext[]; + } + public conditionalOr(i: number): ConditionalOrContext { + return this.getTypedRuleContext(ConditionalOrContext, i) as ConditionalOrContext; + } + public COLON(): TerminalNode { + return this.getToken(CELParser.COLON, 0); + } + public QUESTIONMARK(): TerminalNode { + return this.getToken(CELParser.QUESTIONMARK, 0); + } + public expr(): ExprContext { + return this.getTypedRuleContext(ExprContext, 0) as ExprContext; + } + public get ruleIndex(): number { + return CELParser.RULE_expr; + } + public enterRule(listener: CELListener): void { + if(listener.enterExpr) { + listener.enterExpr(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitExpr) { + listener.exitExpr(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitExpr) { + return visitor.visitExpr(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ConditionalOrContext extends ParserRuleContext { + public _e!: ConditionalAndContext; + public _s9!: Token; + public _ops: Token[] = []; + public _conditionalAnd!: ConditionalAndContext; + public _e1: ConditionalAndContext[] = []; + constructor(parser?: CELParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public conditionalAnd_list(): ConditionalAndContext[] { + return this.getTypedRuleContexts(ConditionalAndContext) as ConditionalAndContext[]; + } + public conditionalAnd(i: number): ConditionalAndContext { + return this.getTypedRuleContext(ConditionalAndContext, i) as ConditionalAndContext; + } + public LOGICAL_OR_list(): TerminalNode[] { + return this.getTokens(CELParser.LOGICAL_OR); + } + public LOGICAL_OR(i: number): TerminalNode { + return this.getToken(CELParser.LOGICAL_OR, i); + } + public get ruleIndex(): number { + return CELParser.RULE_conditionalOr; + } + public enterRule(listener: CELListener): void { + if(listener.enterConditionalOr) { + listener.enterConditionalOr(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitConditionalOr) { + listener.exitConditionalOr(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitConditionalOr) { + return visitor.visitConditionalOr(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ConditionalAndContext extends ParserRuleContext { + public _e!: RelationContext; + public _s8!: Token; + public _ops: Token[] = []; + public _relation!: RelationContext; + public _e1: RelationContext[] = []; + constructor(parser?: CELParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public relation_list(): RelationContext[] { + return this.getTypedRuleContexts(RelationContext) as RelationContext[]; + } + public relation(i: number): RelationContext { + return this.getTypedRuleContext(RelationContext, i) as RelationContext; + } + public LOGICAL_AND_list(): TerminalNode[] { + return this.getTokens(CELParser.LOGICAL_AND); + } + public LOGICAL_AND(i: number): TerminalNode { + return this.getToken(CELParser.LOGICAL_AND, i); + } + public get ruleIndex(): number { + return CELParser.RULE_conditionalAnd; + } + public enterRule(listener: CELListener): void { + if(listener.enterConditionalAnd) { + listener.enterConditionalAnd(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitConditionalAnd) { + listener.exitConditionalAnd(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitConditionalAnd) { + return visitor.visitConditionalAnd(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class RelationContext extends ParserRuleContext { + public _op!: Token; + constructor(parser?: CELParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public calc(): CalcContext { + return this.getTypedRuleContext(CalcContext, 0) as CalcContext; + } + public relation_list(): RelationContext[] { + return this.getTypedRuleContexts(RelationContext) as RelationContext[]; + } + public relation(i: number): RelationContext { + return this.getTypedRuleContext(RelationContext, i) as RelationContext; + } + public LESS(): TerminalNode { + return this.getToken(CELParser.LESS, 0); + } + public LESS_EQUALS(): TerminalNode { + return this.getToken(CELParser.LESS_EQUALS, 0); + } + public GREATER_EQUALS(): TerminalNode { + return this.getToken(CELParser.GREATER_EQUALS, 0); + } + public GREATER(): TerminalNode { + return this.getToken(CELParser.GREATER, 0); + } + public EQUALS(): TerminalNode { + return this.getToken(CELParser.EQUALS, 0); + } + public NOT_EQUALS(): TerminalNode { + return this.getToken(CELParser.NOT_EQUALS, 0); + } + public IN(): TerminalNode { + return this.getToken(CELParser.IN, 0); + } + public get ruleIndex(): number { + return CELParser.RULE_relation; + } + public enterRule(listener: CELListener): void { + if(listener.enterRelation) { + listener.enterRelation(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitRelation) { + listener.exitRelation(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitRelation) { + return visitor.visitRelation(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class CalcContext extends ParserRuleContext { + public _op!: Token; + constructor(parser?: CELParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public unary(): UnaryContext { + return this.getTypedRuleContext(UnaryContext, 0) as UnaryContext; + } + public calc_list(): CalcContext[] { + return this.getTypedRuleContexts(CalcContext) as CalcContext[]; + } + public calc(i: number): CalcContext { + return this.getTypedRuleContext(CalcContext, i) as CalcContext; + } + public STAR(): TerminalNode { + return this.getToken(CELParser.STAR, 0); + } + public SLASH(): TerminalNode { + return this.getToken(CELParser.SLASH, 0); + } + public PERCENT(): TerminalNode { + return this.getToken(CELParser.PERCENT, 0); + } + public PLUS(): TerminalNode { + return this.getToken(CELParser.PLUS, 0); + } + public MINUS(): TerminalNode { + return this.getToken(CELParser.MINUS, 0); + } + public get ruleIndex(): number { + return CELParser.RULE_calc; + } + public enterRule(listener: CELListener): void { + if(listener.enterCalc) { + listener.enterCalc(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitCalc) { + listener.exitCalc(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitCalc) { + return visitor.visitCalc(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class UnaryContext extends ParserRuleContext { + constructor(parser?: CELParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public get ruleIndex(): number { + return CELParser.RULE_unary; + } + public copyFrom(ctx: UnaryContext): void { + super.copyFrom(ctx); + } +} +export class LogicalNotContext extends UnaryContext { + public _s19!: Token; + public _ops: Token[] = []; + constructor(parser: CELParser, ctx: UnaryContext) { + super(parser, ctx.parentCtx, ctx.invokingState); + super.copyFrom(ctx); + } + public member(): MemberContext { + return this.getTypedRuleContext(MemberContext, 0) as MemberContext; + } + public EXCLAM_list(): TerminalNode[] { + return this.getTokens(CELParser.EXCLAM); + } + public EXCLAM(i: number): TerminalNode { + return this.getToken(CELParser.EXCLAM, i); + } + public enterRule(listener: CELListener): void { + if(listener.enterLogicalNot) { + listener.enterLogicalNot(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitLogicalNot) { + listener.exitLogicalNot(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitLogicalNot) { + return visitor.visitLogicalNot(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class MemberExprContext extends UnaryContext { + constructor(parser: CELParser, ctx: UnaryContext) { + super(parser, ctx.parentCtx, ctx.invokingState); + super.copyFrom(ctx); + } + public member(): MemberContext { + return this.getTypedRuleContext(MemberContext, 0) as MemberContext; + } + public enterRule(listener: CELListener): void { + if(listener.enterMemberExpr) { + listener.enterMemberExpr(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitMemberExpr) { + listener.exitMemberExpr(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitMemberExpr) { + return visitor.visitMemberExpr(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class NegateContext extends UnaryContext { + public _s18!: Token; + public _ops: Token[] = []; + constructor(parser: CELParser, ctx: UnaryContext) { + super(parser, ctx.parentCtx, ctx.invokingState); + super.copyFrom(ctx); + } + public member(): MemberContext { + return this.getTypedRuleContext(MemberContext, 0) as MemberContext; + } + public MINUS_list(): TerminalNode[] { + return this.getTokens(CELParser.MINUS); + } + public MINUS(i: number): TerminalNode { + return this.getToken(CELParser.MINUS, i); + } + public enterRule(listener: CELListener): void { + if(listener.enterNegate) { + listener.enterNegate(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitNegate) { + listener.exitNegate(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitNegate) { + return visitor.visitNegate(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class MemberContext extends ParserRuleContext { + constructor(parser?: CELParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public get ruleIndex(): number { + return CELParser.RULE_member; + } + public copyFrom(ctx: MemberContext): void { + super.copyFrom(ctx); + } +} +export class MemberCallContext extends MemberContext { + public _op!: Token; + public _id!: Token; + public _open!: Token; + public _args!: ExprListContext; + constructor(parser: CELParser, ctx: MemberContext) { + super(parser, ctx.parentCtx, ctx.invokingState); + super.copyFrom(ctx); + } + public member(): MemberContext { + return this.getTypedRuleContext(MemberContext, 0) as MemberContext; + } + public RPAREN(): TerminalNode { + return this.getToken(CELParser.RPAREN, 0); + } + public DOT(): TerminalNode { + return this.getToken(CELParser.DOT, 0); + } + public IDENTIFIER(): TerminalNode { + return this.getToken(CELParser.IDENTIFIER, 0); + } + public LPAREN(): TerminalNode { + return this.getToken(CELParser.LPAREN, 0); + } + public exprList(): ExprListContext { + return this.getTypedRuleContext(ExprListContext, 0) as ExprListContext; + } + public enterRule(listener: CELListener): void { + if(listener.enterMemberCall) { + listener.enterMemberCall(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitMemberCall) { + listener.exitMemberCall(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitMemberCall) { + return visitor.visitMemberCall(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class SelectContext extends MemberContext { + public _op!: Token; + public _opt!: Token; + public _id!: Token; + constructor(parser: CELParser, ctx: MemberContext) { + super(parser, ctx.parentCtx, ctx.invokingState); + super.copyFrom(ctx); + } + public member(): MemberContext { + return this.getTypedRuleContext(MemberContext, 0) as MemberContext; + } + public DOT(): TerminalNode { + return this.getToken(CELParser.DOT, 0); + } + public IDENTIFIER(): TerminalNode { + return this.getToken(CELParser.IDENTIFIER, 0); + } + public QUESTIONMARK(): TerminalNode { + return this.getToken(CELParser.QUESTIONMARK, 0); + } + public enterRule(listener: CELListener): void { + if(listener.enterSelect) { + listener.enterSelect(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitSelect) { + listener.exitSelect(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitSelect) { + return visitor.visitSelect(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class PrimaryExprContext extends MemberContext { + constructor(parser: CELParser, ctx: MemberContext) { + super(parser, ctx.parentCtx, ctx.invokingState); + super.copyFrom(ctx); + } + public primary(): PrimaryContext { + return this.getTypedRuleContext(PrimaryContext, 0) as PrimaryContext; + } + public enterRule(listener: CELListener): void { + if(listener.enterPrimaryExpr) { + listener.enterPrimaryExpr(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitPrimaryExpr) { + listener.exitPrimaryExpr(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitPrimaryExpr) { + return visitor.visitPrimaryExpr(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class IndexContext extends MemberContext { + public _op!: Token; + public _opt!: Token; + public _index!: ExprContext; + constructor(parser: CELParser, ctx: MemberContext) { + super(parser, ctx.parentCtx, ctx.invokingState); + super.copyFrom(ctx); + } + public member(): MemberContext { + return this.getTypedRuleContext(MemberContext, 0) as MemberContext; + } + public RPRACKET(): TerminalNode { + return this.getToken(CELParser.RPRACKET, 0); + } + public LBRACKET(): TerminalNode { + return this.getToken(CELParser.LBRACKET, 0); + } + public expr(): ExprContext { + return this.getTypedRuleContext(ExprContext, 0) as ExprContext; + } + public QUESTIONMARK(): TerminalNode { + return this.getToken(CELParser.QUESTIONMARK, 0); + } + public enterRule(listener: CELListener): void { + if(listener.enterIndex) { + listener.enterIndex(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitIndex) { + listener.exitIndex(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitIndex) { + return visitor.visitIndex(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class PrimaryContext extends ParserRuleContext { + constructor(parser?: CELParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public get ruleIndex(): number { + return CELParser.RULE_primary; + } + public copyFrom(ctx: PrimaryContext): void { + super.copyFrom(ctx); + } +} +export class CreateListContext extends PrimaryContext { + public _op!: Token; + public _elems!: ListInitContext; + constructor(parser: CELParser, ctx: PrimaryContext) { + super(parser, ctx.parentCtx, ctx.invokingState); + super.copyFrom(ctx); + } + public RPRACKET(): TerminalNode { + return this.getToken(CELParser.RPRACKET, 0); + } + public LBRACKET(): TerminalNode { + return this.getToken(CELParser.LBRACKET, 0); + } + public COMMA(): TerminalNode { + return this.getToken(CELParser.COMMA, 0); + } + public listInit(): ListInitContext { + return this.getTypedRuleContext(ListInitContext, 0) as ListInitContext; + } + public enterRule(listener: CELListener): void { + if(listener.enterCreateList) { + listener.enterCreateList(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitCreateList) { + listener.exitCreateList(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitCreateList) { + return visitor.visitCreateList(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class CreateStructContext extends PrimaryContext { + public _op!: Token; + public _entries!: MapInitializerListContext; + constructor(parser: CELParser, ctx: PrimaryContext) { + super(parser, ctx.parentCtx, ctx.invokingState); + super.copyFrom(ctx); + } + public RBRACE(): TerminalNode { + return this.getToken(CELParser.RBRACE, 0); + } + public LBRACE(): TerminalNode { + return this.getToken(CELParser.LBRACE, 0); + } + public COMMA(): TerminalNode { + return this.getToken(CELParser.COMMA, 0); + } + public mapInitializerList(): MapInitializerListContext { + return this.getTypedRuleContext(MapInitializerListContext, 0) as MapInitializerListContext; + } + public enterRule(listener: CELListener): void { + if(listener.enterCreateStruct) { + listener.enterCreateStruct(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitCreateStruct) { + listener.exitCreateStruct(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitCreateStruct) { + return visitor.visitCreateStruct(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class ConstantLiteralContext extends PrimaryContext { + constructor(parser: CELParser, ctx: PrimaryContext) { + super(parser, ctx.parentCtx, ctx.invokingState); + super.copyFrom(ctx); + } + public literal(): LiteralContext { + return this.getTypedRuleContext(LiteralContext, 0) as LiteralContext; + } + public enterRule(listener: CELListener): void { + if(listener.enterConstantLiteral) { + listener.enterConstantLiteral(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitConstantLiteral) { + listener.exitConstantLiteral(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitConstantLiteral) { + return visitor.visitConstantLiteral(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class NestedContext extends PrimaryContext { + public _e!: ExprContext; + constructor(parser: CELParser, ctx: PrimaryContext) { + super(parser, ctx.parentCtx, ctx.invokingState); + super.copyFrom(ctx); + } + public LPAREN(): TerminalNode { + return this.getToken(CELParser.LPAREN, 0); + } + public RPAREN(): TerminalNode { + return this.getToken(CELParser.RPAREN, 0); + } + public expr(): ExprContext { + return this.getTypedRuleContext(ExprContext, 0) as ExprContext; + } + public enterRule(listener: CELListener): void { + if(listener.enterNested) { + listener.enterNested(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitNested) { + listener.exitNested(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitNested) { + return visitor.visitNested(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class CreateMessageContext extends PrimaryContext { + public _leadingDot!: Token; + public _IDENTIFIER!: Token; + public _ids: Token[] = []; + public _s16!: Token; + public _ops: Token[] = []; + public _op!: Token; + public _entries!: FieldInitializerListContext; + constructor(parser: CELParser, ctx: PrimaryContext) { + super(parser, ctx.parentCtx, ctx.invokingState); + super.copyFrom(ctx); + } + public RBRACE(): TerminalNode { + return this.getToken(CELParser.RBRACE, 0); + } + public IDENTIFIER_list(): TerminalNode[] { + return this.getTokens(CELParser.IDENTIFIER); + } + public IDENTIFIER(i: number): TerminalNode { + return this.getToken(CELParser.IDENTIFIER, i); + } + public LBRACE(): TerminalNode { + return this.getToken(CELParser.LBRACE, 0); + } + public COMMA(): TerminalNode { + return this.getToken(CELParser.COMMA, 0); + } + public DOT_list(): TerminalNode[] { + return this.getTokens(CELParser.DOT); + } + public DOT(i: number): TerminalNode { + return this.getToken(CELParser.DOT, i); + } + public fieldInitializerList(): FieldInitializerListContext { + return this.getTypedRuleContext(FieldInitializerListContext, 0) as FieldInitializerListContext; + } + public enterRule(listener: CELListener): void { + if(listener.enterCreateMessage) { + listener.enterCreateMessage(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitCreateMessage) { + listener.exitCreateMessage(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitCreateMessage) { + return visitor.visitCreateMessage(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class IdentOrGlobalCallContext extends PrimaryContext { + public _leadingDot!: Token; + public _id!: Token; + public _op!: Token; + public _args!: ExprListContext; + constructor(parser: CELParser, ctx: PrimaryContext) { + super(parser, ctx.parentCtx, ctx.invokingState); + super.copyFrom(ctx); + } + public IDENTIFIER(): TerminalNode { + return this.getToken(CELParser.IDENTIFIER, 0); + } + public RPAREN(): TerminalNode { + return this.getToken(CELParser.RPAREN, 0); + } + public DOT(): TerminalNode { + return this.getToken(CELParser.DOT, 0); + } + public LPAREN(): TerminalNode { + return this.getToken(CELParser.LPAREN, 0); + } + public exprList(): ExprListContext { + return this.getTypedRuleContext(ExprListContext, 0) as ExprListContext; + } + public enterRule(listener: CELListener): void { + if(listener.enterIdentOrGlobalCall) { + listener.enterIdentOrGlobalCall(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitIdentOrGlobalCall) { + listener.exitIdentOrGlobalCall(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitIdentOrGlobalCall) { + return visitor.visitIdentOrGlobalCall(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ExprListContext extends ParserRuleContext { + public _expr!: ExprContext; + public _e: ExprContext[] = []; + constructor(parser?: CELParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public expr_list(): ExprContext[] { + return this.getTypedRuleContexts(ExprContext) as ExprContext[]; + } + public expr(i: number): ExprContext { + return this.getTypedRuleContext(ExprContext, i) as ExprContext; + } + public COMMA_list(): TerminalNode[] { + return this.getTokens(CELParser.COMMA); + } + public COMMA(i: number): TerminalNode { + return this.getToken(CELParser.COMMA, i); + } + public get ruleIndex(): number { + return CELParser.RULE_exprList; + } + public enterRule(listener: CELListener): void { + if(listener.enterExprList) { + listener.enterExprList(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitExprList) { + listener.exitExprList(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitExprList) { + return visitor.visitExprList(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ListInitContext extends ParserRuleContext { + public _optExpr!: OptExprContext; + public _elems: OptExprContext[] = []; + constructor(parser?: CELParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public optExpr_list(): OptExprContext[] { + return this.getTypedRuleContexts(OptExprContext) as OptExprContext[]; + } + public optExpr(i: number): OptExprContext { + return this.getTypedRuleContext(OptExprContext, i) as OptExprContext; + } + public COMMA_list(): TerminalNode[] { + return this.getTokens(CELParser.COMMA); + } + public COMMA(i: number): TerminalNode { + return this.getToken(CELParser.COMMA, i); + } + public get ruleIndex(): number { + return CELParser.RULE_listInit; + } + public enterRule(listener: CELListener): void { + if(listener.enterListInit) { + listener.enterListInit(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitListInit) { + listener.exitListInit(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitListInit) { + return visitor.visitListInit(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class FieldInitializerListContext extends ParserRuleContext { + public _optField!: OptFieldContext; + public _fields: OptFieldContext[] = []; + public _s21!: Token; + public _cols: Token[] = []; + public _expr!: ExprContext; + public _values: ExprContext[] = []; + constructor(parser?: CELParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public optField_list(): OptFieldContext[] { + return this.getTypedRuleContexts(OptFieldContext) as OptFieldContext[]; + } + public optField(i: number): OptFieldContext { + return this.getTypedRuleContext(OptFieldContext, i) as OptFieldContext; + } + public COLON_list(): TerminalNode[] { + return this.getTokens(CELParser.COLON); + } + public COLON(i: number): TerminalNode { + return this.getToken(CELParser.COLON, i); + } + public expr_list(): ExprContext[] { + return this.getTypedRuleContexts(ExprContext) as ExprContext[]; + } + public expr(i: number): ExprContext { + return this.getTypedRuleContext(ExprContext, i) as ExprContext; + } + public COMMA_list(): TerminalNode[] { + return this.getTokens(CELParser.COMMA); + } + public COMMA(i: number): TerminalNode { + return this.getToken(CELParser.COMMA, i); + } + public get ruleIndex(): number { + return CELParser.RULE_fieldInitializerList; + } + public enterRule(listener: CELListener): void { + if(listener.enterFieldInitializerList) { + listener.enterFieldInitializerList(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitFieldInitializerList) { + listener.exitFieldInitializerList(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitFieldInitializerList) { + return visitor.visitFieldInitializerList(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class OptFieldContext extends ParserRuleContext { + public _opt!: Token; + constructor(parser?: CELParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public IDENTIFIER(): TerminalNode { + return this.getToken(CELParser.IDENTIFIER, 0); + } + public QUESTIONMARK(): TerminalNode { + return this.getToken(CELParser.QUESTIONMARK, 0); + } + public get ruleIndex(): number { + return CELParser.RULE_optField; + } + public enterRule(listener: CELListener): void { + if(listener.enterOptField) { + listener.enterOptField(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitOptField) { + listener.exitOptField(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitOptField) { + return visitor.visitOptField(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class MapInitializerListContext extends ParserRuleContext { + public _optExpr!: OptExprContext; + public _keys: OptExprContext[] = []; + public _s21!: Token; + public _cols: Token[] = []; + public _expr!: ExprContext; + public _values: ExprContext[] = []; + constructor(parser?: CELParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public optExpr_list(): OptExprContext[] { + return this.getTypedRuleContexts(OptExprContext) as OptExprContext[]; + } + public optExpr(i: number): OptExprContext { + return this.getTypedRuleContext(OptExprContext, i) as OptExprContext; + } + public COLON_list(): TerminalNode[] { + return this.getTokens(CELParser.COLON); + } + public COLON(i: number): TerminalNode { + return this.getToken(CELParser.COLON, i); + } + public expr_list(): ExprContext[] { + return this.getTypedRuleContexts(ExprContext) as ExprContext[]; + } + public expr(i: number): ExprContext { + return this.getTypedRuleContext(ExprContext, i) as ExprContext; + } + public COMMA_list(): TerminalNode[] { + return this.getTokens(CELParser.COMMA); + } + public COMMA(i: number): TerminalNode { + return this.getToken(CELParser.COMMA, i); + } + public get ruleIndex(): number { + return CELParser.RULE_mapInitializerList; + } + public enterRule(listener: CELListener): void { + if(listener.enterMapInitializerList) { + listener.enterMapInitializerList(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitMapInitializerList) { + listener.exitMapInitializerList(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitMapInitializerList) { + return visitor.visitMapInitializerList(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class OptExprContext extends ParserRuleContext { + public _opt!: Token; + public _e!: ExprContext; + constructor(parser?: CELParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public expr(): ExprContext { + return this.getTypedRuleContext(ExprContext, 0) as ExprContext; + } + public QUESTIONMARK(): TerminalNode { + return this.getToken(CELParser.QUESTIONMARK, 0); + } + public get ruleIndex(): number { + return CELParser.RULE_optExpr; + } + public enterRule(listener: CELListener): void { + if(listener.enterOptExpr) { + listener.enterOptExpr(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitOptExpr) { + listener.exitOptExpr(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitOptExpr) { + return visitor.visitOptExpr(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class LiteralContext extends ParserRuleContext { + constructor(parser?: CELParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public get ruleIndex(): number { + return CELParser.RULE_literal; + } + public copyFrom(ctx: LiteralContext): void { + super.copyFrom(ctx); + } +} +export class BytesContext extends LiteralContext { + public _tok!: Token; + constructor(parser: CELParser, ctx: LiteralContext) { + super(parser, ctx.parentCtx, ctx.invokingState); + super.copyFrom(ctx); + } + public BYTES(): TerminalNode { + return this.getToken(CELParser.BYTES, 0); + } + public enterRule(listener: CELListener): void { + if(listener.enterBytes) { + listener.enterBytes(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitBytes) { + listener.exitBytes(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitBytes) { + return visitor.visitBytes(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class UintContext extends LiteralContext { + public _tok!: Token; + constructor(parser: CELParser, ctx: LiteralContext) { + super(parser, ctx.parentCtx, ctx.invokingState); + super.copyFrom(ctx); + } + public NUM_UINT(): TerminalNode { + return this.getToken(CELParser.NUM_UINT, 0); + } + public enterRule(listener: CELListener): void { + if(listener.enterUint) { + listener.enterUint(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitUint) { + listener.exitUint(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitUint) { + return visitor.visitUint(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class NullContext extends LiteralContext { + public _tok!: Token; + constructor(parser: CELParser, ctx: LiteralContext) { + super(parser, ctx.parentCtx, ctx.invokingState); + super.copyFrom(ctx); + } + public NUL(): TerminalNode { + return this.getToken(CELParser.NUL, 0); + } + public enterRule(listener: CELListener): void { + if(listener.enterNull) { + listener.enterNull(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitNull) { + listener.exitNull(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitNull) { + return visitor.visitNull(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class BoolFalseContext extends LiteralContext { + public _tok!: Token; + constructor(parser: CELParser, ctx: LiteralContext) { + super(parser, ctx.parentCtx, ctx.invokingState); + super.copyFrom(ctx); + } + public CEL_FALSE(): TerminalNode { + return this.getToken(CELParser.CEL_FALSE, 0); + } + public enterRule(listener: CELListener): void { + if(listener.enterBoolFalse) { + listener.enterBoolFalse(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitBoolFalse) { + listener.exitBoolFalse(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitBoolFalse) { + return visitor.visitBoolFalse(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class StringContext extends LiteralContext { + public _tok!: Token; + constructor(parser: CELParser, ctx: LiteralContext) { + super(parser, ctx.parentCtx, ctx.invokingState); + super.copyFrom(ctx); + } + public STRING(): TerminalNode { + return this.getToken(CELParser.STRING, 0); + } + public enterRule(listener: CELListener): void { + if(listener.enterString) { + listener.enterString(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitString) { + listener.exitString(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitString) { + return visitor.visitString(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class DoubleContext extends LiteralContext { + public _sign!: Token; + public _tok!: Token; + constructor(parser: CELParser, ctx: LiteralContext) { + super(parser, ctx.parentCtx, ctx.invokingState); + super.copyFrom(ctx); + } + public NUM_FLOAT(): TerminalNode { + return this.getToken(CELParser.NUM_FLOAT, 0); + } + public MINUS(): TerminalNode { + return this.getToken(CELParser.MINUS, 0); + } + public enterRule(listener: CELListener): void { + if(listener.enterDouble) { + listener.enterDouble(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitDouble) { + listener.exitDouble(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitDouble) { + return visitor.visitDouble(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class BoolTrueContext extends LiteralContext { + public _tok!: Token; + constructor(parser: CELParser, ctx: LiteralContext) { + super(parser, ctx.parentCtx, ctx.invokingState); + super.copyFrom(ctx); + } + public CEL_TRUE(): TerminalNode { + return this.getToken(CELParser.CEL_TRUE, 0); + } + public enterRule(listener: CELListener): void { + if(listener.enterBoolTrue) { + listener.enterBoolTrue(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitBoolTrue) { + listener.exitBoolTrue(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitBoolTrue) { + return visitor.visitBoolTrue(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class IntContext extends LiteralContext { + public _sign!: Token; + public _tok!: Token; + constructor(parser: CELParser, ctx: LiteralContext) { + super(parser, ctx.parentCtx, ctx.invokingState); + super.copyFrom(ctx); + } + public NUM_INT(): TerminalNode { + return this.getToken(CELParser.NUM_INT, 0); + } + public MINUS(): TerminalNode { + return this.getToken(CELParser.MINUS, 0); + } + public enterRule(listener: CELListener): void { + if(listener.enterInt) { + listener.enterInt(this); + } + } + public exitRule(listener: CELListener): void { + if(listener.exitInt) { + listener.exitInt(this); + } + } + // @Override + public accept(visitor: CELVisitor): Result { + if (visitor.visitInt) { + return visitor.visitInt(this); + } else { + return visitor.visitChildren(this); + } + } +} diff --git a/packages/cel/src/lib/gen/CELVisitor.ts b/packages/cel/src/lib/gen/CELVisitor.ts new file mode 100644 index 0000000..04090db --- /dev/null +++ b/packages/cel/src/lib/gen/CELVisitor.ts @@ -0,0 +1,269 @@ +// Generated from packages/cel/src/lib/gen/CEL.g4 by ANTLR 4.13.1 + +import {ParseTreeVisitor} from 'antlr4'; + + +import { StartContext } from "./CELParser"; +import { ExprContext } from "./CELParser"; +import { ConditionalOrContext } from "./CELParser"; +import { ConditionalAndContext } from "./CELParser"; +import { RelationContext } from "./CELParser"; +import { CalcContext } from "./CELParser"; +import { MemberExprContext } from "./CELParser"; +import { LogicalNotContext } from "./CELParser"; +import { NegateContext } from "./CELParser"; +import { MemberCallContext } from "./CELParser"; +import { SelectContext } from "./CELParser"; +import { PrimaryExprContext } from "./CELParser"; +import { IndexContext } from "./CELParser"; +import { IdentOrGlobalCallContext } from "./CELParser"; +import { NestedContext } from "./CELParser"; +import { CreateListContext } from "./CELParser"; +import { CreateStructContext } from "./CELParser"; +import { CreateMessageContext } from "./CELParser"; +import { ConstantLiteralContext } from "./CELParser"; +import { ExprListContext } from "./CELParser"; +import { ListInitContext } from "./CELParser"; +import { FieldInitializerListContext } from "./CELParser"; +import { OptFieldContext } from "./CELParser"; +import { MapInitializerListContext } from "./CELParser"; +import { OptExprContext } from "./CELParser"; +import { IntContext } from "./CELParser"; +import { UintContext } from "./CELParser"; +import { DoubleContext } from "./CELParser"; +import { StringContext } from "./CELParser"; +import { BytesContext } from "./CELParser"; +import { BoolTrueContext } from "./CELParser"; +import { BoolFalseContext } from "./CELParser"; +import { NullContext } from "./CELParser"; + + +/** + * This interface defines a complete generic visitor for a parse tree produced + * by `CELParser`. + * + * @param The return type of the visit operation. Use `void` for + * operations with no return type. + */ +export default class CELVisitor extends ParseTreeVisitor { + /** + * Visit a parse tree produced by `CELParser.start`. + * @param ctx the parse tree + * @return the visitor result + */ + visitStart?: (ctx: StartContext) => Result; + /** + * Visit a parse tree produced by `CELParser.expr`. + * @param ctx the parse tree + * @return the visitor result + */ + visitExpr?: (ctx: ExprContext) => Result; + /** + * Visit a parse tree produced by `CELParser.conditionalOr`. + * @param ctx the parse tree + * @return the visitor result + */ + visitConditionalOr?: (ctx: ConditionalOrContext) => Result; + /** + * Visit a parse tree produced by `CELParser.conditionalAnd`. + * @param ctx the parse tree + * @return the visitor result + */ + visitConditionalAnd?: (ctx: ConditionalAndContext) => Result; + /** + * Visit a parse tree produced by `CELParser.relation`. + * @param ctx the parse tree + * @return the visitor result + */ + visitRelation?: (ctx: RelationContext) => Result; + /** + * Visit a parse tree produced by `CELParser.calc`. + * @param ctx the parse tree + * @return the visitor result + */ + visitCalc?: (ctx: CalcContext) => Result; + /** + * Visit a parse tree produced by the `MemberExpr` + * labeled alternative in `CELParser.unary`. + * @param ctx the parse tree + * @return the visitor result + */ + visitMemberExpr?: (ctx: MemberExprContext) => Result; + /** + * Visit a parse tree produced by the `LogicalNot` + * labeled alternative in `CELParser.unary`. + * @param ctx the parse tree + * @return the visitor result + */ + visitLogicalNot?: (ctx: LogicalNotContext) => Result; + /** + * Visit a parse tree produced by the `Negate` + * labeled alternative in `CELParser.unary`. + * @param ctx the parse tree + * @return the visitor result + */ + visitNegate?: (ctx: NegateContext) => Result; + /** + * Visit a parse tree produced by the `MemberCall` + * labeled alternative in `CELParser.member`. + * @param ctx the parse tree + * @return the visitor result + */ + visitMemberCall?: (ctx: MemberCallContext) => Result; + /** + * Visit a parse tree produced by the `Select` + * labeled alternative in `CELParser.member`. + * @param ctx the parse tree + * @return the visitor result + */ + visitSelect?: (ctx: SelectContext) => Result; + /** + * Visit a parse tree produced by the `PrimaryExpr` + * labeled alternative in `CELParser.member`. + * @param ctx the parse tree + * @return the visitor result + */ + visitPrimaryExpr?: (ctx: PrimaryExprContext) => Result; + /** + * Visit a parse tree produced by the `Index` + * labeled alternative in `CELParser.member`. + * @param ctx the parse tree + * @return the visitor result + */ + visitIndex?: (ctx: IndexContext) => Result; + /** + * Visit a parse tree produced by the `IdentOrGlobalCall` + * labeled alternative in `CELParser.primary`. + * @param ctx the parse tree + * @return the visitor result + */ + visitIdentOrGlobalCall?: (ctx: IdentOrGlobalCallContext) => Result; + /** + * Visit a parse tree produced by the `Nested` + * labeled alternative in `CELParser.primary`. + * @param ctx the parse tree + * @return the visitor result + */ + visitNested?: (ctx: NestedContext) => Result; + /** + * Visit a parse tree produced by the `CreateList` + * labeled alternative in `CELParser.primary`. + * @param ctx the parse tree + * @return the visitor result + */ + visitCreateList?: (ctx: CreateListContext) => Result; + /** + * Visit a parse tree produced by the `CreateStruct` + * labeled alternative in `CELParser.primary`. + * @param ctx the parse tree + * @return the visitor result + */ + visitCreateStruct?: (ctx: CreateStructContext) => Result; + /** + * Visit a parse tree produced by the `CreateMessage` + * labeled alternative in `CELParser.primary`. + * @param ctx the parse tree + * @return the visitor result + */ + visitCreateMessage?: (ctx: CreateMessageContext) => Result; + /** + * Visit a parse tree produced by the `ConstantLiteral` + * labeled alternative in `CELParser.primary`. + * @param ctx the parse tree + * @return the visitor result + */ + visitConstantLiteral?: (ctx: ConstantLiteralContext) => Result; + /** + * Visit a parse tree produced by `CELParser.exprList`. + * @param ctx the parse tree + * @return the visitor result + */ + visitExprList?: (ctx: ExprListContext) => Result; + /** + * Visit a parse tree produced by `CELParser.listInit`. + * @param ctx the parse tree + * @return the visitor result + */ + visitListInit?: (ctx: ListInitContext) => Result; + /** + * Visit a parse tree produced by `CELParser.fieldInitializerList`. + * @param ctx the parse tree + * @return the visitor result + */ + visitFieldInitializerList?: (ctx: FieldInitializerListContext) => Result; + /** + * Visit a parse tree produced by `CELParser.optField`. + * @param ctx the parse tree + * @return the visitor result + */ + visitOptField?: (ctx: OptFieldContext) => Result; + /** + * Visit a parse tree produced by `CELParser.mapInitializerList`. + * @param ctx the parse tree + * @return the visitor result + */ + visitMapInitializerList?: (ctx: MapInitializerListContext) => Result; + /** + * Visit a parse tree produced by `CELParser.optExpr`. + * @param ctx the parse tree + * @return the visitor result + */ + visitOptExpr?: (ctx: OptExprContext) => Result; + /** + * Visit a parse tree produced by the `Int` + * labeled alternative in `CELParser.literal`. + * @param ctx the parse tree + * @return the visitor result + */ + visitInt?: (ctx: IntContext) => Result; + /** + * Visit a parse tree produced by the `Uint` + * labeled alternative in `CELParser.literal`. + * @param ctx the parse tree + * @return the visitor result + */ + visitUint?: (ctx: UintContext) => Result; + /** + * Visit a parse tree produced by the `Double` + * labeled alternative in `CELParser.literal`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDouble?: (ctx: DoubleContext) => Result; + /** + * Visit a parse tree produced by the `String` + * labeled alternative in `CELParser.literal`. + * @param ctx the parse tree + * @return the visitor result + */ + visitString?: (ctx: StringContext) => Result; + /** + * Visit a parse tree produced by the `Bytes` + * labeled alternative in `CELParser.literal`. + * @param ctx the parse tree + * @return the visitor result + */ + visitBytes?: (ctx: BytesContext) => Result; + /** + * Visit a parse tree produced by the `BoolTrue` + * labeled alternative in `CELParser.literal`. + * @param ctx the parse tree + * @return the visitor result + */ + visitBoolTrue?: (ctx: BoolTrueContext) => Result; + /** + * Visit a parse tree produced by the `BoolFalse` + * labeled alternative in `CELParser.literal`. + * @param ctx the parse tree + * @return the visitor result + */ + visitBoolFalse?: (ctx: BoolFalseContext) => Result; + /** + * Visit a parse tree produced by the `Null` + * labeled alternative in `CELParser.literal`. + * @param ctx the parse tree + * @return the visitor result + */ + visitNull?: (ctx: NullContext) => Result; +} + diff --git a/packages/cel/src/lib/logic-manager.ts b/packages/cel/src/lib/logic-manager.ts new file mode 100644 index 0000000..9531d64 --- /dev/null +++ b/packages/cel/src/lib/logic-manager.ts @@ -0,0 +1,83 @@ +import { + Expr, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { create } from '@bufbuild/protobuf'; + +export class LogicManager { + private function: string; + private terms: Expr[]; + private ops: bigint[]; + private variadicASTs: boolean; + + private constructor(functionName: string, term: Expr, variadicASTs: boolean) { + this.function = functionName; + this.terms = [term]; + this.ops = []; + this.variadicASTs = variadicASTs; + } + + static newVariadicLogicManager( + functionName: string, + term: Expr + ): LogicManager { + return new LogicManager(functionName, term, true); + } + + static newBalancingLogicManager( + functionName: string, + term: Expr + ): LogicManager { + return new LogicManager(functionName, term, false); + } + + addTerm(op: bigint, term: Expr): void { + this.terms.push(term); + this.ops.push(op); + } + + toExpr(): Expr { + if (this.terms.length === 1) { + return this.terms[0]; + } + if (this.variadicASTs) { + return create(ExprSchema, { + id: this.ops[0], + exprKind: { + case: 'callExpr', + value: { + function: this.function, + args: this.terms, + }, + }, + }); + } + return this.balancedTree(0, this.ops.length - 1); + } + + private balancedTree(lo: number, hi: number): Expr { + const mid = Math.floor((lo + hi + 1) / 2); + let left: Expr; + if (mid === lo) { + left = this.terms[mid]; + } else { + left = this.balancedTree(lo, mid - 1); + } + let right: Expr; + if (mid === hi) { + right = this.terms[mid + 1]; + } else { + right = this.balancedTree(mid + 1, hi); + } + return create(ExprSchema, { + id: this.ops[mid], + exprKind: { + case: 'callExpr', + value: { + function: this.function, + args: [left, right], + }, + }, + }); + } +} diff --git a/packages/cel/src/lib/macros.ts b/packages/cel/src/lib/macros.ts new file mode 100644 index 0000000..e622dd4 --- /dev/null +++ b/packages/cel/src/lib/macros.ts @@ -0,0 +1,257 @@ +import { isNil } from '@bearclaw/is'; +import { + Expr, + ExprSchema, + Expr_SelectSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { ACCUMULATOR_VAR } from './constants'; +import { + ADD_OPERATOR, + ALL_MACRO, + CONDITIONAL_OPERATOR, + EQUALS_OPERATOR, + EXISTS_MACRO, + EXISTS_ONE_MACRO, + FILTER_MACRO, + HAS_MACRO, + LOGICAL_AND_OPERATOR, + LOGICAL_NOT_OPERATOR, + LOGICAL_OR_OPERATOR, + MAP_MACRO, + NOT_STRICTLY_FALSE_OPERATOR, +} from './operators'; +import { boolExpr, globalCall, identExpr, int64Expr, listExpr } from './utils'; + +export const STANDARD_MACROS = new Set([ + HAS_MACRO, + ALL_MACRO, + EXISTS_MACRO, + EXISTS_ONE_MACRO, + MAP_MACRO, + // MAP_FILTER_MACRO, // TODO: Implement this + FILTER_MACRO, +]); + +export function findMacro(name: string) { + return STANDARD_MACROS.has(name) ? name : undefined; +} + +export function expandMacro(op: string, target: Expr, args: Expr[]): Expr { + switch (op) { + case HAS_MACRO: + return expandHasMacro(target, args); + case ALL_MACRO: + return expandAllMacro(target, args); + case EXISTS_MACRO: + return expandExistsMacro(target, args); + case EXISTS_ONE_MACRO: + return expandExistsOneMacro(target, args); + case MAP_MACRO: + return expandMapMacro(target, args); + case FILTER_MACRO: + return expandFilterMacro(target, args); + default: + throw new Error(`Unknown macro: ${op}`); + } +} + +export function expandHasMacro(target: Expr, args: Expr[]): Expr { + const arg = args[0]; + if (arg.exprKind.case !== 'selectExpr') { + throw new Error('Invalid argument to has() macro'); + } + return create(ExprSchema, { + exprKind: { + case: 'selectExpr', + value: create(Expr_SelectSchema, { + operand: arg.exprKind.value.operand, + field: arg.exprKind.value.field, + testOnly: true, + }), + }, + }); +} + +export function expandAllMacro(target: Expr, args: Expr[]): Expr { + const arg0 = args[0]; + if (arg0.exprKind.case !== 'identExpr') { + throw new Error('Invalid argument to all() macro'); + } + const arg1 = args[1]; + const accuInit = boolExpr(true); + const condition = globalCall( + NOT_STRICTLY_FALSE_OPERATOR, + identExpr(ACCUMULATOR_VAR) + ); + const step = globalCall( + LOGICAL_AND_OPERATOR, + identExpr(ACCUMULATOR_VAR), + arg1 + ); + const result = identExpr(ACCUMULATOR_VAR); + return fold( + arg0.exprKind.value.name, + target, + ACCUMULATOR_VAR, + accuInit, + condition, + step, + result + ); +} + +export function expandExistsMacro(target: Expr, args: Expr[]): Expr { + const arg0 = args[0]; + if (arg0.exprKind.case !== 'identExpr') { + throw new Error('Invalid argument to all() macro'); + } + const arg1 = args[1]; + const accuInit = boolExpr(false); + const condition = globalCall( + NOT_STRICTLY_FALSE_OPERATOR, + globalCall(LOGICAL_NOT_OPERATOR, identExpr(ACCUMULATOR_VAR)) + ); + const step = globalCall( + LOGICAL_OR_OPERATOR, + identExpr(ACCUMULATOR_VAR), + arg1 + ); + const result = identExpr(ACCUMULATOR_VAR); + return fold( + arg0.exprKind.value.name, + target, + ACCUMULATOR_VAR, + accuInit, + condition, + step, + result + ); +} + +export function expandExistsOneMacro(target: Expr, args: Expr[]): Expr { + const arg0 = args[0]; + if (arg0.exprKind.case !== 'identExpr') { + throw new Error('Invalid argument to all() macro'); + } + const arg1 = args[1]; + const zeroExpr = int64Expr(BigInt(0)); + const oneExpr = int64Expr(BigInt(1)); + const accuInit = zeroExpr; + const condition = boolExpr(true); + const step = globalCall( + CONDITIONAL_OPERATOR, + arg1, + globalCall(ADD_OPERATOR, identExpr(ACCUMULATOR_VAR), oneExpr), + identExpr(ACCUMULATOR_VAR) + ); + const result = globalCall( + EQUALS_OPERATOR, + identExpr(ACCUMULATOR_VAR), + oneExpr + ); + return fold( + arg0.exprKind.value.name, + target, + ACCUMULATOR_VAR, + accuInit, + condition, + step, + result + ); +} + +export function expandMapMacro(target: Expr, args: Expr[]): Expr { + const arg0 = args[0]; + if (arg0.exprKind.case !== 'identExpr') { + throw new Error('Invalid argument to map() macro'); + } + let arg1: Expr; + let arg2: Expr; + if (args.length === 3) { + arg2 = args[1]; + arg1 = args[2]; + } else { + arg1 = args[1]; + arg2 = null as unknown as Expr; + } + const accuInit = listExpr([]); + const condition = boolExpr(true); + let step = globalCall( + ADD_OPERATOR, + identExpr(ACCUMULATOR_VAR), + listExpr([arg1]) + ); + if (!isNil(arg2)) { + step = globalCall( + CONDITIONAL_OPERATOR, + arg2, + step, + identExpr(ACCUMULATOR_VAR) + ); + } + return fold( + arg0.exprKind.value.name, + target, + ACCUMULATOR_VAR, + accuInit, + condition, + step, + identExpr(ACCUMULATOR_VAR) + ); +} + +export function expandFilterMacro(target: Expr, args: Expr[]): Expr { + const arg0 = args[0]; + if (arg0.exprKind.case !== 'identExpr') { + throw new Error('Invalid argument to filter() macro'); + } + const arg1 = args[1]; + const accuInit = listExpr([]); + const condition = boolExpr(true); + let step = globalCall( + ADD_OPERATOR, + identExpr(ACCUMULATOR_VAR), + listExpr([arg0]) + ); + step = globalCall( + CONDITIONAL_OPERATOR, + arg1, + step, + identExpr(ACCUMULATOR_VAR) + ); + return fold( + arg0.exprKind.value.name, + target, + ACCUMULATOR_VAR, + accuInit, + condition, + step, + identExpr(ACCUMULATOR_VAR) + ); +} + +function fold( + iterVar: string, + iterRange: Expr, + accuVar: string, + accuInit: Expr, + condition: Expr, + step: Expr, + result: Expr +): Expr { + return create(ExprSchema, { + exprKind: { + case: 'comprehensionExpr', + value: { + iterVar, + iterRange, + accuVar, + accuInit, + loopCondition: condition, + loopStep: step, + result, + }, + }, + }); +} diff --git a/packages/cel/src/lib/operators.ts b/packages/cel/src/lib/operators.ts new file mode 100644 index 0000000..7dae755 --- /dev/null +++ b/packages/cel/src/lib/operators.ts @@ -0,0 +1,91 @@ +// Symbolic operators. +export const CONDITIONAL_OPERATOR = '_?_:_'; +export const LOGICAL_AND_OPERATOR = '_&&_'; +export const LOGICAL_OR_OPERATOR = '_||_'; +export const LOGICAL_NOT_OPERATOR = '!_'; +export const EQUALS_OPERATOR = '_==_'; +export const NOT_EQUALS_OPERATOR = '_!=_'; +export const LESS_OPERATOR = '_<_'; +export const LESS_EQUALS_OPERATOR = '_<=_'; +export const GREATER_OPERATOR = '_>_'; +export const GREATER_EQUALS_OPERATOR = '_>=_'; +export const ADD_OPERATOR = '_+_'; +export const SUBTRACT_OPERATOR = '_-_'; +export const MULTIPLY_OPERATOR = '_*_'; +export const DIVIDE_OPERATOR = '_/_'; +export const MODULO_OPERATOR = '_%_'; +export const NEGATE_OPERATOR = '-_'; +export const INDEX_OPERATOR = '_[_]'; +export const OPT_INDEX_OPERATOR = '_[?_]'; +export const OPT_SELECT_OPERATOR = '_?._'; + +// Macros, must have a valid identifier. +export const HAS_MACRO = 'has'; +export const ALL_MACRO = 'all'; +export const EXISTS_MACRO = 'exists'; +export const EXISTS_ONE_MACRO = 'exists_one'; +export const MAP_MACRO = 'map'; +export const FILTER_MACRO = 'filter'; + +// Named operators, must not have be valid identifiers. +export const NOT_STRICTLY_FALSE_OPERATOR = '@not_strictly_false'; +export const IN_OPERATOR = '@in'; + +export function getOperatorFromText(text: string): string | undefined { + switch (text) { + case '?': + return CONDITIONAL_OPERATOR; + case '&&': + return LOGICAL_AND_OPERATOR; + case '||': + return LOGICAL_OR_OPERATOR; + case '!': + return LOGICAL_NOT_OPERATOR; + case '==': + return EQUALS_OPERATOR; + case '!=': + return NOT_EQUALS_OPERATOR; + case '<': + return LESS_OPERATOR; + case '<=': + return LESS_EQUALS_OPERATOR; + case '>': + return GREATER_OPERATOR; + case '>=': + return GREATER_EQUALS_OPERATOR; + case '+': + return ADD_OPERATOR; + case '-': + return SUBTRACT_OPERATOR; + case '*': + return MULTIPLY_OPERATOR; + case '/': + return DIVIDE_OPERATOR; + case '%': + return MODULO_OPERATOR; + case '[': + return INDEX_OPERATOR; + case 'has': + return HAS_MACRO; + case 'all': + return ALL_MACRO; + case 'exists': + return EXISTS_MACRO; + case 'exists_one': + return EXISTS_ONE_MACRO; + case 'map': + return MAP_MACRO; + case 'filter': + return FILTER_MACRO; + case '@not_strictly_false': + return NOT_STRICTLY_FALSE_OPERATOR; + case 'in': + return IN_OPERATOR; + case '[?': + return OPT_INDEX_OPERATOR; + case '?.': + return OPT_SELECT_OPERATOR; + default: + return undefined; + } +} diff --git a/packages/cel/src/lib/program.ts b/packages/cel/src/lib/program.ts new file mode 100644 index 0000000..968de9c --- /dev/null +++ b/packages/cel/src/lib/program.ts @@ -0,0 +1,15 @@ +import { CELEnvironment } from './environment'; +import { StartContext } from './gen/CELParser'; +import { CELVisitor } from './visitor'; + +export class CELProgram { + constructor( + public readonly env: CELEnvironment, + public readonly ast: StartContext + ) {} + + parse() { + const parser = new CELVisitor(this.env); + return this.ast.accept(parser); + } +} diff --git a/packages/cel/src/lib/standard.ts b/packages/cel/src/lib/standard.ts new file mode 100644 index 0000000..37f7421 --- /dev/null +++ b/packages/cel/src/lib/standard.ts @@ -0,0 +1,46 @@ +import { + DescEnum, + DescExtension, + DescFile, + DescMessage, + DescService, + Registry, +} from '@bufbuild/protobuf'; +import { + AnySchema, + BoolValueSchema, + BytesValueSchema, + DoubleValueSchema, + FloatValueSchema, + Int32ValueSchema, + Int64ValueSchema, + ListValueSchema, + ValueSchema as ProtobufValueSchema, + StringValueSchema, + StructSchema, + UInt32ValueSchema, + UInt64ValueSchema, +} from '@bufbuild/protobuf/wkt'; + +export const standardTypes: ( + | DescMessage + | DescEnum + | Registry + | DescFile + | DescExtension + | DescService +)[] = [ + AnySchema, + ListValueSchema, + StructSchema, + ProtobufValueSchema, + BoolValueSchema, + BytesValueSchema, + DoubleValueSchema, + FloatValueSchema, + Int32ValueSchema, + Int64ValueSchema, + StringValueSchema, + UInt32ValueSchema, + UInt64ValueSchema, +]; diff --git a/packages/cel/src/lib/to-native.spec.ts b/packages/cel/src/lib/to-native.spec.ts new file mode 100644 index 0000000..2b1f896 --- /dev/null +++ b/packages/cel/src/lib/to-native.spec.ts @@ -0,0 +1,122 @@ +import { ExprValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/eval_pb.js'; +import { fromJson } from '@bufbuild/protobuf'; +import { NullValue } from '@bufbuild/protobuf/wkt'; +import { exprValueToNative } from './to-native'; + +describe('exprValueToNative', () => { + it('should convert a boolean value to native', () => { + expect( + exprValueToNative( + fromJson(ExprValueSchema, { value: { boolValue: true } }) + ) + ).toEqual(true); + expect( + exprValueToNative( + fromJson(ExprValueSchema, { value: { boolValue: false } }) + ) + ).toEqual(false); + }); + + it('should convert a bytes value to native', () => { + expect( + exprValueToNative( + fromJson(ExprValueSchema, { value: { bytesValue: 'aGVsbG8=' } }) + ) + ).toEqual(new TextEncoder().encode('hello')); + }); + + it('should convert a double value to native', () => { + expect( + exprValueToNative( + fromJson(ExprValueSchema, { value: { doubleValue: 3.14 } }) + ) + ).toEqual(3.14); + }); + + it('should convert a int64 value to native', () => { + expect( + exprValueToNative( + fromJson(ExprValueSchema, { value: { int64Value: '7' } }) + ) + ).toEqual(BigInt(7)); + }); + + it('should convert a string value to native', () => { + expect( + exprValueToNative( + fromJson(ExprValueSchema, { value: { stringValue: 'hello' } }) + ) + ).toEqual('hello'); + }); + + it('should convert a uint64 value to native', () => { + expect( + exprValueToNative( + fromJson(ExprValueSchema, { value: { uint64Value: '7' } }) + ) + ).toEqual(BigInt(7)); + }); + + it('should convert an enum value to native', () => { + expect( + exprValueToNative( + fromJson(ExprValueSchema, { value: { enumValue: { value: 1 } } }) + ) + ).toEqual(1); + }); + + it('should convert a list value to native', () => { + expect( + exprValueToNative( + fromJson(ExprValueSchema, { + value: { + listValue: { + values: [ + { int64Value: '1' }, + { int64Value: '2' }, + { int64Value: '3' }, + ], + }, + }, + }) + ) + ).toEqual([BigInt(1), BigInt(2), BigInt(3)]); + }); + + it('should convert a map value to native', () => { + expect( + exprValueToNative( + fromJson(ExprValueSchema, { + value: { + mapValue: { + entries: [ + { + key: { stringValue: 'a' }, + value: { int64Value: '1' }, + }, + { + key: { stringValue: 'b' }, + value: { int64Value: '2' }, + }, + { + key: { stringValue: 'c' }, + value: { int64Value: '3' }, + }, + ], + }, + }, + }) + ) + ).toEqual({ a: BigInt(1), b: BigInt(2), c: BigInt(3) }); + }); + + it('should convert a null value to native', () => { + expect( + exprValueToNative( + fromJson(ExprValueSchema, { + value: { nullValue: NullValue.NULL_VALUE }, + }) + ) + ).toEqual(null); + }); +}); diff --git a/packages/cel/src/lib/to-native.ts b/packages/cel/src/lib/to-native.ts new file mode 100644 index 0000000..bc71bea --- /dev/null +++ b/packages/cel/src/lib/to-native.ts @@ -0,0 +1,91 @@ +import { ExprValue } from '@buf/google_cel-spec.bufbuild_es/cel/expr/eval_pb.js'; +import { + Value, + ValueSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { NullValue } from '@bufbuild/protobuf/wkt'; + +/** + * Converts an expression value to a native value. + * + * @param exprValue the expression value to convert to native + * @returns a native value + */ +export function exprValueToNative(exprValue: ExprValue) { + switch (exprValue.kind.case) { + case 'value': + return valueToNative(exprValue.kind.value); + case 'error': + return exprValue.kind.value; + case 'unknown': + return exprValue.kind.value; + default: + throw new Error('unsupported'); + } +} + +export type NativeValue = + | string + | number + | bigint + | boolean + | null + | Uint8Array + | NativeValue[] + | NativeObject; + +export type NativeObject = { + [k: string]: NativeValue; +}; + +function valueToNative(value: Value): NativeValue { + switch (value.kind.case) { + case 'boolValue': + case 'bytesValue': + case 'doubleValue': + case 'int64Value': + case 'stringValue': + case 'uint64Value': + return value.kind.value; + case 'enumValue': + return value.kind.value.value; + case 'listValue': + return value.kind.value.values.map(valueToNative); + case 'mapValue': + return value.kind.value.entries.reduce((acc, entry) => { + if (!entry.key) return acc; + switch (entry.key.kind.case) { + case 'stringValue': + acc[entry.key.kind.value] = valueToNative( + entry.value ?? + create(ValueSchema, { + kind: { + case: 'nullValue', + value: NullValue.NULL_VALUE, + }, + }) + ); + return acc; + case 'int64Value': + case 'uint64Value': + acc[entry.key.kind.value.toString()] = valueToNative( + entry.value ?? + create(ValueSchema, { + kind: { + case: 'nullValue', + value: NullValue.NULL_VALUE, + }, + }) + ); + return acc; + default: + return acc; + } + }, {} as Record); + case 'nullValue': + return null; + default: + throw new Error('unsupported'); + } +} diff --git a/packages/cel/src/lib/utils.ts b/packages/cel/src/lib/utils.ts new file mode 100644 index 0000000..02e81f1 --- /dev/null +++ b/packages/cel/src/lib/utils.ts @@ -0,0 +1,284 @@ +import { + ConstantSchema, + Expr, + ExprSchema, + Expr_IdentSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { NullValue } from '@bufbuild/protobuf/wkt'; +import { ParserRuleContext } from 'antlr4'; + +export function uniqueIdFromContext(ctx: ParserRuleContext) { + return BigInt(ctx.start.start); +} + +export function parseString(str: string) { + const decoded = decodeURIComponent(str); + return decoded.replace(/\\([abfnrtv'"\\])/g, '$1'); +} + +export function parseBytes(str: string) { + // Remove double escapes from the string + str = parseString(str); + // Match octal or hexadecimal numbers + const octalOrHexadecimalNumbers = str.match( + /\\[0-7]{1,3}|\\x[0-9a-fA-F]{2}/g + ); + if (octalOrHexadecimalNumbers) { + const uint8Array = new Uint8Array(octalOrHexadecimalNumbers.length); + for (let i = 0; i < octalOrHexadecimalNumbers.length; i++) { + const octalOrHexadecimalNumber = octalOrHexadecimalNumbers[i]; + if (octalOrHexadecimalNumber.startsWith('\\x')) { + uint8Array[i] = parseInt(octalOrHexadecimalNumber.slice(2), 16); + } else { + uint8Array[i] = parseInt(octalOrHexadecimalNumber.slice(1), 8); + } + } + return uint8Array; + } + return new TextEncoder().encode(str); +} + +export function parseInt64(str: string) { + const decoded = decodeURIComponent(str); + if (decoded.startsWith('-')) { + return -BigInt(decoded.slice(1)); + } + return BigInt(decoded); +} + +export function isNil(value: unknown): value is null | undefined { + return value === null || value === undefined; +} + +export function boolConstant(value: boolean) { + return create(ConstantSchema, { + constantKind: { + case: 'boolValue', + value, + }, + }); +} + +export function boolExpr(value: boolean) { + return create(ExprSchema, { + exprKind: { + case: 'constExpr', + value: boolConstant(value), + }, + }); +} + +export function boolValue(value: boolean) { + return create(ValueSchema, { + kind: { + case: 'boolValue', + value, + }, + }); +} + +export function int64Constant(value: bigint) { + return create(ConstantSchema, { + constantKind: { + case: 'int64Value', + value, + }, + }); +} + +export function int64Expr(value: bigint) { + return create(ExprSchema, { + exprKind: { + case: 'constExpr', + value: int64Constant(value), + }, + }); +} + +export function int64Value(value: bigint) { + return create(ValueSchema, { + kind: { + case: 'int64Value', + value, + }, + }); +} + +export function uint64Constant(value: bigint) { + return create(ConstantSchema, { + constantKind: { + case: 'uint64Value', + value, + }, + }); +} + +export function uint64Expr(value: bigint) { + return create(ExprSchema, { + exprKind: { + case: 'constExpr', + value: uint64Constant(value), + }, + }); +} + +export function uint64Value(value: bigint) { + return create(ValueSchema, { + kind: { + case: 'uint64Value', + value, + }, + }); +} + +export function doubleConstant(value: number) { + return create(ConstantSchema, { + constantKind: { + case: 'doubleValue', + value, + }, + }); +} + +export function doubleExpr(value: number) { + return create(ExprSchema, { + exprKind: { + case: 'constExpr', + value: doubleConstant(value), + }, + }); +} + +export function doubleValue(value: number) { + return create(ValueSchema, { + kind: { + case: 'doubleValue', + value, + }, + }); +} + +export function stringConstant(value: string) { + return create(ConstantSchema, { + constantKind: { + case: 'stringValue', + value, + }, + }); +} + +export function stringExpr(value: string) { + return create(ExprSchema, { + exprKind: { + case: 'constExpr', + value: stringConstant(value), + }, + }); +} + +export function stringValue(value: string) { + return create(ValueSchema, { + kind: { + case: 'stringValue', + value, + }, + }); +} + +export function bytesConstant(value: Uint8Array) { + return create(ConstantSchema, { + constantKind: { + case: 'bytesValue', + value, + }, + }); +} + +export function bytesExpr(value: Uint8Array) { + return create(ExprSchema, { + exprKind: { + case: 'constExpr', + value: bytesConstant(value), + }, + }); +} + +export function bytesValue(value: Uint8Array) { + return create(ValueSchema, { + kind: { + case: 'bytesValue', + value, + }, + }); +} + +export const NULL_CONSTANT = create(ConstantSchema, { + constantKind: { + case: 'nullValue', + value: NullValue.NULL_VALUE, + }, +}); + +export const NULL_EXPR = create(ExprSchema, { + exprKind: { + case: 'constExpr', + value: NULL_CONSTANT, + }, +}); + +export const NULL_VALUE = create(ValueSchema, { + kind: { + case: 'nullValue', + value: NullValue.NULL_VALUE, + }, +}); + +export function identExpr(name: string) { + return create(ExprSchema, { + exprKind: { + case: 'identExpr', + value: create(Expr_IdentSchema, { + name, + }), + }, + }); +} + +export function globalCall(functionName: string, ...args: Expr[]) { + return create(ExprSchema, { + exprKind: { + case: 'callExpr', + value: { + function: functionName, + args, + }, + }, + }); +} + +export function listExpr(exprs: Expr[]) { + return create(ExprSchema, { + exprKind: { + case: 'listExpr', + value: { + elements: exprs, + }, + }, + }); +} + +export function unquote(str: string) { + const reg = /['"]/; + if (!str) { + return ''; + } + if (reg.test(str.charAt(0))) { + str = str.substr(1); + } + if (reg.test(str.charAt(str.length - 1))) { + str = str.substr(0, str.length - 1); + } + return str; +} diff --git a/packages/cel/src/lib/visitor.spec.ts b/packages/cel/src/lib/visitor.spec.ts new file mode 100644 index 0000000..bf9fdd1 --- /dev/null +++ b/packages/cel/src/lib/visitor.spec.ts @@ -0,0 +1,1464 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { + Expr, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { NullValue } from '@bufbuild/protobuf/wkt'; +import { CELEnvironment } from './environment'; +import { CELProgram } from './program'; + +interface TestInfo { + // I contains the input expression to be parsed. + I: string; + + // P contains the expected Expr output for the parsed expression. + P?: Expr | any; + + // E contains the expected error output for a failed parse, or "" if the parse is expected to be successful. + E?: string; + + // L contains the expected source adorned debug output of the expression tree. + L?: string; + + // M contains the expected adorned debug output of the macro calls map + M?: string; + + // Opts contains the list of options to be configured with the parser before parsing the expression. + Opts?: unknown[]; +} + +// See: https://github.com/google/cel-go/blob/master/parser/parser_test.go +const testCases: TestInfo[] = [ + { + I: `"A"`, + // P: `"A"^#1:*expr.Constant_StringValue#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'stringValue', + value: 'A', + }, + }, + }, + }), + }, + { + I: `true`, + // P: `true^#1:*expr.Constant_BoolValue#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'boolValue', + value: true, + }, + }, + }, + }), + }, + { + I: `false`, + // P: `false^#1:*expr.Constant_BoolValue#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'boolValue', + value: false, + }, + }, + }, + }), + }, + { + I: `0`, + // P: `0^#1:*expr.Constant_Int64Value#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(0), + }, + }, + }, + }), + }, + { + I: `42`, + // P: `42^#1:*expr.Constant_Int64Value#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(42), + }, + }, + }, + }), + }, + { + I: `0xF`, + // P: `15^#1:*expr.Constant_Int64Value#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(15), + }, + }, + }, + }), + }, + { + I: `0u`, + // P: `0u^#1:*expr.Constant_Uint64Value#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'uint64Value', + value: BigInt(0), + }, + }, + }, + }), + }, + { + I: `23u`, + // P: `23u^#1:*expr.Constant_Uint64Value#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'uint64Value', + value: BigInt(23), + }, + }, + }, + }), + }, + { + I: `24u`, + // P: `24u^#1:*expr.Constant_Uint64Value#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'uint64Value', + value: BigInt(24), + }, + }, + }, + }), + }, + { + I: `0xFu`, + // P: `15u^#1:*expr.Constant_Uint64Value#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'uint64Value', + value: BigInt(15), + }, + }, + }, + }), + }, + { + I: `-1`, + // P: `-1^#1:*expr.Constant_Int64Value#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(-1), + }, + }, + }, + }), + }, + { + I: `4--4`, + // P: `_-_( + // 4^#1:*expr.Constant_Int64Value#, + // -4^#3:*expr.Constant_Int64Value# + // )^#2:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_-_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(4), + }, + }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(-4), + }, + }, + }, + }, + ], + }, + }, + }), + }, + { + I: `4--4.1`, + // P: `_-_( + // 4^#1:*expr.Constant_Int64Value#, + // -4.1^#3:*expr.Constant_DoubleValue# + // )^#2:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_-_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(4), + }, + }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'doubleValue', + value: -4.1, + }, + }, + }, + }, + ], + }, + }, + }), + }, + { + I: `b"abc"`, + // P: `b"abc"^#1:*expr.Constant_BytesValue#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'bytesValue', + value: new TextEncoder().encode('abc'), + }, + }, + }, + }), + }, + { + I: '23.39', + // P: `23.39^#1:*expr.Constant_DoubleValue#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'doubleValue', + value: 23.39, + }, + }, + }, + }), + }, + { + I: `!a`, + // P: `!_( + // a^#2:*expr.Expr_IdentExpr# + // )^#1:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'callExpr', + value: { + function: '!_', + args: [ + { + id: BigInt(2), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + ], + }, + }, + }), + }, + { + I: 'null', + // P: `null^#1:*expr.Constant_NullValue#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'nullValue', + value: NullValue.NULL_VALUE, + }, + }, + }, + }), + }, + { + I: `a`, + // P: `a^#1:*expr.Expr_IdentExpr#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }), + }, + { + I: `a?b:c`, + // P: `_?_:_( + // a^#1:*expr.Expr_IdentExpr#, + // b^#3:*expr.Expr_IdentExpr#, + // c^#4:*expr.Expr_IdentExpr# + // )^#2:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_?_:_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }, + { + id: BigInt(4), + exprKind: { + case: 'identExpr', + value: { name: 'c' }, + }, + }, + ], + }, + }, + }), + }, + { + I: `a || b`, + // P: `_||_( + // a^#1:*expr.Expr_IdentExpr#, + // b^#2:*expr.Expr_IdentExpr# + // )^#3:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(3), + exprKind: { + case: 'callExpr', + value: { + function: '_||_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + { + id: BigInt(2), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }, + ], + }, + }, + }), + }, + { + I: `a || b || c || d || e || f `, + // P: ` _||_( + // _||_( + // _||_( + // a^#1:*expr.Expr_IdentExpr#, + // b^#2:*expr.Expr_IdentExpr# + // )^#3:*expr.Expr_CallExpr#, + // c^#4:*expr.Expr_IdentExpr# + // )^#5:*expr.Expr_CallExpr#, + // _||_( + // _||_( + // d^#6:*expr.Expr_IdentExpr#, + // e^#8:*expr.Expr_IdentExpr# + // )^#9:*expr.Expr_CallExpr#, + // f^#10:*expr.Expr_IdentExpr# + // )^#11:*expr.Expr_CallExpr# + // )^#7:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(7), + exprKind: { + case: 'callExpr', + value: { + function: '_||_', + args: [ + { + id: BigInt(5), + exprKind: { + case: 'callExpr', + value: { + function: '_||_', + args: [ + { + id: BigInt(3), + exprKind: { + case: 'callExpr', + value: { + function: '_||_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + { + id: BigInt(2), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }, + ], + }, + }, + }, + { + id: BigInt(4), + exprKind: { + case: 'identExpr', + value: { name: 'c' }, + }, + }, + ], + }, + }, + }, + { + id: BigInt(11), + exprKind: { + case: 'callExpr', + value: { + function: '_||_', + args: [ + { + id: BigInt(9), + exprKind: { + case: 'callExpr', + value: { + function: '_||_', + args: [ + { + id: BigInt(6), + exprKind: { + case: 'identExpr', + value: { name: 'd' }, + }, + }, + { + id: BigInt(8), + exprKind: { + case: 'identExpr', + value: { name: 'e' }, + }, + }, + ], + }, + }, + }, + { + id: BigInt(10), + exprKind: { + case: 'identExpr', + value: { name: 'f' }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + }), + }, + { + I: `a && b`, + // P: `_&&_( + // a^#1:*expr.Expr_IdentExpr#, + // b^#2:*expr.Expr_IdentExpr# + // )^#3:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(3), + exprKind: { + case: 'callExpr', + value: { + function: '_&&_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + { + id: BigInt(2), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }, + ], + }, + }, + }), + }, + { + I: `a && b && c && d && e && f && g`, + // P: `_&&_( + // _&&_( + // _&&_( + // a^#1:*expr.Expr_IdentExpr#, + // b^#2:*expr.Expr_IdentExpr# + // )^#3:*expr.Expr_CallExpr#, + // _&&_( + // c^#4:*expr.Expr_IdentExpr#, + // d^#6:*expr.Expr_IdentExpr# + // )^#7:*expr.Expr_CallExpr# + // )^#5:*expr.Expr_CallExpr#, + // _&&_( + // _&&_( + // e^#8:*expr.Expr_IdentExpr#, + // f^#10:*expr.Expr_IdentExpr# + // )^#11:*expr.Expr_CallExpr#, + // g^#12:*expr.Expr_IdentExpr# + // )^#13:*expr.Expr_CallExpr# + // )^#9:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(9), + exprKind: { + case: 'callExpr', + value: { + function: '_&&_', + args: [ + { + id: BigInt(5), + exprKind: { + case: 'callExpr', + value: { + function: '_&&_', + args: [ + { + id: BigInt(3), + exprKind: { + case: 'callExpr', + value: { + function: '_&&_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + { + id: BigInt(2), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }, + ], + }, + }, + }, + { + id: BigInt(7), + exprKind: { + case: 'callExpr', + value: { + function: '_&&_', + args: [ + { + id: BigInt(4), + exprKind: { + case: 'identExpr', + value: { name: 'c' }, + }, + }, + { + id: BigInt(6), + exprKind: { + case: 'identExpr', + value: { name: 'd' }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + }, + { + id: BigInt(13), + exprKind: { + case: 'callExpr', + value: { + function: '_&&_', + args: [ + { + id: BigInt(11), + exprKind: { + case: 'callExpr', + value: { + function: '_&&_', + args: [ + { + id: BigInt(8), + exprKind: { + case: 'identExpr', + value: { name: 'e' }, + }, + }, + { + id: BigInt(10), + exprKind: { + case: 'identExpr', + value: { name: 'f' }, + }, + }, + ], + }, + }, + }, + { + id: BigInt(12), + exprKind: { + case: 'identExpr', + value: { name: 'g' }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + }), + }, + { + I: `a && b && c && d || e && f && g && h`, + // P: `_||_( + // _&&_( + // _&&_( + // a^#1:*expr.Expr_IdentExpr#, + // b^#2:*expr.Expr_IdentExpr# + // )^#3:*expr.Expr_CallExpr#, + // _&&_( + // c^#4:*expr.Expr_IdentExpr#, + // d^#6:*expr.Expr_IdentExpr# + // )^#7:*expr.Expr_CallExpr# + // )^#5:*expr.Expr_CallExpr#, + // _&&_( + // _&&_( + // e^#8:*expr.Expr_IdentExpr#, + // f^#9:*expr.Expr_IdentExpr# + // )^#10:*expr.Expr_CallExpr#, + // _&&_( + // g^#11:*expr.Expr_IdentExpr#, + // h^#13:*expr.Expr_IdentExpr# + // )^#14:*expr.Expr_CallExpr# + // )^#12:*expr.Expr_CallExpr# + // )^#15:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(15), + exprKind: { + case: 'callExpr', + value: { + function: '_||_', + args: [ + { + id: BigInt(5), + exprKind: { + case: 'callExpr', + value: { + function: '_&&_', + args: [ + { + id: BigInt(3), + exprKind: { + case: 'callExpr', + value: { + function: '_&&_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + { + id: BigInt(2), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }, + ], + }, + }, + }, + { + id: BigInt(7), + exprKind: { + case: 'callExpr', + value: { + function: '_&&_', + args: [ + { + id: BigInt(4), + exprKind: { + case: 'identExpr', + value: { name: 'c' }, + }, + }, + { + id: BigInt(6), + exprKind: { + case: 'identExpr', + value: { name: 'd' }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + }, + { + id: BigInt(12), + exprKind: { + case: 'callExpr', + value: { + function: '_&&_', + args: [ + { + id: BigInt(10), + exprKind: { + case: 'callExpr', + value: { + function: '_&&_', + args: [ + { + id: BigInt(8), + exprKind: { + case: 'identExpr', + value: { name: 'e' }, + }, + }, + { + id: BigInt(9), + exprKind: { + case: 'identExpr', + value: { name: 'f' }, + }, + }, + ], + }, + }, + }, + { + id: BigInt(14), + exprKind: { + case: 'callExpr', + value: { + function: '_&&_', + args: [ + { + id: BigInt(11), + exprKind: { + case: 'identExpr', + value: { name: 'g' }, + }, + }, + { + id: BigInt(13), + exprKind: { + case: 'identExpr', + value: { name: 'h' }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + }), + }, + { + I: `a + b`, + // P: `_+_( + // a^#1:*expr.Expr_IdentExpr#, + // b^#3:*expr.Expr_IdentExpr# + // )^#2:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_+_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }, + ], + }, + }, + }), + }, + { + I: `a - b`, + // P: `_-_( + // a^#1:*expr.Expr_IdentExpr#, + // b^#3:*expr.Expr_IdentExpr# + // )^#2:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_-_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }, + ], + }, + }, + }), + }, + { + I: `a * b`, + // P: `_*_( + // a^#1:*expr.Expr_IdentExpr#, + // b^#3:*expr.Expr_IdentExpr# + // )^#2:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_*_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }, + ], + }, + }, + }), + }, + { + I: `a / b`, + // P: `_/_( + // a^#1:*expr.Expr_IdentExpr#, + // b^#3:*expr.Expr_IdentExpr# + // )^#2:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_/_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }, + ], + }, + }, + }), + }, + { + I: `a % b`, + // P: `_%_( + // a^#1:*expr.Expr_IdentExpr#, + // b^#3:*expr.Expr_IdentExpr# + // )^#2:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_%_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }, + ], + }, + }, + }), + }, + { + I: `a in b`, + // P: `@in( + // a^#1:*expr.Expr_IdentExpr#, + // b^#3:*expr.Expr_IdentExpr# + // )^#2:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '@in', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }, + ], + }, + }, + }), + }, + { + I: `a == b`, + // P: `_==_( + // a^#1:*expr.Expr_IdentExpr#, + // b^#3:*expr.Expr_IdentExpr# + // )^#2:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_==_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }, + ], + }, + }, + }), + }, + { + I: `a != b`, + // P: ` _!=_( + // a^#1:*expr.Expr_IdentExpr#, + // b^#3:*expr.Expr_IdentExpr# + // )^#2:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_!=_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }, + ], + }, + }, + }), + }, + { + I: `a > b`, + // P: `_>_( + // a^#1:*expr.Expr_IdentExpr#, + // b^#3:*expr.Expr_IdentExpr# + // )^#2:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_>_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }, + ], + }, + }, + }), + }, + { + I: `a >= b`, + // P: `_>=_( + // a^#1:*expr.Expr_IdentExpr#, + // b^#3:*expr.Expr_IdentExpr# + // )^#2:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_>=_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }, + ], + }, + }, + }), + }, + { + I: `a < b`, + // P: `_<_( + // a^#1:*expr.Expr_IdentExpr#, + // b^#3:*expr.Expr_IdentExpr# + // )^#2:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_<_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }, + ], + }, + }, + }), + }, + { + I: `a <= b`, + // P: `_<=_( + // a^#1:*expr.Expr_IdentExpr#, + // b^#3:*expr.Expr_IdentExpr# + // )^#2:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_<=_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }, + ], + }, + }, + }), + }, + { + I: `a.b`, + // P: `a^#1:*expr.Expr_IdentExpr#.b^#2:*expr.Expr_SelectExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'selectExpr', + value: { + operand: { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + field: 'b', + }, + }, + }), + }, + { + I: `a.b.c`, + // P: `a^#1:*expr.Expr_IdentExpr#.b^#2:*expr.Expr_SelectExpr#.c^#3:*expr.Expr_SelectExpr#`, + P: create(ExprSchema, { + id: BigInt(3), + exprKind: { + case: 'selectExpr', + value: { + operand: { + id: BigInt(2), + exprKind: { + case: 'selectExpr', + value: { + operand: { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + field: 'b', + }, + }, + }, + field: 'c', + }, + }, + }), + }, + { + I: `a[b]`, + // P: `_[_]( + // a^#1:*expr.Expr_IdentExpr#, + // b^#3:*expr.Expr_IdentExpr# + // )^#2:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_[_]', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }, + ], + }, + }, + }), + }, + { + I: `foo{ }`, + // P: `foo{}^#1:*expr.Expr_StructExpr#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'structExpr', + value: { + messageName: 'foo', + entries: [], + }, + }, + }), + }, + { + I: `foo{ a:b }`, + // P: `foo{ + // a:b^#3:*expr.Expr_IdentExpr#^#2:*expr.Expr_CreateStruct_Entry# + // }^#1:*expr.Expr_StructExpr#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'structExpr', + value: { + messageName: 'foo', + entries: [ + { + id: BigInt(2), + keyKind: { + case: 'fieldKey', + value: 'a', + }, + value: { + id: BigInt(3), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }, + }, + ], + }, + }, + }), + }, + { + I: `foo{ a:b, c:d }`, + // P: `foo{ + // a:b^#3:*expr.Expr_IdentExpr#^#2:*expr.Expr_CreateStruct_Entry#, + // c:d^#5:*expr.Expr_IdentExpr#^#4:*expr.Expr_CreateStruct_Entry# + // }^#1:*expr.Expr_StructExpr#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'structExpr', + value: { + messageName: 'foo', + entries: [ + { + id: BigInt(2), + keyKind: { + case: 'fieldKey', + value: 'a', + }, + value: { + id: BigInt(3), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }, + }, + { + id: BigInt(4), + keyKind: { + case: 'fieldKey', + value: 'c', + }, + value: { + id: BigInt(5), + exprKind: { + case: 'identExpr', + value: { name: 'd' }, + }, + }, + }, + ], + }, + }, + }), + }, +]; + +describe('CELVisitor', () => { + for (const testCase of testCases) { + it(`should parse ${testCase.I}`, () => { + // Arrange + const env = new CELEnvironment(); + const ast = env.compile(testCase.I); + const program = new CELProgram(env, ast); + + // Act + const expr = program.parse(); + + // Assert + expect(expr).toEqual(testCase.P); + }); + } +}); diff --git a/packages/cel/src/lib/visitor.ts b/packages/cel/src/lib/visitor.ts new file mode 100644 index 0000000..ac7e1ee --- /dev/null +++ b/packages/cel/src/lib/visitor.ts @@ -0,0 +1,915 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import { assert, isNil } from '@bearclaw/is'; +import { ErrorSetSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/eval_pb.js'; +import { + ConstantSchema, + Expr, + ExprSchema, + Expr_CreateStruct, + Expr_CreateStruct_Entry, + Expr_CreateStruct_EntrySchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { + Status, + StatusSchema, +} from '@buf/googleapis_googleapis.bufbuild_es/google/rpc/status_pb.js'; +import { create, fromJson } from '@bufbuild/protobuf'; +import { NullValue, StringValueSchema, anyPack } from '@bufbuild/protobuf/wkt'; +import { ParseTree, ParserRuleContext, Token } from 'antlr4'; +import { + RESERVED_IDS, + parseBytesConstant, + parseDoubleConstant, + parseIntConstant, + parseStringConstant, + parseUintConstant, +} from './constants'; +import { CELEnvironment } from './environment'; +import { NullException, ParseException } from './exceptions'; +import { + BoolFalseContext, + BoolTrueContext, + BytesContext, + CalcContext, + ConditionalAndContext, + ConditionalOrContext, + ConstantLiteralContext, + CreateMessageContext, + DoubleContext, + ExprContext, + ExprListContext, + FieldInitializerListContext, + IdentOrGlobalCallContext, + IndexContext, + IntContext, + ListInitContext, + LogicalNotContext, + MemberCallContext, + MemberExprContext, + NegateContext, + NestedContext, + NullContext, + PrimaryExprContext, + RelationContext, + SelectContext, + StartContext, + StringContext, + UintContext, +} from './gen/CELParser'; +import { default as GeneratedCelVisitor } from './gen/CELVisitor'; +import { LogicManager } from './logic-manager'; +import { expandMacro, findMacro } from './macros'; +import { + CONDITIONAL_OPERATOR, + INDEX_OPERATOR, + LOGICAL_AND_OPERATOR, + LOGICAL_NOT_OPERATOR, + LOGICAL_OR_OPERATOR, + NEGATE_OPERATOR, + OPT_INDEX_OPERATOR, + OPT_SELECT_OPERATOR, + getOperatorFromText, +} from './operators'; + +export class CELVisitor extends GeneratedCelVisitor { + #id = BigInt(1); + #ERROR = create(ConstantSchema, { + constantKind: { + case: 'stringValue', + value: '<>', + }, + }); + public readonly errors = create(ErrorSetSchema); + + constructor( + public readonly env: CELEnvironment, + private readonly options?: { + enableOptionalSyntax?: boolean; + retainRepeatedUnaryOperators?: boolean; + } + ) { + super(); + } + + override visit = (ctx: ParseTree) => { + return super.visit(this._unnest(ctx)); + }; + + override visitStart = (ctx: StartContext): Expr => { + this._checkNotNil(ctx); + if (isNil(ctx._e)) { + return this._ensureErrorsExist( + create(StatusSchema, { + code: 1, + message: 'no expression context', + }) + ); + } + return this.visit(ctx._e); + }; + + override visitExpr = (ctx: ExprContext): Expr => { + this._checkNotNil(ctx); + if (isNil(ctx._e)) { + return this._ensureErrorsExist( + create(StatusSchema, { + code: 1, + message: 'no expression context', + }) + ); + } + if (!ctx._op) { + return this.visit(ctx._e); + } + if (isNil(ctx._e1) || isNil(ctx._e2)) { + return this._ensureErrorsExist( + create(StatusSchema, { + code: 1, + message: 'no conditional context', + }) + ); + } + // If the expression is a ternary expression + const condition = this.visit(ctx._e); // Visit the condition part + const id = this.#id++; + const trueExpr = this.visit(ctx._e1); // Visit the true part + const falseExpr = this.visit(ctx._e2); // Visit the false part + // Handle the ternary expression, e.g., return condition ? trueExpr : falseExpr; + return create(ExprSchema, { + id, + exprKind: { + case: 'callExpr', + value: { + function: CONDITIONAL_OPERATOR, + args: [condition, trueExpr, falseExpr], + }, + }, + }); + }; + + override visitConditionalOr = (ctx: ConditionalOrContext): Expr => { + this._checkNotNil(ctx); + if (isNil(ctx._e)) { + return this._ensureErrorsExist( + create(StatusSchema, { + code: 1, + message: 'no conditionalor context', + }) + ); + } + const result = this.visit(ctx._e); + const logicManager = LogicManager.newBalancingLogicManager( + LOGICAL_OR_OPERATOR, + result + ); + for (let i = 0; i < ctx._ops.length; i++) { + if (isNil(ctx._e1) || i >= ctx._e1.length) { + return this._reportError(ctx, "unexpected character, wanted '||'"); + } + const term = this.visit(ctx._e1[i]); + logicManager.addTerm(this.#id++, term); + } + return logicManager.toExpr(); + }; + + override visitConditionalAnd = (ctx: ConditionalAndContext): Expr => { + this._checkNotNil(ctx); + if (isNil(ctx._e)) { + return this._ensureErrorsExist( + create(StatusSchema, { + code: 1, + message: 'no conditionaland context', + }) + ); + } + const result = this.visit(ctx._e); + const logicManager = LogicManager.newBalancingLogicManager( + LOGICAL_AND_OPERATOR, + result + ); + for (let i = 0; i < ctx._ops.length; i++) { + if (isNil(ctx._e1) || i >= ctx._e1.length) { + return this._reportError(ctx, "unexpected character, wanted '^^'"); + } + const term = this.visit(ctx._e1[i]); + logicManager.addTerm(this.#id++, term); + } + return logicManager.toExpr(); + }; + + override visitRelation = (ctx: RelationContext): Expr => { + this._checkNotNil(ctx); + if (!isNil(ctx.calc())) { + return this.visit(ctx.calc()); + } + if ( + isNil(ctx.relation_list()) || + ctx.relation_list().length === 0 || + isNil(ctx._op) + ) { + return this._ensureErrorsExist( + create(StatusSchema, { + code: 1, + message: 'no relation context', + }) + ); + } + const operator = getOperatorFromText(ctx._op.text); + if (isNil(operator)) { + return this._reportError(ctx, 'operator not found'); + } + const left = this.visit(ctx.relation(0)); + const id = this.#id++; + const right = this.visit(ctx.relation(1)); + return create(ExprSchema, { + id, + exprKind: { + case: 'callExpr', + value: { + function: operator, + args: [left, right], + }, + }, + }); + }; + + override visitCalc = (ctx: CalcContext): Expr => { + this._checkNotNil(ctx); + if (!isNil(ctx.unary())) { + return this.visit(ctx.unary()); + } + if ( + isNil(ctx.calc_list()) || + ctx.calc_list().length === 0 || + isNil(ctx._op) + ) { + return this._ensureErrorsExist( + create(StatusSchema, { + code: 1, + message: 'no calc context', + }) + ); + } + const operator = getOperatorFromText(ctx._op.text); + if (isNil(operator)) { + return this._reportError(ctx, 'operator not found'); + } + const left = this.visit(ctx.calc(0)); + const id = this.#id++; + const right = this.visit(ctx.calc(1)); + return create(ExprSchema, { + id, + exprKind: { + case: 'callExpr', + value: { + function: operator, + args: [left, right], + }, + }, + }); + }; + + override visitMemberExpr = (ctx: MemberExprContext): Expr => { + this._checkNotNil(ctx); + if (isNil(ctx.member())) { + return this._ensureErrorsExist( + create(StatusSchema, { + code: 1, + message: 'no member expr context', + }) + ); + } + return this.visit(ctx.member()); + }; + + override visitLogicalNot = (ctx: LogicalNotContext): Expr => { + this._checkNotNil(ctx); + if (isNil(ctx.member())) { + return this._ensureErrorsExist( + create(StatusSchema, { + code: 1, + message: 'no member expr context', + }) + ); + } + if (!isNil(ctx._ops) && ctx._ops.length % 2 === 0) { + return this.visit(ctx.member()); + } + const id = this.#id++; + const member = this.visit(ctx.member()); + return create(ExprSchema, { + id, + exprKind: { + case: 'callExpr', + value: { + function: LOGICAL_NOT_OPERATOR, + args: [member], + }, + }, + }); + }; + + override visitNegate = (ctx: NegateContext): Expr => { + this._checkNotNil(ctx); + if (isNil(ctx.member())) { + return this._ensureErrorsExist( + create(StatusSchema, { + code: 1, + message: 'no member context', + }) + ); + } + const expr = this.visit(ctx.member()); + if (isNil(ctx._ops) || ctx._ops.length % 2 === 0) { + return expr; + } + return create(ExprSchema, { + id: this.#id++, + exprKind: { + case: 'callExpr', + value: { + function: NEGATE_OPERATOR, + args: [expr], + }, + }, + }); + }; + + // override visitMemberCall = (ctx: MemberCallContext): Expr => { + // // Implementation logic here + // }; + + override visitSelect = (ctx: SelectContext): Expr => { + this._checkNotNil(ctx); + const operand = this.visit(ctx.member()); + // Handle the error case where no valid identifier is specified. + if (isNil(ctx._id) || isNil(ctx._op)) { + return this._ensureErrorsExist( + create(StatusSchema, { + code: 1, + message: 'no valid identifier specified', + }) + ); + } + const id = ctx._id.text; + if (!isNil(ctx._opt)) { + const literalString = create(ExprSchema, { + id: this.#id++, + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'stringValue', + value: id, + }, + }, + }, + }); + return create(ExprSchema, { + id: this.#id++, + exprKind: { + case: 'callExpr', + value: { + function: OPT_SELECT_OPERATOR, + args: [operand, literalString], + }, + }, + }); + } + return create(ExprSchema, { + id: this.#id++, + exprKind: { + case: 'selectExpr', + value: { + operand, + field: id, + }, + }, + }); + }; + + override visitPrimaryExpr = (ctx: PrimaryExprContext): Expr => { + this._checkNotNil(ctx); + if (isNil(ctx.primary())) { + return this._ensureErrorsExist( + create(StatusSchema, { + code: 1, + message: 'no primary expr context', + }) + ); + } + return this.visit(ctx.primary()); + }; + + override visitIndex = (ctx: IndexContext): Expr => { + this._checkNotNil(ctx); + if (isNil(ctx.member()) || isNil(ctx._index)) { + return this._ensureErrorsExist( + create(StatusSchema, { + code: 1, + message: 'no index context', + }) + ); + } + const target = this.visit(ctx.member()); + const id = this.#id++; + const index = this.visit(ctx._index); + let operatorIndex = INDEX_OPERATOR; + if (!isNil(ctx._op) && ctx._op.text === '?') { + if (!this.options?.enableOptionalSyntax) { + return this._reportError(ctx, "unsupported syntax '[?'"); + } + operatorIndex = OPT_INDEX_OPERATOR; + } + return create(ExprSchema, { + id, + exprKind: { + case: 'callExpr', + value: { + function: operatorIndex, + args: [target, index], + }, + }, + }); + }; + + override visitIdentOrGlobalCall = (ctx: IdentOrGlobalCallContext): Expr => { + this._checkNotNil(ctx); + if (isNil(ctx._id)) { + return this._reportError(ctx, 'no identifier context'); + } + let id = ctx._id.text; + if (RESERVED_IDS.has(id)) { + return this._reportError(ctx, `reserved identifier: ${id}`); + } + if (!isNil(ctx._leadingDot)) { + id = `.${id}`; + } + if (isNil(ctx._op)) { + return create(ExprSchema, { + id: this.#id++, + exprKind: { + case: 'identExpr', + value: { + name: id, + }, + }, + }); + } + return this._globalCallOrMacro(ctx, id); + }; + + // override visitNested = (ctx: NestedContext): Expr => { + // // Implementation logic here + // }; + + // override visitCreateList = (ctx: CreateListContext): Expr => { + // // Implementation logic here + // }; + + // override visitCreateStruct = (ctx: CreateStructContext): Expr => { + // // Implementation logic here + // }; + + override visitCreateMessage = (ctx: CreateMessageContext): Expr => { + this._checkNotNil(ctx); + let messageName = ''; + for (const id of ctx._ids) { + if (messageName.length !== 0) { + messageName += '.'; + } + messageName += id.text; + } + if (!isNil(ctx._leadingDot)) { + messageName = `.${messageName}`; + } + const id = this.#id++; + let entries: Expr_CreateStruct_Entry[] = []; + if (!isNil(ctx._entries)) { + const initializer = this.visit(ctx._entries); + const entriesInitializer = initializer.exprKind + .value as Expr_CreateStruct; + entries = entriesInitializer.entries; + } + return create(ExprSchema, { + id, + exprKind: { + case: 'structExpr', + value: { + messageName, + entries, + }, + }, + }); + }; + + override visitConstantLiteral = (ctx: ConstantLiteralContext): Expr => { + this._checkNotNil(ctx); + const expr = this.visit(ctx.literal()); + if (isNil(expr)) { + return this._ensureErrorsExist( + create(StatusSchema, { + code: 1, + message: 'no literal context', + }) + ); + } + if (expr.exprKind.case !== 'constExpr') { + return this._ensureErrorsExist( + create(StatusSchema, { + code: 1, + message: 'no constant context', + }) + ); + } + return create(ExprSchema, { + id: this.#id++, + exprKind: { + case: 'constExpr', + value: expr.exprKind.value, + }, + }); + }; + + override visitExprList = (ctx: ExprListContext): Expr => { + this._checkNotNil(ctx); + return create(ExprSchema, { + id: this.#id++, + exprKind: { + case: 'listExpr', + value: { + elements: this.visitSlice(ctx.expr_list()), + }, + }, + }); + }; + + override visitListInit = (ctx: ListInitContext): Expr => { + this._checkNotNil(ctx); + const elements = ctx._elems; + const result: Expr[] = []; + const optionals: number[] = []; + for (let i = 0; i < elements.length; i++) { + const ex = this.visit(elements[i]._e); + if (isNil(ex)) { + return create(ExprSchema, { + id: this.#id++, + exprKind: { + case: 'listExpr', + value: { + elements: [], + optionalIndices: [], + }, + }, + }); + } + result.push(ex); + if (elements[i]._opt != null) { + if (!this.options?.enableOptionalSyntax) { + this._reportError(elements[i], "unsupported syntax '?'"); + continue; + } + optionals.push(i); + } + } + return create(ExprSchema, { + id: this.#id++, + exprKind: { + case: 'listExpr', + value: { + elements: result, + optionalIndices: optionals, + }, + }, + }); + }; + + override visitFieldInitializerList = ( + ctx: FieldInitializerListContext + ): Expr => { + this._checkNotNil(ctx); + const fields: Expr_CreateStruct_Entry[] = []; + for (let i = 0; i < ctx._fields.length; i++) { + if (i >= ctx._values.length || i >= ctx._fields.length) { + return this._ensureErrorsExist( + create(StatusSchema, { + code: 1, + message: 'no field initializer list', + }) + ); + } + const field = ctx._fields[i]; + const exprId = this.#id++; + const optionalEntry = !isNil(field._opt); + const id = field.IDENTIFIER(); + if (isNil(id)) { + return this._ensureErrorsExist( + create(StatusSchema, { + code: 1, + message: 'no field identifier', + }) + ); + } + fields.push( + create(Expr_CreateStruct_EntrySchema, { + id: exprId, + keyKind: { + case: 'fieldKey', + value: id.getText(), + }, + value: this.visit(ctx._values[i]), + optionalEntry, + }) + ); + } + return create(ExprSchema, { + id: this.#id++, + exprKind: { + case: 'structExpr', + value: { + entries: fields, + }, + }, + }); + }; + + // override visitOptField = (ctx: OptFieldContext): Expr => { + // // Implementation logic here + // }; + + // override visitMapInitializerList = (ctx: MapInitializerListContext): Expr => { + // // Implementation logic here + // }; + + // override visitOptExpr = (ctx: OptExprContext): Expr => { + // // Implementation logic here + // }; + + override visitInt = (ctx: IntContext): Expr => { + this._checkNotNil(ctx); + const constant = parseIntConstant(ctx.getText()); + // TODO: parse error handling + return create(ExprSchema, { + id: this.#id++, + exprKind: { + case: 'constExpr', + value: constant, + }, + }); + }; + + override visitUint = (ctx: UintContext): Expr => { + this._checkNotNil(ctx); + const constant = parseUintConstant(ctx.getText()); + // TODO: parse error handling + return create(ExprSchema, { + id: this.#id++, + exprKind: { + case: 'constExpr', + value: constant, + }, + }); + }; + + override visitDouble = (ctx: DoubleContext): Expr => { + this._checkNotNil(ctx); + const constant = parseDoubleConstant(ctx.getText()); + // TODO: parse error handling + return create(ExprSchema, { + id: this.#id++, + exprKind: { + case: 'constExpr', + value: constant, + }, + }); + }; + + override visitString = (ctx: StringContext): Expr => { + this._checkNotNil(ctx); + const constant = parseStringConstant(ctx.getText()); + // TODO: parse error handling + return create(ExprSchema, { + id: this.#id++, + exprKind: { + case: 'constExpr', + value: constant, + }, + }); + }; + + override visitBytes = (ctx: BytesContext): Expr => { + this._checkNotNil(ctx); + const constant = parseBytesConstant(ctx.getText()); + // TODO: parse error handling + return create(ExprSchema, { + id: this.#id++, + exprKind: { + case: 'constExpr', + value: constant, + }, + }); + }; + + override visitBoolTrue = (ctx: BoolTrueContext): Expr => { + this._checkNotNil(ctx); + assert(ctx.getText() === 'true', new ParseException('true expected', 0)); + return create(ExprSchema, { + id: this.#id++, + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'boolValue', + value: true, + }, + }, + }, + }); + }; + + override visitBoolFalse = (ctx: BoolFalseContext): Expr => { + this._checkNotNil(ctx); + assert(ctx.getText() === 'false', new ParseException('false expected', 0)); + return create(ExprSchema, { + id: this.#id++, + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'boolValue', + value: false, + }, + }, + }, + }); + }; + + override visitNull = (ctx: NullContext): Expr => { + this._checkNotNil(ctx); + assert(ctx.getText() === 'null', new ParseException('null expected', 0)); + return create(ExprSchema, { + id: this.#id++, + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'nullValue', + value: NullValue.NULL_VALUE, + }, + }, + }, + }); + }; + + visitSlice = (expressions: ExprContext[]): Expr[] => { + if (isNil(expressions) || expressions.length === 0) { + return []; + } + return expressions.map((e) => this.visit(e)); + }; + + private _checkNotNil(value: unknown, message?: string): asserts value { + if (isNil(value)) { + throw new NullException(message || 'value is nil'); + } + } + + private _ensureErrorsExist(status: Status) { + this.errors.errors.push(status); + return create(ExprSchema, { + id: this.#id++, + exprKind: { + case: 'constExpr', + value: this.#ERROR, + }, + }); + } + + private _reportError(context: ParserRuleContext, message: string) { + return this._ensureErrorsExist( + create(StatusSchema, { + code: 1, + message, + details: [ + anyPack( + StringValueSchema, + fromJson(StringValueSchema, JSON.stringify(context, null, 2)) + ), + ], + }) + ); + } + + private _unnest(tree: ParseTree) { + while (tree != null) { + if (tree instanceof ExprContext) { + // conditionalOr op='?' conditionalOr : expr + if (tree._op != null) { + return tree; + } + // conditionalOr + tree = tree._e; + } else if (tree instanceof ConditionalOrContext) { + // conditionalAnd (ops=|| conditionalAnd)* + if (tree._ops != null && tree._ops.length > 0) { + return tree; + } + // conditionalAnd + tree = (tree as ConditionalOrContext)._e; + } else if (tree instanceof ConditionalAndContext) { + // relation (ops=&& relation)* + if (tree._ops != null && tree._ops.length > -1) { + return tree; + } + + // relation + tree = tree._e; + } else if (tree instanceof RelationContext) { + // relation op relation + if (tree._op != null) { + return tree; + } + // calc + tree = tree.calc(); + } else if (tree instanceof CalcContext) { + // calc op calc + if (tree._op != null) { + return tree; + } + + // unary + tree = tree.unary(); + } else if (tree instanceof MemberExprContext) { + // member expands to one of: primary, select, index, or create message + tree = tree.member(); + } else if (tree instanceof PrimaryExprContext) { + // primary expands to one of identifier, nested, create list, create struct, literal + tree = tree.primary(); + } else if (tree instanceof NestedContext) { + // contains a nested 'expr' + tree = tree._e; + } else if (tree instanceof ConstantLiteralContext) { + // expands to a primitive literal + tree = tree.literal(); + } else { + return tree; + } + } + + return tree; + } + + private _receiverCallOrMacro( + ctx: MemberCallContext, + id: string, + member: Expr + ) { + return this._macroOrCall(ctx._args, ctx._open, id, member, true); + } + + private _globalCallOrMacro(ctx: IdentOrGlobalCallContext, id: string) { + return this._macroOrCall(ctx._args, ctx._op, id, undefined, false); + } + + private _macroOrCall( + args: ExprListContext, + open: Token, + id: string, + member?: Expr, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + isReceiverStyle?: boolean + ) { + const macro = findMacro(id); + const _arguments = + args != null + ? this.visitExprList(args) + : create(ExprSchema, { + id: this.#id++, + exprKind: { + case: 'listExpr', + value: { + elements: [], + }, + }, + }); + const _args = + _arguments.exprKind.case === 'listExpr' + ? _arguments.exprKind.value.elements + : []; + if (macro) { + return expandMacro(macro, member as Expr, _args); + } + + return create(ExprSchema, { + id: this.#id++, + exprKind: { + case: 'callExpr', + value: { + function: id, + args: _args, + target: member, + }, + }, + }); + } +} diff --git a/packages/cel/tsconfig.json b/packages/cel/tsconfig.json new file mode 100644 index 0000000..f5b8565 --- /dev/null +++ b/packages/cel/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "module": "commonjs", + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/packages/cel/tsconfig.lib.json b/packages/cel/tsconfig.lib.json new file mode 100644 index 0000000..56bc5e5 --- /dev/null +++ b/packages/cel/tsconfig.lib.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "declaration": true, + "types": ["node", "vite/client"] + }, + "include": ["src/**/*.ts"], + "exclude": ["vite.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] +} diff --git a/packages/cel/tsconfig.spec.json b/packages/cel/tsconfig.spec.json new file mode 100644 index 0000000..3c002c2 --- /dev/null +++ b/packages/cel/tsconfig.spec.json @@ -0,0 +1,26 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": [ + "vitest/globals", + "vitest/importMeta", + "vite/client", + "node", + "vitest" + ] + }, + "include": [ + "vite.config.ts", + "vitest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.test.tsx", + "src/**/*.spec.tsx", + "src/**/*.test.js", + "src/**/*.spec.js", + "src/**/*.test.jsx", + "src/**/*.spec.jsx", + "src/**/*.d.ts" + ] +} diff --git a/packages/cel/vite.config.ts b/packages/cel/vite.config.ts new file mode 100644 index 0000000..9c44967 --- /dev/null +++ b/packages/cel/vite.config.ts @@ -0,0 +1,62 @@ +/// +import { defineConfig } from 'vite'; +import dts from 'vite-plugin-dts'; +import * as path from 'path'; +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; +import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin'; + +export default defineConfig({ + root: __dirname, + cacheDir: '../../node_modules/.vite/packages/cel', + + plugins: [ + nxViteTsPaths(), + nxCopyAssetsPlugin(['*.md']), + dts({ + entryRoot: 'src', + tsconfigPath: path.join(__dirname, 'tsconfig.lib.json'), + }), + ], + + // Uncomment this if you are using workers. + // worker: { + // plugins: [ nxViteTsPaths() ], + // }, + + // Configuration for building your library. + // See: https://vitejs.dev/guide/build.html#library-mode + build: { + outDir: '../../dist/packages/cel', + emptyOutDir: true, + reportCompressedSize: true, + commonjsOptions: { + transformMixedEsModules: true, + }, + lib: { + // Could also be a dictionary or array of multiple entry points. + entry: 'src/index.ts', + name: 'cel', + fileName: 'index', + // Change this to the formats you want to support. + // Don't forget to update your package.json as well. + formats: ['es', 'cjs'], + }, + rollupOptions: { + // External packages that should not be bundled into your library. + external: [], + }, + }, + + test: { + watch: false, + globals: true, + environment: 'node', + include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], + + reporters: ['default'], + coverage: { + reportsDirectory: '../../coverage/packages/cel', + provider: 'v8', + }, + }, +}); diff --git a/project.json b/project.json new file mode 100644 index 0000000..15798f5 --- /dev/null +++ b/project.json @@ -0,0 +1,14 @@ +{ + "name": "bearclaw", + "$schema": "node_modules/nx/schemas/project-schema.json", + "targets": { + "local-registry": { + "executor": "@nx/js:verdaccio", + "options": { + "port": 4873, + "config": ".verdaccio/config.yml", + "storage": "tmp/local-registry/storage" + } + } + } +} diff --git a/tsconfig.base.json b/tsconfig.base.json index 5b7245d..aec497e 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -16,6 +16,7 @@ "skipDefaultLibCheck": true, "baseUrl": ".", "paths": { + "@bearclaw/cel": ["packages/cel/src/index.ts"], "@bearclaw/collections": ["packages/collections/src/index.ts"], "@bearclaw/immutable-class": ["packages/immutable-class/src/index.ts"], "@bearclaw/is": ["packages/is/src/index.ts"] diff --git a/vitest.workspace.ts b/vitest.workspace.ts new file mode 100644 index 0000000..3c983a2 --- /dev/null +++ b/vitest.workspace.ts @@ -0,0 +1 @@ +export default ['**/*/vite.config.ts', '**/*/vitest.config.ts']; From a14883444c36cc3eb8aebe81eed517cd3f4fe5d7 Mon Sep 17 00:00:00 2001 From: jafaircl Date: Thu, 26 Sep 2024 21:42:12 -0400 Subject: [PATCH 02/34] feat(cel): implement createList and createStruct --- packages/cel/src/lib/balancer.ts | 61 ----------- packages/cel/src/lib/visitor.spec.ts | 147 +++++++++++++++++++++++++++ packages/cel/src/lib/visitor.ts | 106 +++++++++++++++++-- 3 files changed, 244 insertions(+), 70 deletions(-) delete mode 100644 packages/cel/src/lib/balancer.ts diff --git a/packages/cel/src/lib/balancer.ts b/packages/cel/src/lib/balancer.ts deleted file mode 100644 index 5b9f0f4..0000000 --- a/packages/cel/src/lib/balancer.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { - Expr, - ExprSchema, -} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; -import { create } from '@bufbuild/protobuf'; - -export class ExpressionBalancer { - private readonly fn!: string; - private readonly terms!: Expr[]; - private readonly ids!: bigint[]; - - constructor(fn: string, expr: Expr) { - if (!fn || fn.trim() === '') { - throw new Error('Function cannot be null or empty'); - } - - this.fn = fn; - this.terms = [expr]; - this.ids = []; - } - - add(operationId: bigint, expr: Expr): void { - if (!expr) { - throw new Error('Expression cannot be null'); - } - - if (operationId <= 0) { - throw new Error('OperationId must be greater than 0'); - } - - this.terms.push(expr); - this.ids.push(operationId); - } - - balance(): Expr { - if (this.terms.length <= 1) { - throw new Error('At least two expressions are required to balance'); - } - - return this.balanceRecursive(0, this.ids.length - 1); - } - - private balanceRecursive(lo: number, hi: number): Expr { - const mid = Math.floor((lo + hi + 1) / 2); - const left = - mid === lo ? this.terms[mid] : this.balanceRecursive(lo, mid - 1); - const right = - mid === hi ? this.terms[mid + 1] : this.balanceRecursive(mid + 1, hi); - - return create(ExprSchema, { - id: BigInt(this.ids[mid]), - exprKind: { - case: 'callExpr', - value: { - function: this.fn, - args: [left, right], - }, - }, - }); - } -} diff --git a/packages/cel/src/lib/visitor.spec.ts b/packages/cel/src/lib/visitor.spec.ts index bf9fdd1..21340b3 100644 --- a/packages/cel/src/lib/visitor.spec.ts +++ b/packages/cel/src/lib/visitor.spec.ts @@ -1444,6 +1444,153 @@ const testCases: TestInfo[] = [ }, }), }, + { + I: `{}`, + // P: `{}^#1:*expr.Expr_StructExpr#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'structExpr', + value: { + messageName: '', + entries: [], + }, + }, + }), + }, + { + I: `{a:b, c:d}`, + // P: `{ + // a^#3:*expr.Expr_IdentExpr#:b^#4:*expr.Expr_IdentExpr#^#2:*expr.Expr_CreateStruct_Entry#, + // c^#6:*expr.Expr_IdentExpr#:d^#7:*expr.Expr_IdentExpr#^#5:*expr.Expr_CreateStruct_Entry# + // }^#1:*expr.Expr_StructExpr#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'structExpr', + value: { + messageName: '', + entries: [ + { + id: BigInt(2), + keyKind: { + case: 'mapKey', + value: { + id: BigInt(3), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + }, + value: { + id: BigInt(4), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }, + }, + { + id: BigInt(5), + keyKind: { + case: 'mapKey', + value: { + id: BigInt(6), + exprKind: { + case: 'identExpr', + value: { name: 'c' }, + }, + }, + }, + value: { + id: BigInt(7), + exprKind: { + case: 'identExpr', + value: { name: 'd' }, + }, + }, + }, + ], + }, + }, + }), + }, + { + I: `[]`, + // P: `[]^#1:*expr.Expr_ListExpr#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'listExpr', + value: { + elements: [], + }, + }, + }), + }, + { + I: `[a]`, + // P: `[ + // a^#2:*expr.Expr_IdentExpr# + // ]^#1:*expr.Expr_ListExpr#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'listExpr', + value: { + elements: [ + { + id: BigInt(2), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + ], + }, + }, + }), + }, + { + I: `[a, b, c]`, + // P: `[ + // a^#2:*expr.Expr_IdentExpr#, + // b^#3:*expr.Expr_IdentExpr#, + // c^#4:*expr.Expr_IdentExpr# + // ]^#1:*expr.Expr_ListExpr#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'listExpr', + value: { + elements: [ + { + id: BigInt(2), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }, + { + id: BigInt(4), + exprKind: { + case: 'identExpr', + value: { name: 'c' }, + }, + }, + ], + }, + }, + }), + }, ]; describe('CELVisitor', () => { diff --git a/packages/cel/src/lib/visitor.ts b/packages/cel/src/lib/visitor.ts index ac7e1ee..33091c5 100644 --- a/packages/cel/src/lib/visitor.ts +++ b/packages/cel/src/lib/visitor.ts @@ -34,7 +34,9 @@ import { ConditionalAndContext, ConditionalOrContext, ConstantLiteralContext, + CreateListContext, CreateMessageContext, + CreateStructContext, DoubleContext, ExprContext, ExprListContext, @@ -44,6 +46,7 @@ import { IntContext, ListInitContext, LogicalNotContext, + MapInitializerListContext, MemberCallContext, MemberExprContext, NegateContext, @@ -463,13 +466,62 @@ export class CELVisitor extends GeneratedCelVisitor { // // Implementation logic here // }; - // override visitCreateList = (ctx: CreateListContext): Expr => { - // // Implementation logic here - // }; + override visitCreateList = (ctx: CreateListContext): Expr => { + this._checkNotNil(ctx); + const listId = this.#id++; + let elements: Expr[] = []; + let optionalIndices: number[] = []; + if (!isNil(ctx._elems)) { + const listInit = this.visit(ctx._elems); + if (listInit.exprKind.case !== 'listExpr') { + return this._ensureErrorsExist( + create(StatusSchema, { + code: 1, + message: 'no list initializer', + }) + ); + } + elements = listInit.exprKind.value.elements; + optionalIndices = listInit.exprKind.value.optionalIndices; + } + return create(ExprSchema, { + id: listId, + exprKind: { + case: 'listExpr', + value: { + elements, + optionalIndices, + }, + }, + }); + }; - // override visitCreateStruct = (ctx: CreateStructContext): Expr => { - // // Implementation logic here - // }; + override visitCreateStruct = (ctx: CreateStructContext): Expr => { + this._checkNotNil(ctx); + const structId = this.#id++; + let entries: Expr_CreateStruct_Entry[] = []; + if (!isNil(ctx._entries)) { + const mapInit = this.visit(ctx._entries); + if (mapInit.exprKind.case !== 'structExpr') { + return this._ensureErrorsExist( + create(StatusSchema, { + code: 1, + message: 'no struct initializer', + }) + ); + } + entries = mapInit.exprKind.value.entries; + } + return create(ExprSchema, { + id: structId, + exprKind: { + case: 'structExpr', + value: { + entries, + }, + }, + }); + }; override visitCreateMessage = (ctx: CreateMessageContext): Expr => { this._checkNotNil(ctx); @@ -637,9 +689,45 @@ export class CELVisitor extends GeneratedCelVisitor { // // Implementation logic here // }; - // override visitMapInitializerList = (ctx: MapInitializerListContext): Expr => { - // // Implementation logic here - // }; + override visitMapInitializerList = (ctx: MapInitializerListContext): Expr => { + this._checkNotNil(ctx); + const fields: Expr_CreateStruct_Entry[] = []; + for (let i = 0; i < ctx._cols.length; i++) { + if (i >= ctx._values.length || i >= ctx._cols.length) { + return this._ensureErrorsExist( + create(StatusSchema, { + code: 1, + message: 'no field initializer list', + }) + ); + } + const colId = this.#id++; + const optKey = ctx._keys[i]; + const optionalKey = !isNil(optKey._opt); + const key = this.visit(optKey._e); + const value = this.visit(ctx._values[i]); + fields.push( + create(Expr_CreateStruct_EntrySchema, { + id: colId, + keyKind: { + case: 'mapKey', + value: key, + }, + value, + optionalEntry: optionalKey, + }) + ); + } + return create(ExprSchema, { + id: this.#id++, + exprKind: { + case: 'structExpr', + value: { + entries: fields, + }, + }, + }); + }; // override visitOptExpr = (ctx: OptExprContext): Expr => { // // Implementation logic here From c09e44ca0b26b20303a401b8fd4c47274adc072f Mon Sep 17 00:00:00 2001 From: jafaircl Date: Sun, 29 Sep 2024 13:02:04 -0400 Subject: [PATCH 03/34] feat(cel): port cel-go macro tests --- packages/cel/src/lib/environment.ts | 19 +- packages/cel/src/lib/macros.ts | 133 ++-- packages/cel/src/lib/program.ts | 5 + packages/cel/src/lib/utils.ts | 53 +- packages/cel/src/lib/visitor.spec.ts | 1022 +++++++++++++++++++++++++- packages/cel/src/lib/visitor.ts | 124 ++-- 6 files changed, 1230 insertions(+), 126 deletions(-) diff --git a/packages/cel/src/lib/environment.ts b/packages/cel/src/lib/environment.ts index 8b09d8b..a05db28 100644 --- a/packages/cel/src/lib/environment.ts +++ b/packages/cel/src/lib/environment.ts @@ -30,16 +30,20 @@ export class CELEnvironment { } compile(input: string, check = false): StartContext { - const chars = new CharStream(input); - const lexer = new CELLexer(chars); - const tokens = new CommonTokenStream(lexer); - const parser = new CELParser(tokens); + const parser = this._getParser(input); const tree = parser.start(); if (tree.exception) throw tree.exception; if (check) this.check(tree); return tree; } + astAsString(input: string) { + const parser = this._getParser(input); + const tree = parser.start(); + if (tree.exception) throw tree.exception; + return tree.toStringTree(parser.ruleNames, parser); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars check(ast: StartContext) { // TODO: implement @@ -66,4 +70,11 @@ export class CELEnvironment { this.addDescriptor(descriptor); } } + + private _getParser(input: string) { + const chars = new CharStream(input); + const lexer = new CELLexer(chars); + const tokens = new CommonTokenStream(lexer); + return new CELParser(tokens); + } } diff --git a/packages/cel/src/lib/macros.ts b/packages/cel/src/lib/macros.ts index e622dd4..5fb22fe 100644 --- a/packages/cel/src/lib/macros.ts +++ b/packages/cel/src/lib/macros.ts @@ -21,7 +21,14 @@ import { MAP_MACRO, NOT_STRICTLY_FALSE_OPERATOR, } from './operators'; -import { boolExpr, globalCall, identExpr, int64Expr, listExpr } from './utils'; +import { + IdHelper, + boolExpr, + globalCall, + identExpr, + int64Expr, + listExpr, +} from './utils'; export const STANDARD_MACROS = new Set([ HAS_MACRO, @@ -37,31 +44,37 @@ export function findMacro(name: string) { return STANDARD_MACROS.has(name) ? name : undefined; } -export function expandMacro(op: string, target: Expr, args: Expr[]): Expr { +export function expandMacro( + id: IdHelper, + op: string, + target: Expr, + args: Expr[] +): Expr { switch (op) { case HAS_MACRO: - return expandHasMacro(target, args); + return expandHasMacro(id, args); case ALL_MACRO: - return expandAllMacro(target, args); + return expandAllMacro(id, target, args); case EXISTS_MACRO: - return expandExistsMacro(target, args); + return expandExistsMacro(id, target, args); case EXISTS_ONE_MACRO: - return expandExistsOneMacro(target, args); + return expandExistsOneMacro(id, target, args); case MAP_MACRO: - return expandMapMacro(target, args); + return expandMapMacro(id, target, args); case FILTER_MACRO: - return expandFilterMacro(target, args); + return expandFilterMacro(id, target, args); default: throw new Error(`Unknown macro: ${op}`); } } -export function expandHasMacro(target: Expr, args: Expr[]): Expr { +export function expandHasMacro(id: IdHelper, args: Expr[]): Expr { const arg = args[0]; if (arg.exprKind.case !== 'selectExpr') { throw new Error('Invalid argument to has() macro'); } return create(ExprSchema, { + id: id.nextId(), exprKind: { case: 'selectExpr', value: create(Expr_SelectSchema, { @@ -73,24 +86,27 @@ export function expandHasMacro(target: Expr, args: Expr[]): Expr { }); } -export function expandAllMacro(target: Expr, args: Expr[]): Expr { +export function expandAllMacro(id: IdHelper, target: Expr, args: Expr[]): Expr { const arg0 = args[0]; if (arg0.exprKind.case !== 'identExpr') { throw new Error('Invalid argument to all() macro'); } const arg1 = args[1]; - const accuInit = boolExpr(true); + const accuInit = boolExpr(id, true); const condition = globalCall( + id, NOT_STRICTLY_FALSE_OPERATOR, - identExpr(ACCUMULATOR_VAR) + identExpr(id, ACCUMULATOR_VAR) ); const step = globalCall( + id, LOGICAL_AND_OPERATOR, - identExpr(ACCUMULATOR_VAR), + identExpr(id, ACCUMULATOR_VAR), arg1 ); - const result = identExpr(ACCUMULATOR_VAR); + const result = identExpr(id, ACCUMULATOR_VAR); return fold( + id, arg0.exprKind.value.name, target, ACCUMULATOR_VAR, @@ -101,24 +117,31 @@ export function expandAllMacro(target: Expr, args: Expr[]): Expr { ); } -export function expandExistsMacro(target: Expr, args: Expr[]): Expr { +export function expandExistsMacro( + id: IdHelper, + target: Expr, + args: Expr[] +): Expr { const arg0 = args[0]; if (arg0.exprKind.case !== 'identExpr') { - throw new Error('Invalid argument to all() macro'); + throw new Error('Invalid argument to exists() macro'); } const arg1 = args[1]; - const accuInit = boolExpr(false); + const accuInit = boolExpr(id, false); const condition = globalCall( + id, NOT_STRICTLY_FALSE_OPERATOR, - globalCall(LOGICAL_NOT_OPERATOR, identExpr(ACCUMULATOR_VAR)) + globalCall(id, LOGICAL_NOT_OPERATOR, identExpr(id, ACCUMULATOR_VAR)) ); const step = globalCall( + id, LOGICAL_OR_OPERATOR, - identExpr(ACCUMULATOR_VAR), + identExpr(id, ACCUMULATOR_VAR), arg1 ); - const result = identExpr(ACCUMULATOR_VAR); + const result = identExpr(id, ACCUMULATOR_VAR); return fold( + id, arg0.exprKind.value.name, target, ACCUMULATOR_VAR, @@ -129,28 +152,38 @@ export function expandExistsMacro(target: Expr, args: Expr[]): Expr { ); } -export function expandExistsOneMacro(target: Expr, args: Expr[]): Expr { +export function expandExistsOneMacro( + id: IdHelper, + target: Expr, + args: Expr[] +): Expr { const arg0 = args[0]; if (arg0.exprKind.case !== 'identExpr') { - throw new Error('Invalid argument to all() macro'); + throw new Error('Invalid argument to exists_one() macro'); } const arg1 = args[1]; - const zeroExpr = int64Expr(BigInt(0)); - const oneExpr = int64Expr(BigInt(1)); - const accuInit = zeroExpr; - const condition = boolExpr(true); + const accuInit = int64Expr(id, BigInt(0)); + const condition = boolExpr(id, true); const step = globalCall( + id, CONDITIONAL_OPERATOR, arg1, - globalCall(ADD_OPERATOR, identExpr(ACCUMULATOR_VAR), oneExpr), - identExpr(ACCUMULATOR_VAR) + globalCall( + id, + ADD_OPERATOR, + identExpr(id, ACCUMULATOR_VAR), + int64Expr(id, BigInt(1)) + ), + identExpr(id, ACCUMULATOR_VAR) ); const result = globalCall( + id, EQUALS_OPERATOR, - identExpr(ACCUMULATOR_VAR), - oneExpr + identExpr(id, ACCUMULATOR_VAR), + int64Expr(id, BigInt(1)) ); return fold( + id, arg0.exprKind.value.name, target, ACCUMULATOR_VAR, @@ -161,7 +194,7 @@ export function expandExistsOneMacro(target: Expr, args: Expr[]): Expr { ); } -export function expandMapMacro(target: Expr, args: Expr[]): Expr { +export function expandMapMacro(id: IdHelper, target: Expr, args: Expr[]): Expr { const arg0 = args[0]; if (arg0.exprKind.case !== 'identExpr') { throw new Error('Invalid argument to map() macro'); @@ -175,63 +208,74 @@ export function expandMapMacro(target: Expr, args: Expr[]): Expr { arg1 = args[1]; arg2 = null as unknown as Expr; } - const accuInit = listExpr([]); - const condition = boolExpr(true); + const accuInit = listExpr(id, []); + const condition = boolExpr(id, true); let step = globalCall( + id, ADD_OPERATOR, - identExpr(ACCUMULATOR_VAR), - listExpr([arg1]) + identExpr(id, ACCUMULATOR_VAR), + listExpr(id, [arg1]) ); if (!isNil(arg2)) { step = globalCall( + id, CONDITIONAL_OPERATOR, arg2, step, - identExpr(ACCUMULATOR_VAR) + identExpr(id, ACCUMULATOR_VAR) ); } return fold( + id, arg0.exprKind.value.name, target, ACCUMULATOR_VAR, accuInit, condition, step, - identExpr(ACCUMULATOR_VAR) + identExpr(id, ACCUMULATOR_VAR) ); } -export function expandFilterMacro(target: Expr, args: Expr[]): Expr { +export function expandFilterMacro( + id: IdHelper, + target: Expr, + args: Expr[] +): Expr { const arg0 = args[0]; if (arg0.exprKind.case !== 'identExpr') { throw new Error('Invalid argument to filter() macro'); } const arg1 = args[1]; - const accuInit = listExpr([]); - const condition = boolExpr(true); + const accuInit = listExpr(id, []); + const condition = boolExpr(id, true); let step = globalCall( + id, ADD_OPERATOR, - identExpr(ACCUMULATOR_VAR), - listExpr([arg0]) + identExpr(id, ACCUMULATOR_VAR), + listExpr(id, [arg0]) ); step = globalCall( + id, CONDITIONAL_OPERATOR, arg1, step, - identExpr(ACCUMULATOR_VAR) + identExpr(id, ACCUMULATOR_VAR) ); return fold( + id, arg0.exprKind.value.name, target, ACCUMULATOR_VAR, accuInit, condition, step, - identExpr(ACCUMULATOR_VAR) + identExpr(id, ACCUMULATOR_VAR) ); } function fold( + id: IdHelper, iterVar: string, iterRange: Expr, accuVar: string, @@ -241,6 +285,7 @@ function fold( result: Expr ): Expr { return create(ExprSchema, { + id: id.nextId(), exprKind: { case: 'comprehensionExpr', value: { diff --git a/packages/cel/src/lib/program.ts b/packages/cel/src/lib/program.ts index 968de9c..2b705b9 100644 --- a/packages/cel/src/lib/program.ts +++ b/packages/cel/src/lib/program.ts @@ -12,4 +12,9 @@ export class CELProgram { const parser = new CELVisitor(this.env); return this.ast.accept(parser); } + + errors() { + const parser = new CELVisitor(this.env); + return parser.errors; + } } diff --git a/packages/cel/src/lib/utils.ts b/packages/cel/src/lib/utils.ts index 02e81f1..e176795 100644 --- a/packages/cel/src/lib/utils.ts +++ b/packages/cel/src/lib/utils.ts @@ -7,11 +7,6 @@ import { import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; import { create } from '@bufbuild/protobuf'; import { NullValue } from '@bufbuild/protobuf/wkt'; -import { ParserRuleContext } from 'antlr4'; - -export function uniqueIdFromContext(ctx: ParserRuleContext) { - return BigInt(ctx.start.start); -} export function parseString(str: string) { const decoded = decodeURIComponent(str); @@ -48,10 +43,6 @@ export function parseInt64(str: string) { return BigInt(decoded); } -export function isNil(value: unknown): value is null | undefined { - return value === null || value === undefined; -} - export function boolConstant(value: boolean) { return create(ConstantSchema, { constantKind: { @@ -61,8 +52,9 @@ export function boolConstant(value: boolean) { }); } -export function boolExpr(value: boolean) { +export function boolExpr(id: IdHelper, value: boolean) { return create(ExprSchema, { + id: id.nextId(), exprKind: { case: 'constExpr', value: boolConstant(value), @@ -88,8 +80,9 @@ export function int64Constant(value: bigint) { }); } -export function int64Expr(value: bigint) { +export function int64Expr(id: IdHelper, value: bigint) { return create(ExprSchema, { + id: id.nextId(), exprKind: { case: 'constExpr', value: int64Constant(value), @@ -115,8 +108,9 @@ export function uint64Constant(value: bigint) { }); } -export function uint64Expr(value: bigint) { +export function uint64Expr(id: IdHelper, value: bigint) { return create(ExprSchema, { + id: id.nextId(), exprKind: { case: 'constExpr', value: uint64Constant(value), @@ -142,8 +136,9 @@ export function doubleConstant(value: number) { }); } -export function doubleExpr(value: number) { +export function doubleExpr(id: IdHelper, value: number) { return create(ExprSchema, { + id: id.nextId(), exprKind: { case: 'constExpr', value: doubleConstant(value), @@ -169,8 +164,9 @@ export function stringConstant(value: string) { }); } -export function stringExpr(value: string) { +export function stringExpr(id: IdHelper, value: string) { return create(ExprSchema, { + id: id.nextId(), exprKind: { case: 'constExpr', value: stringConstant(value), @@ -196,8 +192,9 @@ export function bytesConstant(value: Uint8Array) { }); } -export function bytesExpr(value: Uint8Array) { +export function bytesExpr(id: IdHelper, value: Uint8Array) { return create(ExprSchema, { + id: id.nextId(), exprKind: { case: 'constExpr', value: bytesConstant(value), @@ -222,6 +219,7 @@ export const NULL_CONSTANT = create(ConstantSchema, { }); export const NULL_EXPR = create(ExprSchema, { + // TODO: id exprKind: { case: 'constExpr', value: NULL_CONSTANT, @@ -235,8 +233,9 @@ export const NULL_VALUE = create(ValueSchema, { }, }); -export function identExpr(name: string) { +export function identExpr(id: IdHelper, name: string) { return create(ExprSchema, { + id: id.nextId(), exprKind: { case: 'identExpr', value: create(Expr_IdentSchema, { @@ -246,8 +245,13 @@ export function identExpr(name: string) { }); } -export function globalCall(functionName: string, ...args: Expr[]) { +export function globalCall( + id: IdHelper, + functionName: string, + ...args: Expr[] +) { return create(ExprSchema, { + id: id.nextId(), exprKind: { case: 'callExpr', value: { @@ -258,8 +262,9 @@ export function globalCall(functionName: string, ...args: Expr[]) { }); } -export function listExpr(exprs: Expr[]) { +export function listExpr(id: IdHelper, exprs: Expr[]) { return create(ExprSchema, { + id: id.nextId(), exprKind: { case: 'listExpr', value: { @@ -282,3 +287,15 @@ export function unquote(str: string) { } return str; } + +export class IdHelper { + #id = BigInt(1); + + public currentId() { + return this.#id; + } + + public nextId() { + return this.#id++; + } +} diff --git a/packages/cel/src/lib/visitor.spec.ts b/packages/cel/src/lib/visitor.spec.ts index 21340b3..6e0bcc6 100644 --- a/packages/cel/src/lib/visitor.spec.ts +++ b/packages/cel/src/lib/visitor.spec.ts @@ -3,7 +3,7 @@ import { Expr, ExprSchema, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; -import { create } from '@bufbuild/protobuf'; +import { create, toJsonString } from '@bufbuild/protobuf'; import { NullValue } from '@bufbuild/protobuf/wkt'; import { CELEnvironment } from './environment'; import { CELProgram } from './program'; @@ -22,7 +22,7 @@ interface TestInfo { L?: string; // M contains the expected adorned debug output of the macro calls map - M?: string; + M?: Expr | any; // Opts contains the list of options to be configured with the parser before parsing the expression. Opts?: unknown[]; @@ -1591,6 +1591,993 @@ const testCases: TestInfo[] = [ }, }), }, + { + I: `(a)`, + // P: `a^#1:*expr.Expr_IdentExpr#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }), + }, + { + I: `((a))`, + // P: `a^#1:*expr.Expr_IdentExpr#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }), + }, + { + I: `a()`, + // P: `a()^#1:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'callExpr', + value: { + function: 'a', + args: [], + }, + }, + }), + }, + { + I: `a(b)`, + // P: `a( + // b^#2:*expr.Expr_IdentExpr# + // )^#1:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'callExpr', + value: { + function: 'a', + args: [ + { + id: BigInt(2), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }, + ], + }, + }, + }), + }, + { + I: `a(b, c)`, + // P: `a( + // b^#2:*expr.Expr_IdentExpr#, + // c^#3:*expr.Expr_IdentExpr# + // )^#1:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'callExpr', + value: { + function: 'a', + args: [ + { + id: BigInt(2), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'identExpr', + value: { name: 'c' }, + }, + }, + ], + }, + }, + }), + }, + { + I: `a.b()`, + // P: `a^#1:*expr.Expr_IdentExpr#.b()^#2:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: 'b', + target: { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + args: [], + }, + }, + }), + }, + { + I: `a.b(c)`, + // P: `a^#1:*expr.Expr_IdentExpr#.b( + // c^#3:*expr.Expr_IdentExpr# + // )^#2:*expr.Expr_CallExpr#`, + // L: `a^#1[1,0]#.b( + // c^#3[1,4]# + // )^#2[1,3]#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: 'b', + target: { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + args: [ + { + id: BigInt(3), + exprKind: { + case: 'identExpr', + value: { name: 'c' }, + }, + }, + ], + }, + }, + }), + }, + // TODO: Parse error tests + // // Parse error tests + // { + // I: `0xFFFFFFFFFFFFFFFFF`, + // E: `ERROR: :1:1: invalid int literal + // | 0xFFFFFFFFFFFFFFFFF + // | ^`, + // }, + // { + // I: `0xFFFFFFFFFFFFFFFFFu`, + // E: `ERROR: :1:1: invalid uint literal + // | 0xFFFFFFFFFFFFFFFFFu + // | ^`, + // }, + // { + // I: `1.99e90000009`, + // E: `ERROR: :1:1: invalid double literal + // | 1.99e90000009 + // | ^`, + // }, + // { + // I: `*@a | b`, + // E: `ERROR: :1:1: Syntax error: extraneous input '*' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} + // | *@a | b + // | ^ + // ERROR: :1:2: Syntax error: token recognition error at: '@' + // | *@a | b + // | .^ + // ERROR: :1:5: Syntax error: token recognition error at: '| ' + // | *@a | b + // | ....^ + // ERROR: :1:7: Syntax error: extraneous input 'b' expecting + // | *@a | b + // | ......^`, + // }, + // { + // I: `a | b`, + // E: `ERROR: :1:3: Syntax error: token recognition error at: '| ' + // | a | b + // | ..^ + // ERROR: :1:5: Syntax error: extraneous input 'b' expecting + // | a | b + // | ....^`, + // }, + // Macro tests + { + I: `has(m.f)`, + // P: `m^#2:*expr.Expr_IdentExpr#.f~test-only~^#4:*expr.Expr_SelectExpr#`, + // L: `m^#2[1,4]#.f~test-only~^#4[1,3]#`, + // M: `has( + // m^#2:*expr.Expr_IdentExpr#.f^#3:*expr.Expr_SelectExpr# + // )^#4:has#`, + P: create(ExprSchema, { + id: BigInt(4), + exprKind: { + case: 'selectExpr', + value: { + field: 'f', + operand: { + id: BigInt(2), + exprKind: { + case: 'identExpr', + value: { name: 'm' }, + }, + }, + testOnly: true, + }, + }, + }), + }, + { + I: `m.exists(v, f)`, + // P: `__comprehension__( + // // Variable + // v, + // // Target + // m^#1:*expr.Expr_IdentExpr#, + // // Accumulator + // __result__, + // // Init + // false^#5:*expr.Constant_BoolValue#, + // // LoopCondition + // @not_strictly_false( + // !_( + // __result__^#6:*expr.Expr_IdentExpr# + // )^#7:*expr.Expr_CallExpr# + // )^#8:*expr.Expr_CallExpr#, + // // LoopStep + // _||_( + // __result__^#9:*expr.Expr_IdentExpr#, + // f^#4:*expr.Expr_IdentExpr# + // )^#10:*expr.Expr_CallExpr#, + // // Result + // __result__^#11:*expr.Expr_IdentExpr#)^#12:*expr.Expr_ComprehensionExpr#`, + // M: `m^#1:*expr.Expr_IdentExpr#.exists( + // v^#3:*expr.Expr_IdentExpr#, + // f^#4:*expr.Expr_IdentExpr# + // )^#12:exists#`, + P: create(ExprSchema, { + id: BigInt(12), + exprKind: { + case: 'comprehensionExpr', + value: { + accuInit: { + id: BigInt(5), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'boolValue', + value: false, + }, + }, + }, + }, + accuVar: '__result__', + iterRange: { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'm' }, + }, + }, + iterVar: 'v', + iterVar2: '', + loopCondition: { + id: BigInt(8), + exprKind: { + case: 'callExpr', + value: { + function: '@not_strictly_false', + args: [ + { + id: BigInt(7), + exprKind: { + case: 'callExpr', + value: { + function: '!_', + args: [ + { + id: BigInt(6), + exprKind: { + case: 'identExpr', + value: { name: '__result__' }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + }, + loopStep: { + id: BigInt(10), + exprKind: { + case: 'callExpr', + value: { + function: '_||_', + args: [ + { + id: BigInt(9), + exprKind: { + case: 'identExpr', + value: { name: '__result__' }, + }, + }, + { + id: BigInt(4), + exprKind: { + case: 'identExpr', + value: { name: 'f' }, + }, + }, + ], + }, + }, + }, + result: { + id: BigInt(11), + exprKind: { + case: 'identExpr', + value: { name: '__result__' }, + }, + }, + }, + }, + }), + }, + + { + I: `m.all(v, f)`, + // P: `__comprehension__( + // // Variable + // v, + // // Target + // m^#1:*expr.Expr_IdentExpr#, + // // Accumulator + // __result__, + // // Init + // true^#5:*expr.Constant_BoolValue#, + // // LoopCondition + // @not_strictly_false( + // __result__^#6:*expr.Expr_IdentExpr# + // )^#7:*expr.Expr_CallExpr#, + // // LoopStep + // _&&_( + // __result__^#8:*expr.Expr_IdentExpr#, + // f^#4:*expr.Expr_IdentExpr# + // )^#9:*expr.Expr_CallExpr#, + // // Result + // __result__^#10:*expr.Expr_IdentExpr#)^#11:*expr.Expr_ComprehensionExpr#`, + // M: `m^#1:*expr.Expr_IdentExpr#.all( + // v^#3:*expr.Expr_IdentExpr#, + // f^#4:*expr.Expr_IdentExpr# + // )^#11:all#`, + P: create(ExprSchema, { + id: BigInt(11), + exprKind: { + case: 'comprehensionExpr', + value: { + accuInit: { + id: BigInt(5), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'boolValue', + value: true, + }, + }, + }, + }, + accuVar: '__result__', + iterRange: { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'm' }, + }, + }, + iterVar: 'v', + iterVar2: '', + loopCondition: { + id: BigInt(7), + exprKind: { + case: 'callExpr', + value: { + function: '@not_strictly_false', + args: [ + { + id: BigInt(6), + exprKind: { + case: 'identExpr', + value: { name: '__result__' }, + }, + }, + ], + }, + }, + }, + loopStep: { + id: BigInt(9), + exprKind: { + case: 'callExpr', + value: { + function: '_&&_', + args: [ + { + id: BigInt(8), + exprKind: { + case: 'identExpr', + value: { name: '__result__' }, + }, + }, + { + id: BigInt(4), + exprKind: { + case: 'identExpr', + value: { name: 'f' }, + }, + }, + ], + }, + }, + }, + result: { + id: BigInt(10), + exprKind: { + case: 'identExpr', + value: { name: '__result__' }, + }, + }, + }, + }, + }), + }, + { + I: `m.exists_one(v, f)`, + // P: `__comprehension__( + // // Variable + // v, + // // Target + // m^#1:*expr.Expr_IdentExpr#, + // // Accumulator + // __result__, + // // Init + // 0^#5:*expr.Constant_Int64Value#, + // // LoopCondition + // true^#6:*expr.Constant_BoolValue#, + // // LoopStep + // _?_:_( + // f^#4:*expr.Expr_IdentExpr#, + // _+_( + // __result__^#7:*expr.Expr_IdentExpr#, + // 1^#8:*expr.Constant_Int64Value# + // )^#9:*expr.Expr_CallExpr#, + // __result__^#10:*expr.Expr_IdentExpr# + // )^#11:*expr.Expr_CallExpr#, + // // Result + // _==_( + // __result__^#12:*expr.Expr_IdentExpr#, + // 1^#13:*expr.Constant_Int64Value# + // )^#14:*expr.Expr_CallExpr#)^#15:*expr.Expr_ComprehensionExpr#`, + // M: `m^#1:*expr.Expr_IdentExpr#.exists_one( + // v^#3:*expr.Expr_IdentExpr#, + // f^#4:*expr.Expr_IdentExpr# + // )^#15:exists_one#`, + P: create(ExprSchema, { + id: BigInt(15), + exprKind: { + case: 'comprehensionExpr', + value: { + accuInit: { + id: BigInt(5), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(0), + }, + }, + }, + }, + accuVar: '__result__', + iterRange: { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'm' }, + }, + }, + iterVar: 'v', + iterVar2: '', + loopCondition: { + id: BigInt(6), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'boolValue', + value: true, + }, + }, + }, + }, + loopStep: { + id: BigInt(11), + exprKind: { + case: 'callExpr', + value: { + function: '_?_:_', + args: [ + { + id: BigInt(4), + exprKind: { + case: 'identExpr', + value: { name: 'f' }, + }, + }, + { + id: BigInt(9), + exprKind: { + case: 'callExpr', + value: { + function: '_+_', + args: [ + { + id: BigInt(7), + exprKind: { + case: 'identExpr', + value: { name: '__result__' }, + }, + }, + { + id: BigInt(8), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }, + }, + }, + ], + }, + }, + }, + { + id: BigInt(10), + exprKind: { + case: 'identExpr', + value: { name: '__result__' }, + }, + }, + ], + }, + }, + }, + result: { + id: BigInt(14), + exprKind: { + case: 'callExpr', + value: { + function: '_==_', + args: [ + { + id: BigInt(12), + exprKind: { + case: 'identExpr', + value: { name: '__result__' }, + }, + }, + { + id: BigInt(13), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }, + }, + }, + ], + }, + }, + }, + }, + }, + }), + }, + { + I: `m.map(v, f)`, + // P: `__comprehension__( + // // Variable + // v, + // // Target + // m^#1:*expr.Expr_IdentExpr#, + // // Accumulator + // __result__, + // // Init + // []^#5:*expr.Expr_ListExpr#, + // // LoopCondition + // true^#6:*expr.Constant_BoolValue#, + // // LoopStep + // _+_( + // __result__^#7:*expr.Expr_IdentExpr#, + // [ + // f^#4:*expr.Expr_IdentExpr# + // ]^#8:*expr.Expr_ListExpr# + // )^#9:*expr.Expr_CallExpr#, + // // Result + // __result__^#10:*expr.Expr_IdentExpr#)^#11:*expr.Expr_ComprehensionExpr#`, + // M: `m^#1:*expr.Expr_IdentExpr#.map( + // v^#3:*expr.Expr_IdentExpr#, + // f^#4:*expr.Expr_IdentExpr# + // )^#11:map#`, + P: create(ExprSchema, { + id: BigInt(11), + exprKind: { + case: 'comprehensionExpr', + value: { + accuInit: { + id: BigInt(5), + exprKind: { + case: 'listExpr', + value: { + elements: [], + }, + }, + }, + accuVar: '__result__', + iterRange: { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'm' }, + }, + }, + iterVar: 'v', + iterVar2: '', + loopCondition: { + id: BigInt(6), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'boolValue', + value: true, + }, + }, + }, + }, + loopStep: { + id: BigInt(9), + exprKind: { + case: 'callExpr', + value: { + function: '_+_', + args: [ + { + id: BigInt(7), + exprKind: { + case: 'identExpr', + value: { name: '__result__' }, + }, + }, + { + id: BigInt(8), + exprKind: { + case: 'listExpr', + value: { + elements: [ + { + id: BigInt(4), + exprKind: { + case: 'identExpr', + value: { name: 'f' }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + }, + result: { + id: BigInt(10), + exprKind: { + case: 'identExpr', + value: { name: '__result__' }, + }, + }, + }, + }, + }), + }, + { + I: `m.map(v, p, f)`, + // P: `__comprehension__( + // // Variable + // v, + // // Target + // m^#1:*expr.Expr_IdentExpr#, + // // Accumulator + // __result__, + // // Init + // []^#6:*expr.Expr_ListExpr#, + // // LoopCondition + // true^#7:*expr.Constant_BoolValue#, + // // LoopStep + // _?_:_( + // p^#4:*expr.Expr_IdentExpr#, + // _+_( + // __result__^#8:*expr.Expr_IdentExpr#, + // [ + // f^#5:*expr.Expr_IdentExpr# + // ]^#9:*expr.Expr_ListExpr# + // )^#10:*expr.Expr_CallExpr#, + // __result__^#11:*expr.Expr_IdentExpr# + // )^#12:*expr.Expr_CallExpr#, + // // Result + // __result__^#13:*expr.Expr_IdentExpr#)^#14:*expr.Expr_ComprehensionExpr#`, + // M: `m^#1:*expr.Expr_IdentExpr#.map( + // v^#3:*expr.Expr_IdentExpr#, + // p^#4:*expr.Expr_IdentExpr#, + // f^#5:*expr.Expr_IdentExpr# + // )^#14:map#`, + P: create(ExprSchema, { + id: BigInt(14), + exprKind: { + case: 'comprehensionExpr', + value: { + accuInit: { + id: BigInt(6), + exprKind: { + case: 'listExpr', + value: { + elements: [], + }, + }, + }, + accuVar: '__result__', + iterRange: { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'm' }, + }, + }, + iterVar: 'v', + iterVar2: '', + loopCondition: { + id: BigInt(7), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'boolValue', + value: true, + }, + }, + }, + }, + loopStep: { + id: BigInt(12), + exprKind: { + case: 'callExpr', + value: { + function: '_?_:_', + args: [ + { + id: BigInt(4), + exprKind: { + case: 'identExpr', + value: { name: 'p' }, + }, + }, + { + id: BigInt(10), + exprKind: { + case: 'callExpr', + value: { + function: '_+_', + args: [ + { + id: BigInt(8), + exprKind: { + case: 'identExpr', + value: { name: '__result__' }, + }, + }, + { + id: BigInt(9), + exprKind: { + case: 'listExpr', + value: { + elements: [ + { + id: BigInt(5), + exprKind: { + case: 'identExpr', + value: { name: 'f' }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + }, + { + id: BigInt(11), + exprKind: { + case: 'identExpr', + value: { name: '__result__' }, + }, + }, + ], + }, + }, + }, + result: { + id: BigInt(13), + exprKind: { + case: 'identExpr', + value: { name: '__result__' }, + }, + }, + }, + }, + }), + }, + { + I: `m.filter(v, p)`, + // P: `__comprehension__( + // // Variable + // v, + // // Target + // m^#1:*expr.Expr_IdentExpr#, + // // Accumulator + // __result__, + // // Init + // []^#5:*expr.Expr_ListExpr#, + // // LoopCondition + // true^#6:*expr.Constant_BoolValue#, + // // LoopStep + // _?_:_( + // p^#4:*expr.Expr_IdentExpr#, + // _+_( + // __result__^#7:*expr.Expr_IdentExpr#, + // [ + // v^#3:*expr.Expr_IdentExpr# + // ]^#8:*expr.Expr_ListExpr# + // )^#9:*expr.Expr_CallExpr#, + // __result__^#10:*expr.Expr_IdentExpr# + // )^#11:*expr.Expr_CallExpr#, + // // Result + // __result__^#12:*expr.Expr_IdentExpr#)^#13:*expr.Expr_ComprehensionExpr#`, + // M: `m^#1:*expr.Expr_IdentExpr#.filter( + // v^#3:*expr.Expr_IdentExpr#, + // p^#4:*expr.Expr_IdentExpr# + // )^#13:filter#`, + P: create(ExprSchema, { + id: BigInt(13), + exprKind: { + case: 'comprehensionExpr', + value: { + accuInit: { + id: BigInt(5), + exprKind: { + case: 'listExpr', + value: { + elements: [], + }, + }, + }, + accuVar: '__result__', + iterRange: { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'm' }, + }, + }, + iterVar: 'v', + iterVar2: '', + loopCondition: { + id: BigInt(6), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'boolValue', + value: true, + }, + }, + }, + }, + loopStep: { + id: BigInt(11), + exprKind: { + case: 'callExpr', + value: { + function: '_?_:_', + args: [ + { + id: BigInt(4), + exprKind: { + case: 'identExpr', + value: { name: 'p' }, + }, + }, + { + id: BigInt(9), + exprKind: { + case: 'callExpr', + value: { + function: '_+_', + args: [ + { + id: BigInt(7), + exprKind: { + case: 'identExpr', + value: { name: '__result__' }, + }, + }, + { + id: BigInt(8), + exprKind: { + case: 'listExpr', + value: { + elements: [ + { + id: BigInt(3), + exprKind: { + case: 'identExpr', + value: { name: 'v' }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + }, + { + id: BigInt(10), + exprKind: { + case: 'identExpr', + value: { name: '__result__' }, + }, + }, + ], + }, + }, + }, + result: { + id: BigInt(12), + exprKind: { + case: 'identExpr', + value: { name: '__result__' }, + }, + }, + }, + }, + }), + }, ]; describe('CELVisitor', () => { @@ -1605,7 +2592,36 @@ describe('CELVisitor', () => { const expr = program.parse(); // Assert - expect(expr).toEqual(testCase.P); + if (testCase.P) { + try { + expect(expr).toEqual(testCase.P); + } catch (e) { + // Log the tree and expression for debugging + console.log(env.astAsString(testCase.I)); + console.log(toJsonString(ExprSchema, expr, { prettySpaces: 2 })); + throw e; + } + } else if (testCase.M) { + try { + expect(expr).toEqual(testCase.M); + } catch (e) { + // Log the tree and expression for debugging + console.log(env.astAsString(testCase.I)); + console.log(toJsonString(ExprSchema, expr, { prettySpaces: 2 })); + throw e; + } + } else if (testCase.E) { + try { + expect(program.errors().errors).toContain(testCase.E); + } catch (e) { + // Log the tree and expression for debugging + console.log(env.astAsString(testCase.I)); + console.log(toJsonString(ExprSchema, expr, { prettySpaces: 2 })); + throw e; + } + } else { + throw new Error('Invalid test case'); + } }); } }); diff --git a/packages/cel/src/lib/visitor.ts b/packages/cel/src/lib/visitor.ts index 33091c5..33e530d 100644 --- a/packages/cel/src/lib/visitor.ts +++ b/packages/cel/src/lib/visitor.ts @@ -8,6 +8,7 @@ import { Expr_CreateStruct, Expr_CreateStruct_Entry, Expr_CreateStruct_EntrySchema, + SourceInfoSchema, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; import { Status, @@ -73,9 +74,10 @@ import { OPT_SELECT_OPERATOR, getOperatorFromText, } from './operators'; +import { IdHelper } from './utils'; export class CELVisitor extends GeneratedCelVisitor { - #id = BigInt(1); + #id = new IdHelper(); #ERROR = create(ConstantSchema, { constantKind: { case: 'stringValue', @@ -134,7 +136,7 @@ export class CELVisitor extends GeneratedCelVisitor { } // If the expression is a ternary expression const condition = this.visit(ctx._e); // Visit the condition part - const id = this.#id++; + const id = this.#id.nextId(); const trueExpr = this.visit(ctx._e1); // Visit the true part const falseExpr = this.visit(ctx._e2); // Visit the false part // Handle the ternary expression, e.g., return condition ? trueExpr : falseExpr; @@ -170,7 +172,7 @@ export class CELVisitor extends GeneratedCelVisitor { return this._reportError(ctx, "unexpected character, wanted '||'"); } const term = this.visit(ctx._e1[i]); - logicManager.addTerm(this.#id++, term); + logicManager.addTerm(this.#id.nextId(), term); } return logicManager.toExpr(); }; @@ -195,7 +197,7 @@ export class CELVisitor extends GeneratedCelVisitor { return this._reportError(ctx, "unexpected character, wanted '^^'"); } const term = this.visit(ctx._e1[i]); - logicManager.addTerm(this.#id++, term); + logicManager.addTerm(this.#id.nextId(), term); } return logicManager.toExpr(); }; @@ -222,7 +224,7 @@ export class CELVisitor extends GeneratedCelVisitor { return this._reportError(ctx, 'operator not found'); } const left = this.visit(ctx.relation(0)); - const id = this.#id++; + const id = this.#id.nextId(); const right = this.visit(ctx.relation(1)); return create(ExprSchema, { id, @@ -258,7 +260,7 @@ export class CELVisitor extends GeneratedCelVisitor { return this._reportError(ctx, 'operator not found'); } const left = this.visit(ctx.calc(0)); - const id = this.#id++; + const id = this.#id.nextId(); const right = this.visit(ctx.calc(1)); return create(ExprSchema, { id, @@ -298,7 +300,7 @@ export class CELVisitor extends GeneratedCelVisitor { if (!isNil(ctx._ops) && ctx._ops.length % 2 === 0) { return this.visit(ctx.member()); } - const id = this.#id++; + const id = this.#id.nextId(); const member = this.visit(ctx.member()); return create(ExprSchema, { id, @@ -327,7 +329,7 @@ export class CELVisitor extends GeneratedCelVisitor { return expr; } return create(ExprSchema, { - id: this.#id++, + id: this.#id.nextId(), exprKind: { case: 'callExpr', value: { @@ -338,9 +340,17 @@ export class CELVisitor extends GeneratedCelVisitor { }); }; - // override visitMemberCall = (ctx: MemberCallContext): Expr => { - // // Implementation logic here - // }; + override visitMemberCall = (ctx: MemberCallContext): Expr => { + this._checkNotNil(ctx); + const operand = this.visit(ctx.member()); + if (isNil(ctx._id)) { + return create(ExprSchema, { + id: this.#id.nextId(), + }); + } + const id = ctx._id.text; + return this._receiverCallOrMacro(ctx, id, operand); + }; override visitSelect = (ctx: SelectContext): Expr => { this._checkNotNil(ctx); @@ -355,9 +365,10 @@ export class CELVisitor extends GeneratedCelVisitor { ); } const id = ctx._id.text; + const opId = this.#id.nextId(); if (!isNil(ctx._opt)) { const literalString = create(ExprSchema, { - id: this.#id++, + id: opId, exprKind: { case: 'constExpr', value: { @@ -369,7 +380,7 @@ export class CELVisitor extends GeneratedCelVisitor { }, }); return create(ExprSchema, { - id: this.#id++, + id: opId, exprKind: { case: 'callExpr', value: { @@ -380,7 +391,7 @@ export class CELVisitor extends GeneratedCelVisitor { }); } return create(ExprSchema, { - id: this.#id++, + id: opId, exprKind: { case: 'selectExpr', value: { @@ -415,7 +426,7 @@ export class CELVisitor extends GeneratedCelVisitor { ); } const target = this.visit(ctx.member()); - const id = this.#id++; + const id = this.#id.nextId(); const index = this.visit(ctx._index); let operatorIndex = INDEX_OPERATOR; if (!isNil(ctx._op) && ctx._op.text === '?') { @@ -450,7 +461,7 @@ export class CELVisitor extends GeneratedCelVisitor { } if (isNil(ctx._op)) { return create(ExprSchema, { - id: this.#id++, + id: this.#id.nextId(), exprKind: { case: 'identExpr', value: { @@ -468,7 +479,7 @@ export class CELVisitor extends GeneratedCelVisitor { override visitCreateList = (ctx: CreateListContext): Expr => { this._checkNotNil(ctx); - const listId = this.#id++; + const listId = this.#id.nextId(); let elements: Expr[] = []; let optionalIndices: number[] = []; if (!isNil(ctx._elems)) { @@ -498,7 +509,7 @@ export class CELVisitor extends GeneratedCelVisitor { override visitCreateStruct = (ctx: CreateStructContext): Expr => { this._checkNotNil(ctx); - const structId = this.#id++; + const structId = this.#id.nextId(); let entries: Expr_CreateStruct_Entry[] = []; if (!isNil(ctx._entries)) { const mapInit = this.visit(ctx._entries); @@ -535,7 +546,7 @@ export class CELVisitor extends GeneratedCelVisitor { if (!isNil(ctx._leadingDot)) { messageName = `.${messageName}`; } - const id = this.#id++; + const id = this.#id.nextId(); let entries: Expr_CreateStruct_Entry[] = []; if (!isNil(ctx._entries)) { const initializer = this.visit(ctx._entries); @@ -575,7 +586,7 @@ export class CELVisitor extends GeneratedCelVisitor { ); } return create(ExprSchema, { - id: this.#id++, + id: this.#id.nextId(), exprKind: { case: 'constExpr', value: expr.exprKind.value, @@ -586,7 +597,7 @@ export class CELVisitor extends GeneratedCelVisitor { override visitExprList = (ctx: ExprListContext): Expr => { this._checkNotNil(ctx); return create(ExprSchema, { - id: this.#id++, + id: this.#id.nextId(), exprKind: { case: 'listExpr', value: { @@ -605,7 +616,7 @@ export class CELVisitor extends GeneratedCelVisitor { const ex = this.visit(elements[i]._e); if (isNil(ex)) { return create(ExprSchema, { - id: this.#id++, + id: this.#id.nextId(), exprKind: { case: 'listExpr', value: { @@ -625,7 +636,7 @@ export class CELVisitor extends GeneratedCelVisitor { } } return create(ExprSchema, { - id: this.#id++, + id: this.#id.nextId(), exprKind: { case: 'listExpr', value: { @@ -651,7 +662,7 @@ export class CELVisitor extends GeneratedCelVisitor { ); } const field = ctx._fields[i]; - const exprId = this.#id++; + const exprId = this.#id.nextId(); const optionalEntry = !isNil(field._opt); const id = field.IDENTIFIER(); if (isNil(id)) { @@ -675,7 +686,7 @@ export class CELVisitor extends GeneratedCelVisitor { ); } return create(ExprSchema, { - id: this.#id++, + id: this.#id.nextId(), exprKind: { case: 'structExpr', value: { @@ -701,7 +712,7 @@ export class CELVisitor extends GeneratedCelVisitor { }) ); } - const colId = this.#id++; + const colId = this.#id.nextId(); const optKey = ctx._keys[i]; const optionalKey = !isNil(optKey._opt); const key = this.visit(optKey._e); @@ -719,7 +730,7 @@ export class CELVisitor extends GeneratedCelVisitor { ); } return create(ExprSchema, { - id: this.#id++, + id: this.#id.nextId(), exprKind: { case: 'structExpr', value: { @@ -738,7 +749,7 @@ export class CELVisitor extends GeneratedCelVisitor { const constant = parseIntConstant(ctx.getText()); // TODO: parse error handling return create(ExprSchema, { - id: this.#id++, + id: this.#id.nextId(), exprKind: { case: 'constExpr', value: constant, @@ -751,7 +762,7 @@ export class CELVisitor extends GeneratedCelVisitor { const constant = parseUintConstant(ctx.getText()); // TODO: parse error handling return create(ExprSchema, { - id: this.#id++, + id: this.#id.nextId(), exprKind: { case: 'constExpr', value: constant, @@ -764,7 +775,7 @@ export class CELVisitor extends GeneratedCelVisitor { const constant = parseDoubleConstant(ctx.getText()); // TODO: parse error handling return create(ExprSchema, { - id: this.#id++, + id: this.#id.nextId(), exprKind: { case: 'constExpr', value: constant, @@ -777,7 +788,7 @@ export class CELVisitor extends GeneratedCelVisitor { const constant = parseStringConstant(ctx.getText()); // TODO: parse error handling return create(ExprSchema, { - id: this.#id++, + id: this.#id.nextId(), exprKind: { case: 'constExpr', value: constant, @@ -790,7 +801,7 @@ export class CELVisitor extends GeneratedCelVisitor { const constant = parseBytesConstant(ctx.getText()); // TODO: parse error handling return create(ExprSchema, { - id: this.#id++, + id: this.#id.nextId(), exprKind: { case: 'constExpr', value: constant, @@ -802,7 +813,7 @@ export class CELVisitor extends GeneratedCelVisitor { this._checkNotNil(ctx); assert(ctx.getText() === 'true', new ParseException('true expected', 0)); return create(ExprSchema, { - id: this.#id++, + id: this.#id.nextId(), exprKind: { case: 'constExpr', value: { @@ -819,7 +830,7 @@ export class CELVisitor extends GeneratedCelVisitor { this._checkNotNil(ctx); assert(ctx.getText() === 'false', new ParseException('false expected', 0)); return create(ExprSchema, { - id: this.#id++, + id: this.#id.nextId(), exprKind: { case: 'constExpr', value: { @@ -836,7 +847,7 @@ export class CELVisitor extends GeneratedCelVisitor { this._checkNotNil(ctx); assert(ctx.getText() === 'null', new ParseException('null expected', 0)); return create(ExprSchema, { - id: this.#id++, + id: this.#id.nextId(), exprKind: { case: 'constExpr', value: { @@ -865,7 +876,7 @@ export class CELVisitor extends GeneratedCelVisitor { private _ensureErrorsExist(status: Status) { this.errors.errors.push(status); return create(ExprSchema, { - id: this.#id++, + id: this.#id.nextId(), exprKind: { case: 'constExpr', value: this.#ERROR, @@ -879,9 +890,16 @@ export class CELVisitor extends GeneratedCelVisitor { code: 1, message, details: [ + anyPack( + SourceInfoSchema, + create(SourceInfoSchema, { + location: `${context.start.line}:${context.start.column}`, + // TODO: more info + }) + ), anyPack( StringValueSchema, - fromJson(StringValueSchema, JSON.stringify(context, null, 2)) + fromJson(StringValueSchema, this.env.astAsString(context.getText())) ), ], }) @@ -968,33 +986,25 @@ export class CELVisitor extends GeneratedCelVisitor { isReceiverStyle?: boolean ) { const macro = findMacro(id); - const _arguments = - args != null - ? this.visitExprList(args) - : create(ExprSchema, { - id: this.#id++, - exprKind: { - case: 'listExpr', - value: { - elements: [], - }, - }, - }); - const _args = - _arguments.exprKind.case === 'listExpr' - ? _arguments.exprKind.value.elements - : []; if (macro) { - return expandMacro(macro, member as Expr, _args); + const argList = this.visitExprList(args); + if (argList.exprKind.case !== 'listExpr') { + return this._reportError(args, 'unexpected argument list'); + } + return expandMacro( + this.#id, + macro, + member as Expr, + argList.exprKind.value.elements + ); } - return create(ExprSchema, { - id: this.#id++, + id: this.#id.nextId(), exprKind: { case: 'callExpr', value: { function: id, - args: _args, + args: this.visitSlice(args?.expr_list() ?? []), target: member, }, }, From 643ade32a69b93a07da13eaf546f42b46663aa17 Mon Sep 17 00:00:00 2001 From: jafaircl Date: Sun, 29 Sep 2024 13:17:19 -0400 Subject: [PATCH 04/34] test(cel): add c++ tests --- packages/cel/src/lib/visitor.spec.ts | 745 +++++++++++++++++++++++++++ packages/cel/src/lib/visitor.ts | 5 +- 2 files changed, 747 insertions(+), 3 deletions(-) diff --git a/packages/cel/src/lib/visitor.spec.ts b/packages/cel/src/lib/visitor.spec.ts index 6e0bcc6..48c4a79 100644 --- a/packages/cel/src/lib/visitor.spec.ts +++ b/packages/cel/src/lib/visitor.spec.ts @@ -30,6 +30,7 @@ interface TestInfo { // See: https://github.com/google/cel-go/blob/master/parser/parser_test.go const testCases: TestInfo[] = [ + // Tests from Go parser { I: `"A"`, // P: `"A"^#1:*expr.Constant_StringValue#`, @@ -2578,6 +2579,750 @@ const testCases: TestInfo[] = [ }, }), }, + + // Tests from C++ parser + { + I: 'x * 2', + // P: `_*_( + // x^#1:*expr.Expr_IdentExpr#, + // 2^#3:*expr.Constant_Int64Value# + // )^#2:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_*_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'x' }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(2), + }, + }, + }, + }, + ], + }, + }, + }), + }, + { + I: 'x * 2u', + // P: `_*_( + // x^#1:*expr.Expr_IdentExpr#, + // 2u^#3:*expr.Constant_Uint64Value# + // )^#2:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_*_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'x' }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'uint64Value', + value: BigInt(2), + }, + }, + }, + }, + ], + }, + }, + }), + }, + { + I: 'x * 2.0', + // P: `_*_( + // x^#1:*expr.Expr_IdentExpr#, + // 2^#3:*expr.Constant_DoubleValue# + // )^#2:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_*_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'x' }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'doubleValue', + value: 2.0, + }, + }, + }, + }, + ], + }, + }, + }), + }, + { + I: `"\u2764"`, + // P: "\"\u2764\"^#1:*expr.Constant_StringValue#", + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'stringValue', + value: '❤', + }, + }, + }, + }), + }, + { + I: '"\u2764"', + // P: "\"\u2764\"^#1:*expr.Constant_StringValue#", + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'stringValue', + value: '❤', + }, + }, + }, + }), + }, + { + I: `! false`, + // P: `!_( + // false^#2:*expr.Constant_BoolValue# + // )^#1:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'callExpr', + value: { + function: '!_', + args: [ + { + id: BigInt(2), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'boolValue', + value: false, + }, + }, + }, + }, + ], + }, + }, + }), + }, + { + I: `-a`, + // P: `-_( + // a^#2:*expr.Expr_IdentExpr# + // )^#1:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'callExpr', + value: { + function: '-_', + args: [ + { + id: BigInt(2), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + ], + }, + }, + }), + }, + { + I: `a.b(5)`, + // P: `a^#1:*expr.Expr_IdentExpr#.b( + // 5^#3:*expr.Constant_Int64Value# + // )^#2:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: 'b', + target: { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + args: [ + { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(5), + }, + }, + }, + }, + ], + }, + }, + }), + }, + { + I: `a[3]`, + // P: `_[_]( + // a^#1:*expr.Expr_IdentExpr#, + // 3^#3:*expr.Constant_Int64Value# + // )^#2:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_[_]', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(3), + }, + }, + }, + }, + ], + }, + }, + }), + }, + { + I: `SomeMessage{foo: 5, bar: "xyz"}`, + // P: `SomeMessage{ + // foo:5^#3:*expr.Constant_Int64Value#^#2:*expr.Expr_CreateStruct_Entry#, + // bar:"xyz"^#5:*expr.Constant_StringValue#^#4:*expr.Expr_CreateStruct_Entry# + // }^#1:*expr.Expr_StructExpr#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'structExpr', + value: { + messageName: 'SomeMessage', + entries: [ + { + id: BigInt(2), + keyKind: { + case: 'fieldKey', + value: 'foo', + }, + value: { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(5), + }, + }, + }, + }, + }, + { + id: BigInt(4), + keyKind: { + case: 'fieldKey', + value: 'bar', + }, + value: { + id: BigInt(5), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'stringValue', + value: 'xyz', + }, + }, + }, + }, + }, + ], + }, + }, + }), + }, + { + I: `[3, 4, 5]`, + // P: `[ + // 3^#2:*expr.Constant_Int64Value#, + // 4^#3:*expr.Constant_Int64Value#, + // 5^#4:*expr.Constant_Int64Value# + // ]^#1:*expr.Expr_ListExpr#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'listExpr', + value: { + elements: [ + { + id: BigInt(2), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(3), + }, + }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(4), + }, + }, + }, + }, + { + id: BigInt(4), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(5), + }, + }, + }, + }, + ], + }, + }, + }), + }, + { + I: `[3, 4, 5,]`, + // P: `[ + // 3^#2:*expr.Constant_Int64Value#, + // 4^#3:*expr.Constant_Int64Value#, + // 5^#4:*expr.Constant_Int64Value# + // ]^#1:*expr.Expr_ListExpr#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'listExpr', + value: { + elements: [ + { + id: BigInt(2), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(3), + }, + }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(4), + }, + }, + }, + }, + { + id: BigInt(4), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(5), + }, + }, + }, + }, + ], + }, + }, + }), + }, + { + I: `{foo: 5, bar: "xyz"}`, + // P: `{ + // foo^#3:*expr.Expr_IdentExpr#:5^#4:*expr.Constant_Int64Value#^#2:*expr.Expr_CreateStruct_Entry#, + // bar^#6:*expr.Expr_IdentExpr#:"xyz"^#7:*expr.Constant_StringValue#^#5:*expr.Expr_CreateStruct_Entry# + // }^#1:*expr.Expr_StructExpr#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'structExpr', + value: { + entries: [ + { + id: BigInt(2), + keyKind: { + case: 'mapKey', + value: { + id: BigInt(3), + exprKind: { + case: 'identExpr', + value: { name: 'foo' }, + }, + }, + }, + value: { + id: BigInt(4), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(5), + }, + }, + }, + }, + }, + { + id: BigInt(5), + keyKind: { + case: 'mapKey', + value: { + id: BigInt(6), + exprKind: { + case: 'identExpr', + value: { name: 'bar' }, + }, + }, + }, + value: { + id: BigInt(7), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'stringValue', + value: 'xyz', + }, + }, + }, + }, + }, + ], + }, + }, + }), + }, + { + I: `{foo: 5, bar: "xyz", }`, + // P: `{ + // foo^#3:*expr.Expr_IdentExpr#:5^#4:*expr.Constant_Int64Value#^#2:*expr.Expr_CreateStruct_Entry#, + // bar^#6:*expr.Expr_IdentExpr#:"xyz"^#7:*expr.Constant_StringValue#^#5:*expr.Expr_CreateStruct_Entry# + // }^#1:*expr.Expr_StructExpr#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'structExpr', + value: { + entries: [ + { + id: BigInt(2), + keyKind: { + case: 'mapKey', + value: { + id: BigInt(3), + exprKind: { + case: 'identExpr', + value: { name: 'foo' }, + }, + }, + }, + value: { + id: BigInt(4), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(5), + }, + }, + }, + }, + }, + { + id: BigInt(5), + keyKind: { + case: 'mapKey', + value: { + id: BigInt(6), + exprKind: { + case: 'identExpr', + value: { name: 'bar' }, + }, + }, + }, + value: { + id: BigInt(7), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'stringValue', + value: 'xyz', + }, + }, + }, + }, + }, + ], + }, + }, + }), + }, + { + I: `a > 5 && a < 10`, + // P: `_&&_( + // _>_( + // a^#1:*expr.Expr_IdentExpr#, + // 5^#3:*expr.Constant_Int64Value# + // )^#2:*expr.Expr_CallExpr#, + // _<_( + // a^#4:*expr.Expr_IdentExpr#, + // 10^#6:*expr.Constant_Int64Value# + // )^#5:*expr.Expr_CallExpr# + // )^#7:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(7), + exprKind: { + case: 'callExpr', + value: { + function: '_&&_', + args: [ + { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_>_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(5), + }, + }, + }, + }, + ], + }, + }, + }, + { + id: BigInt(5), + exprKind: { + case: 'callExpr', + value: { + function: '_<_', + args: [ + { + id: BigInt(4), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + { + id: BigInt(6), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(10), + }, + }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + }), + }, + { + I: `a < 5 || a > 10`, + // P: `_||_( + // _<_( + // a^#1:*expr.Expr_IdentExpr#, + // 5^#3:*expr.Constant_Int64Value# + // )^#2:*expr.Expr_CallExpr#, + // _>_( + // a^#4:*expr.Expr_IdentExpr#, + // 10^#6:*expr.Constant_Int64Value# + // )^#5:*expr.Expr_CallExpr# + // )^#7:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(7), + exprKind: { + case: 'callExpr', + value: { + function: '_||_', + args: [ + { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_<_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(5), + }, + }, + }, + }, + ], + }, + }, + }, + { + id: BigInt(5), + exprKind: { + case: 'callExpr', + value: { + function: '_>_', + args: [ + { + id: BigInt(4), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }, + { + id: BigInt(6), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(10), + }, + }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + }), + }, + // TODO: Error tests + // { + // I: `{`, + // E: `ERROR: :1:2: Syntax error: mismatched input '' expecting {'[', '{', '}', '(', '.', ',', '-', '!', '?', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} + // | { + // | .^`, + // }, ]; describe('CELVisitor', () => { diff --git a/packages/cel/src/lib/visitor.ts b/packages/cel/src/lib/visitor.ts index 33e530d..a673a0d 100644 --- a/packages/cel/src/lib/visitor.ts +++ b/packages/cel/src/lib/visitor.ts @@ -324,9 +324,8 @@ export class CELVisitor extends GeneratedCelVisitor { }) ); } - const expr = this.visit(ctx.member()); if (isNil(ctx._ops) || ctx._ops.length % 2 === 0) { - return expr; + return this.visit(ctx.member()); } return create(ExprSchema, { id: this.#id.nextId(), @@ -334,7 +333,7 @@ export class CELVisitor extends GeneratedCelVisitor { case: 'callExpr', value: { function: NEGATE_OPERATOR, - args: [expr], + args: [this.visit(ctx.member())], }, }, }); From 542cc059f923eca4471e896290c139006ee49d5d Mon Sep 17 00:00:00 2001 From: jafaircl Date: Mon, 30 Sep 2024 12:37:55 -0400 Subject: [PATCH 05/34] fix(cel): update macros to match cel-go impl --- packages/cel/src/lib/macros.ts | 94 +++++++++++---------- packages/cel/src/lib/visitor.ts | 144 ++++++++++++++++++++------------ 2 files changed, 141 insertions(+), 97 deletions(-) diff --git a/packages/cel/src/lib/macros.ts b/packages/cel/src/lib/macros.ts index 5fb22fe..dcb8ce2 100644 --- a/packages/cel/src/lib/macros.ts +++ b/packages/cel/src/lib/macros.ts @@ -47,22 +47,22 @@ export function findMacro(name: string) { export function expandMacro( id: IdHelper, op: string, - target: Expr, + target: Expr | null, args: Expr[] ): Expr { switch (op) { case HAS_MACRO: return expandHasMacro(id, args); case ALL_MACRO: - return expandAllMacro(id, target, args); + return expandAllMacro(id, target!, args); case EXISTS_MACRO: - return expandExistsMacro(id, target, args); + return expandExistsMacro(id, target!, args); case EXISTS_ONE_MACRO: - return expandExistsOneMacro(id, target, args); + return expandExistsOneMacro(id, target!, args); case MAP_MACRO: - return expandMapMacro(id, target, args); + return expandMapMacro(id, target!, args); case FILTER_MACRO: - return expandFilterMacro(id, target, args); + return expandFilterMacro(id, target!, args); default: throw new Error(`Unknown macro: ${op}`); } @@ -106,9 +106,9 @@ export function expandAllMacro(id: IdHelper, target: Expr, args: Expr[]): Expr { ); const result = identExpr(id, ACCUMULATOR_VAR); return fold( - id, - arg0.exprKind.value.name, + id.nextId(), target, + arg0.exprKind.value.name, ACCUMULATOR_VAR, accuInit, condition, @@ -141,9 +141,9 @@ export function expandExistsMacro( ); const result = identExpr(id, ACCUMULATOR_VAR); return fold( - id, - arg0.exprKind.value.name, + id.nextId(), target, + arg0.exprKind.value.name, ACCUMULATOR_VAR, accuInit, condition, @@ -183,9 +183,9 @@ export function expandExistsOneMacro( int64Expr(id, BigInt(1)) ); return fold( - id, - arg0.exprKind.value.name, + id.nextId(), target, + arg0.exprKind.value.name, ACCUMULATOR_VAR, accuInit, condition, @@ -195,45 +195,45 @@ export function expandExistsOneMacro( } export function expandMapMacro(id: IdHelper, target: Expr, args: Expr[]): Expr { - const arg0 = args[0]; - if (arg0.exprKind.case !== 'identExpr') { - throw new Error('Invalid argument to map() macro'); + const v = extractIdent(args[0]); + if (isNil(v)) { + throw new Error('argument is not an identifier'); } - let arg1: Expr; - let arg2: Expr; + let fn: Expr | null = null; + let filter: Expr | null = null; if (args.length === 3) { - arg2 = args[1]; - arg1 = args[2]; + filter = args[1]; + fn = args[2]; } else { - arg1 = args[1]; - arg2 = null as unknown as Expr; + fn = args[1]; } - const accuInit = listExpr(id, []); + const init = listExpr(id, []); const condition = boolExpr(id, true); let step = globalCall( id, ADD_OPERATOR, identExpr(id, ACCUMULATOR_VAR), - listExpr(id, [arg1]) + listExpr(id, [fn]) ); - if (!isNil(arg2)) { + if (!isNil(filter)) { step = globalCall( id, CONDITIONAL_OPERATOR, - arg2, + filter, step, identExpr(id, ACCUMULATOR_VAR) ); } + const result = identExpr(id, ACCUMULATOR_VAR); return fold( - id, - arg0.exprKind.value.name, + id.nextId(), target, + v, ACCUMULATOR_VAR, - accuInit, + init, condition, step, - identExpr(id, ACCUMULATOR_VAR) + result ); } @@ -242,42 +242,43 @@ export function expandFilterMacro( target: Expr, args: Expr[] ): Expr { - const arg0 = args[0]; - if (arg0.exprKind.case !== 'identExpr') { - throw new Error('Invalid argument to filter() macro'); + const v = extractIdent(args[0]); + if (isNil(v)) { + throw new Error('argument is not an identifier'); } - const arg1 = args[1]; - const accuInit = listExpr(id, []); + const filter = args[1]; + const listInit = listExpr(id, []); const condition = boolExpr(id, true); let step = globalCall( id, ADD_OPERATOR, identExpr(id, ACCUMULATOR_VAR), - listExpr(id, [arg0]) + listExpr(id, [args[0]]) ); step = globalCall( id, CONDITIONAL_OPERATOR, - arg1, + filter, step, identExpr(id, ACCUMULATOR_VAR) ); + const result = identExpr(id, ACCUMULATOR_VAR); return fold( - id, - arg0.exprKind.value.name, + id.nextId(), target, + v, ACCUMULATOR_VAR, - accuInit, + listInit, condition, step, - identExpr(id, ACCUMULATOR_VAR) + result ); } function fold( - id: IdHelper, - iterVar: string, + exprId: bigint, iterRange: Expr, + iterVar: string, accuVar: string, accuInit: Expr, condition: Expr, @@ -285,7 +286,7 @@ function fold( result: Expr ): Expr { return create(ExprSchema, { - id: id.nextId(), + id: exprId, exprKind: { case: 'comprehensionExpr', value: { @@ -300,3 +301,10 @@ function fold( }, }); } + +function extractIdent(expr: Expr): string | null { + if (expr.exprKind.case !== 'identExpr') { + return null; + } + return expr.exprKind.value.name; +} diff --git a/packages/cel/src/lib/visitor.ts b/packages/cel/src/lib/visitor.ts index a673a0d..8cd3b2a 100644 --- a/packages/cel/src/lib/visitor.ts +++ b/packages/cel/src/lib/visitor.ts @@ -16,7 +16,7 @@ import { } from '@buf/googleapis_googleapis.bufbuild_es/google/rpc/status_pb.js'; import { create, fromJson } from '@bufbuild/protobuf'; import { NullValue, StringValueSchema, anyPack } from '@bufbuild/protobuf/wkt'; -import { ParseTree, ParserRuleContext, Token } from 'antlr4'; +import { ParseTree, ParserRuleContext } from 'antlr4'; import { RESERVED_IDS, parseBytesConstant, @@ -341,14 +341,26 @@ export class CELVisitor extends GeneratedCelVisitor { override visitMemberCall = (ctx: MemberCallContext): Expr => { this._checkNotNil(ctx); - const operand = this.visit(ctx.member()); if (isNil(ctx._id)) { - return create(ExprSchema, { - id: this.#id.nextId(), - }); + return this._reportError(ctx, 'no valid identifier specified'); } + const operand = this.visit(ctx.member()); const id = ctx._id.text; - return this._receiverCallOrMacro(ctx, id, operand); + const opId = this.#id.nextId(); + let args: Expr[] = []; + if (!isNil(ctx._args?.expr_list)) { + args = this.visitSlice(ctx._args.expr_list()); + } + return this._receiverCallOrMacro(opId, id, operand, args); + // this._checkNotNil(ctx); + // const operand = this.visit(ctx.member()); + // if (isNil(ctx._id)) { + // return create(ExprSchema, { + // id: this.#id.nextId(), + // }); + // } + // const id = ctx._id.text; + // return this._receiverCallOrMacro(ctx, id, operand); }; override visitSelect = (ctx: SelectContext): Expr => { @@ -448,28 +460,35 @@ export class CELVisitor extends GeneratedCelVisitor { override visitIdentOrGlobalCall = (ctx: IdentOrGlobalCallContext): Expr => { this._checkNotNil(ctx); + let identName = ''; + if (!isNil(ctx._leadingDot)) { + identName = '.'; + } if (isNil(ctx._id)) { - return this._reportError(ctx, 'no identifier context'); + return this._reportError(ctx, 'no valid identifier specified'); } - let id = ctx._id.text; + const id = ctx._id.text; if (RESERVED_IDS.has(id)) { return this._reportError(ctx, `reserved identifier: ${id}`); } - if (!isNil(ctx._leadingDot)) { - id = `.${id}`; + identName += id; + if (!isNil(ctx._op)) { + const opId = this.#id.nextId(); + let args: Expr[] = []; + if (!isNil(ctx._args)) { + args = this.visitSlice(ctx._args.expr_list()); + } + return this._globalCallOrMacro(opId, identName, args); } - if (isNil(ctx._op)) { - return create(ExprSchema, { - id: this.#id.nextId(), - exprKind: { - case: 'identExpr', - value: { - name: id, - }, + return create(ExprSchema, { + id: this.#id.nextId(), + exprKind: { + case: 'identExpr', + value: { + name: identName, }, - }); - } - return this._globalCallOrMacro(ctx, id); + }, + }); }; // override visitNested = (ctx: NestedContext): Expr => { @@ -964,49 +983,66 @@ export class CELVisitor extends GeneratedCelVisitor { return tree; } - private _receiverCallOrMacro( - ctx: MemberCallContext, - id: string, - member: Expr - ) { - return this._macroOrCall(ctx._args, ctx._open, id, member, true); - } - - private _globalCallOrMacro(ctx: IdentOrGlobalCallContext, id: string) { - return this._macroOrCall(ctx._args, ctx._op, id, undefined, false); + private _globalCallOrMacro(exprId: bigint, fn: string, args: Expr[]) { + const macro = this._expandMacro(exprId, fn, null, args); + if (!isNil(macro)) { + return macro; + } + return create(ExprSchema, { + id: exprId, + exprKind: { + case: 'callExpr', + value: { + function: fn, + args, + }, + }, + }); } - private _macroOrCall( - args: ExprListContext, - open: Token, - id: string, - member?: Expr, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - isReceiverStyle?: boolean + private _receiverCallOrMacro( + exprId: bigint, + fn: string, + target: Expr, + args: Expr[] ) { - const macro = findMacro(id); - if (macro) { - const argList = this.visitExprList(args); - if (argList.exprKind.case !== 'listExpr') { - return this._reportError(args, 'unexpected argument list'); - } - return expandMacro( - this.#id, - macro, - member as Expr, - argList.exprKind.value.elements - ); + const macro = this._expandMacro(exprId, fn, target, args); + if (!isNil(macro)) { + return macro; } return create(ExprSchema, { - id: this.#id.nextId(), + id: exprId, exprKind: { case: 'callExpr', value: { - function: id, - args: this.visitSlice(args?.expr_list() ?? []), - target: member, + function: fn, + args, + target, }, }, }); } + + private _expandMacro( + exprId: bigint, + fn: string, + target: Expr | null, + args: Expr[] + ) { + const macro = findMacro(fn); + if (isNil(macro)) { + return null; + } + try { + const expanded = expandMacro(this.#id, macro, target, args); + return expanded; + } catch (e) { + return this._ensureErrorsExist( + create(StatusSchema, { + code: 1, + message: (e as Error).message, + }) + ); + } + } } From 4d1ca52cfa24f6cd7359ae6e442b40aa421a035e Mon Sep 17 00:00:00 2001 From: jafaircl Date: Mon, 30 Sep 2024 13:36:35 -0400 Subject: [PATCH 06/34] fix(cel): refactoring & tests --- packages/cel/src/lib/visitor.spec.ts | 900 +++++++++++++++++++++++++++ packages/cel/src/lib/visitor.ts | 203 ++---- 2 files changed, 956 insertions(+), 147 deletions(-) diff --git a/packages/cel/src/lib/visitor.spec.ts b/packages/cel/src/lib/visitor.spec.ts index 48c4a79..121a0f6 100644 --- a/packages/cel/src/lib/visitor.spec.ts +++ b/packages/cel/src/lib/visitor.spec.ts @@ -3323,6 +3323,906 @@ const testCases: TestInfo[] = [ // | { // | .^`, // }, + + // Tests from Java parser + { + I: `[] + [1,2,3,] + [4]`, + // P: `_+_( + // _+_( + // []^#1:*expr.Expr_ListExpr#, + // [ + // 1^#4:*expr.Constant_Int64Value#, + // 2^#5:*expr.Constant_Int64Value#, + // 3^#6:*expr.Constant_Int64Value# + // ]^#3:*expr.Expr_ListExpr# + // )^#2:*expr.Expr_CallExpr#, + // [ + // 4^#9:*expr.Constant_Int64Value# + // ]^#8:*expr.Expr_ListExpr# + // )^#7:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(7), + exprKind: { + case: 'callExpr', + value: { + function: '_+_', + args: [ + { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_+_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'listExpr', + value: { + elements: [], + }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'listExpr', + value: { + elements: [ + { + id: BigInt(4), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }, + }, + }, + { + id: BigInt(5), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(2), + }, + }, + }, + }, + { + id: BigInt(6), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(3), + }, + }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + }, + { + id: BigInt(8), + exprKind: { + case: 'listExpr', + value: { + elements: [ + { + id: BigInt(9), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(4), + }, + }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + }), + }, + { + I: `{1:2u, 2:3u}`, + // P: `{ + // 1^#3:*expr.Constant_Int64Value#:2u^#4:*expr.Constant_Uint64Value#^#2:*expr.Expr_CreateStruct_Entry#, + // 2^#6:*expr.Constant_Int64Value#:3u^#7:*expr.Constant_Uint64Value#^#5:*expr.Expr_CreateStruct_Entry# + // }^#1:*expr.Expr_StructExpr#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'structExpr', + value: { + entries: [ + { + id: BigInt(2), + keyKind: { + case: 'mapKey', + value: { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }, + }, + }, + }, + value: { + id: BigInt(4), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'uint64Value', + value: BigInt(2), + }, + }, + }, + }, + }, + { + id: BigInt(5), + keyKind: { + case: 'mapKey', + value: { + id: BigInt(6), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(2), + }, + }, + }, + }, + }, + value: { + id: BigInt(7), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'uint64Value', + value: BigInt(3), + }, + }, + }, + }, + }, + ], + }, + }, + }), + }, + // TODO: TestAllTypes + // { + // I: `TestAllTypes{single_int32: 1, single_int64: 2}`, + // P: `TestAllTypes{ + // single_int32:1^#3:*expr.Constant_Int64Value#^#2:*expr.Expr_CreateStruct_Entry#, + // single_int64:2^#5:*expr.Constant_Int64Value#^#4:*expr.Expr_CreateStruct_Entry# + // }^#1:*expr.Expr_StructExpr#`, + // }, + // { + // I: `TestAllTypes(){}`, + // E: `ERROR: :1:15: Syntax error: mismatched input '{' expecting + // | TestAllTypes(){} + // | ..............^`, + // }, + // { + // I: `TestAllTypes{}()`, + // E: `ERROR: :1:15: Syntax error: mismatched input '(' expecting + // | TestAllTypes{}() + // | ..............^`, + // }, + { + I: `size(x) == x.size()`, + // P: `_==_( + // size( + // x^#2:*expr.Expr_IdentExpr# + // )^#1:*expr.Expr_CallExpr#, + // x^#4:*expr.Expr_IdentExpr#.size()^#5:*expr.Expr_CallExpr# + // )^#3:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(3), + exprKind: { + case: 'callExpr', + value: { + function: '_==_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'callExpr', + value: { + function: 'size', + args: [ + { + id: BigInt(2), + exprKind: { + case: 'identExpr', + value: { name: 'x' }, + }, + }, + ], + }, + }, + }, + { + id: BigInt(5), + exprKind: { + case: 'callExpr', + value: { + function: 'size', + target: { + id: BigInt(4), + exprKind: { + case: 'identExpr', + value: { name: 'x' }, + }, + }, + args: [], + }, + }, + }, + ], + }, + }, + }), + }, + // TODO: errors + // { + // I: `1 + $`, + // E: `ERROR: :1:5: Syntax error: token recognition error at: '$' + // | 1 + $ + // | ....^ + // ERROR: :1:6: Syntax error: mismatched input '' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} + // | 1 + $ + // | .....^`, + // }, + // { + // I: `1 + 2 + // 3 +`, + // E: `ERROR: :2:1: Syntax error: mismatched input '3' expecting + // | 3 + + // | ^`, + // }, + { + I: `"\""`, + // P: `"\""^#1:*expr.Constant_StringValue#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'stringValue', + value: '', + }, + }, + }, + }), + }, + { + I: `[1,3,4][0]`, + // P: `_[_]( + // [ + // 1^#2:*expr.Constant_Int64Value#, + // 3^#3:*expr.Constant_Int64Value#, + // 4^#4:*expr.Constant_Int64Value# + // ]^#1:*expr.Expr_ListExpr#, + // 0^#6:*expr.Constant_Int64Value# + // )^#5:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(5), + exprKind: { + case: 'callExpr', + value: { + function: '_[_]', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'listExpr', + value: { + elements: [ + { + id: BigInt(2), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(3), + }, + }, + }, + }, + { + id: BigInt(4), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(4), + }, + }, + }, + }, + ], + }, + }, + }, + { + id: BigInt(6), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(0), + }, + }, + }, + }, + ], + }, + }, + }), + }, + // TODO: errors + // { + // I: `1.all(2, 3)`, + // E: `ERROR: :1:7: argument must be a simple name + // | 1.all(2, 3) + // | ......^`, + // }, + { + I: `x["a"].single_int32 == 23`, + // P: `_==_( + // _[_]( + // x^#1:*expr.Expr_IdentExpr#, + // "a"^#3:*expr.Constant_StringValue# + // )^#2:*expr.Expr_CallExpr#.single_int32^#4:*expr.Expr_SelectExpr#, + // 23^#6:*expr.Constant_Int64Value# + // )^#5:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(5), + exprKind: { + case: 'callExpr', + value: { + function: '_==_', + args: [ + { + id: BigInt(4), + exprKind: { + case: 'selectExpr', + value: { + operand: { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_[_]', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'x' }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'stringValue', + value: 'a', + }, + }, + }, + }, + ], + }, + }, + }, + field: 'single_int32', + }, + }, + }, + { + id: BigInt(6), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(23), + }, + }, + }, + }, + ], + }, + }, + }), + }, + { + I: `x.single_nested_message != null`, + // P: `_!=_( + // x^#1:*expr.Expr_IdentExpr#.single_nested_message^#2:*expr.Expr_SelectExpr#, + // null^#4:*expr.Constant_NullValue# + // )^#3:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(3), + exprKind: { + case: 'callExpr', + value: { + function: '_!=_', + args: [ + { + id: BigInt(2), + exprKind: { + case: 'selectExpr', + value: { + operand: { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'x' }, + }, + }, + field: 'single_nested_message', + }, + }, + }, + { + id: BigInt(4), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'nullValue', + value: NullValue.NULL_VALUE, + }, + }, + }, + }, + ], + }, + }, + }), + }, + { + I: `false && !true || false ? 2 : 3`, + // P: `_?_:_( + // _||_( + // _&&_( + // false^#1:*expr.Constant_BoolValue#, + // !_( + // true^#3:*expr.Constant_BoolValue# + // )^#2:*expr.Expr_CallExpr# + // )^#4:*expr.Expr_CallExpr#, + // false^#5:*expr.Constant_BoolValue# + // )^#6:*expr.Expr_CallExpr#, + // 2^#8:*expr.Constant_Int64Value#, + // 3^#9:*expr.Constant_Int64Value# + // )^#7:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(7), + exprKind: { + case: 'callExpr', + value: { + function: '_?_:_', + args: [ + { + id: BigInt(6), + exprKind: { + case: 'callExpr', + value: { + function: '_||_', + args: [ + { + id: BigInt(4), + exprKind: { + case: 'callExpr', + value: { + function: '_&&_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'boolValue', + value: false, + }, + }, + }, + }, + { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '!_', + args: [ + { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'boolValue', + value: true, + }, + }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + }, + { + id: BigInt(5), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'boolValue', + value: false, + }, + }, + }, + }, + ], + }, + }, + }, + { + id: BigInt(8), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(2), + }, + }, + }, + }, + { + id: BigInt(9), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(3), + }, + }, + }, + }, + ], + }, + }, + }), + }, + { + I: `b"abc" + B"def"`, + // P: `_+_( + // b"abc"^#1:*expr.Constant_BytesValue#, + // b"def"^#3:*expr.Constant_BytesValue# + // )^#2:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_+_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'bytesValue', + value: new TextEncoder().encode('abc'), + }, + }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'bytesValue', + value: new TextEncoder().encode('def'), + }, + }, + }, + }, + ], + }, + }, + }), + }, + { + I: `1 + 2 * 3 - 1 / 2 == 6 % 1`, + // P: `_==_( + // _-_( + // _+_( + // 1^#1:*expr.Constant_Int64Value#, + // _*_( + // 2^#3:*expr.Constant_Int64Value#, + // 3^#5:*expr.Constant_Int64Value# + // )^#4:*expr.Expr_CallExpr# + // )^#2:*expr.Expr_CallExpr#, + // _/_( + // 1^#7:*expr.Constant_Int64Value#, + // 2^#9:*expr.Constant_Int64Value# + // )^#8:*expr.Expr_CallExpr# + // )^#6:*expr.Expr_CallExpr#, + // _%_( + // 6^#11:*expr.Constant_Int64Value#, + // 1^#13:*expr.Constant_Int64Value# + // )^#12:*expr.Expr_CallExpr# + // )^#10:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(10), + exprKind: { + case: 'callExpr', + value: { + function: '_==_', + args: [ + { + id: BigInt(6), + exprKind: { + case: 'callExpr', + value: { + function: '_-_', + args: [ + { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_+_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }, + }, + }, + { + id: BigInt(4), + exprKind: { + case: 'callExpr', + value: { + function: '_*_', + args: [ + { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(2), + }, + }, + }, + }, + { + id: BigInt(5), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(3), + }, + }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + }, + { + id: BigInt(8), + exprKind: { + case: 'callExpr', + value: { + function: '_/_', + args: [ + { + id: BigInt(7), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }, + }, + }, + { + id: BigInt(9), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(2), + }, + }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + }, + { + id: BigInt(12), + exprKind: { + case: 'callExpr', + value: { + function: '_%_', + args: [ + { + id: BigInt(11), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(6), + }, + }, + }, + }, + { + id: BigInt(13), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + }), + }, + // TODO: errors + // { + // I: `1 + +`, + // E: `ERROR: :1:5: Syntax error: mismatched input '+' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} + // | 1 + + + // | ....^ + // ERROR: :1:6: Syntax error: mismatched input '' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} + // | 1 + + + // | .....^`, + // }, + { + I: `"abc" + "def"`, + // P: `_+_( + // "abc"^#1:*expr.Constant_StringValue#, + // "def"^#3:*expr.Constant_StringValue# + // )^#2:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '_+_', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'stringValue', + value: 'abc', + }, + }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'stringValue', + value: 'def', + }, + }, + }, + }, + ], + }, + }, + }), + }, + // TODO: errors + // { + // I: `{"a": 1}."a"`, + // E: `ERROR: :1:10: Syntax error: no viable alternative at input '."a"' + // | {"a": 1}."a" + // | .........^`, + // }, ]; describe('CELVisitor', () => { diff --git a/packages/cel/src/lib/visitor.ts b/packages/cel/src/lib/visitor.ts index 8cd3b2a..1340a08 100644 --- a/packages/cel/src/lib/visitor.ts +++ b/packages/cel/src/lib/visitor.ts @@ -123,33 +123,18 @@ export class CELVisitor extends GeneratedCelVisitor { }) ); } - if (!ctx._op) { - return this.visit(ctx._e); - } - if (isNil(ctx._e1) || isNil(ctx._e2)) { - return this._ensureErrorsExist( - create(StatusSchema, { - code: 1, - message: 'no conditional context', - }) - ); + const result = this.visit(ctx._e); + if (isNil(ctx._op)) { + return result; } - // If the expression is a ternary expression - const condition = this.visit(ctx._e); // Visit the condition part - const id = this.#id.nextId(); - const trueExpr = this.visit(ctx._e1); // Visit the true part - const falseExpr = this.visit(ctx._e2); // Visit the false part - // Handle the ternary expression, e.g., return condition ? trueExpr : falseExpr; - return create(ExprSchema, { - id, - exprKind: { - case: 'callExpr', - value: { - function: CONDITIONAL_OPERATOR, - args: [condition, trueExpr, falseExpr], - }, - }, - }); + const opId = this.#id.nextId(); + const ifTrue = this.visit(ctx._e1); + const ifFalse = this.visit(ctx._e2); + return this._globalCallOrMacro(opId, CONDITIONAL_OPERATOR, [ + result, + ifTrue, + ifFalse, + ]); }; override visitConditionalOr = (ctx: ConditionalOrContext): Expr => { @@ -226,52 +211,23 @@ export class CELVisitor extends GeneratedCelVisitor { const left = this.visit(ctx.relation(0)); const id = this.#id.nextId(); const right = this.visit(ctx.relation(1)); - return create(ExprSchema, { - id, - exprKind: { - case: 'callExpr', - value: { - function: operator, - args: [left, right], - }, - }, - }); + return this._globalCallOrMacro(id, operator, [left, right]); }; override visitCalc = (ctx: CalcContext): Expr => { this._checkNotNil(ctx); - if (!isNil(ctx.unary())) { - return this.visit(ctx.unary()); - } - if ( - isNil(ctx.calc_list()) || - ctx.calc_list().length === 0 || - isNil(ctx._op) - ) { - return this._ensureErrorsExist( - create(StatusSchema, { - code: 1, - message: 'no calc context', - }) - ); + let opText = ''; + if (!isNil(ctx._op)) { + opText = ctx._op.text; } - const operator = getOperatorFromText(ctx._op.text); + const operator = getOperatorFromText(opText); if (isNil(operator)) { return this._reportError(ctx, 'operator not found'); } - const left = this.visit(ctx.calc(0)); - const id = this.#id.nextId(); - const right = this.visit(ctx.calc(1)); - return create(ExprSchema, { - id, - exprKind: { - case: 'callExpr', - value: { - function: operator, - args: [left, right], - }, - }, - }); + const lhs = this.visit(ctx.calc(0)); + const opId = this.#id.nextId(); + const rhs = this.visit(ctx.calc(1)); + return this._globalCallOrMacro(opId, operator, [lhs, rhs]); }; override visitMemberExpr = (ctx: MemberExprContext): Expr => { @@ -301,17 +257,8 @@ export class CELVisitor extends GeneratedCelVisitor { return this.visit(ctx.member()); } const id = this.#id.nextId(); - const member = this.visit(ctx.member()); - return create(ExprSchema, { - id, - exprKind: { - case: 'callExpr', - value: { - function: LOGICAL_NOT_OPERATOR, - args: [member], - }, - }, - }); + const target = this.visit(ctx.member()); + return this._globalCallOrMacro(id, LOGICAL_NOT_OPERATOR, [target]); }; override visitNegate = (ctx: NegateContext): Expr => { @@ -327,16 +274,9 @@ export class CELVisitor extends GeneratedCelVisitor { if (isNil(ctx._ops) || ctx._ops.length % 2 === 0) { return this.visit(ctx.member()); } - return create(ExprSchema, { - id: this.#id.nextId(), - exprKind: { - case: 'callExpr', - value: { - function: NEGATE_OPERATOR, - args: [this.visit(ctx.member())], - }, - }, - }); + const opId = this.#id.nextId(); + const target = this.visit(ctx.member()); + return this._globalCallOrMacro(opId, NEGATE_OPERATOR, [target]); }; override visitMemberCall = (ctx: MemberCallContext): Expr => { @@ -352,57 +292,46 @@ export class CELVisitor extends GeneratedCelVisitor { args = this.visitSlice(ctx._args.expr_list()); } return this._receiverCallOrMacro(opId, id, operand, args); - // this._checkNotNil(ctx); - // const operand = this.visit(ctx.member()); - // if (isNil(ctx._id)) { - // return create(ExprSchema, { - // id: this.#id.nextId(), - // }); - // } - // const id = ctx._id.text; - // return this._receiverCallOrMacro(ctx, id, operand); }; override visitSelect = (ctx: SelectContext): Expr => { this._checkNotNil(ctx); const operand = this.visit(ctx.member()); - // Handle the error case where no valid identifier is specified. if (isNil(ctx._id) || isNil(ctx._op)) { - return this._ensureErrorsExist( - create(StatusSchema, { - code: 1, - message: 'no valid identifier specified', - }) - ); + return this._reportError(ctx, 'no valid identifier specified'); } const id = ctx._id.text; - const opId = this.#id.nextId(); if (!isNil(ctx._opt)) { - const literalString = create(ExprSchema, { - id: opId, - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'stringValue', - value: id, - }, - }, - }, - }); + if (!this.options?.enableOptionalSyntax) { + return this._reportError(ctx, "unsupported syntax '.?'"); + } return create(ExprSchema, { - id: opId, + id: this.#id.nextId(), exprKind: { case: 'callExpr', value: { function: OPT_SELECT_OPERATOR, - args: [operand, literalString], + args: [ + operand, + create(ExprSchema, { + id: this.#id.nextId(), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'stringValue', + value: id, + }, + }, + }, + }), + ], }, }, }); } return create(ExprSchema, { - id: opId, + id: this.#id.nextId(), exprKind: { case: 'selectExpr', value: { @@ -428,34 +357,20 @@ export class CELVisitor extends GeneratedCelVisitor { override visitIndex = (ctx: IndexContext): Expr => { this._checkNotNil(ctx); - if (isNil(ctx.member()) || isNil(ctx._index)) { - return this._ensureErrorsExist( - create(StatusSchema, { - code: 1, - message: 'no index context', - }) - ); - } const target = this.visit(ctx.member()); - const id = this.#id.nextId(); + if (isNil(ctx._op)) { + return this._reportError(ctx, 'no valid identifier is specified'); + } + const opId = this.#id.nextId(); const index = this.visit(ctx._index); - let operatorIndex = INDEX_OPERATOR; - if (!isNil(ctx._op) && ctx._op.text === '?') { + let operator = INDEX_OPERATOR; + if (!isNil(ctx._opt)) { if (!this.options?.enableOptionalSyntax) { return this._reportError(ctx, "unsupported syntax '[?'"); } - operatorIndex = OPT_INDEX_OPERATOR; + operator = OPT_INDEX_OPERATOR; } - return create(ExprSchema, { - id, - exprKind: { - case: 'callExpr', - value: { - function: operatorIndex, - args: [target, index], - }, - }, - }); + return this._globalCallOrMacro(opId, operator, [target, index]); }; override visitIdentOrGlobalCall = (ctx: IdentOrGlobalCallContext): Expr => { @@ -503,12 +418,8 @@ export class CELVisitor extends GeneratedCelVisitor { if (!isNil(ctx._elems)) { const listInit = this.visit(ctx._elems); if (listInit.exprKind.case !== 'listExpr') { - return this._ensureErrorsExist( - create(StatusSchema, { - code: 1, - message: 'no list initializer', - }) - ); + // This should never happen, but just in case. + return this._reportError(ctx, 'no list initializer'); } elements = listInit.exprKind.value.elements; optionalIndices = listInit.exprKind.value.optionalIndices; @@ -634,7 +545,6 @@ export class CELVisitor extends GeneratedCelVisitor { const ex = this.visit(elements[i]._e); if (isNil(ex)) { return create(ExprSchema, { - id: this.#id.nextId(), exprKind: { case: 'listExpr', value: { @@ -654,7 +564,6 @@ export class CELVisitor extends GeneratedCelVisitor { } } return create(ExprSchema, { - id: this.#id.nextId(), exprKind: { case: 'listExpr', value: { From d8a44ed7c1554fd0968e5c70368477afc6deea74 Mon Sep 17 00:00:00 2001 From: jafaircl Date: Mon, 30 Sep 2024 15:35:33 -0400 Subject: [PATCH 07/34] feat(cel): rename CELVisitor to CELParser --- .../lib/{visitor.spec.ts => parser.spec.ts} | 66 ++++++++++++++++--- .../cel/src/lib/{visitor.ts => parser.ts} | 2 +- packages/cel/src/lib/program.ts | 6 +- 3 files changed, 62 insertions(+), 12 deletions(-) rename packages/cel/src/lib/{visitor.spec.ts => parser.spec.ts} (98%) rename packages/cel/src/lib/{visitor.ts => parser.ts} (99%) diff --git a/packages/cel/src/lib/visitor.spec.ts b/packages/cel/src/lib/parser.spec.ts similarity index 98% rename from packages/cel/src/lib/visitor.spec.ts rename to packages/cel/src/lib/parser.spec.ts index 121a0f6..c64e498 100644 --- a/packages/cel/src/lib/visitor.spec.ts +++ b/packages/cel/src/lib/parser.spec.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-useless-escape */ /* eslint-disable @typescript-eslint/no-explicit-any */ import { Expr, @@ -3517,14 +3518,63 @@ const testCases: TestInfo[] = [ }, }), }, - // TODO: TestAllTypes - // { - // I: `TestAllTypes{single_int32: 1, single_int64: 2}`, - // P: `TestAllTypes{ - // single_int32:1^#3:*expr.Constant_Int64Value#^#2:*expr.Expr_CreateStruct_Entry#, - // single_int64:2^#5:*expr.Constant_Int64Value#^#4:*expr.Expr_CreateStruct_Entry# - // }^#1:*expr.Expr_StructExpr#`, - // }, + { + I: `TestAllTypes{single_int32: 1, single_int64: 2}`, + // P: `TestAllTypes{ + // single_int32:1^#3:*expr.Constant_Int64Value#^#2:*expr.Expr_CreateStruct_Entry#, + // single_int64:2^#5:*expr.Constant_Int64Value#^#4:*expr.Expr_CreateStruct_Entry# + // }^#1:*expr.Expr_StructExpr#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'structExpr', + value: { + messageName: 'TestAllTypes', + entries: [ + { + id: BigInt(2), + keyKind: { + case: 'fieldKey', + value: 'single_int32', + }, + value: { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }, + }, + }, + }, + { + id: BigInt(4), + keyKind: { + case: 'fieldKey', + value: 'single_int64', + }, + value: { + id: BigInt(5), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'int64Value', + value: BigInt(2), + }, + }, + }, + }, + }, + ], + }, + }, + }), + }, + // TODO: errors // { // I: `TestAllTypes(){}`, // E: `ERROR: :1:15: Syntax error: mismatched input '{' expecting diff --git a/packages/cel/src/lib/visitor.ts b/packages/cel/src/lib/parser.ts similarity index 99% rename from packages/cel/src/lib/visitor.ts rename to packages/cel/src/lib/parser.ts index 1340a08..9b14f55 100644 --- a/packages/cel/src/lib/visitor.ts +++ b/packages/cel/src/lib/parser.ts @@ -76,7 +76,7 @@ import { } from './operators'; import { IdHelper } from './utils'; -export class CELVisitor extends GeneratedCelVisitor { +export class CELParser extends GeneratedCelVisitor { #id = new IdHelper(); #ERROR = create(ConstantSchema, { constantKind: { diff --git a/packages/cel/src/lib/program.ts b/packages/cel/src/lib/program.ts index 2b705b9..0ed39f4 100644 --- a/packages/cel/src/lib/program.ts +++ b/packages/cel/src/lib/program.ts @@ -1,6 +1,6 @@ import { CELEnvironment } from './environment'; import { StartContext } from './gen/CELParser'; -import { CELVisitor } from './visitor'; +import { CELParser } from './parser'; export class CELProgram { constructor( @@ -9,12 +9,12 @@ export class CELProgram { ) {} parse() { - const parser = new CELVisitor(this.env); + const parser = new CELParser(this.env); return this.ast.accept(parser); } errors() { - const parser = new CELVisitor(this.env); + const parser = new CELParser(this.env); return parser.errors; } } From 9bc7813afb1c0de29b3e2956e5d77fc612884284 Mon Sep 17 00:00:00 2001 From: jafaircl Date: Tue, 1 Oct 2024 20:54:50 -0400 Subject: [PATCH 08/34] feat(cel): add parser error handling & tests --- packages/cel/src/lib/environment.ts | 31 +- packages/cel/src/lib/errors.ts | 129 +++++++ packages/cel/src/lib/parser.spec.ts | 560 ++++++++++++++++++++++++---- packages/cel/src/lib/parser.ts | 327 +++++----------- packages/cel/src/lib/program.ts | 11 - packages/cel/vite.config.ts | 12 +- 6 files changed, 727 insertions(+), 343 deletions(-) create mode 100644 packages/cel/src/lib/errors.ts diff --git a/packages/cel/src/lib/environment.ts b/packages/cel/src/lib/environment.ts index a05db28..a00c061 100644 --- a/packages/cel/src/lib/environment.ts +++ b/packages/cel/src/lib/environment.ts @@ -8,9 +8,7 @@ import { Registry, createMutableRegistry, } from '@bufbuild/protobuf'; -import { CharStream, CommonTokenStream } from 'antlr4'; -import CELLexer from './gen/CELLexer'; -import CELParser, { StartContext } from './gen/CELParser'; +import { CELParser } from './parser'; export interface CELEnvironmentOptions { container?: string; @@ -29,24 +27,8 @@ export class CELEnvironment { this.declarations = options?.declarations ?? []; } - compile(input: string, check = false): StartContext { - const parser = this._getParser(input); - const tree = parser.start(); - if (tree.exception) throw tree.exception; - if (check) this.check(tree); - return tree; - } - - astAsString(input: string) { - const parser = this._getParser(input); - const tree = parser.start(); - if (tree.exception) throw tree.exception; - return tree.toStringTree(parser.ruleNames, parser); - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - check(ast: StartContext) { - // TODO: implement + compile(input: string): CELParser { + return new CELParser(input); } addDeclaration(decl: Decl) { @@ -70,11 +52,4 @@ export class CELEnvironment { this.addDescriptor(descriptor); } } - - private _getParser(input: string) { - const chars = new CharStream(input); - const lexer = new CELLexer(chars); - const tokens = new CommonTokenStream(lexer); - return new CELParser(tokens); - } } diff --git a/packages/cel/src/lib/errors.ts b/packages/cel/src/lib/errors.ts new file mode 100644 index 0000000..b81a05d --- /dev/null +++ b/packages/cel/src/lib/errors.ts @@ -0,0 +1,129 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import { ErrorSetSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/eval_pb.js'; +import { + SourceInfo, + SourceInfoSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { + Status, + StatusSchema, +} from '@buf/googleapis_googleapis.bufbuild_es/google/rpc/status_pb.js'; +import { create, createRegistry } from '@bufbuild/protobuf'; +import { anyPack, anyUnpack } from '@bufbuild/protobuf/wkt'; +import { ErrorListener, RecognitionException, Recognizer, Token } from 'antlr4'; + +export class Errors { + public readonly errors = create(ErrorSetSchema); + public numErrors = 0; + + constructor( + public readonly source: string, + public readonly sourceDescription = '', + public readonly maxErrorsToReport = 100 + ) {} + + public reportError(line: number, column: number, message: string) { + this.reportErrorAtId(BigInt(0), line, column, message); + } + + public reportErrorAtId( + id: bigint, + line: number, + column: number, + message: string + ) { + this.numErrors++; + if (this.numErrors > this.maxErrorsToReport) { + return; + } + const err = create(StatusSchema, { + code: 0, + message, + details: [ + anyPack( + SourceInfoSchema, + create(SourceInfoSchema, { + positions: { + [id.toString()]: column, + }, + lineOffsets: [line], + location: `${line}:${column}`, + syntaxVersion: 'cel1', + }) + ), + ], + }); + this.errors.errors.push(err); + } + + public toDisplayString() { + return this.errors.errors + .map((err) => this._errorToDisplayString(err)) + .join('\n '); + } + + private _errorToDisplayString(err: Status) { + const sourceInfo = anyUnpack( + err.details[0], + createRegistry(SourceInfoSchema) + ) as SourceInfo; + if (sourceInfo?.$typeName !== SourceInfoSchema.typeName) { + throw new Error('Invalid source info'); + } + const [line, column] = sourceInfo.location.split(':').map(Number); + const result = `ERROR: ${this.sourceDescription}:${line}:${column + 1}: ${ + err.message + }`; + const sourceLine = '\n | ' + this.source.split('\n')[line - 1]; + let indLine = '\n | '; + for (let i = 0; i < column; i++) { + indLine += '.'; + } + indLine += '^'; + return result + sourceLine + indLine; + } +} + +export class LexerErrorListener extends ErrorListener { + constructor(private readonly errors: Errors) { + super(); + } + + override syntaxError( + recognizer: Recognizer, + offendingSymbol: number, + line: number, + charPositionInLine: number, + msg: string, + e: RecognitionException | undefined + ): void { + this.errors.reportErrorAtId( + BigInt(offendingSymbol ?? 0), + line, + charPositionInLine, + `Syntax error: ${msg}` + ); + } +} + +export class ParserErrorListener extends ErrorListener { + constructor(private readonly errors: Errors) { + super(); + } + + override syntaxError( + recognizer: Recognizer, + offendingSymbol: Token, + line: number, + charPositionInLine: number, + msg: string, + e: RecognitionException | undefined + ): void { + this.errors.reportErrorAtId( + BigInt(offendingSymbol?.tokenIndex ?? 0), + line, + charPositionInLine, + `Syntax error: ${msg}` + ); + } +} diff --git a/packages/cel/src/lib/parser.spec.ts b/packages/cel/src/lib/parser.spec.ts index c64e498..b515fc2 100644 --- a/packages/cel/src/lib/parser.spec.ts +++ b/packages/cel/src/lib/parser.spec.ts @@ -1,13 +1,12 @@ +import { Expr } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb'; /* eslint-disable no-useless-escape */ /* eslint-disable @typescript-eslint/no-explicit-any */ import { - Expr, - ExprSchema, + ExprSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; -import { create, toJsonString } from '@bufbuild/protobuf'; +import { create } from '@bufbuild/protobuf'; import { NullValue } from '@bufbuild/protobuf/wkt'; -import { CELEnvironment } from './environment'; -import { CELProgram } from './program'; +import { CELParser } from './parser'; interface TestInfo { // I contains the input expression to be parsed. @@ -1775,15 +1774,15 @@ const testCases: TestInfo[] = [ // | *@a | b // | ......^`, // }, - // { - // I: `a | b`, - // E: `ERROR: :1:3: Syntax error: token recognition error at: '| ' - // | a | b - // | ..^ - // ERROR: :1:5: Syntax error: extraneous input 'b' expecting - // | a | b - // | ....^`, - // }, + { + I: `a | b`, + E: `ERROR: :1:3: Syntax error: token recognition error at: '| ' + | a | b + | ..^ + ERROR: :1:5: Syntax error: extraneous input 'b' expecting + | a | b + | ....^`, + }, // Macro tests { I: `has(m.f)`, @@ -3574,19 +3573,18 @@ const testCases: TestInfo[] = [ }, }), }, - // TODO: errors - // { - // I: `TestAllTypes(){}`, - // E: `ERROR: :1:15: Syntax error: mismatched input '{' expecting - // | TestAllTypes(){} - // | ..............^`, - // }, - // { - // I: `TestAllTypes{}()`, - // E: `ERROR: :1:15: Syntax error: mismatched input '(' expecting - // | TestAllTypes{}() - // | ..............^`, - // }, + { + I: `TestAllTypes(){}`, + E: `ERROR: :1:15: Syntax error: mismatched input '{' expecting + | TestAllTypes(){} + | ..............^`, + }, + { + I: `TestAllTypes{}()`, + E: `ERROR: :1:15: Syntax error: mismatched input '(' expecting + | TestAllTypes{}() + | ..............^`, + }, { I: `size(x) == x.size()`, // P: `_==_( @@ -3652,15 +3650,15 @@ const testCases: TestInfo[] = [ // | 1 + $ // | .....^`, // }, - // { - // I: `1 + 2 - // 3 +`, - // E: `ERROR: :2:1: Syntax error: mismatched input '3' expecting - // | 3 + - // | ^`, - // }, { - I: `"\""`, + I: `1 + 2 +3 +`, + E: `ERROR: :2:1: Syntax error: mismatched input '3' expecting + | 3 + + | ^`, + }, + { + I: `"\\""`, // TODO: revisit this test // P: `"\""^#1:*expr.Constant_StringValue#`, P: create(ExprSchema, { id: BigInt(1), @@ -3669,7 +3667,7 @@ const testCases: TestInfo[] = [ value: { constantKind: { case: 'stringValue', - value: '', + value: '"', }, }, }, @@ -4266,54 +4264,478 @@ const testCases: TestInfo[] = [ }, }), }, - // TODO: errors + { + I: `{"a": 1}."a"`, + E: `ERROR: :1:10: Syntax error: no viable alternative at input '."a"' + | {"a": 1}."a" + | .........^`, + }, + // { // TODO: this comes up with the wrong value + // I: `"\xC3\XBF"`, + // // P: `"ÿ"^#1:*expr.Constant_StringValue#`, + // P: create(ExprSchema, { + // id: BigInt(1), + // exprKind: { + // case: 'constExpr', + // value: { + // constantKind: { + // case: 'stringValue', + // value: 'ÿ', + // }, + // }, + // }, + // }), + // }, + // JS throws an error "octal escape sequences are not allowed in strict mode" + // { + // I: `"\303\277"`, + // P: `"ÿ"^#1:*expr.Constant_StringValue#`, + // }, + { + I: `"hi\u263A \u263Athere"`, + // P: `"hi☺ ☺there"^#1:*expr.Constant_StringValue#`, + P: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'stringValue', + value: 'hi☺ ☺there', + }, + }, + }, + }), + }, + // { + // I: `"\U000003A8\?"`, // TODO: it parses this wrong + // // P: `"Ψ?"^#1:*expr.Constant_StringValue#`, + // P: create(ExprSchema, { + // id: BigInt(1), + // exprKind: { + // case: 'constExpr', + // value: { + // constantKind: { + // case: 'stringValue', + // value: 'Ψ?', + // }, + // }, + // }, + // }), + // }, + // { + // I: `"\a\b\f\n\r\t\v'\"\\\? Legal escapes"`, // TODO: it struggles with this too + // // P: `"\a\b\f\n\r\t\v'\"\\? Legal escapes"^#1:*expr.Constant_StringValue#`, + // P: create(ExprSchema, { + // id: BigInt(1), + // exprKind: { + // case: 'constExpr', + // value: { + // constantKind: { + // case: 'stringValue', + // value: `a\b\f\n\r\t\v\'"\\? Legal escapes`, + // }, + // }, + // }, + // }), + // }, + // { + // I: `"\xFh"`, // TODO: JS won't run this + // E: `ERROR: :1:1: Syntax error: token recognition error at: '"\xFh' + // | "\xFh" + // | ^ + // ERROR: :1:6: Syntax error: token recognition error at: '"' + // | "\xFh" + // | .....^ + // ERROR: :1:7: Syntax error: mismatched input '' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} + // | "\xFh" + // | ......^`, + // }, + // { // TODO: it throws an error but the message is wonky because of the escapes + // I: `"\a\b\f\n\r\t\v\'\"\\\? Illegal escape \>"`, + // E: `ERROR: :1:1: Syntax error: token recognition error at: '"\a\b\f\n\r\t\v\'\"\\\? Illegal escape \>' + // | "\a\b\f\n\r\t\v\'\"\\\? Illegal escape \>" + // | ^ + // ERROR: :1:42: Syntax error: token recognition error at: '"' + // | "\a\b\f\n\r\t\v\'\"\\\? Illegal escape \>" + // | .........................................^ + // ERROR: :1:43: Syntax error: mismatched input '' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} + // | "\a\b\f\n\r\t\v\'\"\\\? Illegal escape \>" + // | ..........................................^`, + // }, + { + I: `"😁" in ["😁", "😑", "😦"]`, + // P: `@in( + // "😁"^#1:*expr.Constant_StringValue#, + // [ + // "😁"^#4:*expr.Constant_StringValue#, + // "😑"^#5:*expr.Constant_StringValue#, + // "😦"^#6:*expr.Constant_StringValue# + // ]^#3:*expr.Expr_ListExpr# + // )^#2:*expr.Expr_CallExpr#`, + P: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'callExpr', + value: { + function: '@in', + args: [ + { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'stringValue', + value: '😁', + }, + }, + }, + }, + { + id: BigInt(3), + exprKind: { + case: 'listExpr', + value: { + elements: [ + { + id: BigInt(4), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'stringValue', + value: '😁', + }, + }, + }, + }, + { + id: BigInt(5), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'stringValue', + value: '😑', + }, + }, + }, + }, + { + id: BigInt(6), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'stringValue', + value: '😦', + }, + }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + }), + }, + // { // TODO: the error message points at the wrong characters + // I: ` '😁' in ['😁', '😑', '😦'] + // && in.😁`, + // E: `ERROR: :2:7: Syntax error: extraneous input 'in' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} + // | && in.😁 + // | ......^ + // ERROR: :2:10: Syntax error: token recognition error at: '😁' + // | && in.😁 + // | .........^ + // ERROR: :2:11: Syntax error: no viable alternative at input '.' + // | && in.😁 + // | ..........^`, + // }, + { + I: 'as', + E: `ERROR: :1:1: reserved identifier: as + | as + | ^`, + }, + { + I: 'break', + E: `ERROR: :1:1: reserved identifier: break + | break + | ^`, + }, + { + I: 'const', + E: `ERROR: :1:1: reserved identifier: const + | const + | ^`, + }, + { + I: 'continue', + E: `ERROR: :1:1: reserved identifier: continue + | continue + | ^`, + }, + { + I: 'else', + E: `ERROR: :1:1: reserved identifier: else + | else + | ^`, + }, + { + I: 'for', + E: `ERROR: :1:1: reserved identifier: for + | for + | ^`, + }, + { + I: 'function', + E: `ERROR: :1:1: reserved identifier: function + | function + | ^`, + }, + { + I: 'if', + E: `ERROR: :1:1: reserved identifier: if + | if + | ^`, + }, + { + I: 'import', + E: `ERROR: :1:1: reserved identifier: import + | import + | ^`, + }, + { + I: 'in', + E: `ERROR: :1:1: Syntax error: mismatched input 'in' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} + | in + | ^ + ERROR: :1:3: Syntax error: mismatched input '' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} + | in + | ..^`, + }, + { + I: 'let', + E: `ERROR: :1:1: reserved identifier: let + | let + | ^`, + }, + { + I: 'loop', + E: `ERROR: :1:1: reserved identifier: loop + | loop + | ^`, + }, + { + I: 'package', + E: `ERROR: :1:1: reserved identifier: package + | package + | ^`, + }, + { + I: 'namespace', + E: `ERROR: :1:1: reserved identifier: namespace + | namespace + | ^`, + }, + { + I: 'return', + E: `ERROR: :1:1: reserved identifier: return + | return + | ^`, + }, + { + I: 'var', + E: `ERROR: :1:1: reserved identifier: var + | var + | ^`, + }, + { + I: 'void', + E: `ERROR: :1:1: reserved identifier: void + | void + | ^`, + }, + { + I: 'while', + E: `ERROR: :1:1: reserved identifier: while + | while + | ^`, + }, + // { // TODO: the errors in the message are in the wrong order + // I: '[1, 2, 3].map(var, var * var)', + // E: `ERROR: :1:15: reserved identifier: var + // | [1, 2, 3].map(var, var * var) + // | ..............^ + // ERROR: :1:15: argument is not an identifier + // | [1, 2, 3].map(var, var * var) + // | ..............^ + // ERROR: :1:20: reserved identifier: var + // | [1, 2, 3].map(var, var * var) + // | ...................^ + // ERROR: :1:26: reserved identifier: var + // | [1, 2, 3].map(var, var * var) + // | .........................^`, + // }, + { + I: 'func{{a}}', + E: `ERROR: :1:6: Syntax error: extraneous input '{' expecting {'}', ',', '?', IDENTIFIER} + | func{{a}} + | .....^ + ERROR: :1:8: Syntax error: mismatched input '}' expecting ':' + | func{{a}} + | .......^ + ERROR: :1:9: Syntax error: extraneous input '}' expecting + | func{{a}} + | ........^`, + }, + { + I: 'msg{:a}', + E: `ERROR: :1:5: Syntax error: extraneous input ':' expecting {'}', ',', '?', IDENTIFIER} + | msg{:a} + | ....^ + ERROR: :1:7: Syntax error: mismatched input '}' expecting ':' + | msg{:a} + | ......^`, + }, + { + I: '{a}', + E: `ERROR: :1:3: Syntax error: mismatched input '}' expecting ':' + | {a} + | ..^`, + }, + { + I: '{:a}', + E: `ERROR: :1:2: Syntax error: extraneous input ':' expecting {'[', '{', '}', '(', '.', ',', '-', '!', '?', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} + | {:a} + | .^ + ERROR: :1:4: Syntax error: mismatched input '}' expecting ':' + | {:a} + | ...^`, + }, + { + I: 'ind[a{b}]', + E: `ERROR: :1:8: Syntax error: mismatched input '}' expecting ':' + | ind[a{b}] + | .......^`, + }, + // TODO: something is weird with these ones: + // { + // I: `--`, + // E: `ERROR: :1:3: Syntax error: no viable alternative at input '-' + // | -- + // | ..^ + // ERROR: :1:3: Syntax error: mismatched input '' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} + // | -- + // | ..^`, + // }, + // { + // I: `?`, + // E: `ERROR: :1:1: Syntax error: mismatched input '?' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} + // | ? + // | ^ + // ERROR: :1:2: Syntax error: mismatched input '' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} + // | ? + // | .^`, + // }, + // { + // I: `a ? b ((?))`, + // E: `ERROR: :1:9: Syntax error: mismatched input '?' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} + // | a ? b ((?)) + // | ........^ + // ERROR: :1:10: Syntax error: mismatched input ')' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} + // | a ? b ((?)) + // | .........^ + // ERROR: :1:12: Syntax error: error recovery attempt limit exceeded: 4 + // | a ? b ((?)) + // | ...........^`, + // }, + // TODO: recusion errors + // { + // I: `[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ + // [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[['too many']]]]]]]]]]]]]]]]]]]]]]]]]]]] + // ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]`, + // E: "ERROR: :-1:0: expression recursion limit exceeded: 32", + // }, // { - // I: `{"a": 1}."a"`, - // E: `ERROR: :1:10: Syntax error: no viable alternative at input '."a"' - // | {"a": 1}."a" - // | .........^`, + // I: `-[-1--1--1--1---1--1--1--0--1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1 + // --3-[-1--1--1--1---1--1--1--0--1--1--1--1--0--3--1--1--0--1--1--1--1--0--1--1--1 + // --3-[-1--1--1--1---1--1--1--0-/1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1 + // --3-[-1--1--1--1---1--1--1--0--1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1 + // --3-[-1--1--1--1---1--1--1--0--1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1 + // --3-[-1--1--1--1---1--1--1--0--1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1 + // --3-[-1--1--1--1---1--1--1--0--1--1--1--1--0--3--1--1--0--1--1--1--1--0--1--1--1 + // --3-[-1--1--1--1---1--1--1--0-/1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1 + // --3-[-1--1--1--1---1-1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1--3-[-1--1 + // --1--1---1--1--1--0--1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1--3-[-1--1 + // --1--1---1--1-À1--0--1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1--3-[-1--1 + // --1--1---1--1--1--0--1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1--3-[-1--1 + // --1--1---1--1--1--0--1--1--1--1--0--3--1--1--0--1--1--1--1--0--1--1--1--3-[-1--1 + // --1--1---1--1--1--0-/1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1--3-[-1--1 + // --1--1---1--1--1--0--1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1--3-[-1--1 + // --1--1---1--1--1--0--1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1--3-[-1--1 + // --1--1---1--1--1--0--1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1--3-[-1--1 + // --1--1---1--1--1--0--1--1--1--1--0--3--1--1--0--1--1--1 + // --1--0--1--1--1--3-[-1--1--1--1---1--1--1--0-/1--1--1--1--0--2--1--1--0--1--1--1 + // --1--0--1--1--1--3-[-1--1--1--1---1--1--1--0--1--1--1--1--0--2--1--1--0--1--1--1 + // --1--0--1--1--1--3-[-1--1--1--1---1--1--1--0--1--1--1--1--0--2--1--1--0--1--1--1 + // --1--0--1--1--1--3-[-1--1--1--1---1--1--1--0--1--1--1--1--0--2--1--1--0--1--1--1 + // --1--0--1--1--1--3-[-1--1--1--1---1--1--1--0--1--1--1--1--0--3--1--1--0--1--1--1 + // --1--0--1--1--1--3-[-1--1--1--1---1--1--1--0-/1--1--1--1--0--2--1--1--0--1--1--1 + // --1--0--1--1--1--3-[-1--1--1--1---1--1--1--0--1--1--1--1--0--1--1--1--3-[-1--1--1 + // --1---1--1--1--0--1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1--3-[-1--1--1 + // --1---1--1--1--0--1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1--3-[-1--1--1 + // --1---1--1--1--0--1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1--3-[-1--1--1 + // --1---1--1--1--0--1--1--1--1--0--3--1--1--0--1--1--1--1--0--1--1--1--3-[-1--1--1 + // --1---1--1--1--0-/1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1--3-[-1--1--1 + // --1---1--1--1--0--1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1--3-[-1--1--1 + // --1---1--1--1--0--1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1--3-[-1--1--1 + // --1---1--1--1--0--1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1--3-[-1--1--1 + // --1---1--1--1--0--1--1--1--1--0--3--1--1--0--1`, + // E: `ERROR: :-1:0: expression recursion limit exceeded: 32 + // ERROR: :3:33: Syntax error: extraneous input '/' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} + // | --3-[-1--1--1--1---1--1--1--0-/1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1 + // | ................................^ + // ERROR: :8:33: Syntax error: extraneous input '/' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} + // | --3-[-1--1--1--1---1--1--1--0-/1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1 + // | ................................^ + // ERROR: :11:17: Syntax error: token recognition error at: 'À' + // | --1--1---1--1-À1--0--1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1--3-[-1--1 + // | ................^ + // ERROR: :14:23: Syntax error: extraneous input '/' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} + // | --1--1---1--1--1--0-/1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1--3-[-1--1 + // | ......................^`, // }, + // TODO: javascript doesn't like the one that starts with "I: `ó" ]; describe('CELVisitor', () => { for (const testCase of testCases) { it(`should parse ${testCase.I}`, () => { // Arrange - const env = new CELEnvironment(); - const ast = env.compile(testCase.I); - const program = new CELProgram(env, ast); + const parser = new CELParser(testCase.I); // Act - const expr = program.parse(); + const expr = parser.parse(); // Assert if (testCase.P) { - try { - expect(expr).toEqual(testCase.P); - } catch (e) { - // Log the tree and expression for debugging - console.log(env.astAsString(testCase.I)); - console.log(toJsonString(ExprSchema, expr, { prettySpaces: 2 })); - throw e; - } + expect(expr).toEqual(testCase.P); } else if (testCase.M) { - try { - expect(expr).toEqual(testCase.M); - } catch (e) { - // Log the tree and expression for debugging - console.log(env.astAsString(testCase.I)); - console.log(toJsonString(ExprSchema, expr, { prettySpaces: 2 })); - throw e; - } + expect(expr).toEqual(testCase.M); } else if (testCase.E) { - try { - expect(program.errors().errors).toContain(testCase.E); - } catch (e) { - // Log the tree and expression for debugging - console.log(env.astAsString(testCase.I)); - console.log(toJsonString(ExprSchema, expr, { prettySpaces: 2 })); - throw e; - } + expect(parser.errors.toDisplayString()).toEqual( + // Account for the difference in spacing between the test case and + // the error message + testCase.E.split('\n') + .map((line) => line.trim()) + .join('\n ') + ); } else { throw new Error('Invalid test case'); } diff --git a/packages/cel/src/lib/parser.ts b/packages/cel/src/lib/parser.ts index 9b14f55..0f4ef74 100644 --- a/packages/cel/src/lib/parser.ts +++ b/packages/cel/src/lib/parser.ts @@ -1,22 +1,20 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { assert, isNil } from '@bearclaw/is'; -import { ErrorSetSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/eval_pb.js'; import { - ConstantSchema, Expr, ExprSchema, Expr_CreateStruct, Expr_CreateStruct_Entry, Expr_CreateStruct_EntrySchema, - SourceInfoSchema, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { NullValue } from '@bufbuild/protobuf/wkt'; import { - Status, - StatusSchema, -} from '@buf/googleapis_googleapis.bufbuild_es/google/rpc/status_pb.js'; -import { create, fromJson } from '@bufbuild/protobuf'; -import { NullValue, StringValueSchema, anyPack } from '@bufbuild/protobuf/wkt'; -import { ParseTree, ParserRuleContext } from 'antlr4'; + CharStream, + CommonTokenStream, + ParseTree, + ParserRuleContext, +} from 'antlr4'; import { RESERVED_IDS, parseBytesConstant, @@ -25,8 +23,9 @@ import { parseStringConstant, parseUintConstant, } from './constants'; -import { CELEnvironment } from './environment'; -import { NullException, ParseException } from './exceptions'; +import { Errors, LexerErrorListener, ParserErrorListener } from './errors'; +import { ParseException } from './exceptions'; +import CELLexer from './gen/CELLexer'; import { BoolFalseContext, BoolTrueContext, @@ -42,6 +41,7 @@ import { ExprContext, ExprListContext, FieldInitializerListContext, + default as GenCELParser, IdentOrGlobalCallContext, IndexContext, IntContext, @@ -78,22 +78,37 @@ import { IdHelper } from './utils'; export class CELParser extends GeneratedCelVisitor { #id = new IdHelper(); - #ERROR = create(ConstantSchema, { - constantKind: { - case: 'stringValue', - value: '<>', - }, - }); - public readonly errors = create(ErrorSetSchema); + readonly #errors!: Errors; constructor( - public readonly env: CELEnvironment, + public readonly source: string, private readonly options?: { enableOptionalSyntax?: boolean; retainRepeatedUnaryOperators?: boolean; } ) { super(); + this.#errors = new Errors(source); + } + + public get errors() { + return this.#errors; + } + + parse() { + const chars = new CharStream(this.source); + const lexer = new CELLexer(chars); + lexer.removeErrorListeners(); + const lexerErrorListener = new LexerErrorListener(this.#errors); + lexer.addErrorListener(lexerErrorListener); + + const tokens = new CommonTokenStream(lexer); + const parser = new GenCELParser(tokens); + parser.removeErrorListeners(); + const parserErrorListener = new ParserErrorListener(this.#errors); + parser.addErrorListener(parserErrorListener); + + return this.visit(parser.start()); } override visit = (ctx: ParseTree) => { @@ -101,28 +116,10 @@ export class CELParser extends GeneratedCelVisitor { }; override visitStart = (ctx: StartContext): Expr => { - this._checkNotNil(ctx); - if (isNil(ctx._e)) { - return this._ensureErrorsExist( - create(StatusSchema, { - code: 1, - message: 'no expression context', - }) - ); - } return this.visit(ctx._e); }; override visitExpr = (ctx: ExprContext): Expr => { - this._checkNotNil(ctx); - if (isNil(ctx._e)) { - return this._ensureErrorsExist( - create(StatusSchema, { - code: 1, - message: 'no expression context', - }) - ); - } const result = this.visit(ctx._e); if (isNil(ctx._op)) { return result; @@ -130,7 +127,7 @@ export class CELParser extends GeneratedCelVisitor { const opId = this.#id.nextId(); const ifTrue = this.visit(ctx._e1); const ifFalse = this.visit(ctx._e2); - return this._globalCallOrMacro(opId, CONDITIONAL_OPERATOR, [ + return this._globalCallOrMacro(ctx, opId, CONDITIONAL_OPERATOR, [ result, ifTrue, ifFalse, @@ -138,22 +135,13 @@ export class CELParser extends GeneratedCelVisitor { }; override visitConditionalOr = (ctx: ConditionalOrContext): Expr => { - this._checkNotNil(ctx); - if (isNil(ctx._e)) { - return this._ensureErrorsExist( - create(StatusSchema, { - code: 1, - message: 'no conditionalor context', - }) - ); - } const result = this.visit(ctx._e); const logicManager = LogicManager.newBalancingLogicManager( LOGICAL_OR_OPERATOR, result ); for (let i = 0; i < ctx._ops.length; i++) { - if (isNil(ctx._e1) || i >= ctx._e1.length) { + if (i >= ctx._e1.length) { return this._reportError(ctx, "unexpected character, wanted '||'"); } const term = this.visit(ctx._e1[i]); @@ -163,23 +151,14 @@ export class CELParser extends GeneratedCelVisitor { }; override visitConditionalAnd = (ctx: ConditionalAndContext): Expr => { - this._checkNotNil(ctx); - if (isNil(ctx._e)) { - return this._ensureErrorsExist( - create(StatusSchema, { - code: 1, - message: 'no conditionaland context', - }) - ); - } const result = this.visit(ctx._e); const logicManager = LogicManager.newBalancingLogicManager( LOGICAL_AND_OPERATOR, result ); for (let i = 0; i < ctx._ops.length; i++) { - if (isNil(ctx._e1) || i >= ctx._e1.length) { - return this._reportError(ctx, "unexpected character, wanted '^^'"); + if (i >= ctx._e1.length) { + return this._reportError(ctx, "unexpected character, wanted '&&'"); } const term = this.visit(ctx._e1[i]); logicManager.addTerm(this.#id.nextId(), term); @@ -188,34 +167,21 @@ export class CELParser extends GeneratedCelVisitor { }; override visitRelation = (ctx: RelationContext): Expr => { - this._checkNotNil(ctx); - if (!isNil(ctx.calc())) { - return this.visit(ctx.calc()); - } - if ( - isNil(ctx.relation_list()) || - ctx.relation_list().length === 0 || - isNil(ctx._op) - ) { - return this._ensureErrorsExist( - create(StatusSchema, { - code: 1, - message: 'no relation context', - }) - ); + let opText = ''; + if (!isNil(ctx._op)) { + opText = ctx._op.text; } - const operator = getOperatorFromText(ctx._op.text); + const operator = getOperatorFromText(opText); if (isNil(operator)) { return this._reportError(ctx, 'operator not found'); } const left = this.visit(ctx.relation(0)); const id = this.#id.nextId(); const right = this.visit(ctx.relation(1)); - return this._globalCallOrMacro(id, operator, [left, right]); + return this._globalCallOrMacro(ctx, id, operator, [left, right]); }; override visitCalc = (ctx: CalcContext): Expr => { - this._checkNotNil(ctx); let opText = ''; if (!isNil(ctx._op)) { opText = ctx._op.text; @@ -227,63 +193,32 @@ export class CELParser extends GeneratedCelVisitor { const lhs = this.visit(ctx.calc(0)); const opId = this.#id.nextId(); const rhs = this.visit(ctx.calc(1)); - return this._globalCallOrMacro(opId, operator, [lhs, rhs]); + return this._globalCallOrMacro(ctx, opId, operator, [lhs, rhs]); }; override visitMemberExpr = (ctx: MemberExprContext): Expr => { - this._checkNotNil(ctx); - if (isNil(ctx.member())) { - return this._ensureErrorsExist( - create(StatusSchema, { - code: 1, - message: 'no member expr context', - }) - ); - } return this.visit(ctx.member()); }; override visitLogicalNot = (ctx: LogicalNotContext): Expr => { - this._checkNotNil(ctx); - if (isNil(ctx.member())) { - return this._ensureErrorsExist( - create(StatusSchema, { - code: 1, - message: 'no member expr context', - }) - ); - } if (!isNil(ctx._ops) && ctx._ops.length % 2 === 0) { return this.visit(ctx.member()); } const id = this.#id.nextId(); const target = this.visit(ctx.member()); - return this._globalCallOrMacro(id, LOGICAL_NOT_OPERATOR, [target]); + return this._globalCallOrMacro(ctx, id, LOGICAL_NOT_OPERATOR, [target]); }; override visitNegate = (ctx: NegateContext): Expr => { - this._checkNotNil(ctx); - if (isNil(ctx.member())) { - return this._ensureErrorsExist( - create(StatusSchema, { - code: 1, - message: 'no member context', - }) - ); - } if (isNil(ctx._ops) || ctx._ops.length % 2 === 0) { return this.visit(ctx.member()); } const opId = this.#id.nextId(); const target = this.visit(ctx.member()); - return this._globalCallOrMacro(opId, NEGATE_OPERATOR, [target]); + return this._globalCallOrMacro(ctx, opId, NEGATE_OPERATOR, [target]); }; override visitMemberCall = (ctx: MemberCallContext): Expr => { - this._checkNotNil(ctx); - if (isNil(ctx._id)) { - return this._reportError(ctx, 'no valid identifier specified'); - } const operand = this.visit(ctx.member()); const id = ctx._id.text; const opId = this.#id.nextId(); @@ -291,15 +226,11 @@ export class CELParser extends GeneratedCelVisitor { if (!isNil(ctx._args?.expr_list)) { args = this.visitSlice(ctx._args.expr_list()); } - return this._receiverCallOrMacro(opId, id, operand, args); + return this._receiverCallOrMacro(ctx, opId, id, operand, args); }; override visitSelect = (ctx: SelectContext): Expr => { - this._checkNotNil(ctx); const operand = this.visit(ctx.member()); - if (isNil(ctx._id) || isNil(ctx._op)) { - return this._reportError(ctx, 'no valid identifier specified'); - } const id = ctx._id.text; if (!isNil(ctx._opt)) { if (!this.options?.enableOptionalSyntax) { @@ -343,20 +274,10 @@ export class CELParser extends GeneratedCelVisitor { }; override visitPrimaryExpr = (ctx: PrimaryExprContext): Expr => { - this._checkNotNil(ctx); - if (isNil(ctx.primary())) { - return this._ensureErrorsExist( - create(StatusSchema, { - code: 1, - message: 'no primary expr context', - }) - ); - } return this.visit(ctx.primary()); }; override visitIndex = (ctx: IndexContext): Expr => { - this._checkNotNil(ctx); const target = this.visit(ctx.member()); if (isNil(ctx._op)) { return this._reportError(ctx, 'no valid identifier is specified'); @@ -370,11 +291,10 @@ export class CELParser extends GeneratedCelVisitor { } operator = OPT_INDEX_OPERATOR; } - return this._globalCallOrMacro(opId, operator, [target, index]); + return this._globalCallOrMacro(ctx, opId, operator, [target, index]); }; override visitIdentOrGlobalCall = (ctx: IdentOrGlobalCallContext): Expr => { - this._checkNotNil(ctx); let identName = ''; if (!isNil(ctx._leadingDot)) { identName = '.'; @@ -393,7 +313,7 @@ export class CELParser extends GeneratedCelVisitor { if (!isNil(ctx._args)) { args = this.visitSlice(ctx._args.expr_list()); } - return this._globalCallOrMacro(opId, identName, args); + return this._globalCallOrMacro(ctx, opId, identName, args); } return create(ExprSchema, { id: this.#id.nextId(), @@ -411,7 +331,6 @@ export class CELParser extends GeneratedCelVisitor { // }; override visitCreateList = (ctx: CreateListContext): Expr => { - this._checkNotNil(ctx); const listId = this.#id.nextId(); let elements: Expr[] = []; let optionalIndices: number[] = []; @@ -437,18 +356,13 @@ export class CELParser extends GeneratedCelVisitor { }; override visitCreateStruct = (ctx: CreateStructContext): Expr => { - this._checkNotNil(ctx); const structId = this.#id.nextId(); let entries: Expr_CreateStruct_Entry[] = []; if (!isNil(ctx._entries)) { const mapInit = this.visit(ctx._entries); if (mapInit.exprKind.case !== 'structExpr') { - return this._ensureErrorsExist( - create(StatusSchema, { - code: 1, - message: 'no struct initializer', - }) - ); + // This should never happen, but just in case. + return this._reportError(ctx, 'no struct initializer'); } entries = mapInit.exprKind.value.entries; } @@ -464,7 +378,6 @@ export class CELParser extends GeneratedCelVisitor { }; override visitCreateMessage = (ctx: CreateMessageContext): Expr => { - this._checkNotNil(ctx); let messageName = ''; for (const id of ctx._ids) { if (messageName.length !== 0) { @@ -481,6 +394,10 @@ export class CELParser extends GeneratedCelVisitor { const initializer = this.visit(ctx._entries); const entriesInitializer = initializer.exprKind .value as Expr_CreateStruct; + if (isNil(entriesInitializer)) { + // This is the result of a syntax error detected elsewhere. + return create(ExprSchema); + } entries = entriesInitializer.entries; } return create(ExprSchema, { @@ -496,23 +413,10 @@ export class CELParser extends GeneratedCelVisitor { }; override visitConstantLiteral = (ctx: ConstantLiteralContext): Expr => { - this._checkNotNil(ctx); const expr = this.visit(ctx.literal()); - if (isNil(expr)) { - return this._ensureErrorsExist( - create(StatusSchema, { - code: 1, - message: 'no literal context', - }) - ); - } if (expr.exprKind.case !== 'constExpr') { - return this._ensureErrorsExist( - create(StatusSchema, { - code: 1, - message: 'no constant context', - }) - ); + // This should never happen, but just in case. + return this._reportError(ctx, 'expr is not a constant'); } return create(ExprSchema, { id: this.#id.nextId(), @@ -524,7 +428,6 @@ export class CELParser extends GeneratedCelVisitor { }; override visitExprList = (ctx: ExprListContext): Expr => { - this._checkNotNil(ctx); return create(ExprSchema, { id: this.#id.nextId(), exprKind: { @@ -537,7 +440,6 @@ export class CELParser extends GeneratedCelVisitor { }; override visitListInit = (ctx: ListInitContext): Expr => { - this._checkNotNil(ctx); const elements = ctx._elems; const result: Expr[] = []; const optionals: number[] = []; @@ -577,28 +479,18 @@ export class CELParser extends GeneratedCelVisitor { override visitFieldInitializerList = ( ctx: FieldInitializerListContext ): Expr => { - this._checkNotNil(ctx); const fields: Expr_CreateStruct_Entry[] = []; for (let i = 0; i < ctx._fields.length; i++) { if (i >= ctx._values.length || i >= ctx._fields.length) { - return this._ensureErrorsExist( - create(StatusSchema, { - code: 1, - message: 'no field initializer list', - }) - ); + // This is the result of a syntax error detected elsewhere. + return create(ExprSchema); } const field = ctx._fields[i]; const exprId = this.#id.nextId(); const optionalEntry = !isNil(field._opt); const id = field.IDENTIFIER(); if (isNil(id)) { - return this._ensureErrorsExist( - create(StatusSchema, { - code: 1, - message: 'no field identifier', - }) - ); + return this._reportError(ctx, 'no valid identifier specified'); } fields.push( create(Expr_CreateStruct_EntrySchema, { @@ -628,16 +520,11 @@ export class CELParser extends GeneratedCelVisitor { // }; override visitMapInitializerList = (ctx: MapInitializerListContext): Expr => { - this._checkNotNil(ctx); const fields: Expr_CreateStruct_Entry[] = []; for (let i = 0; i < ctx._cols.length; i++) { if (i >= ctx._values.length || i >= ctx._cols.length) { - return this._ensureErrorsExist( - create(StatusSchema, { - code: 1, - message: 'no field initializer list', - }) - ); + // This is the result of a syntax error detected elsewhere. + return create(ExprSchema); } const colId = this.#id.nextId(); const optKey = ctx._keys[i]; @@ -672,7 +559,6 @@ export class CELParser extends GeneratedCelVisitor { // }; override visitInt = (ctx: IntContext): Expr => { - this._checkNotNil(ctx); const constant = parseIntConstant(ctx.getText()); // TODO: parse error handling return create(ExprSchema, { @@ -685,7 +571,6 @@ export class CELParser extends GeneratedCelVisitor { }; override visitUint = (ctx: UintContext): Expr => { - this._checkNotNil(ctx); const constant = parseUintConstant(ctx.getText()); // TODO: parse error handling return create(ExprSchema, { @@ -698,7 +583,6 @@ export class CELParser extends GeneratedCelVisitor { }; override visitDouble = (ctx: DoubleContext): Expr => { - this._checkNotNil(ctx); const constant = parseDoubleConstant(ctx.getText()); // TODO: parse error handling return create(ExprSchema, { @@ -711,7 +595,6 @@ export class CELParser extends GeneratedCelVisitor { }; override visitString = (ctx: StringContext): Expr => { - this._checkNotNil(ctx); const constant = parseStringConstant(ctx.getText()); // TODO: parse error handling return create(ExprSchema, { @@ -724,7 +607,6 @@ export class CELParser extends GeneratedCelVisitor { }; override visitBytes = (ctx: BytesContext): Expr => { - this._checkNotNil(ctx); const constant = parseBytesConstant(ctx.getText()); // TODO: parse error handling return create(ExprSchema, { @@ -737,7 +619,6 @@ export class CELParser extends GeneratedCelVisitor { }; override visitBoolTrue = (ctx: BoolTrueContext): Expr => { - this._checkNotNil(ctx); assert(ctx.getText() === 'true', new ParseException('true expected', 0)); return create(ExprSchema, { id: this.#id.nextId(), @@ -754,7 +635,6 @@ export class CELParser extends GeneratedCelVisitor { }; override visitBoolFalse = (ctx: BoolFalseContext): Expr => { - this._checkNotNil(ctx); assert(ctx.getText() === 'false', new ParseException('false expected', 0)); return create(ExprSchema, { id: this.#id.nextId(), @@ -771,7 +651,6 @@ export class CELParser extends GeneratedCelVisitor { }; override visitNull = (ctx: NullContext): Expr => { - this._checkNotNil(ctx); assert(ctx.getText() === 'null', new ParseException('null expected', 0)); return create(ExprSchema, { id: this.#id.nextId(), @@ -794,45 +673,6 @@ export class CELParser extends GeneratedCelVisitor { return expressions.map((e) => this.visit(e)); }; - private _checkNotNil(value: unknown, message?: string): asserts value { - if (isNil(value)) { - throw new NullException(message || 'value is nil'); - } - } - - private _ensureErrorsExist(status: Status) { - this.errors.errors.push(status); - return create(ExprSchema, { - id: this.#id.nextId(), - exprKind: { - case: 'constExpr', - value: this.#ERROR, - }, - }); - } - - private _reportError(context: ParserRuleContext, message: string) { - return this._ensureErrorsExist( - create(StatusSchema, { - code: 1, - message, - details: [ - anyPack( - SourceInfoSchema, - create(SourceInfoSchema, { - location: `${context.start.line}:${context.start.column}`, - // TODO: more info - }) - ), - anyPack( - StringValueSchema, - fromJson(StringValueSchema, this.env.astAsString(context.getText())) - ), - ], - }) - ); - } - private _unnest(tree: ParseTree) { while (tree != null) { if (tree instanceof ExprContext) { @@ -892,8 +732,13 @@ export class CELParser extends GeneratedCelVisitor { return tree; } - private _globalCallOrMacro(exprId: bigint, fn: string, args: Expr[]) { - const macro = this._expandMacro(exprId, fn, null, args); + private _globalCallOrMacro( + ctx: ParserRuleContext, + exprId: bigint, + fn: string, + args: Expr[] + ) { + const macro = this._expandMacro(ctx, fn, null, args); if (!isNil(macro)) { return macro; } @@ -910,12 +755,13 @@ export class CELParser extends GeneratedCelVisitor { } private _receiverCallOrMacro( + ctx: ParserRuleContext, exprId: bigint, fn: string, target: Expr, args: Expr[] ) { - const macro = this._expandMacro(exprId, fn, target, args); + const macro = this._expandMacro(ctx, fn, target, args); if (!isNil(macro)) { return macro; } @@ -933,7 +779,7 @@ export class CELParser extends GeneratedCelVisitor { } private _expandMacro( - exprId: bigint, + ctx: ParserRuleContext, fn: string, target: Expr | null, args: Expr[] @@ -946,12 +792,29 @@ export class CELParser extends GeneratedCelVisitor { const expanded = expandMacro(this.#id, macro, target, args); return expanded; } catch (e) { - return this._ensureErrorsExist( - create(StatusSchema, { - code: 1, - message: (e as Error).message, - }) - ); + return this._reportError(ctx, (e as Error).message); } } + + private _reportError(ctx: ParserRuleContext, message: string) { + const error = create(ExprSchema, { + id: this.#id.nextId(), + exprKind: { + case: 'constExpr', + value: { + constantKind: { + case: 'stringValue', + value: '<>', + }, + }, + }, + }); + this.#errors.reportErrorAtId( + error.id, + ctx.start.line, + ctx.start.column, + message + ); + return error; + } } diff --git a/packages/cel/src/lib/program.ts b/packages/cel/src/lib/program.ts index 0ed39f4..eca28a8 100644 --- a/packages/cel/src/lib/program.ts +++ b/packages/cel/src/lib/program.ts @@ -1,20 +1,9 @@ import { CELEnvironment } from './environment'; import { StartContext } from './gen/CELParser'; -import { CELParser } from './parser'; export class CELProgram { constructor( public readonly env: CELEnvironment, public readonly ast: StartContext ) {} - - parse() { - const parser = new CELParser(this.env); - return this.ast.accept(parser); - } - - errors() { - const parser = new CELParser(this.env); - return parser.errors; - } } diff --git a/packages/cel/vite.config.ts b/packages/cel/vite.config.ts index 9c44967..8017d0a 100644 --- a/packages/cel/vite.config.ts +++ b/packages/cel/vite.config.ts @@ -1,9 +1,9 @@ /// +import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin'; +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; +import * as path from 'path'; import { defineConfig } from 'vite'; import dts from 'vite-plugin-dts'; -import * as path from 'path'; -import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; -import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin'; export default defineConfig({ root: __dirname, @@ -58,5 +58,11 @@ export default defineConfig({ reportsDirectory: '../../coverage/packages/cel', provider: 'v8', }, + onConsoleLog(log: string, type: 'stdout' | 'stderr'): false | void { + console.log('log in test: ', log); + if (log === 'message from third party library' && type === 'stdout') { + return false; + } + }, }, }); From 0eb02a812fc6db737ca6cce66789e821d9919395 Mon Sep 17 00:00:00 2001 From: jafaircl Date: Wed, 2 Oct 2024 08:42:34 -0400 Subject: [PATCH 09/34] feat(cel): add recursion errors --- packages/cel/src/lib/errors.ts | 48 ++++++++++++++------- packages/cel/src/lib/parser.spec.ts | 25 +++++------ packages/cel/src/lib/parser.ts | 66 +++++++++++++++++++++++++++-- 3 files changed, 106 insertions(+), 33 deletions(-) diff --git a/packages/cel/src/lib/errors.ts b/packages/cel/src/lib/errors.ts index b81a05d..843e92e 100644 --- a/packages/cel/src/lib/errors.ts +++ b/packages/cel/src/lib/errors.ts @@ -56,10 +56,31 @@ export class Errors { this.errors.errors.push(err); } + public reportInternalError(message: string) { + this.reportError(-1, -1, message); + } + + public reportSyntaxError(line: number, column: number, message: string) { + this.reportError(line, column, `Syntax error: ${message}`); + } + public toDisplayString() { - return this.errors.errors - .map((err) => this._errorToDisplayString(err)) - .join('\n '); + let hasRecursionError = false; + const errors = []; + for (const error of this.errors.errors) { + const str = this._errorToDisplayString(error); + // Deduplicate recursion errors. + if (str.includes('expression recursion limit exceeded')) { + if (!hasRecursionError) { + hasRecursionError = true; + errors.push(str); + } + } else { + errors.push(str); + } + } + + return errors.join('\n '); } private _errorToDisplayString(err: Status) { @@ -74,6 +95,9 @@ export class Errors { const result = `ERROR: ${this.sourceDescription}:${line}:${column + 1}: ${ err.message }`; + if (line < 0 || column < 0) { + return result; + } const sourceLine = '\n | ' + this.source.split('\n')[line - 1]; let indLine = '\n | '; for (let i = 0; i < column; i++) { @@ -97,12 +121,7 @@ export class LexerErrorListener extends ErrorListener { msg: string, e: RecognitionException | undefined ): void { - this.errors.reportErrorAtId( - BigInt(offendingSymbol ?? 0), - line, - charPositionInLine, - `Syntax error: ${msg}` - ); + this.errors.reportSyntaxError(line, charPositionInLine, msg); } } @@ -119,11 +138,10 @@ export class ParserErrorListener extends ErrorListener { msg: string, e: RecognitionException | undefined ): void { - this.errors.reportErrorAtId( - BigInt(offendingSymbol?.tokenIndex ?? 0), - line, - charPositionInLine, - `Syntax error: ${msg}` - ); + if (msg.startsWith('expression recursion limit exceeded')) { + this.errors.reportInternalError(msg); + } else { + this.errors.reportSyntaxError(line, charPositionInLine, msg); + } } } diff --git a/packages/cel/src/lib/parser.spec.ts b/packages/cel/src/lib/parser.spec.ts index b515fc2..62b75e5 100644 --- a/packages/cel/src/lib/parser.spec.ts +++ b/packages/cel/src/lib/parser.spec.ts @@ -1,9 +1,7 @@ import { Expr } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb'; /* eslint-disable no-useless-escape */ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { - ExprSchema -} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { ExprSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; import { create } from '@bufbuild/protobuf'; import { NullValue } from '@bufbuild/protobuf/wkt'; import { CELParser } from './parser'; @@ -4655,15 +4653,14 @@ const testCases: TestInfo[] = [ // | a ? b ((?)) // | ...........^`, // }, - // TODO: recusion errors - // { - // I: `[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ - // [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[['too many']]]]]]]]]]]]]]]]]]]]]]]]]]]] - // ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]`, - // E: "ERROR: :-1:0: expression recursion limit exceeded: 32", - // }, - // { - // I: `-[-1--1--1--1---1--1--1--0--1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1 + { + I: `[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ + [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[['too many']]]]]]]]]]]]]]]]]]]]]]]]]]]] + ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]`, + E: 'ERROR: :-1:0: expression recursion limit exceeded: 32', + }, + // { // TODO: the error order is wrong + // I: `-[-1--1--1--1---1--1--1--0--1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1 // --3-[-1--1--1--1---1--1--1--0--1--1--1--1--0--3--1--1--0--1--1--1--1--0--1--1--1 // --3-[-1--1--1--1---1--1--1--0-/1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1 // --3-[-1--1--1--1---1--1--1--0--1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1 @@ -4697,7 +4694,7 @@ const testCases: TestInfo[] = [ // --1---1--1--1--0--1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1--3-[-1--1--1 // --1---1--1--1--0--1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1--3-[-1--1--1 // --1---1--1--1--0--1--1--1--1--0--3--1--1--0--1`, - // E: `ERROR: :-1:0: expression recursion limit exceeded: 32 + // E: `ERROR: :-1:0: expression recursion limit exceeded: 32 // ERROR: :3:33: Syntax error: extraneous input '/' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} // | --3-[-1--1--1--1---1--1--1--0-/1--1--1--1--0--2--1--1--0--1--1--1--1--0--1--1--1 // | ................................^ @@ -4718,7 +4715,7 @@ describe('CELVisitor', () => { for (const testCase of testCases) { it(`should parse ${testCase.I}`, () => { // Arrange - const parser = new CELParser(testCase.I); + const parser = new CELParser(testCase.I, { maxRecursionDepth: 32 }); // Act const expr = parser.parse(); diff --git a/packages/cel/src/lib/parser.ts b/packages/cel/src/lib/parser.ts index 0f4ef74..4dbb04e 100644 --- a/packages/cel/src/lib/parser.ts +++ b/packages/cel/src/lib/parser.ts @@ -13,7 +13,9 @@ import { CharStream, CommonTokenStream, ParseTree, + ParseTreeListener, ParserRuleContext, + Token, } from 'antlr4'; import { RESERVED_IDS, @@ -79,16 +81,21 @@ import { IdHelper } from './utils'; export class CELParser extends GeneratedCelVisitor { #id = new IdHelper(); readonly #errors!: Errors; + readonly #maxRecursionDepth: number = 100; constructor( public readonly source: string, private readonly options?: { enableOptionalSyntax?: boolean; retainRepeatedUnaryOperators?: boolean; + maxRecursionDepth?: number; } ) { super(); this.#errors = new Errors(source); + if (this.options?.maxRecursionDepth) { + this.#maxRecursionDepth = this.options.maxRecursionDepth; + } } public get errors() { @@ -99,14 +106,13 @@ export class CELParser extends GeneratedCelVisitor { const chars = new CharStream(this.source); const lexer = new CELLexer(chars); lexer.removeErrorListeners(); - const lexerErrorListener = new LexerErrorListener(this.#errors); - lexer.addErrorListener(lexerErrorListener); + lexer.addErrorListener(new LexerErrorListener(this.#errors)); const tokens = new CommonTokenStream(lexer); const parser = new GenCELParser(tokens); parser.removeErrorListeners(); - const parserErrorListener = new ParserErrorListener(this.#errors); - parser.addErrorListener(parserErrorListener); + parser.addErrorListener(new ParserErrorListener(this.#errors)); + parser.addParseListener(new RecursionListener(this.#maxRecursionDepth)); return this.visit(parser.start()); } @@ -818,3 +824,55 @@ export class CELParser extends GeneratedCelVisitor { return error; } } + +class RecursionListener extends ParseTreeListener { + #ruleTypeDepth: Map = new Map(); + #hasNotified = false; + + constructor(private readonly maxDepth: number) { + super(); + } + + override enterEveryRule(ctx: ParserRuleContext): void { + if (isNil(ctx)) { + return; + } + const ruleIndex = (ctx as unknown as { ruleIndex: number }).ruleIndex; + if (isNil(ruleIndex)) { + return; + } + let depth = this.#ruleTypeDepth.get(ruleIndex); + if (isNil(depth)) { + this.#ruleTypeDepth.set(ruleIndex, 0); + depth = 0; + } else { + depth++; + } + this.#ruleTypeDepth.set(ruleIndex, depth); + if (depth > this.maxDepth && !this.#hasNotified) { + const fakeToken = new Token(); + fakeToken.line = -1; + fakeToken.column = -1; + ctx.parser?.notifyErrorListeners( + `expression recursion limit exceeded: ${this.maxDepth}`, + fakeToken, + undefined + ); + } + } + + override exitEveryRule(ctx: ParserRuleContext): void { + if (isNil(ctx)) { + return; + } + const ruleIndex = (ctx as unknown as { ruleIndex: number }).ruleIndex; + if (isNil(ruleIndex)) { + return; + } + let depth = this.#ruleTypeDepth.get(ruleIndex); + if (!isNil(depth)) { + depth--; + this.#ruleTypeDepth.set(ruleIndex, depth); + } + } +} From 532c0352146718b9ae0be2870657bc0d218b4663 Mon Sep 17 00:00:00 2001 From: jafaircl Date: Wed, 2 Oct 2024 14:43:59 -0400 Subject: [PATCH 10/34] feat(cel): pass ids to utility functions instead of id helper --- packages/cel/src/lib/macros.ts | 165 +++++++++++++++++---------------- packages/cel/src/lib/utils.ts | 52 ++++------- 2 files changed, 105 insertions(+), 112 deletions(-) diff --git a/packages/cel/src/lib/macros.ts b/packages/cel/src/lib/macros.ts index dcb8ce2..f66dba9 100644 --- a/packages/cel/src/lib/macros.ts +++ b/packages/cel/src/lib/macros.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ import { isNil } from '@bearclaw/is'; import { Expr, @@ -21,14 +22,8 @@ import { MAP_MACRO, NOT_STRICTLY_FALSE_OPERATOR, } from './operators'; -import { - IdHelper, - boolExpr, - globalCall, - identExpr, - int64Expr, - listExpr, -} from './utils'; +import { ParserHelper } from './parser-helper'; +import { boolExpr, globalCall, identExpr, int64Expr, listExpr } from './utils'; export const STANDARD_MACROS = new Set([ HAS_MACRO, @@ -45,36 +40,36 @@ export function findMacro(name: string) { } export function expandMacro( - id: IdHelper, + helper: ParserHelper, op: string, target: Expr | null, args: Expr[] ): Expr { switch (op) { case HAS_MACRO: - return expandHasMacro(id, args); + return expandHasMacro(helper, args); case ALL_MACRO: - return expandAllMacro(id, target!, args); + return expandAllMacro(helper, target!, args); case EXISTS_MACRO: - return expandExistsMacro(id, target!, args); + return expandExistsMacro(helper, target!, args); case EXISTS_ONE_MACRO: - return expandExistsOneMacro(id, target!, args); + return expandExistsOneMacro(helper, target!, args); case MAP_MACRO: - return expandMapMacro(id, target!, args); + return expandMapMacro(helper, target!, args); case FILTER_MACRO: - return expandFilterMacro(id, target!, args); + return expandFilterMacro(helper, target!, args); default: throw new Error(`Unknown macro: ${op}`); } } -export function expandHasMacro(id: IdHelper, args: Expr[]): Expr { +export function expandHasMacro(helper: ParserHelper, args: Expr[]): Expr { const arg = args[0]; if (arg.exprKind.case !== 'selectExpr') { throw new Error('Invalid argument to has() macro'); } return create(ExprSchema, { - id: id.nextId(), + id: helper.nextId(), exprKind: { case: 'selectExpr', value: create(Expr_SelectSchema, { @@ -86,27 +81,33 @@ export function expandHasMacro(id: IdHelper, args: Expr[]): Expr { }); } -export function expandAllMacro(id: IdHelper, target: Expr, args: Expr[]): Expr { +export function expandAllMacro( + helper: ParserHelper, + target: Expr, + args: Expr[] +): Expr { const arg0 = args[0]; if (arg0.exprKind.case !== 'identExpr') { throw new Error('Invalid argument to all() macro'); } const arg1 = args[1]; - const accuInit = boolExpr(id, true); + const accuInit = boolExpr(helper.nextId(), true); + const conditionArg0 = identExpr(helper.nextId(), ACCUMULATOR_VAR); const condition = globalCall( - id, + helper.nextId(), NOT_STRICTLY_FALSE_OPERATOR, - identExpr(id, ACCUMULATOR_VAR) + conditionArg0 ); + const stepArg0 = identExpr(helper.nextId(), ACCUMULATOR_VAR); const step = globalCall( - id, + helper.nextId(), LOGICAL_AND_OPERATOR, - identExpr(id, ACCUMULATOR_VAR), + stepArg0, arg1 ); - const result = identExpr(id, ACCUMULATOR_VAR); + const result = identExpr(helper.nextId(), ACCUMULATOR_VAR); return fold( - id.nextId(), + helper.nextId(), target, arg0.exprKind.value.name, ACCUMULATOR_VAR, @@ -118,7 +119,7 @@ export function expandAllMacro(id: IdHelper, target: Expr, args: Expr[]): Expr { } export function expandExistsMacro( - id: IdHelper, + helper: ParserHelper, target: Expr, args: Expr[] ): Expr { @@ -127,21 +128,23 @@ export function expandExistsMacro( throw new Error('Invalid argument to exists() macro'); } const arg1 = args[1]; - const accuInit = boolExpr(id, false); + const accuInit = boolExpr(helper.nextId(), false); + const conditionArg0Arg0 = identExpr(helper.nextId(), ACCUMULATOR_VAR); + const conditionArg0 = globalCall( + helper.nextId(), + LOGICAL_NOT_OPERATOR, + conditionArg0Arg0 + ); const condition = globalCall( - id, + helper.nextId(), NOT_STRICTLY_FALSE_OPERATOR, - globalCall(id, LOGICAL_NOT_OPERATOR, identExpr(id, ACCUMULATOR_VAR)) + conditionArg0 ); - const step = globalCall( - id, - LOGICAL_OR_OPERATOR, - identExpr(id, ACCUMULATOR_VAR), - arg1 - ); - const result = identExpr(id, ACCUMULATOR_VAR); + const stepArg0 = identExpr(helper.nextId(), ACCUMULATOR_VAR); + const step = globalCall(helper.nextId(), LOGICAL_OR_OPERATOR, stepArg0, arg1); + const result = identExpr(helper.nextId(), ACCUMULATOR_VAR); return fold( - id.nextId(), + helper.nextId(), target, arg0.exprKind.value.name, ACCUMULATOR_VAR, @@ -153,7 +156,7 @@ export function expandExistsMacro( } export function expandExistsOneMacro( - id: IdHelper, + helper: ParserHelper, target: Expr, args: Expr[] ): Expr { @@ -162,28 +165,34 @@ export function expandExistsOneMacro( throw new Error('Invalid argument to exists_one() macro'); } const arg1 = args[1]; - const accuInit = int64Expr(id, BigInt(0)); - const condition = boolExpr(id, true); + const accuInit = int64Expr(helper.nextId(), BigInt(0)); + const condition = boolExpr(helper.nextId(), true); + const stepArg1Arg0 = identExpr(helper.nextId(), ACCUMULATOR_VAR); + const stepArg1Arg1 = int64Expr(helper.nextId(), BigInt(1)); + const stepArg1 = globalCall( + helper.nextId(), + ADD_OPERATOR, + stepArg1Arg0, + stepArg1Arg1 + ); + const stepArg2 = identExpr(helper.nextId(), ACCUMULATOR_VAR); const step = globalCall( - id, + helper.nextId(), CONDITIONAL_OPERATOR, arg1, - globalCall( - id, - ADD_OPERATOR, - identExpr(id, ACCUMULATOR_VAR), - int64Expr(id, BigInt(1)) - ), - identExpr(id, ACCUMULATOR_VAR) + stepArg1, + stepArg2 ); + const resultArg0 = identExpr(helper.nextId(), ACCUMULATOR_VAR); + const resultArg1 = int64Expr(helper.nextId(), BigInt(1)); const result = globalCall( - id, + helper.nextId(), EQUALS_OPERATOR, - identExpr(id, ACCUMULATOR_VAR), - int64Expr(id, BigInt(1)) + resultArg0, + resultArg1 ); return fold( - id.nextId(), + helper.nextId(), target, arg0.exprKind.value.name, ACCUMULATOR_VAR, @@ -194,7 +203,11 @@ export function expandExistsOneMacro( ); } -export function expandMapMacro(id: IdHelper, target: Expr, args: Expr[]): Expr { +export function expandMapMacro( + helper: ParserHelper, + target: Expr, + args: Expr[] +): Expr { const v = extractIdent(args[0]); if (isNil(v)) { throw new Error('argument is not an identifier'); @@ -207,26 +220,24 @@ export function expandMapMacro(id: IdHelper, target: Expr, args: Expr[]): Expr { } else { fn = args[1]; } - const init = listExpr(id, []); - const condition = boolExpr(id, true); - let step = globalCall( - id, - ADD_OPERATOR, - identExpr(id, ACCUMULATOR_VAR), - listExpr(id, [fn]) - ); + const init = listExpr(helper.nextId(), []); + const condition = boolExpr(helper.nextId(), true); + const stepArg0 = identExpr(helper.nextId(), ACCUMULATOR_VAR); + const stepArg1 = listExpr(helper.nextId(), [fn]); + let step = globalCall(helper.nextId(), ADD_OPERATOR, stepArg0, stepArg1); if (!isNil(filter)) { + const step2Arg2 = identExpr(helper.nextId(), ACCUMULATOR_VAR); step = globalCall( - id, + helper.nextId(), CONDITIONAL_OPERATOR, filter, step, - identExpr(id, ACCUMULATOR_VAR) + step2Arg2 ); } - const result = identExpr(id, ACCUMULATOR_VAR); + const result = identExpr(helper.nextId(), ACCUMULATOR_VAR); return fold( - id.nextId(), + helper.nextId(), target, v, ACCUMULATOR_VAR, @@ -238,7 +249,7 @@ export function expandMapMacro(id: IdHelper, target: Expr, args: Expr[]): Expr { } export function expandFilterMacro( - id: IdHelper, + helper: ParserHelper, target: Expr, args: Expr[] ): Expr { @@ -247,24 +258,22 @@ export function expandFilterMacro( throw new Error('argument is not an identifier'); } const filter = args[1]; - const listInit = listExpr(id, []); - const condition = boolExpr(id, true); - let step = globalCall( - id, - ADD_OPERATOR, - identExpr(id, ACCUMULATOR_VAR), - listExpr(id, [args[0]]) - ); + const listInit = listExpr(helper.nextId(), []); + const condition = boolExpr(helper.nextId(), true); + const stepArg0 = identExpr(helper.nextId(), ACCUMULATOR_VAR); + const stepArg1 = listExpr(helper.nextId(), [args[0]]); + let step = globalCall(helper.nextId(), ADD_OPERATOR, stepArg0, stepArg1); + const step2Arg1 = identExpr(helper.nextId(), ACCUMULATOR_VAR); step = globalCall( - id, + helper.nextId(), CONDITIONAL_OPERATOR, filter, step, - identExpr(id, ACCUMULATOR_VAR) + step2Arg1 ); - const result = identExpr(id, ACCUMULATOR_VAR); + const result = identExpr(helper.nextId(), ACCUMULATOR_VAR); return fold( - id.nextId(), + helper.nextId(), target, v, ACCUMULATOR_VAR, diff --git a/packages/cel/src/lib/utils.ts b/packages/cel/src/lib/utils.ts index e176795..c717932 100644 --- a/packages/cel/src/lib/utils.ts +++ b/packages/cel/src/lib/utils.ts @@ -52,9 +52,9 @@ export function boolConstant(value: boolean) { }); } -export function boolExpr(id: IdHelper, value: boolean) { +export function boolExpr(id: bigint, value: boolean) { return create(ExprSchema, { - id: id.nextId(), + id, exprKind: { case: 'constExpr', value: boolConstant(value), @@ -80,9 +80,9 @@ export function int64Constant(value: bigint) { }); } -export function int64Expr(id: IdHelper, value: bigint) { +export function int64Expr(id: bigint, value: bigint) { return create(ExprSchema, { - id: id.nextId(), + id, exprKind: { case: 'constExpr', value: int64Constant(value), @@ -108,9 +108,9 @@ export function uint64Constant(value: bigint) { }); } -export function uint64Expr(id: IdHelper, value: bigint) { +export function uint64Expr(id: bigint, value: bigint) { return create(ExprSchema, { - id: id.nextId(), + id, exprKind: { case: 'constExpr', value: uint64Constant(value), @@ -136,9 +136,9 @@ export function doubleConstant(value: number) { }); } -export function doubleExpr(id: IdHelper, value: number) { +export function doubleExpr(id: bigint, value: number) { return create(ExprSchema, { - id: id.nextId(), + id, exprKind: { case: 'constExpr', value: doubleConstant(value), @@ -164,9 +164,9 @@ export function stringConstant(value: string) { }); } -export function stringExpr(id: IdHelper, value: string) { +export function stringExpr(id: bigint, value: string) { return create(ExprSchema, { - id: id.nextId(), + id, exprKind: { case: 'constExpr', value: stringConstant(value), @@ -192,9 +192,9 @@ export function bytesConstant(value: Uint8Array) { }); } -export function bytesExpr(id: IdHelper, value: Uint8Array) { +export function bytesExpr(id: bigint, value: Uint8Array) { return create(ExprSchema, { - id: id.nextId(), + id, exprKind: { case: 'constExpr', value: bytesConstant(value), @@ -233,9 +233,9 @@ export const NULL_VALUE = create(ValueSchema, { }, }); -export function identExpr(id: IdHelper, name: string) { +export function identExpr(id: bigint, name: string) { return create(ExprSchema, { - id: id.nextId(), + id, exprKind: { case: 'identExpr', value: create(Expr_IdentSchema, { @@ -245,13 +245,9 @@ export function identExpr(id: IdHelper, name: string) { }); } -export function globalCall( - id: IdHelper, - functionName: string, - ...args: Expr[] -) { +export function globalCall(id: bigint, functionName: string, ...args: Expr[]) { return create(ExprSchema, { - id: id.nextId(), + id, exprKind: { case: 'callExpr', value: { @@ -262,9 +258,9 @@ export function globalCall( }); } -export function listExpr(id: IdHelper, exprs: Expr[]) { +export function listExpr(id: bigint, exprs: Expr[]) { return create(ExprSchema, { - id: id.nextId(), + id, exprKind: { case: 'listExpr', value: { @@ -287,15 +283,3 @@ export function unquote(str: string) { } return str; } - -export class IdHelper { - #id = BigInt(1); - - public currentId() { - return this.#id; - } - - public nextId() { - return this.#id++; - } -} From e9857b80bdaf50ca6af582b2e9404c60bf0702b6 Mon Sep 17 00:00:00 2001 From: jafaircl Date: Thu, 3 Oct 2024 08:18:36 -0400 Subject: [PATCH 11/34] feat(cel): add source info --- packages/cel/src/lib/errors.ts | 41 +++++--- packages/cel/src/lib/parser-helper.spec.ts | 27 +++++ packages/cel/src/lib/parser-helper.ts | 101 ++++++++++++++++++ packages/cel/src/lib/parser.spec.ts | 5 +- packages/cel/src/lib/parser.ts | 115 +++++++++++---------- packages/cel/src/lib/types.ts | 9 ++ 6 files changed, 226 insertions(+), 72 deletions(-) create mode 100644 packages/cel/src/lib/parser-helper.spec.ts create mode 100644 packages/cel/src/lib/parser-helper.ts create mode 100644 packages/cel/src/lib/types.ts diff --git a/packages/cel/src/lib/errors.ts b/packages/cel/src/lib/errors.ts index 843e92e..3a54f24 100644 --- a/packages/cel/src/lib/errors.ts +++ b/packages/cel/src/lib/errors.ts @@ -11,6 +11,7 @@ import { import { create, createRegistry } from '@bufbuild/protobuf'; import { anyPack, anyUnpack } from '@bufbuild/protobuf/wkt'; import { ErrorListener, RecognitionException, Recognizer, Token } from 'antlr4'; +import { Location } from './types'; export class Errors { public readonly errors = create(ErrorSetSchema); @@ -22,16 +23,11 @@ export class Errors { public readonly maxErrorsToReport = 100 ) {} - public reportError(line: number, column: number, message: string) { - this.reportErrorAtId(BigInt(0), line, column, message); + public reportError(location: Location, message: string) { + this.reportErrorAtId(BigInt(0), location, message); } - public reportErrorAtId( - id: bigint, - line: number, - column: number, - message: string - ) { + public reportErrorAtId(id: bigint, location: Location, message: string) { this.numErrors++; if (this.numErrors > this.maxErrorsToReport) { return; @@ -44,10 +40,10 @@ export class Errors { SourceInfoSchema, create(SourceInfoSchema, { positions: { - [id.toString()]: column, + [id.toString()]: location.column, }, - lineOffsets: [line], - location: `${line}:${column}`, + lineOffsets: [location.line], + location: `${location.line}:${location.column}`, syntaxVersion: 'cel1', }) ), @@ -57,11 +53,24 @@ export class Errors { } public reportInternalError(message: string) { - this.reportError(-1, -1, message); + this.reportError({ line: -1, column: -1 }, message); } - public reportSyntaxError(line: number, column: number, message: string) { - this.reportError(line, column, `Syntax error: ${message}`); + public reportSyntaxError(location: Location, message: string) { + this.reportError(location, `Syntax error: ${message}`); + } + + public reportUnexpectedAstTypeError( + id: bigint, + location: Location, + kind: string, + typeName: string + ) { + return this.reportErrorAtId( + id, + location, + `unexpected ${kind} type: ${typeName}` + ); } public toDisplayString() { @@ -121,7 +130,7 @@ export class LexerErrorListener extends ErrorListener { msg: string, e: RecognitionException | undefined ): void { - this.errors.reportSyntaxError(line, charPositionInLine, msg); + this.errors.reportSyntaxError({ line, column: charPositionInLine }, msg); } } @@ -141,7 +150,7 @@ export class ParserErrorListener extends ErrorListener { if (msg.startsWith('expression recursion limit exceeded')) { this.errors.reportInternalError(msg); } else { - this.errors.reportSyntaxError(line, charPositionInLine, msg); + this.errors.reportSyntaxError({ line, column: charPositionInLine }, msg); } } } diff --git a/packages/cel/src/lib/parser-helper.spec.ts b/packages/cel/src/lib/parser-helper.spec.ts new file mode 100644 index 0000000..ad68ade --- /dev/null +++ b/packages/cel/src/lib/parser-helper.spec.ts @@ -0,0 +1,27 @@ +import { ParserHelper } from './parser-helper'; + +describe('ParserHelper', () => { + it('should compute the line offsets', () => { + const source = 'c.d &&\n\t b.c.arg(10) &&\n\t test(10)'; + const helper = new ParserHelper(source); + expect(helper.sourceInfo.lineOffsets).toEqual([7, 24, 35]); + }); + + it('should compute the offset', () => { + const source = 'c.d &&\n\t b.c.arg(10) &&\n\t test(10)'; + const helper = new ParserHelper(source); + expect(helper.computeOffset(1, 0)).toEqual(0); + expect(helper.computeOffset(1, 5)).toEqual(5); + expect(helper.computeOffset(2, 1)).toEqual(8); + expect(helper.computeOffset(3, 1)).toEqual(25); + }); + + it('should get the location by offset', () => { + const source = 'c.d &&\n\t b.c.arg(10) &&\n\t test(10)'; + const helper = new ParserHelper(source); + expect(helper.getLocationByOffset(0)).toEqual({ line: 1, column: 0 }); + expect(helper.getLocationByOffset(5)).toEqual({ line: 1, column: 5 }); + expect(helper.getLocationByOffset(8)).toEqual({ line: 2, column: 1 }); + expect(helper.getLocationByOffset(25)).toEqual({ line: 3, column: 1 }); + }); +}); diff --git a/packages/cel/src/lib/parser-helper.ts b/packages/cel/src/lib/parser-helper.ts new file mode 100644 index 0000000..0550c38 --- /dev/null +++ b/packages/cel/src/lib/parser-helper.ts @@ -0,0 +1,101 @@ +import { SourceInfoSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb'; +import { create } from '@bufbuild/protobuf'; +import { ParserRuleContext, Token } from 'antlr4'; +import { Location, OffsetRange } from './types'; + +export class ParserHelper { + #id = BigInt(1); + #sourceInfo = create(SourceInfoSchema); + #baseLine = 0; + #baseColumn = 0; + + constructor(public readonly source: string) { + this._computeSourceOffsets(source); + } + + public get sourceInfo() { + return this.#sourceInfo; + } + + public currentId() { + return this.#id; + } + + public nextId(ctx?: ParserRuleContext | Token | Location | OffsetRange) { + const id = this.#id++; + if (ctx) { + let offsetRange: OffsetRange = { start: 0, stop: 0 }; + if (ctx instanceof ParserRuleContext) { + offsetRange.start = this.computeOffset( + ctx.start.line, + ctx.start.column + ); + offsetRange.stop = offsetRange.start + ctx.getText().length; + } else if (ctx instanceof Token) { + offsetRange.start = this.computeOffset(ctx.line, ctx.column); + offsetRange.stop = offsetRange.start + ctx.text.length; + } else if ('line' in ctx && 'column' in ctx) { + // Location + offsetRange.start = this.computeOffset(ctx.line, ctx.column); + offsetRange.stop = offsetRange.start; + } else { + offsetRange = ctx as OffsetRange; + } + this.#sourceInfo.positions[id.toString()] = offsetRange.start; + } + return id; + } + + /** + * calculates the 0-based character offset from a 1-based line and 0-based + * column. + * @param line a 1-based line number + * @param column a 0-based column number + */ + computeOffset(line: number, column: number) { + line = this.#baseLine + line; + column = this.#baseColumn + column; + if (line === 1) { + return column; + } + if (line < 1 || line > this.#sourceInfo.lineOffsets.length) { + return -1; + } + const offset = this.#sourceInfo.lineOffsets[line - 2]; + return offset + column; + } + + /** + * Returns the line and column information for a given character offset. + * + * @param offset the 0-based character offset + * @returns the line and column information + */ + getLocationByOffset(offset: number): Location { + let line = 1; + let column = offset; + for (let i = 0; i < this.#sourceInfo.lineOffsets.length; i++) { + const lineOffset = this.#sourceInfo.lineOffsets[i]; + if (lineOffset > offset) { + break; + } + line++; + column = offset - lineOffset; + } + return { line, column }; + } + + /** + * Computes line offsets for the source code. + * + * @param source the source code + */ + private _computeSourceOffsets(source: string) { + const lines = source.split('\n'); + let offset = 0; + for (const line of lines) { + offset += line.length + 1; + this.#sourceInfo.lineOffsets.push(offset); + } + } +} diff --git a/packages/cel/src/lib/parser.spec.ts b/packages/cel/src/lib/parser.spec.ts index 62b75e5..ba5bf59 100644 --- a/packages/cel/src/lib/parser.spec.ts +++ b/packages/cel/src/lib/parser.spec.ts @@ -1927,7 +1927,6 @@ const testCases: TestInfo[] = [ }, }), }, - { I: `m.all(v, f)`, // P: `__comprehension__( @@ -4722,9 +4721,9 @@ describe('CELVisitor', () => { // Assert if (testCase.P) { - expect(expr).toEqual(testCase.P); + expect(expr.expr).toEqual(testCase.P); } else if (testCase.M) { - expect(expr).toEqual(testCase.M); + expect(expr.expr).toEqual(testCase.M); } else if (testCase.E) { expect(parser.errors.toDisplayString()).toEqual( // Account for the difference in spacing between the test case and diff --git a/packages/cel/src/lib/parser.ts b/packages/cel/src/lib/parser.ts index 4dbb04e..5d5b6c2 100644 --- a/packages/cel/src/lib/parser.ts +++ b/packages/cel/src/lib/parser.ts @@ -6,6 +6,7 @@ import { Expr_CreateStruct, Expr_CreateStruct_Entry, Expr_CreateStruct_EntrySchema, + ParsedExprSchema, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; import { create } from '@bufbuild/protobuf'; import { NullValue } from '@bufbuild/protobuf/wkt'; @@ -76,10 +77,10 @@ import { OPT_SELECT_OPERATOR, getOperatorFromText, } from './operators'; -import { IdHelper } from './utils'; +import { ParserHelper } from './parser-helper'; export class CELParser extends GeneratedCelVisitor { - #id = new IdHelper(); + readonly #helper!: ParserHelper; readonly #errors!: Errors; readonly #maxRecursionDepth: number = 100; @@ -92,6 +93,7 @@ export class CELParser extends GeneratedCelVisitor { } ) { super(); + this.#helper = new ParserHelper(source); this.#errors = new Errors(source); if (this.options?.maxRecursionDepth) { this.#maxRecursionDepth = this.options.maxRecursionDepth; @@ -114,7 +116,11 @@ export class CELParser extends GeneratedCelVisitor { parser.addErrorListener(new ParserErrorListener(this.#errors)); parser.addParseListener(new RecursionListener(this.#maxRecursionDepth)); - return this.visit(parser.start()); + const expr = this.visit(parser.start()); + return create(ParsedExprSchema, { + expr, + sourceInfo: this.#helper.sourceInfo, + }); } override visit = (ctx: ParseTree) => { @@ -130,7 +136,7 @@ export class CELParser extends GeneratedCelVisitor { if (isNil(ctx._op)) { return result; } - const opId = this.#id.nextId(); + const opId = this.#helper.nextId(ctx._op); const ifTrue = this.visit(ctx._e1); const ifFalse = this.visit(ctx._e2); return this._globalCallOrMacro(ctx, opId, CONDITIONAL_OPERATOR, [ @@ -146,12 +152,14 @@ export class CELParser extends GeneratedCelVisitor { LOGICAL_OR_OPERATOR, result ); + const rest = ctx._e1; for (let i = 0; i < ctx._ops.length; i++) { - if (i >= ctx._e1.length) { + if (i >= rest.length) { return this._reportError(ctx, "unexpected character, wanted '||'"); } - const term = this.visit(ctx._e1[i]); - logicManager.addTerm(this.#id.nextId(), term); + const term = this.visit(rest[i]); + const op = ctx._ops[i]; + logicManager.addTerm(this.#helper.nextId(op), term); } return logicManager.toExpr(); }; @@ -162,12 +170,14 @@ export class CELParser extends GeneratedCelVisitor { LOGICAL_AND_OPERATOR, result ); + const rest = ctx._e1; for (let i = 0; i < ctx._ops.length; i++) { if (i >= ctx._e1.length) { return this._reportError(ctx, "unexpected character, wanted '&&'"); } - const term = this.visit(ctx._e1[i]); - logicManager.addTerm(this.#id.nextId(), term); + const term = this.visit(rest[i]); + const op = ctx._ops[i]; + logicManager.addTerm(this.#helper.nextId(op), term); } return logicManager.toExpr(); }; @@ -178,13 +188,13 @@ export class CELParser extends GeneratedCelVisitor { opText = ctx._op.text; } const operator = getOperatorFromText(opText); - if (isNil(operator)) { - return this._reportError(ctx, 'operator not found'); + if (!isNil(operator)) { + const left = this.visit(ctx.relation(0)); + const id = this.#helper.nextId(ctx._op); + const right = this.visit(ctx.relation(1)); + return this._globalCallOrMacro(ctx, id, operator, [left, right]); } - const left = this.visit(ctx.relation(0)); - const id = this.#id.nextId(); - const right = this.visit(ctx.relation(1)); - return this._globalCallOrMacro(ctx, id, operator, [left, right]); + return this._reportError(ctx, 'operator not found'); }; override visitCalc = (ctx: CalcContext): Expr => { @@ -193,13 +203,13 @@ export class CELParser extends GeneratedCelVisitor { opText = ctx._op.text; } const operator = getOperatorFromText(opText); - if (isNil(operator)) { - return this._reportError(ctx, 'operator not found'); + if (!isNil(operator)) { + const lhs = this.visit(ctx.calc(0)); + const opId = this.#helper.nextId(ctx._op); + const rhs = this.visit(ctx.calc(1)); + return this._globalCallOrMacro(ctx, opId, operator, [lhs, rhs]); } - const lhs = this.visit(ctx.calc(0)); - const opId = this.#id.nextId(); - const rhs = this.visit(ctx.calc(1)); - return this._globalCallOrMacro(ctx, opId, operator, [lhs, rhs]); + return this._reportError(ctx, 'operator not found'); }; override visitMemberExpr = (ctx: MemberExprContext): Expr => { @@ -210,7 +220,7 @@ export class CELParser extends GeneratedCelVisitor { if (!isNil(ctx._ops) && ctx._ops.length % 2 === 0) { return this.visit(ctx.member()); } - const id = this.#id.nextId(); + const id = this.#helper.nextId(ctx._ops[0]); const target = this.visit(ctx.member()); return this._globalCallOrMacro(ctx, id, LOGICAL_NOT_OPERATOR, [target]); }; @@ -219,7 +229,7 @@ export class CELParser extends GeneratedCelVisitor { if (isNil(ctx._ops) || ctx._ops.length % 2 === 0) { return this.visit(ctx.member()); } - const opId = this.#id.nextId(); + const opId = this.#helper.nextId(ctx._ops[0]); const target = this.visit(ctx.member()); return this._globalCallOrMacro(ctx, opId, NEGATE_OPERATOR, [target]); }; @@ -227,7 +237,7 @@ export class CELParser extends GeneratedCelVisitor { override visitMemberCall = (ctx: MemberCallContext): Expr => { const operand = this.visit(ctx.member()); const id = ctx._id.text; - const opId = this.#id.nextId(); + const opId = this.#helper.nextId(ctx._open); let args: Expr[] = []; if (!isNil(ctx._args?.expr_list)) { args = this.visitSlice(ctx._args.expr_list()); @@ -243,15 +253,15 @@ export class CELParser extends GeneratedCelVisitor { return this._reportError(ctx, "unsupported syntax '.?'"); } return create(ExprSchema, { - id: this.#id.nextId(), + id: this.#helper.nextId(ctx._op), exprKind: { case: 'callExpr', value: { function: OPT_SELECT_OPERATOR, args: [ operand, - create(ExprSchema, { - id: this.#id.nextId(), + { + id: this.#helper.nextId(ctx._id), exprKind: { case: 'constExpr', value: { @@ -261,14 +271,14 @@ export class CELParser extends GeneratedCelVisitor { }, }, }, - }), + }, ], }, }, }); } return create(ExprSchema, { - id: this.#id.nextId(), + id: this.#helper.nextId(ctx._op), exprKind: { case: 'selectExpr', value: { @@ -288,7 +298,7 @@ export class CELParser extends GeneratedCelVisitor { if (isNil(ctx._op)) { return this._reportError(ctx, 'no valid identifier is specified'); } - const opId = this.#id.nextId(); + const opId = this.#helper.nextId(ctx._op); const index = this.visit(ctx._index); let operator = INDEX_OPERATOR; if (!isNil(ctx._opt)) { @@ -314,7 +324,7 @@ export class CELParser extends GeneratedCelVisitor { } identName += id; if (!isNil(ctx._op)) { - const opId = this.#id.nextId(); + const opId = this.#helper.nextId(ctx._op); let args: Expr[] = []; if (!isNil(ctx._args)) { args = this.visitSlice(ctx._args.expr_list()); @@ -322,7 +332,7 @@ export class CELParser extends GeneratedCelVisitor { return this._globalCallOrMacro(ctx, opId, identName, args); } return create(ExprSchema, { - id: this.#id.nextId(), + id: this.#helper.nextId(ctx._id), exprKind: { case: 'identExpr', value: { @@ -337,7 +347,7 @@ export class CELParser extends GeneratedCelVisitor { // }; override visitCreateList = (ctx: CreateListContext): Expr => { - const listId = this.#id.nextId(); + const listId = this.#helper.nextId(ctx._op); let elements: Expr[] = []; let optionalIndices: number[] = []; if (!isNil(ctx._elems)) { @@ -362,7 +372,7 @@ export class CELParser extends GeneratedCelVisitor { }; override visitCreateStruct = (ctx: CreateStructContext): Expr => { - const structId = this.#id.nextId(); + const structId = this.#helper.nextId(ctx._op); let entries: Expr_CreateStruct_Entry[] = []; if (!isNil(ctx._entries)) { const mapInit = this.visit(ctx._entries); @@ -394,7 +404,7 @@ export class CELParser extends GeneratedCelVisitor { if (!isNil(ctx._leadingDot)) { messageName = `.${messageName}`; } - const id = this.#id.nextId(); + const id = this.#helper.nextId(ctx._op); let entries: Expr_CreateStruct_Entry[] = []; if (!isNil(ctx._entries)) { const initializer = this.visit(ctx._entries); @@ -425,7 +435,7 @@ export class CELParser extends GeneratedCelVisitor { return this._reportError(ctx, 'expr is not a constant'); } return create(ExprSchema, { - id: this.#id.nextId(), + id: this.#helper.nextId(ctx), exprKind: { case: 'constExpr', value: expr.exprKind.value, @@ -435,7 +445,7 @@ export class CELParser extends GeneratedCelVisitor { override visitExprList = (ctx: ExprListContext): Expr => { return create(ExprSchema, { - id: this.#id.nextId(), + id: this.#helper.nextId(ctx), exprKind: { case: 'listExpr', value: { @@ -492,7 +502,7 @@ export class CELParser extends GeneratedCelVisitor { return create(ExprSchema); } const field = ctx._fields[i]; - const exprId = this.#id.nextId(); + const exprId = this.#helper.nextId(ctx._cols[i]); const optionalEntry = !isNil(field._opt); const id = field.IDENTIFIER(); if (isNil(id)) { @@ -511,7 +521,7 @@ export class CELParser extends GeneratedCelVisitor { ); } return create(ExprSchema, { - id: this.#id.nextId(), + id: this.#helper.nextId(ctx), exprKind: { case: 'structExpr', value: { @@ -532,7 +542,7 @@ export class CELParser extends GeneratedCelVisitor { // This is the result of a syntax error detected elsewhere. return create(ExprSchema); } - const colId = this.#id.nextId(); + const colId = this.#helper.nextId(ctx._cols[i]); const optKey = ctx._keys[i]; const optionalKey = !isNil(optKey._opt); const key = this.visit(optKey._e); @@ -550,7 +560,7 @@ export class CELParser extends GeneratedCelVisitor { ); } return create(ExprSchema, { - id: this.#id.nextId(), + id: this.#helper.nextId(ctx), exprKind: { case: 'structExpr', value: { @@ -568,7 +578,7 @@ export class CELParser extends GeneratedCelVisitor { const constant = parseIntConstant(ctx.getText()); // TODO: parse error handling return create(ExprSchema, { - id: this.#id.nextId(), + id: this.#helper.nextId(ctx), exprKind: { case: 'constExpr', value: constant, @@ -580,7 +590,7 @@ export class CELParser extends GeneratedCelVisitor { const constant = parseUintConstant(ctx.getText()); // TODO: parse error handling return create(ExprSchema, { - id: this.#id.nextId(), + id: this.#helper.nextId(ctx), exprKind: { case: 'constExpr', value: constant, @@ -592,7 +602,7 @@ export class CELParser extends GeneratedCelVisitor { const constant = parseDoubleConstant(ctx.getText()); // TODO: parse error handling return create(ExprSchema, { - id: this.#id.nextId(), + id: this.#helper.nextId(ctx), exprKind: { case: 'constExpr', value: constant, @@ -604,7 +614,7 @@ export class CELParser extends GeneratedCelVisitor { const constant = parseStringConstant(ctx.getText()); // TODO: parse error handling return create(ExprSchema, { - id: this.#id.nextId(), + id: this.#helper.nextId(ctx), exprKind: { case: 'constExpr', value: constant, @@ -616,7 +626,7 @@ export class CELParser extends GeneratedCelVisitor { const constant = parseBytesConstant(ctx.getText()); // TODO: parse error handling return create(ExprSchema, { - id: this.#id.nextId(), + id: this.#helper.nextId(ctx), exprKind: { case: 'constExpr', value: constant, @@ -627,7 +637,7 @@ export class CELParser extends GeneratedCelVisitor { override visitBoolTrue = (ctx: BoolTrueContext): Expr => { assert(ctx.getText() === 'true', new ParseException('true expected', 0)); return create(ExprSchema, { - id: this.#id.nextId(), + id: this.#helper.nextId(ctx), exprKind: { case: 'constExpr', value: { @@ -643,7 +653,7 @@ export class CELParser extends GeneratedCelVisitor { override visitBoolFalse = (ctx: BoolFalseContext): Expr => { assert(ctx.getText() === 'false', new ParseException('false expected', 0)); return create(ExprSchema, { - id: this.#id.nextId(), + id: this.#helper.nextId(ctx), exprKind: { case: 'constExpr', value: { @@ -659,7 +669,7 @@ export class CELParser extends GeneratedCelVisitor { override visitNull = (ctx: NullContext): Expr => { assert(ctx.getText() === 'null', new ParseException('null expected', 0)); return create(ExprSchema, { - id: this.#id.nextId(), + id: this.#helper.nextId(ctx), exprKind: { case: 'constExpr', value: { @@ -795,7 +805,7 @@ export class CELParser extends GeneratedCelVisitor { return null; } try { - const expanded = expandMacro(this.#id, macro, target, args); + const expanded = expandMacro(this.#helper, macro, target, args); return expanded; } catch (e) { return this._reportError(ctx, (e as Error).message); @@ -804,7 +814,7 @@ export class CELParser extends GeneratedCelVisitor { private _reportError(ctx: ParserRuleContext, message: string) { const error = create(ExprSchema, { - id: this.#id.nextId(), + id: this.#helper.nextId(ctx), exprKind: { case: 'constExpr', value: { @@ -817,8 +827,7 @@ export class CELParser extends GeneratedCelVisitor { }); this.#errors.reportErrorAtId( error.id, - ctx.start.line, - ctx.start.column, + { line: ctx.start.line, column: ctx.start.column }, message ); return error; diff --git a/packages/cel/src/lib/types.ts b/packages/cel/src/lib/types.ts new file mode 100644 index 0000000..1e38f83 --- /dev/null +++ b/packages/cel/src/lib/types.ts @@ -0,0 +1,9 @@ +export interface Location { + line: number; + column: number; +} + +export interface OffsetRange { + start: number; + stop: number; +} From 521d84b5f63e88b103e051378ef0da6f89c7aa92 Mon Sep 17 00:00:00 2001 From: jafaircl Date: Thu, 3 Oct 2024 08:40:11 -0400 Subject: [PATCH 12/34] feat(cel): add recusion checking in visit methods --- packages/cel/src/lib/errors.ts | 5 +- packages/cel/src/lib/parser.spec.ts | 355 ++++++++++++++++++++++++++++ packages/cel/src/lib/parser.ts | 53 ++++- 3 files changed, 401 insertions(+), 12 deletions(-) diff --git a/packages/cel/src/lib/errors.ts b/packages/cel/src/lib/errors.ts index 3a54f24..a2c1e73 100644 --- a/packages/cel/src/lib/errors.ts +++ b/packages/cel/src/lib/errors.ts @@ -79,7 +79,10 @@ export class Errors { for (const error of this.errors.errors) { const str = this._errorToDisplayString(error); // Deduplicate recursion errors. - if (str.includes('expression recursion limit exceeded')) { + if ( + str.includes('expression recursion limit exceeded') || + str.includes('max recursion depth exceeded') + ) { if (!hasRecursionError) { hasRecursionError = true; errors.push(str); diff --git a/packages/cel/src/lib/parser.spec.ts b/packages/cel/src/lib/parser.spec.ts index ba5bf59..50d00a9 100644 --- a/packages/cel/src/lib/parser.spec.ts +++ b/packages/cel/src/lib/parser.spec.ts @@ -4708,6 +4708,361 @@ const testCases: TestInfo[] = [ // | ......................^`, // }, // TODO: javascript doesn't like the one that starts with "I: `ó" + // Macro Calls Tests + // TODO: these are very complicated + // { + // I: `x.filter(y, y.filter(z, z > 0))`, + // P: `__comprehension__( + // // Variable + // y, + // // Target + // x^#1:*expr.Expr_IdentExpr#, + // // Accumulator + // __result__, + // // Init + // []^#19:*expr.Expr_ListExpr#, + // // LoopCondition + // true^#20:*expr.Constant_BoolValue#, + // // LoopStep + // _?_:_( + // __comprehension__( + // // Variable + // z, + // // Target + // y^#4:*expr.Expr_IdentExpr#, + // // Accumulator + // __result__, + // // Init + // []^#10:*expr.Expr_ListExpr#, + // // LoopCondition + // true^#11:*expr.Constant_BoolValue#, + // // LoopStep + // _?_:_( + // _>_( + // z^#7:*expr.Expr_IdentExpr#, + // 0^#9:*expr.Constant_Int64Value# + // )^#8:*expr.Expr_CallExpr#, + // _+_( + // __result__^#12:*expr.Expr_IdentExpr#, + // [ + // z^#6:*expr.Expr_IdentExpr# + // ]^#13:*expr.Expr_ListExpr# + // )^#14:*expr.Expr_CallExpr#, + // __result__^#15:*expr.Expr_IdentExpr# + // )^#16:*expr.Expr_CallExpr#, + // // Result + // __result__^#17:*expr.Expr_IdentExpr#)^#18:*expr.Expr_ComprehensionExpr#, + // _+_( + // __result__^#21:*expr.Expr_IdentExpr#, + // [ + // y^#3:*expr.Expr_IdentExpr# + // ]^#22:*expr.Expr_ListExpr# + // )^#23:*expr.Expr_CallExpr#, + // __result__^#24:*expr.Expr_IdentExpr# + // )^#25:*expr.Expr_CallExpr#, + // // Result + // __result__^#26:*expr.Expr_IdentExpr#)^#27:*expr.Expr_ComprehensionExpr#`, + // M: `x^#1:*expr.Expr_IdentExpr#.filter( + // y^#3:*expr.Expr_IdentExpr#, + // ^#18:filter# + // )^#27:filter#, + // y^#4:*expr.Expr_IdentExpr#.filter( + // z^#6:*expr.Expr_IdentExpr#, + // _>_( + // z^#7:*expr.Expr_IdentExpr#, + // 0^#9:*expr.Constant_Int64Value# + // )^#8:*expr.Expr_CallExpr# + // )^#18:filter#`, + // }, + // { + // I: `has(a.b).filter(c, c)`, + // P: `__comprehension__( + // // Variable + // c, + // // Target + // a^#2:*expr.Expr_IdentExpr#.b~test-only~^#4:*expr.Expr_SelectExpr#, + // // Accumulator + // __result__, + // // Init + // []^#8:*expr.Expr_ListExpr#, + // // LoopCondition + // true^#9:*expr.Constant_BoolValue#, + // // LoopStep + // _?_:_( + // c^#7:*expr.Expr_IdentExpr#, + // _+_( + // __result__^#10:*expr.Expr_IdentExpr#, + // [ + // c^#6:*expr.Expr_IdentExpr# + // ]^#11:*expr.Expr_ListExpr# + // )^#12:*expr.Expr_CallExpr#, + // __result__^#13:*expr.Expr_IdentExpr# + // )^#14:*expr.Expr_CallExpr#, + // // Result + // __result__^#15:*expr.Expr_IdentExpr#)^#16:*expr.Expr_ComprehensionExpr#`, + // M: `^#4:has#.filter( + // c^#6:*expr.Expr_IdentExpr#, + // c^#7:*expr.Expr_IdentExpr# + // )^#16:filter#, + // has( + // a^#2:*expr.Expr_IdentExpr#.b^#3:*expr.Expr_SelectExpr# + // )^#4:has#`, + // }, + // { + // I: `x.filter(y, y.exists(z, has(z.a)) && y.exists(z, has(z.b)))`, + // P: `__comprehension__( + // // Variable + // y, + // // Target + // x^#1:*expr.Expr_IdentExpr#, + // // Accumulator + // __result__, + // // Init + // []^#35:*expr.Expr_ListExpr#, + // // LoopCondition + // true^#36:*expr.Constant_BoolValue#, + // // LoopStep + // _?_:_( + // _&&_( + // __comprehension__( + // // Variable + // z, + // // Target + // y^#4:*expr.Expr_IdentExpr#, + // // Accumulator + // __result__, + // // Init + // false^#11:*expr.Constant_BoolValue#, + // // LoopCondition + // @not_strictly_false( + // !_( + // __result__^#12:*expr.Expr_IdentExpr# + // )^#13:*expr.Expr_CallExpr# + // )^#14:*expr.Expr_CallExpr#, + // // LoopStep + // _||_( + // __result__^#15:*expr.Expr_IdentExpr#, + // z^#8:*expr.Expr_IdentExpr#.a~test-only~^#10:*expr.Expr_SelectExpr# + // )^#16:*expr.Expr_CallExpr#, + // // Result + // __result__^#17:*expr.Expr_IdentExpr#)^#18:*expr.Expr_ComprehensionExpr#, + // __comprehension__( + // // Variable + // z, + // // Target + // y^#19:*expr.Expr_IdentExpr#, + // // Accumulator + // __result__, + // // Init + // false^#26:*expr.Constant_BoolValue#, + // // LoopCondition + // @not_strictly_false( + // !_( + // __result__^#27:*expr.Expr_IdentExpr# + // )^#28:*expr.Expr_CallExpr# + // )^#29:*expr.Expr_CallExpr#, + // // LoopStep + // _||_( + // __result__^#30:*expr.Expr_IdentExpr#, + // z^#23:*expr.Expr_IdentExpr#.b~test-only~^#25:*expr.Expr_SelectExpr# + // )^#31:*expr.Expr_CallExpr#, + // // Result + // __result__^#32:*expr.Expr_IdentExpr#)^#33:*expr.Expr_ComprehensionExpr# + // )^#34:*expr.Expr_CallExpr#, + // _+_( + // __result__^#37:*expr.Expr_IdentExpr#, + // [ + // y^#3:*expr.Expr_IdentExpr# + // ]^#38:*expr.Expr_ListExpr# + // )^#39:*expr.Expr_CallExpr#, + // __result__^#40:*expr.Expr_IdentExpr# + // )^#41:*expr.Expr_CallExpr#, + // // Result + // __result__^#42:*expr.Expr_IdentExpr#)^#43:*expr.Expr_ComprehensionExpr#`, + // M: `x^#1:*expr.Expr_IdentExpr#.filter( + // y^#3:*expr.Expr_IdentExpr#, + // _&&_( + // ^#18:exists#, + // ^#33:exists# + // )^#34:*expr.Expr_CallExpr# + // )^#43:filter#, + // y^#19:*expr.Expr_IdentExpr#.exists( + // z^#21:*expr.Expr_IdentExpr#, + // ^#25:has# + // )^#33:exists#, + // has( + // z^#23:*expr.Expr_IdentExpr#.b^#24:*expr.Expr_SelectExpr# + // )^#25:has#, + // y^#4:*expr.Expr_IdentExpr#.exists( + // z^#6:*expr.Expr_IdentExpr#, + // ^#10:has# + // )^#18:exists#, + // has( + // z^#8:*expr.Expr_IdentExpr#.a^#9:*expr.Expr_SelectExpr# + // )^#10:has#`, + // }, + // { + // I: `(has(a.b) || has(c.d)).string()`, + // P: `_||_( + // a^#2:*expr.Expr_IdentExpr#.b~test-only~^#4:*expr.Expr_SelectExpr#, + // c^#6:*expr.Expr_IdentExpr#.d~test-only~^#8:*expr.Expr_SelectExpr# + // )^#9:*expr.Expr_CallExpr#.string()^#10:*expr.Expr_CallExpr#`, + // M: `has( + // c^#6:*expr.Expr_IdentExpr#.d^#7:*expr.Expr_SelectExpr# + // )^#8:has#, + // has( + // a^#2:*expr.Expr_IdentExpr#.b^#3:*expr.Expr_SelectExpr# + // )^#4:has#`, + // }, + // { + // I: `has(a.b).asList().exists(c, c)`, + // P: `__comprehension__( + // // Variable + // c, + // // Target + // a^#2:*expr.Expr_IdentExpr#.b~test-only~^#4:*expr.Expr_SelectExpr#.asList()^#5:*expr.Expr_CallExpr#, + // // Accumulator + // __result__, + // // Init + // false^#9:*expr.Constant_BoolValue#, + // // LoopCondition + // @not_strictly_false( + // !_( + // __result__^#10:*expr.Expr_IdentExpr# + // )^#11:*expr.Expr_CallExpr# + // )^#12:*expr.Expr_CallExpr#, + // // LoopStep + // _||_( + // __result__^#13:*expr.Expr_IdentExpr#, + // c^#8:*expr.Expr_IdentExpr# + // )^#14:*expr.Expr_CallExpr#, + // // Result + // __result__^#15:*expr.Expr_IdentExpr#)^#16:*expr.Expr_ComprehensionExpr#`, + // M: `^#4:has#.asList()^#5:*expr.Expr_CallExpr#.exists( + // c^#7:*expr.Expr_IdentExpr#, + // c^#8:*expr.Expr_IdentExpr# + // )^#16:exists#, + // has( + // a^#2:*expr.Expr_IdentExpr#.b^#3:*expr.Expr_SelectExpr# + // )^#4:has#`, + // }, + // { + // I: `[has(a.b), has(c.d)].exists(e, e)`, + // P: `__comprehension__( + // // Variable + // e, + // // Target + // [ + // a^#3:*expr.Expr_IdentExpr#.b~test-only~^#5:*expr.Expr_SelectExpr#, + // c^#7:*expr.Expr_IdentExpr#.d~test-only~^#9:*expr.Expr_SelectExpr# + // ]^#1:*expr.Expr_ListExpr#, + // // Accumulator + // __result__, + // // Init + // false^#13:*expr.Constant_BoolValue#, + // // LoopCondition + // @not_strictly_false( + // !_( + // __result__^#14:*expr.Expr_IdentExpr# + // )^#15:*expr.Expr_CallExpr# + // )^#16:*expr.Expr_CallExpr#, + // // LoopStep + // _||_( + // __result__^#17:*expr.Expr_IdentExpr#, + // e^#12:*expr.Expr_IdentExpr# + // )^#18:*expr.Expr_CallExpr#, + // // Result + // __result__^#19:*expr.Expr_IdentExpr#)^#20:*expr.Expr_ComprehensionExpr#`, + // M: `[ + // ^#5:has#, + // ^#9:has# + // ]^#1:*expr.Expr_ListExpr#.exists( + // e^#11:*expr.Expr_IdentExpr#, + // e^#12:*expr.Expr_IdentExpr# + // )^#20:exists#, + // has( + // c^#7:*expr.Expr_IdentExpr#.d^#8:*expr.Expr_SelectExpr# + // )^#9:has#, + // has( + // a^#3:*expr.Expr_IdentExpr#.b^#4:*expr.Expr_SelectExpr# + // )^#5:has#`, + // }, + { + I: `y!=y!=y!=y!=y!=y!=y!=y!=y!=-y!=-y!=-y!=-y-y!=-y!=-y!=-y-y!=-y!=-y!=-y-y!=-y + !=-y!=-y-y!=-y!=-y!=-y-y!=-y!=-y!=-y-y!=-y!=-y!=-y-y!=-y!=-y!=-y-y!=-y!=-y!=-y-y + !=-y!=-y!=-y-y!=-y!=-y!=-y-y!=-y!=-y!=-y-y!=-y!=-y!=-y-y!=-y!=-y!=-y-y!=-y!=-y + !=-y-y!=-y!=-y!=-y-y!=-y!=-y!=-y-y!=-y!=-y!=-y-y!=-y!=-y!=-y-y!=-y!=-y!=-y-y!=-y + !=-y!=-y-y!=-y!=-y!=-y-y!=-y!=-y!=-y-y!=-y!=-y!=-y-y!=-y!=-y!=-y-y!=-y!=-y!=-y-y + !=-y!=-y!=-y-y!=-y!=-y!=-y-y!=-y!=-y!=-y-y!=-y`, + E: `ERROR: :-1:0: max recursion depth exceeded`, + }, + { + // More than 32 nested list creation statements + I: `[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[['not fine']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]`, + E: `ERROR: :-1:0: expression recursion limit exceeded: 32`, + }, + { + // More than 32 arithmetic operations. + I: `1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 + + 31 + 32 + 33 + 34`, + E: `ERROR: :-1:0: max recursion depth exceeded`, + }, + { + // More than 32 field selections + I: `a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H`, + E: `ERROR: :-1:0: max recursion depth exceeded`, + }, + { + // More than 32 index operations + I: `a[1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20] + [21][22][23][24][25][26][27][28][29][30][31][32][33]`, + E: `ERROR: :-1:0: max recursion depth exceeded`, + }, + { + // More than 32 relation operators + I: `a < 1 < 2 < 3 < 4 < 5 < 6 < 7 < 8 < 9 < 10 < 11 + < 12 < 13 < 14 < 15 < 16 < 17 < 18 < 19 < 20 < 21 + < 22 < 23 < 24 < 25 < 26 < 27 < 28 < 29 < 30 < 31 + < 32 < 33`, + E: `ERROR: :-1:0: max recursion depth exceeded`, + }, + { + // More than 32 index / relation operators. Note, the recursion count is the + // maximum recursion level on the left or right side index expression (20) plus + // the number of relation operators (13) + I: `a[1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20] != + a[1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20] != + a[1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20] != + a[1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20] != + a[1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20] != + a[1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20] != + a[1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20] != + a[1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20] != + a[1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20] != + a[1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20] != + a[1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20] != + a[1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20] != + a[1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20] != + a[1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20]`, + E: `ERROR: :-1:0: max recursion depth exceeded`, + }, + // { // TODO: the error message is wrong + // I: `self.true == 1`, + // E: `ERROR: :1:6: Syntax error: mismatched input 'true' expecting IDENTIFIER + // | self.true == 1 + // | .....^`, + // }, + { + I: `a.?b && a[?b]`, + E: `ERROR: :1:2: unsupported syntax '.?' + | a.?b && a[?b] + | .^ + ERROR: :1:10: unsupported syntax '[?' + | a.?b && a[?b] + | .........^`, + }, ]; describe('CELVisitor', () => { diff --git a/packages/cel/src/lib/parser.ts b/packages/cel/src/lib/parser.ts index 5d5b6c2..98863d7 100644 --- a/packages/cel/src/lib/parser.ts +++ b/packages/cel/src/lib/parser.ts @@ -78,11 +78,13 @@ import { getOperatorFromText, } from './operators'; import { ParserHelper } from './parser-helper'; +import { Location } from './types'; export class CELParser extends GeneratedCelVisitor { readonly #helper!: ParserHelper; readonly #errors!: Errors; readonly #maxRecursionDepth: number = 100; + #recursionDepth = 0; constructor( public readonly source: string, @@ -124,7 +126,21 @@ export class CELParser extends GeneratedCelVisitor { } override visit = (ctx: ParseTree) => { - return super.visit(this._unnest(ctx)); + const tree = this._unnest(ctx); + if ( + tree instanceof ExprContext || + tree instanceof RelationContext || + tree instanceof CalcContext || + tree instanceof SelectContext || + tree instanceof MemberCallContext || + tree instanceof IndexContext + ) { + this._checkAndIncrementRecusionDepth(); + const out = super.visit(tree); + this._decrementRecursionDepth(); + return out; + } + return super.visit(tree); }; override visitStart = (ctx: StartContext): Expr => { @@ -250,7 +266,7 @@ export class CELParser extends GeneratedCelVisitor { const id = ctx._id.text; if (!isNil(ctx._opt)) { if (!this.options?.enableOptionalSyntax) { - return this._reportError(ctx, "unsupported syntax '.?'"); + return this._reportError(ctx._op, "unsupported syntax '.?'"); } return create(ExprSchema, { id: this.#helper.nextId(ctx._op), @@ -303,7 +319,7 @@ export class CELParser extends GeneratedCelVisitor { let operator = INDEX_OPERATOR; if (!isNil(ctx._opt)) { if (!this.options?.enableOptionalSyntax) { - return this._reportError(ctx, "unsupported syntax '[?'"); + return this._reportError(ctx._op, "unsupported syntax '[?'"); } operator = OPT_INDEX_OPERATOR; } @@ -812,7 +828,7 @@ export class CELParser extends GeneratedCelVisitor { } } - private _reportError(ctx: ParserRuleContext, message: string) { + private _reportError(ctx: ParserRuleContext | Token, message: string) { const error = create(ExprSchema, { id: this.#helper.nextId(ctx), exprKind: { @@ -825,13 +841,28 @@ export class CELParser extends GeneratedCelVisitor { }, }, }); - this.#errors.reportErrorAtId( - error.id, - { line: ctx.start.line, column: ctx.start.column }, - message - ); + let location: Location; + if (ctx instanceof ParserRuleContext) { + location = { line: ctx.start.line, column: ctx.start.column }; + } else if (ctx instanceof Token) { + location = { line: ctx.line, column: ctx.column }; + } else { + location = { line: -1, column: -1 }; + } + this.#errors.reportErrorAtId(error.id, location, message); return error; } + + private _checkAndIncrementRecusionDepth() { + this.#recursionDepth++; + if (this.#recursionDepth > this.#maxRecursionDepth) { + return this.errors.reportInternalError('max recursion depth exceeded'); + } + } + + private _decrementRecursionDepth() { + this.#recursionDepth--; + } } class RecursionListener extends ParseTreeListener { @@ -852,8 +883,8 @@ class RecursionListener extends ParseTreeListener { } let depth = this.#ruleTypeDepth.get(ruleIndex); if (isNil(depth)) { - this.#ruleTypeDepth.set(ruleIndex, 0); - depth = 0; + this.#ruleTypeDepth.set(ruleIndex, 1); + depth = 1; } else { depth++; } From 6644a446ce515987757d4710945b8aafaf4dab0e Mon Sep 17 00:00:00 2001 From: jafaircl Date: Thu, 3 Oct 2024 15:31:25 -0400 Subject: [PATCH 13/34] feat(cel): update utility functions & use them for testing/runtime; fix optional select logic --- packages/cel/src/lib/logic-manager.ts | 31 +- packages/cel/src/lib/macros.ts | 364 +- packages/cel/src/lib/parser-helper.ts | 6 +- packages/cel/src/lib/parser.spec.ts | 4396 ++++++------------------- packages/cel/src/lib/parser.ts | 320 +- packages/cel/src/lib/utils.spec.ts | 745 +++++ packages/cel/src/lib/utils.ts | 159 +- 7 files changed, 2152 insertions(+), 3869 deletions(-) create mode 100644 packages/cel/src/lib/utils.spec.ts diff --git a/packages/cel/src/lib/logic-manager.ts b/packages/cel/src/lib/logic-manager.ts index 9531d64..bc437b0 100644 --- a/packages/cel/src/lib/logic-manager.ts +++ b/packages/cel/src/lib/logic-manager.ts @@ -1,8 +1,5 @@ -import { - Expr, - ExprSchema, -} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; -import { create } from '@bufbuild/protobuf'; +import { Expr } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { callExpr } from './utils'; export class LogicManager { private function: string; @@ -41,15 +38,9 @@ export class LogicManager { return this.terms[0]; } if (this.variadicASTs) { - return create(ExprSchema, { - id: this.ops[0], - exprKind: { - case: 'callExpr', - value: { - function: this.function, - args: this.terms, - }, - }, + return callExpr(this.ops[0], { + function: this.function, + args: this.terms, }); } return this.balancedTree(0, this.ops.length - 1); @@ -69,15 +60,9 @@ export class LogicManager { } else { right = this.balancedTree(mid + 1, hi); } - return create(ExprSchema, { - id: this.ops[mid], - exprKind: { - case: 'callExpr', - value: { - function: this.function, - args: [left, right], - }, - }, + return callExpr(this.ops[mid], { + function: this.function, + args: [left, right], }); } } diff --git a/packages/cel/src/lib/macros.ts b/packages/cel/src/lib/macros.ts index f66dba9..ab3163a 100644 --- a/packages/cel/src/lib/macros.ts +++ b/packages/cel/src/lib/macros.ts @@ -1,11 +1,7 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import { isNil } from '@bearclaw/is'; -import { - Expr, - ExprSchema, - Expr_SelectSchema, -} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; -import { create } from '@bufbuild/protobuf'; +import { Expr } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { ParserRuleContext, Token } from 'antlr4'; import { ACCUMULATOR_VAR } from './constants'; import { ADD_OPERATOR, @@ -23,7 +19,17 @@ import { NOT_STRICTLY_FALSE_OPERATOR, } from './operators'; import { ParserHelper } from './parser-helper'; -import { boolExpr, globalCall, identExpr, int64Expr, listExpr } from './utils'; +import { Location, OffsetRange } from './types'; +import { + boolExpr, + callExpr, + comprehensionExpr, + extractIdent, + identExpr, + int64Expr, + listExpr, + selectExpr, +} from './utils'; export const STANDARD_MACROS = new Set([ HAS_MACRO, @@ -40,6 +46,7 @@ export function findMacro(name: string) { } export function expandMacro( + ctx: ParserRuleContext | Token | Location | OffsetRange | null, helper: ParserHelper, op: string, target: Expr | null, @@ -47,170 +54,164 @@ export function expandMacro( ): Expr { switch (op) { case HAS_MACRO: - return expandHasMacro(helper, args); + return expandHasMacro(ctx, helper, args); case ALL_MACRO: - return expandAllMacro(helper, target!, args); + return expandAllMacro(ctx, helper, target!, args); case EXISTS_MACRO: - return expandExistsMacro(helper, target!, args); + return expandExistsMacro(ctx, helper, target!, args); case EXISTS_ONE_MACRO: - return expandExistsOneMacro(helper, target!, args); + return expandExistsOneMacro(ctx, helper, target!, args); case MAP_MACRO: - return expandMapMacro(helper, target!, args); + return expandMapMacro(ctx, helper, target!, args); case FILTER_MACRO: - return expandFilterMacro(helper, target!, args); + return expandFilterMacro(ctx, helper, target!, args); default: throw new Error(`Unknown macro: ${op}`); } } -export function expandHasMacro(helper: ParserHelper, args: Expr[]): Expr { +export function expandHasMacro( + ctx: ParserRuleContext | Token | Location | OffsetRange | null, + helper: ParserHelper, + args: Expr[] +): Expr { const arg = args[0]; if (arg.exprKind.case !== 'selectExpr') { - throw new Error('Invalid argument to has() macro'); + throw new MacroError('invalid argument to has() macro', ctx, arg); } - return create(ExprSchema, { - id: helper.nextId(), - exprKind: { - case: 'selectExpr', - value: create(Expr_SelectSchema, { - operand: arg.exprKind.value.operand, - field: arg.exprKind.value.field, - testOnly: true, - }), - }, + return selectExpr(helper.nextId(ctx), { + operand: arg.exprKind.value.operand, + field: arg.exprKind.value.field, + testOnly: true, }); } export function expandAllMacro( + ctx: ParserRuleContext | Token | Location | OffsetRange | null, helper: ParserHelper, target: Expr, args: Expr[] ): Expr { const arg0 = args[0]; if (arg0.exprKind.case !== 'identExpr') { - throw new Error('Invalid argument to all() macro'); + throw new MacroError('argument must be a simple name', ctx, arg0); } const arg1 = args[1]; - const accuInit = boolExpr(helper.nextId(), true); - const conditionArg0 = identExpr(helper.nextId(), ACCUMULATOR_VAR); - const condition = globalCall( - helper.nextId(), - NOT_STRICTLY_FALSE_OPERATOR, - conditionArg0 - ); - const stepArg0 = identExpr(helper.nextId(), ACCUMULATOR_VAR); - const step = globalCall( - helper.nextId(), - LOGICAL_AND_OPERATOR, - stepArg0, - arg1 - ); - const result = identExpr(helper.nextId(), ACCUMULATOR_VAR); - return fold( - helper.nextId(), - target, - arg0.exprKind.value.name, - ACCUMULATOR_VAR, + const accuInit = boolExpr(helper.nextId(ctx), true); + const conditionArg0 = identExpr(helper.nextId(ctx), { + name: ACCUMULATOR_VAR, + }); + const condition = callExpr(helper.nextId(ctx), { + function: NOT_STRICTLY_FALSE_OPERATOR, + args: [conditionArg0], + }); + const stepArg0 = identExpr(helper.nextId(ctx), { name: ACCUMULATOR_VAR }); + const step = callExpr(helper.nextId(ctx), { + function: LOGICAL_AND_OPERATOR, + args: [stepArg0, arg1], + }); + const result = identExpr(helper.nextId(ctx), { name: ACCUMULATOR_VAR }); + return comprehensionExpr(helper.nextId(ctx), { + iterRange: target, + iterVar: arg0.exprKind.value.name, + accuVar: ACCUMULATOR_VAR, accuInit, - condition, - step, - result - ); + loopCondition: condition, + loopStep: step, + result, + }); } export function expandExistsMacro( + ctx: ParserRuleContext | Token | Location | OffsetRange | null, helper: ParserHelper, target: Expr, args: Expr[] ): Expr { const arg0 = args[0]; if (arg0.exprKind.case !== 'identExpr') { - throw new Error('Invalid argument to exists() macro'); + throw new MacroError('argument must be a simple name', ctx, arg0); } const arg1 = args[1]; - const accuInit = boolExpr(helper.nextId(), false); - const conditionArg0Arg0 = identExpr(helper.nextId(), ACCUMULATOR_VAR); - const conditionArg0 = globalCall( - helper.nextId(), - LOGICAL_NOT_OPERATOR, - conditionArg0Arg0 - ); - const condition = globalCall( - helper.nextId(), - NOT_STRICTLY_FALSE_OPERATOR, - conditionArg0 - ); - const stepArg0 = identExpr(helper.nextId(), ACCUMULATOR_VAR); - const step = globalCall(helper.nextId(), LOGICAL_OR_OPERATOR, stepArg0, arg1); - const result = identExpr(helper.nextId(), ACCUMULATOR_VAR); - return fold( - helper.nextId(), - target, - arg0.exprKind.value.name, - ACCUMULATOR_VAR, + const accuInit = boolExpr(helper.nextId(ctx), false); + const conditionArg0Arg0 = identExpr(helper.nextId(ctx), { + name: ACCUMULATOR_VAR, + }); + const conditionArg0 = callExpr(helper.nextId(ctx), { + function: LOGICAL_NOT_OPERATOR, + args: [conditionArg0Arg0], + }); + const condition = callExpr(helper.nextId(ctx), { + function: NOT_STRICTLY_FALSE_OPERATOR, + args: [conditionArg0], + }); + const stepArg0 = identExpr(helper.nextId(ctx), { name: ACCUMULATOR_VAR }); + const step = callExpr(helper.nextId(ctx), { + function: LOGICAL_OR_OPERATOR, + args: [stepArg0, arg1], + }); + const result = identExpr(helper.nextId(ctx), { name: ACCUMULATOR_VAR }); + return comprehensionExpr(helper.nextId(ctx), { + iterRange: target, + iterVar: arg0.exprKind.value.name, + accuVar: ACCUMULATOR_VAR, accuInit, - condition, - step, - result - ); + loopCondition: condition, + loopStep: step, + result, + }); } export function expandExistsOneMacro( + ctx: ParserRuleContext | Token | Location | OffsetRange | null, helper: ParserHelper, target: Expr, args: Expr[] ): Expr { const arg0 = args[0]; if (arg0.exprKind.case !== 'identExpr') { - throw new Error('Invalid argument to exists_one() macro'); + throw new MacroError('argument must be a simple name', ctx, arg0); } const arg1 = args[1]; - const accuInit = int64Expr(helper.nextId(), BigInt(0)); - const condition = boolExpr(helper.nextId(), true); - const stepArg1Arg0 = identExpr(helper.nextId(), ACCUMULATOR_VAR); - const stepArg1Arg1 = int64Expr(helper.nextId(), BigInt(1)); - const stepArg1 = globalCall( - helper.nextId(), - ADD_OPERATOR, - stepArg1Arg0, - stepArg1Arg1 - ); - const stepArg2 = identExpr(helper.nextId(), ACCUMULATOR_VAR); - const step = globalCall( - helper.nextId(), - CONDITIONAL_OPERATOR, - arg1, - stepArg1, - stepArg2 - ); - const resultArg0 = identExpr(helper.nextId(), ACCUMULATOR_VAR); - const resultArg1 = int64Expr(helper.nextId(), BigInt(1)); - const result = globalCall( - helper.nextId(), - EQUALS_OPERATOR, - resultArg0, - resultArg1 - ); - return fold( - helper.nextId(), - target, - arg0.exprKind.value.name, - ACCUMULATOR_VAR, + const accuInit = int64Expr(helper.nextId(ctx), BigInt(0)); + const condition = boolExpr(helper.nextId(ctx), true); + const stepArg1Arg0 = identExpr(helper.nextId(ctx), { name: ACCUMULATOR_VAR }); + const stepArg1Arg1 = int64Expr(helper.nextId(ctx), BigInt(1)); + const stepArg1 = callExpr(helper.nextId(ctx), { + function: ADD_OPERATOR, + args: [stepArg1Arg0, stepArg1Arg1], + }); + const stepArg2 = identExpr(helper.nextId(ctx), { name: ACCUMULATOR_VAR }); + const step = callExpr(helper.nextId(ctx), { + function: CONDITIONAL_OPERATOR, + args: [arg1, stepArg1, stepArg2], + }); + const resultArg0 = identExpr(helper.nextId(ctx), { name: ACCUMULATOR_VAR }); + const resultArg1 = int64Expr(helper.nextId(ctx), BigInt(1)); + const result = callExpr(helper.nextId(ctx), { + function: EQUALS_OPERATOR, + args: [resultArg0, resultArg1], + }); + return comprehensionExpr(helper.nextId(ctx), { + iterRange: target, + iterVar: arg0.exprKind.value.name, + accuVar: ACCUMULATOR_VAR, accuInit, - condition, - step, - result - ); + loopCondition: condition, + loopStep: step, + result, + }); } export function expandMapMacro( + ctx: ParserRuleContext | Token | Location | OffsetRange | null, helper: ParserHelper, target: Expr, args: Expr[] ): Expr { const v = extractIdent(args[0]); if (isNil(v)) { - throw new Error('argument is not an identifier'); + throw new MacroError('argument is not an identifier', ctx, args[0]); } let fn: Expr | null = null; let filter: Expr | null = null; @@ -220,100 +221,81 @@ export function expandMapMacro( } else { fn = args[1]; } - const init = listExpr(helper.nextId(), []); - const condition = boolExpr(helper.nextId(), true); - const stepArg0 = identExpr(helper.nextId(), ACCUMULATOR_VAR); - const stepArg1 = listExpr(helper.nextId(), [fn]); - let step = globalCall(helper.nextId(), ADD_OPERATOR, stepArg0, stepArg1); + const init = listExpr(helper.nextId(ctx), {}); + const condition = boolExpr(helper.nextId(ctx), true); + const stepArg0 = identExpr(helper.nextId(ctx), { name: ACCUMULATOR_VAR }); + const stepArg1 = listExpr(helper.nextId(ctx), { elements: [fn] }); + let step = callExpr(helper.nextId(ctx), { + function: ADD_OPERATOR, + args: [stepArg0, stepArg1], + }); if (!isNil(filter)) { - const step2Arg2 = identExpr(helper.nextId(), ACCUMULATOR_VAR); - step = globalCall( - helper.nextId(), - CONDITIONAL_OPERATOR, - filter, - step, - step2Arg2 - ); + const step2Arg2 = identExpr(helper.nextId(ctx), { name: ACCUMULATOR_VAR }); + step = callExpr(helper.nextId(ctx), { + function: CONDITIONAL_OPERATOR, + args: [filter, step, step2Arg2], + }); } - const result = identExpr(helper.nextId(), ACCUMULATOR_VAR); - return fold( - helper.nextId(), - target, - v, - ACCUMULATOR_VAR, - init, - condition, - step, - result - ); + const result = identExpr(helper.nextId(ctx), { name: ACCUMULATOR_VAR }); + return comprehensionExpr(helper.nextId(ctx), { + iterRange: target, + iterVar: v, + accuVar: ACCUMULATOR_VAR, + accuInit: init, + loopCondition: condition, + loopStep: step, + result, + }); } export function expandFilterMacro( + ctx: ParserRuleContext | Token | Location | OffsetRange | null, helper: ParserHelper, target: Expr, args: Expr[] ): Expr { const v = extractIdent(args[0]); if (isNil(v)) { - throw new Error('argument is not an identifier'); + throw new MacroError('argument is not an identifier', ctx, args[0]); } const filter = args[1]; - const listInit = listExpr(helper.nextId(), []); - const condition = boolExpr(helper.nextId(), true); - const stepArg0 = identExpr(helper.nextId(), ACCUMULATOR_VAR); - const stepArg1 = listExpr(helper.nextId(), [args[0]]); - let step = globalCall(helper.nextId(), ADD_OPERATOR, stepArg0, stepArg1); - const step2Arg1 = identExpr(helper.nextId(), ACCUMULATOR_VAR); - step = globalCall( - helper.nextId(), - CONDITIONAL_OPERATOR, - filter, - step, - step2Arg1 - ); - const result = identExpr(helper.nextId(), ACCUMULATOR_VAR); - return fold( - helper.nextId(), - target, - v, - ACCUMULATOR_VAR, - listInit, - condition, - step, - result - ); -} - -function fold( - exprId: bigint, - iterRange: Expr, - iterVar: string, - accuVar: string, - accuInit: Expr, - condition: Expr, - step: Expr, - result: Expr -): Expr { - return create(ExprSchema, { - id: exprId, - exprKind: { - case: 'comprehensionExpr', - value: { - iterVar, - iterRange, - accuVar, - accuInit, - loopCondition: condition, - loopStep: step, - result, - }, - }, + const listInit = listExpr(helper.nextId(ctx), {}); + const condition = boolExpr(helper.nextId(ctx), true); + const stepArg0 = identExpr(helper.nextId(ctx), { name: ACCUMULATOR_VAR }); + const stepArg1 = listExpr(helper.nextId(ctx), { elements: [args[0]] }); + let step = callExpr(helper.nextId(ctx), { + function: ADD_OPERATOR, + args: [stepArg0, stepArg1], + }); + const step2Arg1 = identExpr(helper.nextId(ctx), { name: ACCUMULATOR_VAR }); + step = callExpr(helper.nextId(ctx), { + function: CONDITIONAL_OPERATOR, + args: [filter, step, step2Arg1], + }); + const result = identExpr(helper.nextId(ctx), { name: ACCUMULATOR_VAR }); + return comprehensionExpr(helper.nextId(ctx), { + iterRange: target, + iterVar: v, + accuVar: ACCUMULATOR_VAR, + accuInit: listInit, + loopCondition: condition, + loopStep: step, + result, }); } -function extractIdent(expr: Expr): string | null { - if (expr.exprKind.case !== 'identExpr') { - return null; +export class MacroError extends Error { + constructor( + message: string, + public readonly ctx: + | ParserRuleContext + | Token + | Location + | OffsetRange + | null, + public readonly expr?: Expr + ) { + super(message); + this.name = 'MacroError'; } - return expr.exprKind.value.name; } diff --git a/packages/cel/src/lib/parser-helper.ts b/packages/cel/src/lib/parser-helper.ts index 0550c38..78dbe47 100644 --- a/packages/cel/src/lib/parser-helper.ts +++ b/packages/cel/src/lib/parser-helper.ts @@ -1,4 +1,4 @@ -import { SourceInfoSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb'; +import { SourceInfoSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; import { create } from '@bufbuild/protobuf'; import { ParserRuleContext, Token } from 'antlr4'; import { Location, OffsetRange } from './types'; @@ -21,7 +21,9 @@ export class ParserHelper { return this.#id; } - public nextId(ctx?: ParserRuleContext | Token | Location | OffsetRange) { + public nextId( + ctx?: ParserRuleContext | Token | Location | OffsetRange | null + ) { const id = this.#id++; if (ctx) { let offsetRange: OffsetRange = { start: 0, stop: 0 }; diff --git a/packages/cel/src/lib/parser.spec.ts b/packages/cel/src/lib/parser.spec.ts index 50d00a9..215cb90 100644 --- a/packages/cel/src/lib/parser.spec.ts +++ b/packages/cel/src/lib/parser.spec.ts @@ -1,10 +1,50 @@ -import { Expr } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb'; /* eslint-disable no-useless-escape */ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { ExprSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; -import { create } from '@bufbuild/protobuf'; -import { NullValue } from '@bufbuild/protobuf/wkt'; -import { CELParser } from './parser'; +import { isNil } from '@bearclaw/is'; +import { Expr } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { ACCUMULATOR_VAR } from './constants'; +import { + ADD_OPERATOR, + CONDITIONAL_OPERATOR, + DIVIDE_OPERATOR, + EQUALS_OPERATOR, + GREATER_EQUALS_OPERATOR, + GREATER_OPERATOR, + INDEX_OPERATOR, + IN_OPERATOR, + LESS_EQUALS_OPERATOR, + LESS_OPERATOR, + LOGICAL_AND_OPERATOR, + LOGICAL_NOT_OPERATOR, + LOGICAL_OR_OPERATOR, + MODULO_OPERATOR, + MULTIPLY_OPERATOR, + NEGATE_OPERATOR, + NOT_EQUALS_OPERATOR, + NOT_STRICTLY_FALSE_OPERATOR, + OPT_INDEX_OPERATOR, + OPT_SELECT_OPERATOR, + SUBTRACT_OPERATOR, +} from './operators'; +import { CELParser, CELParserOptions } from './parser'; +import { Location } from './types'; +import { + boolExpr, + bytesExpr, + callExpr, + comprehensionExpr, + createStructFieldEntry, + createStructMapEntry, + doubleExpr, + identExpr, + int64Expr, + listExpr, + nullExpr, + selectExpr, + stringExpr, + structExpr, + uint64Expr, +} from './utils'; interface TestInfo { // I contains the input expression to be parsed. @@ -17,193 +57,103 @@ interface TestInfo { E?: string; // L contains the expected source adorned debug output of the expression tree. - L?: string; + L?: { [key: string]: Location }; // M contains the expected adorned debug output of the macro calls map M?: Expr | any; // Opts contains the list of options to be configured with the parser before parsing the expression. - Opts?: unknown[]; + Opts?: CELParserOptions; } // See: https://github.com/google/cel-go/blob/master/parser/parser_test.go const testCases: TestInfo[] = [ + { + I: `has("a")`, + E: `ERROR: :1:5: invalid argument to has() macro + | has("a") + | ....^`, + }, + { + I: `1.exists(2, 3)`, + E: `ERROR: :1:10: argument must be a simple name + | 1.exists(2, 3) + | .........^`, + }, + { + I: `1.exists_one(2, 3)`, + E: `ERROR: :1:14: argument must be a simple name + | 1.exists_one(2, 3) + | .............^`, + }, + { + I: `e.map(1, t)`, + E: `ERROR: :1:7: argument is not an identifier + | e.map(1, t) + | ......^`, + }, + { + I: `e.filter(1, t)`, + E: `ERROR: :1:10: argument is not an identifier + | e.filter(1, t) + | .........^`, + }, + // Tests from Go parser { I: `"A"`, // P: `"A"^#1:*expr.Constant_StringValue#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'stringValue', - value: 'A', - }, - }, - }, - }), + P: stringExpr(BigInt(1), 'A'), }, { I: `true`, // P: `true^#1:*expr.Constant_BoolValue#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'boolValue', - value: true, - }, - }, - }, - }), + P: boolExpr(BigInt(1), true), }, { I: `false`, // P: `false^#1:*expr.Constant_BoolValue#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'boolValue', - value: false, - }, - }, - }, - }), + P: boolExpr(BigInt(1), false), }, { I: `0`, // P: `0^#1:*expr.Constant_Int64Value#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(0), - }, - }, - }, - }), + P: int64Expr(BigInt(1), BigInt(0)), }, { I: `42`, // P: `42^#1:*expr.Constant_Int64Value#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(42), - }, - }, - }, - }), + P: int64Expr(BigInt(1), BigInt(42)), }, { I: `0xF`, // P: `15^#1:*expr.Constant_Int64Value#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(15), - }, - }, - }, - }), + P: int64Expr(BigInt(1), BigInt(15)), }, { I: `0u`, // P: `0u^#1:*expr.Constant_Uint64Value#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'uint64Value', - value: BigInt(0), - }, - }, - }, - }), + P: uint64Expr(BigInt(1), BigInt(0)), }, { I: `23u`, // P: `23u^#1:*expr.Constant_Uint64Value#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'uint64Value', - value: BigInt(23), - }, - }, - }, - }), + P: uint64Expr(BigInt(1), BigInt(23)), }, { I: `24u`, // P: `24u^#1:*expr.Constant_Uint64Value#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'uint64Value', - value: BigInt(24), - }, - }, - }, - }), + P: uint64Expr(BigInt(1), BigInt(24)), }, { I: `0xFu`, // P: `15u^#1:*expr.Constant_Uint64Value#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'uint64Value', - value: BigInt(15), - }, - }, - }, - }), + P: uint64Expr(BigInt(1), BigInt(15)), }, { I: `-1`, // P: `-1^#1:*expr.Constant_Int64Value#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(-1), - }, - }, - }, - }), + P: int64Expr(BigInt(1), BigInt(-1)), }, { I: `4--4`, @@ -211,40 +161,9 @@ const testCases: TestInfo[] = [ // 4^#1:*expr.Constant_Int64Value#, // -4^#3:*expr.Constant_Int64Value# // )^#2:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_-_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(4), - }, - }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(-4), - }, - }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(2), { + function: SUBTRACT_OPERATOR, + args: [int64Expr(BigInt(1), BigInt(4)), int64Expr(BigInt(3), BigInt(-4))], }), }, { @@ -253,124 +172,40 @@ const testCases: TestInfo[] = [ // 4^#1:*expr.Constant_Int64Value#, // -4.1^#3:*expr.Constant_DoubleValue# // )^#2:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_-_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(4), - }, - }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'doubleValue', - value: -4.1, - }, - }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(2), { + function: SUBTRACT_OPERATOR, + args: [int64Expr(BigInt(1), BigInt(4)), doubleExpr(BigInt(3), -4.1)], }), }, { I: `b"abc"`, // P: `b"abc"^#1:*expr.Constant_BytesValue#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'bytesValue', - value: new TextEncoder().encode('abc'), - }, - }, - }, - }), + P: bytesExpr(BigInt(1), new TextEncoder().encode('abc')), }, { I: '23.39', // P: `23.39^#1:*expr.Constant_DoubleValue#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'doubleValue', - value: 23.39, - }, - }, - }, - }), + P: doubleExpr(BigInt(1), 23.39), }, { I: `!a`, // P: `!_( // a^#2:*expr.Expr_IdentExpr# // )^#1:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'callExpr', - value: { - function: '!_', - args: [ - { - id: BigInt(2), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(1), { + function: LOGICAL_NOT_OPERATOR, + args: [identExpr(BigInt(2), { name: 'a' })], }), }, { I: 'null', // P: `null^#1:*expr.Constant_NullValue#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'nullValue', - value: NullValue.NULL_VALUE, - }, - }, - }, - }), + P: nullExpr(BigInt(1)), }, { I: `a`, // P: `a^#1:*expr.Expr_IdentExpr#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }), + P: identExpr(BigInt(1), { name: 'a' }), }, { I: `a?b:c`, @@ -379,37 +214,13 @@ const testCases: TestInfo[] = [ // b^#3:*expr.Expr_IdentExpr#, // c^#4:*expr.Expr_IdentExpr# // )^#2:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_?_:_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }, - { - id: BigInt(4), - exprKind: { - case: 'identExpr', - value: { name: 'c' }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(2), { + function: CONDITIONAL_OPERATOR, + args: [ + identExpr(BigInt(1), { name: 'a' }), + identExpr(BigInt(3), { name: 'b' }), + identExpr(BigInt(4), { name: 'c' }), + ], }), }, { @@ -418,30 +229,12 @@ const testCases: TestInfo[] = [ // a^#1:*expr.Expr_IdentExpr#, // b^#2:*expr.Expr_IdentExpr# // )^#3:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(3), - exprKind: { - case: 'callExpr', - value: { - function: '_||_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - { - id: BigInt(2), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(3), { + function: LOGICAL_OR_OPERATOR, + args: [ + identExpr(BigInt(1), { name: 'a' }), + identExpr(BigInt(2), { name: 'b' }), + ], }), }, { @@ -462,102 +255,36 @@ const testCases: TestInfo[] = [ // f^#10:*expr.Expr_IdentExpr# // )^#11:*expr.Expr_CallExpr# // )^#7:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(7), - exprKind: { - case: 'callExpr', - value: { - function: '_||_', + P: callExpr(BigInt(7), { + function: LOGICAL_OR_OPERATOR, + args: [ + callExpr(BigInt(5), { + function: LOGICAL_OR_OPERATOR, args: [ - { - id: BigInt(5), - exprKind: { - case: 'callExpr', - value: { - function: '_||_', - args: [ - { - id: BigInt(3), - exprKind: { - case: 'callExpr', - value: { - function: '_||_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - { - id: BigInt(2), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }, - ], - }, - }, - }, - { - id: BigInt(4), - exprKind: { - case: 'identExpr', - value: { name: 'c' }, - }, - }, - ], - }, - }, - }, - { - id: BigInt(11), - exprKind: { - case: 'callExpr', - value: { - function: '_||_', - args: [ - { - id: BigInt(9), - exprKind: { - case: 'callExpr', - value: { - function: '_||_', - args: [ - { - id: BigInt(6), - exprKind: { - case: 'identExpr', - value: { name: 'd' }, - }, - }, - { - id: BigInt(8), - exprKind: { - case: 'identExpr', - value: { name: 'e' }, - }, - }, - ], - }, - }, - }, - { - id: BigInt(10), - exprKind: { - case: 'identExpr', - value: { name: 'f' }, - }, - }, - ], - }, - }, - }, + callExpr(BigInt(3), { + function: LOGICAL_OR_OPERATOR, + args: [ + identExpr(BigInt(1), { name: 'a' }), + identExpr(BigInt(2), { name: 'b' }), + ], + }), + identExpr(BigInt(4), { name: 'c' }), + ], + }), + callExpr(BigInt(11), { + function: LOGICAL_OR_OPERATOR, + args: [ + callExpr(BigInt(9), { + function: LOGICAL_OR_OPERATOR, + args: [ + identExpr(BigInt(6), { name: 'd' }), + identExpr(BigInt(8), { name: 'e' }), + ], + }), + identExpr(BigInt(10), { name: 'f' }), ], - }, - }, + }), + ], }), }, { @@ -566,30 +293,12 @@ const testCases: TestInfo[] = [ // a^#1:*expr.Expr_IdentExpr#, // b^#2:*expr.Expr_IdentExpr# // )^#3:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(3), - exprKind: { - case: 'callExpr', - value: { - function: '_&&_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - { - id: BigInt(2), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(3), { + function: LOGICAL_AND_OPERATOR, + args: [ + identExpr(BigInt(1), { name: 'a' }), + identExpr(BigInt(2), { name: 'b' }), + ], }), }, { @@ -613,120 +322,42 @@ const testCases: TestInfo[] = [ // g^#12:*expr.Expr_IdentExpr# // )^#13:*expr.Expr_CallExpr# // )^#9:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(9), - exprKind: { - case: 'callExpr', - value: { - function: '_&&_', + P: callExpr(BigInt(9), { + function: LOGICAL_AND_OPERATOR, + args: [ + callExpr(BigInt(5), { + function: LOGICAL_AND_OPERATOR, args: [ - { - id: BigInt(5), - exprKind: { - case: 'callExpr', - value: { - function: '_&&_', - args: [ - { - id: BigInt(3), - exprKind: { - case: 'callExpr', - value: { - function: '_&&_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - { - id: BigInt(2), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }, - ], - }, - }, - }, - { - id: BigInt(7), - exprKind: { - case: 'callExpr', - value: { - function: '_&&_', - args: [ - { - id: BigInt(4), - exprKind: { - case: 'identExpr', - value: { name: 'c' }, - }, - }, - { - id: BigInt(6), - exprKind: { - case: 'identExpr', - value: { name: 'd' }, - }, - }, - ], - }, - }, - }, - ], - }, - }, - }, - { - id: BigInt(13), - exprKind: { - case: 'callExpr', - value: { - function: '_&&_', - args: [ - { - id: BigInt(11), - exprKind: { - case: 'callExpr', - value: { - function: '_&&_', - args: [ - { - id: BigInt(8), - exprKind: { - case: 'identExpr', - value: { name: 'e' }, - }, - }, - { - id: BigInt(10), - exprKind: { - case: 'identExpr', - value: { name: 'f' }, - }, - }, - ], - }, - }, - }, - { - id: BigInt(12), - exprKind: { - case: 'identExpr', - value: { name: 'g' }, - }, - }, - ], - }, - }, - }, + callExpr(BigInt(3), { + function: LOGICAL_AND_OPERATOR, + args: [ + identExpr(BigInt(1), { name: 'a' }), + identExpr(BigInt(2), { name: 'b' }), + ], + }), + callExpr(BigInt(7), { + function: LOGICAL_AND_OPERATOR, + args: [ + identExpr(BigInt(4), { name: 'c' }), + identExpr(BigInt(6), { name: 'd' }), + ], + }), ], - }, - }, + }), + callExpr(BigInt(13), { + function: LOGICAL_AND_OPERATOR, + args: [ + callExpr(BigInt(11), { + function: LOGICAL_AND_OPERATOR, + args: [ + identExpr(BigInt(8), { name: 'e' }), + identExpr(BigInt(10), { name: 'f' }), + ], + }), + identExpr(BigInt(12), { name: 'g' }), + ], + }), + ], }), }, { @@ -753,138 +384,48 @@ const testCases: TestInfo[] = [ // )^#14:*expr.Expr_CallExpr# // )^#12:*expr.Expr_CallExpr# // )^#15:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(15), - exprKind: { - case: 'callExpr', - value: { - function: '_||_', + P: callExpr(BigInt(15), { + function: LOGICAL_OR_OPERATOR, + args: [ + callExpr(BigInt(5), { + function: LOGICAL_AND_OPERATOR, args: [ - { - id: BigInt(5), - exprKind: { - case: 'callExpr', - value: { - function: '_&&_', - args: [ - { - id: BigInt(3), - exprKind: { - case: 'callExpr', - value: { - function: '_&&_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - { - id: BigInt(2), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }, - ], - }, - }, - }, - { - id: BigInt(7), - exprKind: { - case: 'callExpr', - value: { - function: '_&&_', - args: [ - { - id: BigInt(4), - exprKind: { - case: 'identExpr', - value: { name: 'c' }, - }, - }, - { - id: BigInt(6), - exprKind: { - case: 'identExpr', - value: { name: 'd' }, - }, - }, - ], - }, - }, - }, - ], - }, - }, - }, - { - id: BigInt(12), - exprKind: { - case: 'callExpr', - value: { - function: '_&&_', - args: [ - { - id: BigInt(10), - exprKind: { - case: 'callExpr', - value: { - function: '_&&_', - args: [ - { - id: BigInt(8), - exprKind: { - case: 'identExpr', - value: { name: 'e' }, - }, - }, - { - id: BigInt(9), - exprKind: { - case: 'identExpr', - value: { name: 'f' }, - }, - }, - ], - }, - }, - }, - { - id: BigInt(14), - exprKind: { - case: 'callExpr', - value: { - function: '_&&_', - args: [ - { - id: BigInt(11), - exprKind: { - case: 'identExpr', - value: { name: 'g' }, - }, - }, - { - id: BigInt(13), - exprKind: { - case: 'identExpr', - value: { name: 'h' }, - }, - }, - ], - }, - }, - }, - ], - }, - }, - }, + callExpr(BigInt(3), { + function: LOGICAL_AND_OPERATOR, + args: [ + identExpr(BigInt(1), { name: 'a' }), + identExpr(BigInt(2), { name: 'b' }), + ], + }), + callExpr(BigInt(7), { + function: LOGICAL_AND_OPERATOR, + args: [ + identExpr(BigInt(4), { name: 'c' }), + identExpr(BigInt(6), { name: 'd' }), + ], + }), ], - }, - }, + }), + callExpr(BigInt(12), { + function: LOGICAL_AND_OPERATOR, + args: [ + callExpr(BigInt(10), { + function: LOGICAL_AND_OPERATOR, + args: [ + identExpr(BigInt(8), { name: 'e' }), + identExpr(BigInt(9), { name: 'f' }), + ], + }), + callExpr(BigInt(14), { + function: LOGICAL_AND_OPERATOR, + args: [ + identExpr(BigInt(11), { name: 'g' }), + identExpr(BigInt(13), { name: 'h' }), + ], + }), + ], + }), + ], }), }, { @@ -893,30 +434,12 @@ const testCases: TestInfo[] = [ // a^#1:*expr.Expr_IdentExpr#, // b^#3:*expr.Expr_IdentExpr# // )^#2:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_+_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(2), { + function: ADD_OPERATOR, + args: [ + identExpr(BigInt(1), { name: 'a' }), + identExpr(BigInt(3), { name: 'b' }), + ], }), }, { @@ -925,30 +448,12 @@ const testCases: TestInfo[] = [ // a^#1:*expr.Expr_IdentExpr#, // b^#3:*expr.Expr_IdentExpr# // )^#2:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_-_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(2), { + function: SUBTRACT_OPERATOR, + args: [ + identExpr(BigInt(1), { name: 'a' }), + identExpr(BigInt(3), { name: 'b' }), + ], }), }, { @@ -957,30 +462,12 @@ const testCases: TestInfo[] = [ // a^#1:*expr.Expr_IdentExpr#, // b^#3:*expr.Expr_IdentExpr# // )^#2:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_*_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(2), { + function: MULTIPLY_OPERATOR, + args: [ + identExpr(BigInt(1), { name: 'a' }), + identExpr(BigInt(3), { name: 'b' }), + ], }), }, { @@ -989,30 +476,12 @@ const testCases: TestInfo[] = [ // a^#1:*expr.Expr_IdentExpr#, // b^#3:*expr.Expr_IdentExpr# // )^#2:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_/_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(2), { + function: DIVIDE_OPERATOR, + args: [ + identExpr(BigInt(1), { name: 'a' }), + identExpr(BigInt(3), { name: 'b' }), + ], }), }, { @@ -1021,30 +490,12 @@ const testCases: TestInfo[] = [ // a^#1:*expr.Expr_IdentExpr#, // b^#3:*expr.Expr_IdentExpr# // )^#2:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_%_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(2), { + function: MODULO_OPERATOR, + args: [ + identExpr(BigInt(1), { name: 'a' }), + identExpr(BigInt(3), { name: 'b' }), + ], }), }, { @@ -1053,30 +504,12 @@ const testCases: TestInfo[] = [ // a^#1:*expr.Expr_IdentExpr#, // b^#3:*expr.Expr_IdentExpr# // )^#2:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '@in', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(2), { + function: IN_OPERATOR, + args: [ + identExpr(BigInt(1), { name: 'a' }), + identExpr(BigInt(3), { name: 'b' }), + ], }), }, { @@ -1085,30 +518,12 @@ const testCases: TestInfo[] = [ // a^#1:*expr.Expr_IdentExpr#, // b^#3:*expr.Expr_IdentExpr# // )^#2:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_==_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(2), { + function: EQUALS_OPERATOR, + args: [ + identExpr(BigInt(1), { name: 'a' }), + identExpr(BigInt(3), { name: 'b' }), + ], }), }, { @@ -1117,30 +532,12 @@ const testCases: TestInfo[] = [ // a^#1:*expr.Expr_IdentExpr#, // b^#3:*expr.Expr_IdentExpr# // )^#2:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_!=_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(2), { + function: NOT_EQUALS_OPERATOR, + args: [ + identExpr(BigInt(1), { name: 'a' }), + identExpr(BigInt(3), { name: 'b' }), + ], }), }, { @@ -1149,30 +546,12 @@ const testCases: TestInfo[] = [ // a^#1:*expr.Expr_IdentExpr#, // b^#3:*expr.Expr_IdentExpr# // )^#2:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_>_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(2), { + function: GREATER_OPERATOR, + args: [ + identExpr(BigInt(1), { name: 'a' }), + identExpr(BigInt(3), { name: 'b' }), + ], }), }, { @@ -1181,30 +560,12 @@ const testCases: TestInfo[] = [ // a^#1:*expr.Expr_IdentExpr#, // b^#3:*expr.Expr_IdentExpr# // )^#2:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_>=_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(2), { + function: GREATER_EQUALS_OPERATOR, + args: [ + identExpr(BigInt(1), { name: 'a' }), + identExpr(BigInt(3), { name: 'b' }), + ], }), }, { @@ -1213,30 +574,12 @@ const testCases: TestInfo[] = [ // a^#1:*expr.Expr_IdentExpr#, // b^#3:*expr.Expr_IdentExpr# // )^#2:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_<_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(2), { + function: LESS_OPERATOR, + args: [ + identExpr(BigInt(1), { name: 'a' }), + identExpr(BigInt(3), { name: 'b' }), + ], }), }, { @@ -1245,79 +588,31 @@ const testCases: TestInfo[] = [ // a^#1:*expr.Expr_IdentExpr#, // b^#3:*expr.Expr_IdentExpr# // )^#2:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_<=_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(2), { + function: LESS_EQUALS_OPERATOR, + args: [ + identExpr(BigInt(1), { name: 'a' }), + identExpr(BigInt(3), { name: 'b' }), + ], }), }, { I: `a.b`, // P: `a^#1:*expr.Expr_IdentExpr#.b^#2:*expr.Expr_SelectExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'selectExpr', - value: { - operand: { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - field: 'b', - }, - }, + P: selectExpr(BigInt(2), { + operand: identExpr(BigInt(1), { name: 'a' }), + field: 'b', }), }, { I: `a.b.c`, // P: `a^#1:*expr.Expr_IdentExpr#.b^#2:*expr.Expr_SelectExpr#.c^#3:*expr.Expr_SelectExpr#`, - P: create(ExprSchema, { - id: BigInt(3), - exprKind: { - case: 'selectExpr', - value: { - operand: { - id: BigInt(2), - exprKind: { - case: 'selectExpr', - value: { - operand: { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - field: 'b', - }, - }, - }, - field: 'c', - }, - }, + P: selectExpr(BigInt(3), { + operand: selectExpr(BigInt(2), { + operand: identExpr(BigInt(1), { name: 'a' }), + field: 'b', + }), + field: 'c', }), }, { @@ -1326,44 +621,19 @@ const testCases: TestInfo[] = [ // a^#1:*expr.Expr_IdentExpr#, // b^#3:*expr.Expr_IdentExpr# // )^#2:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_[_]', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(2), { + function: INDEX_OPERATOR, + args: [ + identExpr(BigInt(1), { name: 'a' }), + identExpr(BigInt(3), { name: 'b' }), + ], }), }, { I: `foo{ }`, // P: `foo{}^#1:*expr.Expr_StructExpr#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'structExpr', - value: { - messageName: 'foo', - entries: [], - }, - }, + P: structExpr(BigInt(1), { + messageName: 'foo', }), }, { @@ -1371,30 +641,14 @@ const testCases: TestInfo[] = [ // P: `foo{ // a:b^#3:*expr.Expr_IdentExpr#^#2:*expr.Expr_CreateStruct_Entry# // }^#1:*expr.Expr_StructExpr#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'structExpr', - value: { - messageName: 'foo', - entries: [ - { - id: BigInt(2), - keyKind: { - case: 'fieldKey', - value: 'a', - }, - value: { - id: BigInt(3), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }, - }, - ], - }, - }, + P: structExpr(BigInt(1), { + messageName: 'foo', + entries: [ + createStructFieldEntry(BigInt(2), { + key: 'a', + value: identExpr(BigInt(3), { name: 'b' }), + }), + ], }), }, { @@ -1403,59 +657,24 @@ const testCases: TestInfo[] = [ // a:b^#3:*expr.Expr_IdentExpr#^#2:*expr.Expr_CreateStruct_Entry#, // c:d^#5:*expr.Expr_IdentExpr#^#4:*expr.Expr_CreateStruct_Entry# // }^#1:*expr.Expr_StructExpr#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'structExpr', - value: { - messageName: 'foo', - entries: [ - { - id: BigInt(2), - keyKind: { - case: 'fieldKey', - value: 'a', - }, - value: { - id: BigInt(3), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }, - }, - { - id: BigInt(4), - keyKind: { - case: 'fieldKey', - value: 'c', - }, - value: { - id: BigInt(5), - exprKind: { - case: 'identExpr', - value: { name: 'd' }, - }, - }, - }, - ], - }, - }, + P: structExpr(BigInt(1), { + messageName: 'foo', + entries: [ + createStructFieldEntry(BigInt(2), { + key: 'a', + value: identExpr(BigInt(3), { name: 'b' }), + }), + createStructFieldEntry(BigInt(4), { + key: 'c', + value: identExpr(BigInt(5), { name: 'd' }), + }), + ], }), }, { I: `{}`, // P: `{}^#1:*expr.Expr_StructExpr#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'structExpr', - value: { - messageName: '', - entries: [], - }, - }, - }), + P: structExpr(BigInt(1), {}), }, { I: `{a:b, c:d}`, @@ -1463,92 +682,31 @@ const testCases: TestInfo[] = [ // a^#3:*expr.Expr_IdentExpr#:b^#4:*expr.Expr_IdentExpr#^#2:*expr.Expr_CreateStruct_Entry#, // c^#6:*expr.Expr_IdentExpr#:d^#7:*expr.Expr_IdentExpr#^#5:*expr.Expr_CreateStruct_Entry# // }^#1:*expr.Expr_StructExpr#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'structExpr', - value: { - messageName: '', - entries: [ - { - id: BigInt(2), - keyKind: { - case: 'mapKey', - value: { - id: BigInt(3), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - }, - value: { - id: BigInt(4), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }, - }, - { - id: BigInt(5), - keyKind: { - case: 'mapKey', - value: { - id: BigInt(6), - exprKind: { - case: 'identExpr', - value: { name: 'c' }, - }, - }, - }, - value: { - id: BigInt(7), - exprKind: { - case: 'identExpr', - value: { name: 'd' }, - }, - }, - }, - ], - }, - }, + P: structExpr(BigInt(1), { + entries: [ + createStructMapEntry(BigInt(2), { + key: identExpr(BigInt(3), { name: 'a' }), + value: identExpr(BigInt(4), { name: 'b' }), + }), + createStructMapEntry(BigInt(5), { + key: identExpr(BigInt(6), { name: 'c' }), + value: identExpr(BigInt(7), { name: 'd' }), + }), + ], }), }, { I: `[]`, // P: `[]^#1:*expr.Expr_ListExpr#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'listExpr', - value: { - elements: [], - }, - }, - }), + P: listExpr(BigInt(1), {}), }, { I: `[a]`, // P: `[ // a^#2:*expr.Expr_IdentExpr# // ]^#1:*expr.Expr_ListExpr#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'listExpr', - value: { - elements: [ - { - id: BigInt(2), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - ], - }, - }, + P: listExpr(BigInt(1), { + elements: [identExpr(BigInt(2), { name: 'a' })], }), }, { @@ -1558,96 +716,37 @@ const testCases: TestInfo[] = [ // b^#3:*expr.Expr_IdentExpr#, // c^#4:*expr.Expr_IdentExpr# // ]^#1:*expr.Expr_ListExpr#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'listExpr', - value: { - elements: [ - { - id: BigInt(2), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }, - { - id: BigInt(4), - exprKind: { - case: 'identExpr', - value: { name: 'c' }, - }, - }, - ], - }, - }, + P: listExpr(BigInt(1), { + elements: [ + identExpr(BigInt(2), { name: 'a' }), + identExpr(BigInt(3), { name: 'b' }), + identExpr(BigInt(4), { name: 'c' }), + ], }), }, { I: `(a)`, // P: `a^#1:*expr.Expr_IdentExpr#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }), + P: identExpr(BigInt(1), { name: 'a' }), }, { I: `((a))`, // P: `a^#1:*expr.Expr_IdentExpr#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }), + P: identExpr(BigInt(1), { name: 'a' }), }, { I: `a()`, // P: `a()^#1:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'callExpr', - value: { - function: 'a', - args: [], - }, - }, - }), + P: callExpr(BigInt(1), { function: 'a', args: [] }), }, { I: `a(b)`, // P: `a( // b^#2:*expr.Expr_IdentExpr# // )^#1:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'callExpr', - value: { - function: 'a', - args: [ - { - id: BigInt(2), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(1), { + function: 'a', + args: [identExpr(BigInt(2), { name: 'b' })], }), }, { @@ -1656,51 +755,21 @@ const testCases: TestInfo[] = [ // b^#2:*expr.Expr_IdentExpr#, // c^#3:*expr.Expr_IdentExpr# // )^#1:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'callExpr', - value: { - function: 'a', - args: [ - { - id: BigInt(2), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'identExpr', - value: { name: 'c' }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(1), { + function: 'a', + args: [ + identExpr(BigInt(2), { name: 'b' }), + identExpr(BigInt(3), { name: 'c' }), + ], }), }, { I: `a.b()`, // P: `a^#1:*expr.Expr_IdentExpr#.b()^#2:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: 'b', - target: { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - args: [], - }, - }, + P: callExpr(BigInt(2), { + function: 'b', + target: identExpr(BigInt(1), { name: 'a' }), + args: [], }), }, { @@ -1711,31 +780,16 @@ const testCases: TestInfo[] = [ // L: `a^#1[1,0]#.b( // c^#3[1,4]# // )^#2[1,3]#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: 'b', - target: { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - args: [ - { - id: BigInt(3), - exprKind: { - case: 'identExpr', - value: { name: 'c' }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(2), { + function: 'b', + target: identExpr(BigInt(1), { name: 'a' }), + args: [identExpr(BigInt(3), { name: 'c' })], }), + L: { + '1': { line: 1, column: 0 }, + '2': { line: 1, column: 3 }, + '3': { line: 1, column: 4 }, + }, }, // TODO: Parse error tests // // Parse error tests @@ -1789,23 +843,15 @@ const testCases: TestInfo[] = [ // M: `has( // m^#2:*expr.Expr_IdentExpr#.f^#3:*expr.Expr_SelectExpr# // )^#4:has#`, - P: create(ExprSchema, { - id: BigInt(4), - exprKind: { - case: 'selectExpr', - value: { - field: 'f', - operand: { - id: BigInt(2), - exprKind: { - case: 'identExpr', - value: { name: 'm' }, - }, - }, - testOnly: true, - }, - }, + P: selectExpr(BigInt(4), { + operand: identExpr(BigInt(2), { name: 'm' }), + field: 'f', + testOnly: true, }), + // L: { + // '2': { line: 1, column: 4 }, + // '4': { line: 1, column: 3 }, + // }, }, { I: `m.exists(v, f)`, @@ -1835,96 +881,28 @@ const testCases: TestInfo[] = [ // v^#3:*expr.Expr_IdentExpr#, // f^#4:*expr.Expr_IdentExpr# // )^#12:exists#`, - P: create(ExprSchema, { - id: BigInt(12), - exprKind: { - case: 'comprehensionExpr', - value: { - accuInit: { - id: BigInt(5), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'boolValue', - value: false, - }, - }, - }, - }, - accuVar: '__result__', - iterRange: { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'm' }, - }, - }, - iterVar: 'v', - iterVar2: '', - loopCondition: { - id: BigInt(8), - exprKind: { - case: 'callExpr', - value: { - function: '@not_strictly_false', - args: [ - { - id: BigInt(7), - exprKind: { - case: 'callExpr', - value: { - function: '!_', - args: [ - { - id: BigInt(6), - exprKind: { - case: 'identExpr', - value: { name: '__result__' }, - }, - }, - ], - }, - }, - }, - ], - }, - }, - }, - loopStep: { - id: BigInt(10), - exprKind: { - case: 'callExpr', - value: { - function: '_||_', - args: [ - { - id: BigInt(9), - exprKind: { - case: 'identExpr', - value: { name: '__result__' }, - }, - }, - { - id: BigInt(4), - exprKind: { - case: 'identExpr', - value: { name: 'f' }, - }, - }, - ], - }, - }, - }, - result: { - id: BigInt(11), - exprKind: { - case: 'identExpr', - value: { name: '__result__' }, - }, - }, - }, - }, + P: comprehensionExpr(BigInt(12), { + iterRange: identExpr(BigInt(1), { name: 'm' }), + iterVar: 'v', + accuVar: ACCUMULATOR_VAR, + accuInit: boolExpr(BigInt(5), false), + loopCondition: callExpr(BigInt(8), { + function: NOT_STRICTLY_FALSE_OPERATOR, + args: [ + callExpr(BigInt(7), { + function: LOGICAL_NOT_OPERATOR, + args: [identExpr(BigInt(6), { name: ACCUMULATOR_VAR })], + }), + ], + }), + loopStep: callExpr(BigInt(10), { + function: LOGICAL_OR_OPERATOR, + args: [ + identExpr(BigInt(9), { name: ACCUMULATOR_VAR }), + identExpr(BigInt(4), { name: 'f' }), + ], + }), + result: identExpr(BigInt(11), { name: ACCUMULATOR_VAR }), }), }, { @@ -1953,85 +931,23 @@ const testCases: TestInfo[] = [ // v^#3:*expr.Expr_IdentExpr#, // f^#4:*expr.Expr_IdentExpr# // )^#11:all#`, - P: create(ExprSchema, { - id: BigInt(11), - exprKind: { - case: 'comprehensionExpr', - value: { - accuInit: { - id: BigInt(5), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'boolValue', - value: true, - }, - }, - }, - }, - accuVar: '__result__', - iterRange: { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'm' }, - }, - }, - iterVar: 'v', - iterVar2: '', - loopCondition: { - id: BigInt(7), - exprKind: { - case: 'callExpr', - value: { - function: '@not_strictly_false', - args: [ - { - id: BigInt(6), - exprKind: { - case: 'identExpr', - value: { name: '__result__' }, - }, - }, - ], - }, - }, - }, - loopStep: { - id: BigInt(9), - exprKind: { - case: 'callExpr', - value: { - function: '_&&_', - args: [ - { - id: BigInt(8), - exprKind: { - case: 'identExpr', - value: { name: '__result__' }, - }, - }, - { - id: BigInt(4), - exprKind: { - case: 'identExpr', - value: { name: 'f' }, - }, - }, - ], - }, - }, - }, - result: { - id: BigInt(10), - exprKind: { - case: 'identExpr', - value: { name: '__result__' }, - }, - }, - }, - }, + P: comprehensionExpr(BigInt(11), { + iterRange: identExpr(BigInt(1), { name: 'm' }), + iterVar: 'v', + accuVar: ACCUMULATOR_VAR, + accuInit: boolExpr(BigInt(5), true), + loopCondition: callExpr(BigInt(7), { + function: NOT_STRICTLY_FALSE_OPERATOR, + args: [identExpr(BigInt(6), { name: ACCUMULATOR_VAR })], + }), + loopStep: callExpr(BigInt(9), { + function: LOGICAL_AND_OPERATOR, + args: [ + identExpr(BigInt(8), { name: ACCUMULATOR_VAR }), + identExpr(BigInt(4), { name: 'f' }), + ], + }), + result: identExpr(BigInt(10), { name: ACCUMULATOR_VAR }), }), }, { @@ -2065,132 +981,33 @@ const testCases: TestInfo[] = [ // v^#3:*expr.Expr_IdentExpr#, // f^#4:*expr.Expr_IdentExpr# // )^#15:exists_one#`, - P: create(ExprSchema, { - id: BigInt(15), - exprKind: { - case: 'comprehensionExpr', - value: { - accuInit: { - id: BigInt(5), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(0), - }, - }, - }, - }, - accuVar: '__result__', - iterRange: { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'm' }, - }, - }, - iterVar: 'v', - iterVar2: '', - loopCondition: { - id: BigInt(6), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'boolValue', - value: true, - }, - }, - }, - }, - loopStep: { - id: BigInt(11), - exprKind: { - case: 'callExpr', - value: { - function: '_?_:_', - args: [ - { - id: BigInt(4), - exprKind: { - case: 'identExpr', - value: { name: 'f' }, - }, - }, - { - id: BigInt(9), - exprKind: { - case: 'callExpr', - value: { - function: '_+_', - args: [ - { - id: BigInt(7), - exprKind: { - case: 'identExpr', - value: { name: '__result__' }, - }, - }, - { - id: BigInt(8), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(1), - }, - }, - }, - }, - ], - }, - }, - }, - { - id: BigInt(10), - exprKind: { - case: 'identExpr', - value: { name: '__result__' }, - }, - }, - ], - }, - }, - }, - result: { - id: BigInt(14), - exprKind: { - case: 'callExpr', - value: { - function: '_==_', - args: [ - { - id: BigInt(12), - exprKind: { - case: 'identExpr', - value: { name: '__result__' }, - }, - }, - { - id: BigInt(13), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(1), - }, - }, - }, - }, - ], - }, - }, - }, - }, - }, + P: comprehensionExpr(BigInt(15), { + iterRange: identExpr(BigInt(1), { name: 'm' }), + iterVar: 'v', + accuVar: ACCUMULATOR_VAR, + accuInit: int64Expr(BigInt(5), BigInt(0)), + loopCondition: boolExpr(BigInt(6), true), + loopStep: callExpr(BigInt(11), { + function: CONDITIONAL_OPERATOR, + args: [ + identExpr(BigInt(4), { name: 'f' }), + callExpr(BigInt(9), { + function: ADD_OPERATOR, + args: [ + identExpr(BigInt(7), { name: ACCUMULATOR_VAR }), + int64Expr(BigInt(8), BigInt(1)), + ], + }), + identExpr(BigInt(10), { name: ACCUMULATOR_VAR }), + ], + }), + result: callExpr(BigInt(14), { + function: '_==_', + args: [ + identExpr(BigInt(12), { name: ACCUMULATOR_VAR }), + int64Expr(BigInt(13), BigInt(1)), + ], + }), }), }, { @@ -2219,86 +1036,22 @@ const testCases: TestInfo[] = [ // v^#3:*expr.Expr_IdentExpr#, // f^#4:*expr.Expr_IdentExpr# // )^#11:map#`, - P: create(ExprSchema, { - id: BigInt(11), - exprKind: { - case: 'comprehensionExpr', - value: { - accuInit: { - id: BigInt(5), - exprKind: { - case: 'listExpr', - value: { - elements: [], - }, - }, - }, - accuVar: '__result__', - iterRange: { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'm' }, - }, - }, - iterVar: 'v', - iterVar2: '', - loopCondition: { - id: BigInt(6), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'boolValue', - value: true, - }, - }, - }, - }, - loopStep: { - id: BigInt(9), - exprKind: { - case: 'callExpr', - value: { - function: '_+_', - args: [ - { - id: BigInt(7), - exprKind: { - case: 'identExpr', - value: { name: '__result__' }, - }, - }, - { - id: BigInt(8), - exprKind: { - case: 'listExpr', - value: { - elements: [ - { - id: BigInt(4), - exprKind: { - case: 'identExpr', - value: { name: 'f' }, - }, - }, - ], - }, - }, - }, - ], - }, - }, - }, - result: { - id: BigInt(10), - exprKind: { - case: 'identExpr', - value: { name: '__result__' }, - }, - }, - }, - }, + P: comprehensionExpr(BigInt(11), { + iterRange: identExpr(BigInt(1), { name: 'm' }), + iterVar: 'v', + accuVar: ACCUMULATOR_VAR, + accuInit: listExpr(BigInt(5), {}), + loopCondition: boolExpr(BigInt(6), true), + loopStep: callExpr(BigInt(9), { + function: ADD_OPERATOR, + args: [ + identExpr(BigInt(7), { name: ACCUMULATOR_VAR }), + listExpr(BigInt(8), { + elements: [identExpr(BigInt(4), { name: 'f' })], + }), + ], + }), + result: identExpr(BigInt(10), { name: ACCUMULATOR_VAR }), }), }, { @@ -2332,111 +1085,29 @@ const testCases: TestInfo[] = [ // p^#4:*expr.Expr_IdentExpr#, // f^#5:*expr.Expr_IdentExpr# // )^#14:map#`, - P: create(ExprSchema, { - id: BigInt(14), - exprKind: { - case: 'comprehensionExpr', - value: { - accuInit: { - id: BigInt(6), - exprKind: { - case: 'listExpr', - value: { - elements: [], - }, - }, - }, - accuVar: '__result__', - iterRange: { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'm' }, - }, - }, - iterVar: 'v', - iterVar2: '', - loopCondition: { - id: BigInt(7), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'boolValue', - value: true, - }, - }, - }, - }, - loopStep: { - id: BigInt(12), - exprKind: { - case: 'callExpr', - value: { - function: '_?_:_', - args: [ - { - id: BigInt(4), - exprKind: { - case: 'identExpr', - value: { name: 'p' }, - }, - }, - { - id: BigInt(10), - exprKind: { - case: 'callExpr', - value: { - function: '_+_', - args: [ - { - id: BigInt(8), - exprKind: { - case: 'identExpr', - value: { name: '__result__' }, - }, - }, - { - id: BigInt(9), - exprKind: { - case: 'listExpr', - value: { - elements: [ - { - id: BigInt(5), - exprKind: { - case: 'identExpr', - value: { name: 'f' }, - }, - }, - ], - }, - }, - }, - ], - }, - }, - }, - { - id: BigInt(11), - exprKind: { - case: 'identExpr', - value: { name: '__result__' }, - }, - }, - ], - }, - }, - }, - result: { - id: BigInt(13), - exprKind: { - case: 'identExpr', - value: { name: '__result__' }, - }, - }, - }, - }, + P: comprehensionExpr(BigInt(14), { + iterRange: identExpr(BigInt(1), { name: 'm' }), + iterVar: 'v', + accuVar: ACCUMULATOR_VAR, + accuInit: listExpr(BigInt(6), {}), + loopCondition: boolExpr(BigInt(7), true), + loopStep: callExpr(BigInt(12), { + function: CONDITIONAL_OPERATOR, + args: [ + identExpr(BigInt(4), { name: 'p' }), + callExpr(BigInt(10), { + function: ADD_OPERATOR, + args: [ + identExpr(BigInt(8), { name: ACCUMULATOR_VAR }), + listExpr(BigInt(9), { + elements: [identExpr(BigInt(5), { name: 'f' })], + }), + ], + }), + identExpr(BigInt(11), { name: ACCUMULATOR_VAR }), + ], + }), + result: identExpr(BigInt(13), { name: ACCUMULATOR_VAR }), }), }, { @@ -2469,111 +1140,29 @@ const testCases: TestInfo[] = [ // v^#3:*expr.Expr_IdentExpr#, // p^#4:*expr.Expr_IdentExpr# // )^#13:filter#`, - P: create(ExprSchema, { - id: BigInt(13), - exprKind: { - case: 'comprehensionExpr', - value: { - accuInit: { - id: BigInt(5), - exprKind: { - case: 'listExpr', - value: { - elements: [], - }, - }, - }, - accuVar: '__result__', - iterRange: { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'm' }, - }, - }, - iterVar: 'v', - iterVar2: '', - loopCondition: { - id: BigInt(6), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'boolValue', - value: true, - }, - }, - }, - }, - loopStep: { - id: BigInt(11), - exprKind: { - case: 'callExpr', - value: { - function: '_?_:_', - args: [ - { - id: BigInt(4), - exprKind: { - case: 'identExpr', - value: { name: 'p' }, - }, - }, - { - id: BigInt(9), - exprKind: { - case: 'callExpr', - value: { - function: '_+_', - args: [ - { - id: BigInt(7), - exprKind: { - case: 'identExpr', - value: { name: '__result__' }, - }, - }, - { - id: BigInt(8), - exprKind: { - case: 'listExpr', - value: { - elements: [ - { - id: BigInt(3), - exprKind: { - case: 'identExpr', - value: { name: 'v' }, - }, - }, - ], - }, - }, - }, - ], - }, - }, - }, - { - id: BigInt(10), - exprKind: { - case: 'identExpr', - value: { name: '__result__' }, - }, - }, - ], - }, - }, - }, - result: { - id: BigInt(12), - exprKind: { - case: 'identExpr', - value: { name: '__result__' }, - }, - }, - }, - }, + P: comprehensionExpr(BigInt(13), { + iterRange: identExpr(BigInt(1), { name: 'm' }), + iterVar: 'v', + accuVar: ACCUMULATOR_VAR, + accuInit: listExpr(BigInt(5), {}), + loopCondition: boolExpr(BigInt(6), true), + loopStep: callExpr(BigInt(11), { + function: CONDITIONAL_OPERATOR, + args: [ + identExpr(BigInt(4), { name: 'p' }), + callExpr(BigInt(9), { + function: ADD_OPERATOR, + args: [ + identExpr(BigInt(7), { name: ACCUMULATOR_VAR }), + listExpr(BigInt(8), { + elements: [identExpr(BigInt(3), { name: 'v' })], + }), + ], + }), + identExpr(BigInt(10), { name: ACCUMULATOR_VAR }), + ], + }), + result: identExpr(BigInt(12), { name: ACCUMULATOR_VAR }), }), }, @@ -2584,35 +1173,12 @@ const testCases: TestInfo[] = [ // x^#1:*expr.Expr_IdentExpr#, // 2^#3:*expr.Constant_Int64Value# // )^#2:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_*_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'x' }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(2), - }, - }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(2), { + function: MULTIPLY_OPERATOR, + args: [ + identExpr(BigInt(1), { name: 'x' }), + int64Expr(BigInt(3), BigInt(2)), + ], }), }, { @@ -2621,35 +1187,12 @@ const testCases: TestInfo[] = [ // x^#1:*expr.Expr_IdentExpr#, // 2u^#3:*expr.Constant_Uint64Value# // )^#2:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_*_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'x' }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'uint64Value', - value: BigInt(2), - }, - }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(2), { + function: MULTIPLY_OPERATOR, + args: [ + identExpr(BigInt(1), { name: 'x' }), + uint64Expr(BigInt(3), BigInt(2)), + ], }), }, { @@ -2658,96 +1201,24 @@ const testCases: TestInfo[] = [ // x^#1:*expr.Expr_IdentExpr#, // 2^#3:*expr.Constant_DoubleValue# // )^#2:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_*_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'x' }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'doubleValue', - value: 2.0, - }, - }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(2), { + function: MULTIPLY_OPERATOR, + args: [identExpr(BigInt(1), { name: 'x' }), doubleExpr(BigInt(3), 2.0)], }), }, { I: `"\u2764"`, // P: "\"\u2764\"^#1:*expr.Constant_StringValue#", - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'stringValue', - value: '❤', - }, - }, - }, - }), - }, - { - I: '"\u2764"', - // P: "\"\u2764\"^#1:*expr.Constant_StringValue#", - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'stringValue', - value: '❤', - }, - }, - }, - }), + P: stringExpr(BigInt(1), '❤'), }, { I: `! false`, // P: `!_( // false^#2:*expr.Constant_BoolValue# // )^#1:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'callExpr', - value: { - function: '!_', - args: [ - { - id: BigInt(2), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'boolValue', - value: false, - }, - }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(1), { + function: LOGICAL_NOT_OPERATOR, + args: [boolExpr(BigInt(2), false)], }), }, { @@ -2755,23 +1226,9 @@ const testCases: TestInfo[] = [ // P: `-_( // a^#2:*expr.Expr_IdentExpr# // )^#1:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'callExpr', - value: { - function: '-_', - args: [ - { - id: BigInt(2), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(1), { + function: NEGATE_OPERATOR, + args: [identExpr(BigInt(2), { name: 'a' })], }), }, { @@ -2779,35 +1236,10 @@ const testCases: TestInfo[] = [ // P: `a^#1:*expr.Expr_IdentExpr#.b( // 5^#3:*expr.Constant_Int64Value# // )^#2:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: 'b', - target: { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - args: [ - { - id: BigInt(3), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(5), - }, - }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(2), { + function: 'b', + target: identExpr(BigInt(1), { name: 'a' }), + args: [int64Expr(BigInt(3), BigInt(5))], }), }, { @@ -2816,35 +1248,12 @@ const testCases: TestInfo[] = [ // a^#1:*expr.Expr_IdentExpr#, // 3^#3:*expr.Constant_Int64Value# // )^#2:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_[_]', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(3), - }, - }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(2), { + function: INDEX_OPERATOR, + args: [ + identExpr(BigInt(1), { name: 'a' }), + int64Expr(BigInt(3), BigInt(3)), + ], }), }, { @@ -2853,54 +1262,18 @@ const testCases: TestInfo[] = [ // foo:5^#3:*expr.Constant_Int64Value#^#2:*expr.Expr_CreateStruct_Entry#, // bar:"xyz"^#5:*expr.Constant_StringValue#^#4:*expr.Expr_CreateStruct_Entry# // }^#1:*expr.Expr_StructExpr#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'structExpr', - value: { - messageName: 'SomeMessage', - entries: [ - { - id: BigInt(2), - keyKind: { - case: 'fieldKey', - value: 'foo', - }, - value: { - id: BigInt(3), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(5), - }, - }, - }, - }, - }, - { - id: BigInt(4), - keyKind: { - case: 'fieldKey', - value: 'bar', - }, - value: { - id: BigInt(5), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'stringValue', - value: 'xyz', - }, - }, - }, - }, - }, - ], - }, - }, + P: structExpr(BigInt(1), { + messageName: 'SomeMessage', + entries: [ + createStructFieldEntry(BigInt(2), { + key: 'foo', + value: int64Expr(BigInt(3), BigInt(5)), + }), + createStructFieldEntry(BigInt(4), { + key: 'bar', + value: stringExpr(BigInt(5), 'xyz'), + }), + ], }), }, { @@ -2910,51 +1283,12 @@ const testCases: TestInfo[] = [ // 4^#3:*expr.Constant_Int64Value#, // 5^#4:*expr.Constant_Int64Value# // ]^#1:*expr.Expr_ListExpr#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'listExpr', - value: { - elements: [ - { - id: BigInt(2), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(3), - }, - }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(4), - }, - }, - }, - }, - { - id: BigInt(4), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(5), - }, - }, - }, - }, - ], - }, - }, + P: listExpr(BigInt(1), { + elements: [ + int64Expr(BigInt(2), BigInt(3)), + int64Expr(BigInt(3), BigInt(4)), + int64Expr(BigInt(4), BigInt(5)), + ], }), }, { @@ -2964,51 +1298,12 @@ const testCases: TestInfo[] = [ // 4^#3:*expr.Constant_Int64Value#, // 5^#4:*expr.Constant_Int64Value# // ]^#1:*expr.Expr_ListExpr#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'listExpr', - value: { - elements: [ - { - id: BigInt(2), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(3), - }, - }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(4), - }, - }, - }, - }, - { - id: BigInt(4), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(5), - }, - }, - }, - }, - ], - }, - }, + P: listExpr(BigInt(1), { + elements: [ + int64Expr(BigInt(2), BigInt(3)), + int64Expr(BigInt(3), BigInt(4)), + int64Expr(BigInt(4), BigInt(5)), + ], }), }, { @@ -3017,65 +1312,17 @@ const testCases: TestInfo[] = [ // foo^#3:*expr.Expr_IdentExpr#:5^#4:*expr.Constant_Int64Value#^#2:*expr.Expr_CreateStruct_Entry#, // bar^#6:*expr.Expr_IdentExpr#:"xyz"^#7:*expr.Constant_StringValue#^#5:*expr.Expr_CreateStruct_Entry# // }^#1:*expr.Expr_StructExpr#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'structExpr', - value: { - entries: [ - { - id: BigInt(2), - keyKind: { - case: 'mapKey', - value: { - id: BigInt(3), - exprKind: { - case: 'identExpr', - value: { name: 'foo' }, - }, - }, - }, - value: { - id: BigInt(4), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(5), - }, - }, - }, - }, - }, - { - id: BigInt(5), - keyKind: { - case: 'mapKey', - value: { - id: BigInt(6), - exprKind: { - case: 'identExpr', - value: { name: 'bar' }, - }, - }, - }, - value: { - id: BigInt(7), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'stringValue', - value: 'xyz', - }, - }, - }, - }, - }, - ], - }, - }, + P: structExpr(BigInt(1), { + entries: [ + createStructMapEntry(BigInt(2), { + key: identExpr(BigInt(3), { name: 'foo' }), + value: int64Expr(BigInt(4), BigInt(5)), + }), + createStructMapEntry(BigInt(5), { + key: identExpr(BigInt(6), { name: 'bar' }), + value: stringExpr(BigInt(7), 'xyz'), + }), + ], }), }, { @@ -3084,65 +1331,17 @@ const testCases: TestInfo[] = [ // foo^#3:*expr.Expr_IdentExpr#:5^#4:*expr.Constant_Int64Value#^#2:*expr.Expr_CreateStruct_Entry#, // bar^#6:*expr.Expr_IdentExpr#:"xyz"^#7:*expr.Constant_StringValue#^#5:*expr.Expr_CreateStruct_Entry# // }^#1:*expr.Expr_StructExpr#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'structExpr', - value: { - entries: [ - { - id: BigInt(2), - keyKind: { - case: 'mapKey', - value: { - id: BigInt(3), - exprKind: { - case: 'identExpr', - value: { name: 'foo' }, - }, - }, - }, - value: { - id: BigInt(4), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(5), - }, - }, - }, - }, - }, - { - id: BigInt(5), - keyKind: { - case: 'mapKey', - value: { - id: BigInt(6), - exprKind: { - case: 'identExpr', - value: { name: 'bar' }, - }, - }, - }, - value: { - id: BigInt(7), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'stringValue', - value: 'xyz', - }, - }, - }, - }, - }, - ], - }, - }, + P: structExpr(BigInt(1), { + entries: [ + createStructMapEntry(BigInt(2), { + key: identExpr(BigInt(3), { name: 'foo' }), + value: int64Expr(BigInt(4), BigInt(5)), + }), + createStructMapEntry(BigInt(5), { + key: identExpr(BigInt(6), { name: 'bar' }), + value: stringExpr(BigInt(7), 'xyz'), + }), + ], }), }, { @@ -3157,76 +1356,24 @@ const testCases: TestInfo[] = [ // 10^#6:*expr.Constant_Int64Value# // )^#5:*expr.Expr_CallExpr# // )^#7:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(7), - exprKind: { - case: 'callExpr', - value: { - function: '_&&_', + P: callExpr(BigInt(7), { + function: LOGICAL_AND_OPERATOR, + args: [ + callExpr(BigInt(2), { + function: GREATER_OPERATOR, args: [ - { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_>_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(5), - }, - }, - }, - }, - ], - }, - }, - }, - { - id: BigInt(5), - exprKind: { - case: 'callExpr', - value: { - function: '_<_', - args: [ - { - id: BigInt(4), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - { - id: BigInt(6), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(10), - }, - }, - }, - }, - ], - }, - }, - }, + identExpr(BigInt(1), { name: 'a' }), + int64Expr(BigInt(3), BigInt(5)), ], - }, - }, + }), + callExpr(BigInt(5), { + function: LESS_OPERATOR, + args: [ + identExpr(BigInt(4), { name: 'a' }), + int64Expr(BigInt(6), BigInt(10)), + ], + }), + ], }), }, { @@ -3241,85 +1388,32 @@ const testCases: TestInfo[] = [ // 10^#6:*expr.Constant_Int64Value# // )^#5:*expr.Expr_CallExpr# // )^#7:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(7), - exprKind: { - case: 'callExpr', - value: { - function: '_||_', + P: callExpr(BigInt(7), { + function: LOGICAL_OR_OPERATOR, + args: [ + callExpr(BigInt(2), { + function: LESS_OPERATOR, args: [ - { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_<_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(5), - }, - }, - }, - }, - ], - }, - }, - }, - { - id: BigInt(5), - exprKind: { - case: 'callExpr', - value: { - function: '_>_', - args: [ - { - id: BigInt(4), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }, - { - id: BigInt(6), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(10), - }, - }, - }, - }, - ], - }, - }, - }, + identExpr(BigInt(1), { name: 'a' }), + int64Expr(BigInt(3), BigInt(5)), ], - }, - }, + }), + callExpr(BigInt(5), { + function: GREATER_OPERATOR, + args: [ + identExpr(BigInt(4), { name: 'a' }), + int64Expr(BigInt(6), BigInt(10)), + ], + }), + ], }), }, - // TODO: Error tests - // { - // I: `{`, - // E: `ERROR: :1:2: Syntax error: mismatched input '' expecting {'[', '{', '}', '(', '.', ',', '-', '!', '?', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} - // | { - // | .^`, - // }, + { + I: `{`, + E: `ERROR: :1:2: Syntax error: mismatched input '' expecting {'[', '{', '}', '(', '.', ',', '-', '!', '?', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} + | { + | .^`, + }, // Tests from Java parser { @@ -3337,104 +1431,26 @@ const testCases: TestInfo[] = [ // 4^#9:*expr.Constant_Int64Value# // ]^#8:*expr.Expr_ListExpr# // )^#7:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(7), - exprKind: { - case: 'callExpr', - value: { - function: '_+_', + P: callExpr(BigInt(7), { + function: ADD_OPERATOR, + args: [ + callExpr(BigInt(2), { + function: ADD_OPERATOR, args: [ - { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_+_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'listExpr', - value: { - elements: [], - }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'listExpr', - value: { - elements: [ - { - id: BigInt(4), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(1), - }, - }, - }, - }, - { - id: BigInt(5), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(2), - }, - }, - }, - }, - { - id: BigInt(6), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(3), - }, - }, - }, - }, - ], - }, - }, - }, - ], - }, - }, - }, - { - id: BigInt(8), - exprKind: { - case: 'listExpr', - value: { - elements: [ - { - id: BigInt(9), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(4), - }, - }, - }, - }, - ], - }, - }, - }, + listExpr(BigInt(1), {}), + listExpr(BigInt(3), { + elements: [ + int64Expr(BigInt(4), BigInt(1)), + int64Expr(BigInt(5), BigInt(2)), + int64Expr(BigInt(6), BigInt(3)), + ], + }), ], - }, - }, + }), + listExpr(BigInt(8), { + elements: [int64Expr(BigInt(9), BigInt(4))], + }), + ], }), }, { @@ -3443,75 +1459,17 @@ const testCases: TestInfo[] = [ // 1^#3:*expr.Constant_Int64Value#:2u^#4:*expr.Constant_Uint64Value#^#2:*expr.Expr_CreateStruct_Entry#, // 2^#6:*expr.Constant_Int64Value#:3u^#7:*expr.Constant_Uint64Value#^#5:*expr.Expr_CreateStruct_Entry# // }^#1:*expr.Expr_StructExpr#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'structExpr', - value: { - entries: [ - { - id: BigInt(2), - keyKind: { - case: 'mapKey', - value: { - id: BigInt(3), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(1), - }, - }, - }, - }, - }, - value: { - id: BigInt(4), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'uint64Value', - value: BigInt(2), - }, - }, - }, - }, - }, - { - id: BigInt(5), - keyKind: { - case: 'mapKey', - value: { - id: BigInt(6), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(2), - }, - }, - }, - }, - }, - value: { - id: BigInt(7), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'uint64Value', - value: BigInt(3), - }, - }, - }, - }, - }, - ], - }, - }, + P: structExpr(BigInt(1), { + entries: [ + createStructMapEntry(BigInt(2), { + key: int64Expr(BigInt(3), BigInt(1)), + value: uint64Expr(BigInt(4), BigInt(2)), + }), + createStructMapEntry(BigInt(5), { + key: int64Expr(BigInt(6), BigInt(2)), + value: uint64Expr(BigInt(7), BigInt(3)), + }), + ], }), }, { @@ -3520,54 +1478,18 @@ const testCases: TestInfo[] = [ // single_int32:1^#3:*expr.Constant_Int64Value#^#2:*expr.Expr_CreateStruct_Entry#, // single_int64:2^#5:*expr.Constant_Int64Value#^#4:*expr.Expr_CreateStruct_Entry# // }^#1:*expr.Expr_StructExpr#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'structExpr', - value: { - messageName: 'TestAllTypes', - entries: [ - { - id: BigInt(2), - keyKind: { - case: 'fieldKey', - value: 'single_int32', - }, - value: { - id: BigInt(3), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(1), - }, - }, - }, - }, - }, - { - id: BigInt(4), - keyKind: { - case: 'fieldKey', - value: 'single_int64', - }, - value: { - id: BigInt(5), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(2), - }, - }, - }, - }, - }, - ], - }, - }, + P: structExpr(BigInt(1), { + messageName: 'TestAllTypes', + entries: [ + createStructFieldEntry(BigInt(2), { + key: 'single_int32', + value: int64Expr(BigInt(3), BigInt(1)), + }), + createStructFieldEntry(BigInt(4), { + key: 'single_int64', + value: int64Expr(BigInt(5), BigInt(2)), + }), + ], }), }, { @@ -3590,63 +1512,29 @@ const testCases: TestInfo[] = [ // )^#1:*expr.Expr_CallExpr#, // x^#4:*expr.Expr_IdentExpr#.size()^#5:*expr.Expr_CallExpr# // )^#3:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(3), - exprKind: { - case: 'callExpr', - value: { - function: '_==_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'callExpr', - value: { - function: 'size', - args: [ - { - id: BigInt(2), - exprKind: { - case: 'identExpr', - value: { name: 'x' }, - }, - }, - ], - }, - }, - }, - { - id: BigInt(5), - exprKind: { - case: 'callExpr', - value: { - function: 'size', - target: { - id: BigInt(4), - exprKind: { - case: 'identExpr', - value: { name: 'x' }, - }, - }, - args: [], - }, - }, - }, - ], - }, - }, - }), + P: callExpr(BigInt(3), { + function: EQUALS_OPERATOR, + args: [ + callExpr(BigInt(1), { + function: 'size', + args: [identExpr(BigInt(2), { name: 'x' })], + }), + callExpr(BigInt(5), { + function: 'size', + target: identExpr(BigInt(4), { name: 'x' }), + }), + ], + }), + }, + { + I: `1 + $`, + E: `ERROR: :1:5: Syntax error: token recognition error at: '$' + | 1 + $ + | ....^ + ERROR: :1:6: Syntax error: mismatched input '' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} + | 1 + $ + | .....^`, }, - // TODO: errors - // { - // I: `1 + $`, - // E: `ERROR: :1:5: Syntax error: token recognition error at: '$' - // | 1 + $ - // | ....^ - // ERROR: :1:6: Syntax error: mismatched input '' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} - // | 1 + $ - // | .....^`, - // }, { I: `1 + 2 3 +`, @@ -3657,18 +1545,7 @@ const testCases: TestInfo[] = [ { I: `"\\""`, // TODO: revisit this test // P: `"\""^#1:*expr.Constant_StringValue#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'stringValue', - value: '"', - }, - }, - }, - }), + P: stringExpr(BigInt(1), '"'), }, { I: `[1,3,4][0]`, @@ -3680,83 +1557,27 @@ const testCases: TestInfo[] = [ // ]^#1:*expr.Expr_ListExpr#, // 0^#6:*expr.Constant_Int64Value# // )^#5:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(5), - exprKind: { - case: 'callExpr', - value: { - function: '_[_]', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'listExpr', - value: { - elements: [ - { - id: BigInt(2), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(1), - }, - }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(3), - }, - }, - }, - }, - { - id: BigInt(4), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(4), - }, - }, - }, - }, - ], - }, - }, - }, - { - id: BigInt(6), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(0), - }, - }, - }, - }, + P: callExpr(BigInt(5), { + function: INDEX_OPERATOR, + args: [ + listExpr(BigInt(1), { + elements: [ + int64Expr(BigInt(2), BigInt(1)), + int64Expr(BigInt(3), BigInt(3)), + int64Expr(BigInt(4), BigInt(4)), ], - }, - }, + }), + int64Expr(BigInt(6), BigInt(0)), + ], }), }, // TODO: errors - // { - // I: `1.all(2, 3)`, - // E: `ERROR: :1:7: argument must be a simple name - // | 1.all(2, 3) - // | ......^`, - // }, + { + I: `1.all(2, 3)`, + E: `ERROR: :1:7: argument must be a simple name + | 1.all(2, 3) + | ......^`, + }, { I: `x["a"].single_int32 == 23`, // P: `_==_( @@ -3766,67 +1587,21 @@ const testCases: TestInfo[] = [ // )^#2:*expr.Expr_CallExpr#.single_int32^#4:*expr.Expr_SelectExpr#, // 23^#6:*expr.Constant_Int64Value# // )^#5:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(5), - exprKind: { - case: 'callExpr', - value: { - function: '_==_', - args: [ - { - id: BigInt(4), - exprKind: { - case: 'selectExpr', - value: { - operand: { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_[_]', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'x' }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'stringValue', - value: 'a', - }, - }, - }, - }, - ], - }, - }, - }, - field: 'single_int32', - }, - }, - }, - { - id: BigInt(6), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(23), - }, - }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(5), { + function: EQUALS_OPERATOR, + args: [ + selectExpr(BigInt(4), { + operand: callExpr(BigInt(2), { + function: INDEX_OPERATOR, + args: [ + identExpr(BigInt(1), { name: 'x' }), + stringExpr(BigInt(3), 'a'), + ], + }), + field: 'single_int32', + }), + int64Expr(BigInt(6), BigInt(23)), + ], }), }, { @@ -3835,44 +1610,15 @@ const testCases: TestInfo[] = [ // x^#1:*expr.Expr_IdentExpr#.single_nested_message^#2:*expr.Expr_SelectExpr#, // null^#4:*expr.Constant_NullValue# // )^#3:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(3), - exprKind: { - case: 'callExpr', - value: { - function: '_!=_', - args: [ - { - id: BigInt(2), - exprKind: { - case: 'selectExpr', - value: { - operand: { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'x' }, - }, - }, - field: 'single_nested_message', - }, - }, - }, - { - id: BigInt(4), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'nullValue', - value: NullValue.NULL_VALUE, - }, - }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(3), { + function: NOT_EQUALS_OPERATOR, + args: [ + selectExpr(BigInt(2), { + operand: identExpr(BigInt(1), { name: 'x' }), + field: 'single_nested_message', + }), + nullExpr(BigInt(4)), + ], }), }, { @@ -3890,109 +1636,28 @@ const testCases: TestInfo[] = [ // 2^#8:*expr.Constant_Int64Value#, // 3^#9:*expr.Constant_Int64Value# // )^#7:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(7), - exprKind: { - case: 'callExpr', - value: { - function: '_?_:_', + P: callExpr(BigInt(7), { + function: CONDITIONAL_OPERATOR, + args: [ + callExpr(BigInt(6), { + function: LOGICAL_OR_OPERATOR, args: [ - { - id: BigInt(6), - exprKind: { - case: 'callExpr', - value: { - function: '_||_', - args: [ - { - id: BigInt(4), - exprKind: { - case: 'callExpr', - value: { - function: '_&&_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'boolValue', - value: false, - }, - }, - }, - }, - { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '!_', - args: [ - { - id: BigInt(3), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'boolValue', - value: true, - }, - }, - }, - }, - ], - }, - }, - }, - ], - }, - }, - }, - { - id: BigInt(5), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'boolValue', - value: false, - }, - }, - }, - }, - ], - }, - }, - }, - { - id: BigInt(8), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(2), - }, - }, - }, - }, - { - id: BigInt(9), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(3), - }, - }, - }, - }, + callExpr(BigInt(4), { + function: LOGICAL_AND_OPERATOR, + args: [ + boolExpr(BigInt(1), false), + callExpr(BigInt(2), { + function: LOGICAL_NOT_OPERATOR, + args: [boolExpr(BigInt(3), true)], + }), + ], + }), + boolExpr(BigInt(5), false), ], - }, - }, + }), + int64Expr(BigInt(8), BigInt(2)), + int64Expr(BigInt(9), BigInt(3)), + ], }), }, { @@ -4001,40 +1666,12 @@ const testCases: TestInfo[] = [ // b"abc"^#1:*expr.Constant_BytesValue#, // b"def"^#3:*expr.Constant_BytesValue# // )^#2:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_+_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'bytesValue', - value: new TextEncoder().encode('abc'), - }, - }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'bytesValue', - value: new TextEncoder().encode('def'), - }, - }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(2), { + function: ADD_OPERATOR, + args: [ + bytesExpr(BigInt(1), new TextEncoder().encode('abc')), + bytesExpr(BigInt(3), new TextEncoder().encode('def')), + ], }), }, { @@ -4058,207 +1695,62 @@ const testCases: TestInfo[] = [ // 1^#13:*expr.Constant_Int64Value# // )^#12:*expr.Expr_CallExpr# // )^#10:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(10), - exprKind: { - case: 'callExpr', - value: { - function: '_==_', + P: callExpr(BigInt(10), { + function: EQUALS_OPERATOR, + args: [ + callExpr(BigInt(6), { + function: SUBTRACT_OPERATOR, args: [ - { - id: BigInt(6), - exprKind: { - case: 'callExpr', - value: { - function: '_-_', + callExpr(BigInt(2), { + function: ADD_OPERATOR, + args: [ + int64Expr(BigInt(1), BigInt(1)), + callExpr(BigInt(4), { + function: MULTIPLY_OPERATOR, args: [ - { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_+_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(1), - }, - }, - }, - }, - { - id: BigInt(4), - exprKind: { - case: 'callExpr', - value: { - function: '_*_', - args: [ - { - id: BigInt(3), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(2), - }, - }, - }, - }, - { - id: BigInt(5), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(3), - }, - }, - }, - }, - ], - }, - }, - }, - ], - }, - }, - }, - { - id: BigInt(8), - exprKind: { - case: 'callExpr', - value: { - function: '_/_', - args: [ - { - id: BigInt(7), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(1), - }, - }, - }, - }, - { - id: BigInt(9), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(2), - }, - }, - }, - }, - ], - }, - }, - }, + int64Expr(BigInt(3), BigInt(2)), + int64Expr(BigInt(5), BigInt(3)), ], - }, - }, - }, - { - id: BigInt(12), - exprKind: { - case: 'callExpr', - value: { - function: '_%_', - args: [ - { - id: BigInt(11), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(6), - }, - }, - }, - }, - { - id: BigInt(13), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'int64Value', - value: BigInt(1), - }, - }, - }, - }, - ], - }, - }, - }, + }), + ], + }), + callExpr(BigInt(8), { + function: DIVIDE_OPERATOR, + args: [ + int64Expr(BigInt(7), BigInt(1)), + int64Expr(BigInt(9), BigInt(2)), + ], + }), + ], + }), + callExpr(BigInt(12), { + function: MODULO_OPERATOR, + args: [ + int64Expr(BigInt(11), BigInt(6)), + int64Expr(BigInt(13), BigInt(1)), ], - }, - }, + }), + ], }), }, - // TODO: errors - // { - // I: `1 + +`, - // E: `ERROR: :1:5: Syntax error: mismatched input '+' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} - // | 1 + + - // | ....^ - // ERROR: :1:6: Syntax error: mismatched input '' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} - // | 1 + + - // | .....^`, - // }, + { + I: `1 + +`, + E: `ERROR: :1:5: Syntax error: mismatched input '+' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} + | 1 + + + | ....^ + ERROR: :1:6: Syntax error: mismatched input '' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER} + | 1 + + + | .....^`, + }, { I: `"abc" + "def"`, // P: `_+_( // "abc"^#1:*expr.Constant_StringValue#, // "def"^#3:*expr.Constant_StringValue# // )^#2:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '_+_', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'stringValue', - value: 'abc', - }, - }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'stringValue', - value: 'def', - }, - }, - }, - }, - ], - }, - }, + P: callExpr(BigInt(2), { + function: ADD_OPERATOR, + args: [stringExpr(BigInt(1), 'abc'), stringExpr(BigInt(3), 'def')], }), }, { @@ -4291,18 +1783,7 @@ const testCases: TestInfo[] = [ { I: `"hi\u263A \u263Athere"`, // P: `"hi☺ ☺there"^#1:*expr.Constant_StringValue#`, - P: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'stringValue', - value: 'hi☺ ☺there', - }, - }, - }, - }), + P: stringExpr(BigInt(1), 'hi☺ ☺there'), }, // { // I: `"\U000003A8\?"`, // TODO: it parses this wrong @@ -4370,74 +1851,18 @@ const testCases: TestInfo[] = [ // "😦"^#6:*expr.Constant_StringValue# // ]^#3:*expr.Expr_ListExpr# // )^#2:*expr.Expr_CallExpr#`, - P: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'callExpr', - value: { - function: '@in', - args: [ - { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'stringValue', - value: '😁', - }, - }, - }, - }, - { - id: BigInt(3), - exprKind: { - case: 'listExpr', - value: { - elements: [ - { - id: BigInt(4), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'stringValue', - value: '😁', - }, - }, - }, - }, - { - id: BigInt(5), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'stringValue', - value: '😑', - }, - }, - }, - }, - { - id: BigInt(6), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'stringValue', - value: '😦', - }, - }, - }, - }, - ], - }, - }, - }, + P: callExpr(BigInt(2), { + function: IN_OPERATOR, + args: [ + stringExpr(BigInt(1), '😁'), + listExpr(BigInt(3), { + elements: [ + stringExpr(BigInt(4), '😁'), + stringExpr(BigInt(5), '😑'), + stringExpr(BigInt(6), '😦'), ], - }, - }, + }), + ], }), }, // { // TODO: the error message points at the wrong characters @@ -4621,7 +2046,7 @@ const testCases: TestInfo[] = [ | ind[a{b}] | .......^`, }, - // TODO: something is weird with these ones: + // TODO: something is weird with these ones: TypeError: Cannot read properties of null (reading 'accept') // { // I: `--`, // E: `ERROR: :1:3: Syntax error: no viable alternative at input '-' @@ -5063,13 +2488,177 @@ const testCases: TestInfo[] = [ | a.?b && a[?b] | .........^`, }, + { + I: `a.?b[?0] && a[?c]`, + Opts: { enableOptionalSyntax: true }, + // P: `_&&_( + // _[?_]( + // _?._( + // a^#1:*expr.Expr_IdentExpr#, + // "b"^#2:*expr.Constant_StringValue# + // )^#3:*expr.Expr_CallExpr#, + // 0^#5:*expr.Constant_Int64Value# + // )^#4:*expr.Expr_CallExpr#, + // _[?_]( + // a^#6:*expr.Expr_IdentExpr#, + // c^#8:*expr.Expr_IdentExpr# + // )^#7:*expr.Expr_CallExpr# + // )^#9:*expr.Expr_CallExpr#`, + P: callExpr(BigInt(9), { + function: LOGICAL_AND_OPERATOR, + args: [ + callExpr(BigInt(4), { + function: OPT_INDEX_OPERATOR, + args: [ + callExpr(BigInt(3), { + function: OPT_SELECT_OPERATOR, + args: [ + identExpr(BigInt(1), { name: 'a' }), + stringExpr(BigInt(2), 'b'), + ], + }), + int64Expr(BigInt(5), BigInt(0)), + ], + }), + callExpr(BigInt(7), { + function: OPT_INDEX_OPERATOR, + args: [ + identExpr(BigInt(6), { name: 'a' }), + identExpr(BigInt(8), { name: 'c' }), + ], + }), + ], + }), + }, + { + I: `[?a, ?b]`, + Opts: { enableOptionalSyntax: true }, + // P: `[ + // a^#2:*expr.Expr_IdentExpr#, + // b^#3:*expr.Expr_IdentExpr# + // ]^#1:*expr.Expr_ListExpr#`, + P: listExpr(BigInt(1), { + elements: [ + identExpr(BigInt(2), { name: 'a' }), + identExpr(BigInt(3), { name: 'b' }), + ], + optionalIndices: [0, 1], + }), + }, + { + I: `[?a[?b]]`, + Opts: { enableOptionalSyntax: true }, + // P: `[ + // _[?_]( + // a^#2:*expr.Expr_IdentExpr#, + // b^#4:*expr.Expr_IdentExpr# + // )^#3:*expr.Expr_CallExpr# + // ]^#1:*expr.Expr_ListExpr#`, + P: listExpr(BigInt(1), { + elements: [ + callExpr(BigInt(3), { + function: OPT_INDEX_OPERATOR, + args: [ + identExpr(BigInt(2), { name: 'a' }), + identExpr(BigInt(4), { name: 'b' }), + ], + }), + ], + optionalIndices: [0], + }), + }, + { + I: `[?a, ?b]`, + E: `ERROR: :1:2: unsupported syntax '?' + | [?a, ?b] + | .^ + ERROR: :1:6: unsupported syntax '?' + | [?a, ?b] + | .....^`, + }, + { + I: `Msg{?field: value}`, + Opts: { enableOptionalSyntax: true }, + // P: `Msg{ + // ?field:value^#3:*expr.Expr_IdentExpr#^#2:*expr.Expr_CreateStruct_Entry# + // }^#1:*expr.Expr_StructExpr#`, + P: structExpr(BigInt(1), { + messageName: 'Msg', + entries: [ + createStructFieldEntry(BigInt(2), { + key: 'field', + value: identExpr(BigInt(3), { name: 'value' }), + optionalEntry: true, + }), + ], + }), + }, + { + I: `Msg{?field: value} && {?'key': value}`, + E: `ERROR: :1:5: unsupported syntax '?' + | Msg{?field: value} && {?'key': value} + | ....^ + ERROR: :1:24: unsupported syntax '?' + | Msg{?field: value} && {?'key': value} + | .......................^`, + }, + // { // TODO + // I: `noop_macro(123)`, + // Opts: []Option{ + // Macros(NewGlobalVarArgMacro("noop_macro", + // func(eh ExprHelper, target ast.Expr, args []ast.Expr) (ast.Expr, *common.Error) { + // return nil, nil + // })), + // }, + // P: `noop_macro( + // 123^#2:*expr.Constant_Int64Value# + // )^#1:*expr.Expr_CallExpr#`, + // }, + // { // TODO + // I: `x{?.`, + // Opts: []Option{ + // ErrorRecoveryLookaheadTokenLimit(10), + // ErrorRecoveryLimit(10), + // }, + // E: ` + // ERROR: :1:3: unsupported syntax '?' + // | x{?. + // | ..^ + // ERROR: :1:4: Syntax error: mismatched input '.' expecting IDENTIFIER + // | x{?. + // | ...^`, + // }, + { + I: `x{.`, + E: `ERROR: :1:3: Syntax error: mismatched input '.' expecting {'}', ',', '?', IDENTIFIER} + | x{. + | ..^`, + }, + // { // TODO + // I: `'3# < 10" '& tru ^^`, + // Opts: []Option{ErrorReportingLimit(2)}, + // E: ` + // ERROR: :1:12: Syntax error: token recognition error at: '& ' + // | '3# < 10" '& tru ^^ + // | ...........^ + // ERROR: :1:18: Syntax error: token recognition error at: '^' + // | '3# < 10" '& tru ^^ + // | .................^ + // ERROR: :1:19: Syntax error: More than 2 syntax errors + // | '3# < 10" '& tru ^^ + // | ..................^ + // `, + // }, ]; describe('CELVisitor', () => { for (const testCase of testCases) { it(`should parse ${testCase.I}`, () => { // Arrange - const parser = new CELParser(testCase.I, { maxRecursionDepth: 32 }); + const parser = new CELParser( + testCase.I, + testCase.Opts ?? { maxRecursionDepth: 32 } + ); // Act const expr = parser.parse(); @@ -5077,9 +2666,22 @@ describe('CELVisitor', () => { // Assert if (testCase.P) { expect(expr.expr).toEqual(testCase.P); - } else if (testCase.M) { + } + if (testCase.L) { + const positions = expr.sourceInfo?.positions; + if (isNil(positions)) { + throw new Error(`Invalid test case: ${testCase.I}`); + } + const output: Record = {}; + for (const key of Object.keys(positions)) { + output[key] = parser.getLocationForId(key); + } + expect(output).toEqual(testCase.L); + } + if (testCase.M) { expect(expr.expr).toEqual(testCase.M); - } else if (testCase.E) { + } + if (testCase.E) { expect(parser.errors.toDisplayString()).toEqual( // Account for the difference in spacing between the test case and // the error message @@ -5087,8 +2689,6 @@ describe('CELVisitor', () => { .map((line) => line.trim()) .join('\n ') ); - } else { - throw new Error('Invalid test case'); } }); } diff --git a/packages/cel/src/lib/parser.ts b/packages/cel/src/lib/parser.ts index 98863d7..9cea32e 100644 --- a/packages/cel/src/lib/parser.ts +++ b/packages/cel/src/lib/parser.ts @@ -5,11 +5,9 @@ import { ExprSchema, Expr_CreateStruct, Expr_CreateStruct_Entry, - Expr_CreateStruct_EntrySchema, ParsedExprSchema, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; import { create } from '@bufbuild/protobuf'; -import { NullValue } from '@bufbuild/protobuf/wkt'; import { CharStream, CommonTokenStream, @@ -65,7 +63,7 @@ import { } from './gen/CELParser'; import { default as GeneratedCelVisitor } from './gen/CELVisitor'; import { LogicManager } from './logic-manager'; -import { expandMacro, findMacro } from './macros'; +import { MacroError, expandMacro, findMacro } from './macros'; import { CONDITIONAL_OPERATOR, INDEX_OPERATOR, @@ -78,7 +76,26 @@ import { getOperatorFromText, } from './operators'; import { ParserHelper } from './parser-helper'; -import { Location } from './types'; +import { Location, OffsetRange } from './types'; +import { + boolExpr, + callExpr, + constExpr, + createStructFieldEntry, + createStructMapEntry, + identExpr, + listExpr, + nullExpr, + selectExpr, + stringExpr, + structExpr, +} from './utils'; + +export interface CELParserOptions { + enableOptionalSyntax?: boolean; + retainRepeatedUnaryOperators?: boolean; + maxRecursionDepth?: number; +} export class CELParser extends GeneratedCelVisitor { readonly #helper!: ParserHelper; @@ -88,11 +105,7 @@ export class CELParser extends GeneratedCelVisitor { constructor( public readonly source: string, - private readonly options?: { - enableOptionalSyntax?: boolean; - retainRepeatedUnaryOperators?: boolean; - maxRecursionDepth?: number; - } + private readonly options?: CELParserOptions ) { super(); this.#helper = new ParserHelper(source); @@ -268,40 +281,21 @@ export class CELParser extends GeneratedCelVisitor { if (!this.options?.enableOptionalSyntax) { return this._reportError(ctx._op, "unsupported syntax '.?'"); } + const constant = stringExpr(this.#helper.nextId(ctx._id), id); return create(ExprSchema, { id: this.#helper.nextId(ctx._op), exprKind: { case: 'callExpr', value: { function: OPT_SELECT_OPERATOR, - args: [ - operand, - { - id: this.#helper.nextId(ctx._id), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'stringValue', - value: id, - }, - }, - }, - }, - ], + args: [operand, constant], }, }, }); } - return create(ExprSchema, { - id: this.#helper.nextId(ctx._op), - exprKind: { - case: 'selectExpr', - value: { - operand, - field: id, - }, - }, + return selectExpr(this.#helper.nextId(ctx._op), { + operand, + field: id, }); }; @@ -347,15 +341,7 @@ export class CELParser extends GeneratedCelVisitor { } return this._globalCallOrMacro(ctx, opId, identName, args); } - return create(ExprSchema, { - id: this.#helper.nextId(ctx._id), - exprKind: { - case: 'identExpr', - value: { - name: identName, - }, - }, - }); + return identExpr(this.#helper.nextId(ctx._id), { name: identName }); }; // override visitNested = (ctx: NestedContext): Expr => { @@ -375,15 +361,9 @@ export class CELParser extends GeneratedCelVisitor { elements = listInit.exprKind.value.elements; optionalIndices = listInit.exprKind.value.optionalIndices; } - return create(ExprSchema, { - id: listId, - exprKind: { - case: 'listExpr', - value: { - elements, - optionalIndices, - }, - }, + return listExpr(listId, { + elements, + optionalIndices, }); }; @@ -398,15 +378,7 @@ export class CELParser extends GeneratedCelVisitor { } entries = mapInit.exprKind.value.entries; } - return create(ExprSchema, { - id: structId, - exprKind: { - case: 'structExpr', - value: { - entries, - }, - }, - }); + return structExpr(structId, { entries }); }; override visitCreateMessage = (ctx: CreateMessageContext): Expr => { @@ -432,16 +404,7 @@ export class CELParser extends GeneratedCelVisitor { } entries = entriesInitializer.entries; } - return create(ExprSchema, { - id, - exprKind: { - case: 'structExpr', - value: { - messageName, - entries, - }, - }, - }); + return structExpr(id, { messageName, entries }); }; override visitConstantLiteral = (ctx: ConstantLiteralContext): Expr => { @@ -450,24 +413,12 @@ export class CELParser extends GeneratedCelVisitor { // This should never happen, but just in case. return this._reportError(ctx, 'expr is not a constant'); } - return create(ExprSchema, { - id: this.#helper.nextId(ctx), - exprKind: { - case: 'constExpr', - value: expr.exprKind.value, - }, - }); + return constExpr(this.#helper.nextId(ctx), expr.exprKind.value); }; override visitExprList = (ctx: ExprListContext): Expr => { - return create(ExprSchema, { - id: this.#helper.nextId(ctx), - exprKind: { - case: 'listExpr', - value: { - elements: this.visitSlice(ctx.expr_list()), - }, - }, + return listExpr(this.#helper.nextId(ctx), { + elements: this.visitSlice(ctx.expr_list()), }); }; @@ -478,15 +429,7 @@ export class CELParser extends GeneratedCelVisitor { for (let i = 0; i < elements.length; i++) { const ex = this.visit(elements[i]._e); if (isNil(ex)) { - return create(ExprSchema, { - exprKind: { - case: 'listExpr', - value: { - elements: [], - optionalIndices: [], - }, - }, - }); + return listExpr(BigInt(0), {}); } result.push(ex); if (elements[i]._opt != null) { @@ -497,14 +440,9 @@ export class CELParser extends GeneratedCelVisitor { optionals.push(i); } } - return create(ExprSchema, { - exprKind: { - case: 'listExpr', - value: { - elements: result, - optionalIndices: optionals, - }, - }, + return listExpr(BigInt(0), { + elements: result, + optionalIndices: optionals, }); }; @@ -520,31 +458,23 @@ export class CELParser extends GeneratedCelVisitor { const field = ctx._fields[i]; const exprId = this.#helper.nextId(ctx._cols[i]); const optionalEntry = !isNil(field._opt); + if (optionalEntry && !this.options?.enableOptionalSyntax) { + this._reportError(field, "unsupported syntax '?'"); + continue; + } const id = field.IDENTIFIER(); if (isNil(id)) { return this._reportError(ctx, 'no valid identifier specified'); } fields.push( - create(Expr_CreateStruct_EntrySchema, { - id: exprId, - keyKind: { - case: 'fieldKey', - value: id.getText(), - }, + createStructFieldEntry(exprId, { + key: id.getText(), value: this.visit(ctx._values[i]), optionalEntry, }) ); } - return create(ExprSchema, { - id: this.#helper.nextId(ctx), - exprKind: { - case: 'structExpr', - value: { - entries: fields, - }, - }, - }); + return structExpr(this.#helper.nextId(ctx), { entries: fields }); }; // override visitOptField = (ctx: OptFieldContext): Expr => { @@ -560,30 +490,22 @@ export class CELParser extends GeneratedCelVisitor { } const colId = this.#helper.nextId(ctx._cols[i]); const optKey = ctx._keys[i]; - const optionalKey = !isNil(optKey._opt); + const optionalEntry = !isNil(optKey._opt); + if (optionalEntry && !this.options?.enableOptionalSyntax) { + this._reportError(optKey, "unsupported syntax '?'"); + continue; + } const key = this.visit(optKey._e); const value = this.visit(ctx._values[i]); fields.push( - create(Expr_CreateStruct_EntrySchema, { - id: colId, - keyKind: { - case: 'mapKey', - value: key, - }, + createStructMapEntry(colId, { + key, value, - optionalEntry: optionalKey, + optionalEntry, }) ); } - return create(ExprSchema, { - id: this.#helper.nextId(ctx), - exprKind: { - case: 'structExpr', - value: { - entries: fields, - }, - }, - }); + return structExpr(this.#helper.nextId(ctx), { entries: fields }); }; // override visitOptExpr = (ctx: OptExprContext): Expr => { @@ -592,110 +514,42 @@ export class CELParser extends GeneratedCelVisitor { override visitInt = (ctx: IntContext): Expr => { const constant = parseIntConstant(ctx.getText()); - // TODO: parse error handling - return create(ExprSchema, { - id: this.#helper.nextId(ctx), - exprKind: { - case: 'constExpr', - value: constant, - }, - }); + return constExpr(this.#helper.nextId(ctx), constant); }; override visitUint = (ctx: UintContext): Expr => { const constant = parseUintConstant(ctx.getText()); - // TODO: parse error handling - return create(ExprSchema, { - id: this.#helper.nextId(ctx), - exprKind: { - case: 'constExpr', - value: constant, - }, - }); + return constExpr(this.#helper.nextId(ctx), constant); }; override visitDouble = (ctx: DoubleContext): Expr => { const constant = parseDoubleConstant(ctx.getText()); - // TODO: parse error handling - return create(ExprSchema, { - id: this.#helper.nextId(ctx), - exprKind: { - case: 'constExpr', - value: constant, - }, - }); + return constExpr(this.#helper.nextId(ctx), constant); }; override visitString = (ctx: StringContext): Expr => { const constant = parseStringConstant(ctx.getText()); - // TODO: parse error handling - return create(ExprSchema, { - id: this.#helper.nextId(ctx), - exprKind: { - case: 'constExpr', - value: constant, - }, - }); + return constExpr(this.#helper.nextId(ctx), constant); }; override visitBytes = (ctx: BytesContext): Expr => { const constant = parseBytesConstant(ctx.getText()); - // TODO: parse error handling - return create(ExprSchema, { - id: this.#helper.nextId(ctx), - exprKind: { - case: 'constExpr', - value: constant, - }, - }); + return constExpr(this.#helper.nextId(ctx), constant); }; override visitBoolTrue = (ctx: BoolTrueContext): Expr => { assert(ctx.getText() === 'true', new ParseException('true expected', 0)); - return create(ExprSchema, { - id: this.#helper.nextId(ctx), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'boolValue', - value: true, - }, - }, - }, - }); + return boolExpr(this.#helper.nextId(ctx), true); }; override visitBoolFalse = (ctx: BoolFalseContext): Expr => { assert(ctx.getText() === 'false', new ParseException('false expected', 0)); - return create(ExprSchema, { - id: this.#helper.nextId(ctx), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'boolValue', - value: false, - }, - }, - }, - }); + return boolExpr(this.#helper.nextId(ctx), false); }; override visitNull = (ctx: NullContext): Expr => { assert(ctx.getText() === 'null', new ParseException('null expected', 0)); - return create(ExprSchema, { - id: this.#helper.nextId(ctx), - exprKind: { - case: 'constExpr', - value: { - constantKind: { - case: 'nullValue', - value: NullValue.NULL_VALUE, - }, - }, - }, - }); + return nullExpr(this.#helper.nextId(ctx)); }; visitSlice = (expressions: ExprContext[]): Expr[] => { @@ -705,6 +559,11 @@ export class CELParser extends GeneratedCelVisitor { return expressions.map((e) => this.visit(e)); }; + public getLocationForId(id: string): Location { + const offset = this.#helper.sourceInfo.positions[id]; + return this.#helper.getLocationByOffset(offset); + } + private _unnest(tree: ParseTree) { while (tree != null) { if (tree instanceof ExprContext) { @@ -774,16 +633,7 @@ export class CELParser extends GeneratedCelVisitor { if (!isNil(macro)) { return macro; } - return create(ExprSchema, { - id: exprId, - exprKind: { - case: 'callExpr', - value: { - function: fn, - args, - }, - }, - }); + return callExpr(exprId, { function: fn, args }); } private _receiverCallOrMacro( @@ -797,17 +647,7 @@ export class CELParser extends GeneratedCelVisitor { if (!isNil(macro)) { return macro; } - return create(ExprSchema, { - id: exprId, - exprKind: { - case: 'callExpr', - value: { - function: fn, - args, - target, - }, - }, - }); + return callExpr(exprId, { function: fn, args, target }); } private _expandMacro( @@ -821,14 +661,26 @@ export class CELParser extends GeneratedCelVisitor { return null; } try { - const expanded = expandMacro(this.#helper, macro, target, args); + const expanded = expandMacro(ctx, this.#helper, macro, target, args); return expanded; } catch (e) { + // A MacroError has additional data that can be used to provide a better + // error message. + if (e instanceof MacroError) { + if (!isNil(e.expr)) { + const location = this.getLocationForId(e.expr.id.toString()); + return this._reportError(location, e.message); + } + return this._reportError(e.ctx ?? ctx, e.message); + } return this._reportError(ctx, (e as Error).message); } } - private _reportError(ctx: ParserRuleContext | Token, message: string) { + private _reportError( + ctx: ParserRuleContext | Token | Location | OffsetRange, + message: string + ) { const error = create(ExprSchema, { id: this.#helper.nextId(ctx), exprKind: { @@ -846,6 +698,8 @@ export class CELParser extends GeneratedCelVisitor { location = { line: ctx.start.line, column: ctx.start.column }; } else if (ctx instanceof Token) { location = { line: ctx.line, column: ctx.column }; + } else if ('line' in ctx && 'column' in ctx) { + location = ctx; } else { location = { line: -1, column: -1 }; } diff --git a/packages/cel/src/lib/utils.spec.ts b/packages/cel/src/lib/utils.spec.ts new file mode 100644 index 0000000..39b5064 --- /dev/null +++ b/packages/cel/src/lib/utils.spec.ts @@ -0,0 +1,745 @@ +import { + ConstantSchema, + ExprSchema, + Expr_CreateStruct_EntrySchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { NullValue } from '@bufbuild/protobuf/wkt'; +import { + NULL_CONSTANT, + NULL_VALUE, + boolConstant, + boolExpr, + boolValue, + bytesConstant, + bytesExpr, + bytesValue, + callExpr, + comprehensionExpr, + constExpr, + createStructEntry, + createStructFieldEntry, + createStructMapEntry, + doubleConstant, + doubleExpr, + doubleValue, + extractIdent, + identExpr, + int64Constant, + int64Expr, + int64Value, + listExpr, + nullExpr, + selectExpr, + stringConstant, + stringExpr, + stringValue, + structExpr, + uint64Constant, + uint64Expr, + uint64Value, + unquote, +} from './utils'; + +describe('utils', () => { + it('constExpr', () => { + expect( + constExpr(BigInt(1), { + constantKind: { + case: 'boolValue', + value: true, + }, + }) + ).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'boolValue', + value: true, + }, + }), + }, + }) + ); + }); + + it('boolConstant', () => { + expect(boolConstant(true)).toEqual( + create(ConstantSchema, { + constantKind: { + case: 'boolValue', + value: true, + }, + }) + ); + }); + + it('boolExpr', () => { + expect(boolExpr(BigInt(1), true)).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'boolValue', + value: true, + }, + }), + }, + }) + ); + }); + + it('boolValue', () => { + expect(boolValue(true)).toEqual( + create(ValueSchema, { + kind: { + case: 'boolValue', + value: true, + }, + }) + ); + }); + + it('int64Constant', () => { + expect(int64Constant(BigInt(1))).toEqual( + create(ConstantSchema, { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }) + ); + }); + + it('int64Expr', () => { + expect(int64Expr(BigInt(1), BigInt(1))).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }), + }, + }) + ); + }); + + it('int64Value', () => { + expect(int64Value(BigInt(1))).toEqual( + create(ValueSchema, { + kind: { + case: 'int64Value', + value: BigInt(1), + }, + }) + ); + }); + + it('uint64Constant', () => { + expect(uint64Constant(BigInt(1))).toEqual( + create(ConstantSchema, { + constantKind: { + case: 'uint64Value', + value: BigInt(1), + }, + }) + ); + }); + + it('uint64Expr', () => { + expect(uint64Expr(BigInt(1), BigInt(1))).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'uint64Value', + value: BigInt(1), + }, + }), + }, + }) + ); + }); + + it('uint64Value', () => { + expect(uint64Value(BigInt(1))).toEqual( + create(ValueSchema, { + kind: { + case: 'uint64Value', + value: BigInt(1), + }, + }) + ); + }); + + it('doubleConstant', () => { + expect(doubleConstant(1.1)).toEqual( + create(ConstantSchema, { + constantKind: { + case: 'doubleValue', + value: 1.1, + }, + }) + ); + }); + + it('doubleExpr', () => { + expect(doubleExpr(BigInt(1), 1.1)).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'doubleValue', + value: 1.1, + }, + }), + }, + }) + ); + }); + + it('doubleValue', () => { + expect(doubleValue(1.1)).toEqual( + create(ValueSchema, { + kind: { + case: 'doubleValue', + value: 1.1, + }, + }) + ); + }); + + it('stringConstant', () => { + expect(stringConstant('hello')).toEqual( + create(ConstantSchema, { + constantKind: { + case: 'stringValue', + value: 'hello', + }, + }) + ); + }); + + it('stringExpr', () => { + expect(stringExpr(BigInt(1), 'hello')).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'stringValue', + value: 'hello', + }, + }), + }, + }) + ); + }); + + it('stringValue', () => { + expect(stringValue('hello')).toEqual( + create(ValueSchema, { + kind: { + case: 'stringValue', + value: 'hello', + }, + }) + ); + }); + + it('bytesConstant', () => { + expect(bytesConstant(new Uint8Array([1, 2, 3]))).toEqual( + create(ConstantSchema, { + constantKind: { + case: 'bytesValue', + value: new Uint8Array([1, 2, 3]), + }, + }) + ); + }); + + it('bytesExpr', () => { + expect(bytesExpr(BigInt(1), new Uint8Array([1, 2, 3]))).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'bytesValue', + value: new Uint8Array([1, 2, 3]), + }, + }), + }, + }) + ); + }); + + it('bytesValue', () => { + expect(bytesValue(new Uint8Array([1, 2, 3]))).toEqual( + create(ValueSchema, { + kind: { + case: 'bytesValue', + value: new Uint8Array([1, 2, 3]), + }, + }) + ); + }); + + it('NULL_CONSTANT', () => { + expect(NULL_CONSTANT).toEqual( + create(ConstantSchema, { + constantKind: { + case: 'nullValue', + value: NullValue.NULL_VALUE, + }, + }) + ); + }); + + it('nullExpr', () => { + expect(nullExpr(BigInt(1))).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: NULL_CONSTANT, + }, + }) + ); + }); + + it('NULL_VALUE', () => { + expect(NULL_VALUE).toEqual( + create(ValueSchema, { + kind: { + case: 'nullValue', + value: NullValue.NULL_VALUE, + }, + }) + ); + }); + + it('identExpr', () => { + expect(identExpr(BigInt(1), { name: 'a' })).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }) + ); + }); + + it('callExpr', () => { + expect( + callExpr(BigInt(1), { + function: 'a', + target: identExpr(BigInt(2), { name: 'b' }), + args: [boolExpr(BigInt(3), true)], + }) + ).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'callExpr', + value: { + function: 'a', + target: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }), + args: [ + create(ExprSchema, { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'boolValue', + value: true, + }, + }), + }, + }), + ], + }, + }, + }) + ); + }); + + it('listExpr', () => { + expect( + listExpr(BigInt(1), { + elements: [int64Expr(BigInt(2), BigInt(1))], + }) + ).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'listExpr', + value: { + elements: [ + create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }), + }, + }), + ], + }, + }, + }) + ); + }); + + it('selectExpr', () => { + expect( + selectExpr(BigInt(1), { + operand: identExpr(BigInt(2), { name: 'a' }), + field: 'b', + testOnly: true, + }) + ).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'selectExpr', + value: { + operand: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }), + field: 'b', + testOnly: true, + }, + }, + }) + ); + }); + + it('structExpr', () => { + expect( + structExpr(BigInt(1), { + entries: [ + { + keyKind: { + case: 'fieldKey', + value: 'a', + }, + value: int64Expr(BigInt(2), BigInt(1)), + }, + ], + }) + ).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'structExpr', + value: { + entries: [ + { + keyKind: { + case: 'fieldKey', + value: 'a', + }, + value: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }), + }, + }), + }, + ], + }, + }, + }) + ); + }); + + it('createStructEntry', () => { + expect( + createStructEntry(BigInt(1), { + keyKind: { + case: 'fieldKey', + value: 'a', + }, + value: int64Expr(BigInt(2), BigInt(1)), + }) + ).toEqual( + create(Expr_CreateStruct_EntrySchema, { + id: BigInt(1), + keyKind: { + case: 'fieldKey', + value: 'a', + }, + value: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }), + }, + }), + }) + ); + }); + + it('createStructFieldEntry', () => { + expect( + createStructFieldEntry(BigInt(1), { + key: 'a', + value: int64Expr(BigInt(2), BigInt(1)), + }) + ).toEqual( + create(Expr_CreateStruct_EntrySchema, { + id: BigInt(1), + keyKind: { + case: 'fieldKey', + value: 'a', + }, + value: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }), + }, + }), + }) + ); + }); + + it('createStructMapEntry', () => { + expect( + createStructMapEntry(BigInt(1), { + key: stringExpr(BigInt(2), 'a'), + value: int64Expr(BigInt(3), BigInt(1)), + }) + ).toEqual( + create(Expr_CreateStruct_EntrySchema, { + id: BigInt(1), + keyKind: { + case: 'mapKey', + value: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'stringValue', + value: 'a', + }, + }), + }, + }), + }, + value: create(ExprSchema, { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }), + }, + }), + }) + ); + }); + + it('compreshensionExpr', () => { + const target = identExpr(BigInt(1), { name: 'a' }); + const accuInit = listExpr(BigInt(2), {}); + const condition = boolExpr(BigInt(3), true); + const stepArg0 = identExpr(BigInt(4), { name: 'b' }); + const stepArg1 = listExpr(BigInt(5), { + elements: [int64Expr(BigInt(6), BigInt(1))], + }); + const step = callExpr(BigInt(7), { + function: 'add', + args: [stepArg0, stepArg1], + }); + const resultArg0 = identExpr(BigInt(8), { name: 'b' }); + const resultArg1 = int64Expr(BigInt(9), BigInt(1)); + const result = callExpr(BigInt(10), { + function: 'equals', + args: [resultArg0, resultArg1], + }); + expect( + comprehensionExpr(BigInt(11), { + iterRange: target, + iterVar: 'a', + accuVar: 'b', + accuInit, + loopCondition: condition, + loopStep: step, + result, + }) + ).toEqual( + create(ExprSchema, { + id: BigInt(11), + exprKind: { + case: 'comprehensionExpr', + value: { + iterRange: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }), + iterVar: 'a', + accuVar: 'b', + accuInit: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'listExpr', + value: {}, + }, + }), + loopCondition: create(ExprSchema, { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'boolValue', + value: true, + }, + }), + }, + }), + loopStep: create(ExprSchema, { + id: BigInt(7), + exprKind: { + case: 'callExpr', + value: { + function: 'add', + args: [ + create(ExprSchema, { + id: BigInt(4), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }), + create(ExprSchema, { + id: BigInt(5), + exprKind: { + case: 'listExpr', + value: { + elements: [ + create(ExprSchema, { + id: BigInt(6), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }), + }, + }), + ], + }, + }, + }), + ], + }, + }, + }), + result: create(ExprSchema, { + id: BigInt(10), + exprKind: { + case: 'callExpr', + value: { + function: 'equals', + args: [ + create(ExprSchema, { + id: BigInt(8), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }), + create(ExprSchema, { + id: BigInt(9), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }), + }, + }), + ], + }, + }, + }), + }, + }, + }) + ); + }); + + it('unquote', () => { + expect(unquote('a')).toEqual('a'); + expect(unquote('"a"')).toEqual('a'); + expect(unquote("'a'")).toEqual('a'); + expect(unquote('`a`')).toEqual('a'); + }); + + it('extractIdent', () => { + expect(extractIdent(identExpr(BigInt(1), { name: 'a' }))).toEqual('a'); + expect(extractIdent(int64Expr(BigInt(1), BigInt(1)))).toEqual(null); + }); +}); diff --git a/packages/cel/src/lib/utils.ts b/packages/cel/src/lib/utils.ts index c717932..56e80fe 100644 --- a/packages/cel/src/lib/utils.ts +++ b/packages/cel/src/lib/utils.ts @@ -2,10 +2,16 @@ import { ConstantSchema, Expr, ExprSchema, + Expr_CallSchema, + Expr_ComprehensionSchema, + Expr_CreateListSchema, + Expr_CreateStructSchema, + Expr_CreateStruct_EntrySchema, Expr_IdentSchema, + Expr_SelectSchema, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; -import { create } from '@bufbuild/protobuf'; +import { MessageInitShape, create } from '@bufbuild/protobuf'; import { NullValue } from '@bufbuild/protobuf/wkt'; export function parseString(str: string) { @@ -43,6 +49,19 @@ export function parseInt64(str: string) { return BigInt(decoded); } +export function constExpr( + id: bigint, + init: MessageInitShape +) { + return create(ExprSchema, { + id, + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, init), + }, + }); +} + export function boolConstant(value: boolean) { return create(ConstantSchema, { constantKind: { @@ -218,13 +237,15 @@ export const NULL_CONSTANT = create(ConstantSchema, { }, }); -export const NULL_EXPR = create(ExprSchema, { - // TODO: id - exprKind: { - case: 'constExpr', - value: NULL_CONSTANT, - }, -}); +export function nullExpr(id: bigint) { + return create(ExprSchema, { + id, + exprKind: { + case: 'constExpr', + value: NULL_CONSTANT, + }, + }); +} export const NULL_VALUE = create(ValueSchema, { kind: { @@ -233,45 +254,132 @@ export const NULL_VALUE = create(ValueSchema, { }, }); -export function identExpr(id: bigint, name: string) { +export function identExpr( + id: bigint, + init: MessageInitShape +) { return create(ExprSchema, { id, exprKind: { case: 'identExpr', - value: create(Expr_IdentSchema, { - name, - }), + value: init, }, }); } -export function globalCall(id: bigint, functionName: string, ...args: Expr[]) { +export function callExpr( + id: bigint, + init: MessageInitShape +) { return create(ExprSchema, { id, exprKind: { case: 'callExpr', - value: { - function: functionName, - args, - }, + value: init, }, }); } -export function listExpr(id: bigint, exprs: Expr[]) { +export function listExpr( + id: bigint, + init: MessageInitShape +) { return create(ExprSchema, { id, exprKind: { case: 'listExpr', - value: { - elements: exprs, - }, + value: init, + }, + }); +} + +export function selectExpr( + id: bigint, + init: MessageInitShape +) { + return create(ExprSchema, { + id, + exprKind: { + case: 'selectExpr', + value: init, + }, + }); +} + +export function structExpr( + id: bigint, + init: MessageInitShape +) { + return create(ExprSchema, { + id, + exprKind: { + case: 'structExpr', + value: init, + }, + }); +} + +export function createStructEntry( + id: bigint, + init: MessageInitShape +) { + return create(Expr_CreateStruct_EntrySchema, { + id, + ...init, + }); +} + +export function createStructFieldEntry( + id: bigint, + init: { + key: string; + value: Expr; + optionalEntry?: boolean; + } +) { + return createStructEntry(id, { + keyKind: { + case: 'fieldKey', + value: init.key, + }, + value: init.value, + optionalEntry: init.optionalEntry ?? false, + }); +} + +export function createStructMapEntry( + id: bigint, + init: { + key: Expr; + value: Expr; + optionalEntry?: boolean; + } +) { + return createStructEntry(id, { + keyKind: { + case: 'mapKey', + value: init.key, + }, + value: init.value, + optionalEntry: init.optionalEntry ?? false, + }); +} + +export function comprehensionExpr( + id: bigint, + init: MessageInitShape +) { + return create(ExprSchema, { + id, + exprKind: { + case: 'comprehensionExpr', + value: init, }, }); } export function unquote(str: string) { - const reg = /['"]/; + const reg = /['"`]/; if (!str) { return ''; } @@ -283,3 +391,10 @@ export function unquote(str: string) { } return str; } + +export function extractIdent(expr: Expr): string | null { + if (expr.exprKind.case !== 'identExpr') { + return null; + } + return expr.exprKind.value.name; +} From 584f410782a7525304fcbccd5cb1589487dacba9 Mon Sep 17 00:00:00 2001 From: jafaircl Date: Sat, 5 Oct 2024 10:18:25 -0400 Subject: [PATCH 14/34] feat(cel): checker initial commit --- packages/cel/src/lib/cel.spec.ts | 7 - packages/cel/src/lib/cel.ts | 10 +- packages/cel/src/lib/checker.spec.ts | 239 +++++++ packages/cel/src/lib/checker.ts | 397 ++++++++++++ packages/cel/src/lib/container.test.ts | 15 + packages/cel/src/lib/container.ts | 114 ++++ packages/cel/src/lib/environment.test.ts | 21 + packages/cel/src/lib/environment.ts | 259 +++++++- packages/cel/src/lib/errors.ts | 44 ++ packages/cel/src/lib/parser-helper.ts | 30 +- packages/cel/src/lib/types.spec.ts | 484 ++++++++++++++ packages/cel/src/lib/types.ts | 787 +++++++++++++++++++++++ packages/cel/src/lib/utils.spec.ts | 71 +- packages/cel/src/lib/utils.ts | 242 ++++++- 14 files changed, 2679 insertions(+), 41 deletions(-) delete mode 100644 packages/cel/src/lib/cel.spec.ts create mode 100644 packages/cel/src/lib/checker.spec.ts create mode 100644 packages/cel/src/lib/checker.ts create mode 100644 packages/cel/src/lib/container.test.ts create mode 100644 packages/cel/src/lib/container.ts create mode 100644 packages/cel/src/lib/environment.test.ts create mode 100644 packages/cel/src/lib/types.spec.ts diff --git a/packages/cel/src/lib/cel.spec.ts b/packages/cel/src/lib/cel.spec.ts deleted file mode 100644 index a7a8efb..0000000 --- a/packages/cel/src/lib/cel.spec.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { cel } from './cel'; - -describe('cel', () => { - it('should work', () => { - expect(cel()).toEqual('cel'); - }); -}); diff --git a/packages/cel/src/lib/cel.ts b/packages/cel/src/lib/cel.ts index 19aae82..13a9e7b 100644 --- a/packages/cel/src/lib/cel.ts +++ b/packages/cel/src/lib/cel.ts @@ -1,3 +1,7 @@ -export function cel(): string { - return 'cel'; -} +export { CELEnvironment } from './environment'; +export { CELProgram } from './program'; +// export { CELInterpreter } from './interpreter'; +export { CELChecker } from './checker'; +export { CELContainer } from './container'; +export { CELParser } from './parser'; +export { exprValueToNative } from './to-native'; diff --git a/packages/cel/src/lib/checker.spec.ts b/packages/cel/src/lib/checker.spec.ts new file mode 100644 index 0000000..65fe217 --- /dev/null +++ b/packages/cel/src/lib/checker.spec.ts @@ -0,0 +1,239 @@ +import { isNil } from '@bearclaw/is'; +import { + Type, + Type_PrimitiveType, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { CELChecker } from './checker'; +import { CELContainer } from './container'; +import { CELEnvironment } from './environment'; +import { CELParser } from './parser'; +import { + DYN_TYPE, + ERROR_TYPE, + NULL_TYPE, + listType, + mapType, + primitiveType, +} from './types'; +import { functionDecl, identDecl } from './utils'; + +interface TestInfo { + // in contains the expression to be parsed. + in: string; + + // out contains the output. + out?: string; + + // outType is the expected type of the expression + outType?: Type; + + // container is the container name to use for test. + container?: string; + + // env is the environment to use for testing. + env?: CELEnvironment; + + // err is the expected error for negative test cases. + err?: string; + + // disableStdEnv indicates whether the standard functions should be disabled. + disableStdEnv?: boolean; + + // opts is the set of checker Option flags to use when type-checking. + // opts []Option +} + +const defaultEnv = new CELEnvironment({ + declarations: [ + functionDecl('"fg_s"', { + overloads: [ + { + overloadId: 'fg_s_0', + resultType: primitiveType(Type_PrimitiveType.STRING), + }, + ], + }), + functionDecl('"ffi_s_s"', { + overloads: [ + { + overloadId: 'fi_s_s_0', + params: [primitiveType(Type_PrimitiveType.STRING)], + resultType: primitiveType(Type_PrimitiveType.STRING), + isInstanceFunction: true, + }, + ], + }), + identDecl('is', { type: primitiveType(Type_PrimitiveType.STRING) }), + identDecl('ii', { type: primitiveType(Type_PrimitiveType.INT64) }), + identDecl('iu', { type: primitiveType(Type_PrimitiveType.UINT64) }), + identDecl('iz', { type: primitiveType(Type_PrimitiveType.BOOL) }), + identDecl('ib', { type: primitiveType(Type_PrimitiveType.BYTES) }), + identDecl('id', { type: primitiveType(Type_PrimitiveType.DOUBLE) }), + identDecl('ix', { type: NULL_TYPE }), + ], +}); + +const testCases: TestInfo[] = [ + // Development tests + { + in: `a.b`, + out: `a.b~bool`, + outType: primitiveType(Type_PrimitiveType.STRING), + env: new CELEnvironment({ + declarations: [ + identDecl('a', { + type: mapType({ + keyType: primitiveType(Type_PrimitiveType.STRING), + valueType: primitiveType(Type_PrimitiveType.STRING), + }), + }), + ], + }), + }, + // Const types + { + in: `"A"`, + out: `"A"~string`, + outType: primitiveType(Type_PrimitiveType.STRING), + }, + { + in: `12`, + out: `12~int`, + outType: primitiveType(Type_PrimitiveType.INT64), + }, + { + in: `12u`, + out: `12u~uint`, + outType: primitiveType(Type_PrimitiveType.UINT64), + }, + { + in: `true`, + out: `true~bool`, + outType: primitiveType(Type_PrimitiveType.BOOL), + }, + { + in: `false`, + out: `false~bool`, + outType: primitiveType(Type_PrimitiveType.BOOL), + }, + { + in: `12.23`, + out: `12.23~double`, + outType: primitiveType(Type_PrimitiveType.DOUBLE), + }, + { + in: `null`, + out: `null~null`, + outType: NULL_TYPE, + }, + { + in: `b"ABC"`, + out: `b"ABC"~bytes`, + outType: primitiveType(Type_PrimitiveType.BYTES), + }, + // Ident types + { + in: `is`, + out: `is~string^is`, + outType: primitiveType(Type_PrimitiveType.STRING), + env: defaultEnv, + }, + { + in: `ii`, + out: `ii~int^ii`, + outType: primitiveType(Type_PrimitiveType.INT64), + env: defaultEnv, + }, + { + in: `iu`, + out: `iu~uint^iu`, + outType: primitiveType(Type_PrimitiveType.UINT64), + env: defaultEnv, + }, + { + in: `iz`, + out: `iz~bool^iz`, + outType: primitiveType(Type_PrimitiveType.BOOL), + env: defaultEnv, + }, + { + in: `id`, + out: `id~double^id`, + outType: primitiveType(Type_PrimitiveType.DOUBLE), + env: defaultEnv, + }, + { + in: `ix`, + out: `ix~null^ix`, + outType: NULL_TYPE, + env: defaultEnv, + }, + { + in: `ib`, + out: `ib~bytes^ib`, + outType: primitiveType(Type_PrimitiveType.BYTES), + env: defaultEnv, + }, + { + in: `id`, + out: `id~double^id`, + outType: primitiveType(Type_PrimitiveType.DOUBLE), + env: defaultEnv, + }, + { + in: `[]`, + out: `[]~list(dyn)`, + outType: listType({ elemType: DYN_TYPE }), + }, + { + in: `[1]`, + out: `[1~int]~list(int)`, + outType: listType({ elemType: primitiveType(Type_PrimitiveType.INT64) }), + }, + { + in: `[1, "A"]`, + out: `[1~int, "A"~string]~list(dyn)`, + outType: listType({ elemType: DYN_TYPE }), + }, + { + in: `foo`, + out: `foo~!error!`, + outType: ERROR_TYPE, + err: `ERROR: :1:1: undeclared reference to 'foo' (in container '') +| foo +| ^`, + }, +]; + +describe('CELChecker', () => { + for (const testCase of testCases) { + it(`should parse ${testCase.in}`, () => { + const env = + testCase.env ?? + new CELEnvironment({ container: new CELContainer(testCase.container) }); + const parser = new CELParser(testCase.in); + const parsed = parser.parse(); + if (isNil(parsed.expr)) { + throw new Error('parsed.expr is nil'); + } + const checker = new CELChecker(parsed, testCase.in, env); + const result = checker.check(); + if (testCase.outType) { + expect(result.typeMap[parsed.expr.id.toString()]).toEqual( + testCase.outType + ); + } + if (testCase.err) { + expect(checker.errors.toDisplayString()).toEqual( + // Account for the difference in spacing between the test case and + // the error message + testCase.err + .trim() + .split('\n') + .map((line) => line.trim()) + .join('\n ') + ); + } + }); + } +}); diff --git a/packages/cel/src/lib/checker.ts b/packages/cel/src/lib/checker.ts new file mode 100644 index 0000000..cb92392 --- /dev/null +++ b/packages/cel/src/lib/checker.ts @@ -0,0 +1,397 @@ +/* eslint-disable no-case-declarations */ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +import { isNil } from '@bearclaw/is'; +import { + CheckedExprSchema, + Reference, + Type, + Type_PrimitiveType, + Type_WellKnownType, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb'; +import { + Expr, + ParsedExpr, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { CELEnvironment } from './environment'; +import { Errors } from './errors'; +import { + DYN_TYPE, + ERROR_TYPE, + NULL_TYPE, + isAssignable, + isDyn, + isDynOrError, + isOptionalType, + listType, + mostGeneral, + optionalType, + primitiveType, + substitute, + typeParamType, + unwrapOptionalType, + wellKnownType, +} from './types'; +import { + extractIdent, + functionReference, + getLocationByOffset, + identReference, + mapToObject, + toQualifiedName, +} from './utils'; + +export class CELChecker { + readonly #errors!: Errors; + readonly #referenceMap = new Map(); + readonly #typeMap = new Map(); + #mapping = new Map(); + #freeTypeVarCounter = 0; + + constructor( + public readonly parsed: ParsedExpr, + public readonly source: string, + public readonly env: CELEnvironment + ) { + this.#errors = new Errors(source); + } + + public get dynAggregateLiteralElementTypesEnabled() { + return this.env.aggLitElemType.typeKind.case === DYN_TYPE.typeKind.case; + } + + public get errors() { + return this.#errors; + } + + check(expr: Expr = this.parsed.expr!) { + if (isNil(expr)) { + throw new Error('expr is nil'); + } + const sourceInfo = this.parsed.sourceInfo; + if (isNil(sourceInfo)) { + throw new Error('ParsedExpr.sourceInfo is nil'); + } + switch (expr.exprKind.case) { + case 'constExpr': + this.setType(expr.id, this.checkConstExpr(expr)); + break; + case 'identExpr': + this.checkIdentExpr(expr); + break; + case 'listExpr': + this.checkListExpr(expr); + break; + case 'selectExpr': + this.checkSelect(expr); + break; + default: + this.#errors.reportUnexpectedAstTypeError( + expr.id, + this.getLocationById(expr.id), + 'unspecified', + expr.exprKind.case ?? '' + ); + } + // Walk over the final type map substituting any type parameters either by + // their bound value or by DYN. + for (const [id, t] of this.#typeMap) { + this.setType(BigInt(id), substitute(this.#mapping, t, true)); + } + return create(CheckedExprSchema, { + expr, + sourceInfo, + referenceMap: mapToObject(this.#referenceMap), + typeMap: mapToObject(this.#typeMap), + }); + } + + checkConstExpr(expr: Expr): Type { + if (expr.exprKind.case !== 'constExpr') { + this.#errors.reportUnexpectedAstTypeError( + expr.id, + this.getLocationById(expr.id), + 'constExpr', + expr.exprKind.case! + ); + return ERROR_TYPE; + } + switch (expr.exprKind.value.constantKind.case) { + case 'boolValue': + return primitiveType(Type_PrimitiveType.BOOL); + case 'bytesValue': + return primitiveType(Type_PrimitiveType.BYTES); + case 'doubleValue': + return primitiveType(Type_PrimitiveType.DOUBLE); + case 'int64Value': + return primitiveType(Type_PrimitiveType.INT64); + case 'nullValue': + return NULL_TYPE; + case 'stringValue': + return primitiveType(Type_PrimitiveType.STRING); + case 'uint64Value': + return primitiveType(Type_PrimitiveType.UINT64); + case 'durationValue': + return wellKnownType(Type_WellKnownType.DURATION); + case 'timestampValue': + return wellKnownType(Type_WellKnownType.TIMESTAMP); + default: + this.#errors.reportUnexpectedAstTypeError( + expr.id, + this.getLocationById(expr.id), + 'constExpr', + expr.exprKind.value.constantKind.case! + ); + return ERROR_TYPE; + } + } + + checkIdentExpr(expr: Expr) { + if (expr.exprKind.case !== 'identExpr') { + // This should never happen + throw new Error('expr.exprKind.case is not identExpr'); + } + const identName = extractIdent(expr); + if (isNil(identName)) { + throw new Error('identName is nil'); + } + const ident = this.env.lookupIdent(identName); + if (!isNil(ident)) { + if (ident.declKind.case !== 'ident') { + // This should never happen + throw new Error('ident.declKind.case is not ident'); + } + this.setType(expr.id, ident.declKind.value.type!); + this.setReference( + expr.id, + identReference(ident.name, ident.declKind.value.value!) + ); + return; + } + this.setType(expr.id, ERROR_TYPE); + this.#errors.reportUndeclaredReference( + expr.id, + this.getLocationById(expr.id), + this.env.container, + identName + ); + } + + checkSelect(expr: Expr) { + if (expr.exprKind.case !== 'selectExpr') { + // This should never happen + throw new Error('expr.exprKind.case is not identExpr'); + } + // Before traversing down the tree, try to interpret as qualified name. + const qname = toQualifiedName(expr); + if (qname !== '') { + const ident = this.env.lookupIdent(qname); + if (!isNil(ident)) { + if (ident.declKind.case !== 'ident') { + // This should never happen + throw new Error('ident.declKind.case is not ident'); + } + this.setType(expr.id, ident.declKind.value.type!); + this.setReference( + expr.id, + identReference(ident.name, ident.declKind.value.value!) + ); + return; + } + } + let resultType = this.checkSelectField( + expr, + expr.exprKind.value.operand!, + expr.exprKind.value.field, + false + ); + if (expr.exprKind.value.testOnly) { + resultType = primitiveType(Type_PrimitiveType.BOOL); + } + this.setType(expr.id, substitute(this.#mapping, resultType, false)); + } + + checkOptSelect(expr: Expr) { + if (expr.exprKind.case !== 'selectExpr') { + // This should never happen + throw new Error('expr.exprKind.case is not identExpr'); + } + // Collect metadata related to the opt select call packaged by the parser. + const operand = expr.exprKind.value.operand!; + const field = expr.exprKind.value.field; + + // Perform type-checking using the field selection logic. + const resultType = this.checkSelectField(expr, operand, field, true); + this.setType(expr.id, substitute(this.#mapping, resultType, false)); + this.setReference(expr.id, functionReference(['select_optional_field'])); + } + + checkSelectField( + expr: Expr, + operand: Expr, + field: string, + optional: boolean + ) { + // Interpret as field selection, first traversing down the operand. + this.check(operand); + const operandType = substitute( + this.#mapping, + this.getType(operand.id)!, + false + ); + + // If the target type is 'optional', unwrap it for the sake of this check. + const targetType = isOptionalType(operandType) + ? unwrapOptionalType(operandType) + : operandType; + if (isNil(targetType)) { + // This should never happen + throw new Error('targetType is nil'); + } + + // Assume error type by default as most types do not support field + // selection. + let resultType = ERROR_TYPE; + switch (targetType.typeKind.case) { + case 'mapType': + // Maps yield their value type as the selection result type. + resultType = targetType.typeKind.value.valueType!; + break; + case 'messageType': + // Objects yield their field type declaration as the selection result + // type, but only if the field is defined. + const fieldType = this.env.lookupFieldType( + targetType.typeKind.value, + field + ); + if (!isNil(fieldType)) { + resultType = fieldType; + break; + } + this.#errors.reportUndefinedField( + expr.id, + this.getLocationById(expr.id), + field + ); + break; + case 'typeParam': + // Set the operand type to DYN to prevent assignment to a potentially + // incorrect type at a later point in type-checking. The isAssignable + // call will update the type substitutions for the type param under the + // covers. + this._isAssignable(DYN_TYPE, targetType); + // Also, set the result type to DYN. + resultType = DYN_TYPE; + break; + default: + if (!isDynOrError(targetType)) { + this.#errors.reportTypeDoesNotSupportFieldSelection( + expr.id, + this.getLocationById(expr.id), + targetType + ); + } + resultType = DYN_TYPE; + } + if (isOptionalType(operandType) || optional) { + return optionalType(resultType); + } + return resultType; + } + + checkListExpr(expr: Expr) { + if (expr.exprKind.case !== 'listExpr') { + // This should never happen + throw new Error('expr.exprKind.case is not identExpr'); + } + const createList = expr.exprKind.value; + let elemsType: Type | undefined = undefined; + const optionals = {} as Record; + for (const optInd of createList.optionalIndices) { + optionals[optInd] = true; + } + for (let i = 0; i < createList.elements.length; i++) { + const e = createList.elements[i]; + this.check(e); + const elemType = this.getType(e.id); + if (isNil(elemType)) { + continue; + } + if (optionals[i]) { + if (!isOptionalType(elemType) && !isDyn(elemType)) { + this.#errors.reportTypeMismatch( + e.id, + this.getLocationById(e.id), + optionalType(elemType), + elemType + ); + } + } + elemsType = this._joinTypes(e, elemsType!, elemType!); + } + if (isNil(elemsType)) { + elemsType = this._newTypeVar(); + } + this.setType(expr.id, listType({ elemType: elemsType })); + } + + setType(id: bigint, type: Type) { + this.#typeMap.set(id.toString(), type); + } + + getType(id: bigint) { + return this.#typeMap.get(id.toString()); + } + + setReference(id: bigint, ref: Reference) { + this.#referenceMap.set(id.toString(), ref); + } + + getReference(id: bigint) { + return this.#referenceMap.get(id.toString()); + } + + getLocationById(id: bigint) { + return getLocationByOffset( + this.parsed.sourceInfo!, + this.parsed.sourceInfo!.positions[id.toString()] + ); + } + + private _joinTypes(expr: Expr, previous: Type, current: Type) { + if (isNil(previous)) { + return current; + } + if (this._isAssignable(previous, current)) { + return mostGeneral(previous, current); + } + if (this.dynAggregateLiteralElementTypesEnabled) { + return DYN_TYPE; + } + this.#errors.reportTypeMismatch( + expr.id, + getLocationByOffset( + this.parsed.sourceInfo!, + this.parsed.sourceInfo!.positions[expr.id.toString()] + ), + previous, + current + ); + return ERROR_TYPE; + } + + private _newTypeVar() { + const id = this.#freeTypeVarCounter; + this.#freeTypeVarCounter++; + return typeParamType(`_var${id}`); + } + + private _isAssignable(t1: Type, t2: Type) { + const subs = isAssignable(this.#mapping, t1, t2); + if (!isNil(subs)) { + this.#mapping = subs; + return true; + } + return false; + } +} diff --git a/packages/cel/src/lib/container.test.ts b/packages/cel/src/lib/container.test.ts new file mode 100644 index 0000000..7f35245 --- /dev/null +++ b/packages/cel/src/lib/container.test.ts @@ -0,0 +1,15 @@ +import { CELContainer } from './container'; + +describe('CELContainer', () => { + it('resolveCandidateNames', () => { + const container = new CELContainer('a.b.c.M.N', new Map()); + expect(container.resolveCandidateNames('R.s')).toEqual([ + 'a.b.c.M.N.R.s', + 'a.b.c.M.R.s', + 'a.b.c.R.s', + 'a.b.R.s', + 'a.R.s', + 'R.s', + ]); + }); +}); diff --git a/packages/cel/src/lib/container.ts b/packages/cel/src/lib/container.ts new file mode 100644 index 0000000..b02d206 --- /dev/null +++ b/packages/cel/src/lib/container.ts @@ -0,0 +1,114 @@ +import { isNil } from '@bearclaw/is'; + +/** + * Holds a reference to an optional qualified container name and set of aliases. + * + * The program container can be used to simplify variable, function, and type + * specification within CEL programs and behaves more or less like a C++ + * namespace. See resolveCandidateNames for more details. + */ +export class CELContainer { + constructor( + public readonly name = '', + public readonly aliases = new Map() + ) {} + + /** + * Extends the current container with another name or additional aliases. + * + * @param name the name of the container + * @param aliases the aliases to add to the container + * @returns a new container with the extended name and aliases + */ + extend(name: string, aliases: Map) { + const newAliases = new Map(this.aliases); + for (const [key, value] of aliases) { + newAliases.set(key, value); + } + return new CELContainer(name, newAliases); + } + + /** + * Returns the candidates name of namespaced identifiers in C++ resolution + * order. + * + * Names which shadow other names are returned first. If a name includes + * leading dot ('.'), the name is treated as an absolute identifier which + * cannot be shadowed. + * + * Given a container name a.b.c.M.N and a type name R.s, this will deliver in + * order: + * + * a.b.c.M.N.R.s + * a.b.c.M.R.s + * a.b.c.R.s + * a.b.R.s + * a.R.s + * R.s + * + * If aliases or abbreviations are configured for the container, then alias + * names will take precedence over containerized names. + * + * @param name the candidate name to resolve + */ + resolveCandidateNames(name: string): string[] { + if (name.startsWith('.')) { + const qn = name.substring(1); + const alias = this.findAlias(qn); + if (!isNil(alias)) { + return [alias]; + } + return [qn]; + } + const alias = this.findAlias(name); + if (alias !== '') { + return [alias]; + } + if (name === '') { + return []; + } + let nextCont = this.name; + const candidates = [`${nextCont}.${name}`]; + for ( + let i = nextCont.lastIndexOf('.'); + i > -1; + i = nextCont.lastIndexOf('.') + ) { + nextCont = nextCont.substring(0, i); + candidates.push(`${nextCont}.${name}`); + } + return [...candidates, name]; + } + + /** + * Takes a name as input and returns an alias expansion if one exists. + * + * If the name is qualified, the first component of the qualified name is + * checked against known aliases. Any alias that is found in a qualified name + * is expanded in the result: + * + * alias: R -> my.alias.R + * name: R.S.T + * output: my.alias.R.S.T + * + * Note, the name must not have a leading dot. + * + * @param name the name to find an alias for + * @returns the alias if one exists, otherwise an empty string + */ + findAlias(name: string) { + // If an alias exists for the name, ensure it is searched last. + let simple = name; + let qualifier = ''; + const dot = name.indexOf('.'); + if (dot > -1) { + simple = name.substring(0, dot); + qualifier = name.substring(dot); + } + const alias = this.aliases.get(simple); + if (isNil(alias)) { + return ''; + } + return alias + qualifier; + } +} diff --git a/packages/cel/src/lib/environment.test.ts b/packages/cel/src/lib/environment.test.ts new file mode 100644 index 0000000..e550b70 --- /dev/null +++ b/packages/cel/src/lib/environment.test.ts @@ -0,0 +1,21 @@ +import { Type_PrimitiveType } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb'; +import { CELEnvironment } from './environment'; +import { primitiveType } from './types'; +import { identDecl } from './utils'; + +describe('CELEnvironment', () => { + it('should create an environment', () => { + const env = new CELEnvironment(); + expect(env).toBeDefined(); + }); + + it('should throw an error when adding an overlapping identifier', () => { + const decl = identDecl('is', { + type: primitiveType(Type_PrimitiveType.STRING), + }); + const env = new CELEnvironment({ declarations: [decl] }); + expect(() => env.addIdent(decl)).toThrowError( + `overlapping identifier for name 'is'` + ); + }); +}); diff --git a/packages/cel/src/lib/environment.ts b/packages/cel/src/lib/environment.ts index a00c061..decb0bf 100644 --- a/packages/cel/src/lib/environment.ts +++ b/packages/cel/src/lib/environment.ts @@ -1,4 +1,8 @@ -import { Decl } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { isNil } from '@bearclaw/is'; +import { + Decl, + Type, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; import { DescEnum, DescExtension, @@ -8,48 +12,287 @@ import { Registry, createMutableRegistry, } from '@bufbuild/protobuf'; +import { CELContainer } from './container'; import { CELParser } from './parser'; +import { DYN_TYPE, messageType } from './types'; +import { getFieldDescriptorType, identDecl } from './utils'; export interface CELEnvironmentOptions { - container?: string; + container?: CELContainer; registry?: MutableRegistry; declarations?: Decl[]; + aggLitElemType?: Type; } export class CELEnvironment { - public readonly container?: string; - public readonly registry: MutableRegistry; - public readonly declarations: Decl[]; + public readonly container: CELContainer = new CELContainer(); + public readonly registry: MutableRegistry = createMutableRegistry(); + public readonly declarations: Decl[] = []; + public readonly aggLitElemType = DYN_TYPE; + readonly #declMap = new Map(); constructor(options?: CELEnvironmentOptions) { - this.container = options?.container; - this.registry = options?.registry ?? createMutableRegistry(); - this.declarations = options?.declarations ?? []; + if (options?.container) { + this.container = options.container; + } + if (options?.registry) { + this.registry = options.registry; + } + if (options?.declarations) { + this.declarations = options.declarations; + this._syncDecls(); + } } compile(input: string): CELParser { return new CELParser(input); } + /** + * Finds the declaration by name in the environment's declarations. + * + * @param name the name of the declaration to look up. + * @returns the declaration, or undefined if not found. + */ + findDeclaration(name: string) { + return this.#declMap.get(name); + } + + /** + * Adds a declaration to the environment. + * + * @param decl the declaration to add to the environment. + */ addDeclaration(decl: Decl) { + const existing = this.findIdent(decl.name); + if (!isNil(existing)) { + switch (decl.declKind.case) { + case 'ident': + throw new Error(`overlapping identifier for name '${decl.name}'`); + case 'function': + throw new Error(`overlapping function for name '${decl.name}'`); + default: + throw new Error(`overlapping declaration for name '${decl.name}'`); + } + } this.declarations.push(decl); + this.#declMap.set(decl.name, decl); } + /** + * Finds the descriptor by name in the environment's registry. + * + * @param name the name of the descriptor to look up. + * @returns the descriptor, or undefined if not found. + */ + findDescriptor(name: string) { + return this.registry.get(name); + } + + /** + * Adds a descriptor to the environment's registry. + * + * @param descriptor the descriptor to add to the environment's registry. + */ addDescriptor( descriptor: DescMessage | DescEnum | DescExtension | DescService ) { + const existing = this.findDescriptor(descriptor.name); + if (!isNil(existing)) { + throw new Error(`overlapping descriptor for name '${descriptor.name}'`); + } this.registry.add(descriptor); } + /** + * Finds the message by name in the environment's registry. + * + * @param name the name of the message to look up. + */ + findMessage(name: string) { + return this.registry.getMessage(name); + } + + /** + * Adds a message descriptor to the environment's registry. + * + * @param descriptor the descriptor to add to the environment's registry. + */ + addMessage(descriptor: DescMessage) { + this.addDescriptor(descriptor); + } + + /** + * Finds the enum by name in the environment's registry. + * + * @param name the name of the enum to look up. + * @returns the enum descriptor, or undefined if not found. + */ + findEnum(name: string) { + return this.registry.getEnum(name); + } + + /** + * Adds an enum descriptor to the environment's registry. + * + * @param descriptor the descriptor to add to the environment's registry. + */ + addEnum(descriptor: DescEnum) { + this.registry.add(descriptor); + } + + /** + * Merge the declarations into the environment's declarations. + * + * @param decls the declarations to merge into the environment's declarations. + */ mergeDeclarations(decls: Decl[]) { for (const decl of decls) { this.addDeclaration(decl); } } + /** + * Merge the registry into the environment's registry. + * + * @param registry the registry to merge into the environment's registry. + */ mergeRegistry(registry: Registry) { for (const descriptor of registry) { this.addDescriptor(descriptor); } } + + /** + * Finds the identifier declaration by name in the environment's registry. + * + * @param name the name of the identifier to look up. + * @returns the identifier declaration, or null if not found. + */ + findIdent(name: string) { + const decl = this.findDeclaration(name); + if (decl?.declKind.case === 'ident') { + return decl; + } + return null; + } + + /** + * Adds an identifier declaration to the environment. + * + * @param decl the identifier declaration to add to the environment. + */ + addIdent(decl: Decl) { + if (decl.declKind.case !== 'ident') { + throw new Error('Expected ident declaration'); + } + this.addDeclaration(decl); + } + + /** + * Finds the Type for a message by name in the environment's registry. + * + * @param name the name of the message type to look up. + * @returns the message type, or null if not found. + */ + findMessageType(name: string) { + const descriptor = this.registry.get(name); + if (!isNil(descriptor)) { + return messageType(name); + } + return null; + } + + findMessageFieldType(message: string, fieldName: string) { + const m = this.findMessage(message); + if (isNil(m)) { + return null; + } + const field = m.fields.find((field) => field.name === fieldName); + if (isNil(field)) { + return null; + } + return getFieldDescriptorType(field); + } + + /** + * Finds the function declaration by name in the environment's declarations. + * + * @param name the name of the function to look up. + * @returns the function declaration, or null if not found. + */ + findFunction(name: string) { + const decl = this.findDeclaration(name); + if (decl?.declKind.case === 'function') { + return decl; + } + return null; + } + + /** + * Adds a function declaration to the environment's declarations. + * + * @param decl the function declaration to add to the environment. + */ + addFunction(decl: Decl) { + if (decl.declKind.case !== 'function') { + throw new Error('Expected function declaration'); + } + const existing = this.findFunction(decl.name); + if (!isNil(existing)) { + throw new Error(`overlapping function for name '${decl.name}'`); + } + this.addDeclaration(decl); + } + + /** + * Returns a Decl proto for typeName as an identifier in the Env. Returns null + * if no such identifier is found in the Env. + * + * @param name the name of the identifier to look up. + * @returns a Decl proto for the identifier, or null if not found. + */ + lookupIdent(name: string): Decl | null { + const candidateNames = this.container.resolveCandidateNames(name); + for (const candidateName of candidateNames) { + const ident = this.findIdent(candidateName); + if (!isNil(ident)) { + return ident; + } + + // Next try to import the name as a reference to a message type. If found, + // the declaration is added to the outest (global) scope of the + // environment, so next time we can access it faster. + const type = this.registry.get(candidateName); + if (!isNil(type)) { + const decl = identDecl(candidateName, { + type: messageType(candidateName), + }); + this.addIdent(decl); + return decl; + } + } + return null; + } + + lookupFieldType(message: string, field: string) { + const candidateNames = this.container.resolveCandidateNames(message); + for (const candidateName of candidateNames) { + const fieldType = this.findMessageFieldType(candidateName, field); + if (!isNil(fieldType)) { + return fieldType; + } + } + return null; + } + + /** + * Syncs the declarations array with the declaration map. + */ + private _syncDecls() { + this.#declMap.clear(); + for (const decl of this.declarations) { + this.#declMap.set(decl.name, decl); + } + } } diff --git a/packages/cel/src/lib/errors.ts b/packages/cel/src/lib/errors.ts index a2c1e73..51654e8 100644 --- a/packages/cel/src/lib/errors.ts +++ b/packages/cel/src/lib/errors.ts @@ -1,4 +1,5 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ +import { Type } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb'; import { ErrorSetSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/eval_pb.js'; import { SourceInfo, @@ -11,6 +12,7 @@ import { import { create, createRegistry } from '@bufbuild/protobuf'; import { anyPack, anyUnpack } from '@bufbuild/protobuf/wkt'; import { ErrorListener, RecognitionException, Recognizer, Token } from 'antlr4'; +import { CELContainer } from './container'; import { Location } from './types'; export class Errors { @@ -73,6 +75,48 @@ export class Errors { ); } + public reportUndeclaredReference( + id: bigint, + location: Location, + container: CELContainer, + name: string + ) { + return this.reportErrorAtId( + id, + location, + `undeclared reference to '${name}' (in container '${container.name}')` + ); + } + + public reportTypeMismatch( + id: bigint, + location: Location, + expected: Type, + actual: Type + ) { + return this.reportErrorAtId( + id, + location, + `expected type ${expected.$typeName} but found ${actual.$typeName}` + ); + } + + public reportTypeDoesNotSupportFieldSelection( + id: bigint, + location: Location, + type: Type + ) { + return this.reportErrorAtId( + id, + location, + `type '${type.typeKind.case}' does not support field selection` + ); + } + + public reportUndefinedField(id: bigint, location: Location, field: string) { + return this.reportErrorAtId(id, location, `undefined field '${field}'`); + } + public toDisplayString() { let hasRecursionError = false; const errors = []; diff --git a/packages/cel/src/lib/parser-helper.ts b/packages/cel/src/lib/parser-helper.ts index 78dbe47..8d1e724 100644 --- a/packages/cel/src/lib/parser-helper.ts +++ b/packages/cel/src/lib/parser-helper.ts @@ -2,6 +2,7 @@ import { SourceInfoSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/synt import { create } from '@bufbuild/protobuf'; import { ParserRuleContext, Token } from 'antlr4'; import { Location, OffsetRange } from './types'; +import { computeOffset, getLocationByOffset } from './utils'; export class ParserHelper { #id = BigInt(1); @@ -55,16 +56,13 @@ export class ParserHelper { * @param column a 0-based column number */ computeOffset(line: number, column: number) { - line = this.#baseLine + line; - column = this.#baseColumn + column; - if (line === 1) { - return column; - } - if (line < 1 || line > this.#sourceInfo.lineOffsets.length) { - return -1; - } - const offset = this.#sourceInfo.lineOffsets[line - 2]; - return offset + column; + return computeOffset( + this.#baseLine, + this.#baseColumn, + this.#sourceInfo, + line, + column + ); } /** @@ -74,17 +72,7 @@ export class ParserHelper { * @returns the line and column information */ getLocationByOffset(offset: number): Location { - let line = 1; - let column = offset; - for (let i = 0; i < this.#sourceInfo.lineOffsets.length; i++) { - const lineOffset = this.#sourceInfo.lineOffsets[i]; - if (lineOffset > offset) { - break; - } - line++; - column = offset - lineOffset; - } - return { line, column }; + return getLocationByOffset(this.#sourceInfo, offset); } /** diff --git a/packages/cel/src/lib/types.spec.ts b/packages/cel/src/lib/types.spec.ts new file mode 100644 index 0000000..902aca0 --- /dev/null +++ b/packages/cel/src/lib/types.spec.ts @@ -0,0 +1,484 @@ +import { + TypeSchema, + Type_PrimitiveType, + Type_WellKnownType, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { EmptySchema, NullValue } from '@bufbuild/protobuf/wkt'; +import { + DYN_TYPE, + ERROR_TYPE, + NULL_TYPE, + abstractType, + functionType, + isAssignableType, + isExactType, + listType, + mapType, + messageType, + nullableType, + optionalType, + primitiveType, + typeParamType, + typeType, + wellKnownType, + wrappedType, + wrapperType, +} from './types'; + +describe('types', () => { + it('DYN_TYPE', () => { + expect(DYN_TYPE).toEqual( + create(TypeSchema, { + typeKind: { + case: 'dyn', + value: create(EmptySchema), + }, + }) + ); + }); + + it('NULL_TYPE', () => { + expect(NULL_TYPE).toEqual( + create(TypeSchema, { + typeKind: { + case: 'null', + value: NullValue.NULL_VALUE, + }, + }) + ); + }); + + it('primitiveType', () => { + expect(primitiveType(Type_PrimitiveType.BOOL)).toEqual( + create(TypeSchema, { + typeKind: { + case: 'primitive', + value: 1, + }, + }) + ); + }); + + it('wrapperType', () => { + expect(wrapperType(Type_PrimitiveType.BYTES)).toEqual( + create(TypeSchema, { + typeKind: { + case: 'wrapper', + value: 6, + }, + }) + ); + }); + + it('wellKnownType', () => { + expect(wellKnownType(Type_WellKnownType.ANY)).toEqual( + create(TypeSchema, { + typeKind: { + case: 'wellKnown', + value: 1, + }, + }) + ); + }); + + it('listType', () => { + expect( + listType({ elemType: primitiveType(Type_PrimitiveType.INT64) }) + ).toEqual( + create(TypeSchema, { + typeKind: { + case: 'listType', + value: { + elemType: { + typeKind: { + case: 'primitive', + value: 2, + }, + }, + }, + }, + }) + ); + }); + + it('mapType', () => { + expect( + mapType({ + keyType: primitiveType(Type_PrimitiveType.STRING), + valueType: primitiveType(Type_PrimitiveType.INT64), + }) + ).toEqual( + create(TypeSchema, { + typeKind: { + case: 'mapType', + value: { + keyType: { + typeKind: { + case: 'primitive', + value: 5, + }, + }, + valueType: { + typeKind: { + case: 'primitive', + value: 2, + }, + }, + }, + }, + }) + ); + }); + + it('functionType', () => { + expect( + functionType({ + resultType: primitiveType(Type_PrimitiveType.BOOL), + argTypes: [primitiveType(Type_PrimitiveType.STRING)], + }) + ).toEqual( + create(TypeSchema, { + typeKind: { + case: 'function', + value: { + resultType: { + typeKind: { + case: 'primitive', + value: 1, + }, + }, + argTypes: [ + { + typeKind: { + case: 'primitive', + value: 5, + }, + }, + ], + }, + }, + }) + ); + }); + + it('messageType', () => { + expect(messageType('google.protobuf.Empty')).toEqual( + create(TypeSchema, { + typeKind: { + case: 'messageType', + value: 'google.protobuf.Empty', + }, + }) + ); + }); + + it('typeParamType', () => { + expect(typeParamType('T')).toEqual( + create(TypeSchema, { + typeKind: { + case: 'typeParam', + value: 'T', + }, + }) + ); + }); + + it('typeType', () => { + expect(typeType(primitiveType(Type_PrimitiveType.DOUBLE))).toEqual( + create(TypeSchema, { + typeKind: { + case: 'type', + value: { + typeKind: { + case: 'primitive', + value: 4, + }, + }, + }, + }) + ); + }); + + it('ERROR_TYPE', () => { + expect(ERROR_TYPE).toEqual( + create(TypeSchema, { + typeKind: { + case: 'error', + value: create(EmptySchema), + }, + }) + ); + }); + + it('abstractType', () => { + expect( + abstractType({ + name: 'google.protobuf.Any', + parameterTypes: [primitiveType(Type_PrimitiveType.STRING)], + }) + ).toEqual( + create(TypeSchema, { + typeKind: { + case: 'abstractType', + value: { + name: 'google.protobuf.Any', + parameterTypes: [ + { + typeKind: { + case: 'primitive', + value: 5, + }, + }, + ], + }, + }, + }) + ); + }); + + it('isExactType', () => { + const testCases = [ + { + t1: primitiveType(Type_PrimitiveType.STRING), + t2: primitiveType(Type_PrimitiveType.STRING), + isExact: true, + }, + { + t1: primitiveType(Type_PrimitiveType.STRING), + t2: primitiveType(Type_PrimitiveType.INT64), + isExact: false, + }, + { + t1: optionalType(primitiveType(Type_PrimitiveType.STRING)), + t2: optionalType(primitiveType(Type_PrimitiveType.INT64)), + isExact: false, + }, + { + t1: optionalType(primitiveType(Type_PrimitiveType.UINT64)), + t2: optionalType(primitiveType(Type_PrimitiveType.UINT64)), + isExact: true, + }, + { + t1: optionalType(typeParamType('T')), + t2: optionalType(typeParamType('T')), + isExact: true, + }, + { + t1: optionalType(typeParamType('S')), + t2: optionalType(typeParamType('T')), + isExact: false, + }, + { + t1: mapType({ + keyType: primitiveType(Type_PrimitiveType.STRING), + valueType: primitiveType(Type_PrimitiveType.INT64), + }), + t2: mapType({ + keyType: primitiveType(Type_PrimitiveType.STRING), + valueType: primitiveType(Type_PrimitiveType.INT64), + }), + isExact: true, + }, + { + t1: mapType({ + keyType: primitiveType(Type_PrimitiveType.STRING), + valueType: primitiveType(Type_PrimitiveType.INT64), + }), + t2: mapType({ + keyType: primitiveType(Type_PrimitiveType.STRING), + valueType: primitiveType(Type_PrimitiveType.BOOL), + }), + isExact: false, + }, + { + t1: listType({ + elemType: primitiveType(Type_PrimitiveType.STRING), + }), + t2: listType({ + elemType: primitiveType(Type_PrimitiveType.STRING), + }), + isExact: true, + }, + { + t1: listType({ + elemType: primitiveType(Type_PrimitiveType.STRING), + }), + t2: listType({ + elemType: primitiveType(Type_PrimitiveType.INT64), + }), + isExact: false, + }, + { + t1: wrappedType(Type_PrimitiveType.STRING), + t2: wrappedType(Type_PrimitiveType.STRING), + isExact: true, + }, + { + t1: wrappedType(Type_PrimitiveType.STRING), + t2: wrappedType(Type_PrimitiveType.INT64), + isExact: false, + }, + ]; + for (const testCase of testCases) { + expect(isExactType(testCase.t1, testCase.t2)).toEqual(testCase.isExact); + } + }); + + it('isAssignable', () => { + const testCases = [ + { + t1: nullableType(primitiveType(Type_PrimitiveType.STRING)), + t2: NULL_TYPE, + isAssignable: true, + }, + { + t1: nullableType(primitiveType(Type_PrimitiveType.STRING)), + t2: primitiveType(Type_PrimitiveType.STRING), + isAssignable: true, + }, + { + t1: abstractType({ + name: 'vector', + parameterTypes: [primitiveType(Type_PrimitiveType.DOUBLE)], + }), + t2: abstractType({ + name: 'vector', + parameterTypes: [primitiveType(Type_PrimitiveType.DOUBLE)], + }), + isAssignable: true, + }, + { + t1: abstractType({ + name: 'vector', + parameterTypes: [primitiveType(Type_PrimitiveType.DOUBLE)], + }), + t2: abstractType({ + name: 'vector', + parameterTypes: [primitiveType(Type_PrimitiveType.UINT64)], + }), + isAssignable: false, + }, + { + t1: abstractType({ + name: 'vector', + parameterTypes: [ + nullableType(primitiveType(Type_PrimitiveType.DOUBLE)), + ], + }), + t2: abstractType({ + name: 'vector', + parameterTypes: [NULL_TYPE], + }), + isAssignable: true, + }, + { + t1: abstractType({ + name: 'vector', + parameterTypes: [ + nullableType(primitiveType(Type_PrimitiveType.DOUBLE)), + ], + }), + t2: abstractType({ + name: 'vector', + parameterTypes: [primitiveType(Type_PrimitiveType.DOUBLE)], + }), + isAssignable: true, + }, + { + t1: abstractType({ + name: 'vector', + parameterTypes: [DYN_TYPE], + }), + t2: abstractType({ + name: 'vector', + parameterTypes: [ + nullableType(primitiveType(Type_PrimitiveType.INT64)), + ], + }), + isAssignable: true, + }, + { + t1: abstractType({ + name: 'vector', + parameterTypes: [primitiveType(Type_PrimitiveType.DOUBLE)], + }), + t2: abstractType({ + name: 'vector', + parameterTypes: [ + nullableType(primitiveType(Type_PrimitiveType.INT64)), + ], + }), + isAssignable: false, + }, + { + t1: abstractType({ + name: 'vector', + parameterTypes: [ + nullableType(primitiveType(Type_PrimitiveType.INT64)), + ], + }), + t2: abstractType({ + name: 'vector', + parameterTypes: [DYN_TYPE], + }), + isAssignable: false, + }, + { + t1: messageType('test.TestMessage'), + t2: messageType('test.TestMessage'), + isAssignable: true, + }, + { + t1: messageType('test.TestMessage'), + t2: messageType('test.AnotherTestMessage'), + isAssignable: false, + }, + { + t1: mapType({ + keyType: typeParamType('K'), + valueType: primitiveType(Type_PrimitiveType.INT64), + }), + t2: mapType({ + keyType: primitiveType(Type_PrimitiveType.STRING), + valueType: primitiveType(Type_PrimitiveType.INT64), + }), + isAssignable: true, + }, + { + t1: mapType({ + keyType: primitiveType(Type_PrimitiveType.STRING), + valueType: primitiveType(Type_PrimitiveType.INT64), + }), + t2: mapType({ + keyType: typeParamType('K'), + valueType: primitiveType(Type_PrimitiveType.INT64), + }), + isAssignable: false, + }, + { + t1: listType({ + elemType: typeParamType('T'), + }), + t2: listType({ + elemType: primitiveType(Type_PrimitiveType.INT64), + }), + isAssignable: true, + }, + { + t1: listType({ + elemType: primitiveType(Type_PrimitiveType.INT64), + }), + t2: listType({ + elemType: typeParamType('T'), + }), + isAssignable: false, + }, + ]; + for (const testCase of testCases) { + expect(isAssignableType(testCase.t1, testCase.t2)).toEqual( + testCase.isAssignable + ); + } + }); +}); diff --git a/packages/cel/src/lib/types.ts b/packages/cel/src/lib/types.ts index 1e38f83..1f88cf8 100644 --- a/packages/cel/src/lib/types.ts +++ b/packages/cel/src/lib/types.ts @@ -1,3 +1,20 @@ +/* eslint-disable no-case-declarations */ +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +import { isNil } from '@bearclaw/is'; +import { + Type, + TypeSchema, + Type_AbstractTypeSchema, + Type_FunctionTypeSchema, + Type_ListTypeSchema, + Type_MapTypeSchema, + Type_PrimitiveType, + Type_WellKnownType, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { MessageInitShape, create } from '@bufbuild/protobuf'; +import { EmptySchema, NullValue } from '@bufbuild/protobuf/wkt'; + export interface Location { line: number; column: number; @@ -7,3 +24,773 @@ export interface OffsetRange { start: number; stop: number; } + +export const DYN_TYPE = create(TypeSchema, { + typeKind: { + case: 'dyn', + value: create(EmptySchema), + }, +}); + +export const NULL_TYPE = create(TypeSchema, { + typeKind: { + case: 'null', + value: NullValue.NULL_VALUE, + }, +}); + +export function primitiveType(value: Type_PrimitiveType) { + return create(TypeSchema, { + typeKind: { + case: 'primitive', + value, + }, + }); +} + +export function wrapperType(value: Type_PrimitiveType) { + return create(TypeSchema, { + typeKind: { + case: 'wrapper', + value, + }, + }); +} + +export function wellKnownType(value: Type_WellKnownType) { + return create(TypeSchema, { + typeKind: { + case: 'wellKnown', + value, + }, + }); +} + +export function listType(value: MessageInitShape) { + return create(TypeSchema, { + typeKind: { + case: 'listType', + value, + }, + }); +} + +export function mapType(value: MessageInitShape) { + return create(TypeSchema, { + typeKind: { + case: 'mapType', + value, + }, + }); +} + +export function functionType( + value: MessageInitShape +) { + return create(TypeSchema, { + typeKind: { + case: 'function', + value, + }, + }); +} + +export function messageType(value: string) { + return create(TypeSchema, { + typeKind: { + case: 'messageType', + value, + }, + }); +} + +export function typeParamType(value: string) { + return create(TypeSchema, { + typeKind: { + case: 'typeParam', + value, + }, + }); +} + +export function typeType(value: Type) { + return create(TypeSchema, { + typeKind: { + case: 'type', + value, + }, + }); +} + +export const ERROR_TYPE = create(TypeSchema, { + typeKind: { + case: 'error', + value: create(EmptySchema), + }, +}); + +export function abstractType( + value: MessageInitShape +) { + return create(TypeSchema, { + typeKind: { + case: 'abstractType', + value, + }, + }); +} + +export function optionalType(value: Type) { + return abstractType({ name: 'optional_type', parameterTypes: [value] }); +} + +export function isOptionalType(val: Type) { + return ( + val.typeKind.case === 'abstractType' && + val.typeKind.value.name === 'optional_type' + ); +} + +export function unwrapOptionalType(val: Type) { + if (isOptionalType(val)) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return (val.typeKind.value as any).parameterTypes[0] as Type; + } + return null; +} + +export function wrappedType(value: Type_PrimitiveType) { + return create(TypeSchema, { + typeKind: { + case: 'wrapper', + value, + }, + }); +} + +export function nullableType(value: Type) { + return abstractType({ name: 'nullable_type', parameterTypes: [value] }); +} + +export function isNullableType(val: Type) { + return ( + val.typeKind.case === 'abstractType' && + val.typeKind.value.name === 'nullable_type' + ); +} + +export function unwrapNullableType(val: Type) { + if (isNullableType(val)) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return (val.typeKind.value as any).parameterTypes[0] as Type; + } + return null; +} + +export function isDyn(val: Type) { + return val.typeKind.case === 'dyn'; +} + +export function isError(val: Type) { + return val.typeKind.case === 'error'; +} + +export function isDynOrError(val: Type) { + return isDyn(val) || isError(val); +} + +export function isNullType(val: Type) { + return val.typeKind.case === 'null'; +} + +/** + * Checks whether one type is equal or less specific than another. A type is + * less specific if it matches the other type using the DYN type + * @param t1 the first type + * @param t2 the second type + */ +export function isEqualOrLessSpecific(t1: Type, t2: Type): boolean { + const kind1 = t1.typeKind.case; + const kind2 = t2.typeKind.case; + // The first type is less specific + if (isDyn(t1) || kind1 === 'typeParam') { + return true; + } + // The first type is not less specific. + if (isDyn(t2) || kind2 === 'typeParam') { + return false; + } + // Types must be of the same kind to be equal. + if (kind1 !== kind2) { + return false; + } + // With limited exceptions for ANY and JSON values, the types must agree and + // be equivalent in order to return true. + switch (kind1) { + case 'abstractType': + if (t1.typeKind.case !== t2.typeKind.case) { + // We will never get here + throw new Error('kinds must be equal'); + } + if ( + t1.$typeName !== t2.$typeName || + t1.typeKind.value.parameterTypes.length !== + t2.typeKind.value.parameterTypes.length + ) { + return false; + } + for (let i = 0; i < t1.typeKind.value.parameterTypes.length; i++) { + if ( + isEqualOrLessSpecific( + t1.typeKind.value.parameterTypes[i], + t2.typeKind.value.parameterTypes[i] + ) + ) { + return false; + } + } + return true; + case 'listType': + if (t1.typeKind.case !== t2.typeKind.case) { + // We will never get here + throw new Error('kinds must be equal'); + } + return isEqualOrLessSpecific( + t1.typeKind.value.elemType!, + t2.typeKind.value.elemType! + ); + case 'mapType': + if (t1.typeKind.case !== t2.typeKind.case) { + // We will never get here + throw new Error('kinds must be equal'); + } + return ( + isEqualOrLessSpecific( + t1.typeKind.value.keyType!, + t2.typeKind.value.keyType! + ) && + isEqualOrLessSpecific( + t1.typeKind.value.valueType!, + t2.typeKind.value.valueType! + ) + ); + case 'type': + if (t1.typeKind.case !== t2.typeKind.case) { + // We will never get here + throw new Error('kinds must be equal'); + } + return true; + default: + return ( + t1.typeKind.case === t2.typeKind.case && + t1.typeKind.value === t2.typeKind.value + ); + } +} + +/** + * Returns the more general of two types which are known to unify. + * + * @param t1 the first type + * @param t2 the second type + * @returns the most general type that is equal or less specific than both + * input types + */ +export function mostGeneral(t1: Type, t2: Type): Type { + if (isEqualOrLessSpecific(t1, t2)) { + return t1; + } + return t2; +} + +/** + * Returns an updated type substitution mapping if t1 is assignable to t2. + * @param mapping the current type substitution mapping + * @param t1 the first type + * @param t2 the second type + * @returns an updated type substitution mapping or null if t1 is not assignable + */ +export function isAssignable(mapping: Map, t1: Type, t2: Type) { + const copy = new Map(mapping); + if (internalIsAssignable(copy, t1, t2)) { + return copy; + } + return null; +} + +/** + * Returns true if t1 is assignable to t2. + * + * @param mapping the current type substitution mapping + * @param t1 the first type + * @param t2 the second type + * @returns whether t1 is assignable to t2 + */ +export function internalIsAssignable( + mapping: Map, + t1: Type, + t2: Type +): boolean { + // Process type parameters + const kind1 = t1.typeKind.case; + const kind2 = t2.typeKind.case; + if (kind2 === 'typeParam') { + // If t2 is a valid type substitution for t1, return true. + const [valid, t2HasSub] = isValidTypeSubstitution(mapping, t1, t2); + if (valid) { + return true; + } + // If t2 is not a valid type sub for t1, and already has a known + // substitution return false since it is not possible for t1 to be + // substitution for t2. + if (!valid && t2HasSub) { + return false; + } + // Otherwise, fall through to check whether t1 is a possible substitution + // for t2. + } + if (kind1 === 'typeParam') { + // Return whether t1 is a valid substitution for t2. If not, do no + // additional checks as the possible type substitutions have been searched + // in both directions. + const [valid, _] = isValidTypeSubstitution(mapping, t2, t1); + return valid; + } + // Next check for wildcard types. + if (isDynOrError(t1) || isDynOrError(t2)) { + return true; + } + // Preserve the nullness checks of the legacy type-checker. + if (kind1 == 'null') { + return internalIsAssignableNull(t2); + } + if (kind2 == 'null') { + return internalIsAssignableNull(t1); + } + // Test for when the types do not need to agree, but are more specific than + // dyn. + switch (kind1) { + case 'primitive': + case 'wellKnown': + case 'messageType': + case 'wrapper': + case 'error': + return isAssignableType(t1, t2); + case 'type': + return kind2 === 'type'; + case 'abstractType': + return ( + t2.typeKind.case === 'abstractType' && + internalIsAssignableList( + mapping, + t1.typeKind.value.parameterTypes, + t2.typeKind.value.parameterTypes + ) + ); + case 'listType': + return ( + t2.typeKind.case === 'listType' && + internalIsAssignable( + mapping, + t1.typeKind.value.elemType!, + t2.typeKind.value.elemType! + ) + ); + case 'mapType': + return ( + t2.typeKind.case === 'mapType' && + internalIsAssignable( + mapping, + t1.typeKind.value.keyType!, + t2.typeKind.value.keyType! + ) && + internalIsAssignable( + mapping, + t1.typeKind.value.valueType!, + t2.typeKind.value.valueType! + ) + ); + default: + return false; + } +} + +/** + * Returns true if the element types at each index in the list are + * assignable from l1[i] to l2[i]. The list lengths must also agree for the + * lists to be assignable. + * @param mapping the type map to use for checking references + * @param l1 the first list type + * @param l2 the second list type + * @returns whether the list types are assignable + */ +export function internalIsAssignableList( + mapping: Map, + l1: Type[], + l2: Type[] +) { + if (l1.length !== l2.length) { + return false; + } + for (let i = 0; i < l1.length; i++) { + if (!internalIsAssignable(mapping, l1[i], l2[i])) { + return false; + } + } + return true; +} + +/** + * Returns true if the type is nullable. + * @param t the type to check + * @returns whether the type is nullable + */ +export function internalIsAssignableNull(t: Type) { + return isAssignableType(t, NULL_TYPE); +} + +/** + * Returns whether t2 (or its type substitution) is a valid type substitution + * for t1, and whether t2 has a type substitution in mapping m. + * The type t2 is a valid substitution for t1 if any of the following + * statements is true + * - t2 has a type substitution (t2sub) equal to t1 + * - t2 has a type substitution (t2sub) assignable to t1 + * - t2 does not occur within t1. + * + * @param mapping the type map to use for checking references + * @param t1 the first type + * @param t2 the second type + * @returns a tuple where the first element is whether t2 is a valid type + * substitution for t1, and the second element is whether t2 has a type + * substitution in the mapping + */ +export function isValidTypeSubstitution( + mapping: Map, + t1: Type, + t2: Type +): [boolean, boolean] { + // Early return if the t1 and t2 are the same instance. + const kind1 = t1.typeKind.case; + const kind2 = t2.typeKind.case; + if (kind1 === kind2 && t1 === t2) { + return [true, true]; + } + const t2sub = Array.from(mapping).find(([_, v]) => v === t2)?.[1]; + if (!isNil(t2sub)) { + // Early return if t1 and t2Sub are the same instance as otherwise the + // mapping might mark a type as being a subtitution for itself. + if (kind1 === t2sub.typeKind.case && t1 === t2sub) { + return [true, true]; + } + // If the types are compatible, pick the more general type and return true + if (internalIsAssignable(mapping, t1, t2sub)) { + const t2New = mostGeneral(t1, t2sub); + // only update the type reference map if the target type does not occur + // within it. + if (notReferencedIn(mapping, t2New, t2)) { + const t2Key = Array.from(mapping).find(([_, v]) => v === t2)?.[0]; + mapping.set(t2Key!, t2New); + } + // acknowledge the type agreement, and that the substitution is already + // tracked. + return [true, true]; + } + return [false, true]; + } + if (notReferencedIn(mapping, t2, t1)) { + const t2Key = Array.from(mapping).find(([_, v]) => v === t2)?.[0]; + mapping.set(t2Key!, t1); + return [true, false]; + } + return [false, false]; +} + +/** + * Checks whether the type doesn't appear directly or transitively within the + * other type. This is a standard requirement for type unification, commonly + * referred to as the "occurs check". + * @param m the type map to use for checking references + * @param t the type to use for checking references + * @param withinType the type to check for references + * @returns whether the type is not referenced in the other type + */ +export function notReferencedIn( + m: Map, + t: Type, + withinType: Type +): boolean { + if (t === withinType) { + return false; + } + const withinKind = withinType.typeKind.case; + switch (withinKind) { + case 'typeParam': + const wtSub = Array.from(m).find(([_, v]) => v === withinType)?.[1]; + if (isNil(wtSub)) { + return true; + } + return notReferencedIn(m, t, wtSub); + case 'abstractType': + for (const pt of withinType.typeKind.value.parameterTypes) { + if (!notReferencedIn(m, t, pt)) { + return false; + } + } + return true; + case 'listType': + return notReferencedIn(m, t, withinType.typeKind.value.elemType!); + case 'mapType': + return ( + notReferencedIn(m, t, withinType.typeKind.value.keyType!) && + notReferencedIn(m, t, withinType.typeKind.value.valueType!) + ); + case 'type': + return t.typeKind.value !== withinType; + default: + return true; + } +} + +/** + * Determines whether the current type is type-check assignable from the input + * fromType. + * @param current the current type + * @param fromType the type to check against + * @returns whether the current type is assignable from the input fromType + */ +export function isAssignableType(current: Type, fromType: Type) { + if (isNil(current)) { + return false; + } + return defaultIsAssignableType(current, fromType); +} + +/** + * Provides the standard definition of what it means for one type to be + * assignable to another where any of the following may return a true result: + * - The from types are the same instance + * - The target type is dynamic + * - The fromType has the same kind and type name as the target type, and all + * parameters of the target type are IsAssignableType() from the parameters of + * the fromType. + * + * @param current the current type + * @param fromType the type to check against + */ +export function defaultIsAssignableType( + current: Type, + fromType: Type +): boolean { + if (current === fromType || isDyn(current)) { + return true; + } + if (isNullableType(current) && isNullType(fromType)) { + return true; + } + if (current.typeKind.case === 'typeParam') { + return true; + } + const unwrappedCurrent = unwrapNullableType(current); + if ( + !isNil(unwrappedCurrent) && + isNullableType(current) && + defaultIsAssignableType(unwrappedCurrent, fromType) + ) { + return true; + } + if ( + current.typeKind.case !== fromType.typeKind.case || + current.$typeName !== fromType.$typeName + ) { + return false; + } + switch (current.typeKind.case) { + case 'abstractType': + if (fromType.typeKind.case !== current.typeKind.case) { + return false; + } + for (let i = 0; i < current.typeKind.value.parameterTypes.length; i++) { + if ( + !defaultIsAssignableType( + current.typeKind.value.parameterTypes[i], + fromType.typeKind.value.parameterTypes[i] + ) + ) { + return false; + } + } + return true; + case 'listType': + if (fromType.typeKind.case !== current.typeKind.case) { + return false; + } + return defaultIsAssignableType( + current.typeKind.value.elemType!, + fromType.typeKind.value.elemType! + ); + case 'mapType': + if (fromType.typeKind.case !== current.typeKind.case) { + return false; + } + return ( + defaultIsAssignableType( + current.typeKind.value.keyType!, + fromType.typeKind.value.keyType! + ) && + defaultIsAssignableType( + current.typeKind.value.valueType!, + fromType.typeKind.value.valueType! + ) + ); + default: + break; + } + return isExactType(current, fromType); +} + +/** + * Replaces all direct and indirect occurrences of bound type parameters. + * Unbound type parameters are replaced by DYN if typeParamToDyn is true. + */ +export function substitute( + mapping: Map, + t: Type, + typeParamToDyn: boolean +): Type { + const tSub = Array.from(mapping).find(([_, v]) => v === t)?.[1]; + if (!isNil(tSub)) { + return substitute(mapping, tSub, typeParamToDyn); + } + if (typeParamToDyn && t.typeKind.case === 'typeParam') { + return DYN_TYPE; + } + switch (t.typeKind.case) { + case 'abstractType': + return abstractType({ + name: t.typeKind.value.name, + parameterTypes: t.typeKind.value.parameterTypes.map((t) => + substitute(mapping, t, typeParamToDyn) + ), + }); + case 'listType': + return listType({ + elemType: substitute( + mapping, + t.typeKind.value.elemType!, + typeParamToDyn + ), + }); + case 'mapType': + return mapType({ + keyType: substitute(mapping, t.typeKind.value.keyType!, typeParamToDyn), + valueType: substitute( + mapping, + t.typeKind.value.valueType!, + typeParamToDyn + ), + }); + case 'type': + // TODO: implement + return t; + default: + return t; + } +} + +/** + * Indicates whether the two types are exactly the same. + * + * @param t1 the first type + * @param t2 the second type + * @returns a boolean indicating whether the types are exactly the same + */ +export function isExactType(t1: Type, t2: Type): boolean { + if (isNil(t1)) { + return false; + } + if (t1 === t2) { + return true; + } + if (t1.typeKind.case !== t2.typeKind.case) { + return false; + } + switch (t1.typeKind.case) { + case 'primitive': + case 'wellKnown': + case 'messageType': + case 'wrapper': + case 'typeParam': + case 'dyn': + case 'error': + case 'null': + return t1.typeKind.value === t2.typeKind.value; + case 'abstractType': + if (t2.typeKind.case !== t1.typeKind.case) { + return false; + } + return ( + t1.typeKind.value.name === t2.typeKind.value.name && + isExactTypeList( + t1.typeKind.value.parameterTypes, + t2.typeKind.value.parameterTypes + ) + ); + case 'function': + if (t2.typeKind.case !== t1.typeKind.case) { + return false; + } + return ( + isExactTypeList( + t1.typeKind.value.argTypes, + t2.typeKind.value.argTypes + ) && + isExactType( + t1.typeKind.value.resultType!, + t2.typeKind.value.resultType! + ) + ); + case 'listType': + if (t2.typeKind.case !== t1.typeKind.case) { + return false; + } + return isExactType( + t1.typeKind.value.elemType!, + t2.typeKind.value.elemType! + ); + case 'mapType': + if (t2.typeKind.case !== t1.typeKind.case) { + return false; + } + return ( + isExactType(t1.typeKind.value.keyType!, t2.typeKind.value.keyType!) && + isExactType(t1.typeKind.value.valueType!, t2.typeKind.value.valueType!) + ); + case 'type': + if (t2.typeKind.case !== t1.typeKind.case) { + return false; + } + return isExactType(t1.typeKind.value, t2.typeKind.value); + default: + return true; + } +} + +/** + * Indicates whether the two type lists are exactly the same. + * + * @param t1 the first type list + * @param t2 the second type list + * @returns whether the two type lists are exactly the same + */ +export function isExactTypeList(t1: Type[], t2: Type[]) { + if (t1.length !== t2.length) { + return false; + } + for (let i = 0; i < t1.length; i++) { + if (!isExactType(t1[i], t2[i])) { + return false; + } + } + return true; +} diff --git a/packages/cel/src/lib/utils.spec.ts b/packages/cel/src/lib/utils.spec.ts index 39b5064..d6bd5bc 100644 --- a/packages/cel/src/lib/utils.spec.ts +++ b/packages/cel/src/lib/utils.spec.ts @@ -1,11 +1,13 @@ +import { Type_PrimitiveType } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb'; import { ConstantSchema, ExprSchema, Expr_CreateStruct_EntrySchema, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; -import { create } from '@bufbuild/protobuf'; +import { ScalarType, create } from '@bufbuild/protobuf'; import { NullValue } from '@bufbuild/protobuf/wkt'; +import { primitiveType } from './types'; import { NULL_CONSTANT, NULL_VALUE, @@ -31,6 +33,7 @@ import { int64Value, listExpr, nullExpr, + scalarTypeToPrimitiveType, selectExpr, stringConstant, stringExpr, @@ -742,4 +745,70 @@ describe('utils', () => { expect(extractIdent(identExpr(BigInt(1), { name: 'a' }))).toEqual('a'); expect(extractIdent(int64Expr(BigInt(1), BigInt(1)))).toEqual(null); }); + + it('scalarTypeToPrimitiveType', () => { + const testCases = [ + { + in: ScalarType.BOOL, + out: Type_PrimitiveType.BOOL, + }, + { + in: ScalarType.BYTES, + out: Type_PrimitiveType.BYTES, + }, + { + in: ScalarType.DOUBLE, + out: Type_PrimitiveType.DOUBLE, + }, + { + in: ScalarType.INT64, + out: Type_PrimitiveType.INT64, + }, + { + in: ScalarType.STRING, + out: Type_PrimitiveType.STRING, + }, + { + in: ScalarType.UINT64, + out: Type_PrimitiveType.UINT64, + }, + { + in: ScalarType.FIXED32, + out: Type_PrimitiveType.DOUBLE, + }, + { + in: ScalarType.FIXED64, + out: Type_PrimitiveType.DOUBLE, + }, + { + in: ScalarType.FLOAT, + out: Type_PrimitiveType.DOUBLE, + }, + { + in: ScalarType.SFIXED32, + out: Type_PrimitiveType.DOUBLE, + }, + { + in: ScalarType.SFIXED64, + out: Type_PrimitiveType.DOUBLE, + }, + { + in: ScalarType.SINT32, + out: Type_PrimitiveType.INT64, + }, + { + in: ScalarType.SINT64, + out: Type_PrimitiveType.INT64, + }, + { + in: ScalarType.UINT32, + out: Type_PrimitiveType.UINT64, + }, + ]; + for (const testCase of testCases) { + expect(scalarTypeToPrimitiveType(testCase.in)).toEqual( + primitiveType(testCase.out) + ); + } + }); }); diff --git a/packages/cel/src/lib/utils.ts b/packages/cel/src/lib/utils.ts index 56e80fe..e3a5b73 100644 --- a/packages/cel/src/lib/utils.ts +++ b/packages/cel/src/lib/utils.ts @@ -1,4 +1,15 @@ +/* eslint-disable no-case-declarations */ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import { isNil } from '@bearclaw/is'; import { + DeclSchema, + Decl_FunctionDeclSchema, + Decl_IdentDeclSchema, + ReferenceSchema, + Type_PrimitiveType, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { + Constant, ConstantSchema, Expr, ExprSchema, @@ -9,10 +20,24 @@ import { Expr_CreateStruct_EntrySchema, Expr_IdentSchema, Expr_SelectSchema, + SourceInfo, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; -import { MessageInitShape, create } from '@bufbuild/protobuf'; +import { + DescField, + MessageInitShape, + ScalarType, + create, +} from '@bufbuild/protobuf'; import { NullValue } from '@bufbuild/protobuf/wkt'; +import { + DYN_TYPE, + Location, + listType, + mapType, + messageType, + primitiveType, +} from './types'; export function parseString(str: string) { const decoded = decodeURIComponent(str); @@ -378,6 +403,45 @@ export function comprehensionExpr( }); } +export function functionDecl( + name: string, + init: MessageInitShape +) { + return create(DeclSchema, { + name, + declKind: { + case: 'function', + value: init, + }, + }); +} + +export function identDecl( + name: string, + init: MessageInitShape +) { + return create(DeclSchema, { + name, + declKind: { + case: 'ident', + value: init, + }, + }); +} + +export function identReference(name: string, value: Constant) { + return create(ReferenceSchema, { + name, + value, + }); +} + +export function functionReference(overloadId: string[]) { + return create(ReferenceSchema, { + overloadId, + }); +} + export function unquote(str: string) { const reg = /['"`]/; if (!str) { @@ -398,3 +462,179 @@ export function extractIdent(expr: Expr): string | null { } return expr.exprKind.value.name; } + +/** + * Returns the line and column information for a given character offset. + * + * @param offset the 0-based character offset + * @returns the line and column information + */ +export function getLocationByOffset( + sourceInfo: SourceInfo, + offset: number +): Location { + let line = 1; + let column = offset; + for (let i = 0; i < sourceInfo.lineOffsets.length; i++) { + const lineOffset = sourceInfo.lineOffsets[i]; + if (lineOffset > offset) { + break; + } + line++; + column = offset - lineOffset; + } + return { line, column }; +} + +/** + * calculates the 0-based character offset from a 1-based line and 0-based + * column. + * @param line a 1-based line number + * @param column a 0-based column number + */ +export function computeOffset( + baseLine: number, + baseColumn: number, + sourceInfo: SourceInfo, + line: number, + column: number +) { + line = baseLine + line; + column = baseColumn + column; + if (line === 1) { + return column; + } + if (line < 1 || line > sourceInfo.lineOffsets.length) { + return -1; + } + const offset = sourceInfo.lineOffsets[line - 2]; + return offset + column; +} + +export function mapToObject( + map: Map +) { + const obj = {} as Record; + for (const [key, value] of map.entries()) { + obj[key] = value; + } + return obj; +} + +/** + * Converts an expression AST into a qualified name if possible, or an empty + * string otherwise. + * + * @param expr the expression AST + * @returns a qualified name or an empty string + */ +export function toQualifiedName(expr: Expr): string { + switch (expr.exprKind.case) { + case 'identExpr': + return expr.exprKind.value.name; + case 'selectExpr': + // Test only expressions are not valid as qualified names. + if (expr.exprKind.value.testOnly) { + return ''; + } + if (isNil(expr.exprKind.value.operand)) { + return ''; + } + return `${toQualifiedName(expr.exprKind.value.operand)}.${ + expr.exprKind.value.field + }`; + default: + return ''; + } +} + +/** + * Get the CEL type for a field descriptor. + * + * @param field the field descriptor + * @returns the CEL type for the field + */ +export function getFieldDescriptorType(field: DescField) { + switch (field.fieldKind) { + case 'message': + return messageType(field.message.typeName); + case 'enum': + return messageType(field.enum.typeName); + case 'list': + switch (field.listKind) { + case 'message': + return listType({ + elemType: messageType(field.message.typeName), + }); + case 'enum': + return listType({ + elemType: messageType(field.enum.typeName), + }); + case 'scalar': + return listType({ + elemType: scalarTypeToPrimitiveType(field.scalar), + }); + default: + return DYN_TYPE; + } + case 'scalar': + return scalarTypeToPrimitiveType(field.scalar); + case 'map': + const keyType = scalarTypeToPrimitiveType(field.mapKey); + switch (field.mapKind) { + case 'enum': + return mapType({ + keyType, + valueType: messageType(field.enum.typeName), + }); + case 'message': + return mapType({ + keyType, + valueType: messageType(field.message.typeName), + }); + case 'scalar': + return mapType({ + keyType, + valueType: scalarTypeToPrimitiveType(field.scalar), + }); + default: + return DYN_TYPE; + } + default: + return DYN_TYPE; + } +} + +/** + * Converts a protobuf scalar type to a CEL primitive type. + * + * @param scalar the scalar type + * @returns the CEL primitive type + */ +export function scalarTypeToPrimitiveType(scalar: ScalarType) { + switch (scalar) { + case ScalarType.BOOL: + return primitiveType(Type_PrimitiveType.BOOL); + case ScalarType.BYTES: + return primitiveType(Type_PrimitiveType.BYTES); + case ScalarType.SFIXED32: + case ScalarType.SFIXED64: + case ScalarType.FIXED32: + case ScalarType.FIXED64: + case ScalarType.FLOAT: + case ScalarType.DOUBLE: + return primitiveType(Type_PrimitiveType.DOUBLE); + case ScalarType.INT32: + case ScalarType.INT64: + case ScalarType.SINT32: + case ScalarType.SINT64: + return primitiveType(Type_PrimitiveType.INT64); + case ScalarType.STRING: + return primitiveType(Type_PrimitiveType.STRING); + case ScalarType.UINT32: + case ScalarType.UINT64: + return primitiveType(Type_PrimitiveType.UINT64); + default: + return DYN_TYPE; + } +} From c2b725561f9926f9c3dddd5d7b530e6b4f0315a4 Mon Sep 17 00:00:00 2001 From: jafaircl Date: Sat, 5 Oct 2024 22:04:35 -0400 Subject: [PATCH 15/34] feat(cel): initial check for calls --- packages/cel/src/lib/cel.ts | 2 +- packages/cel/src/lib/checker.spec.ts | 99 ++++++---- packages/cel/src/lib/checker.ts | 271 +++++++++++++++++++++++++- packages/cel/src/lib/environment.ts | 53 ++++++ packages/cel/src/lib/errors.ts | 17 ++ packages/cel/src/lib/overloads.ts | 107 +++++++++++ packages/cel/src/lib/standard.ts | 275 +++++++++++++++++++++++++++ packages/cel/src/lib/types.ts | 29 +++ 8 files changed, 813 insertions(+), 40 deletions(-) create mode 100644 packages/cel/src/lib/overloads.ts diff --git a/packages/cel/src/lib/cel.ts b/packages/cel/src/lib/cel.ts index 13a9e7b..150fff0 100644 --- a/packages/cel/src/lib/cel.ts +++ b/packages/cel/src/lib/cel.ts @@ -1,4 +1,4 @@ -export { CELEnvironment } from './environment'; +export { CELEnvironment, STANDARD_ENV } from './environment'; export { CELProgram } from './program'; // export { CELInterpreter } from './interpreter'; export { CELChecker } from './checker'; diff --git a/packages/cel/src/lib/checker.spec.ts b/packages/cel/src/lib/checker.spec.ts index 65fe217..3528cdc 100644 --- a/packages/cel/src/lib/checker.spec.ts +++ b/packages/cel/src/lib/checker.spec.ts @@ -1,19 +1,21 @@ import { isNil } from '@bearclaw/is'; -import { - Type, - Type_PrimitiveType, -} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { Type } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; import { CELChecker } from './checker'; import { CELContainer } from './container'; -import { CELEnvironment } from './environment'; +import { CELEnvironment, STANDARD_ENV } from './environment'; import { CELParser } from './parser'; import { + BOOL_TYPE, + BYTES_TYPE, + DOUBLE_TYPE, DYN_TYPE, ERROR_TYPE, + INT64_TYPE, NULL_TYPE, + STRING_TYPE, + UINT64_TYPE, listType, mapType, - primitiveType, } from './types'; import { functionDecl, identDecl } from './utils'; @@ -43,32 +45,32 @@ interface TestInfo { // opts []Option } -const defaultEnv = new CELEnvironment({ +const defaultEnv = STANDARD_ENV.extend({ declarations: [ - functionDecl('"fg_s"', { + functionDecl('fg_s', { overloads: [ { overloadId: 'fg_s_0', - resultType: primitiveType(Type_PrimitiveType.STRING), + resultType: STRING_TYPE, }, ], }), - functionDecl('"ffi_s_s"', { + functionDecl('fi_s_s', { overloads: [ { overloadId: 'fi_s_s_0', - params: [primitiveType(Type_PrimitiveType.STRING)], - resultType: primitiveType(Type_PrimitiveType.STRING), + params: [STRING_TYPE], + resultType: STRING_TYPE, isInstanceFunction: true, }, ], }), - identDecl('is', { type: primitiveType(Type_PrimitiveType.STRING) }), - identDecl('ii', { type: primitiveType(Type_PrimitiveType.INT64) }), - identDecl('iu', { type: primitiveType(Type_PrimitiveType.UINT64) }), - identDecl('iz', { type: primitiveType(Type_PrimitiveType.BOOL) }), - identDecl('ib', { type: primitiveType(Type_PrimitiveType.BYTES) }), - identDecl('id', { type: primitiveType(Type_PrimitiveType.DOUBLE) }), + identDecl('is', { type: STRING_TYPE }), + identDecl('ii', { type: INT64_TYPE }), + identDecl('iu', { type: UINT64_TYPE }), + identDecl('iz', { type: BOOL_TYPE }), + identDecl('ib', { type: BYTES_TYPE }), + identDecl('id', { type: DOUBLE_TYPE }), identDecl('ix', { type: NULL_TYPE }), ], }); @@ -78,13 +80,13 @@ const testCases: TestInfo[] = [ { in: `a.b`, out: `a.b~bool`, - outType: primitiveType(Type_PrimitiveType.STRING), + outType: STRING_TYPE, env: new CELEnvironment({ declarations: [ identDecl('a', { type: mapType({ - keyType: primitiveType(Type_PrimitiveType.STRING), - valueType: primitiveType(Type_PrimitiveType.STRING), + keyType: STRING_TYPE, + valueType: STRING_TYPE, }), }), ], @@ -94,32 +96,32 @@ const testCases: TestInfo[] = [ { in: `"A"`, out: `"A"~string`, - outType: primitiveType(Type_PrimitiveType.STRING), + outType: STRING_TYPE, }, { in: `12`, out: `12~int`, - outType: primitiveType(Type_PrimitiveType.INT64), + outType: INT64_TYPE, }, { in: `12u`, out: `12u~uint`, - outType: primitiveType(Type_PrimitiveType.UINT64), + outType: UINT64_TYPE, }, { in: `true`, out: `true~bool`, - outType: primitiveType(Type_PrimitiveType.BOOL), + outType: BOOL_TYPE, }, { in: `false`, out: `false~bool`, - outType: primitiveType(Type_PrimitiveType.BOOL), + outType: BOOL_TYPE, }, { in: `12.23`, out: `12.23~double`, - outType: primitiveType(Type_PrimitiveType.DOUBLE), + outType: DOUBLE_TYPE, }, { in: `null`, @@ -129,37 +131,37 @@ const testCases: TestInfo[] = [ { in: `b"ABC"`, out: `b"ABC"~bytes`, - outType: primitiveType(Type_PrimitiveType.BYTES), + outType: BYTES_TYPE, }, // Ident types { in: `is`, out: `is~string^is`, - outType: primitiveType(Type_PrimitiveType.STRING), + outType: STRING_TYPE, env: defaultEnv, }, { in: `ii`, out: `ii~int^ii`, - outType: primitiveType(Type_PrimitiveType.INT64), + outType: INT64_TYPE, env: defaultEnv, }, { in: `iu`, out: `iu~uint^iu`, - outType: primitiveType(Type_PrimitiveType.UINT64), + outType: UINT64_TYPE, env: defaultEnv, }, { in: `iz`, out: `iz~bool^iz`, - outType: primitiveType(Type_PrimitiveType.BOOL), + outType: BOOL_TYPE, env: defaultEnv, }, { in: `id`, out: `id~double^id`, - outType: primitiveType(Type_PrimitiveType.DOUBLE), + outType: DOUBLE_TYPE, env: defaultEnv, }, { @@ -171,13 +173,13 @@ const testCases: TestInfo[] = [ { in: `ib`, out: `ib~bytes^ib`, - outType: primitiveType(Type_PrimitiveType.BYTES), + outType: BYTES_TYPE, env: defaultEnv, }, { in: `id`, out: `id~double^id`, - outType: primitiveType(Type_PrimitiveType.DOUBLE), + outType: DOUBLE_TYPE, env: defaultEnv, }, { @@ -188,7 +190,7 @@ const testCases: TestInfo[] = [ { in: `[1]`, out: `[1~int]~list(int)`, - outType: listType({ elemType: primitiveType(Type_PrimitiveType.INT64) }), + outType: listType({ elemType: INT64_TYPE }), }, { in: `[1, "A"]`, @@ -203,6 +205,31 @@ const testCases: TestInfo[] = [ | foo | ^`, }, + // Call resolution + { + in: `fg_s()`, + out: `fg_s()~string^fg_s_0`, + outType: STRING_TYPE, + env: defaultEnv, + }, + { + in: `is.fi_s_s()`, + out: `is~string^is.fi_s_s()~string^fi_s_s_0`, + outType: STRING_TYPE, + env: defaultEnv, + }, + { + in: `1 + 2`, + out: `_+_(1~int, 2~int)~int^add_int64`, + outType: INT64_TYPE, + env: defaultEnv, + }, + { + in: `1 + ii`, + out: `_+_(1~int, ii~int^ii)~int^add_int64`, + outType: INT64_TYPE, + env: defaultEnv, + }, ]; describe('CELChecker', () => { diff --git a/packages/cel/src/lib/checker.ts b/packages/cel/src/lib/checker.ts index cb92392..642d88c 100644 --- a/packages/cel/src/lib/checker.ts +++ b/packages/cel/src/lib/checker.ts @@ -1,8 +1,9 @@ /* eslint-disable no-case-declarations */ /* eslint-disable @typescript-eslint/no-non-null-assertion */ -import { isNil } from '@bearclaw/is'; +import { isEmpty, isNil } from '@bearclaw/is'; import { CheckedExprSchema, + Decl, Reference, Type, Type_PrimitiveType, @@ -15,13 +16,22 @@ import { import { create } from '@bufbuild/protobuf'; import { CELEnvironment } from './environment'; import { Errors } from './errors'; +import { + LOGICAL_AND_OPERATOR, + LOGICAL_OR_OPERATOR, + OPT_SELECT_OPERATOR, +} from './operators'; import { DYN_TYPE, ERROR_TYPE, NULL_TYPE, + functionType, isAssignable, + isAssignableList, isDyn, isDynOrError, + isError, + isExactType, isOptionalType, listType, mostGeneral, @@ -41,6 +51,11 @@ import { toQualifiedName, } from './utils'; +export interface OverloadResolution { + resultType?: Type; + checkedRef?: Reference; +} + export class CELChecker { readonly #errors!: Errors; readonly #referenceMap = new Map(); @@ -85,6 +100,9 @@ export class CELChecker { case 'selectExpr': this.checkSelect(expr); break; + case 'callExpr': + this.checkCall(expr); + break; default: this.#errors.reportUnexpectedAstTypeError( expr.id, @@ -180,7 +198,7 @@ export class CELChecker { checkSelect(expr: Expr) { if (expr.exprKind.case !== 'selectExpr') { // This should never happen - throw new Error('expr.exprKind.case is not identExpr'); + throw new Error('expr.exprKind.case is not selectExpr'); } // Before traversing down the tree, try to interpret as qualified name. const qname = toQualifiedName(expr); @@ -299,10 +317,248 @@ export class CELChecker { return resultType; } + checkCall(expr: Expr) { + if (expr.exprKind.case !== 'callExpr') { + // This should never happen + throw new Error('expr.exprKind.case is not callExpr'); + } + const call = expr.exprKind.value; + const fnName = call.function; + if (fnName === OPT_SELECT_OPERATOR) { + this.checkOptSelect(expr); + return; + } + const args = call.args; + // Traverse arguments. + for (const arg of args) { + this.check(arg); + } + + // Regular static call with simple name. + if (isNil(call.target)) { + // Check for the existence of the function. + const fn = this.env.lookupFunction(fnName); + if (isNil(fn)) { + this.#errors.reportUndeclaredReference( + expr.id, + this.getLocationById(expr.id), + this.env.container, + fnName + ); + this.setType(expr.id, ERROR_TYPE); + return; + } + // TODO + // // Overwrite the function name with its fully qualified resolved name. + // expr.exprKind.value.function = toQualifiedName(expr); + // e.SetKindCase(c.NewCall(e.ID(), fn.Name(), args...)) + // Check to see whether the overload resolves. + this.resolveOverloadOrError(expr, fn, null, args); + return; + } + + // If a receiver 'target' is present, it may either be a receiver function, + // or a namespaced function, but not both. Given a.b.c() either a.b.c is a + // function or c is a function with target a.b. + // + // Check whether the target is a namespaced function name. + const qualifiedPrefix = toQualifiedName(call.target); + if (!isEmpty(qualifiedPrefix)) { + const qualifiedName = `${qualifiedPrefix}.${fnName}`; + const fn = this.env.lookupFunction(qualifiedName); + if (!isNil(fn)) { + // The function name is namespaced and so preserving the target operand + // would be an inaccurate representation of the desired evaluation + // behavior. + // Overwrite with fully-qualified resolved function name sans receiver + // target. + expr.exprKind.value.function = qualifiedName; + this.resolveOverloadOrError(expr, fn, call.target, args); + return; + } + } + + // Regular instance call. + this.check(call.target); + const fn = this.env.lookupFunction(fnName); + // Function found, attempt overload resolution. + if (!isNil(fn)) { + this.resolveOverloadOrError(expr, fn, call.target, args); + return; + } + // Function name not declared, record error. + this.setType(expr.id, ERROR_TYPE); + this.#errors.reportUndeclaredReference( + expr.id, + this.getLocationById(expr.id), + this.env.container, + fnName + ); + } + + resolveOverloadOrError( + expr: Expr, + fn: Decl, + target: Expr | null, + args: Expr[] + ) { + if (expr.exprKind.case !== 'callExpr') { + // This should never happen but acts as a type guard. + throw new Error('expr.exprKind.case is not callExpr'); + } + if (fn.declKind.case !== 'function') { + // This should never happen but acts as a type guard. + throw new Error('fn.declKind.case is not a function'); + } + // Attempt to resolve the overload. + const resolution = this.resolveOverload(expr, fn, target, args); + // No such overload, error noted in the resolveOverload call, type recorded + // here. + if (isNil(resolution)) { + this.setType(expr.id, ERROR_TYPE); + return; + } + // Overload found + this.setType(expr.id, resolution.resultType!); + this.setReference(expr.id, resolution.checkedRef!); + } + + resolveOverload( + expr: Expr, + fn: Decl, + target: Expr | null, + args: Expr[] + ): OverloadResolution | null { + if (expr.exprKind.case !== 'callExpr') { + // This should never happen but acts as a type guard. + throw new Error('expr.exprKind.case is not callExpr'); + } + if (fn.declKind.case !== 'function') { + // This should never happen but acts as a type guard. + throw new Error('fn.declKind.case is not a function'); + } + const argTypes: Type[] = []; + if (!isNil(expr.exprKind.value.target)) { + const targetType = isNil(target) ? null : this.getType(target.id); + if (isNil(targetType)) { + // This should never happen but acts as a type guard. + throw new Error('targetType is nil'); + } + argTypes.push(targetType); + } + for (const arg of args) { + const argType = this.getType(arg.id); + if (isNil(argType)) { + // This should never happen but acts as a type guard. + throw new Error('argType is nil'); + } + argTypes.push(argType); + } + + let resultType: Type | undefined = undefined; + let checkedRef: Reference | undefined = undefined; + for (const overload of fn.declKind.value.overloads) { + // TODO: implement disabled overloads + // // Determine whether the overload is currently considered. + // if c.env.isOverloadDisabled(overload.ID()) { + // continue + // } + + // Ensure the call style for the overload matches. + if ( + (isNil(target) && overload.isInstanceFunction) || + (!isNil(target) && !overload.isInstanceFunction) + ) { + // not a compatible call style. + continue; + } + + // Alternative type-checking behavior when the logical operators are + // compacted into variadic AST representations. + if (fn.name === LOGICAL_AND_OPERATOR || fn.name === LOGICAL_OR_OPERATOR) { + checkedRef = functionReference([overload.overloadId]); + for (let i = 0; i < argTypes.length; i++) { + const argType = argTypes[i]; + if ( + !this._isAssignable(argType, primitiveType(Type_PrimitiveType.BOOL)) + ) { + this.#errors.reportTypeMismatch( + args[i].id, + this.getLocationById(args[i].id), + primitiveType(Type_PrimitiveType.BOOL), + argType + ); + resultType = ERROR_TYPE; + } + } + if (!isNil(resultType) && isError(resultType)) { + return null; + } + return { + checkedRef, + resultType: primitiveType(Type_PrimitiveType.BOOL), + }; + } + + let overloadType = functionType({ + resultType: overload.resultType, + argTypes: overload.params, + }); + const typeParams = overload.typeParams; + if (typeParams.length > 0) { + // Instantiate overload's type with fresh type variables. + const substitutions = new Map(); + for (const typeParam of typeParams) { + substitutions.set(typeParam, this._newTypeVar()); + } + overloadType = substitute(substitutions, overloadType, false); + } + + const candidateArgTypes = overload.params.slice(); + if (this._isAssignableList(argTypes, candidateArgTypes)) { + if (isNil(checkedRef)) { + checkedRef = functionReference([overload.overloadId]); + } else { + checkedRef.overloadId.push(overload.overloadId); + } + // First matching overload, determines result type. + const fnResultType = substitute( + this.#mapping, + overload.resultType!, + false + ); + if (isNil(resultType)) { + resultType = fnResultType; + } else if ( + !isDyn(resultType) && + !isExactType(fnResultType, resultType) + ) { + resultType = DYN_TYPE; + } + } + } + + if (isNil(resultType)) { + for (let i = 0; i < argTypes.length; i++) { + argTypes[i] = substitute(this.#mapping, argTypes[i], false); + } + this.#errors.reportNoMatchingOverload( + expr.id, + this.getLocationById(expr.id), + fn.name, + argTypes, + !isNil(target) + ); + return null; + } + + return { checkedRef, resultType }; + } + checkListExpr(expr: Expr) { if (expr.exprKind.case !== 'listExpr') { // This should never happen - throw new Error('expr.exprKind.case is not identExpr'); + throw new Error('expr.exprKind.case is not listExpr'); } const createList = expr.exprKind.value; let elemsType: Type | undefined = undefined; @@ -394,4 +650,13 @@ export class CELChecker { } return false; } + + private _isAssignableList(l1: Type[], l2: Type[]) { + const subs = isAssignableList(this.#mapping, l1, l2); + if (!isNil(subs)) { + this.#mapping = subs; + return true; + } + return false; + } } diff --git a/packages/cel/src/lib/environment.ts b/packages/cel/src/lib/environment.ts index decb0bf..ad93339 100644 --- a/packages/cel/src/lib/environment.ts +++ b/packages/cel/src/lib/environment.ts @@ -14,6 +14,7 @@ import { } from '@bufbuild/protobuf'; import { CELContainer } from './container'; import { CELParser } from './parser'; +import { STANDARD_FUNCTION_DECLARATIONS, standardTypes } from './standard'; import { DYN_TYPE, messageType } from './types'; import { getFieldDescriptorType, identDecl } from './utils'; @@ -48,6 +49,27 @@ export class CELEnvironment { return new CELParser(input); } + extend(options?: CELEnvironmentOptions) { + let container = this.container; + if (options?.container) { + container = this.container.extend( + options.container.name, + options.container.aliases + ); + } + const registry = this.registry; + if (options?.registry) { + for (const descriptor of options.registry) { + registry.add(descriptor); + } + } + let declarations = this.declarations; + if (options?.declarations) { + declarations = [...this.declarations, ...options.declarations]; + } + return new CELEnvironment({ container, registry, declarations }); + } + /** * Finds the declaration by name in the environment's declarations. * @@ -275,6 +297,31 @@ export class CELEnvironment { return null; } + /** + * Returns a Decl proto for typeName as a function in the Env. Returns null if + * no such function is found in the Env. + * + * @param name the name of the function to look up. + * @returns the function declaration, or null if not found. + */ + lookupFunction(name: string): Decl | null { + const candidateNames = this.container.resolveCandidateNames(name); + for (const candidateName of candidateNames) { + const func = this.findFunction(candidateName); + if (!isNil(func)) { + return func; + } + } + return null; + } + + /** + * Look up the type of a field in a message. + * + * @param message the message name + * @param field the field name + * @returns the field type, or null if not found. + */ lookupFieldType(message: string, field: string) { const candidateNames = this.container.resolveCandidateNames(message); for (const candidateName of candidateNames) { @@ -296,3 +343,9 @@ export class CELEnvironment { } } } + +export const STANDARD_ENV = new CELEnvironment({ + container: new CELContainer(), + registry: createMutableRegistry(...standardTypes), + declarations: [...STANDARD_FUNCTION_DECLARATIONS], +}); diff --git a/packages/cel/src/lib/errors.ts b/packages/cel/src/lib/errors.ts index 51654e8..b50882a 100644 --- a/packages/cel/src/lib/errors.ts +++ b/packages/cel/src/lib/errors.ts @@ -117,6 +117,23 @@ export class Errors { return this.reportErrorAtId(id, location, `undefined field '${field}'`); } + public reportNoMatchingOverload( + id: bigint, + location: Location, + name: string, + args: Type[], + isInstance: boolean + ) { + // TODO + // signature := formatFunctionDeclType(nil, args, isInstance) + const signature = ''; + return this.reportErrorAtId( + id, + location, + `ound no matching overload for '${name}' applied to '${signature}'` + ); + } + public toDisplayString() { let hasRecursionError = false; const errors = []; diff --git a/packages/cel/src/lib/overloads.ts b/packages/cel/src/lib/overloads.ts new file mode 100644 index 0000000..7a7ff3a --- /dev/null +++ b/packages/cel/src/lib/overloads.ts @@ -0,0 +1,107 @@ +// Boolean logic overloads +export const CONDITIONAL_OVERLOAD = 'conditional_overload'; +export const LOGICAL_AND_OVERLOAD = 'logical_and_overload'; +export const LOGICAL_OR_OVERLOAD = 'logical_or_overload'; +export const LOGICAL_NOT_OVERLOAD = 'logical_not_overload'; +export const NOT_STRICTLY_FALSE_OVERLOAD = 'not_strictly_false_overload'; +export const EQUALS_OVERLOAD = 'equals_overload'; +export const NOT_EQUALS_OVERLOAD = 'not_equals_overload'; +export const LESS_BOOL_OVERLOAD = 'less_bool_overload'; +export const LESS_INT64_OVERLOAD = 'less_int64_overload'; +export const LESS_INT64_DOUBLE_OVERLOAD = 'less_int64_double_overload'; +export const LESS_INT64_UINT64_OVERLOAD = 'less_int64_uint64_overload'; +export const LESS_UINT64_OVERLOAD = 'less_uint64_overload'; +export const LESS_UINT64_DOUBLE_OVERLOAD = 'less_uint64_double_overload'; +export const LESS_UINT64_INT64_OVERLOAD = 'less_uint64_int64_overload'; +export const LESS_DOUBLE_OVERLOAD = 'less_double_overload'; +export const LESS_DOUBLE_INT64_OVERLOAD = 'less_double_int64_overload'; +export const LESS_DOUBLE_UINT64_OVERLOAD = 'less_double_uint64_overload'; +export const LESS_STRING_OVERLOAD = 'less_string_overload'; +export const LESS_BYTES_OVERLOAD = 'less_bytes_overload'; +export const LESS_TIMESTAMP_OVERLOAD = 'less_timestamp_overload'; +export const LESS_DURATION_OVERLOAD = 'less_duration_overload'; +export const LESS_EQUALS_BOOL_OVERLOAD = 'less_equals_bool_overload'; +export const LESS_EQUALS_INT64_OVERLOAD = 'less_equals_int64_overload'; +export const LESS_EQUALS_INT64_DOUBLE_OVERLOAD = + 'less_equals_int64_double_overload'; +export const LESS_EQUALS_INT64_UINT64_OVERLOAD = + 'less_equals_int64_uint64_overload'; +export const LESS_EQUALS_UINT64_OVERLOAD = 'less_equals_uint64_overload'; +export const LESS_EQUALS_UINT64_DOUBLE_OVERLOAD = + 'less_equals_uint64_double_overload'; +export const LESS_EQUALS_UINT64_INT64_OVERLOAD = + 'less_equals_uint64_int64_overload'; +export const LESS_EQUALS_DOUBLE_OVERLOAD = 'less_equals_double_overload'; +export const LESS_EQUALS_DOUBLE_INT64_OVERLOAD = + 'less_equals_double_int64_overload'; +export const LESS_EQUALS_DOUBLE_UINT64_OVERLOAD = + 'less_equals_double_uint64_overload'; +export const LESS_EQUALS_STRING_OVERLOAD = 'less_equals_string_overload'; +export const LESS_EQUALS_BYTES_OVERLOAD = 'less_equals_bytes_overload'; +export const LESS_EQUALS_TIMESTAMP_OVERLOAD = 'less_equals_timestamp_overload'; +export const LESS_EQUALS_DURATION_OVERLOAD = 'less_equals_duration_overload'; +export const GREATER_BOOL_OVERLOAD = 'greater_bool_overload'; +export const GREATER_INT64_OVERLOAD = 'greater_int64_overload'; +export const GREATER_INT64_DOUBLE_OVERLOAD = 'greater_int64_double_overload'; +export const GREATER_INT64_UINT64_OVERLOAD = 'greater_int64_uint64_overload'; +export const GREATER_UINT64_OVERLOAD = 'greater_uint64_overload'; +export const GREATER_UINT64_DOUBLE_OVERLOAD = 'greater_uint64_double_overload'; +export const GREATER_UINT64_INT64_OVERLOAD = 'greater_uint64_int64_overload'; +export const GREATER_DOUBLE_OVERLOAD = 'greater_double_overload'; +export const GREATER_DOUBLE_INT64_OVERLOAD = 'greater_double_int64_overload'; +export const GREATER_DOUBLE_UINT64_OVERLOAD = 'greater_double_uint64_overload'; +export const GREATER_STRING_OVERLOAD = 'greater_string_overload'; +export const GREATER_BYTES_OVERLOAD = 'greater_bytes_overload'; +export const GREATER_TIMESTAMP_OVERLOAD = 'greater_timestamp_overload'; +export const GREATER_DURATION_OVERLOAD = 'greater_duration_overload'; +export const GREATER_EQUALS_BOOL_OVERLOAD = 'greater_equals_bool_overload'; +export const GREATER_EQUALS_INT64_OVERLOAD = 'greater_equals_int64_overload'; +export const GREATER_EQUALS_INT64_DOUBLE_OVERLOAD = + 'greater_equals_int64_double_overload'; +export const GREATER_EQUALS_INT64_UINT64_OVERLOAD = + 'greater_equals_int64_uint64_overload'; +export const GREATER_EQUALS_UINT64_OVERLOAD = 'greater_equals_uint64_overload'; +export const GREATER_EQUALS_UINT64_DOUBLE_OVERLOAD = + 'greater_equals_uint64_double_overload'; +export const GREATER_EQUALS_UINT64_INT64_OVERLOAD = + 'greater_equals_uint64_int64_overload'; +export const GREATER_EQUALS_DOUBLE_OVERLOAD = 'greater_equals_double_overload'; +export const GREATER_EQUALS_DOUBLE_INT64_OVERLOAD = + 'greater_equals_double_int64_overload'; +export const GREATER_EQUALS_DOUBLE_UINT64_OVERLOAD = + 'greater_equals_double_uint64_overload'; +export const GREATER_EQUALS_STRING_OVERLOAD = 'greater_equals_string_overload'; +export const GREATER_EQUALS_BYTES_OVERLOAD = 'greater_equals_bytes_overload'; +export const GREATER_EQUALS_TIMESTAMP_OVERLOAD = + 'greater_equals_timestamp_overload'; +export const GREATER_EQUALS_DURATION_OVERLOAD = + 'greater_equals_duration_overload'; + +// Math overloads +export const ADD_INT64_OVERLOAD = 'add_int64'; +export const ADD_UINT64_OVERLOAD = 'add_uint64'; +export const ADD_DOUBLE_OVERLOAD = 'add_double'; +export const ADD_STRING_OVERLOAD = 'add_string'; +export const ADD_BYTES_OVERLOAD = 'add_bytes'; +export const ADD_LIST_OVERLOAD = 'add_list'; +export const ADD_TIMESTAMP_DURATION_OVERLOAD = 'add_timestamp_duration'; +export const ADD_DURATION_TIMESTAMP_OVERLOAD = 'add_duration_timestamp'; +export const ADD_DURATION_DURATION_OVERLOAD = 'add_duration_duration'; +export const SUBTRACT_INT64_OVERLOAD = 'subtract_int64'; +export const SUBTRACT_UINT64_OVERLOAD = 'subtract_uint64'; +export const SUBTRACT_DOUBLE_OVERLOAD = 'subtract_double'; +export const SUBTRACT_TIMESTAMP_TIMESTAMP_OVERLOAD = + 'subtract_timestamp_timestamp'; +export const SUBTRACT_TIMESTAMP_DURATION_OVERLOAD = + 'subtract_timestamp_duration'; +export const SUBTRACT_DURATION_DURATION_OVERLOAD = 'subtract_duration_duration'; +export const MULTIPLY_INT64_OVERLOAD = 'multiply_int64'; +export const MULTIPLY_UINT64_OVERLOAD = 'multiply_uint64'; +export const MULTIPLY_DOUBLE_OVERLOAD = 'multiply_double'; +export const DIVIDE_INT64_OVERLOAD = 'divide_int64'; +export const DIVIDE_UINT64_OVERLOAD = 'divide_uint64'; +export const DIVIDE_DOUBLE_OVERLOAD = 'divide_double'; +export const MODULO_INT64_OVERLOAD = 'modulo_int64'; +export const MODULO_UINT64_OVERLOAD = 'modulo_uint64'; +export const NEGATE_INT64_OVERLOAD = 'negate_int64'; +export const NEGATE_DOUBLE_OVERLOAD = 'negate_double'; diff --git a/packages/cel/src/lib/standard.ts b/packages/cel/src/lib/standard.ts index 37f7421..de9b726 100644 --- a/packages/cel/src/lib/standard.ts +++ b/packages/cel/src/lib/standard.ts @@ -21,6 +21,61 @@ import { UInt32ValueSchema, UInt64ValueSchema, } from '@bufbuild/protobuf/wkt'; +import { + ADD_OPERATOR, + CONDITIONAL_OPERATOR, + DIVIDE_OPERATOR, + EQUALS_OPERATOR, + LOGICAL_AND_OPERATOR, + LOGICAL_NOT_OPERATOR, + LOGICAL_OR_OPERATOR, + MODULO_OPERATOR, + MULTIPLY_OPERATOR, + NEGATE_OPERATOR, + NOT_EQUALS_OPERATOR, + NOT_STRICTLY_FALSE_OPERATOR, + SUBTRACT_OPERATOR, +} from './operators'; +import { + ADD_BYTES_OVERLOAD, + ADD_DOUBLE_OVERLOAD, + ADD_INT64_OVERLOAD, + ADD_LIST_OVERLOAD, + ADD_STRING_OVERLOAD, + ADD_UINT64_OVERLOAD, + CONDITIONAL_OVERLOAD, + DIVIDE_DOUBLE_OVERLOAD, + DIVIDE_INT64_OVERLOAD, + DIVIDE_UINT64_OVERLOAD, + EQUALS_OVERLOAD, + LOGICAL_AND_OVERLOAD, + LOGICAL_NOT_OVERLOAD, + LOGICAL_OR_OVERLOAD, + MODULO_INT64_OVERLOAD, + MODULO_UINT64_OVERLOAD, + MULTIPLY_DOUBLE_OVERLOAD, + MULTIPLY_INT64_OVERLOAD, + MULTIPLY_UINT64_OVERLOAD, + NEGATE_DOUBLE_OVERLOAD, + NEGATE_INT64_OVERLOAD, + NOT_EQUALS_OVERLOAD, + NOT_STRICTLY_FALSE_OVERLOAD, + SUBTRACT_DOUBLE_OVERLOAD, + SUBTRACT_INT64_OVERLOAD, + SUBTRACT_UINT64_OVERLOAD, +} from './overloads'; +import { + BOOL_TYPE, + BYTES_TYPE, + DOUBLE_TYPE, + INT64_TYPE, + STRING_TYPE, + UINT64_TYPE, + listType, + mapType, + typeParamType, +} from './types'; +import { functionDecl } from './utils'; export const standardTypes: ( | DescMessage @@ -44,3 +99,223 @@ export const standardTypes: ( UInt32ValueSchema, UInt64ValueSchema, ]; + +const paramA = typeParamType('A'); +const paramB = typeParamType('B'); +const listOfA = listType({ elemType: paramA }); +const mapOfAB = mapType({ keyType: paramA, valueType: paramB }); + +// Logical operators. Special-cased within the interpreter. +// Note, the singleton binding prevents extensions from overriding the operator +// behavior. +export const CONDITIONAL_FUNCTION_DECL = functionDecl(CONDITIONAL_OPERATOR, { + overloads: [ + { + overloadId: CONDITIONAL_OVERLOAD, + params: [BOOL_TYPE, paramA, paramA], + resultType: paramA, + }, + ], +}); +export const LOGICAL_AND_FUNCTION_DECL = functionDecl(LOGICAL_AND_OPERATOR, { + overloads: [ + { + overloadId: LOGICAL_AND_OVERLOAD, + params: [BOOL_TYPE, BOOL_TYPE], + resultType: BOOL_TYPE, + }, + ], +}); +export const LOGICAL_OR_FUNCTION_DECL = functionDecl(LOGICAL_OR_OPERATOR, { + overloads: [ + { + overloadId: LOGICAL_OR_OVERLOAD, + params: [BOOL_TYPE, BOOL_TYPE], + resultType: BOOL_TYPE, + }, + ], +}); +export const LOGICAL_NOT_FUNCTION_DECL = functionDecl(LOGICAL_NOT_OPERATOR, { + overloads: [ + { + overloadId: LOGICAL_NOT_OVERLOAD, + params: [BOOL_TYPE], + resultType: BOOL_TYPE, + }, + ], +}); + +// Comprehension short-circuiting related function +export const NOT_STRICTLY_FALSE_FUNCTION_DECL = functionDecl( + NOT_STRICTLY_FALSE_OPERATOR, + { + overloads: [ + { + overloadId: NOT_STRICTLY_FALSE_OVERLOAD, + params: [BOOL_TYPE], + resultType: BOOL_TYPE, + }, + ], + } +); + +// Equality / inequality. Special-cased in the interpreter +export const EQUALS_FUNCTION_DECL = functionDecl(EQUALS_OPERATOR, { + overloads: [ + { + overloadId: EQUALS_OVERLOAD, + params: [paramA, paramA], + resultType: BOOL_TYPE, + }, + ], +}); +export const NOT_EQUALS_FUNCTION_DECL = functionDecl(NOT_EQUALS_OPERATOR, { + overloads: [ + { + overloadId: NOT_EQUALS_OVERLOAD, + params: [paramA, paramA], + resultType: BOOL_TYPE, + }, + ], +}); + +// Mathematical operators +export const ADD_FUNCTION_DECL = functionDecl(ADD_OPERATOR, { + overloads: [ + { + overloadId: ADD_BYTES_OVERLOAD, + params: [BYTES_TYPE, BYTES_TYPE], + resultType: BYTES_TYPE, + }, + { + overloadId: ADD_DOUBLE_OVERLOAD, + params: [DOUBLE_TYPE, DOUBLE_TYPE], + resultType: DOUBLE_TYPE, + }, + // TODO: duration and timestamp overloads + { + overloadId: ADD_INT64_OVERLOAD, + params: [INT64_TYPE, INT64_TYPE], + resultType: INT64_TYPE, + }, + { + overloadId: ADD_LIST_OVERLOAD, + params: [listOfA, listOfA], + resultType: listOfA, + }, + { + overloadId: ADD_STRING_OVERLOAD, + params: [STRING_TYPE, STRING_TYPE], + resultType: STRING_TYPE, + }, + { + overloadId: ADD_UINT64_OVERLOAD, + params: [UINT64_TYPE, UINT64_TYPE], + resultType: UINT64_TYPE, + }, + ], +}); +export const DIVIDE_FUNCTION_DECL = functionDecl(DIVIDE_OPERATOR, { + overloads: [ + { + overloadId: DIVIDE_DOUBLE_OVERLOAD, + params: [DOUBLE_TYPE, DOUBLE_TYPE], + resultType: DOUBLE_TYPE, + }, + { + overloadId: DIVIDE_INT64_OVERLOAD, + params: [INT64_TYPE, INT64_TYPE], + resultType: DOUBLE_TYPE, + }, + { + overloadId: DIVIDE_UINT64_OVERLOAD, + params: [UINT64_TYPE, UINT64_TYPE], + resultType: DOUBLE_TYPE, + }, + ], +}); +export const MODULO_FUNCTION_DECL = functionDecl(MODULO_OPERATOR, { + overloads: [ + { + overloadId: MODULO_INT64_OVERLOAD, + params: [INT64_TYPE, INT64_TYPE], + resultType: INT64_TYPE, + }, + { + overloadId: MODULO_UINT64_OVERLOAD, + params: [UINT64_TYPE, UINT64_TYPE], + resultType: UINT64_TYPE, + }, + ], +}); +export const MULTIPLY_FUNCTION_DECL = functionDecl(MULTIPLY_OPERATOR, { + overloads: [ + { + overloadId: MULTIPLY_DOUBLE_OVERLOAD, + params: [DOUBLE_TYPE, DOUBLE_TYPE], + resultType: DOUBLE_TYPE, + }, + { + overloadId: MULTIPLY_INT64_OVERLOAD, + params: [INT64_TYPE, INT64_TYPE], + resultType: INT64_TYPE, + }, + { + overloadId: MULTIPLY_UINT64_OVERLOAD, + params: [UINT64_TYPE, UINT64_TYPE], + resultType: UINT64_TYPE, + }, + ], +}); +export const NEGATE_FUNCTION_DECL = functionDecl(NEGATE_OPERATOR, { + overloads: [ + { + overloadId: NEGATE_DOUBLE_OVERLOAD, + params: [DOUBLE_TYPE], + resultType: DOUBLE_TYPE, + }, + { + overloadId: NEGATE_INT64_OVERLOAD, + params: [INT64_TYPE], + resultType: INT64_TYPE, + }, + ], +}); +export const SUBTRACT_FUNCTION_DECL = functionDecl(SUBTRACT_OPERATOR, { + overloads: [ + { + overloadId: SUBTRACT_DOUBLE_OVERLOAD, + params: [DOUBLE_TYPE, DOUBLE_TYPE], + resultType: DOUBLE_TYPE, + }, + { + overloadId: SUBTRACT_INT64_OVERLOAD, + params: [INT64_TYPE, INT64_TYPE], + resultType: INT64_TYPE, + }, + { + overloadId: SUBTRACT_UINT64_OVERLOAD, + params: [UINT64_TYPE, UINT64_TYPE], + resultType: UINT64_TYPE, + }, + // TODO: duration & timestamp overloads + ], +}); + +export const STANDARD_FUNCTION_DECLARATIONS = [ + CONDITIONAL_FUNCTION_DECL, + LOGICAL_AND_FUNCTION_DECL, + LOGICAL_OR_FUNCTION_DECL, + LOGICAL_NOT_FUNCTION_DECL, + NOT_STRICTLY_FALSE_FUNCTION_DECL, + EQUALS_FUNCTION_DECL, + NOT_EQUALS_FUNCTION_DECL, + ADD_FUNCTION_DECL, + DIVIDE_FUNCTION_DECL, + MODULO_FUNCTION_DECL, + MULTIPLY_FUNCTION_DECL, + NEGATE_FUNCTION_DECL, + SUBTRACT_FUNCTION_DECL, +]; + +// TODO: SingletonUnaryBinding, traits diff --git a/packages/cel/src/lib/types.ts b/packages/cel/src/lib/types.ts index 1f88cf8..8f8d79c 100644 --- a/packages/cel/src/lib/types.ts +++ b/packages/cel/src/lib/types.ts @@ -48,6 +48,13 @@ export function primitiveType(value: Type_PrimitiveType) { }); } +export const BOOL_TYPE = primitiveType(Type_PrimitiveType.BOOL); +export const BYTES_TYPE = primitiveType(Type_PrimitiveType.BYTES); +export const DOUBLE_TYPE = primitiveType(Type_PrimitiveType.DOUBLE); +export const INT64_TYPE = primitiveType(Type_PrimitiveType.INT64); +export const STRING_TYPE = primitiveType(Type_PrimitiveType.STRING); +export const UINT64_TYPE = primitiveType(Type_PrimitiveType.UINT64); + export function wrapperType(value: Type_PrimitiveType) { return create(TypeSchema, { typeKind: { @@ -318,6 +325,28 @@ export function isAssignable(mapping: Map, t1: Type, t2: Type) { return null; } +/** + * Returns an updated substitution mapping if l1 is assignable to l2. + * + * @param mapping the current type substitution mapping + * @param l1 the first list + * @param l2 the second list + * @returns an updated type substitution mapping or null if l1 is not assignable + */ +export function isAssignableList( + mapping: Map, + l1: Type[], + l2: Type[] +) { + const copy = new Map(mapping); + for (let i = 0; i < l1.length; i++) { + if (!internalIsAssignable(copy, l1[i], l2[i])) { + return null; + } + } + return copy; +} + /** * Returns true if t1 is assignable to t2. * From ad1094015ba8cb184e183192a9f81eb421d75113 Mon Sep 17 00:00:00 2001 From: jafaircl Date: Sat, 5 Oct 2024 23:34:14 -0400 Subject: [PATCH 16/34] feat(cel): check adding arrays --- packages/cel/src/lib/checker.spec.ts | 6 +++ packages/cel/src/lib/checker.ts | 26 +++++++------ packages/cel/src/lib/types.ts | 57 +++++++++++++++++++++++----- 3 files changed, 69 insertions(+), 20 deletions(-) diff --git a/packages/cel/src/lib/checker.spec.ts b/packages/cel/src/lib/checker.spec.ts index 3528cdc..6c3c3b5 100644 --- a/packages/cel/src/lib/checker.spec.ts +++ b/packages/cel/src/lib/checker.spec.ts @@ -230,6 +230,12 @@ const testCases: TestInfo[] = [ outType: INT64_TYPE, env: defaultEnv, }, + { + in: `[1] + [2]`, + out: `_+_([1~int]~list(int), [2~int]~list(int))~list(int)^add_list`, + outType: listType({ elemType: INT64_TYPE }), + env: defaultEnv, + }, ]; describe('CELChecker', () => { diff --git a/packages/cel/src/lib/checker.ts b/packages/cel/src/lib/checker.ts index 642d88c..24cccdc 100644 --- a/packages/cel/src/lib/checker.ts +++ b/packages/cel/src/lib/checker.ts @@ -22,9 +22,15 @@ import { OPT_SELECT_OPERATOR, } from './operators'; import { + BOOL_TYPE, + BYTES_TYPE, + DOUBLE_TYPE, DYN_TYPE, ERROR_TYPE, + INT64_TYPE, NULL_TYPE, + STRING_TYPE, + UINT64_TYPE, functionType, isAssignable, isAssignableList, @@ -136,19 +142,19 @@ export class CELChecker { } switch (expr.exprKind.value.constantKind.case) { case 'boolValue': - return primitiveType(Type_PrimitiveType.BOOL); + return BOOL_TYPE; case 'bytesValue': - return primitiveType(Type_PrimitiveType.BYTES); + return BYTES_TYPE; case 'doubleValue': - return primitiveType(Type_PrimitiveType.DOUBLE); + return DOUBLE_TYPE; case 'int64Value': - return primitiveType(Type_PrimitiveType.INT64); + return INT64_TYPE; case 'nullValue': return NULL_TYPE; case 'stringValue': - return primitiveType(Type_PrimitiveType.STRING); + return STRING_TYPE; case 'uint64Value': - return primitiveType(Type_PrimitiveType.UINT64); + return UINT64_TYPE; case 'durationValue': return wellKnownType(Type_WellKnownType.DURATION); case 'timestampValue': @@ -348,10 +354,8 @@ export class CELChecker { this.setType(expr.id, ERROR_TYPE); return; } - // TODO - // // Overwrite the function name with its fully qualified resolved name. - // expr.exprKind.value.function = toQualifiedName(expr); - // e.SetKindCase(c.NewCall(e.ID(), fn.Name(), args...)) + // Overwrite the function name with its fully qualified resolved name. + expr.exprKind.value.function = toQualifiedName(expr); // Check to see whether the overload resolves. this.resolveOverloadOrError(expr, fn, null, args); return; @@ -514,7 +518,7 @@ export class CELChecker { overloadType = substitute(substitutions, overloadType, false); } - const candidateArgTypes = overload.params.slice(); + const candidateArgTypes = overload.params; if (this._isAssignableList(argTypes, candidateArgTypes)) { if (isNil(checkedRef)) { checkedRef = functionReference([overload.overloadId]); diff --git a/packages/cel/src/lib/types.ts b/packages/cel/src/lib/types.ts index 8f8d79c..bccadeb 100644 --- a/packages/cel/src/lib/types.ts +++ b/packages/cel/src/lib/types.ts @@ -10,9 +10,11 @@ import { Type_ListTypeSchema, Type_MapTypeSchema, Type_PrimitiveType, + Type_PrimitiveTypeSchema, Type_WellKnownType, + Type_WellKnownTypeSchema, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; -import { MessageInitShape, create } from '@bufbuild/protobuf'; +import { MessageInitShape, create, enumToJson } from '@bufbuild/protobuf'; import { EmptySchema, NullValue } from '@bufbuild/protobuf/wkt'; export interface Location { @@ -518,8 +520,7 @@ export function isValidTypeSubstitution( // only update the type reference map if the target type does not occur // within it. if (notReferencedIn(mapping, t2New, t2)) { - const t2Key = Array.from(mapping).find(([_, v]) => v === t2)?.[0]; - mapping.set(t2Key!, t2New); + mapping.set(formatCELType(t2New), t2New); } // acknowledge the type agreement, and that the substitution is already // tracked. @@ -528,8 +529,7 @@ export function isValidTypeSubstitution( return [false, true]; } if (notReferencedIn(mapping, t2, t1)) { - const t2Key = Array.from(mapping).find(([_, v]) => v === t2)?.[0]; - mapping.set(t2Key!, t1); + mapping.set(formatCELType(t2), t1); return [true, false]; } return [false, false]; @@ -687,7 +687,7 @@ export function substitute( t: Type, typeParamToDyn: boolean ): Type { - const tSub = Array.from(mapping).find(([_, v]) => v === t)?.[1]; + const tSub = findTypeInMapping(mapping, t); if (!isNil(tSub)) { return substitute(mapping, tSub, typeParamToDyn); } @@ -698,8 +698,8 @@ export function substitute( case 'abstractType': return abstractType({ name: t.typeKind.value.name, - parameterTypes: t.typeKind.value.parameterTypes.map((t) => - substitute(mapping, t, typeParamToDyn) + parameterTypes: t.typeKind.value.parameterTypes.map((_t) => + substitute(mapping, _t, typeParamToDyn) ), }); case 'listType': @@ -720,13 +720,52 @@ export function substitute( ), }); case 'type': - // TODO: implement + return substitute(mapping, t.typeKind.value, typeParamToDyn); + case 'typeParam': + const sub = mapping.get(t.typeKind.value); + if (!isNil(sub)) { + return substitute(mapping, sub, typeParamToDyn); + } return t; default: return t; } } +export function formatCELType(t: Type): string { + switch (t.typeKind.case) { + case 'primitive': + // TODO: implement + return enumToJson(Type_PrimitiveTypeSchema, t.typeKind.value) as string; + case 'wellKnown': + // TODO: implement + return enumToJson(Type_WellKnownTypeSchema, t.typeKind.value) as string; + case 'error': + return '!error!'; + case 'null': + return 'null'; + case 'typeParam': + return t.typeKind.value; + case 'abstractType': + if (t.typeKind.value.name === 'function') { + // TODO: implement + } + break; + case 'listType': + return `list(${formatCELType(t.typeKind.value.elemType!)})`; + } + // TODO: implement + return t.typeKind.case ?? 'unknown'; +} + +export function findTypeInMapping(mapping: Map, t: Type) { + return mapping.get(formatCELType(t)); +} + +export function findTypeKeyInMapping(mapping: Map, t: Type) { + return Array.from(mapping).find(([_, v]) => v === t)?.[0]; +} + /** * Indicates whether the two types are exactly the same. * From 078e55baaae1b99bcec9f770a5d0f581adf1b79b Mon Sep 17 00:00:00 2001 From: jafaircl Date: Sat, 5 Oct 2024 23:51:15 -0400 Subject: [PATCH 17/34] test(cel): add more tests & fix test fixture for checker --- packages/cel/src/lib/checker.spec.ts | 39 +++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/packages/cel/src/lib/checker.spec.ts b/packages/cel/src/lib/checker.spec.ts index 6c3c3b5..89d3249 100644 --- a/packages/cel/src/lib/checker.spec.ts +++ b/packages/cel/src/lib/checker.spec.ts @@ -236,14 +236,36 @@ const testCases: TestInfo[] = [ outType: listType({ elemType: INT64_TYPE }), env: defaultEnv, }, + { + in: `[] + [1,2,3,] + [4]`, + outType: listType({ elemType: INT64_TYPE }), + out: ` +_+_( + _+_( + []~list(int), + [1~int, 2~int, 3~int]~list(int))~list(int)^add_list, + [4~int]~list(int)) +~list(int)^add_list +`, + }, + { + in: `[1, 2u] + []`, + out: `_+_( + [ + 1~int, + 2u~uint + ]~list(dyn), + []~list(dyn) + )~list(dyn)^add_list`, + outType: listType({ elemType: DYN_TYPE }), + }, ]; describe('CELChecker', () => { for (const testCase of testCases) { it(`should parse ${testCase.in}`, () => { - const env = - testCase.env ?? - new CELEnvironment({ container: new CELContainer(testCase.container) }); + const container = new CELContainer(testCase.container ?? ''); + const env = testCase.env ?? STANDARD_ENV.extend({ container }); const parser = new CELParser(testCase.in); const parsed = parser.parse(); if (isNil(parsed.expr)) { @@ -252,9 +274,14 @@ describe('CELChecker', () => { const checker = new CELChecker(parsed, testCase.in, env); const result = checker.check(); if (testCase.outType) { - expect(result.typeMap[parsed.expr.id.toString()]).toEqual( - testCase.outType - ); + try { + expect(result.typeMap[parsed.expr.id.toString()]).toEqual( + testCase.outType + ); + } catch (e) { + console.log(checker.errors.toDisplayString()); + throw e; + } } if (testCase.err) { expect(checker.errors.toDisplayString()).toEqual( From d63e924964de60b07b7d7f1f656576476f0b95bf Mon Sep 17 00:00:00 2001 From: jafaircl Date: Sun, 6 Oct 2024 21:45:33 -0400 Subject: [PATCH 18/34] feat(cel): add checkCreateMap --- packages/cel/src/lib/checker.spec.ts | 15 +++++++ packages/cel/src/lib/checker.ts | 65 +++++++++++++++++++++++++++- 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/packages/cel/src/lib/checker.spec.ts b/packages/cel/src/lib/checker.spec.ts index 89d3249..529ee2c 100644 --- a/packages/cel/src/lib/checker.spec.ts +++ b/packages/cel/src/lib/checker.spec.ts @@ -259,6 +259,21 @@ _+_( )~list(dyn)^add_list`, outType: listType({ elemType: DYN_TYPE }), }, + { + in: `{1:2u, 2:3u}`, + outType: mapType({ keyType: INT64_TYPE, valueType: UINT64_TYPE }), + out: `{1~int : 2u~uint, 2~int : 3u~uint}~map(int, uint)`, + }, + { + in: `{"a":1, "b":2}.a`, + outType: INT64_TYPE, + out: `{"a"~string : 1~int, "b"~string : 2~int}~map(string, int).a~int`, + }, + { + in: `{1:2u, 2u:3}`, + outType: mapType({ keyType: DYN_TYPE, valueType: DYN_TYPE }), + out: `{1~int : 2u~uint, 2u~uint : 3~int}~map(dyn, dyn)`, + }, ]; describe('CELChecker', () => { diff --git a/packages/cel/src/lib/checker.ts b/packages/cel/src/lib/checker.ts index 24cccdc..6e55d3b 100644 --- a/packages/cel/src/lib/checker.ts +++ b/packages/cel/src/lib/checker.ts @@ -40,6 +40,7 @@ import { isExactType, isOptionalType, listType, + mapType, mostGeneral, optionalType, primitiveType, @@ -109,6 +110,16 @@ export class CELChecker { case 'callExpr': this.checkCall(expr); break; + case 'structExpr': + const isMapExpr = expr.exprKind.value.entries.some( + (entry) => entry.keyKind.case === 'mapKey' + ); + if (isMapExpr) { + this.checkCreateMap(expr); + } else { + // TODO: Implement checkCreateStruct + } + break; default: this.#errors.reportUnexpectedAstTypeError( expr.id, @@ -595,6 +606,54 @@ export class CELChecker { this.setType(expr.id, listType({ elemType: elemsType })); } + checkCreateMap(expr: Expr) { + if (expr.exprKind.case !== 'structExpr') { + // This should never happen but acts as a type guard. + throw new Error('expr.exprKind.case is not structExpr'); + } + let mapKeyType: Type | undefined = undefined; + let mapValueType: Type | undefined = undefined; + for (let i = 0; i < expr.exprKind.value.entries.length; i++) { + const entry = expr.exprKind.value.entries[i]; + if (entry.keyKind.case !== 'mapKey') { + // This should never happen + throw new Error('entry.keyKind.case is not mapKey'); + } + const key = entry.keyKind.value; + this.check(key); + mapKeyType = this._joinTypes(key, mapKeyType, this.getType(key.id)!); + + const val = entry.value!; + this.check(val); + let valType = this.getType(val.id)!; + if (isOptionalType(mapKeyType)) { + valType = unwrapOptionalType(valType)!; + if (!isOptionalType(valType) && !isDyn(valType)) { + this.#errors.reportTypeMismatch( + val.id, + this.getLocationById(val.id), + optionalType(valType), + valType + ); + } + } + mapValueType = this._joinTypes(val, mapValueType, valType); + } + if (isNil(mapKeyType)) { + // If the map is empty, assign free type variables to typeKey and value + // type. + mapKeyType = this._newTypeVar(); + mapValueType = this._newTypeVar(); + } + this.setType( + expr.id, + mapType({ + keyType: mapKeyType, + valueType: mapValueType, + }) + ); + } + setType(id: bigint, type: Type) { this.#typeMap.set(id.toString(), type); } @@ -618,7 +677,11 @@ export class CELChecker { ); } - private _joinTypes(expr: Expr, previous: Type, current: Type) { + private _joinTypes( + expr: Expr, + previous: Type | null | undefined, + current: Type + ) { if (isNil(previous)) { return current; } From a05c76540b7c61e1a51bc5fe97194a261c052ad5 Mon Sep 17 00:00:00 2001 From: jafaircl Date: Mon, 7 Oct 2024 12:08:21 -0400 Subject: [PATCH 19/34] feat(cel): add checkCreateStruct and more standard function decls --- package-lock.json | 32 ++ package.json | 1 + packages/cel/src/lib/checker.spec.ts | 142 ++++++ packages/cel/src/lib/checker.ts | 108 ++++- packages/cel/src/lib/errors.ts | 30 +- packages/cel/src/lib/overloads.ts | 153 +++++++ packages/cel/src/lib/standard.ts | 651 +++++++++++++++++++++++++++ packages/cel/src/lib/types.ts | 28 +- packages/cel/src/lib/utils.ts | 20 + 9 files changed, 1161 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index d639812..1a69e71 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.1", "license": "MIT", "dependencies": { + "@buf/cel_spec.bufbuild_es": "^2.1.0-20230602032904-0583f28ce7d3.1", "@buf/google_cel-spec.bufbuild_es": "^2.1.0-20240829202630-b69910e4e9bc.1", "@bufbuild/protobuf": "^2.1.0", "antlr4": "^4.13.2", @@ -2028,6 +2029,23 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "node_modules/@buf/cel_spec.bufbuild_es": { + "version": "2.1.0-20230602032904-0583f28ce7d3.1", + "resolved": "https://buf.build/gen/npm/v1/@buf/cel_spec.bufbuild_es/-/cel_spec.bufbuild_es-2.1.0-20230602032904-0583f28ce7d3.1.tgz", + "dependencies": { + "@buf/googleapis_googleapis.bufbuild_es": "2.1.0-20230502210827-cc916c318597.1" + }, + "peerDependencies": { + "@bufbuild/protobuf": "^2.1.0" + } + }, + "node_modules/@buf/cel_spec.bufbuild_es/node_modules/@buf/googleapis_googleapis.bufbuild_es": { + "version": "2.1.0-20230502210827-cc916c318597.1", + "resolved": "https://buf.build/gen/npm/v1/@buf/googleapis_googleapis.bufbuild_es/-/googleapis_googleapis.bufbuild_es-2.1.0-20230502210827-cc916c318597.1.tgz", + "peerDependencies": { + "@bufbuild/protobuf": "^2.1.0" + } + }, "node_modules/@buf/google_cel-spec.bufbuild_es": { "version": "2.1.0-20240829202630-b69910e4e9bc.1", "resolved": "https://buf.build/gen/npm/v1/@buf/google_cel-spec.bufbuild_es/-/google_cel-spec.bufbuild_es-2.1.0-20240829202630-b69910e4e9bc.1.tgz", @@ -18801,6 +18819,20 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "@buf/cel_spec.bufbuild_es": { + "version": "2.1.0-20230602032904-0583f28ce7d3.1", + "resolved": "https://buf.build/gen/npm/v1/@buf/cel_spec.bufbuild_es/-/cel_spec.bufbuild_es-2.1.0-20230602032904-0583f28ce7d3.1.tgz", + "requires": { + "@buf/googleapis_googleapis.bufbuild_es": "2.1.0-20230502210827-cc916c318597.1" + }, + "dependencies": { + "@buf/googleapis_googleapis.bufbuild_es": { + "version": "2.1.0-20230502210827-cc916c318597.1", + "resolved": "https://buf.build/gen/npm/v1/@buf/googleapis_googleapis.bufbuild_es/-/googleapis_googleapis.bufbuild_es-2.1.0-20230502210827-cc916c318597.1.tgz", + "requires": {} + } + } + }, "@buf/google_cel-spec.bufbuild_es": { "version": "2.1.0-20240829202630-b69910e4e9bc.1", "resolved": "https://buf.build/gen/npm/v1/@buf/google_cel-spec.bufbuild_es/-/google_cel-spec.bufbuild_es-2.1.0-20240829202630-b69910e4e9bc.1.tgz", diff --git a/package.json b/package.json index ad906ab..30c1402 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "vitest": "^1.3.1" }, "dependencies": { + "@buf/cel_spec.bufbuild_es": "^2.1.0-20230602032904-0583f28ce7d3.1", "@buf/google_cel-spec.bufbuild_es": "^2.1.0-20240829202630-b69910e4e9bc.1", "@bufbuild/protobuf": "^2.1.0", "antlr4": "^4.13.2", diff --git a/packages/cel/src/lib/checker.spec.ts b/packages/cel/src/lib/checker.spec.ts index 529ee2c..f042f20 100644 --- a/packages/cel/src/lib/checker.spec.ts +++ b/packages/cel/src/lib/checker.spec.ts @@ -1,5 +1,7 @@ import { isNil } from '@bearclaw/is'; +import { TestAllTypesSchema } from '@buf/cel_spec.bufbuild_es/proto/test/v1/proto3/test_all_types_pb.js'; import { Type } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { createMutableRegistry } from '@bufbuild/protobuf'; import { CELChecker } from './checker'; import { CELContainer } from './container'; import { CELEnvironment, STANDARD_ENV } from './environment'; @@ -16,6 +18,7 @@ import { UINT64_TYPE, listType, mapType, + messageType, } from './types'; import { functionDecl, identDecl } from './utils'; @@ -274,6 +277,145 @@ _+_( outType: mapType({ keyType: DYN_TYPE, valueType: DYN_TYPE }), out: `{1~int : 2u~uint, 2u~uint : 3~int}~map(dyn, dyn)`, }, + { + // TODO: this test container is different than in cel-go because we have to import from a different package + in: `TestAllTypes{single_int32: 1, single_int64: 2}`, + container: 'google.api.expr.test.v1.proto3', + out: ` + google.api.expr.test.v1.proto3TestAllTypes{ + single_int32 : 1~int, + single_int64 : 2~int + }~google.api.expr.test.v1.proto3.TestAllTypes^google.api.expr.test.v1.proto3.TestAllTypes`, + outType: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + env: defaultEnv.extend({ + container: new CELContainer('google.api.expr.test.v1.proto3'), + registry: createMutableRegistry(TestAllTypesSchema), + }), + }, + { + // TODO: this test container is different than in cel-go because we have to import from a different package + in: `TestAllTypes{single_int32: 1u}`, + container: 'google.api.expr.test.v1.proto3', + err: ` +ERROR: :1:26: expected type of field 'single_int32' is 'int' but provided type is 'uint' +| TestAllTypes{single_int32: 1u} +| .........................^`, + env: defaultEnv.extend({ + container: new CELContainer('google.api.expr.test.v1.proto3'), + registry: createMutableRegistry(TestAllTypesSchema), + }), + }, + { + // TODO: this test container is different than in cel-go because we have to import from a different package + in: `TestAllTypes{single_int32: 1, undefined: 2}`, + container: 'google.api.expr.test.v1.proto3', + err: ` +ERROR: :1:40: undefined field 'undefined' +| TestAllTypes{single_int32: 1, undefined: 2} +| .......................................^`, + env: defaultEnv.extend({ + container: new CELContainer('google.api.expr.test.v1.proto3'), + registry: createMutableRegistry(TestAllTypesSchema), + }), + }, + { + in: `size(x) == x.size()`, + out: ` +_==_(size(x~list(int)^x)~int^size_list, x~list(int)^x.size()~int^list_size) +~bool^equals`, + env: defaultEnv.extend({ + declarations: [ + identDecl('x', { type: listType({ elemType: INT64_TYPE }) }), + ], + }), + outType: BOOL_TYPE, + }, + { + in: `int(1u) + int(uint("1"))`, + out: ` +_+_(int(1u~uint)~int^uint64_to_int64, +int(uint("1"~string)~uint^string_to_uint64)~int^uint64_to_int64) +~int^add_int64`, + outType: INT64_TYPE, + }, + { + in: `false && !true || false ? 2 : 3`, + out: ` +_?_:_(_||_(_&&_(false~bool, !_(true~bool)~bool^logical_not)~bool^logical_and, + false~bool) + ~bool^logical_or, +2~int, +3~int) +~int^conditional +`, + outType: INT64_TYPE, + }, + { + in: `b"abc" + b"def"`, + out: `_+_(b"abc"~bytes, b"def"~bytes)~bytes^add_bytes`, + outType: BYTES_TYPE, + }, + { + in: `1.0 + 2.0 * 3.0 - 1.0 / 2.20202 != 66.6`, + out: ` +_!=_(_-_(_+_(1~double, _*_(2~double, 3~double)~double^multiply_double) + ~double^add_double, + _/_(1~double, 2.20202~double)~double^divide_double) + ~double^subtract_double, +66.6~double) +~bool^not_equals`, + outType: BOOL_TYPE, + }, + { + in: `null == null && null != null`, + out: ` + _&&_( + _==_( + null~null, + null~null + )~bool^equals, + _!=_( + null~null, + null~null + )~bool^not_equals + )~bool^logical_and`, + outType: BOOL_TYPE, + }, + { + in: `1 == 1 && 2 != 1`, + out: ` + _&&_( + _==_( + 1~int, + 1~int + )~bool^equals, + _!=_( + 2~int, + 1~int + )~bool^not_equals + )~bool^logical_and`, + outType: BOOL_TYPE, + }, + { + in: `1 + 2 * 3 - 1 / 2 == 6 % 1`, + out: ` _==_(_-_(_+_(1~int, _*_(2~int, 3~int)~int^multiply_int64)~int^add_int64, _/_(1~int, 2~int)~int^divide_int64)~int^subtract_int64, _%_(6~int, 1~int)~int^modulo_int64)~bool^equals`, + outType: BOOL_TYPE, + }, + { + in: `"abc" + "def"`, + out: `_+_("abc"~string, "def"~string)~string^add_string`, + outType: STRING_TYPE, + }, + { + in: `1u + 2u * 3u - 1u / 2u == 6u % 1u`, + out: `_==_(_-_(_+_(1u~uint, _*_(2u~uint, 3u~uint)~uint^multiply_uint64) + ~uint^add_uint64, + _/_(1u~uint, 2u~uint)~uint^divide_uint64) + ~uint^subtract_uint64, + _%_(6u~uint, 1u~uint)~uint^modulo_uint64) +~bool^equals`, + outType: BOOL_TYPE, + }, ]; describe('CELChecker', () => { diff --git a/packages/cel/src/lib/checker.ts b/packages/cel/src/lib/checker.ts index 6e55d3b..d1a0518 100644 --- a/packages/cel/src/lib/checker.ts +++ b/packages/cel/src/lib/checker.ts @@ -4,6 +4,7 @@ import { isEmpty, isNil } from '@bearclaw/is'; import { CheckedExprSchema, Decl, + Decl_IdentDecl, Reference, Type, Type_PrimitiveType, @@ -41,6 +42,7 @@ import { isOptionalType, listType, mapType, + maybeUnwrapOptionalType, mostGeneral, optionalType, primitiveType, @@ -53,6 +55,7 @@ import { extractIdent, functionReference, getLocationByOffset, + getWellKNownTypeName, identReference, mapToObject, toQualifiedName, @@ -117,7 +120,7 @@ export class CELChecker { if (isMapExpr) { this.checkCreateMap(expr); } else { - // TODO: Implement checkCreateStruct + this.checkCreateStruct(expr); } break; default: @@ -654,6 +657,109 @@ export class CELChecker { ); } + checkCreateStruct(expr: Expr) { + if (expr.exprKind.case !== 'structExpr') { + // This should never happen but acts as a type guard. + throw new Error('expr.exprKind.case is not structExpr'); + } + const msgVal = expr.exprKind.value; + // Determine the type of the message. + let resultType: Type = ERROR_TYPE; + const ident = this.env.lookupIdent(msgVal.messageName); + if (isNil(ident)) { + this.#errors.reportUndeclaredReference( + expr.id, + this.getLocationById(expr.id), + this.env.container, + msgVal.messageName + ); + this.setType(expr.id, ERROR_TYPE); + return; + } + const identDecl = ident.declKind.value as Decl_IdentDecl; + let typeName = ident.name; + // Ensure the type name is fully qualified in the AST. + if (msgVal.messageName !== typeName) { + expr.exprKind.value.messageName = typeName; + } + this.setReference(expr.id, identReference(typeName, identDecl.value!)); + const identKind = identDecl.type?.typeKind.case; + if (identKind !== 'error') { + if (identKind !== 'messageType' && identKind !== 'wellKnown') { + this.#errors.reportNotAType( + expr.id, + this.getLocationById(expr.id), + typeName + ); + } else { + resultType = identDecl.type!; + // Backwards compatibility test between well-known types and message + // types. In this context, the type is being instantiated by it + // protobuf name which is not ideal or recommended, but some users + // expect this to work. + if (resultType.typeKind.case === 'wellKnown') { + typeName = getWellKNownTypeName(resultType.typeKind.value)!; + } else if (resultType.typeKind.case === 'messageType') { + typeName = resultType.typeKind.value; + } else { + this.#errors.reportNotAMessageType( + expr.id, + this.getLocationById(expr.id), + typeName + ); + resultType = ERROR_TYPE; + } + } + } + this.setType(expr.id, resultType); + + // Check the field initializers. + for (const field of msgVal.entries) { + if (field.keyKind.case !== 'fieldKey') { + // This should never happen but acts as a type guard. + throw new Error('field.keyKind.case is not fieldKey'); + } + + this.check(field.value); + + let fieldType = ERROR_TYPE; + const ft = this.env.lookupFieldType(typeName, field.keyKind.value); + if (!isNil(ft)) { + fieldType = ft; + } else { + this.#errors.reportUndefinedField( + field.value!.id, + this.getLocationById(field.id), + field.keyKind.value + ); + } + + let valType = this.getType(field.value!.id); + if (field.optionalEntry) { + const vt = maybeUnwrapOptionalType(valType); + if (!isNil(vt)) { + valType = vt; + } else { + this.#errors.reportTypeMismatch( + field.value!.id, + this.getLocationById(field.value!.id), + optionalType(fieldType), + valType! + ); + } + } + if (!this._isAssignable(fieldType, valType!)) { + this.#errors.reportFieldTypeMismatch( + field.value!.id, + this.getLocationById(field.id), + field.keyKind.value, + fieldType, + valType! + ); + } + } + } + setType(id: bigint, type: Type) { this.#typeMap.set(id.toString(), type); } diff --git a/packages/cel/src/lib/errors.ts b/packages/cel/src/lib/errors.ts index b50882a..768af02 100644 --- a/packages/cel/src/lib/errors.ts +++ b/packages/cel/src/lib/errors.ts @@ -13,7 +13,7 @@ import { create, createRegistry } from '@bufbuild/protobuf'; import { anyPack, anyUnpack } from '@bufbuild/protobuf/wkt'; import { ErrorListener, RecognitionException, Recognizer, Token } from 'antlr4'; import { CELContainer } from './container'; -import { Location } from './types'; +import { Location, formatCELType } from './types'; export class Errors { public readonly errors = create(ErrorSetSchema); @@ -134,6 +134,34 @@ export class Errors { ); } + public reportNotAType(id: bigint, location: Location, name: string) { + return this.reportErrorAtId(id, location, `'${name}' is not a type`); + } + + public reportNotAMessageType(id: bigint, location: Location, name: string) { + return this.reportErrorAtId( + id, + location, + `'${name}' is not a message type` + ); + } + + public reportFieldTypeMismatch( + id: bigint, + location: Location, + name: string, + field: Type, + value: Type + ) { + return this.reportErrorAtId( + id, + location, + `expected type of field '${name}' is '${formatCELType( + field + )}' but provided type is '${formatCELType(value)}'` + ); + } + public toDisplayString() { let hasRecursionError = false; const errors = []; diff --git a/packages/cel/src/lib/overloads.ts b/packages/cel/src/lib/overloads.ts index 7a7ff3a..dd67019 100644 --- a/packages/cel/src/lib/overloads.ts +++ b/packages/cel/src/lib/overloads.ts @@ -105,3 +105,156 @@ export const MODULO_INT64_OVERLOAD = 'modulo_int64'; export const MODULO_UINT64_OVERLOAD = 'modulo_uint64'; export const NEGATE_INT64_OVERLOAD = 'negate_int64'; export const NEGATE_DOUBLE_OVERLOAD = 'negate_double'; + +// Index overloads +export const INDEX_LIST_OVERLOAD = 'index_list'; +export const INDEX_MAP_OVERLOAD = 'index_map'; +export const INDEX_MESSAGE_OVERLOAD = 'index_message'; // TODO: introduce concept of types.Message + +// In operators +export const DEPRECATED_IN_OVERLOAD = 'in'; +export const IN_LIST_OVERLOAD = 'in_list'; +export const IN_MAP_OVERLOAD = 'in_map'; +export const IN_MESSAGE_OVERLOAD = 'in_message'; // TODO: introduce concept of types.Message + +// Size overloads +export const SIZE_OVERLOAD = 'size'; +export const SIZE_STRING_OVERLOAD = 'size_string'; +export const SIZE_BYTES_OVERLOAD = 'size_bytes'; +export const SIZE_LIST_OVERLOAD = 'size_list'; +export const SIZE_MAP_OVERLOAD = 'size_map'; +export const SIZE_STRING_INST_OVERLOAD = 'string_size'; +export const SIZE_BYTES_INST_OVERLOAD = 'bytes_size'; +export const SIZE_LIST_INST_OVERLOAD = 'list_size'; +export const SIZE_MAP_INST_OVERLOAD = 'map_size'; + +// String function names. +export const CONTAINS_OVERLOAD = 'contains'; +export const ENDS_WITH_OVERLOAD = 'endsWith'; +export const MATCHES_OVERLOAD = 'matches'; +export const STARTS_WITH_OVERLOAD = 'startsWith'; + +// Extension function overloads with complex behaviors that need to be referenced in runtime and static analysis cost computations. +export const EXT_QUOTE_STRING_OVERLOAD = 'strings_quote'; + +// String function overload names. +export const CONTAINS_STRING_OVERLOAD = 'contains_string'; +export const ENDS_WITH_STRING_OVERLOAD = 'ends_with_string'; +export const MATCHES_STRING_OVERLOAD = 'matches_string'; +export const STARTS_WITH_STRING_OVERLOAD = 'starts_with_string'; + +// Extension function overloads with complex behaviors that need to be referenced in runtime and static analysis cost computations. +export const EXT_FORMAT_STRING_OVERLOAD = 'string_format'; + +// Time-based functions. +export const TIME_GET_FULL_YEAR_OVERLOAD = 'getFullYear'; +export const TIME_GET_MONTH_OVERLOAD = 'getMonth'; +export const TIME_GET_DAY_OF_YEAR_OVERLOAD = 'getDayOfYear'; +export const TIME_GET_DATE_OVERLOAD = 'getDate'; +export const TIME_GET_DAY_OF_MONTH_OVERLOAD = 'getDayOfMonth'; +export const TIME_GET_DAY_OF_WEEK_OVERLOAD = 'getDayOfWeek'; +export const TIME_GET_HOURS_OVERLOAD = 'getHours'; +export const TIME_GET_MINUTES_OVERLOAD = 'getMinutes'; +export const TIME_GET_SECONDS_OVERLOAD = 'getSeconds'; +export const TIME_GET_MILLISECONDS_OVERLOAD = 'getMilliseconds'; + +// Timestamp overloads for time functions without timezones. +export const TIMESTAMP_TO_YEAR_OVERLOAD = 'timestamp_to_year'; +export const TIMESTAMP_TO_MONTH_OVERLOAD = 'timestamp_to_month'; +export const TIMESTAMP_TO_DAY_OF_YEAR_OVERLOAD = 'timestamp_to_day_of_year'; +export const TIMESTAMP_TO_DAY_OF_MONTH_ZERO_BASED_OVERLOAD = + 'timestamp_to_day_of_month'; +export const TIMESTAMP_TO_DAY_OF_MONTH_ONE_BASED_OVERLOAD = + 'timestamp_to_day_of_month_1_based'; +export const TIMESTAMP_TO_DAY_OF_WEEK_OVERLOAD = 'timestamp_to_day_of_week'; +export const TIMESTAMP_TO_HOURS_OVERLOAD = 'timestamp_to_hours'; +export const TIMESTAMP_TO_MINUTES_OVERLOAD = 'timestamp_to_minutes'; +export const TIMESTAMP_TO_SECONDS_OVERLOAD = 'timestamp_to_seconds'; +export const TIMESTAMP_TO_MILLISECONDS_OVERLOAD = 'timestamp_to_milliseconds'; + +// Timestamp overloads for time functions with timezones. +export const TIMESTAMP_TO_YEAR_WITH_TZ_OVERLOAD = 'timestamp_to_year_with_tz'; +export const TIMESTAMP_TO_MONTH_WITH_TZ_OVERLOAD = 'timestamp_to_month_with_tz'; +export const TIMESTAMP_TO_DAY_OF_YEAR_WITH_TZ_OVERLOAD = + 'timestamp_to_day_of_year_with_tz'; +export const TIMESTAMP_TO_DAY_OF_MONTH_ZERO_BASED_WITH_TZ_OVERLOAD = + 'timestamp_to_day_of_month_with_tz'; +export const TIMESTAMP_TO_DAY_OF_MONTH_ONE_BASED_WITH_TZ_OVERLOAD = + 'timestamp_to_day_of_month_1_based_with_tz'; +export const TIMESTAMP_TO_DAY_OF_WEEK_WITH_TZ_OVERLOAD = + 'timestamp_to_day_of_week_with_tz'; +export const TIMESTAMP_TO_HOURS_WITH_TZ_OVERLOAD = 'timestamp_to_hours_with_tz'; +export const TIMESTAMP_TO_MINUTES_WITH_TZ_OVERLOAD = + 'timestamp_to_minutes_with_tz'; +export const TIMESTAMP_TO_SECONDS_WITH_TZ_OVERLOAD = 'timestamp_to_seconds_tz'; +export const TIMESTAMP_TO_MILLISECONDS_WITH_TZ_OVERLOAD = + 'timestamp_to_milliseconds_with_tz'; + +// Duration overloads for time functions. +export const DURATION_TO_HOURS_OVERLOAD = 'duration_to_hours'; +export const DURATION_TO_MINUTES_OVERLOAD = 'duration_to_minutes'; +export const DURATION_TO_SECONDS_OVERLOAD = 'duration_to_seconds'; +export const DURATION_TO_MILLISECONDS_OVERLOAD = 'duration_to_milliseconds'; + +// Type conversion methods and overloads +export const TYPE_CONVERT_INT_OVERLOAD = 'int'; +export const TYPE_CONVERT_UINT_OVERLOAD = 'uint'; +export const TYPE_CONVERT_DOUBLE_OVERLOAD = 'double'; +export const TYPE_CONVERT_BOOL_OVERLOAD = 'bool'; +export const TYPE_CONVERT_STRING_OVERLOAD = 'string'; +export const TYPE_CONVERT_BYTES_OVERLOAD = 'bytes'; +export const TYPE_CONVERT_TIMESTAMP_OVERLOAD = 'timestamp'; +export const TYPE_CONVERT_DURATION_OVERLOAD = 'duration'; +export const TYPE_CONVERT_TYPE_OVERLOAD = 'type'; +export const TYPE_CONVERT_DYN_OVERLOAD = 'dyn'; + +// Int conversion functions. +export const INT_TO_INT_OVERLOAD = 'int64_to_int64'; +export const UINT_TO_INT_OVERLOAD = 'uint64_to_int64'; +export const DOUBLE_TO_INT_OVERLOAD = 'double_to_int64'; +export const STRING_TO_INT_OVERLOAD = 'string_to_int64'; +export const TIMESTAMP_TO_INT_OVERLOAD = 'timestamp_to_int64'; +export const DURATION_TO_INT_OVERLOAD = 'duration_to_int64'; + +// Uint conversion functions. +export const UINT_TO_UINT_OVERLOAD = 'uint64_to_uint64'; +export const INT_TO_UINT_OVERLOAD = 'int64_to_uint64'; +export const DOUBLE_TO_UINT_OVERLOAD = 'double_to_uint64'; +export const STRING_TO_UINT_OVERLOAD = 'string_to_uint64'; + +// Double conversion functions. +export const DOUBLE_TO_DOUBLE_OVERLOAD = 'double_to_double'; +export const INT_TO_DOUBLE_OVERLOAD = 'int64_to_double'; +export const UINT_TO_DOUBLE_OVERLOAD = 'uint64_to_double'; +export const STRING_TO_DOUBLE_OVERLOAD = 'string_to_double'; + +// Bool conversion functions. +export const BOOL_TO_BOOL_OVERLOAD = 'bool_to_bool'; +export const STRING_TO_BOOL_OVERLOAD = 'string_to_bool'; + +// Bytes conversion functions. +export const BYTES_TO_BYTES_OVERLOAD = 'bytes_to_bytes'; +export const STRING_TO_BYTES_OVERLOAD = 'string_to_bytes'; + +// String conversion functions. +export const STRING_TO_STRING_OVERLOAD = 'string_to_string'; +export const BOOL_TO_STRING_OVERLOAD = 'bool_to_string'; +export const INT_TO_STRING_OVERLOAD = 'int64_to_string'; +export const UINT_TO_STRING_OVERLOAD = 'uint64_to_string'; +export const DOUBLE_TO_STRING_OVERLOAD = 'double_to_string'; +export const BYTES_TO_STRING_OVERLOAD = 'bytes_to_string'; +export const TIMESTAMP_TO_STRING_OVERLOAD = 'timestamp_to_string'; +export const DURATION_TO_STRING_OVERLOAD = 'duration_to_string'; + +// Timestamp conversion functions +export const TIMESTAMP_TO_TIMESTAMP_OVERLOAD = 'timestamp_to_timestamp'; +export const STRING_TO_TIMESTAMP_OVERLOAD = 'string_to_timestamp'; +export const INT_TO_TIMESTAMP_OVERLOAD = 'int64_to_timestamp'; + +// Convert duration from string +export const DURATION_TO_DURATION_OVERLOAD = 'duration_to_duration'; +export const STRING_TO_DURATION_OVERLOAD = 'string_to_duration'; +export const INT_TO_DURATION_OVERLOAD = 'int64_to_duration'; + +// Convert to dyn +export const TO_DYN_OVERLOAD = 'to_dyn'; diff --git a/packages/cel/src/lib/standard.ts b/packages/cel/src/lib/standard.ts index de9b726..c8a6229 100644 --- a/packages/cel/src/lib/standard.ts +++ b/packages/cel/src/lib/standard.ts @@ -26,6 +26,12 @@ import { CONDITIONAL_OPERATOR, DIVIDE_OPERATOR, EQUALS_OPERATOR, + GREATER_EQUALS_OPERATOR, + GREATER_OPERATOR, + INDEX_OPERATOR, + IN_OPERATOR, + LESS_EQUALS_OPERATOR, + LESS_OPERATOR, LOGICAL_AND_OPERATOR, LOGICAL_NOT_OPERATOR, LOGICAL_OR_OPERATOR, @@ -43,11 +49,74 @@ import { ADD_LIST_OVERLOAD, ADD_STRING_OVERLOAD, ADD_UINT64_OVERLOAD, + BOOL_TO_BOOL_OVERLOAD, + BOOL_TO_STRING_OVERLOAD, + BYTES_TO_BYTES_OVERLOAD, + BYTES_TO_STRING_OVERLOAD, CONDITIONAL_OVERLOAD, DIVIDE_DOUBLE_OVERLOAD, DIVIDE_INT64_OVERLOAD, DIVIDE_UINT64_OVERLOAD, + DOUBLE_TO_DOUBLE_OVERLOAD, + DOUBLE_TO_INT_OVERLOAD, + DOUBLE_TO_STRING_OVERLOAD, + DOUBLE_TO_UINT_OVERLOAD, EQUALS_OVERLOAD, + GREATER_BOOL_OVERLOAD, + GREATER_BYTES_OVERLOAD, + GREATER_DOUBLE_INT64_OVERLOAD, + GREATER_DOUBLE_OVERLOAD, + GREATER_DOUBLE_UINT64_OVERLOAD, + GREATER_EQUALS_BOOL_OVERLOAD, + GREATER_EQUALS_BYTES_OVERLOAD, + GREATER_EQUALS_DOUBLE_INT64_OVERLOAD, + GREATER_EQUALS_DOUBLE_OVERLOAD, + GREATER_EQUALS_DOUBLE_UINT64_OVERLOAD, + GREATER_EQUALS_INT64_DOUBLE_OVERLOAD, + GREATER_EQUALS_INT64_OVERLOAD, + GREATER_EQUALS_INT64_UINT64_OVERLOAD, + GREATER_EQUALS_STRING_OVERLOAD, + GREATER_EQUALS_UINT64_DOUBLE_OVERLOAD, + GREATER_EQUALS_UINT64_INT64_OVERLOAD, + GREATER_EQUALS_UINT64_OVERLOAD, + GREATER_INT64_DOUBLE_OVERLOAD, + GREATER_INT64_OVERLOAD, + GREATER_INT64_UINT64_OVERLOAD, + GREATER_STRING_OVERLOAD, + GREATER_UINT64_DOUBLE_OVERLOAD, + GREATER_UINT64_INT64_OVERLOAD, + GREATER_UINT64_OVERLOAD, + INDEX_LIST_OVERLOAD, + INDEX_MAP_OVERLOAD, + INT_TO_DOUBLE_OVERLOAD, + INT_TO_INT_OVERLOAD, + INT_TO_STRING_OVERLOAD, + INT_TO_UINT_OVERLOAD, + IN_LIST_OVERLOAD, + IN_MAP_OVERLOAD, + LESS_BOOL_OVERLOAD, + LESS_BYTES_OVERLOAD, + LESS_DOUBLE_INT64_OVERLOAD, + LESS_DOUBLE_OVERLOAD, + LESS_DOUBLE_UINT64_OVERLOAD, + LESS_EQUALS_BYTES_OVERLOAD, + LESS_EQUALS_DOUBLE_INT64_OVERLOAD, + LESS_EQUALS_DOUBLE_OVERLOAD, + LESS_EQUALS_DOUBLE_UINT64_OVERLOAD, + LESS_EQUALS_INT64_DOUBLE_OVERLOAD, + LESS_EQUALS_INT64_OVERLOAD, + LESS_EQUALS_INT64_UINT64_OVERLOAD, + LESS_EQUALS_STRING_OVERLOAD, + LESS_EQUALS_UINT64_DOUBLE_OVERLOAD, + LESS_EQUALS_UINT64_INT64_OVERLOAD, + LESS_EQUALS_UINT64_OVERLOAD, + LESS_INT64_DOUBLE_OVERLOAD, + LESS_INT64_OVERLOAD, + LESS_INT64_UINT64_OVERLOAD, + LESS_STRING_OVERLOAD, + LESS_UINT64_DOUBLE_OVERLOAD, + LESS_UINT64_INT64_OVERLOAD, + LESS_UINT64_OVERLOAD, LOGICAL_AND_OVERLOAD, LOGICAL_NOT_OVERLOAD, LOGICAL_OR_OVERLOAD, @@ -60,20 +129,49 @@ import { NEGATE_INT64_OVERLOAD, NOT_EQUALS_OVERLOAD, NOT_STRICTLY_FALSE_OVERLOAD, + SIZE_BYTES_INST_OVERLOAD, + SIZE_BYTES_OVERLOAD, + SIZE_LIST_INST_OVERLOAD, + SIZE_LIST_OVERLOAD, + SIZE_MAP_INST_OVERLOAD, + SIZE_MAP_OVERLOAD, + SIZE_OVERLOAD, + SIZE_STRING_INST_OVERLOAD, + SIZE_STRING_OVERLOAD, + STRING_TO_BOOL_OVERLOAD, + STRING_TO_BYTES_OVERLOAD, + STRING_TO_DOUBLE_OVERLOAD, + STRING_TO_INT_OVERLOAD, + STRING_TO_STRING_OVERLOAD, + STRING_TO_UINT_OVERLOAD, SUBTRACT_DOUBLE_OVERLOAD, SUBTRACT_INT64_OVERLOAD, SUBTRACT_UINT64_OVERLOAD, + TYPE_CONVERT_BOOL_OVERLOAD, + TYPE_CONVERT_BYTES_OVERLOAD, + TYPE_CONVERT_DOUBLE_OVERLOAD, + TYPE_CONVERT_DYN_OVERLOAD, + TYPE_CONVERT_INT_OVERLOAD, + TYPE_CONVERT_STRING_OVERLOAD, + TYPE_CONVERT_TYPE_OVERLOAD, + TYPE_CONVERT_UINT_OVERLOAD, + UINT_TO_DOUBLE_OVERLOAD, + UINT_TO_INT_OVERLOAD, + UINT_TO_STRING_OVERLOAD, + UINT_TO_UINT_OVERLOAD, } from './overloads'; import { BOOL_TYPE, BYTES_TYPE, DOUBLE_TYPE, + DYN_TYPE, INT64_TYPE, STRING_TYPE, UINT64_TYPE, listType, mapType, typeParamType, + typeType, } from './types'; import { functionDecl } from './utils'; @@ -302,6 +400,544 @@ export const SUBTRACT_FUNCTION_DECL = functionDecl(SUBTRACT_OPERATOR, { ], }); +// Relations operators +export const LESS_FUNCTION_DECL = functionDecl(LESS_OPERATOR, { + overloads: [ + { + overloadId: LESS_BOOL_OVERLOAD, + params: [BOOL_TYPE, BOOL_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: LESS_INT64_OVERLOAD, + params: [INT64_TYPE, INT64_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: LESS_INT64_DOUBLE_OVERLOAD, + params: [INT64_TYPE, DOUBLE_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: LESS_INT64_UINT64_OVERLOAD, + params: [INT64_TYPE, UINT64_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: LESS_UINT64_OVERLOAD, + params: [UINT64_TYPE, UINT64_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: LESS_UINT64_DOUBLE_OVERLOAD, + params: [UINT64_TYPE, DOUBLE_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: LESS_UINT64_INT64_OVERLOAD, + params: [UINT64_TYPE, INT64_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: LESS_DOUBLE_OVERLOAD, + params: [DOUBLE_TYPE, DOUBLE_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: LESS_DOUBLE_INT64_OVERLOAD, + params: [DOUBLE_TYPE, INT64_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: LESS_DOUBLE_UINT64_OVERLOAD, + params: [DOUBLE_TYPE, UINT64_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: LESS_STRING_OVERLOAD, + params: [STRING_TYPE, STRING_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: LESS_BYTES_OVERLOAD, + params: [BYTES_TYPE, BYTES_TYPE], + resultType: BOOL_TYPE, + }, + // TODO: duration & timestamp overloads + ], +}); +export const LESS_EQUALS_FUNCTION_DECL = functionDecl(LESS_EQUALS_OPERATOR, { + overloads: [ + { + overloadId: LESS_EQUALS_INT64_OVERLOAD, + params: [INT64_TYPE, INT64_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: LESS_EQUALS_INT64_DOUBLE_OVERLOAD, + params: [INT64_TYPE, DOUBLE_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: LESS_EQUALS_INT64_UINT64_OVERLOAD, + params: [INT64_TYPE, UINT64_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: LESS_EQUALS_UINT64_OVERLOAD, + params: [UINT64_TYPE, UINT64_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: LESS_EQUALS_UINT64_DOUBLE_OVERLOAD, + params: [UINT64_TYPE, DOUBLE_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: LESS_EQUALS_UINT64_INT64_OVERLOAD, + params: [UINT64_TYPE, INT64_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: LESS_EQUALS_DOUBLE_OVERLOAD, + params: [DOUBLE_TYPE, DOUBLE_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: LESS_EQUALS_DOUBLE_INT64_OVERLOAD, + params: [DOUBLE_TYPE, INT64_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: LESS_EQUALS_DOUBLE_UINT64_OVERLOAD, + params: [DOUBLE_TYPE, UINT64_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: LESS_EQUALS_STRING_OVERLOAD, + params: [STRING_TYPE, STRING_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: LESS_EQUALS_BYTES_OVERLOAD, + params: [BYTES_TYPE, BYTES_TYPE], + resultType: BOOL_TYPE, + }, + // TODO: duration & timestamp overloads + ], +}); +export const GREATER_FUNCTION_DECL = functionDecl(GREATER_OPERATOR, { + overloads: [ + { + overloadId: GREATER_BOOL_OVERLOAD, + params: [BOOL_TYPE, BOOL_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: GREATER_INT64_OVERLOAD, + params: [INT64_TYPE, INT64_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: GREATER_INT64_DOUBLE_OVERLOAD, + params: [INT64_TYPE, DOUBLE_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: GREATER_INT64_UINT64_OVERLOAD, + params: [INT64_TYPE, UINT64_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: GREATER_UINT64_OVERLOAD, + params: [UINT64_TYPE, UINT64_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: GREATER_UINT64_DOUBLE_OVERLOAD, + params: [UINT64_TYPE, DOUBLE_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: GREATER_UINT64_INT64_OVERLOAD, + params: [UINT64_TYPE, INT64_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: GREATER_DOUBLE_OVERLOAD, + params: [DOUBLE_TYPE, DOUBLE_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: GREATER_DOUBLE_INT64_OVERLOAD, + params: [DOUBLE_TYPE, INT64_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: GREATER_DOUBLE_UINT64_OVERLOAD, + params: [DOUBLE_TYPE, UINT64_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: GREATER_STRING_OVERLOAD, + params: [STRING_TYPE, STRING_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: GREATER_BYTES_OVERLOAD, + params: [BYTES_TYPE, BYTES_TYPE], + resultType: BOOL_TYPE, + }, + // TODO: duration & timestamp overloads + ], +}); +export const GREATER_EQUALS_FUNCTION_DECL = functionDecl( + GREATER_EQUALS_OPERATOR, + { + overloads: [ + { + overloadId: GREATER_EQUALS_BOOL_OVERLOAD, + params: [BOOL_TYPE, BOOL_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: GREATER_EQUALS_INT64_OVERLOAD, + params: [INT64_TYPE, INT64_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: GREATER_EQUALS_INT64_DOUBLE_OVERLOAD, + params: [INT64_TYPE, DOUBLE_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: GREATER_EQUALS_INT64_UINT64_OVERLOAD, + params: [INT64_TYPE, UINT64_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: GREATER_EQUALS_UINT64_OVERLOAD, + params: [UINT64_TYPE, UINT64_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: GREATER_EQUALS_UINT64_DOUBLE_OVERLOAD, + params: [UINT64_TYPE, DOUBLE_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: GREATER_EQUALS_UINT64_INT64_OVERLOAD, + params: [UINT64_TYPE, INT64_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: GREATER_EQUALS_DOUBLE_OVERLOAD, + params: [DOUBLE_TYPE, DOUBLE_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: GREATER_EQUALS_DOUBLE_INT64_OVERLOAD, + params: [DOUBLE_TYPE, INT64_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: GREATER_EQUALS_DOUBLE_UINT64_OVERLOAD, + params: [DOUBLE_TYPE, UINT64_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: GREATER_EQUALS_STRING_OVERLOAD, + params: [STRING_TYPE, STRING_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: GREATER_EQUALS_BYTES_OVERLOAD, + params: [BYTES_TYPE, BYTES_TYPE], + resultType: BOOL_TYPE, + }, + // TODO: duration & timestamp overloads + ], + } +); + +// Indexing +export const INDEX_FUNCTION_DECL = functionDecl(INDEX_OPERATOR, { + overloads: [ + { + overloadId: INDEX_MAP_OVERLOAD, + params: [mapOfAB, paramA], + resultType: paramB, + }, + { + overloadId: INDEX_LIST_OVERLOAD, + params: [listOfA, INT64_TYPE], + resultType: paramA, + }, + ], +}); + +// Collections operators +export const IN_FUNCTION_DECL = functionDecl(IN_OPERATOR, { + overloads: [ + { + overloadId: IN_LIST_OVERLOAD, + params: [paramA, listOfA], + resultType: BOOL_TYPE, + }, + { + overloadId: IN_MAP_OVERLOAD, + params: [paramA, mapOfAB], + resultType: BOOL_TYPE, + }, + ], +}); +export const SIZE_FUNCTION_DECL = functionDecl(SIZE_OVERLOAD, { + overloads: [ + { + overloadId: SIZE_BYTES_OVERLOAD, + params: [BYTES_TYPE], + resultType: INT64_TYPE, + }, + { + overloadId: SIZE_BYTES_INST_OVERLOAD, + params: [BYTES_TYPE], + resultType: INT64_TYPE, + }, + { + overloadId: SIZE_LIST_OVERLOAD, + params: [listOfA], + resultType: INT64_TYPE, + }, + { + overloadId: SIZE_LIST_INST_OVERLOAD, + params: [listOfA], + resultType: INT64_TYPE, + }, + { + overloadId: SIZE_MAP_OVERLOAD, + params: [mapOfAB], + resultType: INT64_TYPE, + }, + { + overloadId: SIZE_MAP_INST_OVERLOAD, + params: [mapOfAB], + resultType: INT64_TYPE, + }, + { + overloadId: SIZE_STRING_OVERLOAD, + params: [STRING_TYPE], + resultType: INT64_TYPE, + }, + { + overloadId: SIZE_STRING_INST_OVERLOAD, + params: [STRING_TYPE], + resultType: INT64_TYPE, + }, + ], +}); + +// Type conversions +export const TYPE_CONVERT_TYPE_FUNCTION_DECL = functionDecl( + TYPE_CONVERT_TYPE_OVERLOAD, + { + overloads: [ + { + overloadId: TYPE_CONVERT_TYPE_OVERLOAD, + params: [paramA], + resultType: typeType(paramA), + }, + ], + } +); + +// Bool conversions +export const TYPE_CONVERT_BOOL_FUNCTION_DECL = functionDecl( + TYPE_CONVERT_BOOL_OVERLOAD, + { + overloads: [ + { + overloadId: BOOL_TO_BOOL_OVERLOAD, + params: [BOOL_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: STRING_TO_BOOL_OVERLOAD, + params: [STRING_TYPE], + resultType: BOOL_TYPE, + }, + ], + } +); + +// Bytes conversions +export const TYPE_CONVERT_BYTES_FUNCTION_DECL = functionDecl( + TYPE_CONVERT_BYTES_OVERLOAD, + { + overloads: [ + { + overloadId: BYTES_TO_BYTES_OVERLOAD, + params: [BYTES_TYPE], + resultType: BYTES_TYPE, + }, + { + overloadId: STRING_TO_BYTES_OVERLOAD, + params: [STRING_TYPE], + resultType: BYTES_TYPE, + }, + ], + } +); + +// Double conversions +export const TYPE_CONVERT_DOUBLE_FUNCTION_DECL = functionDecl( + TYPE_CONVERT_DOUBLE_OVERLOAD, + { + overloads: [ + { + overloadId: DOUBLE_TO_DOUBLE_OVERLOAD, + params: [DOUBLE_TYPE], + resultType: DOUBLE_TYPE, + }, + { + overloadId: INT_TO_DOUBLE_OVERLOAD, + params: [INT64_TYPE], + resultType: DOUBLE_TYPE, + }, + { + overloadId: STRING_TO_DOUBLE_OVERLOAD, + params: [STRING_TYPE], + resultType: DOUBLE_TYPE, + }, + { + overloadId: UINT_TO_DOUBLE_OVERLOAD, + params: [UINT64_TYPE], + resultType: DOUBLE_TYPE, + }, + ], + } +); + +// TODO: // Duration conversions + +// Dyn conversions +export const TYPE_CONVERT_DYN_FUNCTION_DECL = functionDecl( + TYPE_CONVERT_DYN_OVERLOAD, + { + overloads: [ + { + overloadId: TYPE_CONVERT_TYPE_OVERLOAD, + params: [paramA], + resultType: DYN_TYPE, + }, + ], + } +); + +// Int conversions +export const TYPE_CONVERT_INT_FUNCTION_DECL = functionDecl( + TYPE_CONVERT_INT_OVERLOAD, + { + overloads: [ + { + overloadId: INT_TO_INT_OVERLOAD, + params: [INT64_TYPE], + resultType: INT64_TYPE, + }, + { + overloadId: DOUBLE_TO_INT_OVERLOAD, + params: [DOUBLE_TYPE], + resultType: INT64_TYPE, + }, + // TODO: duration & timestamp + { + overloadId: STRING_TO_INT_OVERLOAD, + params: [STRING_TYPE], + resultType: INT64_TYPE, + }, + { + overloadId: UINT_TO_INT_OVERLOAD, + params: [UINT64_TYPE], + resultType: INT64_TYPE, + }, + ], + } +); + +// String conversions +export const TYPE_CONVERT_STRING_FUNCTION_DECL = functionDecl( + TYPE_CONVERT_STRING_OVERLOAD, + { + overloads: [ + { + overloadId: STRING_TO_STRING_OVERLOAD, + params: [STRING_TYPE], + resultType: STRING_TYPE, + }, + { + overloadId: BOOL_TO_STRING_OVERLOAD, + params: [BOOL_TYPE], + resultType: STRING_TYPE, + }, + { + overloadId: BYTES_TO_STRING_OVERLOAD, + params: [BYTES_TYPE], + resultType: STRING_TYPE, + }, + { + overloadId: DOUBLE_TO_STRING_OVERLOAD, + params: [DOUBLE_TYPE], + resultType: STRING_TYPE, + }, + { + overloadId: INT_TO_STRING_OVERLOAD, + params: [INT64_TYPE], + resultType: STRING_TYPE, + }, + { + overloadId: UINT_TO_STRING_OVERLOAD, + params: [UINT64_TYPE], + resultType: STRING_TYPE, + }, + // TODO: duration & timestamp + ], + } +); + +// TODO: // Timestamp conversions + +// Uint conversions +export const TYPE_CONVERT_UINT_FUNCTION_DECL = functionDecl( + TYPE_CONVERT_UINT_OVERLOAD, + { + overloads: [ + { + overloadId: UINT_TO_UINT_OVERLOAD, + params: [UINT64_TYPE], + resultType: UINT64_TYPE, + }, + { + overloadId: DOUBLE_TO_UINT_OVERLOAD, + params: [DOUBLE_TYPE], + resultType: UINT64_TYPE, + }, + { + overloadId: INT_TO_UINT_OVERLOAD, + params: [INT64_TYPE], + resultType: UINT64_TYPE, + }, + { + overloadId: STRING_TO_UINT_OVERLOAD, + params: [STRING_TYPE], + resultType: UINT64_TYPE, + }, + ], + } +); + +// TODO: // String functions + +// TODO: // Timestamp / duration functions + export const STANDARD_FUNCTION_DECLARATIONS = [ CONDITIONAL_FUNCTION_DECL, LOGICAL_AND_FUNCTION_DECL, @@ -316,6 +952,21 @@ export const STANDARD_FUNCTION_DECLARATIONS = [ MULTIPLY_FUNCTION_DECL, NEGATE_FUNCTION_DECL, SUBTRACT_FUNCTION_DECL, + LESS_FUNCTION_DECL, + LESS_EQUALS_FUNCTION_DECL, + GREATER_FUNCTION_DECL, + GREATER_EQUALS_FUNCTION_DECL, + INDEX_FUNCTION_DECL, + IN_FUNCTION_DECL, + SIZE_FUNCTION_DECL, + TYPE_CONVERT_TYPE_FUNCTION_DECL, + TYPE_CONVERT_BOOL_FUNCTION_DECL, + TYPE_CONVERT_BYTES_FUNCTION_DECL, + TYPE_CONVERT_DOUBLE_FUNCTION_DECL, + TYPE_CONVERT_DYN_FUNCTION_DECL, + TYPE_CONVERT_INT_FUNCTION_DECL, + TYPE_CONVERT_STRING_FUNCTION_DECL, + TYPE_CONVERT_UINT_FUNCTION_DECL, ]; // TODO: SingletonUnaryBinding, traits diff --git a/packages/cel/src/lib/types.ts b/packages/cel/src/lib/types.ts index bccadeb..84c063d 100644 --- a/packages/cel/src/lib/types.ts +++ b/packages/cel/src/lib/types.ts @@ -168,6 +168,13 @@ export function unwrapOptionalType(val: Type) { return null; } +export function maybeUnwrapOptionalType(val: Type | null | undefined) { + if (isNil(val)) { + return null; + } + return unwrapOptionalType(val); +} + export function wrappedType(value: Type_PrimitiveType) { return create(TypeSchema, { typeKind: { @@ -735,8 +742,25 @@ export function substitute( export function formatCELType(t: Type): string { switch (t.typeKind.case) { case 'primitive': - // TODO: implement - return enumToJson(Type_PrimitiveTypeSchema, t.typeKind.value) as string; + switch (t.typeKind.value) { + case Type_PrimitiveType.BOOL: + return 'bool'; + case Type_PrimitiveType.BYTES: + return 'bytes'; + case Type_PrimitiveType.DOUBLE: + return 'double'; + case Type_PrimitiveType.INT64: + return 'int'; + case Type_PrimitiveType.STRING: + return 'string'; + case Type_PrimitiveType.UINT64: + return 'uint'; + default: + return enumToJson( + Type_PrimitiveTypeSchema, + t.typeKind.value + ) as string; + } case 'wellKnown': // TODO: implement return enumToJson(Type_WellKnownTypeSchema, t.typeKind.value) as string; diff --git a/packages/cel/src/lib/utils.ts b/packages/cel/src/lib/utils.ts index e3a5b73..e5c23e9 100644 --- a/packages/cel/src/lib/utils.ts +++ b/packages/cel/src/lib/utils.ts @@ -7,6 +7,7 @@ import { Decl_IdentDeclSchema, ReferenceSchema, Type_PrimitiveType, + Type_WellKnownType, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; import { Constant, @@ -638,3 +639,22 @@ export function scalarTypeToPrimitiveType(scalar: ScalarType) { return DYN_TYPE; } } + +/** + * Converts a CEL WellKnwonType to a string. + * + * @param type the WellKnownType + * @returns a string representation of the WellKnownType (or null if not found) + */ +export function getWellKNownTypeName(type: Type_WellKnownType): string | null { + switch (type) { + case Type_WellKnownType.ANY: + return 'google.protobuf.Any'; + case Type_WellKnownType.DURATION: + return 'google.protobuf.Duration'; + case Type_WellKnownType.TIMESTAMP: + return 'google.protobuf.Timestamp'; + default: + return null; + } +} From c381508d8dd5c7c57d0c79c32616e8660926326a Mon Sep 17 00:00:00 2001 From: jafaircl Date: Mon, 7 Oct 2024 21:44:30 -0400 Subject: [PATCH 20/34] feat(cel): comprehension initial commit --- packages/cel/src/lib/checker.spec.ts | 344 +++++++++++++++--- packages/cel/src/lib/checker.ts | 128 ++++++- packages/cel/src/lib/environment.ts | 34 +- packages/cel/src/lib/errors.ts | 30 +- packages/cel/src/lib/standard.ts | 502 ++++++++++++++++++++++++++- packages/cel/src/lib/types.ts | 106 +++++- 6 files changed, 1052 insertions(+), 92 deletions(-) diff --git a/packages/cel/src/lib/checker.spec.ts b/packages/cel/src/lib/checker.spec.ts index f042f20..2aca959 100644 --- a/packages/cel/src/lib/checker.spec.ts +++ b/packages/cel/src/lib/checker.spec.ts @@ -48,35 +48,40 @@ interface TestInfo { // opts []Option } -const defaultEnv = STANDARD_ENV.extend({ - declarations: [ - functionDecl('fg_s', { - overloads: [ - { - overloadId: 'fg_s_0', - resultType: STRING_TYPE, - }, - ], - }), - functionDecl('fi_s_s', { - overloads: [ - { - overloadId: 'fi_s_s_0', - params: [STRING_TYPE], - resultType: STRING_TYPE, - isInstanceFunction: true, - }, - ], - }), - identDecl('is', { type: STRING_TYPE }), - identDecl('ii', { type: INT64_TYPE }), - identDecl('iu', { type: UINT64_TYPE }), - identDecl('iz', { type: BOOL_TYPE }), - identDecl('ib', { type: BYTES_TYPE }), - identDecl('id', { type: DOUBLE_TYPE }), - identDecl('ix', { type: NULL_TYPE }), - ], -}); +// TODO: The package name for TestAllTypes is different in cel-go because we have to import from a different package. + +function getDefaultEnv() { + return STANDARD_ENV().extend({ + registry: createMutableRegistry(TestAllTypesSchema), + declarations: [ + functionDecl('fg_s', { + overloads: [ + { + overloadId: 'fg_s_0', + resultType: STRING_TYPE, + }, + ], + }), + functionDecl('fi_s_s', { + overloads: [ + { + overloadId: 'fi_s_s_0', + params: [STRING_TYPE], + resultType: STRING_TYPE, + isInstanceFunction: true, + }, + ], + }), + identDecl('is', { type: STRING_TYPE }), + identDecl('ii', { type: INT64_TYPE }), + identDecl('iu', { type: UINT64_TYPE }), + identDecl('iz', { type: BOOL_TYPE }), + identDecl('ib', { type: BYTES_TYPE }), + identDecl('id', { type: DOUBLE_TYPE }), + identDecl('ix', { type: NULL_TYPE }), + ], + }); +} const testCases: TestInfo[] = [ // Development tests @@ -141,49 +146,49 @@ const testCases: TestInfo[] = [ in: `is`, out: `is~string^is`, outType: STRING_TYPE, - env: defaultEnv, + env: getDefaultEnv(), }, { in: `ii`, out: `ii~int^ii`, outType: INT64_TYPE, - env: defaultEnv, + env: getDefaultEnv(), }, { in: `iu`, out: `iu~uint^iu`, outType: UINT64_TYPE, - env: defaultEnv, + env: getDefaultEnv(), }, { in: `iz`, out: `iz~bool^iz`, outType: BOOL_TYPE, - env: defaultEnv, + env: getDefaultEnv(), }, { in: `id`, out: `id~double^id`, outType: DOUBLE_TYPE, - env: defaultEnv, + env: getDefaultEnv(), }, { in: `ix`, out: `ix~null^ix`, outType: NULL_TYPE, - env: defaultEnv, + env: getDefaultEnv(), }, { in: `ib`, out: `ib~bytes^ib`, outType: BYTES_TYPE, - env: defaultEnv, + env: getDefaultEnv(), }, { in: `id`, out: `id~double^id`, outType: DOUBLE_TYPE, - env: defaultEnv, + env: getDefaultEnv(), }, { in: `[]`, @@ -213,31 +218,31 @@ const testCases: TestInfo[] = [ in: `fg_s()`, out: `fg_s()~string^fg_s_0`, outType: STRING_TYPE, - env: defaultEnv, + env: getDefaultEnv(), }, { in: `is.fi_s_s()`, out: `is~string^is.fi_s_s()~string^fi_s_s_0`, outType: STRING_TYPE, - env: defaultEnv, + env: getDefaultEnv(), }, { in: `1 + 2`, out: `_+_(1~int, 2~int)~int^add_int64`, outType: INT64_TYPE, - env: defaultEnv, + env: getDefaultEnv(), }, { in: `1 + ii`, out: `_+_(1~int, ii~int^ii)~int^add_int64`, outType: INT64_TYPE, - env: defaultEnv, + env: getDefaultEnv(), }, { in: `[1] + [2]`, out: `_+_([1~int]~list(int), [2~int]~list(int))~list(int)^add_list`, outType: listType({ elemType: INT64_TYPE }), - env: defaultEnv, + env: getDefaultEnv(), }, { in: `[] + [1,2,3,] + [4]`, @@ -287,9 +292,8 @@ _+_( single_int64 : 2~int }~google.api.expr.test.v1.proto3.TestAllTypes^google.api.expr.test.v1.proto3.TestAllTypes`, outType: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), - env: defaultEnv.extend({ + env: getDefaultEnv().extend({ container: new CELContainer('google.api.expr.test.v1.proto3'), - registry: createMutableRegistry(TestAllTypesSchema), }), }, { @@ -300,9 +304,8 @@ _+_( ERROR: :1:26: expected type of field 'single_int32' is 'int' but provided type is 'uint' | TestAllTypes{single_int32: 1u} | .........................^`, - env: defaultEnv.extend({ + env: getDefaultEnv().extend({ container: new CELContainer('google.api.expr.test.v1.proto3'), - registry: createMutableRegistry(TestAllTypesSchema), }), }, { @@ -313,9 +316,8 @@ ERROR: :1:26: expected type of field 'single_int32' is 'int' but provided ERROR: :1:40: undefined field 'undefined' | TestAllTypes{single_int32: 1, undefined: 2} | .......................................^`, - env: defaultEnv.extend({ + env: getDefaultEnv().extend({ container: new CELContainer('google.api.expr.test.v1.proto3'), - registry: createMutableRegistry(TestAllTypesSchema), }), }, { @@ -323,7 +325,7 @@ ERROR: :1:40: undefined field 'undefined' out: ` _==_(size(x~list(int)^x)~int^size_list, x~list(int)^x.size()~int^list_size) ~bool^equals`, - env: defaultEnv.extend({ + env: getDefaultEnv().extend({ declarations: [ identDecl('x', { type: listType({ elemType: INT64_TYPE }) }), ], @@ -416,13 +418,244 @@ _!=_(_-_(_+_(1~double, _*_(2~double, 3~double)~double^multiply_double) ~bool^equals`, outType: BOOL_TYPE, }, + { + in: `x.single_int32 != null`, + env: getDefaultEnv().extend({ + declarations: [ + identDecl('x', { + type: messageType('google.api.expr.test.v1.proto3.Proto2Message'), + }), + ], + }), + err: ` +ERROR: :1:2: unexpected failed resolution of 'google.api.expr.test.v1.proto3.Proto2Message' +| x.single_int32 != null +| .^ +`, + }, + // TODO: these 2 tests fail with "found no matching overload for '_[_]' applied to '(google.protobuf.Struct, string) -> unknown'" + { + // TODO: this test container is different than in cel-go because we have to import from a different package + in: `x.single_value + 1 / x.single_struct.y == 23`, + env: getDefaultEnv().extend({ + declarations: [ + identDecl('x', { + type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + }), + ], + }), + out: `_==_( + _+_( + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_value~dyn, + _/_( + 1~int, + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_struct~map(string, dyn).y~dyn + )~int^divide_int64 + )~int^add_int64, + 23~int + )~bool^equals`, + outType: BOOL_TYPE, + }, + { + // TODO: this test container is different than in cel-go because we have to import from a different package + in: `x.single_value[23] + x.single_struct['y']`, + env: getDefaultEnv().extend({ + declarations: [ + identDecl('x', { + type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + }), + ], + }), + out: `_+_( + _[_]( + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_value~dyn, + 23~int + )~dyn^index_list|index_map, + _[_]( + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_struct~map(string, dyn), + "y"~string + )~dyn^index_map + )~dyn^add_bytes|add_double|add_duration_duration|add_duration_timestamp|add_int64|add_list|add_string|add_timestamp_duration|add_uint64 + `, + outType: DYN_TYPE, + }, + // { // TODO: calling the enum like this doesn't work + // in: `TestAllTypes.NestedEnum.BAR != 99`, + // container: 'google.api.expr.test.v1.proto3', + // env: getDefaultEnv().extend({ + // container: new CELContainer('google.api.expr.test.v1.proto3'), + // }), + // out: `_!=_(google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum.BAR + // ~int^google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum.BAR, + // 99~int) + // ~bool^not_equals`, + // outType: BOOL_TYPE, + // }, + { + in: `size([] + [1])`, + out: `size(_+_([]~list(int), [1~int]~list(int))~list(int)^add_list)~int^size_list`, + outType: INT64_TYPE, + }, + { + in: `x["claims"]["groups"][0].name == "dummy" +&& x.claims["exp"] == y[1].time +&& x.claims.structured == {'key': z} +&& z == 1.0`, + out: `_&&_( + _&&_( + _==_( + _[_]( + _[_]( + _[_]( + x~map(string, dyn)^x, + "claims"~string + )~dyn^index_map, + "groups"~string + )~list(dyn)^index_map, + 0~int + )~dyn^index_list.name~dyn, + "dummy"~string + )~bool^equals, + _==_( + _[_]( + x~map(string, dyn)^x.claims~dyn, + "exp"~string + )~dyn^index_map, + _[_]( + y~list(dyn)^y, + 1~int + )~dyn^index_list.time~dyn + )~bool^equals + )~bool^logical_and, + _&&_( + _==_( + x~map(string, dyn)^x.claims~dyn.structured~dyn, + { + "key"~string:z~dyn^z + }~map(string, dyn) + )~bool^equals, + _==_( + z~dyn^z, + 1~double + )~bool^equals + )~bool^logical_and +)~bool^logical_and`, + env: getDefaultEnv().extend({ + declarations: [ + identDecl('x', { type: messageType('google.protobuf.Struct') }), + identDecl('y', { type: messageType('google.protobuf.ListValue') }), + identDecl('z', { type: messageType('google.protobuf.Value') }), + ], + }), + outType: BOOL_TYPE, + }, + // { // TODO: this doesn't work + // in: `x + y`, + // env: getDefaultEnv().extend({ + // declarations: [ + // identDecl('x', { + // type: listType({ + // elemType: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + // }), + // }), + // identDecl('y', { type: listType({ elemType: INT64_TYPE }) }), + // ], + // }), + // err: ` + // ERROR: :1:3: found no matching overload for '_+_' applied to '(list(google.api.expr.test.v1.proto3.TestAllTypes), list(int))' + // | x + y + // | ..^ + // `, + // }, + { + in: `x[1u]`, + env: getDefaultEnv().extend({ + declarations: [ + identDecl('x', { + type: listType({ + elemType: messageType( + 'google.api.expr.test.v1.proto3.TestAllTypes' + ), + }), + }), + ], + }), + err: ` +ERROR: :1:2: found no matching overload for '_[_]' applied to '(list(google.api.expr.test.v1.proto3.TestAllTypes), uint)' + | x[1u] + | .^ +`, + }, + { + in: `(x + x)[1].single_int32 == size(x)`, + env: getDefaultEnv().extend({ + declarations: [ + identDecl('x', { + type: listType({ + elemType: messageType( + 'google.api.expr.test.v1.proto3.TestAllTypes' + ), + }), + }), + ], + }), + out: ` +_==_(_[_](_+_(x~list(google.api.expr.test.v1.proto3.TestAllTypes)^x, + x~list(google.api.expr.test.v1.proto3.TestAllTypes)^x) + ~list(google.api.expr.test.v1.proto3.TestAllTypes)^add_list, + 1~int) + ~google.api.expr.test.v1.proto3.TestAllTypes^index_list + . + single_int32 + ~int, +size(x~list(google.api.expr.test.v1.proto3.TestAllTypes)^x)~int^size_list) +~bool^equals +`, + outType: BOOL_TYPE, + }, + { + in: `x.repeated_int64[x.single_int32] == 23`, + env: getDefaultEnv().extend({ + declarations: [ + identDecl('x', { + type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + }), + ], + }), + out: ` +_==_(_[_](x~google.api.expr.test.v1.proto3.TestAllTypes^x.repeated_int64~list(int), + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_int32~int) +~int^index_list, +23~int) +~bool^equals`, + outType: BOOL_TYPE, + }, + + { + in: `size(x.map_int64_nested_type) == 0`, + env: getDefaultEnv().extend({ + declarations: [ + identDecl('x', { + type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + }), + ], + }), + out: ` +_==_(size(x~google.api.expr.test.v1.proto3.TestAllTypes^x.map_int64_nested_type + ~map(int, google.api.expr.test.v1.proto3.NestedTestAllTypes)) +~int^size_map, +0~int) +~bool^equals +`, + outType: BOOL_TYPE, + }, ]; describe('CELChecker', () => { for (const testCase of testCases) { - it(`should parse ${testCase.in}`, () => { + it(`should check ${testCase.in}`, () => { const container = new CELContainer(testCase.container ?? ''); - const env = testCase.env ?? STANDARD_ENV.extend({ container }); + const env = testCase.env ?? getDefaultEnv().extend({ container }); const parser = new CELParser(testCase.in); const parsed = parser.parse(); if (isNil(parsed.expr)) { @@ -435,6 +668,15 @@ describe('CELChecker', () => { expect(result.typeMap[parsed.expr.id.toString()]).toEqual( testCase.outType ); + if ( + testCase.outType !== ERROR_TYPE && + !testCase.err && + checker.errors.errors.errors.length > 0 + ) { + throw new Error( + 'Unexpected errors: ' + checker.errors.toDisplayString() + ); + } } catch (e) { console.log(checker.errors.toDisplayString()); throw e; diff --git a/packages/cel/src/lib/checker.ts b/packages/cel/src/lib/checker.ts index d1a0518..1460341 100644 --- a/packages/cel/src/lib/checker.ts +++ b/packages/cel/src/lib/checker.ts @@ -48,6 +48,7 @@ import { primitiveType, substitute, typeParamType, + unwrapFunctionType, unwrapOptionalType, wellKnownType, } from './types'; @@ -56,6 +57,7 @@ import { functionReference, getLocationByOffset, getWellKNownTypeName, + identDecl, identReference, mapToObject, toQualifiedName, @@ -123,6 +125,9 @@ export class CELChecker { this.checkCreateStruct(expr); } break; + case 'comprehensionExpr': + this.checkComprehension(expr); + break; default: this.#errors.reportUnexpectedAstTypeError( expr.id, @@ -204,6 +209,8 @@ export class CELChecker { expr.id, identReference(ident.name, ident.declKind.value.value!) ); + // Overwrite the identifier with its fully qualified name. + expr.exprKind.value.name = toQualifiedName(expr); return; } this.setType(expr.id, ERROR_TYPE); @@ -305,12 +312,22 @@ export class CELChecker { if (!isNil(fieldType)) { resultType = fieldType; break; + } else { + const msg = this.env.lookupStructType(targetType.typeKind.value); + if (isNil(msg)) { + this.#errors.reportUnexpectedFailedResolution( + expr.id, + this.getLocationById(expr.id), + targetType.typeKind.value + ); + } else { + this.#errors.reportUndefinedField( + expr.id, + this.getLocationById(expr.id), + field + ); + } } - this.#errors.reportUndefinedField( - expr.id, - this.getLocationById(expr.id), - field - ); break; case 'typeParam': // Set the operand type to DYN to prevent assignment to a potentially @@ -542,7 +559,7 @@ export class CELChecker { // First matching overload, determines result type. const fnResultType = substitute( this.#mapping, - overload.resultType!, + unwrapFunctionType(overloadType)!.resultType!, false ); if (isNil(resultType)) { @@ -727,11 +744,20 @@ export class CELChecker { if (!isNil(ft)) { fieldType = ft; } else { - this.#errors.reportUndefinedField( - field.value!.id, - this.getLocationById(field.id), - field.keyKind.value - ); + const msg = this.env.lookupStructType(typeName); + if (isNil(msg)) { + this.#errors.reportUnexpectedFailedResolution( + field.value!.id, + this.getLocationById(field.id), + typeName + ); + } else { + this.#errors.reportUndefinedField( + field.value!.id, + this.getLocationById(field.id), + field.keyKind.value + ); + } } let valType = this.getType(field.value!.id); @@ -760,6 +786,75 @@ export class CELChecker { } } + checkComprehension(expr: Expr) { + if (expr.exprKind.case !== 'comprehensionExpr') { + // This should never happen + throw new Error('expr.exprKind.case is not comprehensionExpr'); + } + const comp = expr.exprKind.value; + this.check(comp.iterRange); + this.check(comp.accuInit); + const accuType = this.getType(comp.accuInit!.id); + const rangeType = substitute( + this.#mapping, + this.getType(comp.iterRange!.id)!, + false + ); + let varType: Type | undefined = undefined; + switch (rangeType.typeKind.case) { + case 'listType': + varType = rangeType.typeKind.value.elemType; + break; + case 'mapType': + // Ranges over the keys. + varType = rangeType.typeKind.value.keyType; + break; + case 'dyn': + case 'error': + case 'typeParam': + // Set the range type to DYN to prevent assignment to a potentially + // incorrect type at a later point in type-checking. The isAssignable + // call will update the type substitutions for the type param under the + // covers. + this._isAssignable(DYN_TYPE, rangeType); + // Set the range iteration variable to type DYN as well. + varType = DYN_TYPE; + break; + default: + this.#errors.reportNotAComprehensionRange( + comp.iterRange!.id, + this.getLocationById(comp.iterRange!.id), + rangeType + ); + varType = ERROR_TYPE; + } + // Create a scope for the comprehension since it has a local accumulation + // variable. This scope will contain the accumulation variable used to + // compute the result. + // TODO: scopes + // c.env = c.env.enterScope(); + this.env.addIdent(identDecl(comp.accuVar, { type: accuType })); + // Create a block scope for the loop. + // TODO: scopes + // c.env = c.env.enterScope(); + this.env.addIdent(identDecl(comp.iterVar, { type: varType })); + // Check the variable references in the condition and step. + this.check(comp.loopCondition); + this._assertType(comp.loopCondition!, BOOL_TYPE); + this.check(comp.loopStep); + this._assertType(comp.loopStep!, accuType!); + // Exit the loop's block scope before checking the result. + // TODO: scopes + // c.env = c.env.exitScope(); + this.check(comp.result); + // Exit the comprehension scope. + // c.env = c.env.exitScope(); + this.setType( + expr.id, + substitute(this.#mapping, this.getType(comp.result!.id)!, false) + ); + } + setType(id: bigint, type: Type) { this.#typeMap.set(id.toString(), type); } @@ -832,4 +927,15 @@ export class CELChecker { } return false; } + + private _assertType(e: Expr, t: Type) { + if (!this._isAssignable(t, this.getType(e.id)!)) { + this.#errors.reportTypeMismatch( + e.id, + this.getLocationById(e.id), + t, + this.getType(e.id)! + ); + } + } } diff --git a/packages/cel/src/lib/environment.ts b/packages/cel/src/lib/environment.ts index ad93339..39eb5b4 100644 --- a/packages/cel/src/lib/environment.ts +++ b/packages/cel/src/lib/environment.ts @@ -315,6 +315,23 @@ export class CELEnvironment { return null; } + /** + * Look up a message descriptor by name. + * + * @param name the name of the message to look up. + * @returns the message descriptor, or null if not found. + */ + lookupStructType(name: string): DescMessage | null { + const candidateNames = this.container.resolveCandidateNames(name); + for (const candidateName of candidateNames) { + const message = this.findMessage(candidateName); + if (!isNil(message)) { + return message; + } + } + return null; + } + /** * Look up the type of a field in a message. * @@ -323,6 +340,11 @@ export class CELEnvironment { * @returns the field type, or null if not found. */ lookupFieldType(message: string, field: string) { + // Make sure the message exists + const m = this.lookupStructType(message); + if (isNil(m)) { + return null; + } const candidateNames = this.container.resolveCandidateNames(message); for (const candidateName of candidateNames) { const fieldType = this.findMessageFieldType(candidateName, field); @@ -344,8 +366,10 @@ export class CELEnvironment { } } -export const STANDARD_ENV = new CELEnvironment({ - container: new CELContainer(), - registry: createMutableRegistry(...standardTypes), - declarations: [...STANDARD_FUNCTION_DECLARATIONS], -}); +export function STANDARD_ENV() { + return new CELEnvironment({ + container: new CELContainer(), + registry: createMutableRegistry(...standardTypes), + declarations: [...STANDARD_FUNCTION_DECLARATIONS], + }); +} diff --git a/packages/cel/src/lib/errors.ts b/packages/cel/src/lib/errors.ts index 768af02..ae177ab 100644 --- a/packages/cel/src/lib/errors.ts +++ b/packages/cel/src/lib/errors.ts @@ -13,7 +13,7 @@ import { create, createRegistry } from '@bufbuild/protobuf'; import { anyPack, anyUnpack } from '@bufbuild/protobuf/wkt'; import { ErrorListener, RecognitionException, Recognizer, Token } from 'antlr4'; import { CELContainer } from './container'; -import { Location, formatCELType } from './types'; +import { Location, formatCELType, formatFunctionDeclType } from './types'; export class Errors { public readonly errors = create(ErrorSetSchema); @@ -124,13 +124,11 @@ export class Errors { args: Type[], isInstance: boolean ) { - // TODO - // signature := formatFunctionDeclType(nil, args, isInstance) - const signature = ''; + const signature = formatFunctionDeclType(null, args, isInstance); return this.reportErrorAtId( id, location, - `ound no matching overload for '${name}' applied to '${signature}'` + `found no matching overload for '${name}' applied to '${signature}'` ); } @@ -162,6 +160,28 @@ export class Errors { ); } + public reportUnexpectedFailedResolution( + id: bigint, + location: Location, + name: string + ) { + return this.reportErrorAtId( + id, + location, + `unexpected failed resolution of '${name}'` + ); + } + + public reportNotAComprehensionRange(id: bigint, location: Location, t: Type) { + return this.reportErrorAtId( + id, + location, + `expression of type '${formatCELType( + t + )}' cannot be range of a comprehension (must be list, map, or dynamic)` + ); + } + public toDisplayString() { let hasRecursionError = false; const errors = []; diff --git a/packages/cel/src/lib/standard.ts b/packages/cel/src/lib/standard.ts index c8a6229..8786eeb 100644 --- a/packages/cel/src/lib/standard.ts +++ b/packages/cel/src/lib/standard.ts @@ -45,15 +45,20 @@ import { import { ADD_BYTES_OVERLOAD, ADD_DOUBLE_OVERLOAD, + ADD_DURATION_DURATION_OVERLOAD, + ADD_DURATION_TIMESTAMP_OVERLOAD, ADD_INT64_OVERLOAD, ADD_LIST_OVERLOAD, ADD_STRING_OVERLOAD, + ADD_TIMESTAMP_DURATION_OVERLOAD, ADD_UINT64_OVERLOAD, BOOL_TO_BOOL_OVERLOAD, BOOL_TO_STRING_OVERLOAD, BYTES_TO_BYTES_OVERLOAD, BYTES_TO_STRING_OVERLOAD, CONDITIONAL_OVERLOAD, + CONTAINS_OVERLOAD, + CONTAINS_STRING_OVERLOAD, DIVIDE_DOUBLE_OVERLOAD, DIVIDE_INT64_OVERLOAD, DIVIDE_UINT64_OVERLOAD, @@ -61,21 +66,33 @@ import { DOUBLE_TO_INT_OVERLOAD, DOUBLE_TO_STRING_OVERLOAD, DOUBLE_TO_UINT_OVERLOAD, + DURATION_TO_DURATION_OVERLOAD, + DURATION_TO_HOURS_OVERLOAD, + DURATION_TO_INT_OVERLOAD, + DURATION_TO_MILLISECONDS_OVERLOAD, + DURATION_TO_MINUTES_OVERLOAD, + DURATION_TO_SECONDS_OVERLOAD, + DURATION_TO_STRING_OVERLOAD, + ENDS_WITH_OVERLOAD, + ENDS_WITH_STRING_OVERLOAD, EQUALS_OVERLOAD, GREATER_BOOL_OVERLOAD, GREATER_BYTES_OVERLOAD, GREATER_DOUBLE_INT64_OVERLOAD, GREATER_DOUBLE_OVERLOAD, GREATER_DOUBLE_UINT64_OVERLOAD, + GREATER_DURATION_OVERLOAD, GREATER_EQUALS_BOOL_OVERLOAD, GREATER_EQUALS_BYTES_OVERLOAD, GREATER_EQUALS_DOUBLE_INT64_OVERLOAD, GREATER_EQUALS_DOUBLE_OVERLOAD, GREATER_EQUALS_DOUBLE_UINT64_OVERLOAD, + GREATER_EQUALS_DURATION_OVERLOAD, GREATER_EQUALS_INT64_DOUBLE_OVERLOAD, GREATER_EQUALS_INT64_OVERLOAD, GREATER_EQUALS_INT64_UINT64_OVERLOAD, GREATER_EQUALS_STRING_OVERLOAD, + GREATER_EQUALS_TIMESTAMP_OVERLOAD, GREATER_EQUALS_UINT64_DOUBLE_OVERLOAD, GREATER_EQUALS_UINT64_INT64_OVERLOAD, GREATER_EQUALS_UINT64_OVERLOAD, @@ -83,14 +100,17 @@ import { GREATER_INT64_OVERLOAD, GREATER_INT64_UINT64_OVERLOAD, GREATER_STRING_OVERLOAD, + GREATER_TIMESTAMP_OVERLOAD, GREATER_UINT64_DOUBLE_OVERLOAD, GREATER_UINT64_INT64_OVERLOAD, GREATER_UINT64_OVERLOAD, INDEX_LIST_OVERLOAD, INDEX_MAP_OVERLOAD, INT_TO_DOUBLE_OVERLOAD, + INT_TO_DURATION_OVERLOAD, INT_TO_INT_OVERLOAD, INT_TO_STRING_OVERLOAD, + INT_TO_TIMESTAMP_OVERLOAD, INT_TO_UINT_OVERLOAD, IN_LIST_OVERLOAD, IN_MAP_OVERLOAD, @@ -99,14 +119,17 @@ import { LESS_DOUBLE_INT64_OVERLOAD, LESS_DOUBLE_OVERLOAD, LESS_DOUBLE_UINT64_OVERLOAD, + LESS_DURATION_OVERLOAD, LESS_EQUALS_BYTES_OVERLOAD, LESS_EQUALS_DOUBLE_INT64_OVERLOAD, LESS_EQUALS_DOUBLE_OVERLOAD, LESS_EQUALS_DOUBLE_UINT64_OVERLOAD, + LESS_EQUALS_DURATION_OVERLOAD, LESS_EQUALS_INT64_DOUBLE_OVERLOAD, LESS_EQUALS_INT64_OVERLOAD, LESS_EQUALS_INT64_UINT64_OVERLOAD, LESS_EQUALS_STRING_OVERLOAD, + LESS_EQUALS_TIMESTAMP_OVERLOAD, LESS_EQUALS_UINT64_DOUBLE_OVERLOAD, LESS_EQUALS_UINT64_INT64_OVERLOAD, LESS_EQUALS_UINT64_OVERLOAD, @@ -114,12 +137,15 @@ import { LESS_INT64_OVERLOAD, LESS_INT64_UINT64_OVERLOAD, LESS_STRING_OVERLOAD, + LESS_TIMESTAMP_OVERLOAD, LESS_UINT64_DOUBLE_OVERLOAD, LESS_UINT64_INT64_OVERLOAD, LESS_UINT64_OVERLOAD, LOGICAL_AND_OVERLOAD, LOGICAL_NOT_OVERLOAD, LOGICAL_OR_OVERLOAD, + MATCHES_OVERLOAD, + MATCHES_STRING_OVERLOAD, MODULO_INT64_OVERLOAD, MODULO_UINT64_OVERLOAD, MULTIPLY_DOUBLE_OVERLOAD, @@ -138,21 +164,63 @@ import { SIZE_OVERLOAD, SIZE_STRING_INST_OVERLOAD, SIZE_STRING_OVERLOAD, + STARTS_WITH_OVERLOAD, + STARTS_WITH_STRING_OVERLOAD, STRING_TO_BOOL_OVERLOAD, STRING_TO_BYTES_OVERLOAD, STRING_TO_DOUBLE_OVERLOAD, + STRING_TO_DURATION_OVERLOAD, STRING_TO_INT_OVERLOAD, STRING_TO_STRING_OVERLOAD, + STRING_TO_TIMESTAMP_OVERLOAD, STRING_TO_UINT_OVERLOAD, SUBTRACT_DOUBLE_OVERLOAD, + SUBTRACT_DURATION_DURATION_OVERLOAD, SUBTRACT_INT64_OVERLOAD, + SUBTRACT_TIMESTAMP_DURATION_OVERLOAD, + SUBTRACT_TIMESTAMP_TIMESTAMP_OVERLOAD, SUBTRACT_UINT64_OVERLOAD, + TIMESTAMP_TO_DAY_OF_MONTH_ONE_BASED_OVERLOAD, + TIMESTAMP_TO_DAY_OF_MONTH_ONE_BASED_WITH_TZ_OVERLOAD, + TIMESTAMP_TO_DAY_OF_MONTH_ZERO_BASED_OVERLOAD, + TIMESTAMP_TO_DAY_OF_MONTH_ZERO_BASED_WITH_TZ_OVERLOAD, + TIMESTAMP_TO_DAY_OF_WEEK_OVERLOAD, + TIMESTAMP_TO_DAY_OF_WEEK_WITH_TZ_OVERLOAD, + TIMESTAMP_TO_DAY_OF_YEAR_OVERLOAD, + TIMESTAMP_TO_DAY_OF_YEAR_WITH_TZ_OVERLOAD, + TIMESTAMP_TO_HOURS_OVERLOAD, + TIMESTAMP_TO_HOURS_WITH_TZ_OVERLOAD, + TIMESTAMP_TO_INT_OVERLOAD, + TIMESTAMP_TO_MILLISECONDS_OVERLOAD, + TIMESTAMP_TO_MILLISECONDS_WITH_TZ_OVERLOAD, + TIMESTAMP_TO_MINUTES_OVERLOAD, + TIMESTAMP_TO_MINUTES_WITH_TZ_OVERLOAD, + TIMESTAMP_TO_MONTH_OVERLOAD, + TIMESTAMP_TO_MONTH_WITH_TZ_OVERLOAD, + TIMESTAMP_TO_SECONDS_OVERLOAD, + TIMESTAMP_TO_SECONDS_WITH_TZ_OVERLOAD, + TIMESTAMP_TO_STRING_OVERLOAD, + TIMESTAMP_TO_TIMESTAMP_OVERLOAD, + TIMESTAMP_TO_YEAR_OVERLOAD, + TIMESTAMP_TO_YEAR_WITH_TZ_OVERLOAD, + TIME_GET_DATE_OVERLOAD, + TIME_GET_DAY_OF_MONTH_OVERLOAD, + TIME_GET_DAY_OF_WEEK_OVERLOAD, + TIME_GET_DAY_OF_YEAR_OVERLOAD, + TIME_GET_FULL_YEAR_OVERLOAD, + TIME_GET_HOURS_OVERLOAD, + TIME_GET_MILLISECONDS_OVERLOAD, + TIME_GET_MINUTES_OVERLOAD, + TIME_GET_MONTH_OVERLOAD, + TIME_GET_SECONDS_OVERLOAD, TYPE_CONVERT_BOOL_OVERLOAD, TYPE_CONVERT_BYTES_OVERLOAD, TYPE_CONVERT_DOUBLE_OVERLOAD, + TYPE_CONVERT_DURATION_OVERLOAD, TYPE_CONVERT_DYN_OVERLOAD, TYPE_CONVERT_INT_OVERLOAD, TYPE_CONVERT_STRING_OVERLOAD, + TYPE_CONVERT_TIMESTAMP_OVERLOAD, TYPE_CONVERT_TYPE_OVERLOAD, TYPE_CONVERT_UINT_OVERLOAD, UINT_TO_DOUBLE_OVERLOAD, @@ -164,9 +232,11 @@ import { BOOL_TYPE, BYTES_TYPE, DOUBLE_TYPE, + DURATION_TYPE, DYN_TYPE, INT64_TYPE, STRING_TYPE, + TIMESTAMP_TYPE, UINT64_TYPE, listType, mapType, @@ -290,7 +360,21 @@ export const ADD_FUNCTION_DECL = functionDecl(ADD_OPERATOR, { params: [DOUBLE_TYPE, DOUBLE_TYPE], resultType: DOUBLE_TYPE, }, - // TODO: duration and timestamp overloads + { + overloadId: ADD_DURATION_DURATION_OVERLOAD, + params: [DURATION_TYPE, DURATION_TYPE], + resultType: DURATION_TYPE, + }, + { + overloadId: ADD_DURATION_TIMESTAMP_OVERLOAD, + params: [DURATION_TYPE, TIMESTAMP_TYPE], + resultType: TIMESTAMP_TYPE, + }, + { + overloadId: ADD_TIMESTAMP_DURATION_OVERLOAD, + params: [TIMESTAMP_TYPE, DURATION_TYPE], + resultType: TIMESTAMP_TYPE, + }, { overloadId: ADD_INT64_OVERLOAD, params: [INT64_TYPE, INT64_TYPE], @@ -323,12 +407,12 @@ export const DIVIDE_FUNCTION_DECL = functionDecl(DIVIDE_OPERATOR, { { overloadId: DIVIDE_INT64_OVERLOAD, params: [INT64_TYPE, INT64_TYPE], - resultType: DOUBLE_TYPE, + resultType: INT64_TYPE, }, { overloadId: DIVIDE_UINT64_OVERLOAD, params: [UINT64_TYPE, UINT64_TYPE], - resultType: DOUBLE_TYPE, + resultType: UINT64_TYPE, }, ], }); @@ -396,7 +480,21 @@ export const SUBTRACT_FUNCTION_DECL = functionDecl(SUBTRACT_OPERATOR, { params: [UINT64_TYPE, UINT64_TYPE], resultType: UINT64_TYPE, }, - // TODO: duration & timestamp overloads + { + overloadId: SUBTRACT_DURATION_DURATION_OVERLOAD, + params: [DURATION_TYPE, DURATION_TYPE], + resultType: DURATION_TYPE, + }, + { + overloadId: SUBTRACT_TIMESTAMP_DURATION_OVERLOAD, + params: [TIMESTAMP_TYPE, DURATION_TYPE], + resultType: TIMESTAMP_TYPE, + }, + { + overloadId: SUBTRACT_TIMESTAMP_TIMESTAMP_OVERLOAD, + params: [TIMESTAMP_TYPE, TIMESTAMP_TYPE], + resultType: DURATION_TYPE, + }, ], }); @@ -463,7 +561,16 @@ export const LESS_FUNCTION_DECL = functionDecl(LESS_OPERATOR, { params: [BYTES_TYPE, BYTES_TYPE], resultType: BOOL_TYPE, }, - // TODO: duration & timestamp overloads + { + overloadId: LESS_TIMESTAMP_OVERLOAD, + params: [TIMESTAMP_TYPE, TIMESTAMP_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: LESS_DURATION_OVERLOAD, + params: [DURATION_TYPE, DURATION_TYPE], + resultType: BOOL_TYPE, + }, ], }); export const LESS_EQUALS_FUNCTION_DECL = functionDecl(LESS_EQUALS_OPERATOR, { @@ -523,7 +630,16 @@ export const LESS_EQUALS_FUNCTION_DECL = functionDecl(LESS_EQUALS_OPERATOR, { params: [BYTES_TYPE, BYTES_TYPE], resultType: BOOL_TYPE, }, - // TODO: duration & timestamp overloads + { + overloadId: LESS_EQUALS_DURATION_OVERLOAD, + params: [DURATION_TYPE, DURATION_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: LESS_EQUALS_TIMESTAMP_OVERLOAD, + params: [TIMESTAMP_TYPE, TIMESTAMP_TYPE], + resultType: BOOL_TYPE, + }, ], }); export const GREATER_FUNCTION_DECL = functionDecl(GREATER_OPERATOR, { @@ -588,7 +704,16 @@ export const GREATER_FUNCTION_DECL = functionDecl(GREATER_OPERATOR, { params: [BYTES_TYPE, BYTES_TYPE], resultType: BOOL_TYPE, }, - // TODO: duration & timestamp overloads + { + overloadId: GREATER_TIMESTAMP_OVERLOAD, + params: [TIMESTAMP_TYPE, TIMESTAMP_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: GREATER_DURATION_OVERLOAD, + params: [DURATION_TYPE, DURATION_TYPE], + resultType: BOOL_TYPE, + }, ], }); export const GREATER_EQUALS_FUNCTION_DECL = functionDecl( @@ -655,7 +780,16 @@ export const GREATER_EQUALS_FUNCTION_DECL = functionDecl( params: [BYTES_TYPE, BYTES_TYPE], resultType: BOOL_TYPE, }, - // TODO: duration & timestamp overloads + { + overloadId: GREATER_EQUALS_DURATION_OVERLOAD, + params: [DURATION_TYPE, DURATION_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: GREATER_EQUALS_TIMESTAMP_OVERLOAD, + params: [TIMESTAMP_TYPE, TIMESTAMP_TYPE], + resultType: BOOL_TYPE, + }, ], } ); @@ -702,6 +836,7 @@ export const SIZE_FUNCTION_DECL = functionDecl(SIZE_OVERLOAD, { overloadId: SIZE_BYTES_INST_OVERLOAD, params: [BYTES_TYPE], resultType: INT64_TYPE, + isInstanceFunction: true, }, { overloadId: SIZE_LIST_OVERLOAD, @@ -712,6 +847,7 @@ export const SIZE_FUNCTION_DECL = functionDecl(SIZE_OVERLOAD, { overloadId: SIZE_LIST_INST_OVERLOAD, params: [listOfA], resultType: INT64_TYPE, + isInstanceFunction: true, }, { overloadId: SIZE_MAP_OVERLOAD, @@ -722,6 +858,7 @@ export const SIZE_FUNCTION_DECL = functionDecl(SIZE_OVERLOAD, { overloadId: SIZE_MAP_INST_OVERLOAD, params: [mapOfAB], resultType: INT64_TYPE, + isInstanceFunction: true, }, { overloadId: SIZE_STRING_OVERLOAD, @@ -732,6 +869,7 @@ export const SIZE_FUNCTION_DECL = functionDecl(SIZE_OVERLOAD, { overloadId: SIZE_STRING_INST_OVERLOAD, params: [STRING_TYPE], resultType: INT64_TYPE, + isInstanceFunction: true, }, ], }); @@ -817,7 +955,29 @@ export const TYPE_CONVERT_DOUBLE_FUNCTION_DECL = functionDecl( } ); -// TODO: // Duration conversions +// Duration conversions +export const TYPE_CONVERT_DURATION_FUNCTION_DECL = functionDecl( + TYPE_CONVERT_DURATION_OVERLOAD, + { + overloads: [ + { + overloadId: DURATION_TO_DURATION_OVERLOAD, + params: [DURATION_TYPE], + resultType: DURATION_TYPE, + }, + { + overloadId: INT_TO_DURATION_OVERLOAD, + params: [INT64_TYPE], + resultType: DURATION_TYPE, + }, + { + overloadId: STRING_TO_DURATION_OVERLOAD, + params: [STRING_TYPE], + resultType: DURATION_TYPE, + }, + ], + } +); // Dyn conversions export const TYPE_CONVERT_DYN_FUNCTION_DECL = functionDecl( @@ -848,12 +1008,21 @@ export const TYPE_CONVERT_INT_FUNCTION_DECL = functionDecl( params: [DOUBLE_TYPE], resultType: INT64_TYPE, }, - // TODO: duration & timestamp + { + overloadId: DURATION_TO_INT_OVERLOAD, + params: [DURATION_TYPE], + resultType: INT64_TYPE, + }, { overloadId: STRING_TO_INT_OVERLOAD, params: [STRING_TYPE], resultType: INT64_TYPE, }, + { + overloadId: TIMESTAMP_TO_INT_OVERLOAD, + params: [TIMESTAMP_TYPE], + resultType: INT64_TYPE, + }, { overloadId: UINT_TO_INT_OVERLOAD, params: [UINT64_TYPE], @@ -898,12 +1067,43 @@ export const TYPE_CONVERT_STRING_FUNCTION_DECL = functionDecl( params: [UINT64_TYPE], resultType: STRING_TYPE, }, - // TODO: duration & timestamp + { + overloadId: DURATION_TO_STRING_OVERLOAD, + params: [DURATION_TYPE], + resultType: STRING_TYPE, + }, + { + overloadId: TIMESTAMP_TO_STRING_OVERLOAD, + params: [TIMESTAMP_TYPE], + resultType: STRING_TYPE, + }, ], } ); -// TODO: // Timestamp conversions +// Timestamp conversions +export const TYPE_CONVERT_TIMESTAMP_FUNCTION_DECL = functionDecl( + TYPE_CONVERT_TIMESTAMP_OVERLOAD, + { + overloads: [ + { + overloadId: TIMESTAMP_TO_TIMESTAMP_OVERLOAD, + params: [TIMESTAMP_TYPE], + resultType: TIMESTAMP_TYPE, + }, + { + overloadId: INT_TO_TIMESTAMP_OVERLOAD, + params: [INT64_TYPE], + resultType: TIMESTAMP_TYPE, + }, + { + overloadId: STRING_TO_TIMESTAMP_OVERLOAD, + params: [STRING_TYPE], + resultType: TIMESTAMP_TYPE, + }, + ], + } +); // Uint conversions export const TYPE_CONVERT_UINT_FUNCTION_DECL = functionDecl( @@ -934,9 +1134,267 @@ export const TYPE_CONVERT_UINT_FUNCTION_DECL = functionDecl( } ); -// TODO: // String functions +// String functions +export const STRING_CONTAINS_FUNCTION_DECL = functionDecl(CONTAINS_OVERLOAD, { + overloads: [ + { + overloadId: CONTAINS_STRING_OVERLOAD, + params: [STRING_TYPE, STRING_TYPE], + resultType: BOOL_TYPE, + }, + ], +}); +export const STRING_ENDSWITH_FUNCTION_DECL = functionDecl(ENDS_WITH_OVERLOAD, { + overloads: [ + { + overloadId: ENDS_WITH_STRING_OVERLOAD, + params: [STRING_TYPE, STRING_TYPE], + resultType: BOOL_TYPE, + }, + ], +}); +export const STRING_STARTSWITH_FUNCTION_DECL = functionDecl( + STARTS_WITH_OVERLOAD, + { + overloads: [ + { + overloadId: STARTS_WITH_STRING_OVERLOAD, + params: [STRING_TYPE, STRING_TYPE], + resultType: BOOL_TYPE, + }, + ], + } +); +export const STRING_MATCHES_FUNCTION_DECL = functionDecl(MATCHES_OVERLOAD, { + overloads: [ + { + overloadId: MATCHES_OVERLOAD, + params: [STRING_TYPE, STRING_TYPE], + resultType: BOOL_TYPE, + }, + { + overloadId: MATCHES_STRING_OVERLOAD, + params: [STRING_TYPE, STRING_TYPE], + resultType: BOOL_TYPE, + }, + ], +}); -// TODO: // Timestamp / duration functions +// Timestamp / duration functions +export const TIME_GET_FULL_YEAR_FUNCTION_DECL = functionDecl( + TIME_GET_FULL_YEAR_OVERLOAD, + { + overloads: [ + { + overloadId: TIMESTAMP_TO_YEAR_OVERLOAD, + params: [TIMESTAMP_TYPE], + resultType: INT64_TYPE, + isInstanceFunction: true, + }, + { + overloadId: TIMESTAMP_TO_YEAR_WITH_TZ_OVERLOAD, + params: [TIMESTAMP_TYPE], + resultType: STRING_TYPE, + isInstanceFunction: true, + }, + ], + } +); +export const TIME_GET_MONTH_FUNCTION_DECL = functionDecl( + TIME_GET_MONTH_OVERLOAD, + { + overloads: [ + { + overloadId: TIMESTAMP_TO_MONTH_OVERLOAD, + params: [TIMESTAMP_TYPE], + resultType: INT64_TYPE, + isInstanceFunction: true, + }, + { + overloadId: TIMESTAMP_TO_MONTH_WITH_TZ_OVERLOAD, + params: [TIMESTAMP_TYPE], + resultType: STRING_TYPE, + isInstanceFunction: true, + }, + ], + } +); +export const TIME_GET_DAY_OF_YEAR_FUNCTION_DECL = functionDecl( + TIME_GET_DAY_OF_YEAR_OVERLOAD, + { + overloads: [ + { + overloadId: TIMESTAMP_TO_DAY_OF_YEAR_OVERLOAD, + params: [TIMESTAMP_TYPE], + resultType: INT64_TYPE, + isInstanceFunction: true, + }, + { + overloadId: TIMESTAMP_TO_DAY_OF_YEAR_WITH_TZ_OVERLOAD, + params: [TIMESTAMP_TYPE], + resultType: STRING_TYPE, + isInstanceFunction: true, + }, + ], + } +); +export const TIME_GET_DAY_OF_MONTH_FUNCTION_DECL = functionDecl( + TIME_GET_DAY_OF_MONTH_OVERLOAD, + { + overloads: [ + { + overloadId: TIMESTAMP_TO_DAY_OF_MONTH_ZERO_BASED_OVERLOAD, + params: [TIMESTAMP_TYPE], + resultType: INT64_TYPE, + isInstanceFunction: true, + }, + { + overloadId: TIMESTAMP_TO_DAY_OF_MONTH_ZERO_BASED_WITH_TZ_OVERLOAD, + params: [TIMESTAMP_TYPE], + resultType: STRING_TYPE, + isInstanceFunction: true, + }, + ], + } +); +export const TIME_GET_DATE_FUNCTION_DECL = functionDecl( + TIME_GET_DATE_OVERLOAD, + { + overloads: [ + { + overloadId: TIMESTAMP_TO_DAY_OF_MONTH_ONE_BASED_OVERLOAD, + params: [TIMESTAMP_TYPE], + resultType: INT64_TYPE, + isInstanceFunction: true, + }, + { + overloadId: TIMESTAMP_TO_DAY_OF_MONTH_ONE_BASED_WITH_TZ_OVERLOAD, + params: [TIMESTAMP_TYPE], + resultType: STRING_TYPE, + isInstanceFunction: true, + }, + ], + } +); +export const TIME_GET_DAY_OF_WEEK_FUNCTION_DECL = functionDecl( + TIME_GET_DAY_OF_WEEK_OVERLOAD, + { + overloads: [ + { + overloadId: TIMESTAMP_TO_DAY_OF_WEEK_OVERLOAD, + params: [TIMESTAMP_TYPE], + resultType: INT64_TYPE, + isInstanceFunction: true, + }, + { + overloadId: TIMESTAMP_TO_DAY_OF_WEEK_WITH_TZ_OVERLOAD, + params: [TIMESTAMP_TYPE], + resultType: STRING_TYPE, + isInstanceFunction: true, + }, + ], + } +); +export const TIME_GET_HOURS_FUNCTION_DECL = functionDecl( + TIME_GET_HOURS_OVERLOAD, + { + overloads: [ + { + overloadId: TIMESTAMP_TO_HOURS_OVERLOAD, + params: [TIMESTAMP_TYPE], + resultType: INT64_TYPE, + isInstanceFunction: true, + }, + { + overloadId: TIMESTAMP_TO_HOURS_WITH_TZ_OVERLOAD, + params: [TIMESTAMP_TYPE], + resultType: STRING_TYPE, + isInstanceFunction: true, + }, + { + overloadId: DURATION_TO_HOURS_OVERLOAD, + params: [DURATION_TYPE], + resultType: INT64_TYPE, + isInstanceFunction: true, + }, + ], + } +); +export const TIME_GET_MINUTES_FUNCTION_DECL = functionDecl( + TIME_GET_MINUTES_OVERLOAD, + { + overloads: [ + { + overloadId: TIMESTAMP_TO_MINUTES_OVERLOAD, + params: [TIMESTAMP_TYPE], + resultType: INT64_TYPE, + isInstanceFunction: true, + }, + { + overloadId: TIMESTAMP_TO_MINUTES_WITH_TZ_OVERLOAD, + params: [TIMESTAMP_TYPE], + resultType: STRING_TYPE, + isInstanceFunction: true, + }, + { + overloadId: DURATION_TO_MINUTES_OVERLOAD, + params: [DURATION_TYPE], + resultType: INT64_TYPE, + isInstanceFunction: true, + }, + ], + } +); +export const TIME_GET_SECONDS_FUNCTION_DECL = functionDecl( + TIME_GET_SECONDS_OVERLOAD, + { + overloads: [ + { + overloadId: TIMESTAMP_TO_SECONDS_OVERLOAD, + params: [TIMESTAMP_TYPE], + resultType: INT64_TYPE, + isInstanceFunction: true, + }, + { + overloadId: TIMESTAMP_TO_SECONDS_WITH_TZ_OVERLOAD, + params: [TIMESTAMP_TYPE], + resultType: STRING_TYPE, + isInstanceFunction: true, + }, + { + overloadId: DURATION_TO_SECONDS_OVERLOAD, + params: [DURATION_TYPE], + resultType: INT64_TYPE, + isInstanceFunction: true, + }, + ], + } +); +export const TIME_GET_MILLISECONDS_FUNCTION_DECL = functionDecl( + TIME_GET_MILLISECONDS_OVERLOAD, + { + overloads: [ + { + overloadId: TIMESTAMP_TO_MILLISECONDS_OVERLOAD, + params: [TIMESTAMP_TYPE], + resultType: INT64_TYPE, + isInstanceFunction: true, + }, + { + overloadId: TIMESTAMP_TO_MILLISECONDS_WITH_TZ_OVERLOAD, + params: [TIMESTAMP_TYPE], + resultType: STRING_TYPE, + isInstanceFunction: true, + }, + { + overloadId: DURATION_TO_MILLISECONDS_OVERLOAD, + params: [DURATION_TYPE], + resultType: INT64_TYPE, + isInstanceFunction: true, + }, + ], + } +); export const STANDARD_FUNCTION_DECLARATIONS = [ CONDITIONAL_FUNCTION_DECL, @@ -963,10 +1421,26 @@ export const STANDARD_FUNCTION_DECLARATIONS = [ TYPE_CONVERT_BOOL_FUNCTION_DECL, TYPE_CONVERT_BYTES_FUNCTION_DECL, TYPE_CONVERT_DOUBLE_FUNCTION_DECL, + TYPE_CONVERT_DURATION_FUNCTION_DECL, TYPE_CONVERT_DYN_FUNCTION_DECL, TYPE_CONVERT_INT_FUNCTION_DECL, TYPE_CONVERT_STRING_FUNCTION_DECL, + TYPE_CONVERT_TIMESTAMP_FUNCTION_DECL, TYPE_CONVERT_UINT_FUNCTION_DECL, + STRING_CONTAINS_FUNCTION_DECL, + STRING_ENDSWITH_FUNCTION_DECL, + STRING_MATCHES_FUNCTION_DECL, + STRING_STARTSWITH_FUNCTION_DECL, + TIME_GET_FULL_YEAR_FUNCTION_DECL, + TIME_GET_MONTH_FUNCTION_DECL, + TIME_GET_DAY_OF_YEAR_FUNCTION_DECL, + TIME_GET_DAY_OF_MONTH_FUNCTION_DECL, + TIME_GET_DATE_FUNCTION_DECL, + TIME_GET_DAY_OF_WEEK_FUNCTION_DECL, + TIME_GET_HOURS_FUNCTION_DECL, + TIME_GET_MINUTES_FUNCTION_DECL, + TIME_GET_SECONDS_FUNCTION_DECL, + TIME_GET_MILLISECONDS_FUNCTION_DECL, ]; // TODO: SingletonUnaryBinding, traits diff --git a/packages/cel/src/lib/types.ts b/packages/cel/src/lib/types.ts index 84c063d..9903657 100644 --- a/packages/cel/src/lib/types.ts +++ b/packages/cel/src/lib/types.ts @@ -75,6 +75,10 @@ export function wellKnownType(value: Type_WellKnownType) { }); } +export const ANY_TYPE = wellKnownType(Type_WellKnownType.ANY); +export const DURATION_TYPE = wellKnownType(Type_WellKnownType.DURATION); +export const TIMESTAMP_TYPE = wellKnownType(Type_WellKnownType.TIMESTAMP); + export function listType(value: MessageInitShape) { return create(TypeSchema, { typeKind: { @@ -104,6 +108,13 @@ export function functionType( }); } +export function unwrapFunctionType(val: Type) { + if (val.typeKind.case === 'function') { + return val.typeKind.value; + } + return null; +} + export function messageType(value: string) { return create(TypeSchema, { typeKind: { @@ -113,6 +124,13 @@ export function messageType(value: string) { }); } +export function unwrapMessageType(val: Type) { + if (val.typeKind.case === 'messageType') { + return val.typeKind.value; + } + return null; +} + export function typeParamType(value: string) { return create(TypeSchema, { typeKind: { @@ -734,13 +752,29 @@ export function substitute( return substitute(mapping, sub, typeParamToDyn); } return t; + case 'messageType': + // Handle special cases for certain message types. + switch (t.typeKind.value) { + case 'google.protobuf.Struct': + return mapType({ + keyType: STRING_TYPE, + valueType: DYN_TYPE, + }); + case 'google.protobuf.Value': + return DYN_TYPE; + case 'google.protobuf.ListValue': + return listType({ elemType: DYN_TYPE }); + default: + break; + } + return t; default: return t; } } -export function formatCELType(t: Type): string { - switch (t.typeKind.case) { +export function formatCELType(t: Type | null): string { + switch (t?.typeKind.case) { case 'primitive': switch (t.typeKind.value) { case Type_PrimitiveType.BOOL: @@ -762,8 +796,19 @@ export function formatCELType(t: Type): string { ) as string; } case 'wellKnown': - // TODO: implement - return enumToJson(Type_WellKnownTypeSchema, t.typeKind.value) as string; + switch (t.typeKind.value) { + case Type_WellKnownType.ANY: + return 'any'; + case Type_WellKnownType.DURATION: + return 'duration'; + case Type_WellKnownType.TIMESTAMP: + return 'timestamp'; + default: + return enumToJson( + Type_WellKnownTypeSchema, + t.typeKind.value + ) as string; + } case 'error': return '!error!'; case 'null': @@ -777,9 +822,16 @@ export function formatCELType(t: Type): string { break; case 'listType': return `list(${formatCELType(t.typeKind.value.elemType!)})`; + case 'type': + return formatCELType(t.typeKind.value); + case 'messageType': + return t.typeKind.value; + case 'mapType': + const keyType = formatCELType(t.typeKind.value.keyType!); + const valueType = formatCELType(t.typeKind.value.valueType!); + return `map(${keyType}, ${valueType})`; } - // TODO: implement - return t.typeKind.case ?? 'unknown'; + return ''; } export function findTypeInMapping(mapping: Map, t: Type) { @@ -886,3 +938,45 @@ export function isExactTypeList(t1: Type[], t2: Type[]) { } return true; } + +export function formatFunctionDeclType( + resultType: Type | null, + argTypes: Type[], + isInstance: boolean +): string { + return formatFunctionInternal( + resultType, + argTypes, + isInstance, + formatCELType + ); +} + +function formatFunctionInternal( + resultType: T | null, + argTypes: T[], + isInstance: boolean, + format: (value: T | null) => string +): string { + let result = ''; + if (isInstance) { + const target = argTypes[0]; + argTypes = argTypes.slice(1); + result += format(target); + result += '.'; + } + result += '('; + for (let i = 0; i < argTypes.length; i++) { + if (i > 0) { + result += ', '; + } + result += format(argTypes[i]); + } + result += ')'; + const rt = format(resultType); + if (rt !== '') { + result += ' -> '; + result += rt; + } + return result; +} From c06539c09465efa6aa5d61b87b40afbba0c565ed Mon Sep 17 00:00:00 2001 From: jafaircl Date: Tue, 8 Oct 2024 21:35:33 -0400 Subject: [PATCH 21/34] feat(cel): this gets most existing check tests to pass and makes code easier to reason about --- packages/cel/src/lib/checker.spec.ts | 151 +++++++++-- packages/cel/src/lib/checker.ts | 322 +++++++++++++---------- packages/cel/src/lib/environment.test.ts | 21 +- packages/cel/src/lib/environment.ts | 206 ++++++++------- packages/cel/src/lib/standard.ts | 7 +- packages/cel/src/lib/types.ts | 110 ++++++-- packages/cel/src/lib/utils.ts | 14 + 7 files changed, 521 insertions(+), 310 deletions(-) diff --git a/packages/cel/src/lib/checker.spec.ts b/packages/cel/src/lib/checker.spec.ts index 2aca959..2a8b01b 100644 --- a/packages/cel/src/lib/checker.spec.ts +++ b/packages/cel/src/lib/checker.spec.ts @@ -53,7 +53,16 @@ interface TestInfo { function getDefaultEnv() { return STANDARD_ENV().extend({ registry: createMutableRegistry(TestAllTypesSchema), - declarations: [ + idents: [ + identDecl('is', { type: STRING_TYPE }), + identDecl('ii', { type: INT64_TYPE }), + identDecl('iu', { type: UINT64_TYPE }), + identDecl('iz', { type: BOOL_TYPE }), + identDecl('ib', { type: BYTES_TYPE }), + identDecl('id', { type: DOUBLE_TYPE }), + identDecl('ix', { type: NULL_TYPE }), + ], + functions: [ functionDecl('fg_s', { overloads: [ { @@ -72,13 +81,6 @@ function getDefaultEnv() { }, ], }), - identDecl('is', { type: STRING_TYPE }), - identDecl('ii', { type: INT64_TYPE }), - identDecl('iu', { type: UINT64_TYPE }), - identDecl('iz', { type: BOOL_TYPE }), - identDecl('ib', { type: BYTES_TYPE }), - identDecl('id', { type: DOUBLE_TYPE }), - identDecl('ix', { type: NULL_TYPE }), ], }); } @@ -90,7 +92,7 @@ const testCases: TestInfo[] = [ out: `a.b~bool`, outType: STRING_TYPE, env: new CELEnvironment({ - declarations: [ + idents: [ identDecl('a', { type: mapType({ keyType: STRING_TYPE, @@ -287,7 +289,7 @@ _+_( in: `TestAllTypes{single_int32: 1, single_int64: 2}`, container: 'google.api.expr.test.v1.proto3', out: ` - google.api.expr.test.v1.proto3TestAllTypes{ + google.api.expr.test.v1.proto3estAllTypes{ single_int32 : 1~int, single_int64 : 2~int }~google.api.expr.test.v1.proto3.TestAllTypes^google.api.expr.test.v1.proto3.TestAllTypes`, @@ -326,9 +328,7 @@ ERROR: :1:40: undefined field 'undefined' _==_(size(x~list(int)^x)~int^size_list, x~list(int)^x.size()~int^list_size) ~bool^equals`, env: getDefaultEnv().extend({ - declarations: [ - identDecl('x', { type: listType({ elemType: INT64_TYPE }) }), - ], + idents: [identDecl('x', { type: listType({ elemType: INT64_TYPE }) })], }), outType: BOOL_TYPE, }, @@ -421,7 +421,7 @@ _!=_(_-_(_+_(1~double, _*_(2~double, 3~double)~double^multiply_double) { in: `x.single_int32 != null`, env: getDefaultEnv().extend({ - declarations: [ + idents: [ identDecl('x', { type: messageType('google.api.expr.test.v1.proto3.Proto2Message'), }), @@ -438,7 +438,7 @@ ERROR: :1:2: unexpected failed resolution of 'google.api.expr.test.v1.pro // TODO: this test container is different than in cel-go because we have to import from a different package in: `x.single_value + 1 / x.single_struct.y == 23`, env: getDefaultEnv().extend({ - declarations: [ + idents: [ identDecl('x', { type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), }), @@ -460,7 +460,7 @@ ERROR: :1:2: unexpected failed resolution of 'google.api.expr.test.v1.pro // TODO: this test container is different than in cel-go because we have to import from a different package in: `x.single_value[23] + x.single_struct['y']`, env: getDefaultEnv().extend({ - declarations: [ + idents: [ identDecl('x', { type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), }), @@ -541,7 +541,7 @@ ERROR: :1:2: unexpected failed resolution of 'google.api.expr.test.v1.pro )~bool^logical_and )~bool^logical_and`, env: getDefaultEnv().extend({ - declarations: [ + idents: [ identDecl('x', { type: messageType('google.protobuf.Struct') }), identDecl('y', { type: messageType('google.protobuf.ListValue') }), identDecl('z', { type: messageType('google.protobuf.Value') }), @@ -549,28 +549,31 @@ ERROR: :1:2: unexpected failed resolution of 'google.api.expr.test.v1.pro }), outType: BOOL_TYPE, }, - // { // TODO: this doesn't work + // TODO: this test does not throw an error when it should + // { // in: `x + y`, // env: getDefaultEnv().extend({ - // declarations: [ + // idents: [ // identDecl('x', { // type: listType({ - // elemType: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + // elemType: messageType( + // 'google.api.expr.test.v1.proto3.TestAllTypes' + // ), // }), // }), // identDecl('y', { type: listType({ elemType: INT64_TYPE }) }), // ], // }), // err: ` - // ERROR: :1:3: found no matching overload for '_+_' applied to '(list(google.api.expr.test.v1.proto3.TestAllTypes), list(int))' - // | x + y - // | ..^ - // `, + // ERROR: :1:3: found no matching overload for '_+_' applied to '(list(google.api.expr.test.v1.proto3.TestAllTypes), list(int))' + // | x + y + // | ..^ + // `, // }, { in: `x[1u]`, env: getDefaultEnv().extend({ - declarations: [ + idents: [ identDecl('x', { type: listType({ elemType: messageType( @@ -589,7 +592,7 @@ ERROR: :1:2: found no matching overload for '_[_]' applied to '(list(goog { in: `(x + x)[1].single_int32 == size(x)`, env: getDefaultEnv().extend({ - declarations: [ + idents: [ identDecl('x', { type: listType({ elemType: messageType( @@ -616,7 +619,7 @@ size(x~list(google.api.expr.test.v1.proto3.TestAllTypes)^x)~int^size_list) { in: `x.repeated_int64[x.single_int32] == 23`, env: getDefaultEnv().extend({ - declarations: [ + idents: [ identDecl('x', { type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), }), @@ -630,11 +633,10 @@ _==_(_[_](x~google.api.expr.test.v1.proto3.TestAllTypes^x.repeated_int64~list(in ~bool^equals`, outType: BOOL_TYPE, }, - { in: `size(x.map_int64_nested_type) == 0`, env: getDefaultEnv().extend({ - declarations: [ + idents: [ identDecl('x', { type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), }), @@ -649,6 +651,97 @@ _==_(size(x~google.api.expr.test.v1.proto3.TestAllTypes^x.map_int64_nested_type `, outType: BOOL_TYPE, }, + { + in: `x.all(y, y == true)`, + env: getDefaultEnv().extend({ + idents: [identDecl('x', { type: BOOL_TYPE })], + }), + out: ` + __comprehension__( + // Variable + y, + // Target + x~bool^x, + // Accumulator + __result__, + // Init + true~bool, + // LoopCondition + @not_strictly_false( + __result__~bool^__result__ + )~bool^not_strictly_false, + // LoopStep + _&&_( + __result__~bool^__result__, + _==_( + y~!error!^y, + true~bool + )~bool^equals + )~bool^logical_and, + // Result + __result__~bool^__result__)~bool + `, + err: `ERROR: :1:1: expression of type 'bool' cannot be range of a comprehension (must be list, map, or dynamic) + | x.all(y, y == true) + | ^`, + }, + { + // TODO: this test fails + in: `x.repeated_int64.map(x, double(x))`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('x', { + type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + }), + ], + }), + out: ` + __comprehension__( + // Variable + x, + // Target + x~google.api.expr.test.v1.proto3.TestAllTypes^x.repeated_int64~list(int), + // Accumulator + __result__, + // Init + []~list(double), + // LoopCondition + true~bool, + // LoopStep + _+_( + __result__~list(double)^__result__, + [ + double( + x~int^x + )~double^int64_to_double + ]~list(double) + )~list(double)^add_list, + // Result + __result__~list(double)^__result__)~list(double) + `, + outType: listType({ elemType: DOUBLE_TYPE }), + }, + // TODO: this test does not throw an error when it should + // { + // in: `x[2].single_int32 == 23`, + // env: getDefaultEnv().extend({ + // idents: [ + // identDecl('x', { + // type: mapType({ + // keyType: STRING_TYPE, + // valueType: messageType( + // 'google.api.expr.test.v1.proto3.TestAllTypes' + // ), + // }), + // }), + // ], + // }), + // err: ` + // ERROR: :1:2: found no matching overload for '_[_]' applied to '(map(string, google.api.expr.test.v1.proto3.TestAllTypes), int)' + // | x[2].single_int32 == 23 + // | .^ + // `, + // }, ]; describe('CELChecker', () => { diff --git a/packages/cel/src/lib/checker.ts b/packages/cel/src/lib/checker.ts index 1460341..2662baa 100644 --- a/packages/cel/src/lib/checker.ts +++ b/packages/cel/src/lib/checker.ts @@ -5,10 +5,10 @@ import { CheckedExprSchema, Decl, Decl_IdentDecl, + Decl_IdentDeclSchema, Reference, Type, Type_PrimitiveType, - Type_WellKnownType, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb'; import { Expr, @@ -26,13 +26,16 @@ import { BOOL_TYPE, BYTES_TYPE, DOUBLE_TYPE, + DURATION_TYPE, DYN_TYPE, ERROR_TYPE, INT64_TYPE, NULL_TYPE, STRING_TYPE, + TIMESTAMP_TYPE, UINT64_TYPE, functionType, + getCheckedWellKnownType, isAssignable, isAssignableList, isDyn, @@ -49,8 +52,8 @@ import { substitute, typeParamType, unwrapFunctionType, + unwrapIdentDeclType, unwrapOptionalType, - wellKnownType, } from './types'; import { extractIdent, @@ -59,6 +62,7 @@ import { getWellKNownTypeName, identDecl, identReference, + isMapExpr, mapToObject, toQualifiedName, } from './utils'; @@ -78,7 +82,7 @@ export class CELChecker { constructor( public readonly parsed: ParsedExpr, public readonly source: string, - public readonly env: CELEnvironment + public env: CELEnvironment ) { this.#errors = new Errors(source); } @@ -99,35 +103,42 @@ export class CELChecker { if (isNil(sourceInfo)) { throw new Error('ParsedExpr.sourceInfo is nil'); } + this.checkExpr(expr); + // Walk over the final type map substituting any type parameters either by + // their bound value or by DYN. + for (const [id, t] of this.#typeMap) { + this.setType(BigInt(id), substitute(this.#mapping, t, true)); + } + return create(CheckedExprSchema, { + expr, + sourceInfo, + referenceMap: mapToObject(this.#referenceMap), + typeMap: mapToObject(this.#typeMap), + }); + } + + checkExpr(expr?: Expr) { + if (isNil(expr)) { + return expr; + } switch (expr.exprKind.case) { case 'constExpr': - this.setType(expr.id, this.checkConstExpr(expr)); - break; + return this.checkConstExpr(expr); case 'identExpr': - this.checkIdentExpr(expr); - break; + return this.checkIdentExpr(expr); case 'listExpr': - this.checkListExpr(expr); - break; + return this.checkListExpr(expr); case 'selectExpr': - this.checkSelect(expr); - break; + return this.checkSelect(expr); case 'callExpr': - this.checkCall(expr); - break; + return this.checkCall(expr); case 'structExpr': - const isMapExpr = expr.exprKind.value.entries.some( - (entry) => entry.keyKind.case === 'mapKey' - ); - if (isMapExpr) { - this.checkCreateMap(expr); - } else { - this.checkCreateStruct(expr); + if (isMapExpr(expr)) { + return this.checkCreateMap(expr); } - break; + return this.checkCreateStruct(expr); case 'comprehensionExpr': - this.checkComprehension(expr); - break; + return this.checkComprehension(expr); default: this.#errors.reportUnexpectedAstTypeError( expr.id, @@ -136,20 +147,10 @@ export class CELChecker { expr.exprKind.case ?? '' ); } - // Walk over the final type map substituting any type parameters either by - // their bound value or by DYN. - for (const [id, t] of this.#typeMap) { - this.setType(BigInt(id), substitute(this.#mapping, t, true)); - } - return create(CheckedExprSchema, { - expr, - sourceInfo, - referenceMap: mapToObject(this.#referenceMap), - typeMap: mapToObject(this.#typeMap), - }); + return expr; } - checkConstExpr(expr: Expr): Type { + checkConstExpr(expr: Expr) { if (expr.exprKind.case !== 'constExpr') { this.#errors.reportUnexpectedAstTypeError( expr.id, @@ -157,27 +158,37 @@ export class CELChecker { 'constExpr', expr.exprKind.case! ); - return ERROR_TYPE; + this.setType(expr.id, ERROR_TYPE); + return expr; } switch (expr.exprKind.value.constantKind.case) { case 'boolValue': - return BOOL_TYPE; + this.setType(expr.id, BOOL_TYPE); + break; case 'bytesValue': - return BYTES_TYPE; + this.setType(expr.id, BYTES_TYPE); + break; case 'doubleValue': - return DOUBLE_TYPE; + this.setType(expr.id, DOUBLE_TYPE); + break; case 'int64Value': - return INT64_TYPE; + this.setType(expr.id, INT64_TYPE); + break; case 'nullValue': - return NULL_TYPE; + this.setType(expr.id, NULL_TYPE); + break; case 'stringValue': - return STRING_TYPE; + this.setType(expr.id, STRING_TYPE); + break; case 'uint64Value': - return UINT64_TYPE; + this.setType(expr.id, UINT64_TYPE); + break; case 'durationValue': - return wellKnownType(Type_WellKnownType.DURATION); + this.setType(expr.id, DURATION_TYPE); + break; case 'timestampValue': - return wellKnownType(Type_WellKnownType.TIMESTAMP); + this.setType(expr.id, TIMESTAMP_TYPE); + break; default: this.#errors.reportUnexpectedAstTypeError( expr.id, @@ -185,8 +196,10 @@ export class CELChecker { 'constExpr', expr.exprKind.value.constantKind.case! ); - return ERROR_TYPE; + this.setType(expr.id, ERROR_TYPE); + break; } + return expr; } checkIdentExpr(expr: Expr) { @@ -199,27 +212,38 @@ export class CELChecker { throw new Error('identName is nil'); } const ident = this.env.lookupIdent(identName); - if (!isNil(ident)) { - if (ident.declKind.case !== 'ident') { - // This should never happen - throw new Error('ident.declKind.case is not ident'); - } - this.setType(expr.id, ident.declKind.value.type!); - this.setReference( + if (isNil(ident)) { + this.setType(expr.id, ERROR_TYPE); + this.#errors.reportUndeclaredReference( expr.id, - identReference(ident.name, ident.declKind.value.value!) + this.getLocationById(expr.id), + this.env.container, + identName ); - // Overwrite the identifier with its fully qualified name. - expr.exprKind.value.name = toQualifiedName(expr); - return; + return expr; } - this.setType(expr.id, ERROR_TYPE); - this.#errors.reportUndeclaredReference( - expr.id, - this.getLocationById(expr.id), - this.env.container, - identName - ); + if (ident.declKind.case !== 'ident') { + // This should never happen + throw new Error('ident.declKind.case is not ident'); + } + // Overwrite the identifier with its fully qualified name. + const qn = toQualifiedName(expr); + expr.exprKind.value.name = qn; + let identType = unwrapIdentDeclType(ident)!; + // Handle special cases for well-known types. + if (identType.type?.typeKind.case === 'messageType') { + const checkedType = getCheckedWellKnownType( + identType.type.typeKind.value + ); + if (!isNil(checkedType)) { + identType = create(Decl_IdentDeclSchema, { + type: checkedType, + }); + } + } + this.setType(expr.id, identType.type!); + this.setReference(expr.id, identReference(ident.name, identType.value!)); + return expr; } checkSelect(expr: Expr) { @@ -229,21 +253,26 @@ export class CELChecker { } // Before traversing down the tree, try to interpret as qualified name. const qname = toQualifiedName(expr); - if (qname !== '') { - const ident = this.env.lookupIdent(qname); + if (!isEmpty(qname)) { + const decl = this.env.lookupIdent(qname); + const ident = !isNil(decl) ? unwrapIdentDeclType(decl) : null; if (!isNil(ident)) { - if (ident.declKind.case !== 'ident') { - // This should never happen - throw new Error('ident.declKind.case is not ident'); + if (expr.exprKind.value.testOnly) { + this.#errors.reportErrorAtId( + expr.id, + this.getLocationById(expr.id), + 'expression does not select a field' + ); + this.setType(expr.id, BOOL_TYPE); + } else { + this.setType(expr.id, ident.type!); + this.setReference(expr.id, identReference(decl!.name, ident.value!)); } - this.setType(expr.id, ident.declKind.value.type!); - this.setReference( - expr.id, - identReference(ident.name, ident.declKind.value.value!) - ); - return; + return expr; } } + + // Interpret as field selection, first traversing down the operand. let resultType = this.checkSelectField( expr, expr.exprKind.value.operand!, @@ -251,9 +280,10 @@ export class CELChecker { false ); if (expr.exprKind.value.testOnly) { - resultType = primitiveType(Type_PrimitiveType.BOOL); + resultType = BOOL_TYPE; } this.setType(expr.id, substitute(this.#mapping, resultType, false)); + return expr; } checkOptSelect(expr: Expr) { @@ -269,6 +299,7 @@ export class CELChecker { const resultType = this.checkSelectField(expr, operand, field, true); this.setType(expr.id, substitute(this.#mapping, resultType, false)); this.setReference(expr.id, functionReference(['select_optional_field'])); + return expr; } checkSelectField( @@ -278,10 +309,10 @@ export class CELChecker { optional: boolean ) { // Interpret as field selection, first traversing down the operand. - this.check(operand); + const checkedOperand = this.checkExpr(operand); const operandType = substitute( this.#mapping, - this.getType(operand.id)!, + this.getType(checkedOperand!.id)!, false ); @@ -362,13 +393,12 @@ export class CELChecker { const call = expr.exprKind.value; const fnName = call.function; if (fnName === OPT_SELECT_OPERATOR) { - this.checkOptSelect(expr); - return; + return this.checkOptSelect(expr); } const args = call.args; // Traverse arguments. for (const arg of args) { - this.check(arg); + this.checkExpr(arg); } // Regular static call with simple name. @@ -383,13 +413,13 @@ export class CELChecker { fnName ); this.setType(expr.id, ERROR_TYPE); - return; + return expr; } // Overwrite the function name with its fully qualified resolved name. - expr.exprKind.value.function = toQualifiedName(expr); + expr.exprKind.value.function = fn.name; // Check to see whether the overload resolves. this.resolveOverloadOrError(expr, fn, null, args); - return; + return expr; } // If a receiver 'target' is present, it may either be a receiver function, @@ -407,19 +437,19 @@ export class CELChecker { // behavior. // Overwrite with fully-qualified resolved function name sans receiver // target. - expr.exprKind.value.function = qualifiedName; - this.resolveOverloadOrError(expr, fn, call.target, args); - return; + expr.exprKind.value.function = fn.name; + this.resolveOverloadOrError(expr, fn, null, args); + return expr; } } // Regular instance call. - this.check(call.target); + const checkedTarget = this.checkExpr(call.target)!; const fn = this.env.lookupFunction(fnName); // Function found, attempt overload resolution. if (!isNil(fn)) { - this.resolveOverloadOrError(expr, fn, call.target, args); - return; + this.resolveOverloadOrError(expr, fn, checkedTarget, args); + return expr; } // Function name not declared, record error. this.setType(expr.id, ERROR_TYPE); @@ -429,6 +459,7 @@ export class CELChecker { this.env.container, fnName ); + return expr; } resolveOverloadOrError( @@ -451,11 +482,12 @@ export class CELChecker { // here. if (isNil(resolution)) { this.setType(expr.id, ERROR_TYPE); - return; + return resolution; } // Overload found this.setType(expr.id, resolution.resultType!); this.setReference(expr.id, resolution.checkedRef!); + return resolution; } resolveOverload( @@ -473,21 +505,11 @@ export class CELChecker { throw new Error('fn.declKind.case is not a function'); } const argTypes: Type[] = []; - if (!isNil(expr.exprKind.value.target)) { - const targetType = isNil(target) ? null : this.getType(target.id); - if (isNil(targetType)) { - // This should never happen but acts as a type guard. - throw new Error('targetType is nil'); - } - argTypes.push(targetType); + if (!isNil(target)) { + argTypes.push(this.getType(target.id)!); } for (const arg of args) { - const argType = this.getType(arg.id); - if (isNil(argType)) { - // This should never happen but acts as a type guard. - throw new Error('argType is nil'); - } - argTypes.push(argType); + argTypes.push(this.getType(arg.id)!); } let resultType: Type | undefined = undefined; @@ -514,13 +536,11 @@ export class CELChecker { checkedRef = functionReference([overload.overloadId]); for (let i = 0; i < argTypes.length; i++) { const argType = argTypes[i]; - if ( - !this._isAssignable(argType, primitiveType(Type_PrimitiveType.BOOL)) - ) { + if (!this._isAssignable(argType, BOOL_TYPE)) { this.#errors.reportTypeMismatch( args[i].id, this.getLocationById(args[i].id), - primitiveType(Type_PrimitiveType.BOOL), + BOOL_TYPE, argType ); resultType = ERROR_TYPE; @@ -549,7 +569,8 @@ export class CELChecker { overloadType = substitute(substitutions, overloadType, false); } - const candidateArgTypes = overload.params; + const unwrappedOverload = unwrapFunctionType(overloadType)!; + const candidateArgTypes = unwrappedOverload.argTypes; if (this._isAssignableList(argTypes, candidateArgTypes)) { if (isNil(checkedRef)) { checkedRef = functionReference([overload.overloadId]); @@ -559,7 +580,7 @@ export class CELChecker { // First matching overload, determines result type. const fnResultType = substitute( this.#mapping, - unwrapFunctionType(overloadType)!.resultType!, + unwrappedOverload.resultType!, false ); if (isNil(resultType)) { @@ -603,7 +624,7 @@ export class CELChecker { } for (let i = 0; i < createList.elements.length; i++) { const e = createList.elements[i]; - this.check(e); + this.checkExpr(e); const elemType = this.getType(e.id); if (isNil(elemType)) { continue; @@ -624,6 +645,7 @@ export class CELChecker { elemsType = this._newTypeVar(); } this.setType(expr.id, listType({ elemType: elemsType })); + return expr; } checkCreateMap(expr: Expr) { @@ -639,25 +661,27 @@ export class CELChecker { // This should never happen throw new Error('entry.keyKind.case is not mapKey'); } - const key = entry.keyKind.value; - this.check(key); - mapKeyType = this._joinTypes(key, mapKeyType, this.getType(key.id)!); + const checkedKey = this.checkExpr(entry.keyKind.value)!; + mapKeyType = this._joinTypes( + checkedKey, + mapKeyType, + this.getType(checkedKey.id)! + ); - const val = entry.value!; - this.check(val); - let valType = this.getType(val.id)!; + const checkedVal = this.checkExpr(entry.value)!; + let valType = this.getType(checkedVal.id)!; if (isOptionalType(mapKeyType)) { valType = unwrapOptionalType(valType)!; if (!isOptionalType(valType) && !isDyn(valType)) { this.#errors.reportTypeMismatch( - val.id, - this.getLocationById(val.id), + checkedVal.id, + this.getLocationById(checkedVal.id), optionalType(valType), valType ); } } - mapValueType = this._joinTypes(val, mapValueType, valType); + mapValueType = this._joinTypes(checkedVal, mapValueType, valType); } if (isNil(mapKeyType)) { // If the map is empty, assign free type variables to typeKey and value @@ -672,6 +696,7 @@ export class CELChecker { valueType: mapValueType, }) ); + return expr; } checkCreateStruct(expr: Expr) { @@ -691,7 +716,7 @@ export class CELChecker { msgVal.messageName ); this.setType(expr.id, ERROR_TYPE); - return; + return expr; } const identDecl = ident.declKind.value as Decl_IdentDecl; let typeName = ident.name; @@ -702,14 +727,26 @@ export class CELChecker { this.setReference(expr.id, identReference(typeName, identDecl.value!)); const identKind = identDecl.type?.typeKind.case; if (identKind !== 'error') { - if (identKind !== 'messageType' && identKind !== 'wellKnown') { + if ( + identKind !== 'type' && + identKind !== 'wellKnown' && + identKind !== 'messageType' + ) { this.#errors.reportNotAType( expr.id, this.getLocationById(expr.id), typeName ); } else { - resultType = identDecl.type!; + switch (identKind) { + case 'type': + resultType = identDecl.type!.typeKind.value; + break; + case 'wellKnown': + case 'messageType': + resultType = identDecl.type!; + break; + } // Backwards compatibility test between well-known types and message // types. In this context, the type is being instantiated by it // protobuf name which is not ideal or recommended, but some users @@ -737,7 +774,7 @@ export class CELChecker { throw new Error('field.keyKind.case is not fieldKey'); } - this.check(field.value); + const checkedValue = this.checkExpr(field.value)!; let fieldType = ERROR_TYPE; const ft = this.env.lookupFieldType(typeName, field.keyKind.value); @@ -760,7 +797,7 @@ export class CELChecker { } } - let valType = this.getType(field.value!.id); + let valType = this.getType(checkedValue.id); if (field.optionalEntry) { const vt = maybeUnwrapOptionalType(valType); if (!isNil(vt)) { @@ -784,6 +821,7 @@ export class CELChecker { ); } } + return expr; } checkComprehension(expr: Expr) { @@ -792,12 +830,12 @@ export class CELChecker { throw new Error('expr.exprKind.case is not comprehensionExpr'); } const comp = expr.exprKind.value; - this.check(comp.iterRange); - this.check(comp.accuInit); - const accuType = this.getType(comp.accuInit!.id); + const checkedRange = this.checkExpr(comp.iterRange); + const checkedInit = this.checkExpr(comp.accuInit); + const accuType = this.getType(checkedInit!.id); const rangeType = substitute( this.#mapping, - this.getType(comp.iterRange!.id)!, + this.getType(checkedRange!.id)!, false ); let varType: Type | undefined = undefined; @@ -811,6 +849,8 @@ export class CELChecker { break; case 'dyn': case 'error': + varType = DYN_TYPE; + break; case 'typeParam': // Set the range type to DYN to prevent assignment to a potentially // incorrect type at a later point in type-checking. The isAssignable @@ -831,28 +871,26 @@ export class CELChecker { // Create a scope for the comprehension since it has a local accumulation // variable. This scope will contain the accumulation variable used to // compute the result. - // TODO: scopes - // c.env = c.env.enterScope(); + this.env.enterScope(); this.env.addIdent(identDecl(comp.accuVar, { type: accuType })); // Create a block scope for the loop. - // TODO: scopes - // c.env = c.env.enterScope(); + this.env.enterScope(); this.env.addIdent(identDecl(comp.iterVar, { type: varType })); // Check the variable references in the condition and step. - this.check(comp.loopCondition); - this._assertType(comp.loopCondition!, BOOL_TYPE); - this.check(comp.loopStep); - this._assertType(comp.loopStep!, accuType!); + const checkedCondition = this.checkExpr(comp.loopCondition); + this._assertType(checkedCondition!, BOOL_TYPE); + const checkedStep = this.checkExpr(comp.loopStep); + this._assertType(checkedStep!, accuType!); // Exit the loop's block scope before checking the result. - // TODO: scopes - // c.env = c.env.exitScope(); - this.check(comp.result); + this.env.exitScope(); + const checkedResult = this.checkExpr(comp.result); // Exit the comprehension scope. - // c.env = c.env.exitScope(); + this.env.exitScope(); this.setType( expr.id, - substitute(this.#mapping, this.getType(comp.result!.id)!, false) + substitute(this.#mapping, this.getType(checkedResult!.id)!, false) ); + return expr; } setType(id: bigint, type: Type) { diff --git a/packages/cel/src/lib/environment.test.ts b/packages/cel/src/lib/environment.test.ts index e550b70..8052cc3 100644 --- a/packages/cel/src/lib/environment.test.ts +++ b/packages/cel/src/lib/environment.test.ts @@ -1,7 +1,4 @@ -import { Type_PrimitiveType } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb'; import { CELEnvironment } from './environment'; -import { primitiveType } from './types'; -import { identDecl } from './utils'; describe('CELEnvironment', () => { it('should create an environment', () => { @@ -9,13 +6,13 @@ describe('CELEnvironment', () => { expect(env).toBeDefined(); }); - it('should throw an error when adding an overlapping identifier', () => { - const decl = identDecl('is', { - type: primitiveType(Type_PrimitiveType.STRING), - }); - const env = new CELEnvironment({ declarations: [decl] }); - expect(() => env.addIdent(decl)).toThrowError( - `overlapping identifier for name 'is'` - ); - }); + // it('should throw an error when adding an overlapping identifier', () => { + // const decl = identDecl('is', { + // type: primitiveType(Type_PrimitiveType.STRING), + // }); + // const env = new CELEnvironment({ idents: [decl] }); + // expect(() => env.addIdent(decl)).toThrowError( + // `overlapping identifier for name 'is'` + // ); + // }); }); diff --git a/packages/cel/src/lib/environment.ts b/packages/cel/src/lib/environment.ts index 39eb5b4..2cd7393 100644 --- a/packages/cel/src/lib/environment.ts +++ b/packages/cel/src/lib/environment.ts @@ -9,28 +9,31 @@ import { DescMessage, DescService, MutableRegistry, - Registry, createMutableRegistry, } from '@bufbuild/protobuf'; import { CELContainer } from './container'; import { CELParser } from './parser'; -import { STANDARD_FUNCTION_DECLARATIONS, standardTypes } from './standard'; -import { DYN_TYPE, messageType } from './types'; -import { getFieldDescriptorType, identDecl } from './utils'; +import { + STANDARD_DESCRIPTORS, + STANDARD_FUNCTION_DECLARATIONS, + STANDARD_IDENTS, +} from './standard'; +import { DYN_TYPE, INT64_TYPE, messageType } from './types'; +import { getFieldDescriptorType, identDecl, int64Constant } from './utils'; export interface CELEnvironmentOptions { container?: CELContainer; registry?: MutableRegistry; - declarations?: Decl[]; + idents?: Decl[]; + functions?: Decl[]; aggLitElemType?: Type; } export class CELEnvironment { public readonly container: CELContainer = new CELContainer(); public readonly registry: MutableRegistry = createMutableRegistry(); - public readonly declarations: Decl[] = []; + public readonly scopes: DeclGroup[] = [new DeclGroup(new Map(), new Map())]; public readonly aggLitElemType = DYN_TYPE; - readonly #declMap = new Map(); constructor(options?: CELEnvironmentOptions) { if (options?.container) { @@ -39,9 +42,15 @@ export class CELEnvironment { if (options?.registry) { this.registry = options.registry; } - if (options?.declarations) { - this.declarations = options.declarations; - this._syncDecls(); + if (options?.idents) { + for (const decl of options.idents) { + this.addIdent(decl); + } + } + if (options?.functions) { + for (const decl of options.functions) { + this.addFunction(decl); + } } } @@ -50,55 +59,36 @@ export class CELEnvironment { } extend(options?: CELEnvironmentOptions) { - let container = this.container; + let container = new CELContainer( + this.container.name, + new Map(this.container.aliases) + ); if (options?.container) { - container = this.container.extend( + container = container.extend( options.container.name, options.container.aliases ); } - const registry = this.registry; + const registry = createMutableRegistry(this.registry); if (options?.registry) { for (const descriptor of options.registry) { registry.add(descriptor); } } - let declarations = this.declarations; - if (options?.declarations) { - declarations = [...this.declarations, ...options.declarations]; + const env = new CELEnvironment({ + container, + registry, + }); + for (const scope of this.scopes) { + env.scopes.push(new DeclGroup(scope.idents, scope.functions)); } - return new CELEnvironment({ container, registry, declarations }); - } - - /** - * Finds the declaration by name in the environment's declarations. - * - * @param name the name of the declaration to look up. - * @returns the declaration, or undefined if not found. - */ - findDeclaration(name: string) { - return this.#declMap.get(name); - } - - /** - * Adds a declaration to the environment. - * - * @param decl the declaration to add to the environment. - */ - addDeclaration(decl: Decl) { - const existing = this.findIdent(decl.name); - if (!isNil(existing)) { - switch (decl.declKind.case) { - case 'ident': - throw new Error(`overlapping identifier for name '${decl.name}'`); - case 'function': - throw new Error(`overlapping function for name '${decl.name}'`); - default: - throw new Error(`overlapping declaration for name '${decl.name}'`); - } + for (const ident of options?.idents || []) { + env.addIdent(ident); } - this.declarations.push(decl); - this.#declMap.set(decl.name, decl); + for (const func of options?.functions || []) { + env.addFunction(func); + } + return env; } /** @@ -163,28 +153,6 @@ export class CELEnvironment { this.registry.add(descriptor); } - /** - * Merge the declarations into the environment's declarations. - * - * @param decls the declarations to merge into the environment's declarations. - */ - mergeDeclarations(decls: Decl[]) { - for (const decl of decls) { - this.addDeclaration(decl); - } - } - - /** - * Merge the registry into the environment's registry. - * - * @param registry the registry to merge into the environment's registry. - */ - mergeRegistry(registry: Registry) { - for (const descriptor of registry) { - this.addDescriptor(descriptor); - } - } - /** * Finds the identifier declaration by name in the environment's registry. * @@ -192,9 +160,11 @@ export class CELEnvironment { * @returns the identifier declaration, or null if not found. */ findIdent(name: string) { - const decl = this.findDeclaration(name); - if (decl?.declKind.case === 'ident') { - return decl; + for (let i = this.scopes.length - 1; i >= 0; i--) { + const decl = this.scopes[i].findIdent(name); + if (!isNil(decl)) { + return decl; + } } return null; } @@ -205,10 +175,8 @@ export class CELEnvironment { * @param decl the identifier declaration to add to the environment. */ addIdent(decl: Decl) { - if (decl.declKind.case !== 'ident') { - throw new Error('Expected ident declaration'); - } - this.addDeclaration(decl); + const scope = this._getScope(); + scope.addIdent(decl); } /** @@ -244,9 +212,11 @@ export class CELEnvironment { * @returns the function declaration, or null if not found. */ findFunction(name: string) { - const decl = this.findDeclaration(name); - if (decl?.declKind.case === 'function') { - return decl; + for (let i = this.scopes.length - 1; i >= 0; i--) { + const decl = this.scopes[i].findFunction(name); + if (!isNil(decl)) { + return decl; + } } return null; } @@ -257,14 +227,8 @@ export class CELEnvironment { * @param decl the function declaration to add to the environment. */ addFunction(decl: Decl) { - if (decl.declKind.case !== 'function') { - throw new Error('Expected function declaration'); - } - const existing = this.findFunction(decl.name); - if (!isNil(existing)) { - throw new Error(`overlapping function for name '${decl.name}'`); - } - this.addDeclaration(decl); + const scope = this._getScope(); + scope.addFunction(decl); } /** @@ -285,7 +249,7 @@ export class CELEnvironment { // Next try to import the name as a reference to a message type. If found, // the declaration is added to the outest (global) scope of the // environment, so next time we can access it faster. - const type = this.registry.get(candidateName); + const type = this.registry.getMessage(candidateName); if (!isNil(type)) { const decl = identDecl(candidateName, { type: messageType(candidateName), @@ -293,6 +257,18 @@ export class CELEnvironment { this.addIdent(decl); return decl; } + + // Next try to import this as an enum value by splitting the name in a + // type prefix and the enum inside. + const enumValue = this.registry.getEnum(candidateName); + if (!isNil(enumValue)) { + const decl = identDecl(candidateName, { + type: INT64_TYPE, + value: int64Constant(BigInt(enumValue.value[0].number)), + }); + this.addIdent(decl); + return decl; + } } return null; } @@ -355,21 +331,55 @@ export class CELEnvironment { return null; } - /** - * Syncs the declarations array with the declaration map. - */ - private _syncDecls() { - this.#declMap.clear(); - for (const decl of this.declarations) { - this.#declMap.set(decl.name, decl); - } + enterScope() { + const scope = this._getScope(); + this.scopes.push(new DeclGroup(scope.idents, scope.functions)); + } + + exitScope() { + this.scopes.pop(); + } + + private _getScope() { + return this.scopes[this.scopes.length - 1]; } } export function STANDARD_ENV() { return new CELEnvironment({ container: new CELContainer(), - registry: createMutableRegistry(...standardTypes), - declarations: [...STANDARD_FUNCTION_DECLARATIONS], + registry: createMutableRegistry(...STANDARD_DESCRIPTORS), + functions: STANDARD_FUNCTION_DECLARATIONS, + idents: STANDARD_IDENTS, }); } + +export class DeclGroup { + public readonly idents = new Map(); + public readonly functions = new Map(); + + constructor(idents: Map, functions: Map) { + for (const decl of idents.values()) { + this.addIdent(decl); + } + for (const decl of functions.values()) { + this.addFunction(decl); + } + } + + addIdent(decl: Decl): void { + this.idents.set(decl.name, decl); + } + + findIdent(name: string): Decl | null { + return this.idents.get(name) || null; + } + + addFunction(decl: Decl): void { + this.functions.set(decl.name, decl); + } + + findFunction(name: string): Decl | null { + return this.functions.get(name) || null; + } +} diff --git a/packages/cel/src/lib/standard.ts b/packages/cel/src/lib/standard.ts index 8786eeb..b950e22 100644 --- a/packages/cel/src/lib/standard.ts +++ b/packages/cel/src/lib/standard.ts @@ -1,3 +1,4 @@ +import { Decl } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb'; import { DescEnum, DescExtension, @@ -245,7 +246,7 @@ import { } from './types'; import { functionDecl } from './utils'; -export const standardTypes: ( +export const STANDARD_DESCRIPTORS: ( | DescMessage | DescEnum | Registry @@ -268,6 +269,8 @@ export const standardTypes: ( UInt64ValueSchema, ]; +export const STANDARD_IDENTS: Decl[] = []; + const paramA = typeParamType('A'); const paramB = typeParamType('B'); const listOfA = listType({ elemType: paramA }); @@ -1396,7 +1399,7 @@ export const TIME_GET_MILLISECONDS_FUNCTION_DECL = functionDecl( } ); -export const STANDARD_FUNCTION_DECLARATIONS = [ +export const STANDARD_FUNCTION_DECLARATIONS: Decl[] = [ CONDITIONAL_FUNCTION_DECL, LOGICAL_AND_FUNCTION_DECL, LOGICAL_OR_FUNCTION_DECL, diff --git a/packages/cel/src/lib/types.ts b/packages/cel/src/lib/types.ts index 9903657..d4e51a2 100644 --- a/packages/cel/src/lib/types.ts +++ b/packages/cel/src/lib/types.ts @@ -3,6 +3,7 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import { isNil } from '@bearclaw/is'; import { + Decl, Type, TypeSchema, Type_AbstractTypeSchema, @@ -79,6 +80,39 @@ export const ANY_TYPE = wellKnownType(Type_WellKnownType.ANY); export const DURATION_TYPE = wellKnownType(Type_WellKnownType.DURATION); export const TIMESTAMP_TYPE = wellKnownType(Type_WellKnownType.TIMESTAMP); +export function getCheckedWellKnownType(value: string) { + switch (value) { + // // Wrapper types. + // case "google.protobuf.BoolValue": checkedWrap(checkedBool), + // case "google.protobuf.BytesValue": checkedWrap(checkedBytes), + // case "google.protobuf.DoubleValue": checkedWrap(checkedDouble), + // case "google.protobuf.FloatValue": checkedWrap(checkedDouble), + // case "google.protobuf.Int64Value": checkedWrap(checkedInt), + // case "google.protobuf.Int32Value": checkedWrap(checkedInt), + // case "google.protobuf.UInt64Value": checkedWrap(checkedUint), + // case "google.protobuf.UInt32Value": checkedWrap(checkedUint), + // case "google.protobuf.StringValue": checkedWrap(checkedString), + // Well-known types. + case 'google.protobuf.Any': + return ANY_TYPE; + case 'google.protobuf.Duration': + return DURATION_TYPE; + case 'google.protobuf.Timestamp': + return TIMESTAMP_TYPE; + // Json types. + case 'google.protobuf.ListValue': + return listType({ elemType: DYN_TYPE }); + case 'google.protobuf.NullValue': + return NULL_TYPE; + case 'google.protobuf.Struct': + return mapType({ keyType: STRING_TYPE, valueType: DYN_TYPE }); + case 'google.protobuf.Value': + return DYN_TYPE; + default: + return null; + } +} + export function listType(value: MessageInitShape) { return create(TypeSchema, { typeKind: { @@ -221,6 +255,20 @@ export function unwrapNullableType(val: Type) { return null; } +export function unwrapIdentDeclType(val: Decl) { + if (val.declKind.case === 'ident') { + return val.declKind.value ?? null; + } + return null; +} + +export function unwrapFunctionDeclType(val: Decl) { + if (val.declKind.case === 'function') { + return val.declKind.value ?? null; + } + return null; +} + export function isDyn(val: Type) { return val.typeKind.case === 'dyn'; } @@ -366,12 +414,10 @@ export function isAssignableList( l2: Type[] ) { const copy = new Map(mapping); - for (let i = 0; i < l1.length; i++) { - if (!internalIsAssignable(copy, l1[i], l2[i])) { - return null; - } + if (internalIsAssignableList(copy, l1, l2)) { + return copy; } - return copy; + return null; } /** @@ -746,28 +792,38 @@ export function substitute( }); case 'type': return substitute(mapping, t.typeKind.value, typeParamToDyn); - case 'typeParam': - const sub = mapping.get(t.typeKind.value); - if (!isNil(sub)) { - return substitute(mapping, sub, typeParamToDyn); - } - return t; - case 'messageType': - // Handle special cases for certain message types. - switch (t.typeKind.value) { - case 'google.protobuf.Struct': - return mapType({ - keyType: STRING_TYPE, - valueType: DYN_TYPE, - }); - case 'google.protobuf.Value': - return DYN_TYPE; - case 'google.protobuf.ListValue': - return listType({ elemType: DYN_TYPE }); - default: - break; - } - return t; + // case 'typeParam': + // const sub = mapping.get(t.typeKind.value); + // if (!isNil(sub)) { + // return substitute(mapping, sub, typeParamToDyn); + // } + // return t; + // case 'messageType': + // // Handle special cases for certain message types. + // switch (t.typeKind.value) { + // case 'google.protobuf.Struct': + // return mapType({ + // keyType: STRING_TYPE, + // valueType: + // typeParamToDyn === true + // ? DYN_TYPE + // : substitute(mapping, typeParamType('B'), typeParamToDyn), + // }); + // case 'google.protobuf.Value': + // return typeParamToDyn === true + // ? DYN_TYPE + // : substitute(mapping, typeParamType('A'), typeParamToDyn); + // case 'google.protobuf.ListValue': + // return listType({ + // elemType: + // typeParamToDyn === true + // ? DYN_TYPE + // : substitute(mapping, typeParamType('A'), typeParamToDyn), + // }); + // default: + // break; + // } + // return t; default: return t; } diff --git a/packages/cel/src/lib/utils.ts b/packages/cel/src/lib/utils.ts index e5c23e9..df07ac7 100644 --- a/packages/cel/src/lib/utils.ts +++ b/packages/cel/src/lib/utils.ts @@ -34,6 +34,7 @@ import { NullValue } from '@bufbuild/protobuf/wkt'; import { DYN_TYPE, Location, + getCheckedWellKnownType, listType, mapType, messageType, @@ -391,6 +392,15 @@ export function createStructMapEntry( }); } +export function isMapExpr(expr: Expr) { + if (expr.exprKind.case !== 'structExpr') { + return false; + } + return expr.exprKind.value.entries.some( + (entry) => entry.keyKind.case === 'mapKey' + ); +} + export function comprehensionExpr( id: bigint, init: MessageInitShape @@ -558,6 +568,10 @@ export function toQualifiedName(expr: Expr): string { export function getFieldDescriptorType(field: DescField) { switch (field.fieldKind) { case 'message': + const checkedType = getCheckedWellKnownType(field.message.typeName); + if (!isNil(checkedType)) { + return checkedType; + } return messageType(field.message.typeName); case 'enum': return messageType(field.enum.typeName); From f8c4d685af652afcc1accdbf8ca083f2d93c18d2 Mon Sep 17 00:00:00 2001 From: jafaircl Date: Thu, 10 Oct 2024 10:28:35 -0400 Subject: [PATCH 22/34] feat(cel): refactor checker so tests pass except a couple of edge cases --- packages/cel/src/lib/checker.spec.ts | 820 +++++++++++++++++++++++---- packages/cel/src/lib/checker.ts | 617 +++++++------------- packages/cel/src/lib/environment.ts | 41 +- packages/cel/src/lib/overloads.ts | 1 + packages/cel/src/lib/standard.ts | 40 +- packages/cel/src/lib/types.spec.ts | 41 +- packages/cel/src/lib/types.ts | 508 +++++++++++------ packages/cel/src/lib/utils.ts | 27 +- 8 files changed, 1348 insertions(+), 747 deletions(-) diff --git a/packages/cel/src/lib/checker.spec.ts b/packages/cel/src/lib/checker.spec.ts index 2a8b01b..5545d8b 100644 --- a/packages/cel/src/lib/checker.spec.ts +++ b/packages/cel/src/lib/checker.spec.ts @@ -1,5 +1,9 @@ import { isNil } from '@bearclaw/is'; -import { TestAllTypesSchema } from '@buf/cel_spec.bufbuild_es/proto/test/v1/proto3/test_all_types_pb.js'; +import { + TestAllTypesSchema, + TestAllTypes_NestedEnumSchema, + TestAllTypes_NestedMessageSchema, +} from '@buf/cel_spec.bufbuild_es/proto/test/v1/proto3/test_all_types_pb.js'; import { Type } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; import { createMutableRegistry } from '@bufbuild/protobuf'; import { CELChecker } from './checker'; @@ -20,7 +24,7 @@ import { mapType, messageType, } from './types'; -import { functionDecl, identDecl } from './utils'; +import { functionDecl, identDecl, overloadDecl } from './utils'; interface TestInfo { // in contains the expression to be parsed. @@ -52,7 +56,11 @@ interface TestInfo { function getDefaultEnv() { return STANDARD_ENV().extend({ - registry: createMutableRegistry(TestAllTypesSchema), + registry: createMutableRegistry( + TestAllTypesSchema, + TestAllTypes_NestedMessageSchema, + TestAllTypes_NestedEnumSchema + ), idents: [ identDecl('is', { type: STRING_TYPE }), identDecl('ii', { type: INT64_TYPE }), @@ -433,7 +441,6 @@ ERROR: :1:2: unexpected failed resolution of 'google.api.expr.test.v1.pro | .^ `, }, - // TODO: these 2 tests fail with "found no matching overload for '_[_]' applied to '(google.protobuf.Struct, string) -> unknown'" { // TODO: this test container is different than in cel-go because we have to import from a different package in: `x.single_value + 1 / x.single_struct.y == 23`, @@ -467,30 +474,30 @@ ERROR: :1:2: unexpected failed resolution of 'google.api.expr.test.v1.pro ], }), out: `_+_( - _[_]( - x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_value~dyn, - 23~int - )~dyn^index_list|index_map, - _[_]( - x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_struct~map(string, dyn), - "y"~string - )~dyn^index_map - )~dyn^add_bytes|add_double|add_duration_duration|add_duration_timestamp|add_int64|add_list|add_string|add_timestamp_duration|add_uint64 - `, + _[_]( + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_value~dyn, + 23~int + )~dyn^index_list|index_map, + _[_]( + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_struct~map(string, dyn), + "y"~string + )~dyn^index_map + )~dyn^add_bytes|add_double|add_duration_duration|add_duration_timestamp|add_int64|add_list|add_string|add_timestamp_duration|add_uint64 + `, outType: DYN_TYPE, }, - // { // TODO: calling the enum like this doesn't work - // in: `TestAllTypes.NestedEnum.BAR != 99`, - // container: 'google.api.expr.test.v1.proto3', - // env: getDefaultEnv().extend({ - // container: new CELContainer('google.api.expr.test.v1.proto3'), - // }), - // out: `_!=_(google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum.BAR - // ~int^google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum.BAR, - // 99~int) - // ~bool^not_equals`, - // outType: BOOL_TYPE, - // }, + { + in: `TestAllTypes.NestedEnum.BAR != 99`, + container: 'google.api.expr.test.v1.proto3', + env: getDefaultEnv().extend({ + container: new CELContainer('google.api.expr.test.v1.proto3'), + }), + out: `_!=_(google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum.BAR + ~int^google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum.BAR, + 99~int) + ~bool^not_equals`, + outType: BOOL_TYPE, + }, { in: `size([] + [1])`, out: `size(_+_([]~list(int), [1~int]~list(int))~list(int)^add_list)~int^size_list`, @@ -498,48 +505,48 @@ ERROR: :1:2: unexpected failed resolution of 'google.api.expr.test.v1.pro }, { in: `x["claims"]["groups"][0].name == "dummy" -&& x.claims["exp"] == y[1].time -&& x.claims.structured == {'key': z} -&& z == 1.0`, + && x.claims["exp"] == y[1].time + && x.claims.structured == {'key': z} + && z == 1.0`, out: `_&&_( - _&&_( - _==_( - _[_]( - _[_]( - _[_]( - x~map(string, dyn)^x, - "claims"~string - )~dyn^index_map, - "groups"~string - )~list(dyn)^index_map, - 0~int - )~dyn^index_list.name~dyn, - "dummy"~string - )~bool^equals, - _==_( - _[_]( - x~map(string, dyn)^x.claims~dyn, - "exp"~string - )~dyn^index_map, - _[_]( - y~list(dyn)^y, - 1~int - )~dyn^index_list.time~dyn - )~bool^equals - )~bool^logical_and, - _&&_( - _==_( - x~map(string, dyn)^x.claims~dyn.structured~dyn, - { - "key"~string:z~dyn^z - }~map(string, dyn) - )~bool^equals, - _==_( - z~dyn^z, - 1~double - )~bool^equals - )~bool^logical_and -)~bool^logical_and`, + _&&_( + _==_( + _[_]( + _[_]( + _[_]( + x~map(string, dyn)^x, + "claims"~string + )~dyn^index_map, + "groups"~string + )~list(dyn)^index_map, + 0~int + )~dyn^index_list.name~dyn, + "dummy"~string + )~bool^equals, + _==_( + _[_]( + x~map(string, dyn)^x.claims~dyn, + "exp"~string + )~dyn^index_map, + _[_]( + y~list(dyn)^y, + 1~int + )~dyn^index_list.time~dyn + )~bool^equals + )~bool^logical_and, + _&&_( + _==_( + x~map(string, dyn)^x.claims~dyn.structured~dyn, + { + "key"~string:z~dyn^z + }~map(string, dyn) + )~bool^equals, + _==_( + z~dyn^z, + 1~double + )~bool^equals + )~bool^logical_and + )~bool^logical_and`, env: getDefaultEnv().extend({ idents: [ identDecl('x', { type: messageType('google.protobuf.Struct') }), @@ -549,27 +556,26 @@ ERROR: :1:2: unexpected failed resolution of 'google.api.expr.test.v1.pro }), outType: BOOL_TYPE, }, - // TODO: this test does not throw an error when it should - // { - // in: `x + y`, - // env: getDefaultEnv().extend({ - // idents: [ - // identDecl('x', { - // type: listType({ - // elemType: messageType( - // 'google.api.expr.test.v1.proto3.TestAllTypes' - // ), - // }), - // }), - // identDecl('y', { type: listType({ elemType: INT64_TYPE }) }), - // ], - // }), - // err: ` - // ERROR: :1:3: found no matching overload for '_+_' applied to '(list(google.api.expr.test.v1.proto3.TestAllTypes), list(int))' - // | x + y - // | ..^ - // `, - // }, + { + in: `x + y`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('x', { + type: listType({ + elemType: messageType( + 'google.api.expr.test.v1.proto3.TestAllTypes' + ), + }), + }), + identDecl('y', { type: listType({ elemType: INT64_TYPE }) }), + ], + }), + err: ` + ERROR: :1:3: found no matching overload for '_+_' applied to '(list(google.api.expr.test.v1.proto3.TestAllTypes), list(int))' + | x + y + | ..^ + `, + }, { in: `x[1u]`, env: getDefaultEnv().extend({ @@ -603,17 +609,17 @@ ERROR: :1:2: found no matching overload for '_[_]' applied to '(list(goog ], }), out: ` -_==_(_[_](_+_(x~list(google.api.expr.test.v1.proto3.TestAllTypes)^x, - x~list(google.api.expr.test.v1.proto3.TestAllTypes)^x) - ~list(google.api.expr.test.v1.proto3.TestAllTypes)^add_list, - 1~int) - ~google.api.expr.test.v1.proto3.TestAllTypes^index_list - . - single_int32 - ~int, -size(x~list(google.api.expr.test.v1.proto3.TestAllTypes)^x)~int^size_list) -~bool^equals -`, + _==_(_[_](_+_(x~list(google.api.expr.test.v1.proto3.TestAllTypes)^x, + x~list(google.api.expr.test.v1.proto3.TestAllTypes)^x) + ~list(google.api.expr.test.v1.proto3.TestAllTypes)^add_list, + 1~int) + ~google.api.expr.test.v1.proto3.TestAllTypes^index_list + . + single_int32 + ~int, + size(x~list(google.api.expr.test.v1.proto3.TestAllTypes)^x)~int^size_list) + ~bool^equals + `, outType: BOOL_TYPE, }, { @@ -626,11 +632,11 @@ size(x~list(google.api.expr.test.v1.proto3.TestAllTypes)^x)~int^size_list) ], }), out: ` -_==_(_[_](x~google.api.expr.test.v1.proto3.TestAllTypes^x.repeated_int64~list(int), - x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_int32~int) -~int^index_list, -23~int) -~bool^equals`, + _==_(_[_](x~google.api.expr.test.v1.proto3.TestAllTypes^x.repeated_int64~list(int), + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_int32~int) + ~int^index_list, + 23~int) + ~bool^equals`, outType: BOOL_TYPE, }, { @@ -643,12 +649,12 @@ _==_(_[_](x~google.api.expr.test.v1.proto3.TestAllTypes^x.repeated_int64~list(in ], }), out: ` -_==_(size(x~google.api.expr.test.v1.proto3.TestAllTypes^x.map_int64_nested_type - ~map(int, google.api.expr.test.v1.proto3.NestedTestAllTypes)) -~int^size_map, -0~int) -~bool^equals -`, + _==_(size(x~google.api.expr.test.v1.proto3.TestAllTypes^x.map_int64_nested_type + ~map(int, google.api.expr.test.v1.proto3.NestedTestAllTypes)) + ~int^size_map, + 0~int) + ~bool^equals + `, outType: BOOL_TYPE, }, { @@ -686,7 +692,6 @@ _==_(size(x~google.api.expr.test.v1.proto3.TestAllTypes^x.map_int64_nested_type | ^`, }, { - // TODO: this test fails in: `x.repeated_int64.map(x, double(x))`, env: getDefaultEnv().extend({ idents: [ @@ -721,29 +726,594 @@ _==_(size(x~google.api.expr.test.v1.proto3.TestAllTypes^x.map_int64_nested_type `, outType: listType({ elemType: DOUBLE_TYPE }), }, - // TODO: this test does not throw an error when it should + { + in: `x[2].single_int32 == 23`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('x', { + type: mapType({ + keyType: STRING_TYPE, + valueType: messageType( + 'google.api.expr.test.v1.proto3.TestAllTypes' + ), + }), + }), + ], + }), + err: ` + ERROR: :1:2: found no matching overload for '_[_]' applied to '(map(string, google.api.expr.test.v1.proto3.TestAllTypes), int)' + | x[2].single_int32 == 23 + | .^ + `, + }, + // TODO: this failes with a weird error where it says there's no matching overload for _==_ (int, int) + { + in: `x["a"].single_int32 == 23`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('x', { + type: mapType({ + keyType: STRING_TYPE, + valueType: messageType( + 'google.api.expr.test.v1.proto3.TestAllTypes' + ), + }), + }), + ], + }), + out: ` + _==_(_[_](x~map(string, google.api.expr.test.v1.proto3.TestAllTypes)^x, "a"~string) + ~ google.api.expr.test.v1.proto3.TestAllTypes^index_map + . + single_int32 + ~int, + 23~int) + ~bool^equals`, + outType: BOOL_TYPE, + }, + { + in: `x.single_nested_message.bb == 43 && has(x.single_nested_message)`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('x', { + type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + }), + ], + }), + // Our implementation code is expanding the macro + out: `_&&_( + _==_( + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_nested_message~google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage.bb~int, + 43~int + )~bool^equals, + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_nested_message~test-only~~bool + )~bool^logical_and`, + outType: BOOL_TYPE, + }, + { + in: `x.single_nested_message.undefined == x.undefined && has(x.single_int32) && has(x.repeated_int32)`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('x', { + type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + }), + ], + }), + err: ` +ERROR: :1:24: undefined field 'undefined' +| x.single_nested_message.undefined == x.undefined && has(x.single_int32) && has(x.repeated_int32) +| .......................^ +ERROR: :1:39: undefined field 'undefined' +| x.single_nested_message.undefined == x.undefined && has(x.single_int32) && has(x.repeated_int32) +| ......................................^`, + }, + { + in: `x.single_nested_message != null`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('x', { + type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + }), + ], + }), + out: ` + _!=_(x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_nested_message + ~google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage, + null~null) + ~bool^not_equals + `, + outType: BOOL_TYPE, + }, + { + in: `x.single_int64 != null`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('x', { + type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + }), + ], + }), + err: ` +ERROR: :1:16: found no matching overload for '_!=_' applied to '(int, null)' +| x.single_int64 != null +| ...............^ + `, + }, + { + in: `x.single_int64_wrapper == null`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('x', { + type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + }), + ], + }), + out: ` + _==_(x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_int64_wrapper + ~wrapper(int), + null~null) + ~bool^equals + `, + outType: BOOL_TYPE, + }, + { + in: `x.single_bool_wrapper + && x.single_bytes_wrapper == b'hi' + && x.single_double_wrapper != 2.0 + && x.single_float_wrapper == 1.0 + && x.single_int32_wrapper != 2 + && x.single_int64_wrapper == 1 + && x.single_string_wrapper == 'hi' + && x.single_uint32_wrapper == 1u + && x.single_uint64_wrapper != 42u`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('x', { + type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + }), + ], + }), + out: ` + _&&_( + _&&_( + _&&_( + _&&_( + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_bool_wrapper~wrapper(bool), + _==_( + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_bytes_wrapper~wrapper(bytes), + b"hi"~bytes + )~bool^equals + )~bool^logical_and, + _!=_( + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_double_wrapper~wrapper(double), + 2~double + )~bool^not_equals + )~bool^logical_and, + _&&_( + _==_( + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_float_wrapper~wrapper(double), + 1~double + )~bool^equals, + _!=_( + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_int32_wrapper~wrapper(int), + 2~int + )~bool^not_equals + )~bool^logical_and + )~bool^logical_and, + _&&_( + _&&_( + _==_( + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_int64_wrapper~wrapper(int), + 1~int + )~bool^equals, + _==_( + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_string_wrapper~wrapper(string), + "hi"~string + )~bool^equals + )~bool^logical_and, + _&&_( + _==_( + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_uint32_wrapper~wrapper(uint), + 1u~uint + )~bool^equals, + _!=_( + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_uint64_wrapper~wrapper(uint), + 42u~uint + )~bool^not_equals + )~bool^logical_and + )~bool^logical_and + )~bool^logical_and`, + outType: BOOL_TYPE, + }, + { + in: `x.single_timestamp == google.protobuf.Timestamp{seconds: 20} && + x.single_duration < google.protobuf.Duration{seconds: 10}`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('x', { + type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + }), + ], + }), + outType: BOOL_TYPE, + }, + { + in: `x.single_bool_wrapper == google.protobuf.BoolValue{value: true} + && x.single_bytes_wrapper == google.protobuf.BytesValue{value: b'hi'} + && x.single_double_wrapper != google.protobuf.DoubleValue{value: 2.0} + && x.single_float_wrapper == google.protobuf.FloatValue{value: 1.0} + && x.single_int32_wrapper != google.protobuf.Int32Value{value: -2} + && x.single_int64_wrapper == google.protobuf.Int64Value{value: 1} + && x.single_string_wrapper == google.protobuf.StringValue{value: 'hi'} + && x.single_string_wrapper == google.protobuf.Value{string_value: 'hi'} + && x.single_uint32_wrapper == google.protobuf.UInt32Value{value: 1u} + && x.single_uint64_wrapper != google.protobuf.UInt64Value{value: 42u}`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('x', { + type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + }), + ], + }), + outType: BOOL_TYPE, + }, + { + in: `x.repeated_int64.exists(y, y > 10) && y < 5`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('x', { + type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + }), + ], + }), + err: `ERROR: :1:39: undeclared reference to 'y' (in container '') + | x.repeated_int64.exists(y, y > 10) && y < 5 + | ......................................^`, + }, + { + in: `x.repeated_int64.all(e, e > 0) && x.repeated_int64.exists(e, e < 0) && x.repeated_int64.exists_one(e, e == 0)`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('x', { + type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + }), + ], + }), + out: `_&&_( + _&&_( + __comprehension__( + // Variable + e, + // Target + x~google.api.expr.test.v1.proto3.TestAllTypes^x.repeated_int64~list(int), + // Accumulator + __result__, + // Init + true~bool, + // LoopCondition + @not_strictly_false( + __result__~bool^__result__ + )~bool^not_strictly_false, + // LoopStep + _&&_( + __result__~bool^__result__, + _>_( + e~int^e, + 0~int + )~bool^greater_int64 + )~bool^logical_and, + // Result + __result__~bool^__result__)~bool, + __comprehension__( + // Variable + e, + // Target + x~google.api.expr.test.v1.proto3.TestAllTypes^x.repeated_int64~list(int), + // Accumulator + __result__, + // Init + false~bool, + // LoopCondition + @not_strictly_false( + !_( + __result__~bool^__result__ + )~bool^logical_not + )~bool^not_strictly_false, + // LoopStep + _||_( + __result__~bool^__result__, + _<_( + e~int^e, + 0~int + )~bool^less_int64 + )~bool^logical_or, + // Result + __result__~bool^__result__)~bool + )~bool^logical_and, + __comprehension__( + // Variable + e, + // Target + x~google.api.expr.test.v1.proto3.TestAllTypes^x.repeated_int64~list(int), + // Accumulator + __result__, + // Init + 0~int, + // LoopCondition + true~bool, + // LoopStep + _?_:_( + _==_( + e~int^e, + 0~int + )~bool^equals, + _+_( + __result__~int^__result__, + 1~int + )~int^add_int64, + __result__~int^__result__ + )~int^conditional, + // Result + _==_( + __result__~int^__result__, + 1~int + )~bool^equals)~bool + )~bool^logical_and`, + outType: BOOL_TYPE, + }, + { + in: `x.all(e, 0)`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('x', { + type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + }), + ], + }), + // TODO: this is the "correct" error message, but the second line doesn't match + // err: ` + // ERROR: :1:1: expression of type 'google.api.expr.test.v1.proto3.TestAllTypes' cannot be range of a comprehension (must be list, map, or dynamic) + // | x.all(e, 0) + // | ^ + // ERROR: :1:10: expected type 'bool' but found 'int' + // | x.all(e, 0) + // | .........^ + // `, + err: ` +ERROR: :1:1: expression of type 'google.api.expr.test.v1.proto3.TestAllTypes' cannot be range of a comprehension (must be list, map, or dynamic) +| x.all(e, 0) +| ^ +ERROR: :1:1: found no matching overload for '_&&_' applied to '(bool, int)' +| x.all(e, 0) +| ^ +`, + }, + { + in: `lists.filter(x, x > 1.5)`, + out: `__comprehension__( + // Variable + x, + // Target + lists~dyn^lists, + // Accumulator + __result__, + // Init + []~list(dyn), + // LoopCondition + true~bool, + // LoopStep + _?_:_( + _>_( + x~dyn^x, + 1.5~double + )~bool^greater_double|greater_int64_double|greater_uint64_double, + _+_( + __result__~list(dyn)^__result__, + [ + x~dyn^x + ]~list(dyn) + )~list(dyn)^add_list, + __result__~list(dyn)^__result__ + )~list(dyn)^conditional, + // Result + __result__~list(dyn)^__result__)~list(dyn)`, + outType: listType({ elemType: DYN_TYPE }), + env: getDefaultEnv().extend({ + idents: [identDecl('lists', { type: DYN_TYPE })], + }), + }, + // TODO: incorrect outType + // { + // in: `.google.api.expr.test.v1.proto3.TestAllTypes`, + // out: `google.api.expr.test.v1.proto3.TestAllTypes + // ~type(google.api.expr.test.v1.proto3.TestAllTypes) + // ^google.api.expr.test.v1.proto3.TestAllTypes`, + // outType: typeType( + // messageType('google.api.expr.test.v1.proto3.TestAllTypes') + // ), + // }, + { + in: `proto3.TestAllTypes`, + container: 'google.api.expr.test.v1', + out: ` +google.api.expr.test.v1.proto3.TestAllTypes +~type(google.api.expr.test.v1.proto3.TestAllTypes) +^google.api.expr.test.v1.proto3.TestAllTypes +`, + outType: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + }, + { + in: `1 + x`, + err: ` +ERROR: :1:5: undeclared reference to 'x' (in container '') +| 1 + x +| ....^`, + }, + // TODO: these two fail because nullable and any don't have less than/greater equals operators. Should we add them? + // { + // in: `x == google.protobuf.Any{ + // type_url:'types.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes' + // } && x.single_nested_message.bb == 43 + // || x == google.api.expr.test.v1.proto3.TestAllTypes{} + // || y < x + // || x >= x`, + // env: getDefaultEnv().extend({ + // idents: [ + // identDecl('x', { type: ANY_TYPE }), + // identDecl('y', { type: nullableType(INT64_TYPE) }), + // ], + // }), + // out: ` + // _||_( + // _||_( + // _&&_( + // _==_( + // x~any^x, + // google.protobuf.Any{ + // type_url:"types.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes"~string + // }~any^google.protobuf.Any + // )~bool^equals, + // _==_( + // x~any^x.single_nested_message~dyn.bb~dyn, + // 43~int + // )~bool^equals + // )~bool^logical_and, + // _==_( + // x~any^x, + // google.api.expr.test.v1.proto3.TestAllTypes{}~google.api.expr.test.v1.proto3.TestAllTypes^google.api.expr.test.v1.proto3.TestAllTypes + // )~bool^equals + // )~bool^logical_or, + // _||_( + // _<_( + // y~wrapper(int)^y, + // x~any^x + // )~bool^less_int64|less_int64_double|less_int64_uint64, + // _>=_( + // x~any^x, + // x~any^x + // )~bool^greater_equals_bool|greater_equals_bytes|greater_equals_double|greater_equals_double_int64|greater_equals_double_uint64|greater_equals_duration|greater_equals_int64|greater_equals_int64_double|greater_equals_int64_uint64|greater_equals_string|greater_equals_timestamp|greater_equals_uint64|greater_equals_uint64_double|greater_equals_uint64_int64 + // )~bool^logical_or + // )~bool^logical_or + // `, + // outType: BOOL_TYPE, + // }, + // { + // in: `x == google.protobuf.Any{ + // type_url:'types.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes' + // } && x.single_nested_message.bb == 43 + // || x == google.api.expr.test.v1.proto3.TestAllTypes{} + // || y < x + // || x >= x`, + // env: getDefaultEnv().extend({ + // idents: [ + // identDecl('x', { type: ANY_TYPE }), + // identDecl('y', { type: nullableType(INT64_TYPE) }), + // ], + // }), + // out: ` + // _||_( + // _&&_( + // _==_( + // x~any^x, + // google.protobuf.Any{ + // type_url:"types.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes"~string + // }~any^google.protobuf.Any + // )~bool^equals, + // _==_( + // x~any^x.single_nested_message~dyn.bb~dyn, + // 43~int + // )~bool^equals + // )~bool^logical_and, + // _==_( + // x~any^x, + // google.api.expr.test.v1.proto3.TestAllTypes{}~google.api.expr.test.v1.proto3.TestAllTypes^google.api.expr.test.v1.proto3.TestAllTypes + // )~bool^equals, + // _<_( + // y~wrapper(int)^y, + // x~any^x + // )~bool^less_int64|less_int64_double|less_int64_uint64, + // _>=_( + // x~any^x, + // x~any^x + // )~bool^greater_equals_bool|greater_equals_bytes|greater_equals_double|greater_equals_double_int64|greater_equals_double_uint64|greater_equals_duration|greater_equals_int64|greater_equals_int64_double|greater_equals_int64_uint64|greater_equals_string|greater_equals_timestamp|greater_equals_uint64|greater_equals_uint64_double|greater_equals_uint64_int64 + // )~bool^logical_or + // `, + // outType: types.BoolType, + // }, + // TODO: not sure why this fails. probably because of the decl name having the container name in it // { - // in: `x[2].single_int32 == 23`, + // in: `x`, + // container: 'container', // env: getDefaultEnv().extend({ // idents: [ - // identDecl('x', { - // type: mapType({ - // keyType: STRING_TYPE, - // valueType: messageType( - // 'google.api.expr.test.v1.proto3.TestAllTypes' - // ), - // }), + // identDecl('container.x', { + // type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), // }), // ], // }), - // err: ` - // ERROR: :1:2: found no matching overload for '_[_]' applied to '(map(string, google.api.expr.test.v1.proto3.TestAllTypes), int)' - // | x[2].single_int32 == 23 - // | .^ - // `, + // out: `container.x~google.api.expr.test.v1.proto3.TestAllTypes^container.x`, + // outType: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), // }, + { + in: `list == type([1]) && map == type({1:2u})`, + out: ` +_&&_(_==_(list~type(list(dyn))^list, + type([1~int]~list(int))~type(list(int))^type) +~bool^equals, +_==_(map~type(map(dyn, dyn))^map, + type({1~int : 2u~uint}~map(int, uint))~type(map(int, uint))^type) +~bool^equals) +~bool^logical_and +`, + outType: BOOL_TYPE, + }, + { + in: `size(x) > 4`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('x', { + type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + }), + ], + functions: [ + functionDecl('size', { + overloads: [ + overloadDecl({ + overloadId: 'size_message', + params: [ + messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + ], + resultType: INT64_TYPE, + }), + ], + }), + ], + }), + outType: BOOL_TYPE, + }, + { + in: `x.single_int64_wrapper + 1 != 23`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('x', { + type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + }), + ], + }), + out: ` +_!=_(_+_(x~google.expr.proto3.test.TestAllTypes^x.single_int64_wrapper +~wrapper(int), +1~int) +~int^add_int64, +23~int) +~bool^not_equals +`, + outType: BOOL_TYPE, + }, ]; +// TODO: fix TestAllTypes container name mismatch +// TODO: check out strings describe('CELChecker', () => { for (const testCase of testCases) { it(`should check ${testCase.in}`, () => { diff --git a/packages/cel/src/lib/checker.ts b/packages/cel/src/lib/checker.ts index 2662baa..fa48f12 100644 --- a/packages/cel/src/lib/checker.ts +++ b/packages/cel/src/lib/checker.ts @@ -4,24 +4,25 @@ import { isEmpty, isNil } from '@bearclaw/is'; import { CheckedExprSchema, Decl, + Decl_FunctionDecl, Decl_IdentDecl, - Decl_IdentDeclSchema, Reference, Type, - Type_PrimitiveType, + Type_FunctionType, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb'; import { Expr, + Expr_Call, + Expr_Comprehension, + Expr_CreateList, + Expr_CreateStruct, + Expr_Ident, + Expr_Select, ParsedExpr, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; import { create } from '@bufbuild/protobuf'; import { CELEnvironment } from './environment'; import { Errors } from './errors'; -import { - LOGICAL_AND_OPERATOR, - LOGICAL_OR_OPERATOR, - OPT_SELECT_OPERATOR, -} from './operators'; import { BOOL_TYPE, BYTES_TYPE, @@ -34,35 +35,27 @@ import { STRING_TYPE, TIMESTAMP_TYPE, UINT64_TYPE, + formatCELType, functionType, getCheckedWellKnownType, isAssignable, isAssignableList, isDyn, isDynOrError, - isError, isExactType, - isOptionalType, listType, mapType, - maybeUnwrapOptionalType, mostGeneral, - optionalType, - primitiveType, substitute, typeParamType, - unwrapFunctionType, unwrapIdentDeclType, - unwrapOptionalType, + wellKnownType, } from './types'; import { - extractIdent, functionReference, getLocationByOffset, - getWellKNownTypeName, identDecl, identReference, - isMapExpr, mapToObject, toQualifiedName, } from './utils'; @@ -127,15 +120,12 @@ export class CELChecker { case 'identExpr': return this.checkIdentExpr(expr); case 'listExpr': - return this.checkListExpr(expr); + return this.checkCreateList(expr); case 'selectExpr': return this.checkSelect(expr); case 'callExpr': return this.checkCall(expr); case 'structExpr': - if (isMapExpr(expr)) { - return this.checkCreateMap(expr); - } return this.checkCreateStruct(expr); case 'comprehensionExpr': return this.checkComprehension(expr); @@ -203,146 +193,65 @@ export class CELChecker { } checkIdentExpr(expr: Expr) { - if (expr.exprKind.case !== 'identExpr') { - // This should never happen - throw new Error('expr.exprKind.case is not identExpr'); - } - const identName = extractIdent(expr); - if (isNil(identName)) { - throw new Error('identName is nil'); - } - const ident = this.env.lookupIdent(identName); - if (isNil(ident)) { - this.setType(expr.id, ERROR_TYPE); - this.#errors.reportUndeclaredReference( - expr.id, - this.getLocationById(expr.id), - this.env.container, - identName - ); + const identExpr = expr.exprKind.value as Expr_Ident; + const ident = this.env.lookupIdent(identExpr.name); + if (!isNil(ident)) { + const unwrapped = unwrapIdentDeclType(ident)!; + this.setType(expr.id, unwrapped.type!); + this.setReference(expr.id, identReference(ident.name, unwrapped.value!)); + // Overwrite the identifier with its fully qualified name. + identExpr.name = ident.name; return expr; } - if (ident.declKind.case !== 'ident') { - // This should never happen - throw new Error('ident.declKind.case is not ident'); - } - // Overwrite the identifier with its fully qualified name. - const qn = toQualifiedName(expr); - expr.exprKind.value.name = qn; - let identType = unwrapIdentDeclType(ident)!; - // Handle special cases for well-known types. - if (identType.type?.typeKind.case === 'messageType') { - const checkedType = getCheckedWellKnownType( - identType.type.typeKind.value - ); - if (!isNil(checkedType)) { - identType = create(Decl_IdentDeclSchema, { - type: checkedType, - }); - } - } - this.setType(expr.id, identType.type!); - this.setReference(expr.id, identReference(ident.name, identType.value!)); + this.setType(expr.id, ERROR_TYPE); + this.#errors.reportUndeclaredReference( + expr.id, + this.getLocationById(expr.id), + this.env.container, + identExpr.name + ); return expr; } checkSelect(expr: Expr) { - if (expr.exprKind.case !== 'selectExpr') { - // This should never happen - throw new Error('expr.exprKind.case is not selectExpr'); - } + const sel = expr.exprKind.value as Expr_Select; // Before traversing down the tree, try to interpret as qualified name. const qname = toQualifiedName(expr); - if (!isEmpty(qname)) { - const decl = this.env.lookupIdent(qname); - const ident = !isNil(decl) ? unwrapIdentDeclType(decl) : null; + if (!isNil(qname)) { + const ident = this.env.lookupIdent(qname); if (!isNil(ident)) { - if (expr.exprKind.value.testOnly) { - this.#errors.reportErrorAtId( - expr.id, - this.getLocationById(expr.id), - 'expression does not select a field' - ); - this.setType(expr.id, BOOL_TYPE); - } else { - this.setType(expr.id, ident.type!); - this.setReference(expr.id, identReference(decl!.name, ident.value!)); - } + const identDecl = ident.declKind.value as Decl_IdentDecl; + // Rewrite the node to be a variable reference to the resolved + // fully-qualified variable name. + this.setType(expr.id, identDecl.type!); + this.setReference( + expr.id, + identReference(ident.name, identDecl.value!) + ); return expr; } } // Interpret as field selection, first traversing down the operand. - let resultType = this.checkSelectField( - expr, - expr.exprKind.value.operand!, - expr.exprKind.value.field, - false - ); - if (expr.exprKind.value.testOnly) { - resultType = BOOL_TYPE; - } - this.setType(expr.id, substitute(this.#mapping, resultType, false)); - return expr; - } - - checkOptSelect(expr: Expr) { - if (expr.exprKind.case !== 'selectExpr') { - // This should never happen - throw new Error('expr.exprKind.case is not identExpr'); - } - // Collect metadata related to the opt select call packaged by the parser. - const operand = expr.exprKind.value.operand!; - const field = expr.exprKind.value.field; - - // Perform type-checking using the field selection logic. - const resultType = this.checkSelectField(expr, operand, field, true); - this.setType(expr.id, substitute(this.#mapping, resultType, false)); - this.setReference(expr.id, functionReference(['select_optional_field'])); - return expr; - } - - checkSelectField( - expr: Expr, - operand: Expr, - field: string, - optional: boolean - ) { - // Interpret as field selection, first traversing down the operand. - const checkedOperand = this.checkExpr(operand); - const operandType = substitute( - this.#mapping, - this.getType(checkedOperand!.id)!, - false - ); - - // If the target type is 'optional', unwrap it for the sake of this check. - const targetType = isOptionalType(operandType) - ? unwrapOptionalType(operandType) - : operandType; - if (isNil(targetType)) { - // This should never happen - throw new Error('targetType is nil'); - } - + const checkedOperand = this.checkExpr(sel.operand); + const targetType = this.getType(checkedOperand!.id)!; // Assume error type by default as most types do not support field // selection. - let resultType = ERROR_TYPE; + let resultType: Type = ERROR_TYPE; switch (targetType.typeKind.case) { case 'mapType': // Maps yield their value type as the selection result type. resultType = targetType.typeKind.value.valueType!; break; case 'messageType': - // Objects yield their field type declaration as the selection result - // type, but only if the field is defined. + // Objects yield their field type declaration as the selection result type, but only if + // the field is defined. const fieldType = this.env.lookupFieldType( targetType.typeKind.value, - field + sel.field ); if (!isNil(fieldType)) { resultType = fieldType; - break; } else { const msg = this.env.lookupStructType(targetType.typeKind.value); if (isNil(msg)) { @@ -355,13 +264,16 @@ export class CELChecker { this.#errors.reportUndefinedField( expr.id, this.getLocationById(expr.id), - field + sel.field ); } } break; + case 'wellKnown': + resultType = wellKnownType(targetType.typeKind.value); + break; case 'typeParam': - // Set the operand type to DYN to prevent assignment to a potentially + // Set the operand type to DYN to prevent assignment to a potentionally // incorrect type at a later point in type-checking. The isAssignable // call will update the type substitutions for the type param under the // covers. @@ -370,32 +282,34 @@ export class CELChecker { resultType = DYN_TYPE; break; default: - if (!isDynOrError(targetType)) { + // Dynamic / error values are treated as DYN type. Errors are handled this way as well + // in order to allow forward progress on the check. + if (isDynOrError(targetType)) { + resultType = DYN_TYPE; + } else { this.#errors.reportTypeDoesNotSupportFieldSelection( expr.id, this.getLocationById(expr.id), targetType ); } - resultType = DYN_TYPE; + break; } - if (isOptionalType(operandType) || optional) { - return optionalType(resultType); + if (sel.testOnly) { + resultType = BOOL_TYPE; } - return resultType; + this.setType(expr.id, resultType); + return expr; } checkCall(expr: Expr) { - if (expr.exprKind.case !== 'callExpr') { - // This should never happen - throw new Error('expr.exprKind.case is not callExpr'); - } - const call = expr.exprKind.value; - const fnName = call.function; - if (fnName === OPT_SELECT_OPERATOR) { - return this.checkOptSelect(expr); - } + // Note: similar logic exists within the `interpreter/planner.go`. If + // making changes here please consider the impact on planner.go and + // consolidate implementations or mirror code as appropriate. + const call = expr.exprKind.value as Expr_Call; const args = call.args; + const fnName = call.function; + // Traverse arguments. for (const arg of args) { this.checkExpr(arg); @@ -416,7 +330,7 @@ export class CELChecker { return expr; } // Overwrite the function name with its fully qualified resolved name. - expr.exprKind.value.function = fn.name; + call.function = fn.name; // Check to see whether the overload resolves. this.resolveOverloadOrError(expr, fn, null, args); return expr; @@ -427,32 +341,33 @@ export class CELChecker { // function or c is a function with target a.b. // // Check whether the target is a namespaced function name. - const qualifiedPrefix = toQualifiedName(call.target); - if (!isEmpty(qualifiedPrefix)) { - const qualifiedName = `${qualifiedPrefix}.${fnName}`; - const fn = this.env.lookupFunction(qualifiedName); + const target = call.target; + const qualifiedPrefix = toQualifiedName(target); + if (!isNil(qualifiedPrefix)) { + const maybeQualifiedName = `${qualifiedPrefix}.${fnName}`; + const fn = this.env.lookupFunction(maybeQualifiedName); if (!isNil(fn)) { // The function name is namespaced and so preserving the target operand // would be an inaccurate representation of the desired evaluation - // behavior. - // Overwrite with fully-qualified resolved function name sans receiver - // target. - expr.exprKind.value.function = fn.name; + // behavior. Overwrite with fully-qualified resolved function name sans + // receiver target. + call.function = fn.name; this.resolveOverloadOrError(expr, fn, null, args); return expr; } } // Regular instance call. - const checkedTarget = this.checkExpr(call.target)!; + this.checkExpr(target); + // Overwrite with fully-qualified resolved function name sans receiver + // target. const fn = this.env.lookupFunction(fnName); // Function found, attempt overload resolution. if (!isNil(fn)) { - this.resolveOverloadOrError(expr, fn, checkedTarget, args); + this.resolveOverloadOrError(expr, fn, target, args); return expr; } // Function name not declared, record error. - this.setType(expr.id, ERROR_TYPE); this.#errors.reportUndeclaredReference( expr.id, this.getLocationById(expr.id), @@ -468,14 +383,6 @@ export class CELChecker { target: Expr | null, args: Expr[] ) { - if (expr.exprKind.case !== 'callExpr') { - // This should never happen but acts as a type guard. - throw new Error('expr.exprKind.case is not callExpr'); - } - if (fn.declKind.case !== 'function') { - // This should never happen but acts as a type guard. - throw new Error('fn.declKind.case is not a function'); - } // Attempt to resolve the overload. const resolution = this.resolveOverload(expr, fn, target, args); // No such overload, error noted in the resolveOverload call, type recorded @@ -492,36 +399,30 @@ export class CELChecker { resolveOverload( expr: Expr, - fn: Decl, + fnDecl: Decl, target: Expr | null, args: Expr[] ): OverloadResolution | null { - if (expr.exprKind.case !== 'callExpr') { - // This should never happen but acts as a type guard. - throw new Error('expr.exprKind.case is not callExpr'); - } - if (fn.declKind.case !== 'function') { - // This should never happen but acts as a type guard. - throw new Error('fn.declKind.case is not a function'); - } + const fn = fnDecl.declKind.value as Decl_FunctionDecl; const argTypes: Type[] = []; if (!isNil(target)) { - argTypes.push(this.getType(target.id)!); + const argType = this.getType(target.id); + if (isNil(argType)) { + throw new Error(`Could not resolve type for target '${target}'`); + } + argTypes.push(argType); } - for (const arg of args) { - argTypes.push(this.getType(arg.id)!); + for (let i = 0; i < args.length; i++) { + const argType = this.getType(args[i].id); + if (isNil(argType)) { + throw new Error(`Could not resolve type for argument '${target}'`); + } + argTypes.push(argType); } let resultType: Type | undefined = undefined; let checkedRef: Reference | undefined = undefined; - for (const overload of fn.declKind.value.overloads) { - // TODO: implement disabled overloads - // // Determine whether the overload is currently considered. - // if c.env.isOverloadDisabled(overload.ID()) { - // continue - // } - - // Ensure the call style for the overload matches. + for (const overload of fn.overloads) { if ( (isNil(target) && overload.isInstanceFunction) || (!isNil(target) && !overload.isInstanceFunction) @@ -530,57 +431,35 @@ export class CELChecker { continue; } - // Alternative type-checking behavior when the logical operators are - // compacted into variadic AST representations. - if (fn.name === LOGICAL_AND_OPERATOR || fn.name === LOGICAL_OR_OPERATOR) { - checkedRef = functionReference([overload.overloadId]); - for (let i = 0; i < argTypes.length; i++) { - const argType = argTypes[i]; - if (!this._isAssignable(argType, BOOL_TYPE)) { - this.#errors.reportTypeMismatch( - args[i].id, - this.getLocationById(args[i].id), - BOOL_TYPE, - argType - ); - resultType = ERROR_TYPE; - } - } - if (!isNil(resultType) && isError(resultType)) { - return null; - } - return { - checkedRef, - resultType: primitiveType(Type_PrimitiveType.BOOL), - }; - } - let overloadType = functionType({ resultType: overload.resultType, argTypes: overload.params, }); - const typeParams = overload.typeParams; - if (typeParams.length > 0) { + if (overload.typeParams.length > 0) { // Instantiate overload's type with fresh type variables. const substitutions = new Map(); - for (const typeParam of typeParams) { - substitutions.set(typeParam, this._newTypeVar()); + for (const typeParam of overload.typeParams) { + substitutions.set( + formatCELType(typeParamType(typeParam)), + this._newTypeVar() + ); } overloadType = substitute(substitutions, overloadType, false); } - const unwrappedOverload = unwrapFunctionType(overloadType)!; - const candidateArgTypes = unwrappedOverload.argTypes; + const overloadTypeFn = overloadType.typeKind.value as Type_FunctionType; + const candidateArgTypes = overloadTypeFn.argTypes; if (this._isAssignableList(argTypes, candidateArgTypes)) { if (isNil(checkedRef)) { checkedRef = functionReference([overload.overloadId]); } else { checkedRef.overloadId.push(overload.overloadId); } + // First matching overload, determines result type. const fnResultType = substitute( this.#mapping, - unwrappedOverload.resultType!, + overloadTypeFn.resultType!, false ); if (isNil(resultType)) { @@ -595,229 +474,145 @@ export class CELChecker { } if (isNil(resultType)) { - for (let i = 0; i < argTypes.length; i++) { - argTypes[i] = substitute(this.#mapping, argTypes[i], false); - } this.#errors.reportNoMatchingOverload( expr.id, this.getLocationById(expr.id), - fn.name, + fnDecl.name, argTypes, !isNil(target) ); return null; } - - return { checkedRef, resultType }; + return { resultType, checkedRef }; } - checkListExpr(expr: Expr) { - if (expr.exprKind.case !== 'listExpr') { - // This should never happen - throw new Error('expr.exprKind.case is not listExpr'); - } - const createList = expr.exprKind.value; - let elemsType: Type | undefined = undefined; - const optionals = {} as Record; - for (const optInd of createList.optionalIndices) { - optionals[optInd] = true; - } - for (let i = 0; i < createList.elements.length; i++) { - const e = createList.elements[i]; + checkCreateList(expr: Expr) { + const create = expr.exprKind.value as Expr_CreateList; + let elemType: Type | undefined = undefined; + for (let i = 0; i < create.elements.length; i++) { + const e = create.elements[i]; this.checkExpr(e); - const elemType = this.getType(e.id); - if (isNil(elemType)) { - continue; - } - if (optionals[i]) { - if (!isOptionalType(elemType) && !isDyn(elemType)) { - this.#errors.reportTypeMismatch( - e.id, - this.getLocationById(e.id), - optionalType(elemType), - elemType - ); - } - } - elemsType = this._joinTypes(e, elemsType!, elemType!); + elemType = this._joinTypes(e, elemType!, this.getType(e.id)!); } - if (isNil(elemsType)) { - elemsType = this._newTypeVar(); + if (isNil(elemType)) { + // If the list is empty, assign free type var to elem type. + elemType = this._newTypeVar(); } - this.setType(expr.id, listType({ elemType: elemsType })); + this.setType(expr.id, listType({ elemType })); return expr; } - checkCreateMap(expr: Expr) { - if (expr.exprKind.case !== 'structExpr') { - // This should never happen but acts as a type guard. - throw new Error('expr.exprKind.case is not structExpr'); - } - let mapKeyType: Type | undefined = undefined; - let mapValueType: Type | undefined = undefined; - for (let i = 0; i < expr.exprKind.value.entries.length; i++) { - const entry = expr.exprKind.value.entries[i]; - if (entry.keyKind.case !== 'mapKey') { - // This should never happen - throw new Error('entry.keyKind.case is not mapKey'); - } - const checkedKey = this.checkExpr(entry.keyKind.value)!; - mapKeyType = this._joinTypes( - checkedKey, - mapKeyType, - this.getType(checkedKey.id)! - ); - - const checkedVal = this.checkExpr(entry.value)!; - let valType = this.getType(checkedVal.id)!; - if (isOptionalType(mapKeyType)) { - valType = unwrapOptionalType(valType)!; - if (!isOptionalType(valType) && !isDyn(valType)) { - this.#errors.reportTypeMismatch( - checkedVal.id, - this.getLocationById(checkedVal.id), - optionalType(valType), - valType - ); - } - } - mapValueType = this._joinTypes(checkedVal, mapValueType, valType); + checkCreateStruct(expr: Expr) { + const struct = expr.exprKind.value as Expr_CreateStruct; + if (!isEmpty(struct.messageName)) { + return this.checkCreateMessage(expr); } - if (isNil(mapKeyType)) { + return this.checkCreateMap(expr); + } + + checkCreateMap(expr: Expr) { + const mapVal = expr.exprKind.value as Expr_CreateStruct; + let keyType: Type | undefined = undefined; + let valueType: Type | undefined = undefined; + for (let i = 0; i < mapVal.entries.length; i++) { + const key = mapVal.entries[i].keyKind.value as Expr; + this.checkExpr(key); + keyType = this._joinTypes(key, keyType, this.getType(key.id)!); + + const val = mapVal.entries[i].value as Expr; + this.checkExpr(val); + valueType = this._joinTypes(val, valueType, this.getType(val.id)!); + } + if (isNil(keyType)) { // If the map is empty, assign free type variables to typeKey and value // type. - mapKeyType = this._newTypeVar(); - mapValueType = this._newTypeVar(); + keyType = this._newTypeVar(); + valueType = this._newTypeVar(); } - this.setType( - expr.id, - mapType({ - keyType: mapKeyType, - valueType: mapValueType, - }) - ); + this.setType(expr.id, mapType({ keyType, valueType })); return expr; } - checkCreateStruct(expr: Expr) { - if (expr.exprKind.case !== 'structExpr') { - // This should never happen but acts as a type guard. - throw new Error('expr.exprKind.case is not structExpr'); - } - const msgVal = expr.exprKind.value; + checkCreateMessage(expr: Expr) { + const mapVal = expr.exprKind.value as Expr_CreateStruct; // Determine the type of the message. - let resultType: Type = ERROR_TYPE; - const ident = this.env.lookupIdent(msgVal.messageName); - if (isNil(ident)) { + let messageType: Type = ERROR_TYPE; + const decl = this.env.lookupIdent(mapVal.messageName); + if (isNil(decl)) { this.#errors.reportUndeclaredReference( expr.id, this.getLocationById(expr.id), this.env.container, - msgVal.messageName + mapVal.messageName ); - this.setType(expr.id, ERROR_TYPE); return expr; } - const identDecl = ident.declKind.value as Decl_IdentDecl; - let typeName = ident.name; // Ensure the type name is fully qualified in the AST. - if (msgVal.messageName !== typeName) { - expr.exprKind.value.messageName = typeName; - } - this.setReference(expr.id, identReference(typeName, identDecl.value!)); - const identKind = identDecl.type?.typeKind.case; - if (identKind !== 'error') { - if ( - identKind !== 'type' && - identKind !== 'wellKnown' && - identKind !== 'messageType' - ) { - this.#errors.reportNotAType( + mapVal.messageName = decl.name; + const ident = decl.declKind.value as Decl_IdentDecl; + this.setReference(expr.id, identReference(decl.name, ident.value!)); + const identKind = ident.type!.typeKind.case; + if (identKind === 'type') { + messageType = ident.type!; + if (messageType.typeKind.case !== 'messageType') { + this.#errors.reportNotAMessageType( expr.id, this.getLocationById(expr.id), - typeName + decl.name ); - } else { - switch (identKind) { - case 'type': - resultType = identDecl.type!.typeKind.value; - break; - case 'wellKnown': - case 'messageType': - resultType = identDecl.type!; - break; - } - // Backwards compatibility test between well-known types and message - // types. In this context, the type is being instantiated by it - // protobuf name which is not ideal or recommended, but some users - // expect this to work. - if (resultType.typeKind.case === 'wellKnown') { - typeName = getWellKNownTypeName(resultType.typeKind.value)!; - } else if (resultType.typeKind.case === 'messageType') { - typeName = resultType.typeKind.value; - } else { - this.#errors.reportNotAMessageType( - expr.id, - this.getLocationById(expr.id), - typeName - ); - resultType = ERROR_TYPE; - } + messageType = ERROR_TYPE; } } - this.setType(expr.id, resultType); + if (identKind === 'messageType') { + messageType = ident.type!; + } + const checkedType = getCheckedWellKnownType(mapVal.messageName); + if (!isNil(checkedType)) { + messageType = checkedType; + } + this.setType(expr.id, messageType); // Check the field initializers. - for (const field of msgVal.entries) { - if (field.keyKind.case !== 'fieldKey') { - // This should never happen but acts as a type guard. - throw new Error('field.keyKind.case is not fieldKey'); + for (const entry of mapVal.entries) { + const field = entry.keyKind.value as string; + const value = entry.value; + if (isNil(value)) { + this.#errors.reportUndefinedField( + entry.id, + this.getLocationById(entry.id), + field + ); + continue; } + this.checkExpr(value); - const checkedValue = this.checkExpr(field.value)!; - - let fieldType = ERROR_TYPE; - const ft = this.env.lookupFieldType(typeName, field.keyKind.value); - if (!isNil(ft)) { - fieldType = ft; + let fieldType: Type = ERROR_TYPE; + const t = this.env.lookupFieldType(mapVal.messageName, field); + if (!isNil(t)) { + fieldType = t; } else { - const msg = this.env.lookupStructType(typeName); + const msg = this.env.lookupStructType(mapVal.messageName); if (isNil(msg)) { this.#errors.reportUnexpectedFailedResolution( - field.value!.id, - this.getLocationById(field.id), - typeName + expr.id, + this.getLocationById(expr.id), + mapVal.messageName ); } else { this.#errors.reportUndefinedField( - field.value!.id, - this.getLocationById(field.id), - field.keyKind.value - ); - } - } - - let valType = this.getType(checkedValue.id); - if (field.optionalEntry) { - const vt = maybeUnwrapOptionalType(valType); - if (!isNil(vt)) { - valType = vt; - } else { - this.#errors.reportTypeMismatch( - field.value!.id, - this.getLocationById(field.value!.id), - optionalType(fieldType), - valType! + entry.id, + this.getLocationById(entry.id), + field ); } } - if (!this._isAssignable(fieldType, valType!)) { + if (!this._isAssignable(fieldType, this.getType(value.id)!)) { this.#errors.reportFieldTypeMismatch( - field.value!.id, - this.getLocationById(field.id), - field.keyKind.value, + entry.id, + this.getLocationById(entry.id), + field, fieldType, - valType! + this.getType(value.id)! ); } } @@ -825,20 +620,13 @@ export class CELChecker { } checkComprehension(expr: Expr) { - if (expr.exprKind.case !== 'comprehensionExpr') { - // This should never happen - throw new Error('expr.exprKind.case is not comprehensionExpr'); - } - const comp = expr.exprKind.value; - const checkedRange = this.checkExpr(comp.iterRange); - const checkedInit = this.checkExpr(comp.accuInit); - const accuType = this.getType(checkedInit!.id); - const rangeType = substitute( - this.#mapping, - this.getType(checkedRange!.id)!, - false - ); + const comp = expr.exprKind.value as Expr_Comprehension; + this.checkExpr(comp.iterRange); + this.checkExpr(comp.accuInit); + const accuType = this.getType(comp.accuInit!.id); + const rangeType = this.getType(comp.iterRange!.id)!; let varType: Type | undefined = undefined; + switch (rangeType.typeKind.case) { case 'listType': varType = rangeType.typeKind.value.elemType; @@ -849,8 +637,6 @@ export class CELChecker { break; case 'dyn': case 'error': - varType = DYN_TYPE; - break; case 'typeParam': // Set the range type to DYN to prevent assignment to a potentially // incorrect type at a later point in type-checking. The isAssignable @@ -877,19 +663,16 @@ export class CELChecker { this.env.enterScope(); this.env.addIdent(identDecl(comp.iterVar, { type: varType })); // Check the variable references in the condition and step. - const checkedCondition = this.checkExpr(comp.loopCondition); - this._assertType(checkedCondition!, BOOL_TYPE); - const checkedStep = this.checkExpr(comp.loopStep); - this._assertType(checkedStep!, accuType!); + this.checkExpr(comp.loopCondition); + this._assertType(comp.loopCondition!, BOOL_TYPE); + this.checkExpr(comp.loopStep); + this._assertType(comp.loopStep!, accuType!); // Exit the loop's block scope before checking the result. this.env.exitScope(); - const checkedResult = this.checkExpr(comp.result); + this.checkExpr(comp.result); // Exit the comprehension scope. this.env.exitScope(); - this.setType( - expr.id, - substitute(this.#mapping, this.getType(checkedResult!.id)!, false) - ); + this.setType(expr.id, this.getType(comp.result!.id)!); return expr; } diff --git a/packages/cel/src/lib/environment.ts b/packages/cel/src/lib/environment.ts index 2cd7393..a7e55fc 100644 --- a/packages/cel/src/lib/environment.ts +++ b/packages/cel/src/lib/environment.ts @@ -1,6 +1,7 @@ import { isNil } from '@bearclaw/is'; import { Decl, + Decl_IdentDecl, Type, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; import { @@ -18,8 +19,16 @@ import { STANDARD_FUNCTION_DECLARATIONS, STANDARD_IDENTS, } from './standard'; -import { DYN_TYPE, INT64_TYPE, messageType } from './types'; -import { getFieldDescriptorType, identDecl, int64Constant } from './utils'; +import { + DYN_TYPE, + INT64_TYPE, + STRING_TYPE, + getCheckedWellKnownType, + isCheckedWellKnownType, + mapType, + messageType, +} from './types'; +import { getFieldDescriptorType, identDecl } from './utils'; export interface CELEnvironmentOptions { container?: CELContainer; @@ -249,8 +258,8 @@ export class CELEnvironment { // Next try to import the name as a reference to a message type. If found, // the declaration is added to the outest (global) scope of the // environment, so next time we can access it faster. - const type = this.registry.getMessage(candidateName); - if (!isNil(type)) { + const messageDesc = this.registry.getMessage(candidateName); + if (!isNil(messageDesc)) { const decl = identDecl(candidateName, { type: messageType(candidateName), }); @@ -260,11 +269,13 @@ export class CELEnvironment { // Next try to import this as an enum value by splitting the name in a // type prefix and the enum inside. - const enumValue = this.registry.getEnum(candidateName); - if (!isNil(enumValue)) { + const enumDesc = this.registry.getEnum(candidateName); + if (!isNil(enumDesc)) { const decl = identDecl(candidateName, { - type: INT64_TYPE, - value: int64Constant(BigInt(enumValue.value[0].number)), + type: mapType({ + keyType: STRING_TYPE, + valueType: INT64_TYPE, + }), }); this.addIdent(decl); return decl; @@ -368,13 +379,25 @@ export class DeclGroup { } addIdent(decl: Decl): void { - this.idents.set(decl.name, decl); + this.idents.set(decl.name, this.sanitizeIdent(decl)); } findIdent(name: string): Decl | null { return this.idents.get(name) || null; } + sanitizeIdent(decl: Decl) { + const ident = decl.declKind.value as Decl_IdentDecl; + if (!isNil(ident.type) && isCheckedWellKnownType(ident.type)) { + return identDecl(decl.name, { + type: getCheckedWellKnownType( + ident.type.typeKind.value as string + ) as Type, + }); + } + return decl; + } + addFunction(decl: Decl): void { this.functions.set(decl.name, decl); } diff --git a/packages/cel/src/lib/overloads.ts b/packages/cel/src/lib/overloads.ts index dd67019..0181b18 100644 --- a/packages/cel/src/lib/overloads.ts +++ b/packages/cel/src/lib/overloads.ts @@ -109,6 +109,7 @@ export const NEGATE_DOUBLE_OVERLOAD = 'negate_double'; // Index overloads export const INDEX_LIST_OVERLOAD = 'index_list'; export const INDEX_MAP_OVERLOAD = 'index_map'; +export const INDEX_STRUCT_OVERLOAD = 'index_struct'; export const INDEX_MESSAGE_OVERLOAD = 'index_message'; // TODO: introduce concept of types.Message // In operators diff --git a/packages/cel/src/lib/standard.ts b/packages/cel/src/lib/standard.ts index b950e22..ff2246a 100644 --- a/packages/cel/src/lib/standard.ts +++ b/packages/cel/src/lib/standard.ts @@ -12,6 +12,7 @@ import { BoolValueSchema, BytesValueSchema, DoubleValueSchema, + DurationSchema, FloatValueSchema, Int32ValueSchema, Int64ValueSchema, @@ -19,6 +20,7 @@ import { ValueSchema as ProtobufValueSchema, StringValueSchema, StructSchema, + TimestampSchema, UInt32ValueSchema, UInt64ValueSchema, } from '@bufbuild/protobuf/wkt'; @@ -244,7 +246,7 @@ import { typeParamType, typeType, } from './types'; -import { functionDecl } from './utils'; +import { functionDecl, identDecl } from './utils'; export const STANDARD_DESCRIPTORS: ( | DescMessage @@ -267,14 +269,32 @@ export const STANDARD_DESCRIPTORS: ( StringValueSchema, UInt32ValueSchema, UInt64ValueSchema, + TimestampSchema, + DurationSchema, ]; -export const STANDARD_IDENTS: Decl[] = []; +export const STANDARD_IDENTS: Decl[] = [ + identDecl('bool', { type: typeType(BOOL_TYPE) }), + identDecl('bytes', { type: typeType(BYTES_TYPE) }), + identDecl('double', { type: typeType(DOUBLE_TYPE) }), + identDecl('duration', { type: typeType(DURATION_TYPE) }), + identDecl('dyn', { type: typeType(DYN_TYPE) }), + identDecl('int', { type: typeType(INT64_TYPE) }), + identDecl('string', { type: typeType(STRING_TYPE) }), + identDecl('timestamp', { type: typeType(TIMESTAMP_TYPE) }), + identDecl('uint', { type: typeType(UINT64_TYPE) }), + identDecl('list', { type: typeType(listType({ elemType: DYN_TYPE })) }), + identDecl('map', { + type: typeType(mapType({ keyType: DYN_TYPE, valueType: DYN_TYPE })), + }), +]; const paramA = typeParamType('A'); +const typeParamAList = ['A']; const paramB = typeParamType('B'); const listOfA = listType({ elemType: paramA }); const mapOfAB = mapType({ keyType: paramA, valueType: paramB }); +const typeParamABList = ['A', 'B']; // Logical operators. Special-cased within the interpreter. // Note, the singleton binding prevents extensions from overriding the operator @@ -285,6 +305,7 @@ export const CONDITIONAL_FUNCTION_DECL = functionDecl(CONDITIONAL_OPERATOR, { overloadId: CONDITIONAL_OVERLOAD, params: [BOOL_TYPE, paramA, paramA], resultType: paramA, + typeParams: typeParamAList, }, ], }); @@ -335,8 +356,9 @@ export const EQUALS_FUNCTION_DECL = functionDecl(EQUALS_OPERATOR, { overloads: [ { overloadId: EQUALS_OVERLOAD, - params: [paramA, paramA], + params: [paramA, paramB], resultType: BOOL_TYPE, + typeParams: typeParamABList, }, ], }); @@ -346,6 +368,7 @@ export const NOT_EQUALS_FUNCTION_DECL = functionDecl(NOT_EQUALS_OPERATOR, { overloadId: NOT_EQUALS_OVERLOAD, params: [paramA, paramA], resultType: BOOL_TYPE, + typeParams: typeParamABList, }, ], }); @@ -387,6 +410,7 @@ export const ADD_FUNCTION_DECL = functionDecl(ADD_OPERATOR, { overloadId: ADD_LIST_OVERLOAD, params: [listOfA, listOfA], resultType: listOfA, + typeParams: typeParamAList, }, { overloadId: ADD_STRING_OVERLOAD, @@ -804,11 +828,13 @@ export const INDEX_FUNCTION_DECL = functionDecl(INDEX_OPERATOR, { overloadId: INDEX_MAP_OVERLOAD, params: [mapOfAB, paramA], resultType: paramB, + typeParams: typeParamABList, }, { overloadId: INDEX_LIST_OVERLOAD, params: [listOfA, INT64_TYPE], resultType: paramA, + typeParams: typeParamAList, }, ], }); @@ -820,11 +846,13 @@ export const IN_FUNCTION_DECL = functionDecl(IN_OPERATOR, { overloadId: IN_LIST_OVERLOAD, params: [paramA, listOfA], resultType: BOOL_TYPE, + typeParams: typeParamAList, }, { overloadId: IN_MAP_OVERLOAD, params: [paramA, mapOfAB], resultType: BOOL_TYPE, + typeParams: typeParamABList, }, ], }); @@ -845,22 +873,26 @@ export const SIZE_FUNCTION_DECL = functionDecl(SIZE_OVERLOAD, { overloadId: SIZE_LIST_OVERLOAD, params: [listOfA], resultType: INT64_TYPE, + typeParams: typeParamAList, }, { overloadId: SIZE_LIST_INST_OVERLOAD, params: [listOfA], resultType: INT64_TYPE, + typeParams: typeParamAList, isInstanceFunction: true, }, { overloadId: SIZE_MAP_OVERLOAD, params: [mapOfAB], resultType: INT64_TYPE, + typeParams: typeParamABList, }, { overloadId: SIZE_MAP_INST_OVERLOAD, params: [mapOfAB], resultType: INT64_TYPE, + typeParams: typeParamABList, isInstanceFunction: true, }, { @@ -886,6 +918,7 @@ export const TYPE_CONVERT_TYPE_FUNCTION_DECL = functionDecl( overloadId: TYPE_CONVERT_TYPE_OVERLOAD, params: [paramA], resultType: typeType(paramA), + typeParams: typeParamAList, }, ], } @@ -991,6 +1024,7 @@ export const TYPE_CONVERT_DYN_FUNCTION_DECL = functionDecl( overloadId: TYPE_CONVERT_TYPE_OVERLOAD, params: [paramA], resultType: DYN_TYPE, + typeParams: typeParamAList, }, ], } diff --git a/packages/cel/src/lib/types.spec.ts b/packages/cel/src/lib/types.spec.ts index 902aca0..244e50b 100644 --- a/packages/cel/src/lib/types.spec.ts +++ b/packages/cel/src/lib/types.spec.ts @@ -10,6 +10,7 @@ import { ERROR_TYPE, NULL_TYPE, abstractType, + formatCELType, functionType, isAssignableType, isExactType, @@ -325,7 +326,7 @@ describe('types', () => { } }); - it('isAssignable', () => { + describe('isAssignable', () => { const testCases = [ { t1: nullableType(primitiveType(Type_PrimitiveType.STRING)), @@ -474,10 +475,44 @@ describe('types', () => { }), isAssignable: false, }, + { + t1: listType({ + elemType: primitiveType(Type_PrimitiveType.INT64), + }), + t2: listType({ + elemType: primitiveType(Type_PrimitiveType.STRING), + }), + isAssignable: false, + }, + { + t1: listType({ + elemType: primitiveType(Type_PrimitiveType.STRING), + }), + t2: listType({ + elemType: primitiveType(Type_PrimitiveType.INT64), + }), + isAssignable: false, + }, + { + t1: listType({ + elemType: messageType('test.TestMessage'), + }), + t2: listType({ + elemType: primitiveType(Type_PrimitiveType.INT64), + }), + isAssignable: false, + }, ]; for (const testCase of testCases) { - expect(isAssignableType(testCase.t1, testCase.t2)).toEqual( - testCase.isAssignable + it( + formatCELType(testCase.t2) + + ' is assignable to ' + + formatCELType(testCase.t1), + () => { + expect(isAssignableType(testCase.t1, testCase.t2)).toEqual( + testCase.isAssignable + ); + } ); } }); diff --git a/packages/cel/src/lib/types.ts b/packages/cel/src/lib/types.ts index d4e51a2..91ea90a 100644 --- a/packages/cel/src/lib/types.ts +++ b/packages/cel/src/lib/types.ts @@ -6,9 +6,13 @@ import { Decl, Type, TypeSchema, + Type_AbstractType, Type_AbstractTypeSchema, + Type_FunctionType, Type_FunctionTypeSchema, + Type_ListType, Type_ListTypeSchema, + Type_MapType, Type_MapTypeSchema, Type_PrimitiveType, Type_PrimitiveTypeSchema, @@ -80,18 +84,51 @@ export const ANY_TYPE = wellKnownType(Type_WellKnownType.ANY); export const DURATION_TYPE = wellKnownType(Type_WellKnownType.DURATION); export const TIMESTAMP_TYPE = wellKnownType(Type_WellKnownType.TIMESTAMP); +export function isCheckedWellKnownType(type: Type) { + if (type.typeKind.case !== 'messageType') { + return false; + } + switch (type.typeKind.value) { + case 'google.protobuf.BoolValue': // Wrapper types. + case 'google.protobuf.BytesValue': + case 'google.protobuf.DoubleValue': + case 'google.protobuf.FloatValue': + case 'google.protobuf.Int64Value': + case 'google.protobuf.Int32Value': + case 'google.protobuf.UInt64Value': + case 'google.protobuf.UInt32Value': + case 'google.protobuf.StringValue': + case 'google.protobuf.Any': // Well-known types. + case 'google.protobuf.Duration': + case 'google.protobuf.Timestamp': + case 'google.protobuf.ListValue': // Json types. + case 'google.protobuf.NullValue': + case 'google.protobuf.Struct': + case 'google.protobuf.Value': + return true; + default: + return false; + } +} + export function getCheckedWellKnownType(value: string) { switch (value) { - // // Wrapper types. - // case "google.protobuf.BoolValue": checkedWrap(checkedBool), - // case "google.protobuf.BytesValue": checkedWrap(checkedBytes), - // case "google.protobuf.DoubleValue": checkedWrap(checkedDouble), - // case "google.protobuf.FloatValue": checkedWrap(checkedDouble), - // case "google.protobuf.Int64Value": checkedWrap(checkedInt), - // case "google.protobuf.Int32Value": checkedWrap(checkedInt), - // case "google.protobuf.UInt64Value": checkedWrap(checkedUint), - // case "google.protobuf.UInt32Value": checkedWrap(checkedUint), - // case "google.protobuf.StringValue": checkedWrap(checkedString), + // Wrapper types. + case 'google.protobuf.BoolValue': + return BOOL_TYPE; + case 'google.protobuf.BytesValue': + return BYTES_TYPE; + case 'google.protobuf.DoubleValue': + case 'google.protobuf.FloatValue': + return DOUBLE_TYPE; + case 'google.protobuf.Int64Value': + case 'google.protobuf.Int32Value': + return INT64_TYPE; + case 'google.protobuf.UInt64Value': + case 'google.protobuf.UInt32Value': + return UINT64_TYPE; + case 'google.protobuf.StringValue': + return STRING_TYPE; // Well-known types. case 'google.protobuf.Any': return ANY_TYPE; @@ -315,7 +352,7 @@ export function isEqualOrLessSpecific(t1: Type, t2: Type): boolean { throw new Error('kinds must be equal'); } if ( - t1.$typeName !== t2.$typeName || + t1.typeKind.value.name !== t2.typeKind.value.name || t1.typeKind.value.parameterTypes.length !== t2.typeKind.value.parameterTypes.length ) { @@ -332,6 +369,35 @@ export function isEqualOrLessSpecific(t1: Type, t2: Type): boolean { } } return true; + case 'function': + if (t1.typeKind.case !== t2.typeKind.case) { + // We will never get here + throw new Error('kinds must be equal'); + } + if ( + !isEqualOrLessSpecific( + t1.typeKind.value.resultType!, + t2.typeKind.value.resultType! + ) + ) { + return false; + } + if ( + t1.typeKind.value.argTypes.length !== t2.typeKind.value.argTypes.length + ) { + return false; + } + for (let i = 0; i < t1.typeKind.value.argTypes.length; i++) { + if ( + isEqualOrLessSpecific( + t1.typeKind.value.argTypes[i], + t2.typeKind.value.argTypes[i] + ) + ) { + return false; + } + } + return true; case 'listType': if (t1.typeKind.case !== t2.typeKind.case) { // We will never get here @@ -433,90 +499,209 @@ export function internalIsAssignable( t1: Type, t2: Type ): boolean { + // A type is always assignable to itself. + // Early terminate the call to avoid cases of infinite recursion. + if (t1 === t2) { + return true; + } // Process type parameters const kind1 = t1.typeKind.case; const kind2 = t2.typeKind.case; if (kind2 === 'typeParam') { - // If t2 is a valid type substitution for t1, return true. - const [valid, t2HasSub] = isValidTypeSubstitution(mapping, t1, t2); - if (valid) { - return true; - } - // If t2 is not a valid type sub for t1, and already has a known - // substitution return false since it is not possible for t1 to be - // substitution for t2. - if (!valid && t2HasSub) { + const t2Sub = mapping.get(formatCELType(t2)); + if (!isNil(t2Sub)) { + // If the types are compatible, pick the more general type and return true + if (internalIsAssignable(mapping, t1, t2Sub)) { + mapping.set(formatCELType(t2), mostGeneral(t1, t2Sub)); + return true; + } return false; } - // Otherwise, fall through to check whether t1 is a possible substitution - // for t2. + if (notReferencedIn(mapping, t2, t1)) { + mapping.set(formatCELType(t2), t1); + return true; + } } if (kind1 === 'typeParam') { - // Return whether t1 is a valid substitution for t2. If not, do no - // additional checks as the possible type substitutions have been searched - // in both directions. - const [valid, _] = isValidTypeSubstitution(mapping, t2, t1); - return valid; + // For the lower type bound, we currently do not perform adjustment. The restricted + // way we use type parameters in lower type bounds, it is not necessary, but may + // become if we generalize type unification. + const t1Sub = mapping.get(formatCELType(t1)); + if (!isNil(t1Sub)) { + // If the types are compatible, pick the more general type and return true + if (internalIsAssignable(mapping, t1Sub, t2)) { + mapping.set(formatCELType(t1), mostGeneral(t1Sub, t2)); + return true; + } + return false; + } + if (notReferencedIn(mapping, t1, t2)) { + mapping.set(formatCELType(t1), t2); + return true; + } } // Next check for wildcard types. if (isDynOrError(t1) || isDynOrError(t2)) { return true; } - // Preserve the nullness checks of the legacy type-checker. - if (kind1 == 'null') { - return internalIsAssignableNull(t2); - } - if (kind2 == 'null') { - return internalIsAssignableNull(t1); - } - // Test for when the types do not need to agree, but are more specific than - // dyn. + + // Test for when the types do not need to agree, but are more specific than dyn. switch (kind1) { + case 'null': + return internalIsAssignableNull(t2); case 'primitive': - case 'wellKnown': - case 'messageType': + return internalIsAssignablePrimitive(t1.typeKind.value, t2); case 'wrapper': - case 'error': - return isAssignableType(t1, t2); - case 'type': - return kind2 === 'type'; + return internalIsAssignable( + mapping, + primitiveType(t1.typeKind.value), + t2 + ); + default: + if (kind1 != kind2) { + return false; + } + } + + // Test for when the types must agree. + switch (kind1) { + // ERROR, TYPE_PARAM, and DYN handled above. case 'abstractType': - return ( - t2.typeKind.case === 'abstractType' && - internalIsAssignableList( - mapping, - t1.typeKind.value.parameterTypes, - t2.typeKind.value.parameterTypes - ) + return internalIsAssignableAbstractType( + mapping, + t1.typeKind.value, + t2.typeKind.value as Type_AbstractType + ); + case 'function': + return internalIsAssignableFunction( + mapping, + t1.typeKind.value, + t2.typeKind.value as Type_FunctionType ); case 'listType': - return ( - t2.typeKind.case === 'listType' && - internalIsAssignable( - mapping, - t1.typeKind.value.elemType!, - t2.typeKind.value.elemType! - ) + return internalIsAssignable( + mapping, + t1.typeKind.value.elemType!, + (t2.typeKind.value as Type_ListType).elemType! ); case 'mapType': - return ( - t2.typeKind.case === 'mapType' && - internalIsAssignable( - mapping, - t1.typeKind.value.keyType!, - t2.typeKind.value.keyType! - ) && - internalIsAssignable( - mapping, - t1.typeKind.value.valueType!, - t2.typeKind.value.valueType! - ) + return internalIsAssignableMap( + mapping, + t1.typeKind.value, + t2.typeKind.value as Type_MapType ); + case 'messageType': + return t1.typeKind.value === t2.typeKind.value; + case 'type': + // A type is a type is a type, any additional parameterization of the + // type cannot affect method resolution or assignability. + return true; + case 'wellKnown': + return t1.typeKind.value === t2.typeKind.value; + default: + return false; + } +} + +/** + * Returns true if the target type is the same or if it is a wrapper + * for the primitive type. + * + * @param p1 the primitive type + * @param t2 the target type + * @returns whether the primitive type is assignable to the target type + */ +export function internalIsAssignablePrimitive( + p1: Type_PrimitiveType, + t2: Type +): boolean { + switch (t2.typeKind.case) { + case 'primitive': + return p1 === t2.typeKind.value; + case 'wrapper': + return p1 === t2.typeKind.value; default: return false; } } +/** + * Returns true if the abstract type names agree and all type + * parameters are assignable. + * + * @param mapping the type map to use for checking references + * @param a1 the first abstract type + * @param a2 the second abstract type + * @returns whether the abstract types are assignable + */ +export function internalIsAssignableAbstractType( + mapping: Map, + a1: Type_AbstractType, + a2: Type_AbstractType +): boolean { + if (a1.name !== a2.name) { + return false; + } + return internalIsAssignableList( + mapping, + a1.parameterTypes, + a2.parameterTypes + ); +} + +/** + * Returns true if the function return type and arg types are + * assignable. + */ +export function internalIsAssignableFunction( + mapping: Map, + f1: Type_FunctionType, + f2: Type_FunctionType +) { + const f1Args = flattenFunctionTypes(f1); + const f2Args = flattenFunctionTypes(f2); + return internalIsAssignableList(mapping, f1Args, f2Args); +} + +/** + * Takes a function with arg types T1, T2, ..., TN and result type TR and + * returns a slice containing {T1, T2, ..., TN, TR}. + * + * @param f the function type + * @returns the list of types for the function + */ +export function flattenFunctionTypes(f: Type_FunctionType) { + const argTypes = f.argTypes; + if (argTypes.length === 0) { + return [f.resultType!]; + } + for (let i = 0; i < argTypes.length; i++) { + argTypes.push(argTypes[i]); + } + argTypes.push(f.resultType!); + return argTypes; +} + +/** + * Returns true if map m1 may be assigned to map m2. + * + * @param mapping the type map to use for checking references + * @param m1 the first map type + * @param m2 the second map type + * @returns whether the map types are assignable + */ +export function internalIsAssignableMap( + mapping: Map, + m1: Type_MapType, + m2: Type_MapType +) { + return internalIsAssignableList( + mapping, + [m1.keyType!, m1.valueType!], + [m2.keyType!, m2.valueType!] + ); +} + /** * Returns true if the element types at each index in the list are * assignable from l1[i] to l2[i]. The list lengths must also agree for the @@ -548,62 +733,16 @@ export function internalIsAssignableList( * @returns whether the type is nullable */ export function internalIsAssignableNull(t: Type) { - return isAssignableType(t, NULL_TYPE); -} - -/** - * Returns whether t2 (or its type substitution) is a valid type substitution - * for t1, and whether t2 has a type substitution in mapping m. - * The type t2 is a valid substitution for t1 if any of the following - * statements is true - * - t2 has a type substitution (t2sub) equal to t1 - * - t2 has a type substitution (t2sub) assignable to t1 - * - t2 does not occur within t1. - * - * @param mapping the type map to use for checking references - * @param t1 the first type - * @param t2 the second type - * @returns a tuple where the first element is whether t2 is a valid type - * substitution for t1, and the second element is whether t2 has a type - * substitution in the mapping - */ -export function isValidTypeSubstitution( - mapping: Map, - t1: Type, - t2: Type -): [boolean, boolean] { - // Early return if the t1 and t2 are the same instance. - const kind1 = t1.typeKind.case; - const kind2 = t2.typeKind.case; - if (kind1 === kind2 && t1 === t2) { - return [true, true]; - } - const t2sub = Array.from(mapping).find(([_, v]) => v === t2)?.[1]; - if (!isNil(t2sub)) { - // Early return if t1 and t2Sub are the same instance as otherwise the - // mapping might mark a type as being a subtitution for itself. - if (kind1 === t2sub.typeKind.case && t1 === t2sub) { - return [true, true]; - } - // If the types are compatible, pick the more general type and return true - if (internalIsAssignable(mapping, t1, t2sub)) { - const t2New = mostGeneral(t1, t2sub); - // only update the type reference map if the target type does not occur - // within it. - if (notReferencedIn(mapping, t2New, t2)) { - mapping.set(formatCELType(t2New), t2New); - } - // acknowledge the type agreement, and that the substitution is already - // tracked. - return [true, true]; - } - return [false, true]; - } - if (notReferencedIn(mapping, t2, t1)) { - mapping.set(formatCELType(t2), t1); - return [true, false]; + switch (t.typeKind.case) { + case 'abstractType': + case 'messageType': + case 'null': + case 'wellKnown': + case 'wrapper': + return true; + default: + return false; } - return [false, false]; } /** @@ -620,13 +759,12 @@ export function notReferencedIn( t: Type, withinType: Type ): boolean { - if (t === withinType) { + if (isExactType(t, withinType)) { return false; } - const withinKind = withinType.typeKind.case; - switch (withinKind) { + switch (withinType.typeKind.case) { case 'typeParam': - const wtSub = Array.from(m).find(([_, v]) => v === withinType)?.[1]; + const wtSub = m.get(formatCELType(withinType)); if (isNil(wtSub)) { return true; } @@ -638,6 +776,16 @@ export function notReferencedIn( } } return true; + case 'function': + if (!notReferencedIn(m, t, withinType.typeKind.value.resultType!)) { + return false; + } + for (const pt of withinType.typeKind.value.argTypes) { + if (!notReferencedIn(m, t, pt)) { + return false; + } + } + return true; case 'listType': return notReferencedIn(m, t, withinType.typeKind.value.elemType!); case 'mapType': @@ -645,8 +793,8 @@ export function notReferencedIn( notReferencedIn(m, t, withinType.typeKind.value.keyType!) && notReferencedIn(m, t, withinType.typeKind.value.valueType!) ); - case 'type': - return t.typeKind.value !== withinType; + case 'wrapper': + return notReferencedIn(m, t, wrappedType(withinType.typeKind.value)); default: return true; } @@ -688,9 +836,6 @@ export function defaultIsAssignableType( if (isNullableType(current) && isNullType(fromType)) { return true; } - if (current.typeKind.case === 'typeParam') { - return true; - } const unwrappedCurrent = unwrapNullableType(current); if ( !isNil(unwrappedCurrent) && @@ -699,15 +844,27 @@ export function defaultIsAssignableType( ) { return true; } - if ( - current.typeKind.case !== fromType.typeKind.case || - current.$typeName !== fromType.$typeName - ) { - return false; - } switch (current.typeKind.case) { + case 'primitive': + case 'wellKnown': + case 'wrapper': + return current.typeKind.value === fromType.typeKind.value; + case 'messageType': + const checkedType = getCheckedWellKnownType(current.typeKind.value); + if (!isNil(checkedType)) { + return defaultIsAssignableType(checkedType, fromType); + } + return current.typeKind.value === fromType.typeKind.value; + case 'type': + return fromType.typeKind.case === 'type'; case 'abstractType': - if (fromType.typeKind.case !== current.typeKind.case) { + if (current.typeKind.case !== fromType.typeKind.case) { + return false; + } + if ( + current.typeKind.value.parameterTypes.length !== + fromType.typeKind.value.parameterTypes.length + ) { return false; } for (let i = 0; i < current.typeKind.value.parameterTypes.length; i++) { @@ -722,7 +879,7 @@ export function defaultIsAssignableType( } return true; case 'listType': - if (fromType.typeKind.case !== current.typeKind.case) { + if (fromType.typeKind.case !== 'listType') { return false; } return defaultIsAssignableType( @@ -730,7 +887,7 @@ export function defaultIsAssignableType( fromType.typeKind.value.elemType! ); case 'mapType': - if (fromType.typeKind.case !== current.typeKind.case) { + if (fromType.typeKind.case !== 'mapType') { return false; } return ( @@ -744,9 +901,8 @@ export function defaultIsAssignableType( ) ); default: - break; + return true; } - return isExactType(current, fromType); } /** @@ -758,7 +914,7 @@ export function substitute( t: Type, typeParamToDyn: boolean ): Type { - const tSub = findTypeInMapping(mapping, t); + const tSub = mapping.get(formatCELType(t)); if (!isNil(tSub)) { return substitute(mapping, tSub, typeParamToDyn); } @@ -766,6 +922,17 @@ export function substitute( return DYN_TYPE; } switch (t.typeKind.case) { + case 'function': + return functionType({ + argTypes: t.typeKind.value.argTypes.map((_t) => + substitute(mapping, _t, typeParamToDyn) + ), + resultType: substitute( + mapping, + t.typeKind.value.resultType!, + typeParamToDyn + ), + }); case 'abstractType': return abstractType({ name: t.typeKind.value.name, @@ -791,39 +958,7 @@ export function substitute( ), }); case 'type': - return substitute(mapping, t.typeKind.value, typeParamToDyn); - // case 'typeParam': - // const sub = mapping.get(t.typeKind.value); - // if (!isNil(sub)) { - // return substitute(mapping, sub, typeParamToDyn); - // } - // return t; - // case 'messageType': - // // Handle special cases for certain message types. - // switch (t.typeKind.value) { - // case 'google.protobuf.Struct': - // return mapType({ - // keyType: STRING_TYPE, - // valueType: - // typeParamToDyn === true - // ? DYN_TYPE - // : substitute(mapping, typeParamType('B'), typeParamToDyn), - // }); - // case 'google.protobuf.Value': - // return typeParamToDyn === true - // ? DYN_TYPE - // : substitute(mapping, typeParamType('A'), typeParamToDyn); - // case 'google.protobuf.ListValue': - // return listType({ - // elemType: - // typeParamToDyn === true - // ? DYN_TYPE - // : substitute(mapping, typeParamType('A'), typeParamToDyn), - // }); - // default: - // break; - // } - // return t; + return typeType(substitute(mapping, t.typeKind.value, typeParamToDyn)); default: return t; } @@ -872,13 +1007,14 @@ export function formatCELType(t: Type | null): string { case 'typeParam': return t.typeKind.value; case 'abstractType': - if (t.typeKind.value.name === 'function') { - // TODO: implement - } - break; + const at = t.typeKind.value; + return `${at.name}(${at.parameterTypes.map(formatCELType).join(', ')})`; case 'listType': return `list(${formatCELType(t.typeKind.value.elemType!)})`; case 'type': + if (isNil(t.typeKind.value) || isNil(t.typeKind.value.typeKind.value)) { + return 'type'; + } return formatCELType(t.typeKind.value); case 'messageType': return t.typeKind.value; @@ -886,6 +1022,16 @@ export function formatCELType(t: Type | null): string { const keyType = formatCELType(t.typeKind.value.keyType!); const valueType = formatCELType(t.typeKind.value.valueType!); return `map(${keyType}, ${valueType})`; + case 'dyn': + return 'dyn'; + case 'function': + return formatFunctionDeclType( + t.typeKind.value.resultType!, + t.typeKind.value.argTypes, + false + ); + case 'wrapper': + return `wrapper(${formatCELType(primitiveType(t.typeKind.value))})`; } return ''; } diff --git a/packages/cel/src/lib/utils.ts b/packages/cel/src/lib/utils.ts index df07ac7..39fe1d1 100644 --- a/packages/cel/src/lib/utils.ts +++ b/packages/cel/src/lib/utils.ts @@ -1,9 +1,11 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable no-case-declarations */ /* eslint-disable @typescript-eslint/no-unused-vars */ import { isNil } from '@bearclaw/is'; import { DeclSchema, Decl_FunctionDeclSchema, + Decl_FunctionDecl_OverloadSchema, Decl_IdentDeclSchema, ReferenceSchema, Type_PrimitiveType, @@ -427,6 +429,12 @@ export function functionDecl( }); } +export function overloadDecl( + init: MessageInitShape +) { + return create(Decl_FunctionDecl_OverloadSchema, init); +} + export function identDecl( name: string, init: MessageInitShape @@ -539,24 +547,25 @@ export function mapToObject( * @param expr the expression AST * @returns a qualified name or an empty string */ -export function toQualifiedName(expr: Expr): string { +export function toQualifiedName(expr: Expr): string | null { switch (expr.exprKind.case) { case 'identExpr': return expr.exprKind.value.name; case 'selectExpr': + const sel = expr.exprKind.value; // Test only expressions are not valid as qualified names. - if (expr.exprKind.value.testOnly) { - return ''; + if (sel.testOnly) { + return null; } - if (isNil(expr.exprKind.value.operand)) { - return ''; + const qual = toQualifiedName(sel.operand!); + if (!isNil(qual)) { + return `${qual}.${sel.field}`; } - return `${toQualifiedName(expr.exprKind.value.operand)}.${ - expr.exprKind.value.field - }`; + break; default: - return ''; + break; } + return null; } /** From 5eb25a5b555b090310e2bbe85609e91efd3442d6 Mon Sep 17 00:00:00 2001 From: jafaircl Date: Thu, 10 Oct 2024 15:05:18 -0400 Subject: [PATCH 23/34] test(cel): add remaining test cases --- packages/cel/src/lib/checker.spec.ts | 1135 +++++++++++++++++++++++++- packages/cel/src/lib/checker.ts | 6 +- packages/cel/src/lib/errors.ts | 6 +- packages/cel/src/lib/standard.ts | 5 + packages/cel/src/lib/types.ts | 32 +- 5 files changed, 1140 insertions(+), 44 deletions(-) diff --git a/packages/cel/src/lib/checker.spec.ts b/packages/cel/src/lib/checker.spec.ts index 5545d8b..2f61ece 100644 --- a/packages/cel/src/lib/checker.spec.ts +++ b/packages/cel/src/lib/checker.spec.ts @@ -1,8 +1,13 @@ import { isNil } from '@bearclaw/is'; import { - TestAllTypesSchema, - TestAllTypes_NestedEnumSchema, - TestAllTypes_NestedMessageSchema, + TestAllTypesSchema as TestAllTypesSchemaProto2, + TestAllTypes_NestedEnumSchema as TestAllTypes_NestedEnumSchemaProto2, + TestAllTypes_NestedMessageSchema as TestAllTypes_NestedMessageSchemaProto2, +} from '@buf/cel_spec.bufbuild_es/proto/test/v1/proto2/test_all_types_pb.js'; +import { + TestAllTypesSchema as TestAllTypesSchemaProto3, + TestAllTypes_NestedEnumSchema as TestAllTypes_NestedEnumSchemaProto3, + TestAllTypes_NestedMessageSchema as TestAllTypes_NestedMessageSchemaProto3, } from '@buf/cel_spec.bufbuild_es/proto/test/v1/proto3/test_all_types_pb.js'; import { Type } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; import { createMutableRegistry } from '@bufbuild/protobuf'; @@ -20,9 +25,11 @@ import { NULL_TYPE, STRING_TYPE, UINT64_TYPE, + abstractType, listType, mapType, messageType, + typeParamType, } from './types'; import { functionDecl, identDecl, overloadDecl } from './utils'; @@ -52,14 +59,15 @@ interface TestInfo { // opts []Option } -// TODO: The package name for TestAllTypes is different in cel-go because we have to import from a different package. - function getDefaultEnv() { return STANDARD_ENV().extend({ registry: createMutableRegistry( - TestAllTypesSchema, - TestAllTypes_NestedMessageSchema, - TestAllTypes_NestedEnumSchema + TestAllTypesSchemaProto3, + TestAllTypes_NestedMessageSchemaProto3, + TestAllTypes_NestedEnumSchemaProto3, + TestAllTypesSchemaProto2, + TestAllTypes_NestedMessageSchemaProto2, + TestAllTypes_NestedEnumSchemaProto2 ), idents: [ identDecl('is', { type: STRING_TYPE }), @@ -293,7 +301,6 @@ _+_( out: `{1~int : 2u~uint, 2u~uint : 3~int}~map(dyn, dyn)`, }, { - // TODO: this test container is different than in cel-go because we have to import from a different package in: `TestAllTypes{single_int32: 1, single_int64: 2}`, container: 'google.api.expr.test.v1.proto3', out: ` @@ -307,7 +314,6 @@ _+_( }), }, { - // TODO: this test container is different than in cel-go because we have to import from a different package in: `TestAllTypes{single_int32: 1u}`, container: 'google.api.expr.test.v1.proto3', err: ` @@ -319,7 +325,6 @@ ERROR: :1:26: expected type of field 'single_int32' is 'int' but provided }), }, { - // TODO: this test container is different than in cel-go because we have to import from a different package in: `TestAllTypes{single_int32: 1, undefined: 2}`, container: 'google.api.expr.test.v1.proto3', err: ` @@ -442,7 +447,6 @@ ERROR: :1:2: unexpected failed resolution of 'google.api.expr.test.v1.pro `, }, { - // TODO: this test container is different than in cel-go because we have to import from a different package in: `x.single_value + 1 / x.single_struct.y == 23`, env: getDefaultEnv().extend({ idents: [ @@ -464,7 +468,6 @@ ERROR: :1:2: unexpected failed resolution of 'google.api.expr.test.v1.pro outType: BOOL_TYPE, }, { - // TODO: this test container is different than in cel-go because we have to import from a different package in: `x.single_value[23] + x.single_struct['y']`, env: getDefaultEnv().extend({ idents: [ @@ -746,7 +749,6 @@ ERROR: :1:2: found no matching overload for '_[_]' applied to '(list(goog | .^ `, }, - // TODO: this failes with a weird error where it says there's no matching overload for _==_ (int, int) { in: `x["a"].single_int32 == 23`, env: getDefaultEnv().extend({ @@ -1301,7 +1303,7 @@ _==_(map~type(map(dyn, dyn))^map, ], }), out: ` -_!=_(_+_(x~google.expr.proto3.test.TestAllTypes^x.single_int64_wrapper +_!=_(_+_(x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_int64_wrapper ~wrapper(int), 1~int) ~int^add_int64, @@ -1310,10 +1312,1105 @@ _!=_(_+_(x~google.expr.proto3.test.TestAllTypes^x.single_int64_wrapper `, outType: BOOL_TYPE, }, + { + in: `x.single_int64_wrapper + y != 23`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('x', { + type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + }), + identDecl('y', { type: messageType('google.protobuf.Int32Value') }), + ], + }), + out: ` +_!=_( + _+_( + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_int64_wrapper~wrapper(int), + y~wrapper(int)^y + )~int^add_int64, + 23~int + )~bool^not_equals +`, + outType: BOOL_TYPE, + }, + { + in: `1 in [1, 2, 3]`, + out: `@in( + 1~int, + [ + 1~int, + 2~int, + 3~int + ]~list(int) + )~bool^in_list`, + outType: BOOL_TYPE, + }, + { + in: `1 in dyn([1, 2, 3])`, + out: `@in( + 1~int, + dyn( + [ + 1~int, + 2~int, + 3~int + ]~list(int) + )~dyn^to_dyn + )~bool^in_list|in_map`, + outType: BOOL_TYPE, + }, + { + in: `type(null) == null_type`, + out: `_==_( + type( + null~null + )~type(null)^type, + null_type~type(null)^null_type + )~bool^equals`, + outType: BOOL_TYPE, + }, + { + in: `type(type) == type`, + out: `_==_( + type( + type~type(type)^type + )~type(type(type))^type, + type~type(type)^type +)~bool^equals`, + outType: BOOL_TYPE, + }, + { + in: `([[[1]], [[2]], [[3]]][0][0] + [2, 3, {'four': {'five': 'six'}}])[3]`, + out: `_[_]( + _+_( + _[_]( + _[_]( + [ + [ + [ + 1~int + ]~list(int) + ]~list(list(int)), + [ + [ + 2~int + ]~list(int) + ]~list(list(int)), + [ + [ + 3~int + ]~list(int) + ]~list(list(int)) + ]~list(list(list(int))), + 0~int + )~list(list(int))^index_list, + 0~int + )~list(int)^index_list, + [ + 2~int, + 3~int, + { + "four"~string:{ + "five"~string:"six"~string + }~map(string, string) + }~map(string, map(string, string)) + ]~list(dyn) + )~list(dyn)^add_list, + 3~int +)~dyn^index_list`, + outType: DYN_TYPE, + }, + { + in: `[1] + [dyn('string')]`, + out: `_+_( + [ + 1~int + ]~list(int), + [ + dyn( + "string"~string + )~dyn^to_dyn + ]~list(dyn) +)~list(dyn)^add_list`, + outType: listType({ elemType: DYN_TYPE }), + }, + { + in: `[dyn('string')] + [1]`, + out: `_+_( + [ + dyn( + "string"~string + )~dyn^to_dyn + ]~list(dyn), + [ + 1~int + ]~list(int) +)~list(dyn)^add_list`, + outType: listType({ elemType: DYN_TYPE }), + }, + // TODO; this one throws the correct error and points to the right spot but the argTypes are (_var2, _var0) instead of (list(dyn), dyn) + // { + // in: `[].map(x, [].map(y, x in y && y in x))`, + // err: ` + // ERROR: :1:33: found no matching overload for '@in' applied to '(list(dyn), dyn)' + // | [].map(x, [].map(y, x in y && y in x)) + // | ................................^`, + // }, + { + in: `args.user["myextension"].customAttributes.filter(x, x.name == "hobbies")`, + out: `__comprehension__( + // Variable + x, + // Target + _[_]( + args~map(string, dyn)^args.user~dyn, + "myextension"~string + )~dyn^index_map.customAttributes~dyn, + // Accumulator + __result__, + // Init + []~list(dyn), + // LoopCondition + true~bool, + // LoopStep + _?_:_( + _==_( + x~dyn^x.name~dyn, + "hobbies"~string + )~bool^equals, + _+_( + __result__~list(dyn)^__result__, + [ + x~dyn^x + ]~list(dyn) + )~list(dyn)^add_list, + __result__~list(dyn)^__result__ + )~list(dyn)^conditional, + // Result + __result__~list(dyn)^__result__)~list(dyn)`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('args', { + type: mapType({ keyType: STRING_TYPE, valueType: DYN_TYPE }), + }), + ], + }), + outType: listType({ elemType: DYN_TYPE }), + }, + { + in: `a.b + 1 == a[0]`, + out: `_==_( + _+_( + a~dyn^a.b~dyn, + 1~int + )~int^add_int64, + _[_]( + a~dyn^a, + 0~int + )~dyn^index_list|index_map + )~bool^equals`, + env: getDefaultEnv().extend({ + idents: [identDecl('a', { type: typeParamType('T') })], + }), + outType: BOOL_TYPE, + }, + { + in: `!has(pb2.single_int64) + && !has(pb2.repeated_int32) + && !has(pb2.map_string_string) + && !has(pb3.single_int64) + && !has(pb3.repeated_int32) + && !has(pb3.map_string_string)`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('pb2', { + type: messageType('google.api.expr.test.v1.proto2.TestAllTypes'), + }), + identDecl('pb3', { + type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + }), + ], + }), + out: ` + _&&_( + _&&_( + _&&_( + !_( + pb2~google.api.expr.test.v1.proto2.TestAllTypes^pb2.single_int64~test-only~~bool + )~bool^logical_not, + !_( + pb2~google.api.expr.test.v1.proto2.TestAllTypes^pb2.repeated_int32~test-only~~bool + )~bool^logical_not + )~bool^logical_and, + !_( + pb2~google.api.expr.test.v1.proto2.TestAllTypes^pb2.map_string_string~test-only~~bool + )~bool^logical_not + )~bool^logical_and, + _&&_( + _&&_( + !_( + pb3~google.api.expr.test.v1.proto3.TestAllTypes^pb3.single_int64~test-only~~bool + )~bool^logical_not, + !_( + pb3~google.api.expr.test.v1.proto3.TestAllTypes^pb3.repeated_int32~test-only~~bool + )~bool^logical_not + )~bool^logical_and, + !_( + pb3~google.api.expr.test.v1.proto3.TestAllTypes^pb3.map_string_string~test-only~~bool + )~bool^logical_not + )~bool^logical_and + )~bool^logical_and`, + outType: BOOL_TYPE, + }, + { + in: `TestAllTypes{}.repeated_nested_message`, + container: 'google.api.expr.test.v1.proto2', + out: ` +google.api.expr.test.v1.proto2.TestAllTypes{}~google.api.expr.test.v1.proto2.TestAllTypes^ +google.api.expr.test.v1.proto2.TestAllTypes.repeated_nested_message +~list(google.api.expr.test.v1.proto2.TestAllTypes.NestedMessage)`, + outType: listType({ + elemType: messageType( + 'google.api.expr.test.v1.proto2.TestAllTypes.NestedMessage' + ), + }), + }, + { + in: `TestAllTypes{}.repeated_nested_message`, + container: 'google.api.expr.test.v1.proto3', + out: ` + google.api.expr.test.v1.proto3.TestAllTypes{}~google.api.expr.test.v1.proto3.TestAllTypes^ + google.api.expr.test.v1.proto3.TestAllTypes.repeated_nested_message + ~list(google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage)`, + outType: listType({ + elemType: messageType( + 'google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage' + ), + }), + }, + { + in: `base64.encode('hello')`, + env: getDefaultEnv().extend({ + functions: [ + functionDecl('base64.encode', { + overloads: [ + overloadDecl({ + overloadId: 'base64_encode_string', + params: [STRING_TYPE], + resultType: STRING_TYPE, + }), + ], + }), + ], + }), + out: ` + base64.encode( + "hello"~string + )~string^base64_encode_string`, + outType: STRING_TYPE, + }, + // TODO: namespaced functions + // { + // in: `encode('hello')`, + // container: `base64`, + // env: getDefaultEnv().extend({ + // functions: [ + // functionDecl('base64.encode', { + // overloads: [ + // overloadDecl({ + // overloadId: 'base64_encode_string', + // params: [STRING_TYPE], + // resultType: STRING_TYPE, + // }), + // ], + // }), + // ], + // }), + // out: ` + // base64.encode( + // "hello"~string + // )~string^base64_encode_string`, + // outType: STRING_TYPE, + // }, + { + in: `{}`, + out: `{}~map(dyn, dyn)`, + outType: mapType({ keyType: DYN_TYPE, valueType: DYN_TYPE }), + }, + { + in: `set([1, 2, 3])`, + out: ` +set( + [ + 1~int, + 2~int, + 3~int + ]~list(int) +)~set(int)^set_list`, + env: getDefaultEnv().extend({ + functions: [ + functionDecl('set', { + overloads: [ + overloadDecl({ + overloadId: 'set_list', + params: [listType({ elemType: typeParamType('T') })], + resultType: abstractType({ + name: 'set', + parameterTypes: [typeParamType('T')], + }), + }), + ], + }), + ], + }), + outType: abstractType({ name: 'set', parameterTypes: [INT64_TYPE] }), + }, + { + in: `set([1, 2]) == set([2, 1])`, + out: ` + _==_( + set([1~int, 2~int]~list(int))~set(int)^set_list, + set([2~int, 1~int]~list(int))~set(int)^set_list + )~bool^equals`, + env: getDefaultEnv().extend({ + functions: [ + functionDecl('set', { + overloads: [ + overloadDecl({ + overloadId: 'set_list', + params: [listType({ elemType: typeParamType('T') })], + resultType: abstractType({ + name: 'set', + parameterTypes: [typeParamType('T')], + }), + }), + ], + }), + ], + }), + outType: BOOL_TYPE, + }, + { + in: `set([1, 2]) == x`, + out: ` +_==_( + set([1~int, 2~int]~list(int))~set(int)^set_list, + x~set(int)^x +)~bool^equals`, + env: getDefaultEnv().extend({ + functions: [ + functionDecl('set', { + overloads: [ + overloadDecl({ + overloadId: 'set_list', + params: [listType({ elemType: typeParamType('T') })], + resultType: abstractType({ + name: 'set', + parameterTypes: [typeParamType('T')], + }), + }), + ], + }), + ], + idents: [ + identDecl('x', { + type: abstractType({ + name: 'set', + parameterTypes: [typeParamType('T')], + }), + }), + ], + }), + outType: BOOL_TYPE, + }, + { + in: `int{}`, + err: ` + ERROR: :1:4: 'int' is not a message type + | int{} + | ...^ + `, + }, + { + in: `Msg{}`, + err: ` + ERROR: :1:4: undeclared reference to 'Msg' (in container '') + | Msg{} + | ...^ + `, + }, + { + in: `fun()`, + err: ` + ERROR: :1:4: undeclared reference to 'fun' (in container '') + | fun() + | ...^ + `, + }, + { + in: `'string'.fun()`, + err: ` + ERROR: :1:13: undeclared reference to 'fun' (in container '') + | 'string'.fun() + | ............^ + `, + }, + { + in: `[].length`, + err: ` + ERROR: :1:3: type 'list(_var0)' does not support field selection + | [].length + | ..^ + `, + }, + // TODO: implement CrossTypeNumericComparisons + // { + // in: `1 <= 1.0 && 1u <= 1.0 && 1.0 <= 1 && 1.0 <= 1u && 1 <= 1u && 1u <= 1`, + // opts: []Option{CrossTypeNumericComparisons(false)}, + // err: ` + // ERROR: :1:3: found no matching overload for '_<=_' applied to '(int, double)' + // | 1 <= 1.0 && 1u <= 1.0 && 1.0 <= 1 && 1.0 <= 1u && 1 <= 1u && 1u <= 1 + // | ..^ + // ERROR: :1:16: found no matching overload for '_<=_' applied to '(uint, double)' + // | 1 <= 1.0 && 1u <= 1.0 && 1.0 <= 1 && 1.0 <= 1u && 1 <= 1u && 1u <= 1 + // | ...............^ + // ERROR: :1:30: found no matching overload for '_<=_' applied to '(double, int)' + // | 1 <= 1.0 && 1u <= 1.0 && 1.0 <= 1 && 1.0 <= 1u && 1 <= 1u && 1u <= 1 + // | .............................^ + // ERROR: :1:42: found no matching overload for '_<=_' applied to '(double, uint)' + // | 1 <= 1.0 && 1u <= 1.0 && 1.0 <= 1 && 1.0 <= 1u && 1 <= 1u && 1u <= 1 + // | .........................................^ + // ERROR: :1:53: found no matching overload for '_<=_' applied to '(int, uint)' + // | 1 <= 1.0 && 1u <= 1.0 && 1.0 <= 1 && 1.0 <= 1u && 1 <= 1u && 1u <= 1 + // | ....................................................^ + // ERROR: :1:65: found no matching overload for '_<=_' applied to '(uint, int)' + // | 1 <= 1.0 && 1u <= 1.0 && 1.0 <= 1 && 1.0 <= 1u && 1 <= 1u && 1u <= 1 + // | ................................................................^ + // `, + // }, + // { + // in: `1 <= 1.0 && 1u <= 1.0 && 1.0 <= 1 && 1.0 <= 1u && 1 <= 1u && 1u <= 1`, + // opts: []Option{CrossTypeNumericComparisons(true)}, + // outType: types.BoolType, + // out: ` + // _&&_( + // _&&_( + // _&&_( + // _<=_( + // 1~int, + // 1~double + // )~bool^less_equals_int64_double, + // _<=_( + // 1u~uint, + // 1~double + // )~bool^less_equals_uint64_double + // )~bool^logical_and, + // _<=_( + // 1~double, + // 1~int + // )~bool^less_equals_double_int64 + // )~bool^logical_and, + // _&&_( + // _&&_( + // _<=_( + // 1~double, + // 1u~uint + // )~bool^less_equals_double_uint64, + // _<=_( + // 1~int, + // 1u~uint + // )~bool^less_equals_int64_uint64 + // )~bool^logical_and, + // _<=_( + // 1u~uint, + // 1~int + // )~bool^less_equals_uint64_int64 + // )~bool^logical_and + // )~bool^logical_and`, + // }, + // { + // in: `1 < 1.0 && 1u < 1.0 && 1.0 < 1 && 1.0 < 1u && 1 < 1u && 1u < 1`, + // opts: []Option{CrossTypeNumericComparisons(true)}, + // outType: types.BoolType, + // out: ` + // _&&_( + // _&&_( + // _&&_( + // _<_( + // 1~int, + // 1~double + // )~bool^less_int64_double, + // _<_( + // 1u~uint, + // 1~double + // )~bool^less_uint64_double + // )~bool^logical_and, + // _<_( + // 1~double, + // 1~int + // )~bool^less_double_int64 + // )~bool^logical_and, + // _&&_( + // _&&_( + // _<_( + // 1~double, + // 1u~uint + // )~bool^less_double_uint64, + // _<_( + // 1~int, + // 1u~uint + // )~bool^less_int64_uint64 + // )~bool^logical_and, + // _<_( + // 1u~uint, + // 1~int + // )~bool^less_uint64_int64 + // )~bool^logical_and + // )~bool^logical_and`, + // }, + // { + // in: `1 > 1.0 && 1u > 1.0 && 1.0 > 1 && 1.0 > 1u && 1 > 1u && 1u > 1`, + // opts: []Option{CrossTypeNumericComparisons(true)}, + // outType: types.BoolType, + // out: ` + // _&&_( + // _&&_( + // _&&_( + // _>_( + // 1~int, + // 1~double + // )~bool^greater_int64_double, + // _>_( + // 1u~uint, + // 1~double + // )~bool^greater_uint64_double + // )~bool^logical_and, + // _>_( + // 1~double, + // 1~int + // )~bool^greater_double_int64 + // )~bool^logical_and, + // _&&_( + // _&&_( + // _>_( + // 1~double, + // 1u~uint + // )~bool^greater_double_uint64, + // _>_( + // 1~int, + // 1u~uint + // )~bool^greater_int64_uint64 + // )~bool^logical_and, + // _>_( + // 1u~uint, + // 1~int + // )~bool^greater_uint64_int64 + // )~bool^logical_and + // )~bool^logical_and`, + // }, + // { + // in: `1 >= 1.0 && 1u >= 1.0 && 1.0 >= 1 && 1.0 >= 1u && 1 >= 1u && 1u >= 1`, + // opts: []Option{CrossTypeNumericComparisons(true)}, + // outType: types.BoolType, + // out: ` + // _&&_( + // _&&_( + // _&&_( + // _>=_( + // 1~int, + // 1~double + // )~bool^greater_equals_int64_double, + // _>=_( + // 1u~uint, + // 1~double + // )~bool^greater_equals_uint64_double + // )~bool^logical_and, + // _>=_( + // 1~double, + // 1~int + // )~bool^greater_equals_double_int64 + // )~bool^logical_and, + // _&&_( + // _&&_( + // _>=_( + // 1~double, + // 1u~uint + // )~bool^greater_equals_double_uint64, + // _>=_( + // 1~int, + // 1u~uint + // )~bool^greater_equals_int64_uint64 + // )~bool^logical_and, + // _>=_( + // 1u~uint, + // 1~int + // )~bool^greater_equals_uint64_int64 + // )~bool^logical_and + // )~bool^logical_and`, + // }, + // { + // in: `1 >= 1.0 && 1u >= 1.0 && 1.0 >= 1 && 1.0 >= 1u && 1 >= 1u && 1u >= 1`, + // opts: []Option{CrossTypeNumericComparisons(true)}, + // env: testEnv{variadicASTs: true}, + // outType: types.BoolType, + // out: ` + // _&&_( + // _>=_( + // 1~int, + // 1~double + // )~bool^greater_equals_int64_double, + // _>=_( + // 1u~uint, + // 1~double + // )~bool^greater_equals_uint64_double, + // _>=_( + // 1~double, + // 1~int + // )~bool^greater_equals_double_int64, + // _>=_( + // 1~double, + // 1u~uint + // )~bool^greater_equals_double_uint64, + // _>=_( + // 1~int, + // 1u~uint + // )~bool^greater_equals_int64_uint64, + // _>=_( + // 1u~uint, + // 1~int + // )~bool^greater_equals_uint64_int64 + // )~bool^logical_and`, + // }, + { + in: `[1].map(x, [x, x]).map(x, [x, x])`, + outType: listType({ + elemType: listType({ elemType: listType({ elemType: INT64_TYPE }) }), + }), + out: `__comprehension__( + // Variable + x, + // Target + __comprehension__( + // Variable + x, + // Target + [ + 1~int + ]~list(int), + // Accumulator + __result__, + // Init + []~list(list(int)), + // LoopCondition + true~bool, + // LoopStep + _+_( + __result__~list(list(int))^__result__, + [ + [ + x~int^x, + x~int^x + ]~list(int) + ]~list(list(int)) + )~list(list(int))^add_list, + // Result + __result__~list(list(int))^__result__)~list(list(int)), + // Accumulator + __result__, + // Init + []~list(list(list(int))), + // LoopCondition + true~bool, + // LoopStep + _+_( + __result__~list(list(list(int)))^__result__, + [ + [ + x~list(int)^x, + x~list(int)^x + ]~list(list(int)) + ]~list(list(list(int))) + )~list(list(list(int)))^add_list, + // Result + __result__~list(list(list(int)))^__result__)~list(list(list(int))) + `, + }, + { + in: `values.filter(i, i.content != "").map(i, i.content)`, + outType: listType({ elemType: STRING_TYPE }), + env: getDefaultEnv().extend({ + idents: [ + identDecl('values', { + type: listType({ + elemType: mapType({ keyType: STRING_TYPE, valueType: STRING_TYPE }), + }), + }), + ], + }), + out: `__comprehension__( + // Variable + i, + // Target + __comprehension__( + // Variable + i, + // Target + values~list(map(string, string))^values, + // Accumulator + __result__, + // Init + []~list(map(string, string)), + // LoopCondition + true~bool, + // LoopStep + _?_:_( + _!=_( + i~map(string, string)^i.content~string, + ""~string + )~bool^not_equals, + _+_( + __result__~list(map(string, string))^__result__, + [ + i~map(string, string)^i + ]~list(map(string, string)) + )~list(map(string, string))^add_list, + __result__~list(map(string, string))^__result__ + )~list(map(string, string))^conditional, + // Result + __result__~list(map(string, string))^__result__)~list(map(string, string)), + // Accumulator + __result__, + // Init + []~list(string), + // LoopCondition + true~bool, + // LoopStep + _+_( + __result__~list(string)^__result__, + [ + i~map(string, string)^i.content~string + ]~list(string) + )~list(string)^add_list, + // Result + __result__~list(string)^__result__)~list(string)`, + }, + // TODO: Not sure the 3rd param for map is implemented + // { + // in: `[{}.map(c,c,c)]+[{}.map(c,c,c)]`, + // outType: listType({ elemType: listType({ elemType: BOOL_TYPE }) }), + // out: `_+_( + // [ + // __comprehension__( + // // Variable + // c, + // // Target + // {}~map(bool, dyn), + // // Accumulator + // __result__, + // // Init + // []~list(bool), + // // LoopCondition + // true~bool, + // // LoopStep + // _?_:_( + // c~bool^c, + // _+_( + // __result__~list(bool)^__result__, + // [ + // c~bool^c + // ]~list(bool) + // )~list(bool)^add_list, + // __result__~list(bool)^__result__ + // )~list(bool)^conditional, + // // Result + // __result__~list(bool)^__result__)~list(bool) + // ]~list(list(bool)), + // [ + // __comprehension__( + // // Variable + // c, + // // Target + // {}~map(bool, dyn), + // // Accumulator + // __result__, + // // Init + // []~list(bool), + // // LoopCondition + // true~bool, + // // LoopStep + // _?_:_( + // c~bool^c, + // _+_( + // __result__~list(bool)^__result__, + // [ + // c~bool^c + // ]~list(bool) + // )~list(bool)^add_list, + // __result__~list(bool)^__result__ + // )~list(bool)^conditional, + // // Result + // __result__~list(bool)^__result__)~list(bool) + // ]~list(list(bool)) + // )~list(list(bool))^add_list`, + // }, + // TODO: nestedgroup does not exist on TestAllTypes. Revisit when we switch to the buf-managed proto + // { + // in: 'type(testAllTypes.nestedgroup.nested_id) == int', + // env: getDefaultEnv().extend({ + // idents: [ + // identDecl('testAllTypes', { + // type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), + // }), + // ], + // }), + // outType: BOOL_TYPE, + // out: `_==_( + // type( + // testAllTypes~google.api.expr.test.v1.proto3.TestAllTypes^testAllTypes.nestedgroup~google.api.expr.test.v1.proto3.TestAllTypes.NestedGroup.nested_id~int + // )~type(int)^type, + // int~type(int)^int + // )~bool^equals`, + // }, + // TODO: Optionals + // { + // in: `a.?b`, + // env: getDefaultEnv().extend({ + // idents: [ + // identDecl('a', { + // type: mapType({ + // keyType: STRING_TYPE, + // valueType: optionalType(STRING_TYPE), + // }), + // }), + // ], + // }), + // outType: optionalType(STRING_TYPE), + // out: `_?._( + // a~map(string, string)^a, + // "b" + // )~optional_type(string)^select_optional_field`, + // }, + // { + // in: `type(a.?b) == optional_type`, + // env: testEnv{ + // optionalSyntax: true, + // idents: []*decls.VariableDecl{ + // decls.NewVariable("a", types.NewMapType(types.StringType, types.StringType)), + // }, + // }, + // outType: types.BoolType, + // out: `_==_( + // type( + // _?._( + // a~map(string, string)^a, + // "b" + // )~optional_type(string)^select_optional_field + // )~type(optional_type(string))^type, + // optional_type~type(optional_type)^optional_type + // )~bool^equals`, + // }, + // { + // in: `a.b`, + // env: testEnv{ + // idents: []*decls.VariableDecl{ + // decls.NewVariable("a", types.NewOptionalType(types.NewMapType(types.StringType, types.StringType))), + // }, + // }, + // outType: types.NewOptionalType(types.StringType), + // out: `a~optional_type(map(string, string))^a.b~optional_type(string)`, + // }, + // { + // in: `a.dynamic`, + // env: testEnv{ + // idents: []*decls.VariableDecl{ + // decls.NewVariable("a", types.NewOptionalType(types.DynType)), + // }, + // }, + // outType: types.NewOptionalType(types.DynType), + // out: `a~optional_type(dyn)^a.dynamic~optional_type(dyn)`, + // }, + // { + // in: `has(a.dynamic)`, + // env: testEnv{ + // idents: []*decls.VariableDecl{ + // decls.NewVariable("a", types.NewOptionalType(types.DynType)), + // }, + // }, + // outType: types.BoolType, + // out: `a~optional_type(dyn)^a.dynamic~test-only~~bool`, + // }, + // { + // in: `has(a.?b.c)`, + // env: testEnv{ + // optionalSyntax: true, + // idents: []*decls.VariableDecl{ + // decls.NewVariable("a", types.NewOptionalType(types.NewMapType(types.StringType, types.DynType))), + // }, + // }, + // outType: types.BoolType, + // out: `_?._( + // a~optional_type(map(string, dyn))^a, + // "b" + // )~optional_type(dyn)^select_optional_field.c~test-only~~bool`, + // }, + // { + // in: `{?'key': {'a': 'b'}.?value}`, + // env: testEnv{optionalSyntax: true}, + // outType: types.NewMapType(types.StringType, types.StringType), + // out: `{ + // ?"key"~string:_?._( + // { + // "a"~string:"b"~string + // }~map(string, string), + // "value" + // )~optional_type(string)^select_optional_field + // }~map(string, string)`, + // }, + // { + // in: `{?'key': {'a': 'b'}.?value}.key`, + // env: testEnv{optionalSyntax: true}, + // outType: types.StringType, + // out: `{ + // ?"key"~string:_?._( + // { + // "a"~string:"b"~string + // }~map(string, string), + // "value" + // )~optional_type(string)^select_optional_field + // }~map(string, string).key~string`, + // }, + // { + // in: `{?'nested': a.b}`, + // env: testEnv{ + // optionalSyntax: true, + // idents: []*decls.VariableDecl{ + // decls.NewVariable("a", types.NewOptionalType(types.NewMapType(types.StringType, types.StringType))), + // }, + // }, + // outType: types.NewMapType(types.StringType, types.StringType), + // out: `{ + // ?"nested"~string:a~optional_type(map(string, string))^a.b~optional_type(string) + // }~map(string, string)`, + // }, + // { + // in: `{?'key': 'hi'}`, + // env: testEnv{optionalSyntax: true}, + // err: `ERROR: :1:10: expected type 'optional_type(string)' but found 'string' + // | {?'key': 'hi'} + // | .........^`, + // }, + // { + // in: `[?a, ?b, 'world']`, + // env: testEnv{ + // optionalSyntax: true, + // idents: []*decls.VariableDecl{ + // decls.NewVariable("a", types.NewOptionalType(types.StringType)), + // decls.NewVariable("b", types.NewOptionalType(types.StringType)), + // }, + // }, + // outType: types.NewListType(types.StringType), + // out: `[ + // a~optional_type(string)^a, + // b~optional_type(string)^b, + // "world"~string + // ]~list(string)`, + // }, + // { + // in: `[?'value']`, + // env: testEnv{optionalSyntax: true}, + // err: `ERROR: :1:3: expected type 'optional_type(string)' but found 'string' + // | [?'value'] + // | ..^`, + // }, + // { + // in: `TestAllTypes{?single_int32: {}.?i}`, + // container: "google.expr.proto2.test", + // env: testEnv{optionalSyntax: true}, + // out: `google.expr.proto2.test.TestAllTypes{ + // ?single_int32:_?._( + // {}~map(dyn, int), + // "i" + // )~optional_type(int)^select_optional_field + // }~google.expr.proto2.test.TestAllTypes^google.expr.proto2.test.TestAllTypes`, + // outType: types.NewObjectType( + // "google.expr.proto2.test.TestAllTypes", + // ), + // }, + // { + // in: `TestAllTypes{?single_int32: 1}`, + // container: "google.expr.proto2.test", + // env: testEnv{optionalSyntax: true}, + // err: `ERROR: :1:29: expected type 'optional_type(int)' but found 'int' + // | TestAllTypes{?single_int32: 1} + // | ............................^`, + // }, + { + in: `undef`, + err: `ERROR: :1:1: undeclared reference to 'undef' (in container '') + | undef + | ^`, + }, + { + in: `undef()`, + err: `ERROR: :1:6: undeclared reference to 'undef' (in container '') + | undef() + | .....^`, + }, + // TODO: nullables + // { + // in: `null_int == null || null == null_int || null_msg == null || null == null_msg`, + // env: testEnv{ + // idents: []*decls.VariableDecl{ + // decls.NewVariable("null_int", types.NewNullableType(types.IntType)), + // decls.NewVariable("null_msg", types.NewObjectType("google.expr.proto2.test.TestAllTypes")), + // }, + // }, + // outType: types.BoolType, + // }, + // { + // in: `NotAMessage{}`, + // env: testEnv{ + // idents: []*decls.VariableDecl{ + // decls.NewVariable("NotAMessage", types.NewNullableType(types.IntType)), + // }, + // }, + // err: `ERROR: :1:12: 'wrapper(int)' is not a type + // | NotAMessage{} + // | ...........^`, + // }, + { + in: `{}.map(c,[c,type(c)])`, + out: `__comprehension__( + // Variable + c, + // Target + {}~map(dyn, dyn), + // Accumulator + __result__, + // Init + []~list(list(dyn)), + // LoopCondition + true~bool, + // LoopStep + _+_( + __result__~list(list(dyn))^__result__, + [ + [ + c~dyn^c, + type( + c~dyn^c + )~type(dyn)^type + ]~list(dyn) + ]~list(list(dyn)) + )~list(list(dyn))^add_list, + // Result + __result__~list(list(dyn))^__result__)~list(list(dyn))`, + outType: listType({ elemType: listType({ elemType: DYN_TYPE }) }), + }, ]; -// TODO: fix TestAllTypes container name mismatch -// TODO: check out strings +// TODO: The package name for TestAllTypes is different in cel-go because we have to import from a different package. +// TODO: test the "out" key strings describe('CELChecker', () => { for (const testCase of testCases) { it(`should check ${testCase.in}`, () => { @@ -1321,6 +2418,10 @@ describe('CELChecker', () => { const env = testCase.env ?? getDefaultEnv().extend({ container }); const parser = new CELParser(testCase.in); const parsed = parser.parse(); + if (testCase.in === `a.?b`) { + console.log('hey buddy'); + console.dir(parsed.expr, { depth: null }); + } if (isNil(parsed.expr)) { throw new Error('parsed.expr is nil'); } diff --git a/packages/cel/src/lib/checker.ts b/packages/cel/src/lib/checker.ts index fa48f12..c70ab60 100644 --- a/packages/cel/src/lib/checker.ts +++ b/packages/cel/src/lib/checker.ts @@ -624,7 +624,11 @@ export class CELChecker { this.checkExpr(comp.iterRange); this.checkExpr(comp.accuInit); const accuType = this.getType(comp.accuInit!.id); - const rangeType = this.getType(comp.iterRange!.id)!; + const rangeType = substitute( + this.#mapping, + this.getType(comp.iterRange!.id)!, + false + ); let varType: Type | undefined = undefined; switch (rangeType.typeKind.case) { diff --git a/packages/cel/src/lib/errors.ts b/packages/cel/src/lib/errors.ts index ae177ab..d047d2a 100644 --- a/packages/cel/src/lib/errors.ts +++ b/packages/cel/src/lib/errors.ts @@ -13,7 +13,7 @@ import { create, createRegistry } from '@bufbuild/protobuf'; import { anyPack, anyUnpack } from '@bufbuild/protobuf/wkt'; import { ErrorListener, RecognitionException, Recognizer, Token } from 'antlr4'; import { CELContainer } from './container'; -import { Location, formatCELType, formatFunctionDeclType } from './types'; +import { Location, formatCELType, formatFunctionType } from './types'; export class Errors { public readonly errors = create(ErrorSetSchema); @@ -109,7 +109,7 @@ export class Errors { return this.reportErrorAtId( id, location, - `type '${type.typeKind.case}' does not support field selection` + `type '${formatCELType(type)}' does not support field selection` ); } @@ -124,7 +124,7 @@ export class Errors { args: Type[], isInstance: boolean ) { - const signature = formatFunctionDeclType(null, args, isInstance); + const signature = formatFunctionType(null, args, isInstance); return this.reportErrorAtId( id, location, diff --git a/packages/cel/src/lib/standard.ts b/packages/cel/src/lib/standard.ts index ff2246a..7b4435d 100644 --- a/packages/cel/src/lib/standard.ts +++ b/packages/cel/src/lib/standard.ts @@ -238,8 +238,10 @@ import { DURATION_TYPE, DYN_TYPE, INT64_TYPE, + NULL_TYPE, STRING_TYPE, TIMESTAMP_TYPE, + TYPE_TYPE, UINT64_TYPE, listType, mapType, @@ -287,6 +289,9 @@ export const STANDARD_IDENTS: Decl[] = [ identDecl('map', { type: typeType(mapType({ keyType: DYN_TYPE, valueType: DYN_TYPE })), }), + identDecl('type', { type: typeType(TYPE_TYPE) }), + identDecl('null_type', { type: typeType(NULL_TYPE) }), + identDecl('null', { type: NULL_TYPE }), ]; const paramA = typeParamType('A'); diff --git a/packages/cel/src/lib/types.ts b/packages/cel/src/lib/types.ts index 91ea90a..dc14159 100644 --- a/packages/cel/src/lib/types.ts +++ b/packages/cel/src/lib/types.ts @@ -238,6 +238,8 @@ export function abstractType( }); } +export const TYPE_TYPE = abstractType({ name: 'type' }); + export function optionalType(value: Type) { return abstractType({ name: 'optional_type', parameterTypes: [value] }); } @@ -1025,7 +1027,7 @@ export function formatCELType(t: Type | null): string { case 'dyn': return 'dyn'; case 'function': - return formatFunctionDeclType( + return formatFunctionType( t.typeKind.value.resultType!, t.typeKind.value.argTypes, false @@ -1141,44 +1143,28 @@ export function isExactTypeList(t1: Type[], t2: Type[]) { return true; } -export function formatFunctionDeclType( +export function formatFunctionType( resultType: Type | null, argTypes: Type[], isInstance: boolean -): string { - return formatFunctionInternal( - resultType, - argTypes, - isInstance, - formatCELType - ); -} - -function formatFunctionInternal( - resultType: T | null, - argTypes: T[], - isInstance: boolean, - format: (value: T | null) => string ): string { let result = ''; if (isInstance) { const target = argTypes[0]; argTypes = argTypes.slice(1); - result += format(target); - result += '.'; + result = formatCELType(target) + '.'; } result += '('; for (let i = 0; i < argTypes.length; i++) { + const argType = argTypes[i]; if (i > 0) { result += ', '; } - result += format(argTypes[i]); + result += formatCELType(argType); } result += ')'; - const rt = format(resultType); - if (rt !== '') { - result += ' -> '; - result += rt; + if (!isNil(resultType)) { + result += ' -> ' + formatCELType(resultType); } return result; } From ddfec5f14faa7eb030cc087be6e3b3884aaf8286 Mon Sep 17 00:00:00 2001 From: jafaircl Date: Mon, 21 Oct 2024 20:50:20 -0400 Subject: [PATCH 24/34] feat(cel): add optionals --- packages/cel/src/lib/checker.spec.ts | 807 ++++++++++++++------------- packages/cel/src/lib/checker.ts | 191 ++++--- packages/cel/src/lib/errors.ts | 12 + packages/cel/src/lib/parser.spec.ts | 2 +- packages/cel/src/lib/types.ts | 5 + 5 files changed, 574 insertions(+), 443 deletions(-) diff --git a/packages/cel/src/lib/checker.spec.ts b/packages/cel/src/lib/checker.spec.ts index 2f61ece..1d560a4 100644 --- a/packages/cel/src/lib/checker.spec.ts +++ b/packages/cel/src/lib/checker.spec.ts @@ -14,7 +14,7 @@ import { createMutableRegistry } from '@bufbuild/protobuf'; import { CELChecker } from './checker'; import { CELContainer } from './container'; import { CELEnvironment, STANDARD_ENV } from './environment'; -import { CELParser } from './parser'; +import { CELParser, CELParserOptions } from './parser'; import { BOOL_TYPE, BYTES_TYPE, @@ -23,12 +23,15 @@ import { ERROR_TYPE, INT64_TYPE, NULL_TYPE, + OPTIONAL_TYPE, STRING_TYPE, UINT64_TYPE, abstractType, listType, mapType, messageType, + nullableType, + optionalType, typeParamType, } from './types'; import { functionDecl, identDecl, overloadDecl } from './utils'; @@ -57,6 +60,7 @@ interface TestInfo { // opts is the set of checker Option flags to use when type-checking. // opts []Option + parserOptions?: CELParserOptions; } function getDefaultEnv() { @@ -1763,7 +1767,7 @@ _==_( | ..^ `, }, - // TODO: implement CrossTypeNumericComparisons + // TODO: implement CrossTypeNumericComparisons flag. Right now they are always enabled // { // in: `1 <= 1.0 && 1u <= 1.0 && 1.0 <= 1 && 1.0 <= 1u && 1 <= 1u && 1u <= 1`, // opts: []Option{CrossTypeNumericComparisons(false)}, @@ -1788,199 +1792,200 @@ _==_( // | ................................................................^ // `, // }, - // { - // in: `1 <= 1.0 && 1u <= 1.0 && 1.0 <= 1 && 1.0 <= 1u && 1 <= 1u && 1u <= 1`, - // opts: []Option{CrossTypeNumericComparisons(true)}, - // outType: types.BoolType, - // out: ` - // _&&_( - // _&&_( - // _&&_( - // _<=_( - // 1~int, - // 1~double - // )~bool^less_equals_int64_double, - // _<=_( - // 1u~uint, - // 1~double - // )~bool^less_equals_uint64_double - // )~bool^logical_and, - // _<=_( - // 1~double, - // 1~int - // )~bool^less_equals_double_int64 - // )~bool^logical_and, - // _&&_( - // _&&_( - // _<=_( - // 1~double, - // 1u~uint - // )~bool^less_equals_double_uint64, - // _<=_( - // 1~int, - // 1u~uint - // )~bool^less_equals_int64_uint64 - // )~bool^logical_and, - // _<=_( - // 1u~uint, - // 1~int - // )~bool^less_equals_uint64_int64 - // )~bool^logical_and - // )~bool^logical_and`, - // }, - // { - // in: `1 < 1.0 && 1u < 1.0 && 1.0 < 1 && 1.0 < 1u && 1 < 1u && 1u < 1`, - // opts: []Option{CrossTypeNumericComparisons(true)}, - // outType: types.BoolType, - // out: ` - // _&&_( - // _&&_( - // _&&_( - // _<_( - // 1~int, - // 1~double - // )~bool^less_int64_double, - // _<_( - // 1u~uint, - // 1~double - // )~bool^less_uint64_double - // )~bool^logical_and, - // _<_( - // 1~double, - // 1~int - // )~bool^less_double_int64 - // )~bool^logical_and, - // _&&_( - // _&&_( - // _<_( - // 1~double, - // 1u~uint - // )~bool^less_double_uint64, - // _<_( - // 1~int, - // 1u~uint - // )~bool^less_int64_uint64 - // )~bool^logical_and, - // _<_( - // 1u~uint, - // 1~int - // )~bool^less_uint64_int64 - // )~bool^logical_and - // )~bool^logical_and`, - // }, - // { - // in: `1 > 1.0 && 1u > 1.0 && 1.0 > 1 && 1.0 > 1u && 1 > 1u && 1u > 1`, - // opts: []Option{CrossTypeNumericComparisons(true)}, - // outType: types.BoolType, - // out: ` - // _&&_( - // _&&_( - // _&&_( - // _>_( - // 1~int, - // 1~double - // )~bool^greater_int64_double, - // _>_( - // 1u~uint, - // 1~double - // )~bool^greater_uint64_double - // )~bool^logical_and, - // _>_( - // 1~double, - // 1~int - // )~bool^greater_double_int64 - // )~bool^logical_and, - // _&&_( - // _&&_( - // _>_( - // 1~double, - // 1u~uint - // )~bool^greater_double_uint64, - // _>_( - // 1~int, - // 1u~uint - // )~bool^greater_int64_uint64 - // )~bool^logical_and, - // _>_( - // 1u~uint, - // 1~int - // )~bool^greater_uint64_int64 - // )~bool^logical_and - // )~bool^logical_and`, - // }, - // { - // in: `1 >= 1.0 && 1u >= 1.0 && 1.0 >= 1 && 1.0 >= 1u && 1 >= 1u && 1u >= 1`, - // opts: []Option{CrossTypeNumericComparisons(true)}, - // outType: types.BoolType, - // out: ` - // _&&_( - // _&&_( - // _&&_( - // _>=_( - // 1~int, - // 1~double - // )~bool^greater_equals_int64_double, - // _>=_( - // 1u~uint, - // 1~double - // )~bool^greater_equals_uint64_double - // )~bool^logical_and, - // _>=_( - // 1~double, - // 1~int - // )~bool^greater_equals_double_int64 - // )~bool^logical_and, - // _&&_( - // _&&_( - // _>=_( - // 1~double, - // 1u~uint - // )~bool^greater_equals_double_uint64, - // _>=_( - // 1~int, - // 1u~uint - // )~bool^greater_equals_int64_uint64 - // )~bool^logical_and, - // _>=_( - // 1u~uint, - // 1~int - // )~bool^greater_equals_uint64_int64 - // )~bool^logical_and - // )~bool^logical_and`, - // }, - // { - // in: `1 >= 1.0 && 1u >= 1.0 && 1.0 >= 1 && 1.0 >= 1u && 1 >= 1u && 1u >= 1`, - // opts: []Option{CrossTypeNumericComparisons(true)}, - // env: testEnv{variadicASTs: true}, - // outType: types.BoolType, - // out: ` - // _&&_( - // _>=_( - // 1~int, - // 1~double - // )~bool^greater_equals_int64_double, - // _>=_( - // 1u~uint, - // 1~double - // )~bool^greater_equals_uint64_double, - // _>=_( - // 1~double, - // 1~int - // )~bool^greater_equals_double_int64, - // _>=_( - // 1~double, - // 1u~uint - // )~bool^greater_equals_double_uint64, - // _>=_( - // 1~int, - // 1u~uint - // )~bool^greater_equals_int64_uint64, - // _>=_( - // 1u~uint, - // 1~int - // )~bool^greater_equals_uint64_int64 - // )~bool^logical_and`, - // }, + { + in: `1 <= 1.0 && 1u <= 1.0 && 1.0 <= 1 && 1.0 <= 1u && 1 <= 1u && 1u <= 1`, + // opts: []Option{CrossTypeNumericComparisons(true)}, + outType: BOOL_TYPE, + out: ` + _&&_( + _&&_( + _&&_( + _<=_( + 1~int, + 1~double + )~bool^less_equals_int64_double, + _<=_( + 1u~uint, + 1~double + )~bool^less_equals_uint64_double + )~bool^logical_and, + _<=_( + 1~double, + 1~int + )~bool^less_equals_double_int64 + )~bool^logical_and, + _&&_( + _&&_( + _<=_( + 1~double, + 1u~uint + )~bool^less_equals_double_uint64, + _<=_( + 1~int, + 1u~uint + )~bool^less_equals_int64_uint64 + )~bool^logical_and, + _<=_( + 1u~uint, + 1~int + )~bool^less_equals_uint64_int64 + )~bool^logical_and + )~bool^logical_and`, + }, + { + in: `1 < 1.0 && 1u < 1.0 && 1.0 < 1 && 1.0 < 1u && 1 < 1u && 1u < 1`, + // opts: []Option{CrossTypeNumericComparisons(true)}, + outType: BOOL_TYPE, + out: ` + _&&_( + _&&_( + _&&_( + _<_( + 1~int, + 1~double + )~bool^less_int64_double, + _<_( + 1u~uint, + 1~double + )~bool^less_uint64_double + )~bool^logical_and, + _<_( + 1~double, + 1~int + )~bool^less_double_int64 + )~bool^logical_and, + _&&_( + _&&_( + _<_( + 1~double, + 1u~uint + )~bool^less_double_uint64, + _<_( + 1~int, + 1u~uint + )~bool^less_int64_uint64 + )~bool^logical_and, + _<_( + 1u~uint, + 1~int + )~bool^less_uint64_int64 + )~bool^logical_and + )~bool^logical_and`, + }, + { + in: `1 > 1.0 && 1u > 1.0 && 1.0 > 1 && 1.0 > 1u && 1 > 1u && 1u > 1`, + // opts: []Option{CrossTypeNumericComparisons(true)}, + outType: BOOL_TYPE, + out: ` + _&&_( + _&&_( + _&&_( + _>_( + 1~int, + 1~double + )~bool^greater_int64_double, + _>_( + 1u~uint, + 1~double + )~bool^greater_uint64_double + )~bool^logical_and, + _>_( + 1~double, + 1~int + )~bool^greater_double_int64 + )~bool^logical_and, + _&&_( + _&&_( + _>_( + 1~double, + 1u~uint + )~bool^greater_double_uint64, + _>_( + 1~int, + 1u~uint + )~bool^greater_int64_uint64 + )~bool^logical_and, + _>_( + 1u~uint, + 1~int + )~bool^greater_uint64_int64 + )~bool^logical_and + )~bool^logical_and`, + }, + { + in: `1 >= 1.0 && 1u >= 1.0 && 1.0 >= 1 && 1.0 >= 1u && 1 >= 1u && 1u >= 1`, + // opts: []Option{CrossTypeNumericComparisons(true)}, + outType: BOOL_TYPE, + out: ` + _&&_( + _&&_( + _&&_( + _>=_( + 1~int, + 1~double + )~bool^greater_equals_int64_double, + _>=_( + 1u~uint, + 1~double + )~bool^greater_equals_uint64_double + )~bool^logical_and, + _>=_( + 1~double, + 1~int + )~bool^greater_equals_double_int64 + )~bool^logical_and, + _&&_( + _&&_( + _>=_( + 1~double, + 1u~uint + )~bool^greater_equals_double_uint64, + _>=_( + 1~int, + 1u~uint + )~bool^greater_equals_int64_uint64 + )~bool^logical_and, + _>=_( + 1u~uint, + 1~int + )~bool^greater_equals_uint64_int64 + )~bool^logical_and + )~bool^logical_and`, + }, + // TODO: implement variadicASTs option? + { + in: `1 >= 1.0 && 1u >= 1.0 && 1.0 >= 1 && 1.0 >= 1u && 1 >= 1u && 1u >= 1`, + // opts: []Option{CrossTypeNumericComparisons(true)}, + // env: testEnv{variadicASTs: true}, + outType: BOOL_TYPE, + out: ` + _&&_( + _>=_( + 1~int, + 1~double + )~bool^greater_equals_int64_double, + _>=_( + 1u~uint, + 1~double + )~bool^greater_equals_uint64_double, + _>=_( + 1~double, + 1~int + )~bool^greater_equals_double_int64, + _>=_( + 1~double, + 1u~uint + )~bool^greater_equals_double_uint64, + _>=_( + 1~int, + 1u~uint + )~bool^greater_equals_int64_uint64, + _>=_( + 1u~uint, + 1~int + )~bool^greater_equals_uint64_int64 + )~bool^logical_and`, + }, { in: `[1].map(x, [x, x]).map(x, [x, x])`, outType: listType({ @@ -2172,149 +2177,196 @@ _==_( // )~bool^equals`, // }, // TODO: Optionals + { + in: `a.?b`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('a', { + type: mapType({ + keyType: STRING_TYPE, + valueType: STRING_TYPE, + }), + }), + ], + }), + parserOptions: { enableOptionalSyntax: true }, + outType: optionalType(STRING_TYPE), + out: `_?._( + a~map(string, string)^a, + "b" + )~optional_type(string)^select_optional_field`, + }, + { + in: `type(a.?b) == optional_type`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('optional_type', { type: OPTIONAL_TYPE }), + identDecl('a', { + type: mapType({ + keyType: STRING_TYPE, + valueType: STRING_TYPE, + }), + }), + ], + }), + parserOptions: { enableOptionalSyntax: true }, + outType: BOOL_TYPE, + out: `_==_( + type( + _?._( + a~map(string, string)^a, + "b" + )~optional_type(string)^select_optional_field + )~type(optional_type(string))^type, + optional_type~type(optional_type)^optional_type + )~bool^equals`, + }, + { + in: `a.b`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('a', { + type: optionalType( + mapType({ + keyType: STRING_TYPE, + valueType: STRING_TYPE, + }) + ), + }), + ], + }), + outType: optionalType(STRING_TYPE), + out: `a~optional_type(map(string, string))^a.b~optional_type(string)`, + }, + { + in: `a.dynamic`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('a', { + type: optionalType(DYN_TYPE), + }), + ], + }), + outType: optionalType(DYN_TYPE), + out: `a~optional_type(dyn)^a.dynamic~optional_type(dyn)`, + }, + { + in: `has(a.dynamic)`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('a', { + type: optionalType(DYN_TYPE), + }), + ], + }), + outType: BOOL_TYPE, + out: `a~optional_type(dyn)^a.dynamic~test-only~~bool`, + }, + { + in: `has(a.?b.c)`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('a', { + type: optionalType( + mapType({ + keyType: STRING_TYPE, + valueType: DYN_TYPE, + }) + ), + }), + ], + }), + parserOptions: { enableOptionalSyntax: true }, + outType: BOOL_TYPE, + out: `_?._( + a~optional_type(map(string, dyn))^a, + "b" + )~optional_type(dyn)^select_optional_field.c~test-only~~bool`, + }, + { + in: `{?'key': {'a': 'b'}.?value}`, + parserOptions: { enableOptionalSyntax: true }, + outType: mapType({ + keyType: STRING_TYPE, + // TODO: the go test has this as just a string type, but it seems like it should be optional. And the test passes with this change + valueType: optionalType(STRING_TYPE), + }), + out: `{ + ?"key"~string:_?._( + { + "a"~string:"b"~string + }~map(string, string), + "value" + )~optional_type(string)^select_optional_field + }~map(string, string)`, + }, + { + in: `{?'key': {'a': 'b'}.?value}.key`, + parserOptions: { enableOptionalSyntax: true }, + // TODO: the go test has this as just a string type, but it seems like it should be optional. And the test passes with this change + outType: optionalType(STRING_TYPE), + out: `{ + ?"key"~string:_?._( + { + "a"~string:"b"~string + }~map(string, string), + "value" + )~optional_type(string)^select_optional_field + }~map(string, string).key~string`, + }, + { + in: `{?'nested': a.b}`, + parserOptions: { enableOptionalSyntax: true }, + env: getDefaultEnv().extend({ + idents: [ + identDecl('a', { + type: optionalType( + mapType({ + keyType: STRING_TYPE, + valueType: STRING_TYPE, + }) + ), + }), + ], + }), + outType: mapType({ + keyType: STRING_TYPE, + // TODO: the go test has this as just a string type, but it seems like it should be optional. And the test passes with this change + valueType: optionalType(STRING_TYPE), + }), + out: `{ + ?"nested"~string:a~optional_type(map(string, string))^a.b~optional_type(string) + }~map(string, string)`, + }, + // TODO: does this test make sense? // { - // in: `a.?b`, + // in: `{?'key': 'hi'}`, + // parserOptions: { enableOptionalSyntax: true }, + // err: `ERROR: :1:10: expected type 'optional_type(string)' but found 'string' + // | {?'key': 'hi'} + // | .........^`, + // }, + // TODO: this outputs a DYN list + // { + // in: `[?a, ?b, 'world']`, + // parserOptions: { enableOptionalSyntax: true }, // env: getDefaultEnv().extend({ // idents: [ // identDecl('a', { - // type: mapType({ - // keyType: STRING_TYPE, - // valueType: optionalType(STRING_TYPE), - // }), + // type: optionalType(STRING_TYPE), + // }), + // identDecl('b', { + // type: optionalType(STRING_TYPE), // }), // ], // }), - // outType: optionalType(STRING_TYPE), - // out: `_?._( - // a~map(string, string)^a, - // "b" - // )~optional_type(string)^select_optional_field`, - // }, - // { - // in: `type(a.?b) == optional_type`, - // env: testEnv{ - // optionalSyntax: true, - // idents: []*decls.VariableDecl{ - // decls.NewVariable("a", types.NewMapType(types.StringType, types.StringType)), - // }, - // }, - // outType: types.BoolType, - // out: `_==_( - // type( - // _?._( - // a~map(string, string)^a, - // "b" - // )~optional_type(string)^select_optional_field - // )~type(optional_type(string))^type, - // optional_type~type(optional_type)^optional_type - // )~bool^equals`, - // }, - // { - // in: `a.b`, - // env: testEnv{ - // idents: []*decls.VariableDecl{ - // decls.NewVariable("a", types.NewOptionalType(types.NewMapType(types.StringType, types.StringType))), - // }, - // }, - // outType: types.NewOptionalType(types.StringType), - // out: `a~optional_type(map(string, string))^a.b~optional_type(string)`, - // }, - // { - // in: `a.dynamic`, - // env: testEnv{ - // idents: []*decls.VariableDecl{ - // decls.NewVariable("a", types.NewOptionalType(types.DynType)), - // }, - // }, - // outType: types.NewOptionalType(types.DynType), - // out: `a~optional_type(dyn)^a.dynamic~optional_type(dyn)`, - // }, - // { - // in: `has(a.dynamic)`, - // env: testEnv{ - // idents: []*decls.VariableDecl{ - // decls.NewVariable("a", types.NewOptionalType(types.DynType)), - // }, - // }, - // outType: types.BoolType, - // out: `a~optional_type(dyn)^a.dynamic~test-only~~bool`, - // }, - // { - // in: `has(a.?b.c)`, - // env: testEnv{ - // optionalSyntax: true, - // idents: []*decls.VariableDecl{ - // decls.NewVariable("a", types.NewOptionalType(types.NewMapType(types.StringType, types.DynType))), - // }, - // }, - // outType: types.BoolType, - // out: `_?._( - // a~optional_type(map(string, dyn))^a, - // "b" - // )~optional_type(dyn)^select_optional_field.c~test-only~~bool`, - // }, - // { - // in: `{?'key': {'a': 'b'}.?value}`, - // env: testEnv{optionalSyntax: true}, - // outType: types.NewMapType(types.StringType, types.StringType), - // out: `{ - // ?"key"~string:_?._( - // { - // "a"~string:"b"~string - // }~map(string, string), - // "value" - // )~optional_type(string)^select_optional_field - // }~map(string, string)`, - // }, - // { - // in: `{?'key': {'a': 'b'}.?value}.key`, - // env: testEnv{optionalSyntax: true}, - // outType: types.StringType, - // out: `{ - // ?"key"~string:_?._( - // { - // "a"~string:"b"~string - // }~map(string, string), - // "value" - // )~optional_type(string)^select_optional_field - // }~map(string, string).key~string`, - // }, - // { - // in: `{?'nested': a.b}`, - // env: testEnv{ - // optionalSyntax: true, - // idents: []*decls.VariableDecl{ - // decls.NewVariable("a", types.NewOptionalType(types.NewMapType(types.StringType, types.StringType))), - // }, - // }, - // outType: types.NewMapType(types.StringType, types.StringType), - // out: `{ - // ?"nested"~string:a~optional_type(map(string, string))^a.b~optional_type(string) - // }~map(string, string)`, - // }, - // { - // in: `{?'key': 'hi'}`, - // env: testEnv{optionalSyntax: true}, - // err: `ERROR: :1:10: expected type 'optional_type(string)' but found 'string' - // | {?'key': 'hi'} - // | .........^`, - // }, - // { - // in: `[?a, ?b, 'world']`, - // env: testEnv{ - // optionalSyntax: true, - // idents: []*decls.VariableDecl{ - // decls.NewVariable("a", types.NewOptionalType(types.StringType)), - // decls.NewVariable("b", types.NewOptionalType(types.StringType)), - // }, - // }, - // outType: types.NewListType(types.StringType), + // outType: listType({ elemType: STRING_TYPE }), // out: `[ - // a~optional_type(string)^a, - // b~optional_type(string)^b, - // "world"~string - // ]~list(string)`, - // }, + // a~optional_type(string)^a, + // b~optional_type(string)^b, + // "world"~string + // ]~list(string)`, + // }, // { // in: `[?'value']`, // env: testEnv{optionalSyntax: true}, @@ -2322,28 +2374,28 @@ _==_( // | [?'value'] // | ..^`, // }, - // { - // in: `TestAllTypes{?single_int32: {}.?i}`, - // container: "google.expr.proto2.test", - // env: testEnv{optionalSyntax: true}, - // out: `google.expr.proto2.test.TestAllTypes{ - // ?single_int32:_?._( - // {}~map(dyn, int), - // "i" - // )~optional_type(int)^select_optional_field - // }~google.expr.proto2.test.TestAllTypes^google.expr.proto2.test.TestAllTypes`, - // outType: types.NewObjectType( - // "google.expr.proto2.test.TestAllTypes", - // ), - // }, - // { - // in: `TestAllTypes{?single_int32: 1}`, - // container: "google.expr.proto2.test", - // env: testEnv{optionalSyntax: true}, + // TODO: this outputs an error + // { + // in: `TestAllTypes{?single_int32: {}.?i}`, + // container: 'google.api.expr.test.v1.proto2', + // parserOptions: { enableOptionalSyntax: true }, + // out: `google.api.expr.test.v1.proto2.TestAllTypes{ + // ?single_int32:_?._( + // {}~map(dyn, int), + // "i" + // )~optional_type(int)^select_optional_field + // }~google.api.expr.test.v1.proto2.TestAllTypes^google.api.expr.test.v1.proto2.TestAllTypes`, + // outType: messageType('google.api.expr.test.v1.proto2.TestAllTypes'), + // }, + // TODO: this does not put out an error + // { + // in: `TestAllTypes{?single_int32: 1}`, + // container: 'google.api.expr.test.v1.proto2', + // parserOptions: { enableOptionalSyntax: true }, // err: `ERROR: :1:29: expected type 'optional_type(int)' but found 'int' - // | TestAllTypes{?single_int32: 1} - // | ............................^`, - // }, + // | TestAllTypes{?single_int32: 1} + // | ............................^`, + // }, { in: `undef`, err: `ERROR: :1:1: undeclared reference to 'undef' (in container '') @@ -2356,28 +2408,30 @@ _==_( | undef() | .....^`, }, + { + in: `null_int == null || null == null_int || null_msg == null || null == null_msg`, + env: getDefaultEnv().extend({ + idents: [ + identDecl('null_int', { type: nullableType(INT64_TYPE) }), + identDecl('null_msg', { + type: nullableType( + messageType('google.api.expr.test.v1.proto2.TestAllTypes') + ), + }), + ], + }), + outType: BOOL_TYPE, + }, // TODO: nullables - // { - // in: `null_int == null || null == null_int || null_msg == null || null == null_msg`, - // env: testEnv{ - // idents: []*decls.VariableDecl{ - // decls.NewVariable("null_int", types.NewNullableType(types.IntType)), - // decls.NewVariable("null_msg", types.NewObjectType("google.expr.proto2.test.TestAllTypes")), - // }, - // }, - // outType: types.BoolType, - // }, - // { + // { // in: `NotAMessage{}`, - // env: testEnv{ - // idents: []*decls.VariableDecl{ - // decls.NewVariable("NotAMessage", types.NewNullableType(types.IntType)), - // }, - // }, + // env: getDefaultEnv().extend({ + // idents: [identDecl('NotAMessage', { type: nullableType(INT64_TYPE) })], + // }), // err: `ERROR: :1:12: 'wrapper(int)' is not a type - // | NotAMessage{} - // | ...........^`, - // }, + // | NotAMessage{} + // | ...........^`, + // }, { in: `{}.map(c,[c,type(c)])`, out: `__comprehension__( @@ -2416,22 +2470,18 @@ describe('CELChecker', () => { it(`should check ${testCase.in}`, () => { const container = new CELContainer(testCase.container ?? ''); const env = testCase.env ?? getDefaultEnv().extend({ container }); - const parser = new CELParser(testCase.in); + const parser = new CELParser(testCase.in, testCase.parserOptions); const parsed = parser.parse(); - if (testCase.in === `a.?b`) { - console.log('hey buddy'); - console.dir(parsed.expr, { depth: null }); - } if (isNil(parsed.expr)) { throw new Error('parsed.expr is nil'); } const checker = new CELChecker(parsed, testCase.in, env); const result = checker.check(); if (testCase.outType) { + const got = result.typeMap[parsed.expr.id.toString()]; + const expected = testCase.outType; try { - expect(result.typeMap[parsed.expr.id.toString()]).toEqual( - testCase.outType - ); + expect(got).toEqual(expected); if ( testCase.outType !== ERROR_TYPE && !testCase.err && @@ -2443,6 +2493,7 @@ describe('CELChecker', () => { } } catch (e) { console.log(checker.errors.toDisplayString()); + console.dir({ expected, got }, { depth: null }); throw e; } } diff --git a/packages/cel/src/lib/checker.ts b/packages/cel/src/lib/checker.ts index c70ab60..04a02e6 100644 --- a/packages/cel/src/lib/checker.ts +++ b/packages/cel/src/lib/checker.ts @@ -23,6 +23,7 @@ import { import { create } from '@bufbuild/protobuf'; import { CELEnvironment } from './environment'; import { Errors } from './errors'; +import { OPT_SELECT_OPERATOR } from './operators'; import { BOOL_TYPE, BYTES_TYPE, @@ -43,9 +44,12 @@ import { isDyn, isDynOrError, isExactType, + isOptionalType, listType, mapType, + maybeUnwrapOptionalType, mostGeneral, + optionalType, substitute, typeParamType, unwrapIdentDeclType, @@ -232,69 +236,12 @@ export class CELChecker { } } - // Interpret as field selection, first traversing down the operand. - const checkedOperand = this.checkExpr(sel.operand); - const targetType = this.getType(checkedOperand!.id)!; - // Assume error type by default as most types do not support field - // selection. - let resultType: Type = ERROR_TYPE; - switch (targetType.typeKind.case) { - case 'mapType': - // Maps yield their value type as the selection result type. - resultType = targetType.typeKind.value.valueType!; - break; - case 'messageType': - // Objects yield their field type declaration as the selection result type, but only if - // the field is defined. - const fieldType = this.env.lookupFieldType( - targetType.typeKind.value, - sel.field - ); - if (!isNil(fieldType)) { - resultType = fieldType; - } else { - const msg = this.env.lookupStructType(targetType.typeKind.value); - if (isNil(msg)) { - this.#errors.reportUnexpectedFailedResolution( - expr.id, - this.getLocationById(expr.id), - targetType.typeKind.value - ); - } else { - this.#errors.reportUndefinedField( - expr.id, - this.getLocationById(expr.id), - sel.field - ); - } - } - break; - case 'wellKnown': - resultType = wellKnownType(targetType.typeKind.value); - break; - case 'typeParam': - // Set the operand type to DYN to prevent assignment to a potentionally - // incorrect type at a later point in type-checking. The isAssignable - // call will update the type substitutions for the type param under the - // covers. - this._isAssignable(DYN_TYPE, targetType); - // Also, set the result type to DYN. - resultType = DYN_TYPE; - break; - default: - // Dynamic / error values are treated as DYN type. Errors are handled this way as well - // in order to allow forward progress on the check. - if (isDynOrError(targetType)) { - resultType = DYN_TYPE; - } else { - this.#errors.reportTypeDoesNotSupportFieldSelection( - expr.id, - this.getLocationById(expr.id), - targetType - ); - } - break; - } + let resultType = this.checkSelectField( + expr, + sel.operand!, + sel.field, + false + ); if (sel.testOnly) { resultType = BOOL_TYPE; } @@ -307,8 +254,11 @@ export class CELChecker { // making changes here please consider the impact on planner.go and // consolidate implementations or mirror code as appropriate. const call = expr.exprKind.value as Expr_Call; - const args = call.args; const fnName = call.function; + if (fnName === OPT_SELECT_OPERATOR) { + return this.checkOptSelect(expr); + } + const args = call.args; // Traverse arguments. for (const arg of args) { @@ -680,6 +630,119 @@ export class CELChecker { return expr; } + checkOptSelect(expr: Expr) { + // Collect metadata related to the opt select call packaged by the parser. + const call = expr.exprKind.value as Expr_Call; + const operand = call.args[0]; + const field = call.args[1]; + if ( + field.exprKind.case !== 'constExpr' || + (field.exprKind.case === 'constExpr' && + field.exprKind.value.constantKind.case !== 'stringValue') + ) { + this.#errors.reportNotAnOptionalFieldSelection( + field.id, + this.getLocationById(field.id), + field.exprKind.case! + ); + return expr; + } + + const resultType = this.checkSelectField( + expr, + operand, + field.exprKind.value.constantKind.value as string, + true + ); + this.setType(expr.id, substitute(this.#mapping, resultType, false)); + this.setReference(expr.id, functionReference(['select_optional_field'])); + return expr; + } + + checkSelectField( + expr: Expr, + operand: Expr, + field: string, + optional: boolean + ) { + // Interpret as field selection, first traversing down the operand. + const checkedOperand = this.checkExpr(operand)!; + const operandType = substitute( + this.#mapping, + this.getType(checkedOperand.id)!, + false + ); + + // If the target type is 'optional', unwrap it for the sake of this check. + const targetType = maybeUnwrapOptionalType(operandType)!; + + // Assume error type by default as most types do not support field + // selection. + let resultType = ERROR_TYPE; + switch (targetType.typeKind.case) { + case 'mapType': + // Maps yield their value type as the selection result type. + resultType = targetType.typeKind.value.valueType!; + break; + case 'messageType': + // Objects yield their field type declaration as the selection result type, but only if + // the field is defined. + const fieldType = this.env.lookupFieldType( + targetType.typeKind.value, + field + ); + if (!isNil(fieldType)) { + resultType = fieldType; + } else { + const msg = this.env.lookupStructType(targetType.typeKind.value); + if (isNil(msg)) { + this.#errors.reportUnexpectedFailedResolution( + expr.id, + this.getLocationById(expr.id), + targetType.typeKind.value + ); + } else { + this.#errors.reportUndefinedField( + expr.id, + this.getLocationById(expr.id), + field + ); + } + } + break; + case 'wellKnown': + resultType = wellKnownType(targetType.typeKind.value); + break; + case 'typeParam': + // Set the operand type to DYN to prevent assignment to a potentially + // incorrect type at a later point in type-checking. The isAssignable + // call will update the type substitutions for the type param under the + // covers. + this._isAssignable(DYN_TYPE, targetType); + // Also, set the result type to DYN. + resultType = DYN_TYPE; + break; + default: + // Dynamic / error values are treated as DYN type. Errors are handled + // this way as well in order to allow forward progress on the check. + if (!isDynOrError(targetType)) { + this.#errors.reportTypeDoesNotSupportFieldSelection( + expr.id, + this.getLocationById(expr.id), + targetType + ); + } + resultType = DYN_TYPE; + break; + } + // If the target type was optional coming in, then the result must be + // optional going out. + if (isOptionalType(operandType) || optional) { + return optionalType(resultType); + } + return resultType; + } + setType(id: bigint, type: Type) { this.#typeMap.set(id.toString(), type); } diff --git a/packages/cel/src/lib/errors.ts b/packages/cel/src/lib/errors.ts index d047d2a..19cbac3 100644 --- a/packages/cel/src/lib/errors.ts +++ b/packages/cel/src/lib/errors.ts @@ -117,6 +117,18 @@ export class Errors { return this.reportErrorAtId(id, location, `undefined field '${field}'`); } + public reportNotAnOptionalFieldSelection( + id: bigint, + location: Location, + field: string + ) { + return this.reportErrorAtId( + id, + location, + `unsupported optional field selection: ${field}` + ); + } + public reportNoMatchingOverload( id: bigint, location: Location, diff --git a/packages/cel/src/lib/parser.spec.ts b/packages/cel/src/lib/parser.spec.ts index 215cb90..53dee31 100644 --- a/packages/cel/src/lib/parser.spec.ts +++ b/packages/cel/src/lib/parser.spec.ts @@ -2486,7 +2486,7 @@ const testCases: TestInfo[] = [ | .^ ERROR: :1:10: unsupported syntax '[?' | a.?b && a[?b] - | .........^`, + | .........^`, }, { I: `a.?b[?0] && a[?c]`, diff --git a/packages/cel/src/lib/types.ts b/packages/cel/src/lib/types.ts index dc14159..d9b1989 100644 --- a/packages/cel/src/lib/types.ts +++ b/packages/cel/src/lib/types.ts @@ -263,9 +263,14 @@ export function maybeUnwrapOptionalType(val: Type | null | undefined) { if (isNil(val)) { return null; } + if (!isOptionalType(val)) { + return val; + } return unwrapOptionalType(val); } +export const OPTIONAL_TYPE = abstractType({ name: 'optional_type' }); + export function wrappedType(value: Type_PrimitiveType) { return create(TypeSchema, { typeKind: { From 1170e9462ad2ac319742bac79da90c368a37863b Mon Sep 17 00:00:00 2001 From: jafaircl Date: Tue, 22 Oct 2024 18:01:01 -0400 Subject: [PATCH 25/34] feat(cel): rearragne to be closer to other implementations --- packages/cel/src/lib/cel.ts | 6 +- .../cel/src/lib/{ => checker}/checker.spec.ts | 46 ++- packages/cel/src/lib/{ => checker}/checker.ts | 72 ++-- .../cel/src/lib/{ => checker}/types.spec.ts | 45 ++- packages/cel/src/lib/{ => checker}/types.ts | 338 +----------------- packages/cel/src/lib/common/ast.ts | 59 +++ .../src/lib/{ => common}/constants.spec.ts | 2 +- .../cel/src/lib/{ => common}/constants.ts | 2 +- .../container.spec.ts} | 0 .../cel/src/lib/{ => common}/container.ts | 0 .../cel/src/lib/common/decls/function-decl.ts | 47 +++ .../cel/src/lib/common/decls/ident-decl.ts | 42 +++ packages/cel/src/lib/{ => common}/errors.ts | 3 +- packages/cel/src/lib/{ => common}/standard.ts | 40 +-- packages/cel/src/lib/common/types/abstract.ts | 33 ++ packages/cel/src/lib/common/types/bool.ts | 14 + packages/cel/src/lib/common/types/bytes.ts | 14 + packages/cel/src/lib/common/types/double.ts | 23 ++ packages/cel/src/lib/common/types/dyn.ts | 26 ++ packages/cel/src/lib/common/types/error.ts | 26 ++ packages/cel/src/lib/common/types/function.ts | 33 ++ packages/cel/src/lib/common/types/int.ts | 23 ++ packages/cel/src/lib/common/types/list.ts | 31 ++ packages/cel/src/lib/common/types/map.ts | 38 ++ packages/cel/src/lib/common/types/message.ts | 27 ++ packages/cel/src/lib/common/types/null.ts | 26 ++ packages/cel/src/lib/common/types/nullable.ts | 28 ++ packages/cel/src/lib/common/types/optional.ts | 31 ++ .../cel/src/lib/common/types/primitive.ts | 30 ++ packages/cel/src/lib/common/types/string.ts | 23 ++ .../cel/src/lib/common/types/type-param.ts | 27 ++ packages/cel/src/lib/common/types/type.ts | 27 ++ packages/cel/src/lib/common/types/uint.ts | 23 ++ .../cel/src/lib/common/types/utils.spec.ts | 89 +++++ packages/cel/src/lib/common/types/utils.ts | 148 ++++++++ packages/cel/src/lib/common/types/wkt.ts | 108 ++++++ packages/cel/src/lib/common/types/wrapper.ts | 28 ++ .../cel/src/lib/{ => common}/utils.spec.ts | 71 +--- packages/cel/src/lib/{ => common}/utils.ts | 234 +----------- packages/cel/src/lib/environment.ts | 21 +- packages/cel/src/lib/logic-manager.ts | 2 +- packages/cel/src/lib/{ => parser}/macros.ts | 26 +- .../lib/{ => parser}/parser-helper.spec.ts | 0 .../cel/src/lib/{ => parser}/parser-helper.ts | 8 +- .../cel/src/lib/{ => parser}/parser.spec.ts | 40 +-- packages/cel/src/lib/{ => parser}/parser.ts | 50 +-- 46 files changed, 1227 insertions(+), 803 deletions(-) rename packages/cel/src/lib/{ => checker}/checker.spec.ts (98%) rename packages/cel/src/lib/{ => checker}/checker.ts (94%) rename packages/cel/src/lib/{ => checker}/types.spec.ts (91%) rename packages/cel/src/lib/{ => checker}/types.ts (75%) create mode 100644 packages/cel/src/lib/common/ast.ts rename packages/cel/src/lib/{ => common}/constants.spec.ts (99%) rename packages/cel/src/lib/{ => common}/constants.ts (99%) rename packages/cel/src/lib/{container.test.ts => common/container.spec.ts} (100%) rename packages/cel/src/lib/{ => common}/container.ts (100%) create mode 100644 packages/cel/src/lib/common/decls/function-decl.ts create mode 100644 packages/cel/src/lib/common/decls/ident-decl.ts rename packages/cel/src/lib/{ => common}/errors.ts (98%) rename packages/cel/src/lib/{ => common}/standard.ts (97%) create mode 100644 packages/cel/src/lib/common/types/abstract.ts create mode 100644 packages/cel/src/lib/common/types/bool.ts create mode 100644 packages/cel/src/lib/common/types/bytes.ts create mode 100644 packages/cel/src/lib/common/types/double.ts create mode 100644 packages/cel/src/lib/common/types/dyn.ts create mode 100644 packages/cel/src/lib/common/types/error.ts create mode 100644 packages/cel/src/lib/common/types/function.ts create mode 100644 packages/cel/src/lib/common/types/int.ts create mode 100644 packages/cel/src/lib/common/types/list.ts create mode 100644 packages/cel/src/lib/common/types/map.ts create mode 100644 packages/cel/src/lib/common/types/message.ts create mode 100644 packages/cel/src/lib/common/types/null.ts create mode 100644 packages/cel/src/lib/common/types/nullable.ts create mode 100644 packages/cel/src/lib/common/types/optional.ts create mode 100644 packages/cel/src/lib/common/types/primitive.ts create mode 100644 packages/cel/src/lib/common/types/string.ts create mode 100644 packages/cel/src/lib/common/types/type-param.ts create mode 100644 packages/cel/src/lib/common/types/type.ts create mode 100644 packages/cel/src/lib/common/types/uint.ts create mode 100644 packages/cel/src/lib/common/types/utils.spec.ts create mode 100644 packages/cel/src/lib/common/types/utils.ts create mode 100644 packages/cel/src/lib/common/types/wkt.ts create mode 100644 packages/cel/src/lib/common/types/wrapper.ts rename packages/cel/src/lib/{ => common}/utils.spec.ts (91%) rename packages/cel/src/lib/{ => common}/utils.ts (61%) rename packages/cel/src/lib/{ => parser}/macros.ts (98%) rename packages/cel/src/lib/{ => parser}/parser-helper.spec.ts (100%) rename packages/cel/src/lib/{ => parser}/parser-helper.ts (95%) rename packages/cel/src/lib/{ => parser}/parser.spec.ts (99%) rename packages/cel/src/lib/{ => parser}/parser.ts (98%) diff --git a/packages/cel/src/lib/cel.ts b/packages/cel/src/lib/cel.ts index 150fff0..3faed74 100644 --- a/packages/cel/src/lib/cel.ts +++ b/packages/cel/src/lib/cel.ts @@ -1,7 +1,7 @@ export { CELEnvironment, STANDARD_ENV } from './environment'; export { CELProgram } from './program'; // export { CELInterpreter } from './interpreter'; -export { CELChecker } from './checker'; -export { CELContainer } from './container'; -export { CELParser } from './parser'; +export { CELChecker } from './checker/checker'; +export { CELContainer } from './common/container'; +export { CELParser } from './parser/parser'; export { exprValueToNative } from './to-native'; diff --git a/packages/cel/src/lib/checker.spec.ts b/packages/cel/src/lib/checker/checker.spec.ts similarity index 98% rename from packages/cel/src/lib/checker.spec.ts rename to packages/cel/src/lib/checker/checker.spec.ts index 1d560a4..9f90def 100644 --- a/packages/cel/src/lib/checker.spec.ts +++ b/packages/cel/src/lib/checker/checker.spec.ts @@ -11,30 +11,28 @@ import { } from '@buf/cel_spec.bufbuild_es/proto/test/v1/proto3/test_all_types_pb.js'; import { Type } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; import { createMutableRegistry } from '@bufbuild/protobuf'; +import { CELContainer } from '../common/container'; +import { functionDecl, overloadDecl } from '../common/decls/function-decl'; +import { identDecl } from '../common/decls/ident-decl'; +import { abstractType } from '../common/types/abstract'; +import { BOOL_TYPE } from '../common/types/bool'; +import { BYTES_TYPE } from '../common/types/bytes'; +import { DOUBLE_TYPE } from '../common/types/double'; +import { DYN_TYPE } from '../common/types/dyn'; +import { ERROR_TYPE } from '../common/types/error'; +import { INT64_TYPE } from '../common/types/int'; +import { listType } from '../common/types/list'; +import { mapType } from '../common/types/map'; +import { messageType } from '../common/types/message'; +import { NULL_TYPE } from '../common/types/null'; +import { nullableType } from '../common/types/nullable'; +import { ABSTRACT_OPTIONAL_TYPE, optionalType } from '../common/types/optional'; +import { STRING_TYPE } from '../common/types/string'; +import { typeParamType } from '../common/types/type-param'; +import { UINT64_TYPE } from '../common/types/uint'; +import { CELEnvironment, STANDARD_ENV } from '../environment'; +import { CELParser, CELParserOptions } from '../parser/parser'; import { CELChecker } from './checker'; -import { CELContainer } from './container'; -import { CELEnvironment, STANDARD_ENV } from './environment'; -import { CELParser, CELParserOptions } from './parser'; -import { - BOOL_TYPE, - BYTES_TYPE, - DOUBLE_TYPE, - DYN_TYPE, - ERROR_TYPE, - INT64_TYPE, - NULL_TYPE, - OPTIONAL_TYPE, - STRING_TYPE, - UINT64_TYPE, - abstractType, - listType, - mapType, - messageType, - nullableType, - optionalType, - typeParamType, -} from './types'; -import { functionDecl, identDecl, overloadDecl } from './utils'; interface TestInfo { // in contains the expression to be parsed. @@ -2200,7 +2198,7 @@ _==_( in: `type(a.?b) == optional_type`, env: getDefaultEnv().extend({ idents: [ - identDecl('optional_type', { type: OPTIONAL_TYPE }), + identDecl('optional_type', { type: ABSTRACT_OPTIONAL_TYPE }), identDecl('a', { type: mapType({ keyType: STRING_TYPE, diff --git a/packages/cel/src/lib/checker.ts b/packages/cel/src/lib/checker/checker.ts similarity index 94% rename from packages/cel/src/lib/checker.ts rename to packages/cel/src/lib/checker/checker.ts index 04a02e6..976db8f 100644 --- a/packages/cel/src/lib/checker.ts +++ b/packages/cel/src/lib/checker/checker.ts @@ -21,48 +21,50 @@ import { ParsedExpr, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; import { create } from '@bufbuild/protobuf'; -import { CELEnvironment } from './environment'; -import { Errors } from './errors'; -import { OPT_SELECT_OPERATOR } from './operators'; +import { getLocationByOffset } from '../common/ast'; +import { functionReference } from '../common/decls/function-decl'; +import { + identDecl, + identReference, + unwrapIdentDecl, +} from '../common/decls/ident-decl'; +import { Errors } from '../common/errors'; +import { BOOL_TYPE } from '../common/types/bool'; +import { BYTES_TYPE } from '../common/types/bytes'; +import { DOUBLE_TYPE } from '../common/types/double'; +import { DYN_TYPE, isDynType } from '../common/types/dyn'; +import { ERROR_TYPE } from '../common/types/error'; +import { functionType } from '../common/types/function'; +import { INT64_TYPE } from '../common/types/int'; +import { listType } from '../common/types/list'; +import { mapType } from '../common/types/map'; +import { NULL_TYPE } from '../common/types/null'; +import { + isOptionalType, + maybeUnwrapOptionalType, + optionalType, +} from '../common/types/optional'; +import { STRING_TYPE } from '../common/types/string'; +import { typeParamType } from '../common/types/type-param'; +import { UINT64_TYPE } from '../common/types/uint'; +import { isDynTypeOrErrorType } from '../common/types/utils'; import { - BOOL_TYPE, - BYTES_TYPE, - DOUBLE_TYPE, DURATION_TYPE, - DYN_TYPE, - ERROR_TYPE, - INT64_TYPE, - NULL_TYPE, - STRING_TYPE, TIMESTAMP_TYPE, - UINT64_TYPE, - formatCELType, - functionType, getCheckedWellKnownType, + wellKnownType, +} from '../common/types/wkt'; +import { mapToObject, toQualifiedName } from '../common/utils'; +import { CELEnvironment } from '../environment'; +import { OPT_SELECT_OPERATOR } from '../operators'; +import { + formatCELType, isAssignable, isAssignableList, - isDyn, - isDynOrError, isExactType, - isOptionalType, - listType, - mapType, - maybeUnwrapOptionalType, mostGeneral, - optionalType, substitute, - typeParamType, - unwrapIdentDeclType, - wellKnownType, } from './types'; -import { - functionReference, - getLocationByOffset, - identDecl, - identReference, - mapToObject, - toQualifiedName, -} from './utils'; export interface OverloadResolution { resultType?: Type; @@ -200,7 +202,7 @@ export class CELChecker { const identExpr = expr.exprKind.value as Expr_Ident; const ident = this.env.lookupIdent(identExpr.name); if (!isNil(ident)) { - const unwrapped = unwrapIdentDeclType(ident)!; + const unwrapped = unwrapIdentDecl(ident)!; this.setType(expr.id, unwrapped.type!); this.setReference(expr.id, identReference(ident.name, unwrapped.value!)); // Overwrite the identifier with its fully qualified name. @@ -415,7 +417,7 @@ export class CELChecker { if (isNil(resultType)) { resultType = fnResultType; } else if ( - !isDyn(resultType) && + !isDynType(resultType) && !isExactType(fnResultType, resultType) ) { resultType = DYN_TYPE; @@ -725,7 +727,7 @@ export class CELChecker { default: // Dynamic / error values are treated as DYN type. Errors are handled // this way as well in order to allow forward progress on the check. - if (!isDynOrError(targetType)) { + if (!isDynTypeOrErrorType(targetType)) { this.#errors.reportTypeDoesNotSupportFieldSelection( expr.id, this.getLocationById(expr.id), diff --git a/packages/cel/src/lib/types.spec.ts b/packages/cel/src/lib/checker/types.spec.ts similarity index 91% rename from packages/cel/src/lib/types.spec.ts rename to packages/cel/src/lib/checker/types.spec.ts index 244e50b..68c2011 100644 --- a/packages/cel/src/lib/types.spec.ts +++ b/packages/cel/src/lib/checker/types.spec.ts @@ -5,27 +5,22 @@ import { } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; import { create } from '@bufbuild/protobuf'; import { EmptySchema, NullValue } from '@bufbuild/protobuf/wkt'; -import { - DYN_TYPE, - ERROR_TYPE, - NULL_TYPE, - abstractType, - formatCELType, - functionType, - isAssignableType, - isExactType, - listType, - mapType, - messageType, - nullableType, - optionalType, - primitiveType, - typeParamType, - typeType, - wellKnownType, - wrappedType, - wrapperType, -} from './types'; +import { abstractType } from '../common/types/abstract'; +import { DYN_TYPE } from '../common/types/dyn'; +import { ERROR_TYPE } from '../common/types/error'; +import { functionType } from '../common/types/function'; +import { listType } from '../common/types/list'; +import { mapType } from '../common/types/map'; +import { messageType } from '../common/types/message'; +import { NULL_TYPE } from '../common/types/null'; +import { nullableType } from '../common/types/nullable'; +import { optionalType } from '../common/types/optional'; +import { primitiveType } from '../common/types/primitive'; +import { typeType } from '../common/types/type'; +import { typeParamType } from '../common/types/type-param'; +import { wellKnownType } from '../common/types/wkt'; +import { wrapperType } from '../common/types/wrapper'; +import { formatCELType, isAssignableType, isExactType } from './types'; describe('types', () => { it('DYN_TYPE', () => { @@ -311,13 +306,13 @@ describe('types', () => { isExact: false, }, { - t1: wrappedType(Type_PrimitiveType.STRING), - t2: wrappedType(Type_PrimitiveType.STRING), + t1: wrapperType(Type_PrimitiveType.STRING), + t2: wrapperType(Type_PrimitiveType.STRING), isExact: true, }, { - t1: wrappedType(Type_PrimitiveType.STRING), - t2: wrappedType(Type_PrimitiveType.INT64), + t1: wrapperType(Type_PrimitiveType.STRING), + t2: wrapperType(Type_PrimitiveType.INT64), isExact: false, }, ]; diff --git a/packages/cel/src/lib/types.ts b/packages/cel/src/lib/checker/types.ts similarity index 75% rename from packages/cel/src/lib/types.ts rename to packages/cel/src/lib/checker/types.ts index d9b1989..4d86aa0 100644 --- a/packages/cel/src/lib/types.ts +++ b/packages/cel/src/lib/checker/types.ts @@ -3,331 +3,29 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import { isNil } from '@bearclaw/is'; import { - Decl, Type, - TypeSchema, Type_AbstractType, - Type_AbstractTypeSchema, Type_FunctionType, - Type_FunctionTypeSchema, Type_ListType, - Type_ListTypeSchema, Type_MapType, - Type_MapTypeSchema, Type_PrimitiveType, Type_PrimitiveTypeSchema, Type_WellKnownType, Type_WellKnownTypeSchema, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; -import { MessageInitShape, create, enumToJson } from '@bufbuild/protobuf'; -import { EmptySchema, NullValue } from '@bufbuild/protobuf/wkt'; - -export interface Location { - line: number; - column: number; -} - -export interface OffsetRange { - start: number; - stop: number; -} - -export const DYN_TYPE = create(TypeSchema, { - typeKind: { - case: 'dyn', - value: create(EmptySchema), - }, -}); - -export const NULL_TYPE = create(TypeSchema, { - typeKind: { - case: 'null', - value: NullValue.NULL_VALUE, - }, -}); - -export function primitiveType(value: Type_PrimitiveType) { - return create(TypeSchema, { - typeKind: { - case: 'primitive', - value, - }, - }); -} - -export const BOOL_TYPE = primitiveType(Type_PrimitiveType.BOOL); -export const BYTES_TYPE = primitiveType(Type_PrimitiveType.BYTES); -export const DOUBLE_TYPE = primitiveType(Type_PrimitiveType.DOUBLE); -export const INT64_TYPE = primitiveType(Type_PrimitiveType.INT64); -export const STRING_TYPE = primitiveType(Type_PrimitiveType.STRING); -export const UINT64_TYPE = primitiveType(Type_PrimitiveType.UINT64); - -export function wrapperType(value: Type_PrimitiveType) { - return create(TypeSchema, { - typeKind: { - case: 'wrapper', - value, - }, - }); -} - -export function wellKnownType(value: Type_WellKnownType) { - return create(TypeSchema, { - typeKind: { - case: 'wellKnown', - value, - }, - }); -} - -export const ANY_TYPE = wellKnownType(Type_WellKnownType.ANY); -export const DURATION_TYPE = wellKnownType(Type_WellKnownType.DURATION); -export const TIMESTAMP_TYPE = wellKnownType(Type_WellKnownType.TIMESTAMP); - -export function isCheckedWellKnownType(type: Type) { - if (type.typeKind.case !== 'messageType') { - return false; - } - switch (type.typeKind.value) { - case 'google.protobuf.BoolValue': // Wrapper types. - case 'google.protobuf.BytesValue': - case 'google.protobuf.DoubleValue': - case 'google.protobuf.FloatValue': - case 'google.protobuf.Int64Value': - case 'google.protobuf.Int32Value': - case 'google.protobuf.UInt64Value': - case 'google.protobuf.UInt32Value': - case 'google.protobuf.StringValue': - case 'google.protobuf.Any': // Well-known types. - case 'google.protobuf.Duration': - case 'google.protobuf.Timestamp': - case 'google.protobuf.ListValue': // Json types. - case 'google.protobuf.NullValue': - case 'google.protobuf.Struct': - case 'google.protobuf.Value': - return true; - default: - return false; - } -} - -export function getCheckedWellKnownType(value: string) { - switch (value) { - // Wrapper types. - case 'google.protobuf.BoolValue': - return BOOL_TYPE; - case 'google.protobuf.BytesValue': - return BYTES_TYPE; - case 'google.protobuf.DoubleValue': - case 'google.protobuf.FloatValue': - return DOUBLE_TYPE; - case 'google.protobuf.Int64Value': - case 'google.protobuf.Int32Value': - return INT64_TYPE; - case 'google.protobuf.UInt64Value': - case 'google.protobuf.UInt32Value': - return UINT64_TYPE; - case 'google.protobuf.StringValue': - return STRING_TYPE; - // Well-known types. - case 'google.protobuf.Any': - return ANY_TYPE; - case 'google.protobuf.Duration': - return DURATION_TYPE; - case 'google.protobuf.Timestamp': - return TIMESTAMP_TYPE; - // Json types. - case 'google.protobuf.ListValue': - return listType({ elemType: DYN_TYPE }); - case 'google.protobuf.NullValue': - return NULL_TYPE; - case 'google.protobuf.Struct': - return mapType({ keyType: STRING_TYPE, valueType: DYN_TYPE }); - case 'google.protobuf.Value': - return DYN_TYPE; - default: - return null; - } -} - -export function listType(value: MessageInitShape) { - return create(TypeSchema, { - typeKind: { - case: 'listType', - value, - }, - }); -} - -export function mapType(value: MessageInitShape) { - return create(TypeSchema, { - typeKind: { - case: 'mapType', - value, - }, - }); -} - -export function functionType( - value: MessageInitShape -) { - return create(TypeSchema, { - typeKind: { - case: 'function', - value, - }, - }); -} - -export function unwrapFunctionType(val: Type) { - if (val.typeKind.case === 'function') { - return val.typeKind.value; - } - return null; -} - -export function messageType(value: string) { - return create(TypeSchema, { - typeKind: { - case: 'messageType', - value, - }, - }); -} - -export function unwrapMessageType(val: Type) { - if (val.typeKind.case === 'messageType') { - return val.typeKind.value; - } - return null; -} - -export function typeParamType(value: string) { - return create(TypeSchema, { - typeKind: { - case: 'typeParam', - value, - }, - }); -} - -export function typeType(value: Type) { - return create(TypeSchema, { - typeKind: { - case: 'type', - value, - }, - }); -} - -export const ERROR_TYPE = create(TypeSchema, { - typeKind: { - case: 'error', - value: create(EmptySchema), - }, -}); - -export function abstractType( - value: MessageInitShape -) { - return create(TypeSchema, { - typeKind: { - case: 'abstractType', - value, - }, - }); -} - -export const TYPE_TYPE = abstractType({ name: 'type' }); - -export function optionalType(value: Type) { - return abstractType({ name: 'optional_type', parameterTypes: [value] }); -} - -export function isOptionalType(val: Type) { - return ( - val.typeKind.case === 'abstractType' && - val.typeKind.value.name === 'optional_type' - ); -} - -export function unwrapOptionalType(val: Type) { - if (isOptionalType(val)) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return (val.typeKind.value as any).parameterTypes[0] as Type; - } - return null; -} - -export function maybeUnwrapOptionalType(val: Type | null | undefined) { - if (isNil(val)) { - return null; - } - if (!isOptionalType(val)) { - return val; - } - return unwrapOptionalType(val); -} - -export const OPTIONAL_TYPE = abstractType({ name: 'optional_type' }); - -export function wrappedType(value: Type_PrimitiveType) { - return create(TypeSchema, { - typeKind: { - case: 'wrapper', - value, - }, - }); -} - -export function nullableType(value: Type) { - return abstractType({ name: 'nullable_type', parameterTypes: [value] }); -} - -export function isNullableType(val: Type) { - return ( - val.typeKind.case === 'abstractType' && - val.typeKind.value.name === 'nullable_type' - ); -} - -export function unwrapNullableType(val: Type) { - if (isNullableType(val)) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return (val.typeKind.value as any).parameterTypes[0] as Type; - } - return null; -} - -export function unwrapIdentDeclType(val: Decl) { - if (val.declKind.case === 'ident') { - return val.declKind.value ?? null; - } - return null; -} - -export function unwrapFunctionDeclType(val: Decl) { - if (val.declKind.case === 'function') { - return val.declKind.value ?? null; - } - return null; -} - -export function isDyn(val: Type) { - return val.typeKind.case === 'dyn'; -} - -export function isError(val: Type) { - return val.typeKind.case === 'error'; -} - -export function isDynOrError(val: Type) { - return isDyn(val) || isError(val); -} - -export function isNullType(val: Type) { - return val.typeKind.case === 'null'; -} +import { enumToJson } from '@bufbuild/protobuf'; +import { abstractType } from '../common/types/abstract'; +import { DYN_TYPE, isDynType } from '../common/types/dyn'; +import { functionType } from '../common/types/function'; +import { listType } from '../common/types/list'; +import { mapType } from '../common/types/map'; +import { isNullType } from '../common/types/null'; +import { isNullableType, unwrapNullableType } from '../common/types/nullable'; +import { primitiveType } from '../common/types/primitive'; +import { typeType } from '../common/types/type'; +import { isDynTypeOrErrorType } from '../common/types/utils'; +import { getCheckedWellKnownType } from '../common/types/wkt'; +import { wrapperType } from '../common/types/wrapper'; /** * Checks whether one type is equal or less specific than another. A type is @@ -339,11 +37,11 @@ export function isEqualOrLessSpecific(t1: Type, t2: Type): boolean { const kind1 = t1.typeKind.case; const kind2 = t2.typeKind.case; // The first type is less specific - if (isDyn(t1) || kind1 === 'typeParam') { + if (isDynType(t1) || kind1 === 'typeParam') { return true; } // The first type is not less specific. - if (isDyn(t2) || kind2 === 'typeParam') { + if (isDynType(t2) || kind2 === 'typeParam') { return false; } // Types must be of the same kind to be equal. @@ -548,7 +246,7 @@ export function internalIsAssignable( } } // Next check for wildcard types. - if (isDynOrError(t1) || isDynOrError(t2)) { + if (isDynTypeOrErrorType(t1) || isDynTypeOrErrorType(t2)) { return true; } @@ -801,7 +499,7 @@ export function notReferencedIn( notReferencedIn(m, t, withinType.typeKind.value.valueType!) ); case 'wrapper': - return notReferencedIn(m, t, wrappedType(withinType.typeKind.value)); + return notReferencedIn(m, t, wrapperType(withinType.typeKind.value)); default: return true; } @@ -837,7 +535,7 @@ export function defaultIsAssignableType( current: Type, fromType: Type ): boolean { - if (current === fromType || isDyn(current)) { + if (current === fromType || isDynType(current)) { return true; } if (isNullableType(current) && isNullType(fromType)) { diff --git a/packages/cel/src/lib/common/ast.ts b/packages/cel/src/lib/common/ast.ts new file mode 100644 index 0000000..3bf0705 --- /dev/null +++ b/packages/cel/src/lib/common/ast.ts @@ -0,0 +1,59 @@ +import { SourceInfo } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; + +export interface Location { + line: number; + column: number; +} + +export interface OffsetRange { + start: number; + stop: number; +} + +/** + * Returns the line and column information for a given character offset. + * + * @param offset the 0-based character offset + * @returns the line and column information + */ +export function getLocationByOffset( + sourceInfo: SourceInfo, + offset: number +): Location { + let line = 1; + let column = offset; + for (let i = 0; i < sourceInfo.lineOffsets.length; i++) { + const lineOffset = sourceInfo.lineOffsets[i]; + if (lineOffset > offset) { + break; + } + line++; + column = offset - lineOffset; + } + return { line, column }; +} + +/** + * calculates the 0-based character offset from a 1-based line and 0-based + * column. + * @param line a 1-based line number + * @param column a 0-based column number + */ +export function computeOffset( + baseLine: number, + baseColumn: number, + sourceInfo: SourceInfo, + line: number, + column: number +) { + line = baseLine + line; + column = baseColumn + column; + if (line === 1) { + return column; + } + if (line < 1 || line > sourceInfo.lineOffsets.length) { + return -1; + } + const offset = sourceInfo.lineOffsets[line - 2]; + return offset + column; +} diff --git a/packages/cel/src/lib/constants.spec.ts b/packages/cel/src/lib/common/constants.spec.ts similarity index 99% rename from packages/cel/src/lib/constants.spec.ts rename to packages/cel/src/lib/common/constants.spec.ts index abcc206..023ef93 100644 --- a/packages/cel/src/lib/constants.spec.ts +++ b/packages/cel/src/lib/common/constants.spec.ts @@ -1,3 +1,4 @@ +import { ParseException } from '../exceptions'; import { parseBytesConstant, parseDoubleConstant, @@ -5,7 +6,6 @@ import { parseStringConstant, parseUintConstant, } from './constants'; -import { ParseException } from './exceptions'; describe('ConstantsTest', () => { it('parseInt_base10Zero', () => { diff --git a/packages/cel/src/lib/constants.ts b/packages/cel/src/lib/common/constants.ts similarity index 99% rename from packages/cel/src/lib/constants.ts rename to packages/cel/src/lib/common/constants.ts index 93380e6..ca4d047 100644 --- a/packages/cel/src/lib/constants.ts +++ b/packages/cel/src/lib/common/constants.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import { ConstantSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; import { create } from '@bufbuild/protobuf'; -import { ParseException } from './exceptions'; +import { ParseException } from '../exceptions'; const DOUBLE_QUOTE = `"`; const SINGLE_QUOTE = `'`; diff --git a/packages/cel/src/lib/container.test.ts b/packages/cel/src/lib/common/container.spec.ts similarity index 100% rename from packages/cel/src/lib/container.test.ts rename to packages/cel/src/lib/common/container.spec.ts diff --git a/packages/cel/src/lib/container.ts b/packages/cel/src/lib/common/container.ts similarity index 100% rename from packages/cel/src/lib/container.ts rename to packages/cel/src/lib/common/container.ts diff --git a/packages/cel/src/lib/common/decls/function-decl.ts b/packages/cel/src/lib/common/decls/function-decl.ts new file mode 100644 index 0000000..72f9a0c --- /dev/null +++ b/packages/cel/src/lib/common/decls/function-decl.ts @@ -0,0 +1,47 @@ +import { + Decl, + DeclSchema, + Decl_FunctionDecl, + Decl_FunctionDeclSchema, + Decl_FunctionDecl_OverloadSchema, + ReferenceSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { MessageInitShape, create } from '@bufbuild/protobuf'; + +export function functionDecl( + name: string, + init: MessageInitShape +) { + return create(DeclSchema, { + name, + declKind: { + case: 'function', + value: init, + }, + }); +} + +export function isFunctionDecl(val: Decl): val is Decl & { + declKind: { case: 'function'; value: Decl_FunctionDecl }; +} { + return val.declKind.case === 'function'; +} + +export function unwrapFunctionDecl(val: Decl) { + if (isFunctionDecl(val)) { + return val.declKind.value; + } + return null; +} + +export function overloadDecl( + init: MessageInitShape +) { + return create(Decl_FunctionDecl_OverloadSchema, init); +} + +export function functionReference(overloadId: string[]) { + return create(ReferenceSchema, { + overloadId, + }); +} diff --git a/packages/cel/src/lib/common/decls/ident-decl.ts b/packages/cel/src/lib/common/decls/ident-decl.ts new file mode 100644 index 0000000..b2b4837 --- /dev/null +++ b/packages/cel/src/lib/common/decls/ident-decl.ts @@ -0,0 +1,42 @@ +import { + Decl, + DeclSchema, + Decl_IdentDecl, + Decl_IdentDeclSchema, + ReferenceSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { Constant } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { MessageInitShape, create } from '@bufbuild/protobuf'; + +export function identDecl( + name: string, + init: MessageInitShape +) { + return create(DeclSchema, { + name, + declKind: { + case: 'ident', + value: init, + }, + }); +} + +export function isIdentDecl(val: Decl): val is Decl & { + declKind: { case: 'ident'; value: Decl_IdentDecl }; +} { + return val.declKind.case === 'ident'; +} + +export function unwrapIdentDecl(val: Decl) { + if (isIdentDecl(val)) { + return val.declKind.value; + } + return null; +} + +export function identReference(name: string, value: Constant) { + return create(ReferenceSchema, { + name, + value, + }); +} diff --git a/packages/cel/src/lib/errors.ts b/packages/cel/src/lib/common/errors.ts similarity index 98% rename from packages/cel/src/lib/errors.ts rename to packages/cel/src/lib/common/errors.ts index 19cbac3..3f96957 100644 --- a/packages/cel/src/lib/errors.ts +++ b/packages/cel/src/lib/common/errors.ts @@ -12,8 +12,9 @@ import { import { create, createRegistry } from '@bufbuild/protobuf'; import { anyPack, anyUnpack } from '@bufbuild/protobuf/wkt'; import { ErrorListener, RecognitionException, Recognizer, Token } from 'antlr4'; +import { formatCELType, formatFunctionType } from '../checker/types'; +import { Location } from './ast'; import { CELContainer } from './container'; -import { Location, formatCELType, formatFunctionType } from './types'; export class Errors { public readonly errors = create(ErrorSetSchema); diff --git a/packages/cel/src/lib/standard.ts b/packages/cel/src/lib/common/standard.ts similarity index 97% rename from packages/cel/src/lib/standard.ts rename to packages/cel/src/lib/common/standard.ts index 7b4435d..e361a5c 100644 --- a/packages/cel/src/lib/standard.ts +++ b/packages/cel/src/lib/common/standard.ts @@ -44,7 +44,7 @@ import { NOT_EQUALS_OPERATOR, NOT_STRICTLY_FALSE_OPERATOR, SUBTRACT_OPERATOR, -} from './operators'; +} from '../operators'; import { ADD_BYTES_OVERLOAD, ADD_DOUBLE_OVERLOAD, @@ -230,25 +230,23 @@ import { UINT_TO_INT_OVERLOAD, UINT_TO_STRING_OVERLOAD, UINT_TO_UINT_OVERLOAD, -} from './overloads'; -import { - BOOL_TYPE, - BYTES_TYPE, - DOUBLE_TYPE, - DURATION_TYPE, - DYN_TYPE, - INT64_TYPE, - NULL_TYPE, - STRING_TYPE, - TIMESTAMP_TYPE, - TYPE_TYPE, - UINT64_TYPE, - listType, - mapType, - typeParamType, - typeType, -} from './types'; -import { functionDecl, identDecl } from './utils'; +} from '../overloads'; +import { functionDecl } from './decls/function-decl'; +import { identDecl } from './decls/ident-decl'; +import { ABSTRACT_TYPE_TYPE } from './types/abstract'; +import { BOOL_TYPE } from './types/bool'; +import { BYTES_TYPE } from './types/bytes'; +import { DOUBLE_TYPE } from './types/double'; +import { DYN_TYPE } from './types/dyn'; +import { INT64_TYPE } from './types/int'; +import { listType } from './types/list'; +import { mapType } from './types/map'; +import { NULL_TYPE } from './types/null'; +import { STRING_TYPE } from './types/string'; +import { typeType } from './types/type'; +import { typeParamType } from './types/type-param'; +import { UINT64_TYPE } from './types/uint'; +import { DURATION_TYPE, TIMESTAMP_TYPE } from './types/wkt'; export const STANDARD_DESCRIPTORS: ( | DescMessage @@ -289,7 +287,7 @@ export const STANDARD_IDENTS: Decl[] = [ identDecl('map', { type: typeType(mapType({ keyType: DYN_TYPE, valueType: DYN_TYPE })), }), - identDecl('type', { type: typeType(TYPE_TYPE) }), + identDecl('type', { type: typeType(ABSTRACT_TYPE_TYPE) }), identDecl('null_type', { type: typeType(NULL_TYPE) }), identDecl('null', { type: NULL_TYPE }), ]; diff --git a/packages/cel/src/lib/common/types/abstract.ts b/packages/cel/src/lib/common/types/abstract.ts new file mode 100644 index 0000000..d33434f --- /dev/null +++ b/packages/cel/src/lib/common/types/abstract.ts @@ -0,0 +1,33 @@ +import { + Type, + TypeSchema, + Type_AbstractType, + Type_AbstractTypeSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { MessageInitShape, create } from '@bufbuild/protobuf'; + +export function abstractType( + value: MessageInitShape +) { + return create(TypeSchema, { + typeKind: { + case: 'abstractType', + value, + }, + }); +} + +export function isAbstractType(val: Type): val is Type & { + typeKind: { case: 'abstractType'; value: Type_AbstractType }; +} { + return val.typeKind.case === 'abstractType'; +} + +export function unwrapAbstractType(val: Type): Type_AbstractType | null { + if (isAbstractType(val)) { + return val.typeKind.value; + } + return null; +} + +export const ABSTRACT_TYPE_TYPE = abstractType({ name: 'type' }); diff --git a/packages/cel/src/lib/common/types/bool.ts b/packages/cel/src/lib/common/types/bool.ts new file mode 100644 index 0000000..a526236 --- /dev/null +++ b/packages/cel/src/lib/common/types/bool.ts @@ -0,0 +1,14 @@ +import { + Type, + Type_PrimitiveType, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { primitiveType } from './primitive'; + +export const BOOL_TYPE = primitiveType(Type_PrimitiveType.BOOL); + +export function isBoolType(type: Type) { + return ( + type.typeKind.case === 'primitive' && + type.typeKind.value === Type_PrimitiveType.BOOL + ); +} diff --git a/packages/cel/src/lib/common/types/bytes.ts b/packages/cel/src/lib/common/types/bytes.ts new file mode 100644 index 0000000..e56563c --- /dev/null +++ b/packages/cel/src/lib/common/types/bytes.ts @@ -0,0 +1,14 @@ +import { + Type, + Type_PrimitiveType, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { primitiveType } from './primitive'; + +export const BYTES_TYPE = primitiveType(Type_PrimitiveType.BYTES); + +export function isBytesType(val: Type) { + return ( + val.typeKind.case === 'primitive' && + val.typeKind.value === Type_PrimitiveType.BYTES + ); +} diff --git a/packages/cel/src/lib/common/types/double.ts b/packages/cel/src/lib/common/types/double.ts new file mode 100644 index 0000000..0ecc3b8 --- /dev/null +++ b/packages/cel/src/lib/common/types/double.ts @@ -0,0 +1,23 @@ +import { + Type, + Type_PrimitiveType, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { primitiveType } from './primitive'; + +export const DOUBLE_TYPE = primitiveType(Type_PrimitiveType.DOUBLE); + +export function isDoubleType(val: Type): val is Type & { + typeKind: { case: 'primitive'; value: Type_PrimitiveType.DOUBLE }; +} { + return ( + val.typeKind.case === 'primitive' && + val.typeKind.value === Type_PrimitiveType.DOUBLE + ); +} + +export function unwrapDoubleType(val: Type) { + if (isDoubleType(val)) { + return val.typeKind.value; + } + return null; +} diff --git a/packages/cel/src/lib/common/types/dyn.ts b/packages/cel/src/lib/common/types/dyn.ts new file mode 100644 index 0000000..84aaaef --- /dev/null +++ b/packages/cel/src/lib/common/types/dyn.ts @@ -0,0 +1,26 @@ +import { + Type, + TypeSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb'; +import { create } from '@bufbuild/protobuf'; +import { Empty, EmptySchema } from '@bufbuild/protobuf/wkt'; + +export const DYN_TYPE = create(TypeSchema, { + typeKind: { + case: 'dyn', + value: create(EmptySchema), + }, +}); + +export function isDynType(val: Type): val is Type & { + typeKind: { case: 'dyn'; value: Empty }; +} { + return val.typeKind.case === 'dyn'; +} + +export function unwrapDynType(val: Type) { + if (isDynType(val)) { + return val.typeKind.value; + } + return null; +} diff --git a/packages/cel/src/lib/common/types/error.ts b/packages/cel/src/lib/common/types/error.ts new file mode 100644 index 0000000..cb3959f --- /dev/null +++ b/packages/cel/src/lib/common/types/error.ts @@ -0,0 +1,26 @@ +import { + Type, + TypeSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { Empty, EmptySchema } from '@bufbuild/protobuf/wkt'; + +export const ERROR_TYPE = create(TypeSchema, { + typeKind: { + case: 'error', + value: create(EmptySchema), + }, +}); + +export function isErrorType(val: Type): val is Type & { + typeKind: { case: 'error'; value: Empty }; +} { + return val.typeKind.case === 'error'; +} + +export function unwrapErrorType(val: Type) { + if (isErrorType(val)) { + return val.typeKind.value; + } + return null; +} diff --git a/packages/cel/src/lib/common/types/function.ts b/packages/cel/src/lib/common/types/function.ts new file mode 100644 index 0000000..87fe405 --- /dev/null +++ b/packages/cel/src/lib/common/types/function.ts @@ -0,0 +1,33 @@ +import { + Type, + TypeSchema, + Type_FunctionTypeSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { MessageInitShape, create } from '@bufbuild/protobuf'; + +export function functionType( + value: MessageInitShape +) { + return create(TypeSchema, { + typeKind: { + case: 'function', + value, + }, + }); +} + +export function isFunctionType(val: Type): val is Type & { + typeKind: { + case: 'function'; + value: MessageInitShape; + }; +} { + return val.typeKind.case === 'function'; +} + +export function unwrapFunctionType(val: Type) { + if (isFunctionType(val)) { + return val.typeKind.value; + } + return null; +} diff --git a/packages/cel/src/lib/common/types/int.ts b/packages/cel/src/lib/common/types/int.ts new file mode 100644 index 0000000..64f4eb2 --- /dev/null +++ b/packages/cel/src/lib/common/types/int.ts @@ -0,0 +1,23 @@ +import { + Type, + Type_PrimitiveType, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { primitiveType } from './primitive'; + +export const INT64_TYPE = primitiveType(Type_PrimitiveType.INT64); + +export function isInt64Type(val: Type): val is Type & { + typeKind: { case: 'primitive'; value: Type_PrimitiveType.INT64 }; +} { + return ( + val.typeKind.case === 'primitive' && + val.typeKind.value === Type_PrimitiveType.INT64 + ); +} + +export function unwrapInt64Type(val: Type) { + if (isInt64Type(val)) { + return val.typeKind.value; + } + return null; +} diff --git a/packages/cel/src/lib/common/types/list.ts b/packages/cel/src/lib/common/types/list.ts new file mode 100644 index 0000000..1a9aee8 --- /dev/null +++ b/packages/cel/src/lib/common/types/list.ts @@ -0,0 +1,31 @@ +import { + Type, + TypeSchema, + Type_ListTypeSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { MessageInitShape, create } from '@bufbuild/protobuf'; + +export function listType(value: MessageInitShape) { + return create(TypeSchema, { + typeKind: { + case: 'listType', + value, + }, + }); +} + +export function isListType(val: Type): val is Type & { + typeKind: { + case: 'listType'; + value: MessageInitShape; + }; +} { + return val.typeKind.case === 'listType'; +} + +export function unwrapListElemType(val: Type) { + if (isListType(val)) { + return val.typeKind.value.elemType; + } + return null; +} diff --git a/packages/cel/src/lib/common/types/map.ts b/packages/cel/src/lib/common/types/map.ts new file mode 100644 index 0000000..1dc977f --- /dev/null +++ b/packages/cel/src/lib/common/types/map.ts @@ -0,0 +1,38 @@ +import { + Type, + TypeSchema, + Type_MapTypeSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { MessageInitShape, create } from '@bufbuild/protobuf'; + +export function mapType(value: MessageInitShape) { + return create(TypeSchema, { + typeKind: { + case: 'mapType', + value, + }, + }); +} + +export function isMapType(val: Type): val is Type & { + typeKind: { + case: 'mapType'; + value: MessageInitShape; + }; +} { + return val.typeKind.case === 'mapType'; +} + +export function unwrapMapKeyType(val: Type) { + if (isMapType(val)) { + return val.typeKind.value.keyType; + } + return null; +} + +export function unwrapMapValueType(val: Type) { + if (isMapType(val)) { + return val.typeKind.value.valueType; + } + return null; +} diff --git a/packages/cel/src/lib/common/types/message.ts b/packages/cel/src/lib/common/types/message.ts new file mode 100644 index 0000000..e12df13 --- /dev/null +++ b/packages/cel/src/lib/common/types/message.ts @@ -0,0 +1,27 @@ +import { + Type, + TypeSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { create } from '@bufbuild/protobuf'; + +export function messageType(value: string) { + return create(TypeSchema, { + typeKind: { + case: 'messageType', + value, + }, + }); +} + +export function isMessageType(val: Type): val is Type & { + typeKind: { case: 'messageType'; value: string }; +} { + return val.typeKind.case === 'messageType'; +} + +export function unwrapMessageType(val: Type) { + if (isMessageType(val)) { + return val.typeKind.value; + } + return null; +} diff --git a/packages/cel/src/lib/common/types/null.ts b/packages/cel/src/lib/common/types/null.ts new file mode 100644 index 0000000..0b3f29f --- /dev/null +++ b/packages/cel/src/lib/common/types/null.ts @@ -0,0 +1,26 @@ +import { + Type, + TypeSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { NullValue } from '@bufbuild/protobuf/wkt'; + +export const NULL_TYPE = create(TypeSchema, { + typeKind: { + case: 'null', + value: NullValue.NULL_VALUE, + }, +}); + +export function isNullType(type: Type): type is Type & { + typeKind: { case: 'null'; value: NullValue }; +} { + return type.typeKind.case === 'null'; +} + +export function unwrapNullType(type: Type) { + if (isNullType(type)) { + return type.typeKind.value; + } + return null; +} diff --git a/packages/cel/src/lib/common/types/nullable.ts b/packages/cel/src/lib/common/types/nullable.ts new file mode 100644 index 0000000..72b0588 --- /dev/null +++ b/packages/cel/src/lib/common/types/nullable.ts @@ -0,0 +1,28 @@ +import { Type } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { abstractType, isAbstractType } from './abstract'; + +export function nullableType(value: Type) { + return abstractType({ name: 'nullable_type', parameterTypes: [value] }); +} + +export function isNullableType(val: Type): val is Type & { + typeKind: { + case: 'abstractType'; + value: { name: 'nullable_type'; parameterTypes: [Type] }; + }; +} { + return isAbstractType(val) && val.typeKind.value.name === 'nullable_type'; +} + +export function unwrapNullableType(val: Type) { + if (isNullableType(val)) { + return val.typeKind.value.parameterTypes[0]; + } + return null; +} + +export function maybeUnwrapNullableType(val: Type) { + return isNullableType(val) ? unwrapNullableType(val) : val; +} + +export const ABSTRACT_NULLABLE_TYPE = abstractType({ name: 'nullable_type' }); diff --git a/packages/cel/src/lib/common/types/optional.ts b/packages/cel/src/lib/common/types/optional.ts new file mode 100644 index 0000000..aca8457 --- /dev/null +++ b/packages/cel/src/lib/common/types/optional.ts @@ -0,0 +1,31 @@ +import { Type } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { abstractType, isAbstractType } from './abstract'; + +export function optionalType(value: Type) { + return abstractType({ name: 'optional_type', parameterTypes: [value] }); +} + +export function isOptionalType(val: Type): val is Type & { + typeKind: { + case: 'abstractType'; + value: { name: 'optional_type'; parameterTypes: [Type] }; + }; +} { + if (!isAbstractType(val)) { + return false; + } + return val.typeKind.value.name === 'optional_type'; +} + +export function unwrapOptionalType(val: Type) { + if (isOptionalType(val)) { + return val.typeKind.value.parameterTypes[0]; + } + return null; +} + +export function maybeUnwrapOptionalType(val: Type) { + return isOptionalType(val) ? unwrapOptionalType(val) : val; +} + +export const ABSTRACT_OPTIONAL_TYPE = abstractType({ name: 'optional_type' }); diff --git a/packages/cel/src/lib/common/types/primitive.ts b/packages/cel/src/lib/common/types/primitive.ts new file mode 100644 index 0000000..2c90169 --- /dev/null +++ b/packages/cel/src/lib/common/types/primitive.ts @@ -0,0 +1,30 @@ +import { + Type, + Type_PrimitiveType, + TypeSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { create } from '@bufbuild/protobuf'; + +export function primitiveType(value: Type_PrimitiveType) { + return create(TypeSchema, { + typeKind: { + case: 'primitive', + value, + }, + }); +} + +export function isPrimitiveType( + val: Type +): val is Type & { + typeKind: { case: 'primitive'; value: Type_PrimitiveType }; +} { + return val.typeKind.case === 'primitive'; +} + +export function unwrapPrimitiveType(val: Type) { + if (isPrimitiveType(val)) { + return val.typeKind.value; + } + return null; +} diff --git a/packages/cel/src/lib/common/types/string.ts b/packages/cel/src/lib/common/types/string.ts new file mode 100644 index 0000000..69e4b37 --- /dev/null +++ b/packages/cel/src/lib/common/types/string.ts @@ -0,0 +1,23 @@ +import { + Type, + Type_PrimitiveType, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { primitiveType } from './primitive'; + +export const STRING_TYPE = primitiveType(Type_PrimitiveType.STRING); + +export function isStringType(val: Type): val is Type & { + typeKind: { case: 'primitive'; value: Type_PrimitiveType }; +} { + return ( + val.typeKind.case === 'primitive' && + val.typeKind.value === Type_PrimitiveType.STRING + ); +} + +export function unwrapStringType(val: Type) { + if (isStringType(val)) { + return val.typeKind.value; + } + return null; +} diff --git a/packages/cel/src/lib/common/types/type-param.ts b/packages/cel/src/lib/common/types/type-param.ts new file mode 100644 index 0000000..4e0d224 --- /dev/null +++ b/packages/cel/src/lib/common/types/type-param.ts @@ -0,0 +1,27 @@ +import { + Type, + TypeSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { create } from '@bufbuild/protobuf'; + +export function typeParamType(value: string) { + return create(TypeSchema, { + typeKind: { + case: 'typeParam', + value, + }, + }); +} + +export function isTypeParamType(val: Type): val is Type & { + typeKind: { case: 'typeParam'; value: string }; +} { + return val.typeKind.case === 'typeParam'; +} + +export function unwrapTypeParamType(val: Type) { + if (isTypeParamType(val)) { + return val.typeKind.value; + } + return null; +} diff --git a/packages/cel/src/lib/common/types/type.ts b/packages/cel/src/lib/common/types/type.ts new file mode 100644 index 0000000..440aa4b --- /dev/null +++ b/packages/cel/src/lib/common/types/type.ts @@ -0,0 +1,27 @@ +import { + Type, + TypeSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { create } from '@bufbuild/protobuf'; + +export function typeType(value: Type) { + return create(TypeSchema, { + typeKind: { + case: 'type', + value, + }, + }); +} + +export function isTypeType(value: Type): value is Type & { + typeKind: { case: 'type'; value: Type }; +} { + return value.typeKind.case === 'type'; +} + +export function unwrapTypeType(value: Type) { + if (isTypeType(value)) { + return value.typeKind.value; + } + return null; +} diff --git a/packages/cel/src/lib/common/types/uint.ts b/packages/cel/src/lib/common/types/uint.ts new file mode 100644 index 0000000..584e879 --- /dev/null +++ b/packages/cel/src/lib/common/types/uint.ts @@ -0,0 +1,23 @@ +import { + Type, + Type_PrimitiveType, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { primitiveType } from './primitive'; + +export const UINT64_TYPE = primitiveType(Type_PrimitiveType.UINT64); + +export function isUint64Type(type: Type): type is Type & { + typeKind: { case: 'primitive'; value: Type_PrimitiveType }; +} { + return ( + type.typeKind.case === 'primitive' && + type.typeKind.value === Type_PrimitiveType.UINT64 + ); +} + +export function unwrapUnit64Type(type: Type) { + if (isUint64Type(type)) { + return type.typeKind.value; + } + return null; +} diff --git a/packages/cel/src/lib/common/types/utils.spec.ts b/packages/cel/src/lib/common/types/utils.spec.ts new file mode 100644 index 0000000..8258a26 --- /dev/null +++ b/packages/cel/src/lib/common/types/utils.spec.ts @@ -0,0 +1,89 @@ +import { Type_PrimitiveType } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb'; +import { ScalarType } from '@bufbuild/protobuf'; +import { BOOL_TYPE } from './bool'; +import { BYTES_TYPE } from './bytes'; +import { DYN_TYPE } from './dyn'; +import { ERROR_TYPE } from './error'; +import { INT64_TYPE } from './int'; +import { primitiveType } from './primitive'; +import { STRING_TYPE } from './string'; +import { UINT64_TYPE } from './uint'; +import { isDynTypeOrErrorType, scalarTypeToPrimitiveType } from './utils'; + +describe('utils', () => { + it('isDynTypeOrErrorType', () => { + expect(isDynTypeOrErrorType(DYN_TYPE)).toBe(true); + expect(isDynTypeOrErrorType(ERROR_TYPE)).toBe(true); + expect(isDynTypeOrErrorType(BOOL_TYPE)).toBe(false); + expect(isDynTypeOrErrorType(BYTES_TYPE)).toBe(false); + expect(isDynTypeOrErrorType(INT64_TYPE)).toBe(false); + expect(isDynTypeOrErrorType(STRING_TYPE)).toBe(false); + expect(isDynTypeOrErrorType(UINT64_TYPE)).toBe(false); + }); + + it('scalarTypeToPrimitiveType', () => { + const testCases = [ + { + in: ScalarType.BOOL, + out: Type_PrimitiveType.BOOL, + }, + { + in: ScalarType.BYTES, + out: Type_PrimitiveType.BYTES, + }, + { + in: ScalarType.DOUBLE, + out: Type_PrimitiveType.DOUBLE, + }, + { + in: ScalarType.INT64, + out: Type_PrimitiveType.INT64, + }, + { + in: ScalarType.STRING, + out: Type_PrimitiveType.STRING, + }, + { + in: ScalarType.UINT64, + out: Type_PrimitiveType.UINT64, + }, + { + in: ScalarType.FIXED32, + out: Type_PrimitiveType.DOUBLE, + }, + { + in: ScalarType.FIXED64, + out: Type_PrimitiveType.DOUBLE, + }, + { + in: ScalarType.FLOAT, + out: Type_PrimitiveType.DOUBLE, + }, + { + in: ScalarType.SFIXED32, + out: Type_PrimitiveType.DOUBLE, + }, + { + in: ScalarType.SFIXED64, + out: Type_PrimitiveType.DOUBLE, + }, + { + in: ScalarType.SINT32, + out: Type_PrimitiveType.INT64, + }, + { + in: ScalarType.SINT64, + out: Type_PrimitiveType.INT64, + }, + { + in: ScalarType.UINT32, + out: Type_PrimitiveType.UINT64, + }, + ]; + for (const testCase of testCases) { + expect(scalarTypeToPrimitiveType(testCase.in)).toEqual( + primitiveType(testCase.out) + ); + } + }); +}); diff --git a/packages/cel/src/lib/common/types/utils.ts b/packages/cel/src/lib/common/types/utils.ts new file mode 100644 index 0000000..260999a --- /dev/null +++ b/packages/cel/src/lib/common/types/utils.ts @@ -0,0 +1,148 @@ +/* eslint-disable no-case-declarations */ +import { isNil } from '@bearclaw/is'; +import { + Type, + Type_PrimitiveType, + Type_WellKnownType, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { DescField, ScalarType } from '@bufbuild/protobuf'; +import { Empty } from '@bufbuild/protobuf/wkt'; +import { DYN_TYPE, isDynType } from './dyn'; +import { isErrorType } from './error'; +import { listType } from './list'; +import { mapType } from './map'; +import { messageType } from './message'; +import { primitiveType } from './primitive'; +import { getCheckedWellKnownType } from './wkt'; + +export function isDynTypeOrErrorType(val: Type): val is Type & + ( + | { + typeKind: { + case: 'error'; + value: Empty; + }; + } + | { + typeKind: { + case: 'dyn'; + value: Empty; + }; + } + ) { + return isDynType(val) || isErrorType(val); +} + +/** + * Get the CEL type for a field descriptor. + * + * @param field the field descriptor + * @returns the CEL type for the field + */ +export function getFieldDescriptorType(field: DescField) { + switch (field.fieldKind) { + case 'message': + const checkedType = getCheckedWellKnownType(field.message.typeName); + if (!isNil(checkedType)) { + return checkedType; + } + return messageType(field.message.typeName); + case 'enum': + return messageType(field.enum.typeName); + case 'list': + switch (field.listKind) { + case 'message': + return listType({ + elemType: messageType(field.message.typeName), + }); + case 'enum': + return listType({ + elemType: messageType(field.enum.typeName), + }); + case 'scalar': + return listType({ + elemType: scalarTypeToPrimitiveType(field.scalar), + }); + default: + return DYN_TYPE; + } + case 'scalar': + return scalarTypeToPrimitiveType(field.scalar); + case 'map': + const keyType = scalarTypeToPrimitiveType(field.mapKey); + switch (field.mapKind) { + case 'enum': + return mapType({ + keyType, + valueType: messageType(field.enum.typeName), + }); + case 'message': + return mapType({ + keyType, + valueType: messageType(field.message.typeName), + }); + case 'scalar': + return mapType({ + keyType, + valueType: scalarTypeToPrimitiveType(field.scalar), + }); + default: + return DYN_TYPE; + } + default: + return DYN_TYPE; + } +} + +/** + * Converts a protobuf scalar type to a CEL primitive type. + * + * @param scalar the scalar type + * @returns the CEL primitive type + */ +export function scalarTypeToPrimitiveType(scalar: ScalarType) { + switch (scalar) { + case ScalarType.BOOL: + return primitiveType(Type_PrimitiveType.BOOL); + case ScalarType.BYTES: + return primitiveType(Type_PrimitiveType.BYTES); + case ScalarType.SFIXED32: + case ScalarType.SFIXED64: + case ScalarType.FIXED32: + case ScalarType.FIXED64: + case ScalarType.FLOAT: + case ScalarType.DOUBLE: + return primitiveType(Type_PrimitiveType.DOUBLE); + case ScalarType.INT32: + case ScalarType.INT64: + case ScalarType.SINT32: + case ScalarType.SINT64: + return primitiveType(Type_PrimitiveType.INT64); + case ScalarType.STRING: + return primitiveType(Type_PrimitiveType.STRING); + case ScalarType.UINT32: + case ScalarType.UINT64: + return primitiveType(Type_PrimitiveType.UINT64); + default: + return DYN_TYPE; + } +} + +/** + * Converts a CEL WellKnwonType to a string. + * + * @param type the WellKnownType + * @returns a string representation of the WellKnownType (or null if not found) + */ +export function getWellKNownTypeName(type: Type_WellKnownType): string | null { + switch (type) { + case Type_WellKnownType.ANY: + return 'google.protobuf.Any'; + case Type_WellKnownType.DURATION: + return 'google.protobuf.Duration'; + case Type_WellKnownType.TIMESTAMP: + return 'google.protobuf.Timestamp'; + default: + return null; + } +} diff --git a/packages/cel/src/lib/common/types/wkt.ts b/packages/cel/src/lib/common/types/wkt.ts new file mode 100644 index 0000000..fd912e8 --- /dev/null +++ b/packages/cel/src/lib/common/types/wkt.ts @@ -0,0 +1,108 @@ +import { + Type, + TypeSchema, + Type_WellKnownType, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb'; +import { create } from '@bufbuild/protobuf'; +import { BOOL_TYPE } from './bool'; +import { BYTES_TYPE } from './bytes'; +import { DOUBLE_TYPE } from './double'; +import { DYN_TYPE } from './dyn'; +import { INT64_TYPE } from './int'; +import { listType } from './list'; +import { mapType } from './map'; +import { NULL_TYPE } from './null'; +import { STRING_TYPE } from './string'; +import { UINT64_TYPE } from './uint'; + +export function wellKnownType(value: Type_WellKnownType) { + return create(TypeSchema, { + typeKind: { + case: 'wellKnown', + value, + }, + }); +} + +export function isWellKnownType(val: Type): val is Type & { + typeKind: { case: 'wellKnown'; value: Type_WellKnownType }; +} { + return val.typeKind.case === 'wellKnown'; +} + +export function unwrapWellKnownType(value: Type) { + if (isWellKnownType(value)) { + return value.typeKind.value; + } + return null; +} + +export const ANY_TYPE = wellKnownType(Type_WellKnownType.ANY); +export const DURATION_TYPE = wellKnownType(Type_WellKnownType.DURATION); +export const TIMESTAMP_TYPE = wellKnownType(Type_WellKnownType.TIMESTAMP); + +export function isCheckedWellKnownType(type: Type) { + if (type.typeKind.case !== 'messageType') { + return false; + } + switch (type.typeKind.value) { + case 'google.protobuf.BoolValue': // Wrapper types. + case 'google.protobuf.BytesValue': + case 'google.protobuf.DoubleValue': + case 'google.protobuf.FloatValue': + case 'google.protobuf.Int64Value': + case 'google.protobuf.Int32Value': + case 'google.protobuf.UInt64Value': + case 'google.protobuf.UInt32Value': + case 'google.protobuf.StringValue': + case 'google.protobuf.Any': // Well-known types. + case 'google.protobuf.Duration': + case 'google.protobuf.Timestamp': + case 'google.protobuf.ListValue': // Json types. + case 'google.protobuf.NullValue': + case 'google.protobuf.Struct': + case 'google.protobuf.Value': + return true; + default: + return false; + } +} + +export function getCheckedWellKnownType(value: string) { + switch (value) { + // Wrapper types. + case 'google.protobuf.BoolValue': + return BOOL_TYPE; + case 'google.protobuf.BytesValue': + return BYTES_TYPE; + case 'google.protobuf.DoubleValue': + case 'google.protobuf.FloatValue': + return DOUBLE_TYPE; + case 'google.protobuf.Int64Value': + case 'google.protobuf.Int32Value': + return INT64_TYPE; + case 'google.protobuf.UInt64Value': + case 'google.protobuf.UInt32Value': + return UINT64_TYPE; + case 'google.protobuf.StringValue': + return STRING_TYPE; + // Well-known types. + case 'google.protobuf.Any': + return ANY_TYPE; + case 'google.protobuf.Duration': + return DURATION_TYPE; + case 'google.protobuf.Timestamp': + return TIMESTAMP_TYPE; + // Json types. + case 'google.protobuf.ListValue': + return listType({ elemType: DYN_TYPE }); + case 'google.protobuf.NullValue': + return NULL_TYPE; + case 'google.protobuf.Struct': + return mapType({ keyType: STRING_TYPE, valueType: DYN_TYPE }); + case 'google.protobuf.Value': + return DYN_TYPE; + default: + return null; + } +} diff --git a/packages/cel/src/lib/common/types/wrapper.ts b/packages/cel/src/lib/common/types/wrapper.ts new file mode 100644 index 0000000..46f0178 --- /dev/null +++ b/packages/cel/src/lib/common/types/wrapper.ts @@ -0,0 +1,28 @@ +import { + Type, + TypeSchema, + Type_PrimitiveType, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { create } from '@bufbuild/protobuf'; + +export function wrapperType(value: Type_PrimitiveType) { + return create(TypeSchema, { + typeKind: { + case: 'wrapper', + value, + }, + }); +} + +export function isWrapperType( + val: Type +): val is Type & { typeKind: { case: 'wrapper'; value: Type_PrimitiveType } } { + return val.typeKind.case === 'wrapper'; +} + +export function unwrapWrapperType(val: Type) { + if (isWrapperType(val)) { + return val.typeKind.value; + } + return null; +} diff --git a/packages/cel/src/lib/utils.spec.ts b/packages/cel/src/lib/common/utils.spec.ts similarity index 91% rename from packages/cel/src/lib/utils.spec.ts rename to packages/cel/src/lib/common/utils.spec.ts index d6bd5bc..39b5064 100644 --- a/packages/cel/src/lib/utils.spec.ts +++ b/packages/cel/src/lib/common/utils.spec.ts @@ -1,13 +1,11 @@ -import { Type_PrimitiveType } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb'; import { ConstantSchema, ExprSchema, Expr_CreateStruct_EntrySchema, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; -import { ScalarType, create } from '@bufbuild/protobuf'; +import { create } from '@bufbuild/protobuf'; import { NullValue } from '@bufbuild/protobuf/wkt'; -import { primitiveType } from './types'; import { NULL_CONSTANT, NULL_VALUE, @@ -33,7 +31,6 @@ import { int64Value, listExpr, nullExpr, - scalarTypeToPrimitiveType, selectExpr, stringConstant, stringExpr, @@ -745,70 +742,4 @@ describe('utils', () => { expect(extractIdent(identExpr(BigInt(1), { name: 'a' }))).toEqual('a'); expect(extractIdent(int64Expr(BigInt(1), BigInt(1)))).toEqual(null); }); - - it('scalarTypeToPrimitiveType', () => { - const testCases = [ - { - in: ScalarType.BOOL, - out: Type_PrimitiveType.BOOL, - }, - { - in: ScalarType.BYTES, - out: Type_PrimitiveType.BYTES, - }, - { - in: ScalarType.DOUBLE, - out: Type_PrimitiveType.DOUBLE, - }, - { - in: ScalarType.INT64, - out: Type_PrimitiveType.INT64, - }, - { - in: ScalarType.STRING, - out: Type_PrimitiveType.STRING, - }, - { - in: ScalarType.UINT64, - out: Type_PrimitiveType.UINT64, - }, - { - in: ScalarType.FIXED32, - out: Type_PrimitiveType.DOUBLE, - }, - { - in: ScalarType.FIXED64, - out: Type_PrimitiveType.DOUBLE, - }, - { - in: ScalarType.FLOAT, - out: Type_PrimitiveType.DOUBLE, - }, - { - in: ScalarType.SFIXED32, - out: Type_PrimitiveType.DOUBLE, - }, - { - in: ScalarType.SFIXED64, - out: Type_PrimitiveType.DOUBLE, - }, - { - in: ScalarType.SINT32, - out: Type_PrimitiveType.INT64, - }, - { - in: ScalarType.SINT64, - out: Type_PrimitiveType.INT64, - }, - { - in: ScalarType.UINT32, - out: Type_PrimitiveType.UINT64, - }, - ]; - for (const testCase of testCases) { - expect(scalarTypeToPrimitiveType(testCase.in)).toEqual( - primitiveType(testCase.out) - ); - } - }); }); diff --git a/packages/cel/src/lib/utils.ts b/packages/cel/src/lib/common/utils.ts similarity index 61% rename from packages/cel/src/lib/utils.ts rename to packages/cel/src/lib/common/utils.ts index 39fe1d1..965c6be 100644 --- a/packages/cel/src/lib/utils.ts +++ b/packages/cel/src/lib/common/utils.ts @@ -3,16 +3,6 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { isNil } from '@bearclaw/is'; import { - DeclSchema, - Decl_FunctionDeclSchema, - Decl_FunctionDecl_OverloadSchema, - Decl_IdentDeclSchema, - ReferenceSchema, - Type_PrimitiveType, - Type_WellKnownType, -} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; -import { - Constant, ConstantSchema, Expr, ExprSchema, @@ -23,25 +13,10 @@ import { Expr_CreateStruct_EntrySchema, Expr_IdentSchema, Expr_SelectSchema, - SourceInfo, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; -import { - DescField, - MessageInitShape, - ScalarType, - create, -} from '@bufbuild/protobuf'; +import { MessageInitShape, create } from '@bufbuild/protobuf'; import { NullValue } from '@bufbuild/protobuf/wkt'; -import { - DYN_TYPE, - Location, - getCheckedWellKnownType, - listType, - mapType, - messageType, - primitiveType, -} from './types'; export function parseString(str: string) { const decoded = decodeURIComponent(str); @@ -416,51 +391,6 @@ export function comprehensionExpr( }); } -export function functionDecl( - name: string, - init: MessageInitShape -) { - return create(DeclSchema, { - name, - declKind: { - case: 'function', - value: init, - }, - }); -} - -export function overloadDecl( - init: MessageInitShape -) { - return create(Decl_FunctionDecl_OverloadSchema, init); -} - -export function identDecl( - name: string, - init: MessageInitShape -) { - return create(DeclSchema, { - name, - declKind: { - case: 'ident', - value: init, - }, - }); -} - -export function identReference(name: string, value: Constant) { - return create(ReferenceSchema, { - name, - value, - }); -} - -export function functionReference(overloadId: string[]) { - return create(ReferenceSchema, { - overloadId, - }); -} - export function unquote(str: string) { const reg = /['"`]/; if (!str) { @@ -482,54 +412,6 @@ export function extractIdent(expr: Expr): string | null { return expr.exprKind.value.name; } -/** - * Returns the line and column information for a given character offset. - * - * @param offset the 0-based character offset - * @returns the line and column information - */ -export function getLocationByOffset( - sourceInfo: SourceInfo, - offset: number -): Location { - let line = 1; - let column = offset; - for (let i = 0; i < sourceInfo.lineOffsets.length; i++) { - const lineOffset = sourceInfo.lineOffsets[i]; - if (lineOffset > offset) { - break; - } - line++; - column = offset - lineOffset; - } - return { line, column }; -} - -/** - * calculates the 0-based character offset from a 1-based line and 0-based - * column. - * @param line a 1-based line number - * @param column a 0-based column number - */ -export function computeOffset( - baseLine: number, - baseColumn: number, - sourceInfo: SourceInfo, - line: number, - column: number -) { - line = baseLine + line; - column = baseColumn + column; - if (line === 1) { - return column; - } - if (line < 1 || line > sourceInfo.lineOffsets.length) { - return -1; - } - const offset = sourceInfo.lineOffsets[line - 2]; - return offset + column; -} - export function mapToObject( map: Map ) { @@ -567,117 +449,3 @@ export function toQualifiedName(expr: Expr): string | null { } return null; } - -/** - * Get the CEL type for a field descriptor. - * - * @param field the field descriptor - * @returns the CEL type for the field - */ -export function getFieldDescriptorType(field: DescField) { - switch (field.fieldKind) { - case 'message': - const checkedType = getCheckedWellKnownType(field.message.typeName); - if (!isNil(checkedType)) { - return checkedType; - } - return messageType(field.message.typeName); - case 'enum': - return messageType(field.enum.typeName); - case 'list': - switch (field.listKind) { - case 'message': - return listType({ - elemType: messageType(field.message.typeName), - }); - case 'enum': - return listType({ - elemType: messageType(field.enum.typeName), - }); - case 'scalar': - return listType({ - elemType: scalarTypeToPrimitiveType(field.scalar), - }); - default: - return DYN_TYPE; - } - case 'scalar': - return scalarTypeToPrimitiveType(field.scalar); - case 'map': - const keyType = scalarTypeToPrimitiveType(field.mapKey); - switch (field.mapKind) { - case 'enum': - return mapType({ - keyType, - valueType: messageType(field.enum.typeName), - }); - case 'message': - return mapType({ - keyType, - valueType: messageType(field.message.typeName), - }); - case 'scalar': - return mapType({ - keyType, - valueType: scalarTypeToPrimitiveType(field.scalar), - }); - default: - return DYN_TYPE; - } - default: - return DYN_TYPE; - } -} - -/** - * Converts a protobuf scalar type to a CEL primitive type. - * - * @param scalar the scalar type - * @returns the CEL primitive type - */ -export function scalarTypeToPrimitiveType(scalar: ScalarType) { - switch (scalar) { - case ScalarType.BOOL: - return primitiveType(Type_PrimitiveType.BOOL); - case ScalarType.BYTES: - return primitiveType(Type_PrimitiveType.BYTES); - case ScalarType.SFIXED32: - case ScalarType.SFIXED64: - case ScalarType.FIXED32: - case ScalarType.FIXED64: - case ScalarType.FLOAT: - case ScalarType.DOUBLE: - return primitiveType(Type_PrimitiveType.DOUBLE); - case ScalarType.INT32: - case ScalarType.INT64: - case ScalarType.SINT32: - case ScalarType.SINT64: - return primitiveType(Type_PrimitiveType.INT64); - case ScalarType.STRING: - return primitiveType(Type_PrimitiveType.STRING); - case ScalarType.UINT32: - case ScalarType.UINT64: - return primitiveType(Type_PrimitiveType.UINT64); - default: - return DYN_TYPE; - } -} - -/** - * Converts a CEL WellKnwonType to a string. - * - * @param type the WellKnownType - * @returns a string representation of the WellKnownType (or null if not found) - */ -export function getWellKNownTypeName(type: Type_WellKnownType): string | null { - switch (type) { - case Type_WellKnownType.ANY: - return 'google.protobuf.Any'; - case Type_WellKnownType.DURATION: - return 'google.protobuf.Duration'; - case Type_WellKnownType.TIMESTAMP: - return 'google.protobuf.Timestamp'; - default: - return null; - } -} diff --git a/packages/cel/src/lib/environment.ts b/packages/cel/src/lib/environment.ts index a7e55fc..04038a6 100644 --- a/packages/cel/src/lib/environment.ts +++ b/packages/cel/src/lib/environment.ts @@ -12,23 +12,24 @@ import { MutableRegistry, createMutableRegistry, } from '@bufbuild/protobuf'; -import { CELContainer } from './container'; -import { CELParser } from './parser'; +import { CELContainer } from './common/container'; +import { identDecl } from './common/decls/ident-decl'; import { STANDARD_DESCRIPTORS, STANDARD_FUNCTION_DECLARATIONS, STANDARD_IDENTS, -} from './standard'; +} from './common/standard'; +import { DYN_TYPE } from './common/types/dyn'; +import { INT64_TYPE } from './common/types/int'; +import { mapType } from './common/types/map'; +import { messageType } from './common/types/message'; +import { STRING_TYPE } from './common/types/string'; +import { getFieldDescriptorType } from './common/types/utils'; import { - DYN_TYPE, - INT64_TYPE, - STRING_TYPE, getCheckedWellKnownType, isCheckedWellKnownType, - mapType, - messageType, -} from './types'; -import { getFieldDescriptorType, identDecl } from './utils'; +} from './common/types/wkt'; +import { CELParser } from './parser/parser'; export interface CELEnvironmentOptions { container?: CELContainer; diff --git a/packages/cel/src/lib/logic-manager.ts b/packages/cel/src/lib/logic-manager.ts index bc437b0..b762aeb 100644 --- a/packages/cel/src/lib/logic-manager.ts +++ b/packages/cel/src/lib/logic-manager.ts @@ -1,5 +1,5 @@ import { Expr } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; -import { callExpr } from './utils'; +import { callExpr } from './common/utils'; export class LogicManager { private function: string; diff --git a/packages/cel/src/lib/macros.ts b/packages/cel/src/lib/parser/macros.ts similarity index 98% rename from packages/cel/src/lib/macros.ts rename to packages/cel/src/lib/parser/macros.ts index ab3163a..f3d8365 100644 --- a/packages/cel/src/lib/macros.ts +++ b/packages/cel/src/lib/parser/macros.ts @@ -2,7 +2,18 @@ import { isNil } from '@bearclaw/is'; import { Expr } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; import { ParserRuleContext, Token } from 'antlr4'; -import { ACCUMULATOR_VAR } from './constants'; +import { Location, OffsetRange } from '../common/ast'; +import { ACCUMULATOR_VAR } from '../common/constants'; +import { + boolExpr, + callExpr, + comprehensionExpr, + extractIdent, + identExpr, + int64Expr, + listExpr, + selectExpr, +} from '../common/utils'; import { ADD_OPERATOR, ALL_MACRO, @@ -17,19 +28,8 @@ import { LOGICAL_OR_OPERATOR, MAP_MACRO, NOT_STRICTLY_FALSE_OPERATOR, -} from './operators'; +} from '../operators'; import { ParserHelper } from './parser-helper'; -import { Location, OffsetRange } from './types'; -import { - boolExpr, - callExpr, - comprehensionExpr, - extractIdent, - identExpr, - int64Expr, - listExpr, - selectExpr, -} from './utils'; export const STANDARD_MACROS = new Set([ HAS_MACRO, diff --git a/packages/cel/src/lib/parser-helper.spec.ts b/packages/cel/src/lib/parser/parser-helper.spec.ts similarity index 100% rename from packages/cel/src/lib/parser-helper.spec.ts rename to packages/cel/src/lib/parser/parser-helper.spec.ts diff --git a/packages/cel/src/lib/parser-helper.ts b/packages/cel/src/lib/parser/parser-helper.ts similarity index 95% rename from packages/cel/src/lib/parser-helper.ts rename to packages/cel/src/lib/parser/parser-helper.ts index 8d1e724..69f5756 100644 --- a/packages/cel/src/lib/parser-helper.ts +++ b/packages/cel/src/lib/parser/parser-helper.ts @@ -1,8 +1,12 @@ import { SourceInfoSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; import { create } from '@bufbuild/protobuf'; import { ParserRuleContext, Token } from 'antlr4'; -import { Location, OffsetRange } from './types'; -import { computeOffset, getLocationByOffset } from './utils'; +import { + Location, + OffsetRange, + computeOffset, + getLocationByOffset, +} from '../common/ast'; export class ParserHelper { #id = BigInt(1); diff --git a/packages/cel/src/lib/parser.spec.ts b/packages/cel/src/lib/parser/parser.spec.ts similarity index 99% rename from packages/cel/src/lib/parser.spec.ts rename to packages/cel/src/lib/parser/parser.spec.ts index 53dee31..0d563ac 100644 --- a/packages/cel/src/lib/parser.spec.ts +++ b/packages/cel/src/lib/parser/parser.spec.ts @@ -2,7 +2,25 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { isNil } from '@bearclaw/is'; import { Expr } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; -import { ACCUMULATOR_VAR } from './constants'; +import { Location } from '../common/ast'; +import { ACCUMULATOR_VAR } from '../common/constants'; +import { + boolExpr, + bytesExpr, + callExpr, + comprehensionExpr, + createStructFieldEntry, + createStructMapEntry, + doubleExpr, + identExpr, + int64Expr, + listExpr, + nullExpr, + selectExpr, + stringExpr, + structExpr, + uint64Expr, +} from '../common/utils'; import { ADD_OPERATOR, CONDITIONAL_OPERATOR, @@ -25,26 +43,8 @@ import { OPT_INDEX_OPERATOR, OPT_SELECT_OPERATOR, SUBTRACT_OPERATOR, -} from './operators'; +} from '../operators'; import { CELParser, CELParserOptions } from './parser'; -import { Location } from './types'; -import { - boolExpr, - bytesExpr, - callExpr, - comprehensionExpr, - createStructFieldEntry, - createStructMapEntry, - doubleExpr, - identExpr, - int64Expr, - listExpr, - nullExpr, - selectExpr, - stringExpr, - structExpr, - uint64Expr, -} from './utils'; interface TestInfo { // I contains the input expression to be parsed. diff --git a/packages/cel/src/lib/parser.ts b/packages/cel/src/lib/parser/parser.ts similarity index 98% rename from packages/cel/src/lib/parser.ts rename to packages/cel/src/lib/parser/parser.ts index 9cea32e..95b4375 100644 --- a/packages/cel/src/lib/parser.ts +++ b/packages/cel/src/lib/parser/parser.ts @@ -16,6 +16,7 @@ import { ParserRuleContext, Token, } from 'antlr4'; +import { Location, OffsetRange } from '../checker/types'; import { RESERVED_IDS, parseBytesConstant, @@ -23,10 +24,27 @@ import { parseIntConstant, parseStringConstant, parseUintConstant, -} from './constants'; -import { Errors, LexerErrorListener, ParserErrorListener } from './errors'; -import { ParseException } from './exceptions'; -import CELLexer from './gen/CELLexer'; +} from '../common/constants'; +import { + Errors, + LexerErrorListener, + ParserErrorListener, +} from '../common/errors'; +import { + boolExpr, + callExpr, + constExpr, + createStructFieldEntry, + createStructMapEntry, + identExpr, + listExpr, + nullExpr, + selectExpr, + stringExpr, + structExpr, +} from '../common/utils'; +import { ParseException } from '../exceptions'; +import CELLexer from '../gen/CELLexer'; import { BoolFalseContext, BoolTrueContext, @@ -60,10 +78,9 @@ import { StartContext, StringContext, UintContext, -} from './gen/CELParser'; -import { default as GeneratedCelVisitor } from './gen/CELVisitor'; -import { LogicManager } from './logic-manager'; -import { MacroError, expandMacro, findMacro } from './macros'; +} from '../gen/CELParser'; +import { default as GeneratedCelVisitor } from '../gen/CELVisitor'; +import { LogicManager } from '../logic-manager'; import { CONDITIONAL_OPERATOR, INDEX_OPERATOR, @@ -74,22 +91,9 @@ import { OPT_INDEX_OPERATOR, OPT_SELECT_OPERATOR, getOperatorFromText, -} from './operators'; +} from '../operators'; +import { MacroError, expandMacro, findMacro } from './macros'; import { ParserHelper } from './parser-helper'; -import { Location, OffsetRange } from './types'; -import { - boolExpr, - callExpr, - constExpr, - createStructFieldEntry, - createStructMapEntry, - identExpr, - listExpr, - nullExpr, - selectExpr, - stringExpr, - structExpr, -} from './utils'; export interface CELParserOptions { enableOptionalSyntax?: boolean; From 4caed4d0ea6bdacfe79734db0553d7cafa0a7b05 Mon Sep 17 00:00:00 2001 From: jafaircl Date: Tue, 22 Oct 2024 21:37:23 -0400 Subject: [PATCH 26/34] feat(cel): more organization & tweaks --- packages/cel/src/lib/checker/checker.ts | 48 +- .../cel/src/lib/common/types/bool.spec.ts | 50 ++ packages/cel/src/lib/common/types/bool.ts | 61 ++ .../cel/src/lib/common/types/bytes.spec.ts | 50 ++ packages/cel/src/lib/common/types/bytes.ts | 63 ++ .../cel/src/lib/common/types/call.spec.ts | 86 ++ packages/cel/src/lib/common/types/call.ts | 35 + .../lib/common/types/comprehension.spec.ts | 151 ++++ .../cel/src/lib/common/types/comprehension.ts | 35 + .../cel/src/lib/common/types/constant.spec.ts | 32 + packages/cel/src/lib/common/types/constant.ts | 33 + .../cel/src/lib/common/types/double.spec.ts | 50 ++ packages/cel/src/lib/common/types/double.ts | 64 ++ .../cel/src/lib/common/types/ident.spec.ts | 27 + packages/cel/src/lib/common/types/ident.ts | 35 + packages/cel/src/lib/common/types/int.spec.ts | 50 ++ packages/cel/src/lib/common/types/int.ts | 61 ++ .../cel/src/lib/common/types/list.spec.ts | 63 ++ packages/cel/src/lib/common/types/list.ts | 54 ++ .../cel/src/lib/common/types/null.spec.ts | 46 ++ packages/cel/src/lib/common/types/null.ts | 58 ++ .../cel/src/lib/common/types/select.spec.ts | 58 ++ packages/cel/src/lib/common/types/select.ts | 35 + .../cel/src/lib/common/types/string.spec.ts | 50 ++ packages/cel/src/lib/common/types/string.ts | 63 ++ .../cel/src/lib/common/types/struct.spec.ts | 161 ++++ packages/cel/src/lib/common/types/struct.ts | 113 +++ .../cel/src/lib/common/types/uint.spec.ts | 48 ++ packages/cel/src/lib/common/types/uint.ts | 61 ++ packages/cel/src/lib/common/utils.spec.ts | 737 +----------------- packages/cel/src/lib/common/utils.ts | 396 +--------- packages/cel/src/lib/logic-manager.ts | 2 +- packages/cel/src/lib/parser/macros.ts | 25 +- packages/cel/src/lib/parser/parser.spec.ts | 156 ++-- packages/cel/src/lib/parser/parser.ts | 43 +- 35 files changed, 1828 insertions(+), 1272 deletions(-) create mode 100644 packages/cel/src/lib/common/types/bool.spec.ts create mode 100644 packages/cel/src/lib/common/types/bytes.spec.ts create mode 100644 packages/cel/src/lib/common/types/call.spec.ts create mode 100644 packages/cel/src/lib/common/types/call.ts create mode 100644 packages/cel/src/lib/common/types/comprehension.spec.ts create mode 100644 packages/cel/src/lib/common/types/comprehension.ts create mode 100644 packages/cel/src/lib/common/types/constant.spec.ts create mode 100644 packages/cel/src/lib/common/types/constant.ts create mode 100644 packages/cel/src/lib/common/types/double.spec.ts create mode 100644 packages/cel/src/lib/common/types/ident.spec.ts create mode 100644 packages/cel/src/lib/common/types/ident.ts create mode 100644 packages/cel/src/lib/common/types/int.spec.ts create mode 100644 packages/cel/src/lib/common/types/list.spec.ts create mode 100644 packages/cel/src/lib/common/types/null.spec.ts create mode 100644 packages/cel/src/lib/common/types/select.spec.ts create mode 100644 packages/cel/src/lib/common/types/select.ts create mode 100644 packages/cel/src/lib/common/types/string.spec.ts create mode 100644 packages/cel/src/lib/common/types/struct.spec.ts create mode 100644 packages/cel/src/lib/common/types/struct.ts create mode 100644 packages/cel/src/lib/common/types/uint.spec.ts diff --git a/packages/cel/src/lib/checker/checker.ts b/packages/cel/src/lib/checker/checker.ts index 976db8f..b00fb59 100644 --- a/packages/cel/src/lib/checker/checker.ts +++ b/packages/cel/src/lib/checker/checker.ts @@ -4,7 +4,6 @@ import { isEmpty, isNil } from '@bearclaw/is'; import { CheckedExprSchema, Decl, - Decl_FunctionDecl, Decl_IdentDecl, Reference, Type, @@ -12,17 +11,14 @@ import { } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb'; import { Expr, - Expr_Call, - Expr_Comprehension, - Expr_CreateList, - Expr_CreateStruct, - Expr_Ident, - Expr_Select, ParsedExpr, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; import { create } from '@bufbuild/protobuf'; import { getLocationByOffset } from '../common/ast'; -import { functionReference } from '../common/decls/function-decl'; +import { + functionReference, + unwrapFunctionDecl, +} from '../common/decls/function-decl'; import { identDecl, identReference, @@ -31,12 +27,16 @@ import { import { Errors } from '../common/errors'; import { BOOL_TYPE } from '../common/types/bool'; import { BYTES_TYPE } from '../common/types/bytes'; +import { unwrapCallExpr } from '../common/types/call'; +import { unwrapComprehensionExpr } from '../common/types/comprehension'; +import { isConstExpr, unwrapConstExpr } from '../common/types/constant'; import { DOUBLE_TYPE } from '../common/types/double'; import { DYN_TYPE, isDynType } from '../common/types/dyn'; import { ERROR_TYPE } from '../common/types/error'; import { functionType } from '../common/types/function'; +import { unwrapIdentExpr } from '../common/types/ident'; import { INT64_TYPE } from '../common/types/int'; -import { listType } from '../common/types/list'; +import { listType, unwrapCreateList } from '../common/types/list'; import { mapType } from '../common/types/map'; import { NULL_TYPE } from '../common/types/null'; import { @@ -44,7 +44,9 @@ import { maybeUnwrapOptionalType, optionalType, } from '../common/types/optional'; +import { unwrapSelectExpr } from '../common/types/select'; import { STRING_TYPE } from '../common/types/string'; +import { unwrapStructExpr } from '../common/types/struct'; import { typeParamType } from '../common/types/type-param'; import { UINT64_TYPE } from '../common/types/uint'; import { isDynTypeOrErrorType } from '../common/types/utils'; @@ -147,7 +149,7 @@ export class CELChecker { } checkConstExpr(expr: Expr) { - if (expr.exprKind.case !== 'constExpr') { + if (!isConstExpr(expr)) { this.#errors.reportUnexpectedAstTypeError( expr.id, this.getLocationById(expr.id), @@ -157,7 +159,9 @@ export class CELChecker { this.setType(expr.id, ERROR_TYPE); return expr; } - switch (expr.exprKind.value.constantKind.case) { + 1; + const constant = unwrapConstExpr(expr)!; + switch (constant.constantKind.case) { case 'boolValue': this.setType(expr.id, BOOL_TYPE); break; @@ -190,7 +194,7 @@ export class CELChecker { expr.id, this.getLocationById(expr.id), 'constExpr', - expr.exprKind.value.constantKind.case! + constant.constantKind.case! ); this.setType(expr.id, ERROR_TYPE); break; @@ -199,7 +203,7 @@ export class CELChecker { } checkIdentExpr(expr: Expr) { - const identExpr = expr.exprKind.value as Expr_Ident; + const identExpr = unwrapIdentExpr(expr)!; const ident = this.env.lookupIdent(identExpr.name); if (!isNil(ident)) { const unwrapped = unwrapIdentDecl(ident)!; @@ -220,7 +224,7 @@ export class CELChecker { } checkSelect(expr: Expr) { - const sel = expr.exprKind.value as Expr_Select; + const sel = unwrapSelectExpr(expr)!; // Before traversing down the tree, try to interpret as qualified name. const qname = toQualifiedName(expr); if (!isNil(qname)) { @@ -255,7 +259,7 @@ export class CELChecker { // Note: similar logic exists within the `interpreter/planner.go`. If // making changes here please consider the impact on planner.go and // consolidate implementations or mirror code as appropriate. - const call = expr.exprKind.value as Expr_Call; + const call = unwrapCallExpr(expr)!; const fnName = call.function; if (fnName === OPT_SELECT_OPERATOR) { return this.checkOptSelect(expr); @@ -355,7 +359,7 @@ export class CELChecker { target: Expr | null, args: Expr[] ): OverloadResolution | null { - const fn = fnDecl.declKind.value as Decl_FunctionDecl; + const fn = unwrapFunctionDecl(fnDecl)!; const argTypes: Type[] = []; if (!isNil(target)) { const argType = this.getType(target.id); @@ -439,7 +443,7 @@ export class CELChecker { } checkCreateList(expr: Expr) { - const create = expr.exprKind.value as Expr_CreateList; + const create = unwrapCreateList(expr)!; let elemType: Type | undefined = undefined; for (let i = 0; i < create.elements.length; i++) { const e = create.elements[i]; @@ -455,7 +459,7 @@ export class CELChecker { } checkCreateStruct(expr: Expr) { - const struct = expr.exprKind.value as Expr_CreateStruct; + const struct = unwrapStructExpr(expr)!; if (!isEmpty(struct.messageName)) { return this.checkCreateMessage(expr); } @@ -463,7 +467,7 @@ export class CELChecker { } checkCreateMap(expr: Expr) { - const mapVal = expr.exprKind.value as Expr_CreateStruct; + const mapVal = unwrapStructExpr(expr)!; let keyType: Type | undefined = undefined; let valueType: Type | undefined = undefined; for (let i = 0; i < mapVal.entries.length; i++) { @@ -486,7 +490,7 @@ export class CELChecker { } checkCreateMessage(expr: Expr) { - const mapVal = expr.exprKind.value as Expr_CreateStruct; + const mapVal = unwrapStructExpr(expr)!; // Determine the type of the message. let messageType: Type = ERROR_TYPE; const decl = this.env.lookupIdent(mapVal.messageName); @@ -572,7 +576,7 @@ export class CELChecker { } checkComprehension(expr: Expr) { - const comp = expr.exprKind.value as Expr_Comprehension; + const comp = unwrapComprehensionExpr(expr)!; this.checkExpr(comp.iterRange); this.checkExpr(comp.accuInit); const accuType = this.getType(comp.accuInit!.id); @@ -634,7 +638,7 @@ export class CELChecker { checkOptSelect(expr: Expr) { // Collect metadata related to the opt select call packaged by the parser. - const call = expr.exprKind.value as Expr_Call; + const call = unwrapCallExpr(expr)!; const operand = call.args[0]; const field = call.args[1]; if ( diff --git a/packages/cel/src/lib/common/types/bool.spec.ts b/packages/cel/src/lib/common/types/bool.spec.ts new file mode 100644 index 0000000..5d7735c --- /dev/null +++ b/packages/cel/src/lib/common/types/bool.spec.ts @@ -0,0 +1,50 @@ +import { + ConstantSchema, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb'; +import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb'; +import { create } from '@bufbuild/protobuf'; +import { boolConstant, boolExpr, boolValue } from './bool'; + +describe('bool', () => { + it('boolConstant', () => { + expect(boolConstant(true)).toEqual( + create(ConstantSchema, { + constantKind: { + case: 'boolValue', + value: true, + }, + }) + ); + }); + + it('boolExpr', () => { + expect(boolExpr(BigInt(1), true)).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'boolValue', + value: true, + }, + }), + }, + }) + ); + }); + + it('boolValue', () => { + expect(boolValue(true)).toEqual( + create(ValueSchema, { + kind: { + case: 'boolValue', + value: true, + }, + }) + ); + }); + + // TODO: validations +}); diff --git a/packages/cel/src/lib/common/types/bool.ts b/packages/cel/src/lib/common/types/bool.ts index a526236..8eb262e 100644 --- a/packages/cel/src/lib/common/types/bool.ts +++ b/packages/cel/src/lib/common/types/bool.ts @@ -2,6 +2,18 @@ import { Type, Type_PrimitiveType, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { + Constant, + ConstantSchema, + Expr, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { + Value, + ValueSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { isConstExpr } from './constant'; import { primitiveType } from './primitive'; export const BOOL_TYPE = primitiveType(Type_PrimitiveType.BOOL); @@ -12,3 +24,52 @@ export function isBoolType(type: Type) { type.typeKind.value === Type_PrimitiveType.BOOL ); } + +export function boolConstant(value: boolean) { + return create(ConstantSchema, { + constantKind: { + case: 'boolValue', + value, + }, + }); +} + +export function isBoolConstant(constant: Constant): constant is Constant & { + constantKind: { case: 'boolValue'; value: boolean }; +} { + return constant.constantKind.case === 'boolValue'; +} + +export function boolExpr(id: bigint, value: boolean) { + return create(ExprSchema, { + id, + exprKind: { + case: 'constExpr', + value: boolConstant(value), + }, + }); +} + +export function isBoolExpr(expr: Expr): expr is Expr & { + exprKind: { + case: 'constExpr'; + value: Constant & { constantKind: { case: 'boolValue'; value: boolean } }; + }; +} { + return isConstExpr(expr) && isBoolConstant(expr.exprKind.value); +} + +export function boolValue(value: boolean) { + return create(ValueSchema, { + kind: { + case: 'boolValue', + value, + }, + }); +} + +export function isBoolValue(value: Value): value is Value & { + kind: { case: 'boolValue'; value: boolean }; +} { + return value.kind.case === 'boolValue'; +} diff --git a/packages/cel/src/lib/common/types/bytes.spec.ts b/packages/cel/src/lib/common/types/bytes.spec.ts new file mode 100644 index 0000000..445fc8b --- /dev/null +++ b/packages/cel/src/lib/common/types/bytes.spec.ts @@ -0,0 +1,50 @@ +import { + ConstantSchema, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb'; +import { create } from '@bufbuild/protobuf'; +import { bytesConstant, bytesExpr, bytesValue } from './bytes'; + +describe('bytes', () => { + it('bytesConstant', () => { + expect(bytesConstant(new Uint8Array([1, 2, 3]))).toEqual( + create(ConstantSchema, { + constantKind: { + case: 'bytesValue', + value: new Uint8Array([1, 2, 3]), + }, + }) + ); + }); + + it('bytesExpr', () => { + expect(bytesExpr(BigInt(1), new Uint8Array([1, 2, 3]))).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'bytesValue', + value: new Uint8Array([1, 2, 3]), + }, + }), + }, + }) + ); + }); + + it('bytesValue', () => { + expect(bytesValue(new Uint8Array([1, 2, 3]))).toEqual( + create(ValueSchema, { + kind: { + case: 'bytesValue', + value: new Uint8Array([1, 2, 3]), + }, + }) + ); + }); + + // TODO: validations +}); diff --git a/packages/cel/src/lib/common/types/bytes.ts b/packages/cel/src/lib/common/types/bytes.ts index e56563c..86cf642 100644 --- a/packages/cel/src/lib/common/types/bytes.ts +++ b/packages/cel/src/lib/common/types/bytes.ts @@ -2,6 +2,18 @@ import { Type, Type_PrimitiveType, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { + Constant, + ConstantSchema, + Expr, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { + Value, + ValueSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { isConstExpr } from './constant'; import { primitiveType } from './primitive'; export const BYTES_TYPE = primitiveType(Type_PrimitiveType.BYTES); @@ -12,3 +24,54 @@ export function isBytesType(val: Type) { val.typeKind.value === Type_PrimitiveType.BYTES ); } + +export function bytesConstant(value: Uint8Array) { + return create(ConstantSchema, { + constantKind: { + case: 'bytesValue', + value, + }, + }); +} + +export function isBytesConstant(constant: Constant): constant is Constant & { + constantKind: { case: 'bytesValue'; value: Uint8Array }; +} { + return constant.constantKind.case === 'bytesValue'; +} + +export function bytesExpr(id: bigint, value: Uint8Array) { + return create(ExprSchema, { + id, + exprKind: { + case: 'constExpr', + value: bytesConstant(value), + }, + }); +} + +export function isBytesExpr(expr: Expr): expr is Expr & { + exprKind: { + case: 'constExpr'; + value: Constant & { + constantKind: { case: 'bytesValue'; value: Uint8Array }; + }; + }; +} { + return isConstExpr(expr) && isBytesConstant(expr.exprKind.value); +} + +export function bytesValue(value: Uint8Array) { + return create(ValueSchema, { + kind: { + case: 'bytesValue', + value, + }, + }); +} + +export function isBytesValue(value: Value): value is Value & { + kind: { case: 'bytesValue'; value: Uint8Array }; +} { + return value.kind.case === 'bytesValue'; +} diff --git a/packages/cel/src/lib/common/types/call.spec.ts b/packages/cel/src/lib/common/types/call.spec.ts new file mode 100644 index 0000000..474af44 --- /dev/null +++ b/packages/cel/src/lib/common/types/call.spec.ts @@ -0,0 +1,86 @@ +import { + ConstantSchema, + ExprSchema, + Expr_CallSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { boolExpr } from './bool'; +import { callExpr, unwrapCallExpr } from './call'; +import { identExpr } from './ident'; + +describe('call', () => { + it('callExpr', () => { + expect( + callExpr(BigInt(1), { + function: 'a', + target: identExpr(BigInt(2), { name: 'b' }), + args: [boolExpr(BigInt(3), true)], + }) + ).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'callExpr', + value: { + function: 'a', + target: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }), + args: [ + create(ExprSchema, { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'boolValue', + value: true, + }, + }), + }, + }), + ], + }, + }, + }) + ); + }); + + it('unwrapCallExpr', () => { + const expr = callExpr(BigInt(1), { + function: 'a', + target: identExpr(BigInt(2), { name: 'b' }), + args: [boolExpr(BigInt(3), true)], + }); + expect(unwrapCallExpr(expr)).toEqual( + create(Expr_CallSchema, { + function: 'a', + target: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }), + args: [ + create(ExprSchema, { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'boolValue', + value: true, + }, + }), + }, + }), + ], + }) + ); + }); +}); diff --git a/packages/cel/src/lib/common/types/call.ts b/packages/cel/src/lib/common/types/call.ts new file mode 100644 index 0000000..4cb4b6f --- /dev/null +++ b/packages/cel/src/lib/common/types/call.ts @@ -0,0 +1,35 @@ +import { + Expr, + Expr_CallSchema, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { create, MessageInitShape } from '@bufbuild/protobuf'; + +export function callExpr( + id: bigint, + init: MessageInitShape +) { + return create(ExprSchema, { + id, + exprKind: { + case: 'callExpr', + value: init, + }, + }); +} + +export function isCallExpr(expr: Expr): expr is Expr & { + exprKind: { + case: 'callExpr'; + value: MessageInitShape; + }; +} { + return expr.exprKind.case === 'callExpr'; +} + +export function unwrapCallExpr(expr: Expr) { + if (isCallExpr(expr)) { + return expr.exprKind.value; + } + return null; +} diff --git a/packages/cel/src/lib/common/types/comprehension.spec.ts b/packages/cel/src/lib/common/types/comprehension.spec.ts new file mode 100644 index 0000000..6cce826 --- /dev/null +++ b/packages/cel/src/lib/common/types/comprehension.spec.ts @@ -0,0 +1,151 @@ +import { + ConstantSchema, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { boolExpr } from './bool'; +import { callExpr } from './call'; +import { comprehensionExpr } from './comprehension'; +import { identExpr } from './ident'; +import { int64Expr } from './int'; +import { listExpr } from './list'; + +describe('comprehansion', () => { + it('compreshensionExpr', () => { + const target = identExpr(BigInt(1), { name: 'a' }); + const accuInit = listExpr(BigInt(2), {}); + const condition = boolExpr(BigInt(3), true); + const stepArg0 = identExpr(BigInt(4), { name: 'b' }); + const stepArg1 = listExpr(BigInt(5), { + elements: [int64Expr(BigInt(6), BigInt(1))], + }); + const step = callExpr(BigInt(7), { + function: 'add', + args: [stepArg0, stepArg1], + }); + const resultArg0 = identExpr(BigInt(8), { name: 'b' }); + const resultArg1 = int64Expr(BigInt(9), BigInt(1)); + const result = callExpr(BigInt(10), { + function: 'equals', + args: [resultArg0, resultArg1], + }); + expect( + comprehensionExpr(BigInt(11), { + iterRange: target, + iterVar: 'a', + accuVar: 'b', + accuInit, + loopCondition: condition, + loopStep: step, + result, + }) + ).toEqual( + create(ExprSchema, { + id: BigInt(11), + exprKind: { + case: 'comprehensionExpr', + value: { + iterRange: create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }), + iterVar: 'a', + accuVar: 'b', + accuInit: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'listExpr', + value: {}, + }, + }), + loopCondition: create(ExprSchema, { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'boolValue', + value: true, + }, + }), + }, + }), + loopStep: create(ExprSchema, { + id: BigInt(7), + exprKind: { + case: 'callExpr', + value: { + function: 'add', + args: [ + create(ExprSchema, { + id: BigInt(4), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }), + create(ExprSchema, { + id: BigInt(5), + exprKind: { + case: 'listExpr', + value: { + elements: [ + create(ExprSchema, { + id: BigInt(6), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }), + }, + }), + ], + }, + }, + }), + ], + }, + }, + }), + result: create(ExprSchema, { + id: BigInt(10), + exprKind: { + case: 'callExpr', + value: { + function: 'equals', + args: [ + create(ExprSchema, { + id: BigInt(8), + exprKind: { + case: 'identExpr', + value: { name: 'b' }, + }, + }), + create(ExprSchema, { + id: BigInt(9), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }), + }, + }), + ], + }, + }, + }), + }, + }, + }) + ); + }); +}); diff --git a/packages/cel/src/lib/common/types/comprehension.ts b/packages/cel/src/lib/common/types/comprehension.ts new file mode 100644 index 0000000..5958b5e --- /dev/null +++ b/packages/cel/src/lib/common/types/comprehension.ts @@ -0,0 +1,35 @@ +import { + Expr, + Expr_ComprehensionSchema, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { create, MessageInitShape } from '@bufbuild/protobuf'; + +export function comprehensionExpr( + id: bigint, + init: MessageInitShape +) { + return create(ExprSchema, { + id, + exprKind: { + case: 'comprehensionExpr', + value: init, + }, + }); +} + +export function isComprehensionExpr(val: Expr): val is Expr & { + exprKind: { + case: 'comprehensionExpr'; + value: MessageInitShape; + }; +} { + return val.exprKind.case === 'comprehensionExpr'; +} + +export function unwrapComprehensionExpr(val: Expr) { + if (isComprehensionExpr(val)) { + return val.exprKind.value; + } + return null; +} diff --git a/packages/cel/src/lib/common/types/constant.spec.ts b/packages/cel/src/lib/common/types/constant.spec.ts new file mode 100644 index 0000000..eaa8871 --- /dev/null +++ b/packages/cel/src/lib/common/types/constant.spec.ts @@ -0,0 +1,32 @@ +import { + ConstantSchema, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { constExpr } from './constant'; + +describe('utils', () => { + it('constExpr', () => { + expect( + constExpr(BigInt(1), { + constantKind: { + case: 'boolValue', + value: true, + }, + }) + ).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'boolValue', + value: true, + }, + }), + }, + }) + ); + }); +}); diff --git a/packages/cel/src/lib/common/types/constant.ts b/packages/cel/src/lib/common/types/constant.ts new file mode 100644 index 0000000..c6b8d86 --- /dev/null +++ b/packages/cel/src/lib/common/types/constant.ts @@ -0,0 +1,33 @@ +import { + Constant, + ConstantSchema, + Expr, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { MessageInitShape, create } from '@bufbuild/protobuf'; + +export function constExpr( + id: bigint, + init: MessageInitShape +) { + return create(ExprSchema, { + id, + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, init), + }, + }); +} + +export function isConstExpr( + expr: Expr +): expr is Expr & { exprKind: { case: 'constExpr'; value: Constant } } { + return expr.exprKind.case === 'constExpr'; +} + +export function unwrapConstExpr(expr: Expr) { + if (isConstExpr(expr)) { + return expr.exprKind.value; + } + return null; +} diff --git a/packages/cel/src/lib/common/types/double.spec.ts b/packages/cel/src/lib/common/types/double.spec.ts new file mode 100644 index 0000000..00c197e --- /dev/null +++ b/packages/cel/src/lib/common/types/double.spec.ts @@ -0,0 +1,50 @@ +import { + ConstantSchema, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { doubleConstant, doubleExpr, doubleValue } from './double'; + +describe('double', () => { + it('doubleConstant', () => { + expect(doubleConstant(1.1)).toEqual( + create(ConstantSchema, { + constantKind: { + case: 'doubleValue', + value: 1.1, + }, + }) + ); + }); + + it('doubleExpr', () => { + expect(doubleExpr(BigInt(1), 1.1)).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'doubleValue', + value: 1.1, + }, + }), + }, + }) + ); + }); + + it('doubleValue', () => { + expect(doubleValue(1.1)).toEqual( + create(ValueSchema, { + kind: { + case: 'doubleValue', + value: 1.1, + }, + }) + ); + }); + + // TODO: validations +}); diff --git a/packages/cel/src/lib/common/types/double.ts b/packages/cel/src/lib/common/types/double.ts index 0ecc3b8..69fd461 100644 --- a/packages/cel/src/lib/common/types/double.ts +++ b/packages/cel/src/lib/common/types/double.ts @@ -2,6 +2,17 @@ import { Type, Type_PrimitiveType, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { + Constant, + ConstantSchema, + Expr, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { + Value, + ValueSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { create } from '@bufbuild/protobuf'; import { primitiveType } from './primitive'; export const DOUBLE_TYPE = primitiveType(Type_PrimitiveType.DOUBLE); @@ -21,3 +32,56 @@ export function unwrapDoubleType(val: Type) { } return null; } + +export function doubleConstant(value: number) { + return create(ConstantSchema, { + constantKind: { + case: 'doubleValue', + value, + }, + }); +} + +export function isDoubleConstant(constant: Constant): constant is Constant & { + constantKind: { case: 'doubleValue'; value: number }; +} { + return constant.constantKind.case === 'doubleValue'; +} + +export function doubleExpr(id: bigint, value: number) { + return create(ExprSchema, { + id, + exprKind: { + case: 'constExpr', + value: doubleConstant(value), + }, + }); +} + +export function isDoubleExpr(expr: Expr): expr is Expr & { + exprKind: { + case: 'constExpr'; + value: Constant & { + constantKind: { case: 'doubleValue'; value: number }; + }; + }; +} { + return ( + expr.exprKind.case === 'constExpr' && isDoubleConstant(expr.exprKind.value) + ); +} + +export function doubleValue(value: number) { + return create(ValueSchema, { + kind: { + case: 'doubleValue', + value, + }, + }); +} + +export function isDoubleValue(value: Value): value is Value & { + kind: { case: 'doubleValue'; value: number }; +} { + return value.kind.case === 'doubleValue'; +} diff --git a/packages/cel/src/lib/common/types/ident.spec.ts b/packages/cel/src/lib/common/types/ident.spec.ts new file mode 100644 index 0000000..fdedc0d --- /dev/null +++ b/packages/cel/src/lib/common/types/ident.spec.ts @@ -0,0 +1,27 @@ +import { + ExprSchema, + Expr_IdentSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb'; +import { create } from '@bufbuild/protobuf'; +import { identExpr, unwrapIdentExpr } from './ident'; + +describe('ident', () => { + it('identExpr', () => { + expect(identExpr(BigInt(1), { name: 'a' })).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }) + ); + }); + + it('unwrapIdentExpr', () => { + const expr = identExpr(BigInt(1), { name: 'a' }); + expect(unwrapIdentExpr(expr)).toEqual( + create(Expr_IdentSchema, { name: 'a' }) + ); + }); +}); diff --git a/packages/cel/src/lib/common/types/ident.ts b/packages/cel/src/lib/common/types/ident.ts new file mode 100644 index 0000000..d00a02d --- /dev/null +++ b/packages/cel/src/lib/common/types/ident.ts @@ -0,0 +1,35 @@ +import { + Expr, + Expr_IdentSchema, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { create, MessageInitShape } from '@bufbuild/protobuf'; + +export function identExpr( + id: bigint, + init: MessageInitShape +) { + return create(ExprSchema, { + id, + exprKind: { + case: 'identExpr', + value: init, + }, + }); +} + +export function isIdentExpr(expr: Expr): expr is Expr & { + exprKind: { + case: 'identExpr'; + value: MessageInitShape; + }; +} { + return expr.exprKind.case === 'identExpr'; +} + +export function unwrapIdentExpr(expr: Expr) { + if (isIdentExpr(expr)) { + return expr.exprKind.value; + } + return null; +} diff --git a/packages/cel/src/lib/common/types/int.spec.ts b/packages/cel/src/lib/common/types/int.spec.ts new file mode 100644 index 0000000..82fe1c5 --- /dev/null +++ b/packages/cel/src/lib/common/types/int.spec.ts @@ -0,0 +1,50 @@ +import { + ConstantSchema, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { int64Constant, int64Expr, int64Value } from './int'; + +describe('int', () => { + it('int64Constant', () => { + expect(int64Constant(BigInt(1))).toEqual( + create(ConstantSchema, { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }) + ); + }); + + it('int64Expr', () => { + expect(int64Expr(BigInt(1), BigInt(1))).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }), + }, + }) + ); + }); + + it('int64Value', () => { + expect(int64Value(BigInt(1))).toEqual( + create(ValueSchema, { + kind: { + case: 'int64Value', + value: BigInt(1), + }, + }) + ); + }); + + // TODO: validations +}); diff --git a/packages/cel/src/lib/common/types/int.ts b/packages/cel/src/lib/common/types/int.ts index 64f4eb2..4333867 100644 --- a/packages/cel/src/lib/common/types/int.ts +++ b/packages/cel/src/lib/common/types/int.ts @@ -2,6 +2,18 @@ import { Type, Type_PrimitiveType, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { + Constant, + ConstantSchema, + Expr, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { + Value, + ValueSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { isConstExpr } from './constant'; import { primitiveType } from './primitive'; export const INT64_TYPE = primitiveType(Type_PrimitiveType.INT64); @@ -21,3 +33,52 @@ export function unwrapInt64Type(val: Type) { } return null; } + +export function int64Constant(value: bigint) { + return create(ConstantSchema, { + constantKind: { + case: 'int64Value', + value, + }, + }); +} + +export function isInt64Constant(constant: Constant): constant is Constant & { + constantKind: { case: 'int64Value'; value: bigint }; +} { + return constant.constantKind.case === 'int64Value'; +} + +export function int64Expr(id: bigint, value: bigint) { + return create(ExprSchema, { + id, + exprKind: { + case: 'constExpr', + value: int64Constant(value), + }, + }); +} + +export function isInt64Expr(expr: Expr): expr is Expr & { + exprKind: { + case: 'constExpr'; + value: Constant & { constantKind: { case: 'int64Value'; value: bigint } }; + }; +} { + return isConstExpr(expr) && isInt64Constant(expr.exprKind.value); +} + +export function int64Value(value: bigint) { + return create(ValueSchema, { + kind: { + case: 'int64Value', + value, + }, + }); +} + +export function isInt64Value(value: Value): value is Value & { + kind: { case: 'int64Value'; value: bigint }; +} { + return value.kind.case === 'int64Value'; +} diff --git a/packages/cel/src/lib/common/types/list.spec.ts b/packages/cel/src/lib/common/types/list.spec.ts new file mode 100644 index 0000000..0936927 --- /dev/null +++ b/packages/cel/src/lib/common/types/list.spec.ts @@ -0,0 +1,63 @@ +import { + ConstantSchema, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb'; +import { create } from '@bufbuild/protobuf'; +import { int64Expr, int64Value } from './int'; +import { listExpr, listValue } from './list'; + +describe('list', () => { + it('listExpr', () => { + expect( + listExpr(BigInt(1), { + elements: [int64Expr(BigInt(2), BigInt(1))], + }) + ).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'listExpr', + value: { + elements: [ + create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }), + }, + }), + ], + }, + }, + }) + ); + }); + + it('listValue', () => { + expect(listValue({ values: [int64Value(BigInt(2))] })).toEqual( + create(ValueSchema, { + kind: { + case: 'listValue', + value: { + values: [ + create(ValueSchema, { + kind: { + case: 'int64Value', + value: BigInt(2), + }, + }), + ], + }, + }, + }) + ); + }); + + // TODO: validations +}); diff --git a/packages/cel/src/lib/common/types/list.ts b/packages/cel/src/lib/common/types/list.ts index 1a9aee8..361bc84 100644 --- a/packages/cel/src/lib/common/types/list.ts +++ b/packages/cel/src/lib/common/types/list.ts @@ -3,6 +3,16 @@ import { TypeSchema, Type_ListTypeSchema, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { + Expr, + ExprSchema, + Expr_CreateListSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { + ListValueSchema, + Value, + ValueSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; import { MessageInitShape, create } from '@bufbuild/protobuf'; export function listType(value: MessageInitShape) { @@ -29,3 +39,47 @@ export function unwrapListElemType(val: Type) { } return null; } + +export function listExpr( + id: bigint, + init: MessageInitShape +) { + return create(ExprSchema, { + id, + exprKind: { + case: 'listExpr', + value: init, + }, + }); +} + +export function isListExpr(val: Expr): val is Expr & { + exprKind: { + case: 'listExpr'; + value: MessageInitShape; + }; +} { + return val.exprKind.case === 'listExpr'; +} + +export function unwrapCreateList(val: Expr) { + if (isListExpr(val)) { + return val.exprKind.value; + } + return null; +} + +export function listValue(value: MessageInitShape) { + return create(ValueSchema, { + kind: { + case: 'listValue', + value, + }, + }); +} + +export function isListValue(val: Value): val is Value & { + kind: { case: 'listValue'; value: MessageInitShape }; +} { + return val.kind.case === 'listValue'; +} diff --git a/packages/cel/src/lib/common/types/null.spec.ts b/packages/cel/src/lib/common/types/null.spec.ts new file mode 100644 index 0000000..dea2ee3 --- /dev/null +++ b/packages/cel/src/lib/common/types/null.spec.ts @@ -0,0 +1,46 @@ +import { + ConstantSchema, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { NullValue } from '@bufbuild/protobuf/wkt'; +import { NULL_CONSTANT, NULL_VALUE, nullExpr } from './null'; + +describe('null', () => { + it('NULL_CONSTANT', () => { + expect(NULL_CONSTANT).toEqual( + create(ConstantSchema, { + constantKind: { + case: 'nullValue', + value: NullValue.NULL_VALUE, + }, + }) + ); + }); + + it('nullExpr', () => { + expect(nullExpr(BigInt(1))).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: NULL_CONSTANT, + }, + }) + ); + }); + + it('NULL_VALUE', () => { + expect(NULL_VALUE).toEqual( + create(ValueSchema, { + kind: { + case: 'nullValue', + value: NullValue.NULL_VALUE, + }, + }) + ); + }); + + // TODO: validations +}); diff --git a/packages/cel/src/lib/common/types/null.ts b/packages/cel/src/lib/common/types/null.ts index 0b3f29f..00c0bed 100644 --- a/packages/cel/src/lib/common/types/null.ts +++ b/packages/cel/src/lib/common/types/null.ts @@ -2,8 +2,19 @@ import { Type, TypeSchema, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { + Constant, + ConstantSchema, + Expr, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { + Value, + ValueSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; import { create } from '@bufbuild/protobuf'; import { NullValue } from '@bufbuild/protobuf/wkt'; +import { isConstExpr } from './constant'; export const NULL_TYPE = create(TypeSchema, { typeKind: { @@ -24,3 +35,50 @@ export function unwrapNullType(type: Type) { } return null; } + +export const NULL_CONSTANT = create(ConstantSchema, { + constantKind: { + case: 'nullValue', + value: NullValue.NULL_VALUE, + }, +}); + +export function isNullConstant(constant: Constant): constant is Constant & { + constantKind: { case: 'nullValue'; value: NullValue.NULL_VALUE }; +} { + return constant.constantKind.case === 'nullValue'; +} + +export function nullExpr(id: bigint) { + return create(ExprSchema, { + id, + exprKind: { + case: 'constExpr', + value: NULL_CONSTANT, + }, + }); +} + +export function isNullExpr(expr: Expr): expr is Expr & { + exprKind: { + case: 'constExpr'; + value: Constant & { + constantKind: { case: 'nullValue'; value: NullValue.NULL_VALUE }; + }; + }; +} { + return isConstExpr(expr) && isNullConstant(expr.exprKind.value); +} + +export const NULL_VALUE = create(ValueSchema, { + kind: { + case: 'nullValue', + value: NullValue.NULL_VALUE, + }, +}); + +export function isNullValue(value: Value): value is Value & { + kind: { case: 'nullValue'; value: NullValue.NULL_VALUE }; +} { + return value.kind.case === 'nullValue'; +} diff --git a/packages/cel/src/lib/common/types/select.spec.ts b/packages/cel/src/lib/common/types/select.spec.ts new file mode 100644 index 0000000..abd4692 --- /dev/null +++ b/packages/cel/src/lib/common/types/select.spec.ts @@ -0,0 +1,58 @@ +import { + ExprSchema, + Expr_SelectSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { identExpr } from './ident'; +import { selectExpr, unwrapSelectExpr } from './select'; + +describe('select', () => { + it('selectExpr', () => { + expect( + selectExpr(BigInt(1), { + operand: identExpr(BigInt(2), { name: 'a' }), + field: 'b', + testOnly: true, + }) + ).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'selectExpr', + value: { + operand: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }), + field: 'b', + testOnly: true, + }, + }, + }) + ); + }); + + it('unwrapSelectExpr', () => { + const expr = selectExpr(BigInt(1), { + operand: identExpr(BigInt(2), { name: 'a' }), + field: 'b', + testOnly: true, + }); + expect(unwrapSelectExpr(expr)).toEqual( + create(Expr_SelectSchema, { + field: 'b', + operand: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'identExpr', + value: { name: 'a' }, + }, + }), + testOnly: true, + }) + ); + }); +}); diff --git a/packages/cel/src/lib/common/types/select.ts b/packages/cel/src/lib/common/types/select.ts new file mode 100644 index 0000000..33d8bd2 --- /dev/null +++ b/packages/cel/src/lib/common/types/select.ts @@ -0,0 +1,35 @@ +import { + Expr, + Expr_SelectSchema, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb'; +import { create, MessageInitShape } from '@bufbuild/protobuf'; + +export function selectExpr( + id: bigint, + init: MessageInitShape +) { + return create(ExprSchema, { + id, + exprKind: { + case: 'selectExpr', + value: init, + }, + }); +} + +export function isSelectExpr(val: Expr): val is Expr & { + exprKind: { + case: 'selectExpr'; + value: MessageInitShape; + }; +} { + return val.exprKind.case === 'selectExpr'; +} + +export function unwrapSelectExpr(val: Expr) { + if (isSelectExpr(val)) { + return val.exprKind.value; + } + return null; +} diff --git a/packages/cel/src/lib/common/types/string.spec.ts b/packages/cel/src/lib/common/types/string.spec.ts new file mode 100644 index 0000000..356e307 --- /dev/null +++ b/packages/cel/src/lib/common/types/string.spec.ts @@ -0,0 +1,50 @@ +import { + ConstantSchema, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { stringConstant, stringExpr, stringValue } from './string'; + +describe('string', () => { + it('stringConstant', () => { + expect(stringConstant('hello')).toEqual( + create(ConstantSchema, { + constantKind: { + case: 'stringValue', + value: 'hello', + }, + }) + ); + }); + + it('stringExpr', () => { + expect(stringExpr(BigInt(1), 'hello')).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'stringValue', + value: 'hello', + }, + }), + }, + }) + ); + }); + + it('stringValue', () => { + expect(stringValue('hello')).toEqual( + create(ValueSchema, { + kind: { + case: 'stringValue', + value: 'hello', + }, + }) + ); + }); + + // TODO: validations +}); diff --git a/packages/cel/src/lib/common/types/string.ts b/packages/cel/src/lib/common/types/string.ts index 69e4b37..13f2613 100644 --- a/packages/cel/src/lib/common/types/string.ts +++ b/packages/cel/src/lib/common/types/string.ts @@ -2,6 +2,18 @@ import { Type, Type_PrimitiveType, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { + Constant, + ConstantSchema, + Expr, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { + Value, + ValueSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { isConstExpr } from './constant'; import { primitiveType } from './primitive'; export const STRING_TYPE = primitiveType(Type_PrimitiveType.STRING); @@ -21,3 +33,54 @@ export function unwrapStringType(val: Type) { } return null; } + +export function stringConstant(value: string) { + return create(ConstantSchema, { + constantKind: { + case: 'stringValue', + value, + }, + }); +} + +export function isStringConstant(constant: Constant): constant is Constant & { + constantKind: { case: 'stringValue'; value: string }; +} { + return constant.constantKind.case === 'stringValue'; +} + +export function stringExpr(id: bigint, value: string) { + return create(ExprSchema, { + id, + exprKind: { + case: 'constExpr', + value: stringConstant(value), + }, + }); +} + +export function isStringExpr(expr: Expr): expr is Expr & { + exprKind: { + case: 'constExpr'; + value: Constant & { + constantKind: { case: 'stringValue'; value: string }; + }; + }; +} { + return isConstExpr(expr) && isStringConstant(expr.exprKind.value); +} + +export function stringValue(value: string) { + return create(ValueSchema, { + kind: { + case: 'stringValue', + value, + }, + }); +} + +export function isStringValue(value: Value): value is Value & { + kind: { case: 'stringValue'; value: string }; +} { + return value.kind.case === 'stringValue'; +} diff --git a/packages/cel/src/lib/common/types/struct.spec.ts b/packages/cel/src/lib/common/types/struct.spec.ts new file mode 100644 index 0000000..d7e6bd2 --- /dev/null +++ b/packages/cel/src/lib/common/types/struct.spec.ts @@ -0,0 +1,161 @@ +import { + ConstantSchema, + ExprSchema, + Expr_CreateStruct_EntrySchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb'; +import { create } from '@bufbuild/protobuf'; +import { int64Expr } from './int'; +import { stringExpr } from './string'; +import { + structEntry, + structExpr, + structFieldEntry, + structMapEntry, +} from './struct'; + +describe('struct', () => { + it('structExpr', () => { + expect( + structExpr(BigInt(1), { + entries: [ + { + keyKind: { + case: 'fieldKey', + value: 'a', + }, + value: int64Expr(BigInt(2), BigInt(1)), + }, + ], + }) + ).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'structExpr', + value: { + entries: [ + { + keyKind: { + case: 'fieldKey', + value: 'a', + }, + value: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }), + }, + }), + }, + ], + }, + }, + }) + ); + }); + + it('createStructEntry', () => { + expect( + structEntry({ + id: BigInt(1), + keyKind: { + case: 'fieldKey', + value: 'a', + }, + value: int64Expr(BigInt(2), BigInt(1)), + }) + ).toEqual( + create(Expr_CreateStruct_EntrySchema, { + id: BigInt(1), + keyKind: { + case: 'fieldKey', + value: 'a', + }, + value: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }), + }, + }), + }) + ); + }); + + it('createStructFieldEntry', () => { + expect( + structFieldEntry(BigInt(1), 'a', int64Expr(BigInt(2), BigInt(1))) + ).toEqual( + create(Expr_CreateStruct_EntrySchema, { + id: BigInt(1), + keyKind: { + case: 'fieldKey', + value: 'a', + }, + value: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }), + }, + }), + }) + ); + }); + + it('createStructMapEntry', () => { + expect( + structMapEntry( + BigInt(1), + stringExpr(BigInt(2), 'a'), + int64Expr(BigInt(3), BigInt(1)) + ) + ).toEqual( + create(Expr_CreateStruct_EntrySchema, { + id: BigInt(1), + keyKind: { + case: 'mapKey', + value: create(ExprSchema, { + id: BigInt(2), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'stringValue', + value: 'a', + }, + }), + }, + }), + }, + value: create(ExprSchema, { + id: BigInt(3), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'int64Value', + value: BigInt(1), + }, + }), + }, + }), + }) + ); + }); +}); diff --git a/packages/cel/src/lib/common/types/struct.ts b/packages/cel/src/lib/common/types/struct.ts new file mode 100644 index 0000000..f945292 --- /dev/null +++ b/packages/cel/src/lib/common/types/struct.ts @@ -0,0 +1,113 @@ +import { + Expr, + Expr_CreateStruct_Entry, + Expr_CreateStruct_EntrySchema, + Expr_CreateStructSchema, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { create, MessageInitShape } from '@bufbuild/protobuf'; + +export function structExpr( + id: bigint, + init: MessageInitShape +) { + return create(ExprSchema, { + id, + exprKind: { + case: 'structExpr', + value: init, + }, + }); +} + +export function isStructExpr(expr: Expr): expr is Expr & { + exprKind: { + case: 'structExpr'; + value: MessageInitShape; + }; +} { + return expr.exprKind.case === 'structExpr'; +} + +export function unwrapStructExpr(expr: Expr) { + if (isStructExpr(expr)) { + return expr.exprKind.value; + } + return null; +} + +export function structEntry( + init: MessageInitShape +) { + return create(Expr_CreateStruct_EntrySchema, init); +} + +export function structFieldEntry( + id: bigint, + key: string, + value: Expr, + optionalEntry?: boolean +) { + return structEntry({ + id, + keyKind: { + case: 'fieldKey', + value: key, + }, + value, + optionalEntry: optionalEntry ?? false, + }); +} + +export function isStructFieldEntry( + entry: Expr_CreateStruct_Entry +): entry is Expr_CreateStruct_Entry & { + keyKind: { + case: 'fieldKey'; + value: string; + }; +} { + return entry.keyKind.case === 'fieldKey'; +} + +export function structMapEntry( + id: bigint, + key: Expr, + value: Expr, + optionalEntry?: boolean +) { + return structEntry({ + id, + keyKind: { + case: 'mapKey', + value: key, + }, + value, + optionalEntry: optionalEntry ?? false, + }); +} + +export function isStructMapEntry( + entry: Expr_CreateStruct_Entry +): entry is Expr_CreateStruct_Entry & { + keyKind: { + case: 'mapKey'; + value: Expr; + }; +} { + return entry.keyKind.case === 'mapKey'; +} + +export function isMessageStructExpr(expr: Expr) { + if (!isStructExpr(expr)) { + return false; + } + return expr.exprKind.value.entries.every(isStructFieldEntry); +} + +export function isMapStructExpr(expr: Expr) { + if (!isStructExpr(expr)) { + return false; + } + return expr.exprKind.value.entries.every(isStructMapEntry); +} diff --git a/packages/cel/src/lib/common/types/uint.spec.ts b/packages/cel/src/lib/common/types/uint.spec.ts new file mode 100644 index 0000000..7192948 --- /dev/null +++ b/packages/cel/src/lib/common/types/uint.spec.ts @@ -0,0 +1,48 @@ +import { + ConstantSchema, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { uint64Constant, uint64Expr, uint64Value } from './uint'; + +describe('uint', () => { + it('uint64Constant', () => { + expect(uint64Constant(BigInt(1))).toEqual( + create(ConstantSchema, { + constantKind: { + case: 'uint64Value', + value: BigInt(1), + }, + }) + ); + }); + + it('uint64Expr', () => { + expect(uint64Expr(BigInt(1), BigInt(1))).toEqual( + create(ExprSchema, { + id: BigInt(1), + exprKind: { + case: 'constExpr', + value: create(ConstantSchema, { + constantKind: { + case: 'uint64Value', + value: BigInt(1), + }, + }), + }, + }) + ); + }); + + it('uint64Value', () => { + expect(uint64Value(BigInt(1))).toEqual( + create(ValueSchema, { + kind: { + case: 'uint64Value', + value: BigInt(1), + }, + }) + ); + }); +}); diff --git a/packages/cel/src/lib/common/types/uint.ts b/packages/cel/src/lib/common/types/uint.ts index 584e879..1bd073b 100644 --- a/packages/cel/src/lib/common/types/uint.ts +++ b/packages/cel/src/lib/common/types/uint.ts @@ -2,6 +2,18 @@ import { Type, Type_PrimitiveType, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { + Constant, + ConstantSchema, + Expr, + ExprSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; +import { + Value, + ValueSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { isConstExpr } from './constant'; import { primitiveType } from './primitive'; export const UINT64_TYPE = primitiveType(Type_PrimitiveType.UINT64); @@ -21,3 +33,52 @@ export function unwrapUnit64Type(type: Type) { } return null; } + +export function uint64Constant(value: bigint) { + return create(ConstantSchema, { + constantKind: { + case: 'uint64Value', + value, + }, + }); +} + +export function isUint64Constant(constant: Constant): constant is Constant & { + constantKind: { case: 'uint64Value'; value: bigint }; +} { + return constant.constantKind.case === 'uint64Value'; +} + +export function uint64Expr(id: bigint, value: bigint) { + return create(ExprSchema, { + id, + exprKind: { + case: 'constExpr', + value: uint64Constant(value), + }, + }); +} + +export function isUint64Expr(expr: Expr): expr is Expr & { + exprKind: { + case: 'constExpr'; + value: Constant & { constantKind: { case: 'uint64Value'; value: bigint } }; + }; +} { + return isConstExpr(expr) && isUint64Constant(expr.exprKind.value); +} + +export function uint64Value(value: bigint) { + return create(ValueSchema, { + kind: { + case: 'uint64Value', + value, + }, + }); +} + +export function isUint64Value(value: Value): value is Value & { + kind: { case: 'uint64Value'; value: bigint }; +} { + return value.kind.case === 'uint64Value'; +} diff --git a/packages/cel/src/lib/common/utils.spec.ts b/packages/cel/src/lib/common/utils.spec.ts index 39b5064..410638a 100644 --- a/packages/cel/src/lib/common/utils.spec.ts +++ b/packages/cel/src/lib/common/utils.spec.ts @@ -1,745 +1,10 @@ -import { - ConstantSchema, - ExprSchema, - Expr_CreateStruct_EntrySchema, -} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; -import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; -import { create } from '@bufbuild/protobuf'; -import { NullValue } from '@bufbuild/protobuf/wkt'; -import { - NULL_CONSTANT, - NULL_VALUE, - boolConstant, - boolExpr, - boolValue, - bytesConstant, - bytesExpr, - bytesValue, - callExpr, - comprehensionExpr, - constExpr, - createStructEntry, - createStructFieldEntry, - createStructMapEntry, - doubleConstant, - doubleExpr, - doubleValue, - extractIdent, - identExpr, - int64Constant, - int64Expr, - int64Value, - listExpr, - nullExpr, - selectExpr, - stringConstant, - stringExpr, - stringValue, - structExpr, - uint64Constant, - uint64Expr, - uint64Value, - unquote, -} from './utils'; +import { unquote } from './utils'; describe('utils', () => { - it('constExpr', () => { - expect( - constExpr(BigInt(1), { - constantKind: { - case: 'boolValue', - value: true, - }, - }) - ).toEqual( - create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: create(ConstantSchema, { - constantKind: { - case: 'boolValue', - value: true, - }, - }), - }, - }) - ); - }); - - it('boolConstant', () => { - expect(boolConstant(true)).toEqual( - create(ConstantSchema, { - constantKind: { - case: 'boolValue', - value: true, - }, - }) - ); - }); - - it('boolExpr', () => { - expect(boolExpr(BigInt(1), true)).toEqual( - create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: create(ConstantSchema, { - constantKind: { - case: 'boolValue', - value: true, - }, - }), - }, - }) - ); - }); - - it('boolValue', () => { - expect(boolValue(true)).toEqual( - create(ValueSchema, { - kind: { - case: 'boolValue', - value: true, - }, - }) - ); - }); - - it('int64Constant', () => { - expect(int64Constant(BigInt(1))).toEqual( - create(ConstantSchema, { - constantKind: { - case: 'int64Value', - value: BigInt(1), - }, - }) - ); - }); - - it('int64Expr', () => { - expect(int64Expr(BigInt(1), BigInt(1))).toEqual( - create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: create(ConstantSchema, { - constantKind: { - case: 'int64Value', - value: BigInt(1), - }, - }), - }, - }) - ); - }); - - it('int64Value', () => { - expect(int64Value(BigInt(1))).toEqual( - create(ValueSchema, { - kind: { - case: 'int64Value', - value: BigInt(1), - }, - }) - ); - }); - - it('uint64Constant', () => { - expect(uint64Constant(BigInt(1))).toEqual( - create(ConstantSchema, { - constantKind: { - case: 'uint64Value', - value: BigInt(1), - }, - }) - ); - }); - - it('uint64Expr', () => { - expect(uint64Expr(BigInt(1), BigInt(1))).toEqual( - create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: create(ConstantSchema, { - constantKind: { - case: 'uint64Value', - value: BigInt(1), - }, - }), - }, - }) - ); - }); - - it('uint64Value', () => { - expect(uint64Value(BigInt(1))).toEqual( - create(ValueSchema, { - kind: { - case: 'uint64Value', - value: BigInt(1), - }, - }) - ); - }); - - it('doubleConstant', () => { - expect(doubleConstant(1.1)).toEqual( - create(ConstantSchema, { - constantKind: { - case: 'doubleValue', - value: 1.1, - }, - }) - ); - }); - - it('doubleExpr', () => { - expect(doubleExpr(BigInt(1), 1.1)).toEqual( - create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: create(ConstantSchema, { - constantKind: { - case: 'doubleValue', - value: 1.1, - }, - }), - }, - }) - ); - }); - - it('doubleValue', () => { - expect(doubleValue(1.1)).toEqual( - create(ValueSchema, { - kind: { - case: 'doubleValue', - value: 1.1, - }, - }) - ); - }); - - it('stringConstant', () => { - expect(stringConstant('hello')).toEqual( - create(ConstantSchema, { - constantKind: { - case: 'stringValue', - value: 'hello', - }, - }) - ); - }); - - it('stringExpr', () => { - expect(stringExpr(BigInt(1), 'hello')).toEqual( - create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: create(ConstantSchema, { - constantKind: { - case: 'stringValue', - value: 'hello', - }, - }), - }, - }) - ); - }); - - it('stringValue', () => { - expect(stringValue('hello')).toEqual( - create(ValueSchema, { - kind: { - case: 'stringValue', - value: 'hello', - }, - }) - ); - }); - - it('bytesConstant', () => { - expect(bytesConstant(new Uint8Array([1, 2, 3]))).toEqual( - create(ConstantSchema, { - constantKind: { - case: 'bytesValue', - value: new Uint8Array([1, 2, 3]), - }, - }) - ); - }); - - it('bytesExpr', () => { - expect(bytesExpr(BigInt(1), new Uint8Array([1, 2, 3]))).toEqual( - create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: create(ConstantSchema, { - constantKind: { - case: 'bytesValue', - value: new Uint8Array([1, 2, 3]), - }, - }), - }, - }) - ); - }); - - it('bytesValue', () => { - expect(bytesValue(new Uint8Array([1, 2, 3]))).toEqual( - create(ValueSchema, { - kind: { - case: 'bytesValue', - value: new Uint8Array([1, 2, 3]), - }, - }) - ); - }); - - it('NULL_CONSTANT', () => { - expect(NULL_CONSTANT).toEqual( - create(ConstantSchema, { - constantKind: { - case: 'nullValue', - value: NullValue.NULL_VALUE, - }, - }) - ); - }); - - it('nullExpr', () => { - expect(nullExpr(BigInt(1))).toEqual( - create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'constExpr', - value: NULL_CONSTANT, - }, - }) - ); - }); - - it('NULL_VALUE', () => { - expect(NULL_VALUE).toEqual( - create(ValueSchema, { - kind: { - case: 'nullValue', - value: NullValue.NULL_VALUE, - }, - }) - ); - }); - - it('identExpr', () => { - expect(identExpr(BigInt(1), { name: 'a' })).toEqual( - create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }) - ); - }); - - it('callExpr', () => { - expect( - callExpr(BigInt(1), { - function: 'a', - target: identExpr(BigInt(2), { name: 'b' }), - args: [boolExpr(BigInt(3), true)], - }) - ).toEqual( - create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'callExpr', - value: { - function: 'a', - target: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }), - args: [ - create(ExprSchema, { - id: BigInt(3), - exprKind: { - case: 'constExpr', - value: create(ConstantSchema, { - constantKind: { - case: 'boolValue', - value: true, - }, - }), - }, - }), - ], - }, - }, - }) - ); - }); - - it('listExpr', () => { - expect( - listExpr(BigInt(1), { - elements: [int64Expr(BigInt(2), BigInt(1))], - }) - ).toEqual( - create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'listExpr', - value: { - elements: [ - create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'constExpr', - value: create(ConstantSchema, { - constantKind: { - case: 'int64Value', - value: BigInt(1), - }, - }), - }, - }), - ], - }, - }, - }) - ); - }); - - it('selectExpr', () => { - expect( - selectExpr(BigInt(1), { - operand: identExpr(BigInt(2), { name: 'a' }), - field: 'b', - testOnly: true, - }) - ).toEqual( - create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'selectExpr', - value: { - operand: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }), - field: 'b', - testOnly: true, - }, - }, - }) - ); - }); - - it('structExpr', () => { - expect( - structExpr(BigInt(1), { - entries: [ - { - keyKind: { - case: 'fieldKey', - value: 'a', - }, - value: int64Expr(BigInt(2), BigInt(1)), - }, - ], - }) - ).toEqual( - create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'structExpr', - value: { - entries: [ - { - keyKind: { - case: 'fieldKey', - value: 'a', - }, - value: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'constExpr', - value: create(ConstantSchema, { - constantKind: { - case: 'int64Value', - value: BigInt(1), - }, - }), - }, - }), - }, - ], - }, - }, - }) - ); - }); - - it('createStructEntry', () => { - expect( - createStructEntry(BigInt(1), { - keyKind: { - case: 'fieldKey', - value: 'a', - }, - value: int64Expr(BigInt(2), BigInt(1)), - }) - ).toEqual( - create(Expr_CreateStruct_EntrySchema, { - id: BigInt(1), - keyKind: { - case: 'fieldKey', - value: 'a', - }, - value: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'constExpr', - value: create(ConstantSchema, { - constantKind: { - case: 'int64Value', - value: BigInt(1), - }, - }), - }, - }), - }) - ); - }); - - it('createStructFieldEntry', () => { - expect( - createStructFieldEntry(BigInt(1), { - key: 'a', - value: int64Expr(BigInt(2), BigInt(1)), - }) - ).toEqual( - create(Expr_CreateStruct_EntrySchema, { - id: BigInt(1), - keyKind: { - case: 'fieldKey', - value: 'a', - }, - value: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'constExpr', - value: create(ConstantSchema, { - constantKind: { - case: 'int64Value', - value: BigInt(1), - }, - }), - }, - }), - }) - ); - }); - - it('createStructMapEntry', () => { - expect( - createStructMapEntry(BigInt(1), { - key: stringExpr(BigInt(2), 'a'), - value: int64Expr(BigInt(3), BigInt(1)), - }) - ).toEqual( - create(Expr_CreateStruct_EntrySchema, { - id: BigInt(1), - keyKind: { - case: 'mapKey', - value: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'constExpr', - value: create(ConstantSchema, { - constantKind: { - case: 'stringValue', - value: 'a', - }, - }), - }, - }), - }, - value: create(ExprSchema, { - id: BigInt(3), - exprKind: { - case: 'constExpr', - value: create(ConstantSchema, { - constantKind: { - case: 'int64Value', - value: BigInt(1), - }, - }), - }, - }), - }) - ); - }); - - it('compreshensionExpr', () => { - const target = identExpr(BigInt(1), { name: 'a' }); - const accuInit = listExpr(BigInt(2), {}); - const condition = boolExpr(BigInt(3), true); - const stepArg0 = identExpr(BigInt(4), { name: 'b' }); - const stepArg1 = listExpr(BigInt(5), { - elements: [int64Expr(BigInt(6), BigInt(1))], - }); - const step = callExpr(BigInt(7), { - function: 'add', - args: [stepArg0, stepArg1], - }); - const resultArg0 = identExpr(BigInt(8), { name: 'b' }); - const resultArg1 = int64Expr(BigInt(9), BigInt(1)); - const result = callExpr(BigInt(10), { - function: 'equals', - args: [resultArg0, resultArg1], - }); - expect( - comprehensionExpr(BigInt(11), { - iterRange: target, - iterVar: 'a', - accuVar: 'b', - accuInit, - loopCondition: condition, - loopStep: step, - result, - }) - ).toEqual( - create(ExprSchema, { - id: BigInt(11), - exprKind: { - case: 'comprehensionExpr', - value: { - iterRange: create(ExprSchema, { - id: BigInt(1), - exprKind: { - case: 'identExpr', - value: { name: 'a' }, - }, - }), - iterVar: 'a', - accuVar: 'b', - accuInit: create(ExprSchema, { - id: BigInt(2), - exprKind: { - case: 'listExpr', - value: {}, - }, - }), - loopCondition: create(ExprSchema, { - id: BigInt(3), - exprKind: { - case: 'constExpr', - value: create(ConstantSchema, { - constantKind: { - case: 'boolValue', - value: true, - }, - }), - }, - }), - loopStep: create(ExprSchema, { - id: BigInt(7), - exprKind: { - case: 'callExpr', - value: { - function: 'add', - args: [ - create(ExprSchema, { - id: BigInt(4), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }), - create(ExprSchema, { - id: BigInt(5), - exprKind: { - case: 'listExpr', - value: { - elements: [ - create(ExprSchema, { - id: BigInt(6), - exprKind: { - case: 'constExpr', - value: create(ConstantSchema, { - constantKind: { - case: 'int64Value', - value: BigInt(1), - }, - }), - }, - }), - ], - }, - }, - }), - ], - }, - }, - }), - result: create(ExprSchema, { - id: BigInt(10), - exprKind: { - case: 'callExpr', - value: { - function: 'equals', - args: [ - create(ExprSchema, { - id: BigInt(8), - exprKind: { - case: 'identExpr', - value: { name: 'b' }, - }, - }), - create(ExprSchema, { - id: BigInt(9), - exprKind: { - case: 'constExpr', - value: create(ConstantSchema, { - constantKind: { - case: 'int64Value', - value: BigInt(1), - }, - }), - }, - }), - ], - }, - }, - }), - }, - }, - }) - ); - }); - it('unquote', () => { expect(unquote('a')).toEqual('a'); expect(unquote('"a"')).toEqual('a'); expect(unquote("'a'")).toEqual('a'); expect(unquote('`a`')).toEqual('a'); }); - - it('extractIdent', () => { - expect(extractIdent(identExpr(BigInt(1), { name: 'a' }))).toEqual('a'); - expect(extractIdent(int64Expr(BigInt(1), BigInt(1)))).toEqual(null); - }); }); diff --git a/packages/cel/src/lib/common/utils.ts b/packages/cel/src/lib/common/utils.ts index 965c6be..0e10477 100644 --- a/packages/cel/src/lib/common/utils.ts +++ b/packages/cel/src/lib/common/utils.ts @@ -2,394 +2,7 @@ /* eslint-disable no-case-declarations */ /* eslint-disable @typescript-eslint/no-unused-vars */ import { isNil } from '@bearclaw/is'; -import { - ConstantSchema, - Expr, - ExprSchema, - Expr_CallSchema, - Expr_ComprehensionSchema, - Expr_CreateListSchema, - Expr_CreateStructSchema, - Expr_CreateStruct_EntrySchema, - Expr_IdentSchema, - Expr_SelectSchema, -} from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; -import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; -import { MessageInitShape, create } from '@bufbuild/protobuf'; -import { NullValue } from '@bufbuild/protobuf/wkt'; - -export function parseString(str: string) { - const decoded = decodeURIComponent(str); - return decoded.replace(/\\([abfnrtv'"\\])/g, '$1'); -} - -export function parseBytes(str: string) { - // Remove double escapes from the string - str = parseString(str); - // Match octal or hexadecimal numbers - const octalOrHexadecimalNumbers = str.match( - /\\[0-7]{1,3}|\\x[0-9a-fA-F]{2}/g - ); - if (octalOrHexadecimalNumbers) { - const uint8Array = new Uint8Array(octalOrHexadecimalNumbers.length); - for (let i = 0; i < octalOrHexadecimalNumbers.length; i++) { - const octalOrHexadecimalNumber = octalOrHexadecimalNumbers[i]; - if (octalOrHexadecimalNumber.startsWith('\\x')) { - uint8Array[i] = parseInt(octalOrHexadecimalNumber.slice(2), 16); - } else { - uint8Array[i] = parseInt(octalOrHexadecimalNumber.slice(1), 8); - } - } - return uint8Array; - } - return new TextEncoder().encode(str); -} - -export function parseInt64(str: string) { - const decoded = decodeURIComponent(str); - if (decoded.startsWith('-')) { - return -BigInt(decoded.slice(1)); - } - return BigInt(decoded); -} - -export function constExpr( - id: bigint, - init: MessageInitShape -) { - return create(ExprSchema, { - id, - exprKind: { - case: 'constExpr', - value: create(ConstantSchema, init), - }, - }); -} - -export function boolConstant(value: boolean) { - return create(ConstantSchema, { - constantKind: { - case: 'boolValue', - value, - }, - }); -} - -export function boolExpr(id: bigint, value: boolean) { - return create(ExprSchema, { - id, - exprKind: { - case: 'constExpr', - value: boolConstant(value), - }, - }); -} - -export function boolValue(value: boolean) { - return create(ValueSchema, { - kind: { - case: 'boolValue', - value, - }, - }); -} - -export function int64Constant(value: bigint) { - return create(ConstantSchema, { - constantKind: { - case: 'int64Value', - value, - }, - }); -} - -export function int64Expr(id: bigint, value: bigint) { - return create(ExprSchema, { - id, - exprKind: { - case: 'constExpr', - value: int64Constant(value), - }, - }); -} - -export function int64Value(value: bigint) { - return create(ValueSchema, { - kind: { - case: 'int64Value', - value, - }, - }); -} - -export function uint64Constant(value: bigint) { - return create(ConstantSchema, { - constantKind: { - case: 'uint64Value', - value, - }, - }); -} - -export function uint64Expr(id: bigint, value: bigint) { - return create(ExprSchema, { - id, - exprKind: { - case: 'constExpr', - value: uint64Constant(value), - }, - }); -} - -export function uint64Value(value: bigint) { - return create(ValueSchema, { - kind: { - case: 'uint64Value', - value, - }, - }); -} - -export function doubleConstant(value: number) { - return create(ConstantSchema, { - constantKind: { - case: 'doubleValue', - value, - }, - }); -} - -export function doubleExpr(id: bigint, value: number) { - return create(ExprSchema, { - id, - exprKind: { - case: 'constExpr', - value: doubleConstant(value), - }, - }); -} - -export function doubleValue(value: number) { - return create(ValueSchema, { - kind: { - case: 'doubleValue', - value, - }, - }); -} - -export function stringConstant(value: string) { - return create(ConstantSchema, { - constantKind: { - case: 'stringValue', - value, - }, - }); -} - -export function stringExpr(id: bigint, value: string) { - return create(ExprSchema, { - id, - exprKind: { - case: 'constExpr', - value: stringConstant(value), - }, - }); -} - -export function stringValue(value: string) { - return create(ValueSchema, { - kind: { - case: 'stringValue', - value, - }, - }); -} - -export function bytesConstant(value: Uint8Array) { - return create(ConstantSchema, { - constantKind: { - case: 'bytesValue', - value, - }, - }); -} - -export function bytesExpr(id: bigint, value: Uint8Array) { - return create(ExprSchema, { - id, - exprKind: { - case: 'constExpr', - value: bytesConstant(value), - }, - }); -} - -export function bytesValue(value: Uint8Array) { - return create(ValueSchema, { - kind: { - case: 'bytesValue', - value, - }, - }); -} - -export const NULL_CONSTANT = create(ConstantSchema, { - constantKind: { - case: 'nullValue', - value: NullValue.NULL_VALUE, - }, -}); - -export function nullExpr(id: bigint) { - return create(ExprSchema, { - id, - exprKind: { - case: 'constExpr', - value: NULL_CONSTANT, - }, - }); -} - -export const NULL_VALUE = create(ValueSchema, { - kind: { - case: 'nullValue', - value: NullValue.NULL_VALUE, - }, -}); - -export function identExpr( - id: bigint, - init: MessageInitShape -) { - return create(ExprSchema, { - id, - exprKind: { - case: 'identExpr', - value: init, - }, - }); -} - -export function callExpr( - id: bigint, - init: MessageInitShape -) { - return create(ExprSchema, { - id, - exprKind: { - case: 'callExpr', - value: init, - }, - }); -} - -export function listExpr( - id: bigint, - init: MessageInitShape -) { - return create(ExprSchema, { - id, - exprKind: { - case: 'listExpr', - value: init, - }, - }); -} - -export function selectExpr( - id: bigint, - init: MessageInitShape -) { - return create(ExprSchema, { - id, - exprKind: { - case: 'selectExpr', - value: init, - }, - }); -} - -export function structExpr( - id: bigint, - init: MessageInitShape -) { - return create(ExprSchema, { - id, - exprKind: { - case: 'structExpr', - value: init, - }, - }); -} - -export function createStructEntry( - id: bigint, - init: MessageInitShape -) { - return create(Expr_CreateStruct_EntrySchema, { - id, - ...init, - }); -} - -export function createStructFieldEntry( - id: bigint, - init: { - key: string; - value: Expr; - optionalEntry?: boolean; - } -) { - return createStructEntry(id, { - keyKind: { - case: 'fieldKey', - value: init.key, - }, - value: init.value, - optionalEntry: init.optionalEntry ?? false, - }); -} - -export function createStructMapEntry( - id: bigint, - init: { - key: Expr; - value: Expr; - optionalEntry?: boolean; - } -) { - return createStructEntry(id, { - keyKind: { - case: 'mapKey', - value: init.key, - }, - value: init.value, - optionalEntry: init.optionalEntry ?? false, - }); -} - -export function isMapExpr(expr: Expr) { - if (expr.exprKind.case !== 'structExpr') { - return false; - } - return expr.exprKind.value.entries.some( - (entry) => entry.keyKind.case === 'mapKey' - ); -} - -export function comprehensionExpr( - id: bigint, - init: MessageInitShape -) { - return create(ExprSchema, { - id, - exprKind: { - case: 'comprehensionExpr', - value: init, - }, - }); -} +import { Expr } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; export function unquote(str: string) { const reg = /['"`]/; @@ -405,13 +18,6 @@ export function unquote(str: string) { return str; } -export function extractIdent(expr: Expr): string | null { - if (expr.exprKind.case !== 'identExpr') { - return null; - } - return expr.exprKind.value.name; -} - export function mapToObject( map: Map ) { diff --git a/packages/cel/src/lib/logic-manager.ts b/packages/cel/src/lib/logic-manager.ts index b762aeb..cc10f0c 100644 --- a/packages/cel/src/lib/logic-manager.ts +++ b/packages/cel/src/lib/logic-manager.ts @@ -1,5 +1,5 @@ import { Expr } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; -import { callExpr } from './common/utils'; +import { callExpr } from './common/types/call'; export class LogicManager { private function: string; diff --git a/packages/cel/src/lib/parser/macros.ts b/packages/cel/src/lib/parser/macros.ts index f3d8365..9b9982c 100644 --- a/packages/cel/src/lib/parser/macros.ts +++ b/packages/cel/src/lib/parser/macros.ts @@ -4,16 +4,13 @@ import { Expr } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; import { ParserRuleContext, Token } from 'antlr4'; import { Location, OffsetRange } from '../common/ast'; import { ACCUMULATOR_VAR } from '../common/constants'; -import { - boolExpr, - callExpr, - comprehensionExpr, - extractIdent, - identExpr, - int64Expr, - listExpr, - selectExpr, -} from '../common/utils'; +import { boolExpr } from '../common/types/bool'; +import { callExpr } from '../common/types/call'; +import { comprehensionExpr } from '../common/types/comprehension'; +import { identExpr, unwrapIdentExpr } from '../common/types/ident'; +import { int64Expr } from '../common/types/int'; +import { listExpr } from '../common/types/list'; +import { selectExpr } from '../common/types/select'; import { ADD_OPERATOR, ALL_MACRO, @@ -209,7 +206,7 @@ export function expandMapMacro( target: Expr, args: Expr[] ): Expr { - const v = extractIdent(args[0]); + const v = unwrapIdentExpr(args[0]); if (isNil(v)) { throw new MacroError('argument is not an identifier', ctx, args[0]); } @@ -239,7 +236,7 @@ export function expandMapMacro( const result = identExpr(helper.nextId(ctx), { name: ACCUMULATOR_VAR }); return comprehensionExpr(helper.nextId(ctx), { iterRange: target, - iterVar: v, + iterVar: v.name, accuVar: ACCUMULATOR_VAR, accuInit: init, loopCondition: condition, @@ -254,7 +251,7 @@ export function expandFilterMacro( target: Expr, args: Expr[] ): Expr { - const v = extractIdent(args[0]); + const v = unwrapIdentExpr(args[0]); if (isNil(v)) { throw new MacroError('argument is not an identifier', ctx, args[0]); } @@ -275,7 +272,7 @@ export function expandFilterMacro( const result = identExpr(helper.nextId(ctx), { name: ACCUMULATOR_VAR }); return comprehensionExpr(helper.nextId(ctx), { iterRange: target, - iterVar: v, + iterVar: v.name, accuVar: ACCUMULATOR_VAR, accuInit: listInit, loopCondition: condition, diff --git a/packages/cel/src/lib/parser/parser.spec.ts b/packages/cel/src/lib/parser/parser.spec.ts index 0d563ac..46931d5 100644 --- a/packages/cel/src/lib/parser/parser.spec.ts +++ b/packages/cel/src/lib/parser/parser.spec.ts @@ -4,23 +4,23 @@ import { isNil } from '@bearclaw/is'; import { Expr } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; import { Location } from '../common/ast'; import { ACCUMULATOR_VAR } from '../common/constants'; +import { boolExpr } from '../common/types/bool'; +import { bytesExpr } from '../common/types/bytes'; +import { callExpr } from '../common/types/call'; +import { comprehensionExpr } from '../common/types/comprehension'; +import { doubleExpr } from '../common/types/double'; +import { identExpr } from '../common/types/ident'; +import { int64Expr } from '../common/types/int'; +import { listExpr } from '../common/types/list'; +import { nullExpr } from '../common/types/null'; +import { selectExpr } from '../common/types/select'; +import { stringExpr } from '../common/types/string'; import { - boolExpr, - bytesExpr, - callExpr, - comprehensionExpr, - createStructFieldEntry, - createStructMapEntry, - doubleExpr, - identExpr, - int64Expr, - listExpr, - nullExpr, - selectExpr, - stringExpr, structExpr, - uint64Expr, -} from '../common/utils'; + structFieldEntry, + structMapEntry, +} from '../common/types/struct'; +import { uint64Expr } from '../common/types/uint'; import { ADD_OPERATOR, CONDITIONAL_OPERATOR, @@ -644,10 +644,7 @@ const testCases: TestInfo[] = [ P: structExpr(BigInt(1), { messageName: 'foo', entries: [ - createStructFieldEntry(BigInt(2), { - key: 'a', - value: identExpr(BigInt(3), { name: 'b' }), - }), + structFieldEntry(BigInt(2), 'a', identExpr(BigInt(3), { name: 'b' })), ], }), }, @@ -660,14 +657,8 @@ const testCases: TestInfo[] = [ P: structExpr(BigInt(1), { messageName: 'foo', entries: [ - createStructFieldEntry(BigInt(2), { - key: 'a', - value: identExpr(BigInt(3), { name: 'b' }), - }), - createStructFieldEntry(BigInt(4), { - key: 'c', - value: identExpr(BigInt(5), { name: 'd' }), - }), + structFieldEntry(BigInt(2), 'a', identExpr(BigInt(3), { name: 'b' })), + structFieldEntry(BigInt(4), 'c', identExpr(BigInt(5), { name: 'd' })), ], }), }, @@ -684,14 +675,16 @@ const testCases: TestInfo[] = [ // }^#1:*expr.Expr_StructExpr#`, P: structExpr(BigInt(1), { entries: [ - createStructMapEntry(BigInt(2), { - key: identExpr(BigInt(3), { name: 'a' }), - value: identExpr(BigInt(4), { name: 'b' }), - }), - createStructMapEntry(BigInt(5), { - key: identExpr(BigInt(6), { name: 'c' }), - value: identExpr(BigInt(7), { name: 'd' }), - }), + structMapEntry( + BigInt(2), + identExpr(BigInt(3), { name: 'a' }), + identExpr(BigInt(4), { name: 'b' }) + ), + structMapEntry( + BigInt(5), + identExpr(BigInt(6), { name: 'c' }), + identExpr(BigInt(7), { name: 'd' }) + ), ], }), }, @@ -1265,14 +1258,8 @@ const testCases: TestInfo[] = [ P: structExpr(BigInt(1), { messageName: 'SomeMessage', entries: [ - createStructFieldEntry(BigInt(2), { - key: 'foo', - value: int64Expr(BigInt(3), BigInt(5)), - }), - createStructFieldEntry(BigInt(4), { - key: 'bar', - value: stringExpr(BigInt(5), 'xyz'), - }), + structFieldEntry(BigInt(2), 'foo', int64Expr(BigInt(3), BigInt(5))), + structFieldEntry(BigInt(4), 'bar', stringExpr(BigInt(5), 'xyz')), ], }), }, @@ -1314,14 +1301,16 @@ const testCases: TestInfo[] = [ // }^#1:*expr.Expr_StructExpr#`, P: structExpr(BigInt(1), { entries: [ - createStructMapEntry(BigInt(2), { - key: identExpr(BigInt(3), { name: 'foo' }), - value: int64Expr(BigInt(4), BigInt(5)), - }), - createStructMapEntry(BigInt(5), { - key: identExpr(BigInt(6), { name: 'bar' }), - value: stringExpr(BigInt(7), 'xyz'), - }), + structMapEntry( + BigInt(2), + identExpr(BigInt(3), { name: 'foo' }), + int64Expr(BigInt(4), BigInt(5)) + ), + structMapEntry( + BigInt(5), + identExpr(BigInt(6), { name: 'bar' }), + stringExpr(BigInt(7), 'xyz') + ), ], }), }, @@ -1333,14 +1322,16 @@ const testCases: TestInfo[] = [ // }^#1:*expr.Expr_StructExpr#`, P: structExpr(BigInt(1), { entries: [ - createStructMapEntry(BigInt(2), { - key: identExpr(BigInt(3), { name: 'foo' }), - value: int64Expr(BigInt(4), BigInt(5)), - }), - createStructMapEntry(BigInt(5), { - key: identExpr(BigInt(6), { name: 'bar' }), - value: stringExpr(BigInt(7), 'xyz'), - }), + structMapEntry( + BigInt(2), + identExpr(BigInt(3), { name: 'foo' }), + int64Expr(BigInt(4), BigInt(5)) + ), + structMapEntry( + BigInt(5), + identExpr(BigInt(6), { name: 'bar' }), + stringExpr(BigInt(7), 'xyz') + ), ], }), }, @@ -1461,14 +1452,16 @@ const testCases: TestInfo[] = [ // }^#1:*expr.Expr_StructExpr#`, P: structExpr(BigInt(1), { entries: [ - createStructMapEntry(BigInt(2), { - key: int64Expr(BigInt(3), BigInt(1)), - value: uint64Expr(BigInt(4), BigInt(2)), - }), - createStructMapEntry(BigInt(5), { - key: int64Expr(BigInt(6), BigInt(2)), - value: uint64Expr(BigInt(7), BigInt(3)), - }), + structMapEntry( + BigInt(2), + int64Expr(BigInt(3), BigInt(1)), + uint64Expr(BigInt(4), BigInt(2)) + ), + structMapEntry( + BigInt(5), + int64Expr(BigInt(6), BigInt(2)), + uint64Expr(BigInt(7), BigInt(3)) + ), ], }), }, @@ -1481,14 +1474,16 @@ const testCases: TestInfo[] = [ P: structExpr(BigInt(1), { messageName: 'TestAllTypes', entries: [ - createStructFieldEntry(BigInt(2), { - key: 'single_int32', - value: int64Expr(BigInt(3), BigInt(1)), - }), - createStructFieldEntry(BigInt(4), { - key: 'single_int64', - value: int64Expr(BigInt(5), BigInt(2)), - }), + structFieldEntry( + BigInt(2), + 'single_int32', + int64Expr(BigInt(3), BigInt(1)) + ), + structFieldEntry( + BigInt(4), + 'single_int64', + int64Expr(BigInt(5), BigInt(2)) + ), ], }), }, @@ -2585,11 +2580,12 @@ const testCases: TestInfo[] = [ P: structExpr(BigInt(1), { messageName: 'Msg', entries: [ - createStructFieldEntry(BigInt(2), { - key: 'field', - value: identExpr(BigInt(3), { name: 'value' }), - optionalEntry: true, - }), + structFieldEntry( + BigInt(2), + 'field', + identExpr(BigInt(3), { name: 'value' }), + true + ), ], }), }, diff --git a/packages/cel/src/lib/parser/parser.ts b/packages/cel/src/lib/parser/parser.ts index 95b4375..baf307c 100644 --- a/packages/cel/src/lib/parser/parser.ts +++ b/packages/cel/src/lib/parser/parser.ts @@ -16,7 +16,7 @@ import { ParserRuleContext, Token, } from 'antlr4'; -import { Location, OffsetRange } from '../checker/types'; +import { Location, OffsetRange } from '../common/ast'; import { RESERVED_IDS, parseBytesConstant, @@ -30,19 +30,19 @@ import { LexerErrorListener, ParserErrorListener, } from '../common/errors'; +import { boolExpr } from '../common/types/bool'; +import { callExpr } from '../common/types/call'; +import { constExpr } from '../common/types/constant'; +import { identExpr } from '../common/types/ident'; +import { listExpr } from '../common/types/list'; +import { nullExpr } from '../common/types/null'; +import { selectExpr } from '../common/types/select'; +import { stringExpr } from '../common/types/string'; import { - boolExpr, - callExpr, - constExpr, - createStructFieldEntry, - createStructMapEntry, - identExpr, - listExpr, - nullExpr, - selectExpr, - stringExpr, structExpr, -} from '../common/utils'; + structFieldEntry, + structMapEntry, +} from '../common/types/struct'; import { ParseException } from '../exceptions'; import CELLexer from '../gen/CELLexer'; import { @@ -471,11 +471,12 @@ export class CELParser extends GeneratedCelVisitor { return this._reportError(ctx, 'no valid identifier specified'); } fields.push( - createStructFieldEntry(exprId, { - key: id.getText(), - value: this.visit(ctx._values[i]), - optionalEntry, - }) + structFieldEntry( + exprId, + id.getText(), + this.visit(ctx._values[i]), + optionalEntry + ) ); } return structExpr(this.#helper.nextId(ctx), { entries: fields }); @@ -501,13 +502,7 @@ export class CELParser extends GeneratedCelVisitor { } const key = this.visit(optKey._e); const value = this.visit(ctx._values[i]); - fields.push( - createStructMapEntry(colId, { - key, - value, - optionalEntry, - }) - ); + fields.push(structMapEntry(colId, key, value, optionalEntry)); } return structExpr(this.#helper.nextId(ctx), { entries: fields }); }; From 32d6040ec14227f45fe4e005a55216b0578226c5 Mon Sep 17 00:00:00 2001 From: jafaircl Date: Tue, 29 Oct 2024 21:51:55 -0400 Subject: [PATCH 27/34] feat(cel): interpreter checkpoint --- package-lock.json | 14 + package.json | 1 + packages/cel/src/lib/checker/checker.spec.ts | 8 +- packages/cel/src/lib/checker/checker.ts | 8 +- packages/cel/src/lib/checker/types.spec.ts | 3 +- packages/cel/src/lib/checker/types.ts | 77 +-- packages/cel/src/lib/common/errors.ts | 3 +- packages/cel/src/lib/common/expr-value.ts | 84 ++++ packages/cel/src/lib/common/format.ts | 85 ++++ .../cel/src/lib/common/types/bool.spec.ts | 109 ++++- packages/cel/src/lib/common/types/bool.ts | 103 ++++ .../cel/src/lib/common/types/bytes.spec.ts | 163 ++++++- packages/cel/src/lib/common/types/bytes.ts | 125 +++++ packages/cel/src/lib/common/types/compare.ts | 19 + packages/cel/src/lib/common/types/convert.ts | 32 ++ .../cel/src/lib/common/types/double.spec.ts | 306 +++++++++++- packages/cel/src/lib/common/types/double.ts | 192 ++++++++ .../cel/src/lib/common/types/duration.spec.ts | 68 +++ packages/cel/src/lib/common/types/duration.ts | 112 +++++ packages/cel/src/lib/common/types/int.spec.ts | 440 +++++++++++++++++- packages/cel/src/lib/common/types/int.ts | 305 ++++++++++++ packages/cel/src/lib/common/types/native.ts | 40 ++ packages/cel/src/lib/common/types/number.ts | 24 + packages/cel/src/lib/common/types/object.ts | 21 + .../src/lib/common/types/timestamp.spec.ts | 23 + .../cel/src/lib/common/types/timestamp.ts | 53 +++ .../src/lib/common/types/traits/comparer.ts | 17 + .../cel/src/lib/common/types/traits/math.ts | 70 +++ .../src/lib/common/types/traits/negater.ts | 17 + .../cel/src/lib/common/types/traits/sizer.ts | 11 + .../cel/src/lib/common/types/traits/trait.ts | 49 ++ packages/cel/src/lib/common/types/type.ts | 8 + packages/cel/src/lib/common/types/uint.ts | 10 + packages/cel/src/lib/common/types/utils.ts | 4 + packages/cel/src/lib/common/types/wkt.ts | 13 +- packages/cel/src/lib/common/utils.ts | 10 + .../cel/src/lib/interpreter/activation.ts | 41 ++ .../cel/src/lib/interpreter/attributes.ts | 231 +++++++++ .../cel/src/lib/interpreter/dispatcher.ts | 48 ++ .../cel/src/lib/interpreter/interpretable.ts | 17 + packages/cel/src/lib/interpreter/overload.ts | 63 +++ packages/cel/src/lib/interpreter/planner.ts | 0 42 files changed, 2938 insertions(+), 89 deletions(-) create mode 100644 packages/cel/src/lib/common/expr-value.ts create mode 100644 packages/cel/src/lib/common/format.ts create mode 100644 packages/cel/src/lib/common/types/compare.ts create mode 100644 packages/cel/src/lib/common/types/convert.ts create mode 100644 packages/cel/src/lib/common/types/duration.spec.ts create mode 100644 packages/cel/src/lib/common/types/duration.ts create mode 100644 packages/cel/src/lib/common/types/native.ts create mode 100644 packages/cel/src/lib/common/types/number.ts create mode 100644 packages/cel/src/lib/common/types/object.ts create mode 100644 packages/cel/src/lib/common/types/timestamp.spec.ts create mode 100644 packages/cel/src/lib/common/types/timestamp.ts create mode 100644 packages/cel/src/lib/common/types/traits/comparer.ts create mode 100644 packages/cel/src/lib/common/types/traits/math.ts create mode 100644 packages/cel/src/lib/common/types/traits/negater.ts create mode 100644 packages/cel/src/lib/common/types/traits/sizer.ts create mode 100644 packages/cel/src/lib/common/types/traits/trait.ts create mode 100644 packages/cel/src/lib/interpreter/activation.ts create mode 100644 packages/cel/src/lib/interpreter/attributes.ts create mode 100644 packages/cel/src/lib/interpreter/dispatcher.ts create mode 100644 packages/cel/src/lib/interpreter/interpretable.ts create mode 100644 packages/cel/src/lib/interpreter/overload.ts create mode 100644 packages/cel/src/lib/interpreter/planner.ts diff --git a/package-lock.json b/package-lock.json index 1a69e71..92a6a10 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "antlr4": "^4.13.2", "class-transformer": "^0.5.1", "deep-freeze-strict": "^1.1.1", + "dequal": "^2.0.3", "fast-json-stable-stringify": "^2.1.0", "immer": "^9.0.15", "just-extend": "^6.1.1", @@ -9459,6 +9460,14 @@ "node": ">= 0.8" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" + } + }, "node_modules/destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -24169,6 +24178,11 @@ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true }, + "dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==" + }, "destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", diff --git a/package.json b/package.json index 30c1402..a30b884 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "antlr4": "^4.13.2", "class-transformer": "^0.5.1", "deep-freeze-strict": "^1.1.1", + "dequal": "^2.0.3", "fast-json-stable-stringify": "^2.1.0", "immer": "^9.0.15", "just-extend": "^6.1.1", diff --git a/packages/cel/src/lib/checker/checker.spec.ts b/packages/cel/src/lib/checker/checker.spec.ts index 9f90def..96b19d2 100644 --- a/packages/cel/src/lib/checker/checker.spec.ts +++ b/packages/cel/src/lib/checker/checker.spec.ts @@ -2483,20 +2483,20 @@ describe('CELChecker', () => { if ( testCase.outType !== ERROR_TYPE && !testCase.err && - checker.errors.errors.errors.length > 0 + checker.errors.length > 0 ) { throw new Error( - 'Unexpected errors: ' + checker.errors.toDisplayString() + 'Unexpected errors: ' + checker.errorsToDisplayString() ); } } catch (e) { - console.log(checker.errors.toDisplayString()); + console.log(checker.errorsToDisplayString()); console.dir({ expected, got }, { depth: null }); throw e; } } if (testCase.err) { - expect(checker.errors.toDisplayString()).toEqual( + expect(checker.errorsToDisplayString()).toEqual( // Account for the difference in spacing between the test case and // the error message testCase.err diff --git a/packages/cel/src/lib/checker/checker.ts b/packages/cel/src/lib/checker/checker.ts index b00fb59..f2f5924 100644 --- a/packages/cel/src/lib/checker/checker.ts +++ b/packages/cel/src/lib/checker/checker.ts @@ -25,6 +25,7 @@ import { unwrapIdentDecl, } from '../common/decls/ident-decl'; import { Errors } from '../common/errors'; +import { formatCELType } from '../common/format'; import { BOOL_TYPE } from '../common/types/bool'; import { BYTES_TYPE } from '../common/types/bytes'; import { unwrapCallExpr } from '../common/types/call'; @@ -60,7 +61,6 @@ import { mapToObject, toQualifiedName } from '../common/utils'; import { CELEnvironment } from '../environment'; import { OPT_SELECT_OPERATOR } from '../operators'; import { - formatCELType, isAssignable, isAssignableList, isExactType, @@ -93,7 +93,11 @@ export class CELChecker { } public get errors() { - return this.#errors; + return this.#errors.errors.errors; + } + + public errorsToDisplayString() { + return this.#errors.toDisplayString(); } check(expr: Expr = this.parsed.expr!) { diff --git a/packages/cel/src/lib/checker/types.spec.ts b/packages/cel/src/lib/checker/types.spec.ts index 68c2011..e76cd15 100644 --- a/packages/cel/src/lib/checker/types.spec.ts +++ b/packages/cel/src/lib/checker/types.spec.ts @@ -5,6 +5,7 @@ import { } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; import { create } from '@bufbuild/protobuf'; import { EmptySchema, NullValue } from '@bufbuild/protobuf/wkt'; +import { formatCELType } from '../common/format'; import { abstractType } from '../common/types/abstract'; import { DYN_TYPE } from '../common/types/dyn'; import { ERROR_TYPE } from '../common/types/error'; @@ -20,7 +21,7 @@ import { typeType } from '../common/types/type'; import { typeParamType } from '../common/types/type-param'; import { wellKnownType } from '../common/types/wkt'; import { wrapperType } from '../common/types/wrapper'; -import { formatCELType, isAssignableType, isExactType } from './types'; +import { isAssignableType, isExactType } from './types'; describe('types', () => { it('DYN_TYPE', () => { diff --git a/packages/cel/src/lib/checker/types.ts b/packages/cel/src/lib/checker/types.ts index 4d86aa0..030e6cb 100644 --- a/packages/cel/src/lib/checker/types.ts +++ b/packages/cel/src/lib/checker/types.ts @@ -9,11 +9,8 @@ import { Type_ListType, Type_MapType, Type_PrimitiveType, - Type_PrimitiveTypeSchema, - Type_WellKnownType, - Type_WellKnownTypeSchema, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; -import { enumToJson } from '@bufbuild/protobuf'; +import { formatCELType } from '../common/format'; import { abstractType } from '../common/types/abstract'; import { DYN_TYPE, isDynType } from '../common/types/dyn'; import { functionType } from '../common/types/function'; @@ -669,78 +666,6 @@ export function substitute( } } -export function formatCELType(t: Type | null): string { - switch (t?.typeKind.case) { - case 'primitive': - switch (t.typeKind.value) { - case Type_PrimitiveType.BOOL: - return 'bool'; - case Type_PrimitiveType.BYTES: - return 'bytes'; - case Type_PrimitiveType.DOUBLE: - return 'double'; - case Type_PrimitiveType.INT64: - return 'int'; - case Type_PrimitiveType.STRING: - return 'string'; - case Type_PrimitiveType.UINT64: - return 'uint'; - default: - return enumToJson( - Type_PrimitiveTypeSchema, - t.typeKind.value - ) as string; - } - case 'wellKnown': - switch (t.typeKind.value) { - case Type_WellKnownType.ANY: - return 'any'; - case Type_WellKnownType.DURATION: - return 'duration'; - case Type_WellKnownType.TIMESTAMP: - return 'timestamp'; - default: - return enumToJson( - Type_WellKnownTypeSchema, - t.typeKind.value - ) as string; - } - case 'error': - return '!error!'; - case 'null': - return 'null'; - case 'typeParam': - return t.typeKind.value; - case 'abstractType': - const at = t.typeKind.value; - return `${at.name}(${at.parameterTypes.map(formatCELType).join(', ')})`; - case 'listType': - return `list(${formatCELType(t.typeKind.value.elemType!)})`; - case 'type': - if (isNil(t.typeKind.value) || isNil(t.typeKind.value.typeKind.value)) { - return 'type'; - } - return formatCELType(t.typeKind.value); - case 'messageType': - return t.typeKind.value; - case 'mapType': - const keyType = formatCELType(t.typeKind.value.keyType!); - const valueType = formatCELType(t.typeKind.value.valueType!); - return `map(${keyType}, ${valueType})`; - case 'dyn': - return 'dyn'; - case 'function': - return formatFunctionType( - t.typeKind.value.resultType!, - t.typeKind.value.argTypes, - false - ); - case 'wrapper': - return `wrapper(${formatCELType(primitiveType(t.typeKind.value))})`; - } - return ''; -} - export function findTypeInMapping(mapping: Map, t: Type) { return mapping.get(formatCELType(t)); } diff --git a/packages/cel/src/lib/common/errors.ts b/packages/cel/src/lib/common/errors.ts index 3f96957..4ec2b63 100644 --- a/packages/cel/src/lib/common/errors.ts +++ b/packages/cel/src/lib/common/errors.ts @@ -12,9 +12,10 @@ import { import { create, createRegistry } from '@bufbuild/protobuf'; import { anyPack, anyUnpack } from '@bufbuild/protobuf/wkt'; import { ErrorListener, RecognitionException, Recognizer, Token } from 'antlr4'; -import { formatCELType, formatFunctionType } from '../checker/types'; +import { formatFunctionType } from '../checker/types'; import { Location } from './ast'; import { CELContainer } from './container'; +import { formatCELType } from './format'; export class Errors { public readonly errors = create(ErrorSetSchema); diff --git a/packages/cel/src/lib/common/expr-value.ts b/packages/cel/src/lib/common/expr-value.ts new file mode 100644 index 0000000..d43f63b --- /dev/null +++ b/packages/cel/src/lib/common/expr-value.ts @@ -0,0 +1,84 @@ +import { + ErrorSet, + ErrorSetSchema, + ExprValue, + ExprValueSchema, + UnknownSet, + UnknownSetSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/eval_pb.js'; +import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { MessageInitShape, create } from '@bufbuild/protobuf'; + +export function exprValueValue(value: Value) { + return create(ExprValueSchema, { + kind: { + case: 'value', + value, + }, + }); +} + +export function isExprValueValue( + exprValue: ExprValue +): exprValue is ExprValue & { + kind: { case: 'value'; value: Value }; +} { + return exprValue.kind.case === 'value'; +} + +export function unwrapExprValueValue(exprValue: ExprValue) { + if (isExprValueValue(exprValue)) { + return exprValue.kind.value as Value; + } + return null; +} + +export function exprValueError(value: MessageInitShape) { + return create(ExprValueSchema, { + kind: { + case: 'error', + value, + }, + }); +} + +export function isExprValueError( + exprValue: ExprValue +): exprValue is ExprValue & { + kind: { case: 'error'; value: ErrorSet }; +} { + return exprValue.kind.case === 'error'; +} + +export function unwrapExprValueError(exprValue: ExprValue) { + if (isExprValueError(exprValue)) { + return exprValue.kind.value as ErrorSet; + } + return null; +} + +export function exprValueUnknown( + value: MessageInitShape +) { + return create(ExprValueSchema, { + kind: { + case: 'unknown', + value, + }, + }); +} + +export function isExprValueUnknown( + exprValue: ExprValue +): exprValue is ExprValue & { + kind: { case: 'unknown'; value: UnknownSet }; +} { + return exprValue.kind.case === 'unknown'; +} + +export function unwrapExprValueUnknown(exprValue: ExprValue) { + if (isExprValueUnknown(exprValue)) { + return exprValue.kind.value as UnknownSet; + } + return null; +} diff --git a/packages/cel/src/lib/common/format.ts b/packages/cel/src/lib/common/format.ts new file mode 100644 index 0000000..70fa876 --- /dev/null +++ b/packages/cel/src/lib/common/format.ts @@ -0,0 +1,85 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +/* eslint-disable no-case-declarations */ +import { isNil } from '@bearclaw/is'; +import { + Type, + Type_PrimitiveType, + Type_PrimitiveTypeSchema, + Type_WellKnownType, + Type_WellKnownTypeSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { enumToJson } from '@bufbuild/protobuf'; +import { formatFunctionType } from '../checker/types'; +import { primitiveType } from './types/primitive'; + +export function formatCELType(t: Type | null): string { + switch (t?.typeKind.case) { + case 'primitive': + switch (t.typeKind.value) { + case Type_PrimitiveType.BOOL: + return 'bool'; + case Type_PrimitiveType.BYTES: + return 'bytes'; + case Type_PrimitiveType.DOUBLE: + return 'double'; + case Type_PrimitiveType.INT64: + return 'int'; + case Type_PrimitiveType.STRING: + return 'string'; + case Type_PrimitiveType.UINT64: + return 'uint'; + default: + return enumToJson( + Type_PrimitiveTypeSchema, + t.typeKind.value + ) as string; + } + case 'wellKnown': + switch (t.typeKind.value) { + case Type_WellKnownType.ANY: + return 'any'; + case Type_WellKnownType.DURATION: + return 'duration'; + case Type_WellKnownType.TIMESTAMP: + return 'timestamp'; + default: + return enumToJson( + Type_WellKnownTypeSchema, + t.typeKind.value + ) as string; + } + case 'error': + return '!error!'; + case 'null': + return 'null'; + case 'typeParam': + return t.typeKind.value; + case 'abstractType': + const at = t.typeKind.value; + return `${at.name}(${at.parameterTypes.map(formatCELType).join(', ')})`; + case 'listType': + return `list(${formatCELType(t.typeKind.value.elemType!)})`; + case 'type': + if (isNil(t.typeKind.value) || isNil(t.typeKind.value.typeKind.value)) { + return 'type'; + } + return formatCELType(t.typeKind.value); + case 'messageType': + return t.typeKind.value; + case 'mapType': + const keyType = formatCELType(t.typeKind.value.keyType!); + const valueType = formatCELType(t.typeKind.value.valueType!); + return `map(${keyType}, ${valueType})`; + case 'dyn': + return 'dyn'; + case 'function': + return formatFunctionType( + t.typeKind.value.resultType!, + t.typeKind.value.argTypes, + false + ); + case 'wrapper': + return `wrapper(${formatCELType(primitiveType(t.typeKind.value))})`; + } + return ''; +} diff --git a/packages/cel/src/lib/common/types/bool.spec.ts b/packages/cel/src/lib/common/types/bool.spec.ts index 5d7735c..048f061 100644 --- a/packages/cel/src/lib/common/types/bool.spec.ts +++ b/packages/cel/src/lib/common/types/bool.spec.ts @@ -4,7 +4,22 @@ import { } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb'; import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb'; import { create } from '@bufbuild/protobuf'; -import { boolConstant, boolExpr, boolValue } from './bool'; +import { AnySchema, BoolValueSchema, anyPack } from '@bufbuild/protobuf/wkt'; +import { + BOOL_TYPE, + boolConstant, + boolExpr, + boolValue, + compareBoolValue, + convertBoolValueToNative, + convertBoolValueToType, + equalBoolValue, + isZeroBoolValue, + negateBoolValue, +} from './bool'; +import { int64Value } from './int'; +import { STRING_TYPE, stringValue } from './string'; +import { TYPE_TYPE } from './type'; describe('bool', () => { it('boolConstant', () => { @@ -47,4 +62,96 @@ describe('bool', () => { }); // TODO: validations + + it('convertBoolValueToNative - js boolean', () => { + expect(() => { + convertBoolValueToNative(stringValue('true'), Boolean); + }).toThrow(); + const value = boolValue(true); + expect(convertBoolValueToNative(value, Boolean)).toEqual(true); + }); + + it('convertBoolValueToNative - anyPack', () => { + const value = boolValue(true); + const packed = anyPack( + BoolValueSchema, + create(BoolValueSchema, { value: true }) + ); + expect(convertBoolValueToNative(value, AnySchema)).toEqual(packed); + }); + + it('convertBoolValueToNative - bool wrapper', () => { + const value = boolValue(true); + expect(convertBoolValueToNative(value, BoolValueSchema)).toEqual( + create(BoolValueSchema, { value: true }) + ); + }); + + it('convertBoolValueToNative - invalid type', () => { + const value = boolValue(true); + expect(convertBoolValueToNative(value, Array)).toEqual( + new Error(`type conversion error from 'bool' to 'Array'`) + ); + }); + + it('convertBoolValueToType', () => { + expect(() => { + convertBoolValueToType(stringValue('true'), BOOL_TYPE); + }).toThrow(); + const value = boolValue(true); + expect(convertBoolValueToType(value, BOOL_TYPE)).toEqual(boolValue(true)); + expect(convertBoolValueToType(value, STRING_TYPE)).toEqual( + stringValue('true') + ); + expect(convertBoolValueToType(value, TYPE_TYPE)).toEqual(BOOL_TYPE); + }); + + it('equalBoolValue', () => { + expect(() => { + equalBoolValue(stringValue('true'), boolValue(true)); + }).toThrow(); + expect(equalBoolValue(boolValue(true), boolValue(true))).toEqual( + boolValue(true) + ); + expect(equalBoolValue(boolValue(false), boolValue(true))).toEqual( + boolValue(false) + ); + expect(equalBoolValue(boolValue(true), boolValue(false))).toEqual( + boolValue(false) + ); + }); + + it('isZeroBoolValue', () => { + expect(() => { + isZeroBoolValue(stringValue('true')); + }).toThrow(); + expect(isZeroBoolValue(boolValue(true))).toEqual(boolValue(false)); + expect(isZeroBoolValue(boolValue(false))).toEqual(boolValue(true)); + }); + + it('compareBoolValue', () => { + expect(() => { + compareBoolValue(stringValue('true'), boolValue(true)); + }).toThrow(); + expect(compareBoolValue(boolValue(true), boolValue(true))).toEqual( + int64Value(BigInt(0)) + ); + expect(compareBoolValue(boolValue(false), boolValue(true))).toEqual( + int64Value(BigInt(-1)) + ); + expect(compareBoolValue(boolValue(true), boolValue(false))).toEqual( + int64Value(BigInt(1)) + ); + expect(compareBoolValue(boolValue(true), stringValue('true'))).toEqual( + new Error('no such overload') + ); + }); + + it('negateBoolValue', () => { + expect(() => { + negateBoolValue(stringValue('true')); + }).toThrow(); + expect(negateBoolValue(boolValue(true))).toEqual(boolValue(false)); + expect(negateBoolValue(boolValue(false))).toEqual(boolValue(true)); + }); }); diff --git a/packages/cel/src/lib/common/types/bool.ts b/packages/cel/src/lib/common/types/bool.ts index 8eb262e..a1436fe 100644 --- a/packages/cel/src/lib/common/types/bool.ts +++ b/packages/cel/src/lib/common/types/bool.ts @@ -13,8 +13,14 @@ import { ValueSchema, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; import { create } from '@bufbuild/protobuf'; +import { AnySchema, BoolValueSchema, anyPack } from '@bufbuild/protobuf/wkt'; +import { formatCELType } from '../format'; import { isConstExpr } from './constant'; +import { int64Value } from './int'; +import { NativeType } from './native'; import { primitiveType } from './primitive'; +import { stringValue } from './string'; +import { Trait } from './traits/trait'; export const BOOL_TYPE = primitiveType(Type_PrimitiveType.BOOL); @@ -73,3 +79,100 @@ export function isBoolValue(value: Value): value is Value & { } { return value.kind.case === 'boolValue'; } + +export function convertBoolValueToNative(value: Value, type: NativeType) { + if (!isBoolValue(value)) { + // This should never happen + throw new Error('value is not a bool'); + } + switch (type) { + case Boolean: + return value.kind.value; + case AnySchema: + return anyPack( + BoolValueSchema, + create(BoolValueSchema, { value: value.kind.value }) + ); + case BoolValueSchema: + return create(BoolValueSchema, { value: value.kind.value }); + default: + break; + } + return new Error( + `type conversion error from '${formatCELType(BOOL_TYPE)}' to '${type.name}'` + ); +} + +export function convertBoolValueToType(value: Value, type: Type) { + if (!isBoolValue(value)) { + // This should never happen + throw new Error('value is not a bool'); + } + switch (type.typeKind.case) { + case 'primitive': + switch (type.typeKind.value) { + case Type_PrimitiveType.BOOL: + return boolValue(value.kind.value); + case Type_PrimitiveType.STRING: + return stringValue(value.kind.value ? 'true' : 'false'); + default: + break; + } + break; + case 'type': + return BOOL_TYPE; + default: + break; + } + return new Error( + `type conversion error from '${formatCELType( + BOOL_TYPE + )}' to '${formatCELType(type)}'` + ); +} + +export function equalBoolValue(value: Value, other: Value) { + if (!isBoolValue(value)) { + // This should never happen + throw new Error('value is not a bool'); + } + if (!isBoolValue(other)) { + return boolValue(false); + } + return boolValue(value.kind.value === other.kind.value); +} + +export function isZeroBoolValue(value: Value) { + if (!isBoolValue(value)) { + // This should never happen + throw new Error('value is not a bool'); + } + return equalBoolValue(value, boolValue(false)); +} + +export const BOOL_TRAITS = new Set([Trait.COMPARER_TYPE, Trait.NEGATER_TYPE]); + +export function compareBoolValue(value: Value, other: Value) { + if (!isBoolValue(value)) { + // This should never happen + throw new Error('value is not a bool'); + } + if (!isBoolValue(other)) { + return new Error('no such overload'); + } + if (value.kind.value === other.kind.value) { + return int64Value(BigInt(0)); + } + if (!value.kind.value && other.kind.value) { + return int64Value(BigInt(-1)); + } + return int64Value(BigInt(1)); +} + +export function negateBoolValue(value: Value) { + if (!isBoolValue(value)) { + // This should never happen + throw new Error('value is not a bool'); + } + return boolValue(!value.kind.value); +} diff --git a/packages/cel/src/lib/common/types/bytes.spec.ts b/packages/cel/src/lib/common/types/bytes.spec.ts index 445fc8b..84c479b 100644 --- a/packages/cel/src/lib/common/types/bytes.spec.ts +++ b/packages/cel/src/lib/common/types/bytes.spec.ts @@ -4,7 +4,24 @@ import { } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb'; import { create } from '@bufbuild/protobuf'; -import { bytesConstant, bytesExpr, bytesValue } from './bytes'; +import { AnySchema, BytesValueSchema, anyPack } from '@bufbuild/protobuf/wkt'; +import { boolValue } from './bool'; +import { + BYTES_TYPE, + addBytesValue, + bytesConstant, + bytesExpr, + bytesValue, + compareBytesValue, + convertBytesValueToNative, + convertBytesValueToType, + equalBytesValue, + isZeroBytesValue, + sizeBytesValue, +} from './bytes'; +import { int64Value } from './int'; +import { STRING_TYPE, stringValue } from './string'; +import { TYPE_TYPE } from './type'; describe('bytes', () => { it('bytesConstant', () => { @@ -47,4 +64,148 @@ describe('bytes', () => { }); // TODO: validations + + it('convertBytesValueToNative - js Uint8Array', () => { + expect(() => { + convertBytesValueToNative(stringValue('foo'), Uint8Array); + }).toThrow(); + expect( + convertBytesValueToNative( + bytesValue(new Uint8Array([1, 2, 3])), + Uint8Array + ) + ).toEqual(new Uint8Array([1, 2, 3])); + }); + + it('convertBytesValueToNative - anyPack', () => { + const value = bytesValue(new Uint8Array([1, 2, 3])); + const packed = anyPack( + BytesValueSchema, + create(BytesValueSchema, { value: new Uint8Array([1, 2, 3]) }) + ); + expect(convertBytesValueToNative(value, AnySchema)).toEqual(packed); + }); + + it('convertBytesValueToNative - bytes wrapper', () => { + const value = bytesValue(new Uint8Array([1, 2, 3])); + expect(convertBytesValueToNative(value, BytesValueSchema)).toEqual( + create(BytesValueSchema, { value: new Uint8Array([1, 2, 3]) }) + ); + }); + + it('convertBytesValueToNative - invalid type', () => { + const value = bytesValue(new Uint8Array([1, 2, 3])); + expect(convertBytesValueToNative(value, Boolean)).toEqual( + new Error(`type conversion error from 'bytes' to 'Boolean'`) + ); + }); + + it('convertBytesValueToType', () => { + expect(() => { + convertBytesValueToType(stringValue('true'), BYTES_TYPE); + }).toThrow(); + const value = bytesValue(new TextEncoder().encode('helloworld')); + expect(convertBytesValueToType(value, BYTES_TYPE)).toEqual(value); + expect(convertBytesValueToType(value, STRING_TYPE)).toEqual( + stringValue('helloworld') + ); + expect(convertBytesValueToType(value, TYPE_TYPE)).toEqual(BYTES_TYPE); + }); + + it('equalBytesValue', () => { + expect(() => { + equalBytesValue( + stringValue('foo'), + bytesValue(new Uint8Array([1, 2, 3])) + ); + }).toThrow(); + expect( + equalBytesValue( + bytesValue(new Uint8Array([1, 2, 3])), + bytesValue(new Uint8Array([1, 2, 3])) + ) + ).toEqual(boolValue(true)); + expect( + equalBytesValue( + bytesValue(new Uint8Array([1, 2, 3])), + bytesValue(new Uint8Array([1, 2])) + ) + ).toEqual(boolValue(false)); + expect( + equalBytesValue(bytesValue(new Uint8Array([1, 2, 3])), stringValue('')) + ).toEqual(boolValue(false)); + }); + + it('isZeroBytesValue', () => { + expect(() => { + isZeroBytesValue(stringValue('foo')); + }).toThrow(); + expect(isZeroBytesValue(bytesValue(new Uint8Array([1, 2, 3])))).toEqual( + boolValue(false) + ); + expect(isZeroBytesValue(bytesValue(new Uint8Array([])))).toEqual( + boolValue(true) + ); + }); + + it('addBytesValue', () => { + expect(() => { + addBytesValue(stringValue('foo'), bytesValue(new Uint8Array([1, 2, 3]))); + }).toThrow(); + expect( + addBytesValue( + bytesValue(new TextEncoder().encode('foo')), + bytesValue(new TextEncoder().encode('bar')) + ) + ).toEqual(bytesValue(new TextEncoder().encode('foobar'))); + expect( + addBytesValue( + bytesValue(new TextEncoder().encode('foo')), + stringValue('bar') + ) + ).toEqual(new Error('no such overload')); + }); + + it('compareBytesValue', () => { + expect(() => { + compareBytesValue( + stringValue('foo'), + bytesValue(new Uint8Array([1, 2, 3])) + ); + }).toThrow(); + expect( + compareBytesValue( + bytesValue(new TextEncoder().encode('1234')), + bytesValue(new TextEncoder().encode('2345')) + ) + ).toEqual(int64Value(BigInt(-1))); + expect( + compareBytesValue( + bytesValue(new TextEncoder().encode('1234')), + bytesValue(new TextEncoder().encode('1234')) + ) + ).toEqual(int64Value(BigInt(0))); + expect( + compareBytesValue( + bytesValue(new TextEncoder().encode('2345')), + bytesValue(new TextEncoder().encode('1234')) + ) + ).toEqual(int64Value(BigInt(1))); + expect( + compareBytesValue( + bytesValue(new TextEncoder().encode('1234')), + stringValue('1234') + ) + ).toEqual(new Error('no such overload')); + }); + + it('sizeBytesValue', () => { + expect(() => { + sizeBytesValue(stringValue('foo')); + }).toThrow(); + expect( + sizeBytesValue(bytesValue(new TextEncoder().encode('1234567890'))).kind + .value + ).toEqual(BigInt(10)); + }); }); diff --git a/packages/cel/src/lib/common/types/bytes.ts b/packages/cel/src/lib/common/types/bytes.ts index 86cf642..cb64711 100644 --- a/packages/cel/src/lib/common/types/bytes.ts +++ b/packages/cel/src/lib/common/types/bytes.ts @@ -13,8 +13,16 @@ import { ValueSchema, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; import { create } from '@bufbuild/protobuf'; +import { AnySchema, BytesValueSchema, anyPack } from '@bufbuild/protobuf/wkt'; +import { dequal } from 'dequal'; +import { formatCELType } from '../format'; +import { boolValue } from './bool'; import { isConstExpr } from './constant'; +import { int64Value } from './int'; +import { NativeType } from './native'; import { primitiveType } from './primitive'; +import { stringValue } from './string'; +import { Trait } from './traits/trait'; export const BYTES_TYPE = primitiveType(Type_PrimitiveType.BYTES); @@ -75,3 +83,120 @@ export function isBytesValue(value: Value): value is Value & { } { return value.kind.case === 'bytesValue'; } + +export function convertBytesValueToNative(value: Value, type: NativeType) { + if (!isBytesValue(value)) { + throw new Error('bytes value is not a bytes'); + } + switch (type) { + case Uint8Array: + return value.kind.value; + case AnySchema: + return anyPack( + BytesValueSchema, + create(BytesValueSchema, { value: value.kind.value }) + ); + case BytesValueSchema: + return create(BytesValueSchema, { value: value.kind.value }); + default: + break; + } + return new Error( + `type conversion error from '${formatCELType(BYTES_TYPE)}' to '${ + type.name + }'` + ); +} + +export function convertBytesValueToType(value: Value, type: Type) { + if (!isBytesValue(value)) { + throw new Error('bytes value is not a bytes'); + } + switch (type.typeKind.case) { + case 'primitive': + switch (type.typeKind.value) { + case Type_PrimitiveType.BYTES: + return bytesValue(value.kind.value); + case Type_PrimitiveType.STRING: + return stringValue(new TextDecoder().decode(value.kind.value)); + default: + break; + } + break; + case 'type': + return BYTES_TYPE; + default: + break; + } + return new Error( + `type conversion error from '${formatCELType( + BYTES_TYPE + )}' to '${formatCELType(type)}'` + ); +} + +export function equalBytesValue(value: Value, other: Value) { + if (!isBytesValue(value)) { + throw new Error('bytes value is not a bytes'); + } + if (!isBytesValue(other)) { + return boolValue(false); + } + return boolValue(dequal(value.kind.value, other.kind.value)); +} + +export function isZeroBytesValue(value: Value) { + if (!isBytesValue(value)) { + throw new Error('bytes value is not a bytes'); + } + return boolValue(value.kind.value.length === 0); +} + +export const BYTES_TRAITS = new Set([ + Trait.ADDER_TYPE, + Trait.COMPARER_TYPE, + Trait.SIZER_TYPE, +]); + +export function addBytesValue(value: Value, other: Value) { + if (!isBytesValue(value)) { + throw new Error('bytes value is not a bytes'); + } + if (!isBytesValue(other)) { + return new Error('no such overload'); + } + return bytesValue(new Uint8Array([...value.kind.value, ...other.kind.value])); +} + +export function compareBytesValue(value: Value, other: Value) { + if (!isBytesValue(value)) { + throw new Error('bytes value is not a bytes'); + } + if (!isBytesValue(other)) { + return new Error('no such overload'); + } + if (value.kind.value.length < other.kind.value.length) { + return int64Value(BigInt(-1)); + } + if (value.kind.value.length > other.kind.value.length) { + return int64Value(BigInt(1)); + } + for (let i = 0; i < value.kind.value.length; i++) { + const v = value.kind.value[i]; + const o = other.kind.value[i]; + if (v < o) { + return int64Value(BigInt(-1)); + } + if (v > o) { + return int64Value(BigInt(1)); + } + } + return int64Value(BigInt(0)); +} + +export function sizeBytesValue(value: Value) { + if (!isBytesValue(value)) { + throw new Error('bytes value is not a bytes'); + } + return int64Value(BigInt(value.kind.value.length)); +} diff --git a/packages/cel/src/lib/common/types/compare.ts b/packages/cel/src/lib/common/types/compare.ts new file mode 100644 index 0000000..bfa2487 --- /dev/null +++ b/packages/cel/src/lib/common/types/compare.ts @@ -0,0 +1,19 @@ +import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { int64Value } from './int'; +import { isNumberValue } from './number'; + +export function compareNumberValues(value: Value, other: Value) { + if (!isNumberValue(value)) { + return new Error('value is not a number (double, int64, or uint64)'); + } + if (!isNumberValue(other)) { + return new Error('other is not a number (double, int64, or uint64)'); + } + if (value.kind.value < other.kind.value) { + return int64Value(BigInt(-1)); + } + if (value.kind.value > other.kind.value) { + return int64Value(BigInt(1)); + } + return int64Value(BigInt(0)); +} diff --git a/packages/cel/src/lib/common/types/convert.ts b/packages/cel/src/lib/common/types/convert.ts new file mode 100644 index 0000000..b315fa7 --- /dev/null +++ b/packages/cel/src/lib/common/types/convert.ts @@ -0,0 +1,32 @@ +import { Type } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { convertBoolValueToNative, convertBoolValueToType } from './bool'; +import { convertBytesValueToNative, convertBytesValueToType } from './bytes'; +import { convertDoubleValueToNative, convertDoubleValueToType } from './double'; +import { NativeType } from './native'; + +export function convertToNative(value: Value, type: NativeType) { + switch (value.kind.case) { + case 'boolValue': + return convertBoolValueToNative(value, type); + case 'bytesValue': + return convertBytesValueToNative(value, type); + case 'doubleValue': + return convertDoubleValueToNative(value, type); + default: + return new Error('no such overload'); + } +} + +export function convertToType(value: Value, type: Type) { + switch (value.kind.case) { + case 'boolValue': + return convertBoolValueToType(value, type); + case 'bytesValue': + return convertBytesValueToType(value, type); + case 'doubleValue': + return convertDoubleValueToType(value, type); + default: + return new Error('no such overload'); + } +} diff --git a/packages/cel/src/lib/common/types/double.spec.ts b/packages/cel/src/lib/common/types/double.spec.ts index 00c197e..9cada17 100644 --- a/packages/cel/src/lib/common/types/double.spec.ts +++ b/packages/cel/src/lib/common/types/double.spec.ts @@ -4,7 +4,31 @@ import { } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; import { create } from '@bufbuild/protobuf'; -import { doubleConstant, doubleExpr, doubleValue } from './double'; +import { + AnySchema, + DoubleValueSchema, + FloatValueSchema, + anyPack, +} from '@bufbuild/protobuf/wkt'; +import { boolValue } from './bool'; +import { + DOUBLE_TYPE, + addDoubleValue, + compareDoubleValue, + convertDoubleValueToNative, + convertDoubleValueToType, + divideDoubleValue, + doubleConstant, + doubleExpr, + doubleValue, + equalDoubleValue, + isZeroDoubleValue, + multiplyDoubleValue, +} from './double'; +import { INT64_TYPE, int64Value } from './int'; +import { STRING_TYPE, stringValue } from './string'; +import { TYPE_TYPE } from './type'; +import { UINT64_TYPE, uint64Value } from './uint'; describe('double', () => { it('doubleConstant', () => { @@ -47,4 +71,284 @@ describe('double', () => { }); // TODO: validations + + it('convertDoubleValueToNative - js Number', () => { + expect(() => { + convertDoubleValueToNative(stringValue('foo'), Number); + }).toThrow(); + expect(convertDoubleValueToNative(doubleValue(3.14), Number)).toEqual(3.14); + }); + + it('convertDoubleValueToNative - anyPack', () => { + const value = doubleValue(-1.4); + const packed = anyPack( + DoubleValueSchema, + create(DoubleValueSchema, { value: -1.4 }) + ); + expect(convertDoubleValueToNative(value, AnySchema)).toEqual(packed); + }); + + it('convertDoubleValueToNative - double wrapper', () => { + const value = doubleValue(30000000.1); + expect(convertDoubleValueToNative(value, DoubleValueSchema)).toEqual( + create(DoubleValueSchema, { value: 30000000.1 }) + ); + }); + + it('convertDoubleValueToNative - double wrapper', () => { + const value = doubleValue(1.7976931348623157); + expect(convertDoubleValueToNative(value, FloatValueSchema)).toEqual( + create(FloatValueSchema, { value: 1.7976931348623157 }) + ); + }); + + it('convertDoubleValueToNative - invalid type', () => { + const value = doubleValue(-3.14159); + expect(convertDoubleValueToNative(value, Boolean)).toEqual( + new Error(`type conversion error from 'double' to 'Boolean'`) + ); + }); + + it('convertDoubleValueToType', () => { + expect(() => { + convertDoubleValueToType(stringValue('true'), DOUBLE_TYPE); + }).toThrow(); + const value = doubleValue(1234.5); + expect(convertDoubleValueToType(value, DOUBLE_TYPE)).toEqual(value); + expect(convertDoubleValueToType(value, STRING_TYPE)).toEqual( + stringValue('1234.5') + ); + expect(convertDoubleValueToType(value, TYPE_TYPE)).toEqual(DOUBLE_TYPE); + // Int64 errors + expect(convertDoubleValueToType(doubleValue(NaN), INT64_TYPE)).toEqual( + new Error('integer overflow') + ); + expect(convertDoubleValueToType(doubleValue(Infinity), INT64_TYPE)).toEqual( + new Error('integer overflow') + ); + expect( + convertDoubleValueToType(doubleValue(-Infinity), INT64_TYPE) + ).toEqual(new Error('integer overflow')); + expect( + convertDoubleValueToType(doubleValue(Number.MAX_VALUE), INT64_TYPE) + ).toEqual(new Error('integer overflow')); + expect( + convertDoubleValueToType(doubleValue(-1 * Number.MAX_VALUE), INT64_TYPE) + ).toEqual(new Error('integer overflow')); + // Uint64 errors + expect(convertDoubleValueToType(doubleValue(NaN), UINT64_TYPE)).toEqual( + new Error('unsigned integer overflow') + ); + expect( + convertDoubleValueToType(doubleValue(Infinity), UINT64_TYPE) + ).toEqual(new Error('unsigned integer overflow')); + expect(convertDoubleValueToType(doubleValue(-1), UINT64_TYPE)).toEqual( + new Error('unsigned integer overflow') + ); + expect( + convertDoubleValueToType(doubleValue(Number.MAX_VALUE), UINT64_TYPE) + ).toEqual(new Error('unsigned integer overflow')); + }); + + it('equalDoubleValue', () => { + expect(() => { + equalDoubleValue(stringValue('foo'), doubleValue(1)); + }).toThrow(); + const testCases = [ + { + a: doubleValue(-10), + b: doubleValue(-10), + out: boolValue(true), + }, + { + a: doubleValue(-10), + b: doubleValue(10), + out: boolValue(false), + }, + { + a: doubleValue(10), + b: uint64Value(BigInt(10)), + out: boolValue(true), + }, + { + a: doubleValue(9), + b: uint64Value(BigInt(10)), + out: boolValue(false), + }, + { + a: doubleValue(10), + b: int64Value(BigInt(10)), + out: boolValue(true), + }, + { + a: doubleValue(10), + b: int64Value(BigInt(-15)), + out: boolValue(false), + }, + { + a: doubleValue(NaN), + b: int64Value(BigInt(10)), + out: boolValue(false), + }, + { + a: doubleValue(10), + b: doubleValue(NaN), + out: boolValue(false), + }, + ]; + for (const testCase of testCases) { + expect(equalDoubleValue(testCase.a, testCase.b)).toEqual(testCase.out); + } + }); + + it('isZeroDoubleValue', () => { + expect(() => { + isZeroDoubleValue(stringValue('foo')); + }).toThrow(); + expect(isZeroDoubleValue(doubleValue(0))).toEqual(boolValue(true)); + expect(isZeroDoubleValue(doubleValue(1))).toEqual(boolValue(false)); + }); + + it('addDoubleValue', () => { + expect(() => { + addDoubleValue(stringValue('foo'), doubleValue(1)); + }).toThrow(); + expect(addDoubleValue(doubleValue(1), doubleValue(2))).toEqual( + doubleValue(3) + ); + expect(addDoubleValue(doubleValue(1), uint64Value(BigInt(2)))).toEqual( + doubleValue(3) + ); + expect(addDoubleValue(doubleValue(1), int64Value(BigInt(2)))).toEqual( + doubleValue(3) + ); + expect(addDoubleValue(doubleValue(1), stringValue('2'))).toEqual( + new Error('no such overload') + ); + }); + + it('compareDoubleValue', () => { + expect(() => { + compareDoubleValue(stringValue('foo'), doubleValue(1)); + }).toThrow(); + const testCases = [ + { + a: doubleValue(42), + b: doubleValue(42), + out: int64Value(BigInt(0)), + }, + { + a: doubleValue(42), + b: uint64Value(BigInt(42)), + out: int64Value(BigInt(0)), + }, + { + a: doubleValue(42), + b: int64Value(BigInt(42)), + out: int64Value(BigInt(0)), + }, + { + a: doubleValue(-1300), + b: doubleValue(204), + out: int64Value(BigInt(-1)), + }, + { + a: doubleValue(-1300), + b: uint64Value(BigInt(204)), + out: int64Value(BigInt(-1)), + }, + { + a: doubleValue(203.9), + b: int64Value(BigInt(204)), + out: int64Value(BigInt(-1)), + }, + { + a: doubleValue(1300), + b: uint64Value(BigInt(Number.MAX_SAFE_INTEGER + 1)), + out: int64Value(BigInt(-1)), + }, + { + a: doubleValue(204), + b: uint64Value(BigInt(205)), + out: int64Value(BigInt(-1)), + }, + { + a: doubleValue(204), + b: doubleValue(Number.MAX_SAFE_INTEGER + 1025), + out: int64Value(BigInt(-1)), + }, + { + a: doubleValue(204), + b: doubleValue(NaN), + out: new Error('NaN values cannot be ordered'), + }, + { + a: doubleValue(NaN), + b: doubleValue(204), + out: new Error('NaN values cannot be ordered'), + }, + { + a: doubleValue(204), + b: doubleValue(-1300), + out: int64Value(BigInt(1)), + }, + { + a: doubleValue(204), + b: uint64Value(BigInt(10)), + out: int64Value(BigInt(1)), + }, + { + a: doubleValue(204.1), + b: int64Value(BigInt(204)), + out: int64Value(BigInt(1)), + }, + { + a: doubleValue(1), + b: stringValue('1'), + out: new Error('no such overload'), + }, + ]; + for (const testCase of testCases) { + expect(compareDoubleValue(testCase.a, testCase.b)).toEqual(testCase.out); + } + }); + + it('divideDoubleValue', () => { + expect(() => { + divideDoubleValue(stringValue('foo'), doubleValue(1)); + }).toThrow(); + expect(divideDoubleValue(doubleValue(1), doubleValue(2))).toEqual( + doubleValue(0.5) + ); + expect(divideDoubleValue(doubleValue(1), uint64Value(BigInt(2)))).toEqual( + doubleValue(0.5) + ); + expect(divideDoubleValue(doubleValue(1), int64Value(BigInt(2)))).toEqual( + doubleValue(0.5) + ); + expect(divideDoubleValue(doubleValue(1), stringValue('2'))).toEqual( + new Error('no such overload') + ); + expect(divideDoubleValue(doubleValue(1), doubleValue(0))).toEqual( + doubleValue(Infinity) + ); + }); + + it('multiplyDoubleValue', () => { + expect(() => { + multiplyDoubleValue(stringValue('foo'), doubleValue(1)); + }).toThrow(); + expect(multiplyDoubleValue(doubleValue(2), doubleValue(21))).toEqual( + doubleValue(42) + ); + expect( + multiplyDoubleValue(doubleValue(2), uint64Value(BigInt(21))) + ).toEqual(doubleValue(42)); + expect(multiplyDoubleValue(doubleValue(2), int64Value(BigInt(21)))).toEqual( + doubleValue(42) + ); + expect(multiplyDoubleValue(doubleValue(2), stringValue('21'))).toEqual( + new Error('no such overload') + ); + }); }); diff --git a/packages/cel/src/lib/common/types/double.ts b/packages/cel/src/lib/common/types/double.ts index 69fd461..f309b78 100644 --- a/packages/cel/src/lib/common/types/double.ts +++ b/packages/cel/src/lib/common/types/double.ts @@ -13,7 +13,22 @@ import { ValueSchema, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; import { create } from '@bufbuild/protobuf'; +import { + AnySchema, + DoubleValueSchema, + FloatValueSchema, + anyPack, +} from '@bufbuild/protobuf/wkt'; +import { formatCELType } from '../format'; +import { boolValue } from './bool'; +import { compareNumberValues } from './compare'; +import { int64Value, isValidInt64 } from './int'; +import { NativeType } from './native'; +import { isNumberValue } from './number'; import { primitiveType } from './primitive'; +import { stringValue } from './string'; +import { Trait } from './traits/trait'; +import { isValidUint64, uint64Value } from './uint'; export const DOUBLE_TYPE = primitiveType(Type_PrimitiveType.DOUBLE); @@ -85,3 +100,180 @@ export function isDoubleValue(value: Value): value is Value & { } { return value.kind.case === 'doubleValue'; } + +export function convertDoubleValueToNative(value: Value, type: NativeType) { + if (!isDoubleValue(value)) { + throw new Error('double value is not a double'); + } + switch (type) { + case Number: + return value.kind.value; + case AnySchema: + return anyPack( + DoubleValueSchema, + create(DoubleValueSchema, { value: value.kind.value }) + ); + case DoubleValueSchema: + return create(DoubleValueSchema, { value: value.kind.value }); + case FloatValueSchema: + return create(FloatValueSchema, { value: value.kind.value }); + default: + break; + } + return new Error( + `type conversion error from '${formatCELType(DOUBLE_TYPE)}' to '${ + type.name + }'` + ); +} + +export function convertDoubleValueToType(value: Value, type: Type) { + if (!isDoubleValue(value)) { + throw new Error('double value is not a double'); + } + switch (type.typeKind.case) { + case 'primitive': + switch (type.typeKind.value) { + case Type_PrimitiveType.DOUBLE: + return doubleValue(value.kind.value); + case Type_PrimitiveType.INT64: + if ( + Number.isNaN(value.kind.value) || + value.kind.value >= Infinity || + value.kind.value <= -Infinity || + !isValidInt64(BigInt(value.kind.value)) + ) { + return new Error('integer overflow'); + } + return int64Value(BigInt(value.kind.value)); + case Type_PrimitiveType.UINT64: + if ( + Number.isNaN(value.kind.value) || + value.kind.value >= Infinity || + !isValidUint64(BigInt(value.kind.value)) + ) { + return new Error('unsigned integer overflow'); + } + return uint64Value(BigInt(value.kind.value)); + case Type_PrimitiveType.STRING: + return stringValue(value.kind.value.toString()); + default: + break; + } + break; + case 'type': + return DOUBLE_TYPE; + default: + break; + } + return new Error( + `type conversion error from '${formatCELType( + DOUBLE_TYPE + )}' to '${formatCELType(type)}'` + ); +} + +export function equalDoubleValue(value: Value, other: Value) { + if (!isDoubleValue(value)) { + throw new Error('double value is not a double'); + } + if (!isNumberValue(other)) { + return boolValue(false); + } + if ( + Number.isNaN(Number(value.kind.value)) || + Number.isNaN(Number(other.kind.value)) + ) { + return boolValue(false); + } + const compared = compareNumberValues(value, other); + if (compared instanceof Error) { + return boolValue(false); + } + return boolValue(compared.kind.value === BigInt(0)); +} + +export function isZeroDoubleValue(value: Value) { + if (!isDoubleValue(value)) { + throw new Error('double value is not a double'); + } + return boolValue(value.kind.value === 0); +} + +export const DOUBLE_TRAITS = new Set([ + Trait.ADDER_TYPE, + Trait.COMPARER_TYPE, + Trait.DIVIDER_TYPE, + Trait.MULTIPLIER_TYPE, + Trait.NEGATER_TYPE, + Trait.SUBTRACTOR_TYPE, +]); + +export function addDoubleValue(value: Value, other: Value) { + if (!isDoubleValue(value)) { + throw new Error('double value is not a double'); + } + if (!isNumberValue(other)) { + return new Error('no such overload'); + } + return doubleValue(value.kind.value + Number(other.kind.value)); +} + +export function compareDoubleValue(value: Value, other: Value) { + if (!isDoubleValue(value)) { + throw new Error('double value is not a double'); + } + if (!isNumberValue(other)) { + return new Error('no such overload'); + } + if ( + Number.isNaN(Number(value.kind.value)) || + Number.isNaN(Number(other.kind.value)) + ) { + return new Error('NaN values cannot be ordered'); + } + if (value.kind.value < Number.MIN_SAFE_INTEGER) { + return int64Value(BigInt(-1)); + } + if (value.kind.value > Number.MAX_SAFE_INTEGER) { + return int64Value(BigInt(1)); + } + return compareNumberValues(value, other); +} + +export function divideDoubleValue(value: Value, other: Value) { + if (!isDoubleValue(value)) { + throw new Error('double value is not a double'); + } + if (!isNumberValue(other)) { + return new Error('no such overload'); + } + return doubleValue(value.kind.value / Number(other.kind.value)); +} + +export function multiplyDoubleValue(value: Value, other: Value) { + if (!isDoubleValue(value)) { + throw new Error('double value is not a double'); + } + if (!isNumberValue(other)) { + return new Error('no such overload'); + } + return doubleValue(value.kind.value * Number(other.kind.value)); +} + +export function negateDoubleValue(value: Value) { + if (!isDoubleValue(value)) { + throw new Error('double value is not a double'); + } + return doubleValue(-value.kind.value); +} + +export function subtractDoubleValue(value: Value, other: Value) { + if (!isDoubleValue(value)) { + throw new Error('double value is not a double'); + } + if (!isNumberValue(other)) { + return new Error('no such overload'); + } + return doubleValue(value.kind.value - Number(other.kind.value)); +} diff --git a/packages/cel/src/lib/common/types/duration.spec.ts b/packages/cel/src/lib/common/types/duration.spec.ts new file mode 100644 index 0000000..eaa1187 --- /dev/null +++ b/packages/cel/src/lib/common/types/duration.spec.ts @@ -0,0 +1,68 @@ +import { create } from '@bufbuild/protobuf'; +import { DurationSchema, anyPack } from '@bufbuild/protobuf/wkt'; +import { convertDurationValueToType, durationValue } from './duration'; +import { INT64_TYPE, int64Value } from './int'; +import { objectValue } from './object'; +import { STRING_TYPE, stringValue } from './string'; +import { TYPE_TYPE } from './type'; +import { UINT64_TYPE } from './uint'; +import { DURATION_TYPE } from './wkt'; + +describe('duration', () => { + it('durationValue', () => { + expect(durationValue({ seconds: BigInt(100) })).toEqual( + objectValue( + anyPack( + DurationSchema, + create(DurationSchema, { seconds: BigInt(100) }) + ) + ) + ); + }); + + // TODO: validations + + // TODO: convertDurationValueToNative + + it('convertDurationValueToType', () => { + expect(() => { + convertDurationValueToType(stringValue('foo'), INT64_TYPE); + }).toThrow(); + expect( + convertDurationValueToType( + durationValue({ seconds: BigInt(42) }), + STRING_TYPE + ) + ).toEqual(stringValue('42s')); + expect( + convertDurationValueToType( + durationValue({ seconds: BigInt(7506), nanos: 1000 }), + STRING_TYPE + ) + ).toEqual(stringValue('7506.000001s')); + expect( + convertDurationValueToType( + durationValue({ seconds: BigInt(7506), nanos: 1000 }), + INT64_TYPE + ) + ).toEqual(int64Value(BigInt(7506000001000))); + expect( + convertDurationValueToType( + durationValue({ seconds: BigInt(42) }), + DURATION_TYPE + ) + ).toEqual(durationValue({ seconds: BigInt(42) })); + expect( + convertDurationValueToType( + durationValue({ seconds: BigInt(42) }), + TYPE_TYPE + ) + ).toEqual(DURATION_TYPE); + expect( + convertDurationValueToType( + durationValue({ seconds: BigInt(42) }), + UINT64_TYPE + ) + ).toEqual(new Error(`type conversion error from 'duration' to 'uint'`)); + }); +}); diff --git a/packages/cel/src/lib/common/types/duration.ts b/packages/cel/src/lib/common/types/duration.ts new file mode 100644 index 0000000..2524411 --- /dev/null +++ b/packages/cel/src/lib/common/types/duration.ts @@ -0,0 +1,112 @@ +/* eslint-disable no-case-declarations */ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +import { + Type, + Type_PrimitiveType, + Type_WellKnownType, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { + Value, + ValueSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { MessageInitShape, clone, create } from '@bufbuild/protobuf'; +import { + Any, + AnySchema, + Duration, + DurationSchema, + anyPack, + anyUnpack, +} from '@bufbuild/protobuf/wkt'; +import { formatCELType } from '../format'; +import { int64Value } from './int'; +import { NativeType } from './native'; +import { isObjectValue } from './object'; +import { stringValue } from './string'; +import { typeNameToUrl } from './utils'; +import { DURATION_TYPE, WKT_REGISTRY } from './wkt'; + +export function durationValue(init: MessageInitShape) { + return create(ValueSchema, { + kind: { + case: 'objectValue', + value: anyPack(DurationSchema, create(DurationSchema, init)), + }, + }); +} + +export function isDurationValue(value: Value): value is Value & { + kind: { case: 'objectValue'; value: Any }; +} { + return ( + isObjectValue(value) && + value.kind.value.typeUrl === typeNameToUrl(DurationSchema.typeName) + ); +} + +export function unwrapDurationValue(value: Value) { + if (isDurationValue(value)) { + return anyUnpack(value.kind.value, WKT_REGISTRY) as Duration; + } + return null; +} + +export function convertDurationValueToNative(value: Value, type: NativeType) { + if (!isDurationValue(value)) { + throw new Error('duration value is not a duration'); + } + const duration = unwrapDurationValue(value)!; + switch (type) { + case AnySchema: + return anyPack(DurationSchema, duration); + case DurationSchema: + return clone(DurationSchema, duration); + default: + break; + } + return new Error( + `type conversion error from '${formatCELType(DURATION_TYPE)}' to '${ + type.name + }'` + ); +} + +export function convertDurationValueToType(value: Value, type: Type) { + if (!isDurationValue(value)) { + throw new Error('duration value is not a duration'); + } + const duration = unwrapDurationValue(value)!; + switch (type.typeKind.case) { + case 'primitive': + switch (type.typeKind.value) { + case Type_PrimitiveType.STRING: + return stringValue( + `${Number(duration.seconds) + duration.nanos * 1e-9}s` + ); + case Type_PrimitiveType.INT64: + return int64Value( + duration.seconds * BigInt(1e9) + BigInt(duration.nanos) + ); + default: + break; + } + break; + case 'wellKnown': + switch (type.typeKind.value) { + case Type_WellKnownType.DURATION: + return durationValue(clone(DurationSchema, duration)); + default: + break; + } + break; + case 'type': + return DURATION_TYPE; + default: + break; + } + return new Error( + `type conversion error from '${formatCELType( + DURATION_TYPE + )}' to '${formatCELType(type)}'` + ); +} diff --git a/packages/cel/src/lib/common/types/int.spec.ts b/packages/cel/src/lib/common/types/int.spec.ts index 82fe1c5..8f5fbcd 100644 --- a/packages/cel/src/lib/common/types/int.spec.ts +++ b/packages/cel/src/lib/common/types/int.spec.ts @@ -4,7 +4,43 @@ import { } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; import { create } from '@bufbuild/protobuf'; -import { int64Constant, int64Expr, int64Value } from './int'; +import { + AnySchema, + Int32ValueSchema, + Int64ValueSchema, + anyPack, + timestampFromMs, +} from '@bufbuild/protobuf/wkt'; +import { boolValue } from './bool'; +import { DOUBLE_TYPE, doubleValue } from './double'; +import { + INT64_TYPE, + MAX_INT64, + MIN_INT64, + addInt64Value, + compareInt64Value, + convertInt64ValueToNative, + convertInt64ValueToType, + divideInt64Value, + equalInt64Value, + int64Constant, + int64Expr, + int64Value, + isZeroInt64Value, + moduloInt64Value, + multiplyInt64Value, + negateInt64Value, + subtractInt64Value, +} from './int'; +import { STRING_TYPE, stringValue } from './string'; +import { + MAX_UNIX_TIME_MS, + MIN_UNIX_TIME_MS, + timestampValue, +} from './timestamp'; +import { TYPE_TYPE } from './type'; +import { UINT64_TYPE, uint64Value } from './uint'; +import { TIMESTAMP_TYPE } from './wkt'; describe('int', () => { it('int64Constant', () => { @@ -47,4 +83,406 @@ describe('int', () => { }); // TODO: validations + + it('convertInt64ValueToNative - js BigInt', () => { + expect(() => { + convertInt64ValueToNative(stringValue('foo'), Number); + }).toThrow(); + expect(convertInt64ValueToNative(int64Value(BigInt(42)), BigInt)).toEqual( + BigInt(42) + ); + }); + + it('convertInt64ValueToNative - anyPack', () => { + const value = int64Value(BigInt(-42)); + const packed = anyPack( + Int64ValueSchema, + create(Int64ValueSchema, { value: BigInt(-42) }) + ); + expect(convertInt64ValueToNative(value, AnySchema)).toEqual(packed); + }); + + it('convertInt64ValueToNative - int64 wrapper', () => { + const value = int64Value(BigInt(30000000)); + expect(convertInt64ValueToNative(value, Int64ValueSchema)).toEqual( + create(Int64ValueSchema, { value: BigInt(30000000) }) + ); + // Value errors + expect( + convertInt64ValueToNative( + int64Value(MAX_INT64 + BigInt(1)), + Int64ValueSchema + ) + ).toEqual(new Error('integer overflow')); + expect( + convertInt64ValueToNative( + int64Value(MIN_INT64 - BigInt(1)), + Int64ValueSchema + ) + ).toEqual(new Error('integer overflow')); + }); + + it('convertInt64ValueToNative - int32 wrapper', () => { + const value = int64Value(BigInt(7976931348623157)); + expect(convertInt64ValueToNative(value, Int32ValueSchema)).toEqual( + create(Int32ValueSchema, { value: 7976931348623157 }) + ); + // Value errors + expect( + convertInt64ValueToNative( + int64Value(BigInt(Number.MAX_SAFE_INTEGER + 1)), + Int32ValueSchema + ) + ).toEqual(new Error('integer overflow')); + expect( + convertInt64ValueToNative( + int64Value(BigInt(Number.MIN_SAFE_INTEGER - 1)), + Int32ValueSchema + ) + ).toEqual(new Error('integer overflow')); + }); + + it('convertInt64ValueToNative - invalid type', () => { + const value = int64Value(BigInt(-314159)); + expect(convertInt64ValueToNative(value, Boolean)).toEqual( + new Error(`type conversion error from 'int' to 'Boolean'`) + ); + }); + + it('convertInt64ValueToType', () => { + expect(() => { + convertInt64ValueToType(stringValue('foo'), TYPE_TYPE); + }).toThrow(); + const tests = [ + { + in: int64Value(BigInt(42)), + type: TYPE_TYPE, + out: INT64_TYPE, + }, + { + in: int64Value(BigInt(42)), + type: INT64_TYPE, + out: int64Value(BigInt(42)), + }, + { + in: int64Value(BigInt(42)), + type: UINT64_TYPE, + out: uint64Value(BigInt(42)), + }, + { + in: int64Value(BigInt(-42)), + type: UINT64_TYPE, + out: new Error('unsigned integer overflow'), + }, + { + in: int64Value(BigInt(42)), + type: DOUBLE_TYPE, + out: doubleValue(42), + }, + { + in: int64Value(BigInt(-42)), + type: STRING_TYPE, + out: stringValue('-42'), + }, + { + in: int64Value(BigInt(946684800)), + type: TIMESTAMP_TYPE, + out: timestampValue(timestampFromMs(946684800)), + }, + { + in: int64Value(BigInt(MAX_UNIX_TIME_MS + 1)), + type: TIMESTAMP_TYPE, + out: new Error('timestamp overflow'), + }, + { + in: int64Value(BigInt(MIN_UNIX_TIME_MS - 1)), + type: TIMESTAMP_TYPE, + out: new Error('timestamp overflow'), + }, + ]; + for (const test of tests) { + expect(convertInt64ValueToType(test.in, test.type)).toEqual(test.out); + } + }); + + it('equalInt64Value', () => { + expect(() => { + equalInt64Value(stringValue('foo'), int64Value(BigInt(42))); + }).toThrow(); + const tests = [ + { + a: int64Value(BigInt(-10)), + b: int64Value(BigInt(-10)), + out: boolValue(true), + }, + { + a: int64Value(BigInt(10)), + b: int64Value(BigInt(-10)), + out: boolValue(false), + }, + { + a: int64Value(BigInt(10)), + b: uint64Value(BigInt(10)), + out: boolValue(true), + }, + { + a: int64Value(BigInt(9)), + b: uint64Value(BigInt(10)), + out: boolValue(false), + }, + { + a: int64Value(BigInt(10)), + b: doubleValue(10), + out: boolValue(true), + }, + { + a: int64Value(BigInt(10)), + b: doubleValue(-10.5), + out: boolValue(false), + }, + { + a: int64Value(BigInt(10)), + b: doubleValue(NaN), + out: boolValue(false), + }, + { + a: int64Value(BigInt(10)), + b: stringValue('10'), + out: boolValue(false), + }, + ]; + for (const test of tests) { + expect(equalInt64Value(test.a, test.b)).toEqual(test.out); + } + }); + + it('isZeroInt64Value', () => { + expect(isZeroInt64Value(int64Value(BigInt(0)))).toEqual(boolValue(true)); + expect(isZeroInt64Value(int64Value(BigInt(1)))).toEqual(boolValue(false)); + }); + + it('addInt64Value', () => { + expect(() => { + addInt64Value(stringValue('foo'), int64Value(BigInt(42))); + }).toThrow(); + expect(addInt64Value(int64Value(BigInt(1)), int64Value(BigInt(2)))).toEqual( + int64Value(BigInt(3)) + ); + expect(addInt64Value(int64Value(BigInt(1)), stringValue('-4'))).toEqual( + new Error('no such overload') + ); + expect(addInt64Value(int64Value(MAX_INT64), int64Value(BigInt(1)))).toEqual( + new Error('integer overflow') + ); + expect( + addInt64Value(int64Value(MIN_INT64), int64Value(BigInt(-1))) + ).toEqual(new Error('integer overflow')); + expect( + addInt64Value(int64Value(MAX_INT64 - BigInt(1)), int64Value(BigInt(1))) + ).toEqual(int64Value(MAX_INT64)); + expect( + addInt64Value(int64Value(MIN_INT64 + BigInt(1)), int64Value(BigInt(-1))) + ).toEqual(int64Value(MIN_INT64)); + }); + + it('compareInt64Value', () => { + expect(() => { + compareInt64Value(stringValue('foo'), int64Value(BigInt(42))); + }).toThrow(); + const tests = [ + { + a: int64Value(BigInt(42)), + b: int64Value(BigInt(42)), + out: int64Value(BigInt(0)), + }, + { + a: int64Value(BigInt(42)), + b: uint64Value(BigInt(42)), + out: int64Value(BigInt(0)), + }, + { + a: int64Value(BigInt(42)), + b: doubleValue(42), + out: int64Value(BigInt(0)), + }, + { + a: int64Value(BigInt(-1300)), + b: int64Value(BigInt(204)), + out: int64Value(BigInt(-1)), + }, + { + a: int64Value(BigInt(204)), + b: doubleValue(204.1), + out: int64Value(BigInt(-1)), + }, + { + a: int64Value(BigInt(1300)), + b: uint64Value(MAX_INT64 + BigInt(1)), + out: int64Value(BigInt(-1)), + }, + { + a: int64Value(BigInt(204)), + b: uint64Value(BigInt(205)), + out: int64Value(BigInt(-1)), + }, + { + a: int64Value(BigInt(204)), + b: doubleValue(Number(MAX_INT64) + 1025.0), + out: int64Value(BigInt(-1)), + }, + { + a: int64Value(BigInt(204)), + b: doubleValue(NaN), + out: new Error('NaN values cannot be ordered'), + }, + { + a: int64Value(BigInt(204)), + b: int64Value(BigInt(-1300)), + out: int64Value(BigInt(1)), + }, + { + a: int64Value(BigInt(204)), + b: uint64Value(BigInt(10)), + out: int64Value(BigInt(1)), + }, + { + a: int64Value(BigInt(204)), + b: doubleValue(203.9), + out: int64Value(BigInt(1)), + }, + { + a: int64Value(BigInt(204)), + b: doubleValue(Number(MIN_INT64) - 1025.0), + out: int64Value(BigInt(1)), + }, + { + a: int64Value(BigInt(1)), + b: stringValue('1'), + out: new Error('no such overload'), + }, + ]; + for (const test of tests) { + expect(compareInt64Value(test.a, test.b)).toEqual(test.out); + } + }); + + it('divideInt64Value', () => { + expect(() => { + divideInt64Value(stringValue('foo'), int64Value(BigInt(42))); + }).toThrow(); + expect( + divideInt64Value(int64Value(BigInt(3)), int64Value(BigInt(2))) + ).toEqual(int64Value(BigInt(1))); + expect( + divideInt64Value(int64Value(BigInt(3)), int64Value(BigInt(0))) + ).toEqual(new Error('divide by zero')); + expect( + divideInt64Value(int64Value(MIN_INT64), int64Value(BigInt(-1))) + ).toEqual(new Error('integer overflow')); + }); + + it('moduloInt64Value', () => { + expect(() => { + moduloInt64Value(stringValue('foo'), int64Value(BigInt(42))); + }).toThrow(); + expect( + moduloInt64Value(int64Value(BigInt(21)), int64Value(BigInt(2))) + ).toEqual(int64Value(BigInt(1))); + expect( + moduloInt64Value(int64Value(BigInt(21)), int64Value(BigInt(0))) + ).toEqual(new Error('modulus by zero')); + expect( + moduloInt64Value(int64Value(MIN_INT64), int64Value(BigInt(-1))) + ).toEqual(new Error('integer overflow')); + }); + + it('multiplyInt64Value', () => { + expect(() => { + multiplyInt64Value(stringValue('foo'), int64Value(BigInt(42))); + }).toThrow(); + expect( + multiplyInt64Value(int64Value(BigInt(2)), int64Value(BigInt(-2))) + ).toEqual(int64Value(BigInt(-4))); + expect( + multiplyInt64Value( + int64Value(MAX_INT64 / BigInt(2)), + int64Value(BigInt(3)) + ) + ).toEqual(new Error('integer overflow')); + expect( + multiplyInt64Value( + int64Value(MIN_INT64 / BigInt(2)), + int64Value(BigInt(3)) + ) + ).toEqual(new Error('integer overflow')); + expect( + multiplyInt64Value( + int64Value(MAX_INT64 / BigInt(2)), + int64Value(BigInt(2)) + ) + ).toEqual(int64Value(MAX_INT64 - BigInt(1))); + expect( + multiplyInt64Value( + int64Value(MIN_INT64 / BigInt(2)), + int64Value(BigInt(2)) + ) + ).toEqual(int64Value(MIN_INT64)); + expect( + multiplyInt64Value( + int64Value(MAX_INT64 / BigInt(2)), + int64Value(BigInt(-2)) + ) + ).toEqual(int64Value(MIN_INT64 + BigInt(2))); + expect( + multiplyInt64Value( + int64Value((MIN_INT64 + BigInt(2)) / BigInt(2)), + int64Value(BigInt(-2)) + ) + ).toEqual(int64Value(MAX_INT64 - BigInt(1))); + expect( + multiplyInt64Value(int64Value(MIN_INT64), int64Value(BigInt(-1))) + ).toEqual(new Error('integer overflow')); + }); + + it('negateInt64Value', () => { + expect(() => { + negateInt64Value(stringValue('foo')); + }).toThrow(); + expect(negateInt64Value(int64Value(BigInt(42)))).toEqual( + int64Value(BigInt(-42)) + ); + expect(negateInt64Value(int64Value(MIN_INT64))).toEqual( + new Error('integer overflow') + ); + expect(negateInt64Value(int64Value(MAX_INT64))).toEqual( + int64Value(MIN_INT64 + BigInt(1)) + ); + }); + + it('subtractInt64Value', () => { + expect(() => { + subtractInt64Value(stringValue('foo'), int64Value(BigInt(42))); + }).toThrow(); + expect( + subtractInt64Value(int64Value(BigInt(4)), int64Value(BigInt(-3))) + ).toEqual(int64Value(BigInt(7))); + expect( + subtractInt64Value(int64Value(MAX_INT64), int64Value(BigInt(-1))) + ).toEqual(new Error('integer overflow')); + expect( + subtractInt64Value(int64Value(MIN_INT64), int64Value(BigInt(1))) + ).toEqual(new Error('integer overflow')); + expect( + subtractInt64Value( + int64Value(MAX_INT64 - BigInt(1)), + int64Value(BigInt(-1)) + ) + ).toEqual(int64Value(MAX_INT64)); + expect( + subtractInt64Value( + int64Value(MIN_INT64 + BigInt(1)), + int64Value(BigInt(1)) + ) + ).toEqual(int64Value(MIN_INT64)); + }); }); diff --git a/packages/cel/src/lib/common/types/int.ts b/packages/cel/src/lib/common/types/int.ts index 4333867..72282fc 100644 --- a/packages/cel/src/lib/common/types/int.ts +++ b/packages/cel/src/lib/common/types/int.ts @@ -1,6 +1,7 @@ import { Type, Type_PrimitiveType, + Type_WellKnownType, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; import { Constant, @@ -13,8 +14,28 @@ import { ValueSchema, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; import { create } from '@bufbuild/protobuf'; +import { + AnySchema, + Int32ValueSchema, + Int64ValueSchema, + anyPack, + timestampFromMs, +} from '@bufbuild/protobuf/wkt'; +import { formatCELType } from '../format'; +import { boolValue } from './bool'; +import { compareNumberValues } from './compare'; import { isConstExpr } from './constant'; +import { doubleValue, isDoubleValue } from './double'; +import { NativeType } from './native'; +import { isNumberValue } from './number'; import { primitiveType } from './primitive'; +import { stringValue } from './string'; +import { MAX_UNIX_TIME, MIN_UNIX_TIME, timestampValue } from './timestamp'; +import { Trait } from './traits/trait'; +import { isValidUint64, uint64Value } from './uint'; + +export const MAX_INT64 = BigInt(2) ** BigInt(63) - BigInt(1); +export const MIN_INT64 = BigInt(-1) * BigInt(2) ** BigInt(63); export const INT64_TYPE = primitiveType(Type_PrimitiveType.INT64); @@ -82,3 +103,287 @@ export function isInt64Value(value: Value): value is Value & { } { return value.kind.case === 'int64Value'; } + +export function isValidInt32(value: number) { + return ( + !Number.isNaN(value) && + value >= Number.MIN_SAFE_INTEGER && + value <= Number.MAX_SAFE_INTEGER && + value < Infinity && + value > -Infinity + ); +} + +export function isValidInt64(value: bigint) { + return ( + !Number.isNaN(value) && + value <= MAX_INT64 && + value >= MIN_INT64 && + value < Infinity && + value > -Infinity + ); +} + +export function convertInt64ValueToNative(value: Value, type: NativeType) { + if (!isInt64Value(value)) { + throw new Error('int64 value is not a int64'); + } + switch (type) { + case BigInt: + return value.kind.value; + case Number: + return Number(value.kind.value); + case AnySchema: + return anyPack( + Int64ValueSchema, + create(Int64ValueSchema, { value: value.kind.value }) + ); + case Int32ValueSchema: + if (!isValidInt32(Number(value.kind.value))) { + return new Error('integer overflow'); + } + return create(Int32ValueSchema, { value: Number(value.kind.value) }); + case Int64ValueSchema: + if (!isValidInt64(value.kind.value)) { + return new Error('integer overflow'); + } + return create(Int64ValueSchema, { value: value.kind.value }); + default: + break; + } + return new Error( + `type conversion error from '${formatCELType(INT64_TYPE)}' to '${ + type.name + }'` + ); +} + +export function convertInt64ValueToType(value: Value, type: Type) { + if (!isInt64Value(value)) { + throw new Error('int64 value is not a int64'); + } + switch (type.typeKind.case) { + case 'primitive': + switch (type.typeKind.value) { + case Type_PrimitiveType.INT64: + if ( + Number.isNaN(value.kind.value) || + !isValidInt64(value.kind.value) + ) { + return new Error('integer overflow'); + } + return int64Value(value.kind.value); + case Type_PrimitiveType.UINT64: + if ( + Number.isNaN(value.kind.value) || + !isValidUint64(value.kind.value) + ) { + return new Error('unsigned integer overflow'); + } + return uint64Value(value.kind.value); + case Type_PrimitiveType.DOUBLE: + return doubleValue(Number(value.kind.value)); + case Type_PrimitiveType.STRING: + return stringValue(value.kind.value.toString()); + default: + break; + } + break; + case 'wellKnown': + switch (type.typeKind.value) { + case Type_WellKnownType.TIMESTAMP: + if ( + Number.isNaN(value.kind.value) || + value.kind.value < MIN_UNIX_TIME || + value.kind.value > MAX_UNIX_TIME + ) { + return new Error('timestamp overflow'); + } + return timestampValue(timestampFromMs(Number(value.kind.value))); + default: + break; + } + break; + case 'type': + return INT64_TYPE; + default: + break; + } + return new Error( + `type conversion error from '${formatCELType( + INT64_TYPE + )}' to '${formatCELType(type)}'` + ); +} + +export function equalInt64Value(value: Value, other: Value) { + if (!isInt64Value(value)) { + throw new Error('int64 value is not a int64'); + } + if (!isNumberValue(other)) { + return boolValue(false); + } + if ( + Number.isNaN(Number(value.kind.value)) || + Number.isNaN(Number(other.kind.value)) + ) { + return boolValue(false); + } + const compared = compareNumberValues(value, other); + if (compared instanceof Error) { + return boolValue(false); + } + return boolValue(compared.kind.value === BigInt(0)); +} + +export function isZeroInt64Value(value: Value) { + if (!isInt64Value(value)) { + throw new Error('int64 value is not a int64'); + } + return boolValue(value.kind.value === BigInt(0)); +} + +export const INT64_TRAITS = new Set([ + Trait.ADDER_TYPE, + Trait.COMPARER_TYPE, + Trait.DIVIDER_TYPE, + Trait.MODDER_TYPE, + Trait.MULTIPLIER_TYPE, + Trait.NEGATER_TYPE, + Trait.SUBTRACTOR_TYPE, +]); + +export function addInt64Value(value: Value, other: Value) { + if (!isInt64Value(value)) { + throw new Error('int64 value is not a int64'); + } + if (!isNumberValue(other)) { + return new Error('no such overload'); + } + if ( + (other.kind.value > 0 && + value.kind.value > MAX_INT64 - BigInt(other.kind.value)) || + (other.kind.value < 0 && + value.kind.value < MIN_INT64 - BigInt(other.kind.value)) + ) { + return new Error('integer overflow'); + } + return int64Value(value.kind.value + BigInt(other.kind.value)); +} + +export function compareInt64Value(value: Value, other: Value) { + if (!isInt64Value(value)) { + throw new Error('int64 value is not a int64'); + } + if (!isNumberValue(other)) { + return new Error('no such overload'); + } + if ( + Number.isNaN(Number(value.kind.value)) || + Number.isNaN(Number(other.kind.value)) + ) { + return new Error('NaN values cannot be ordered'); + } + if (isDoubleValue(other) && value.kind.value < Number.MIN_SAFE_INTEGER) { + return int64Value(BigInt(-1)); + } + if (isDoubleValue(other) && value.kind.value > Number.MAX_SAFE_INTEGER) { + return int64Value(BigInt(1)); + } + return compareNumberValues(value, other); +} + +export function divideInt64Value(value: Value, other: Value) { + if (!isInt64Value(value)) { + throw new Error('int64 value is not a int64'); + } + if (!isNumberValue(other)) { + return new Error('no such overload'); + } + if (Number(other.kind.value) === 0) { + return new Error('divide by zero'); + } + // Negating MinInt64 would result in a valid of MaxInt64+1. + if (value.kind.value === MIN_INT64 && Number(other.kind.value) === -1) { + return new Error('integer overflow'); + } + return int64Value(value.kind.value / BigInt(other.kind.value)); +} + +export function moduloInt64Value(value: Value, other: Value) { + if (!isInt64Value(value)) { + throw new Error('int64 value is not a int64'); + } + if (!isNumberValue(other)) { + return new Error('no such overload'); + } + if (Number(other.kind.value) === 0) { + return new Error('modulus by zero'); + } + // Negating MinInt64 would result in a valid of MaxInt64+1. + if (value.kind.value === MIN_INT64 && Number(other.kind.value) === -1) { + return new Error('integer overflow'); + } + return int64Value(value.kind.value % BigInt(other.kind.value)); +} + +export function multiplyInt64Value(value: Value, other: Value) { + if (!isInt64Value(value)) { + throw new Error('int64 value is not a int64'); + } + if (!isNumberValue(other)) { + return new Error('no such overload'); + } + const x = value.kind.value; + const y = BigInt(other.kind.value); + // Detecting multiplication overflow is more complicated than the others. The + // first two detect attempting to negate MinInt64, which would result in + // MaxInt64+1. The other four detect normal overflow conditions. + if ( + (x === BigInt(-1) && y == MIN_INT64) || + (y === BigInt(-1) && x == MIN_INT64) || + // x is positive, y is positive + (x > 0 && y > 0 && x > MAX_INT64 / y) || + // x is positive, y is negative + (x > 0 && y < 0 && y < MIN_INT64 / x) || + // x is negative, y is positive + (x < 0 && y > 0 && x < MIN_INT64 / y) || + // x is negative, y is negative + (x < 0 && y < 0 && y < MAX_INT64 / x) + ) { + return new Error('integer overflow'); + } + return int64Value(value.kind.value * BigInt(other.kind.value)); +} + +export function negateInt64Value(value: Value) { + if (!isInt64Value(value)) { + throw new Error('int64 value is not a int64'); + } + if (value.kind.value === MIN_INT64) { + return new Error('integer overflow'); + } + // Negating MinInt64 would result in a value of MaxInt64+1. + if (value.kind.value === MIN_INT64) { + return new Error('integer overflow'); + } + return int64Value(-value.kind.value); +} + +export function subtractInt64Value(value: Value, other: Value) { + if (!isInt64Value(value)) { + throw new Error('int64 value is not a int64'); + } + if (!isNumberValue(other)) { + return new Error('no such overload'); + } + if ( + (other.kind.value < 0 && + value.kind.value > MAX_INT64 + BigInt(other.kind.value)) || + (other.kind.value > 0 && + value.kind.value < MIN_INT64 + BigInt(other.kind.value)) + ) { + return new Error('integer overflow'); + } + return int64Value(value.kind.value - BigInt(other.kind.value)); +} diff --git a/packages/cel/src/lib/common/types/native.ts b/packages/cel/src/lib/common/types/native.ts new file mode 100644 index 0000000..8836447 --- /dev/null +++ b/packages/cel/src/lib/common/types/native.ts @@ -0,0 +1,40 @@ +import { + AnySchema, + BoolValueSchema, + BytesValueSchema, + DoubleValueSchema, + DurationSchema, + FloatValueSchema, + Int32ValueSchema, + Int64ValueSchema, + StringValueSchema, + StructSchema, + TimestampSchema, + UInt64ValueSchema, +} from '@bufbuild/protobuf/wkt'; + +/** + * Native types that can be used for convertToNative functions + */ +export type NativeType = + | typeof Boolean + | typeof Number + | typeof String + | typeof Object + | typeof Array + | typeof Uint8Array + | typeof Function + | typeof Symbol + | typeof BigInt + | typeof AnySchema + | typeof BoolValueSchema + | typeof BytesValueSchema + | typeof DoubleValueSchema + | typeof DurationSchema + | typeof FloatValueSchema + | typeof Int32ValueSchema + | typeof Int64ValueSchema + | typeof StringValueSchema + | typeof StructSchema + | typeof TimestampSchema + | typeof UInt64ValueSchema; diff --git a/packages/cel/src/lib/common/types/number.ts b/packages/cel/src/lib/common/types/number.ts new file mode 100644 index 0000000..2b903be --- /dev/null +++ b/packages/cel/src/lib/common/types/number.ts @@ -0,0 +1,24 @@ +import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { isDoubleValue } from './double'; +import { isInt64Value } from './int'; +import { isUint64Value } from './uint'; + +export function isNumberValue(value: Value): value is Value & { + kind: + | { case: 'doubleValue'; value: number } + | { case: 'int64Value'; value: bigint } + | { case: 'uint64Value'; value: bigint }; +} { + return isDoubleValue(value) || isInt64Value(value) || isUint64Value(value); +} + +export function unwrapNumberValue(value: Value): number | bigint | null { + switch (value.kind.case) { + case 'int64Value': + case 'uint64Value': + case 'doubleValue': + return value.kind.value; + default: + return null; + } +} diff --git a/packages/cel/src/lib/common/types/object.ts b/packages/cel/src/lib/common/types/object.ts new file mode 100644 index 0000000..019d83d --- /dev/null +++ b/packages/cel/src/lib/common/types/object.ts @@ -0,0 +1,21 @@ +import { + Value, + ValueSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb'; +import { MessageInitShape, create } from '@bufbuild/protobuf'; +import { Any, AnySchema } from '@bufbuild/protobuf/wkt'; + +export function objectValue(init: MessageInitShape) { + return create(ValueSchema, { + kind: { + case: 'objectValue', + value: init, + }, + }); +} + +export function isObjectValue(value: Value): value is Value & { + kind: { case: 'objectValue'; value: Any }; +} { + return value.kind.case === 'objectValue'; +} diff --git a/packages/cel/src/lib/common/types/timestamp.spec.ts b/packages/cel/src/lib/common/types/timestamp.spec.ts new file mode 100644 index 0000000..04c1954 --- /dev/null +++ b/packages/cel/src/lib/common/types/timestamp.spec.ts @@ -0,0 +1,23 @@ +import { + TimestampSchema, + anyPack, + timestampFromDate, +} from '@bufbuild/protobuf/wkt'; +import { objectValue } from './object'; +import { + isTimestampValue, + timestampValue, + unwrapTimestampValue, +} from './timestamp'; + +describe('timestamp', () => { + it('timestampValue', () => { + const now = new Date(); + const value = timestampValue(timestampFromDate(now)); + expect(value).toEqual( + objectValue(anyPack(TimestampSchema, timestampFromDate(now))) + ); + expect(isTimestampValue(value)).toBe(true); + expect(unwrapTimestampValue(value)).toEqual(timestampFromDate(now)); + }); +}); diff --git a/packages/cel/src/lib/common/types/timestamp.ts b/packages/cel/src/lib/common/types/timestamp.ts new file mode 100644 index 0000000..0d4278b --- /dev/null +++ b/packages/cel/src/lib/common/types/timestamp.ts @@ -0,0 +1,53 @@ +import { + Value, + ValueSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { MessageInitShape, create } from '@bufbuild/protobuf'; +import { + Any, + Timestamp, + TimestampSchema, + anyPack, + anyUnpack, +} from '@bufbuild/protobuf/wkt'; +import { isObjectValue } from './object'; +import { typeNameToUrl } from './utils'; +import { WKT_REGISTRY } from './wkt'; + +// Number of seconds between `0001-01-01T00:00:00Z` and the Unix epoch. +export const MIN_UNIX_TIME = -62135596800; +export const MIN_UNIX_TIME_MS = MIN_UNIX_TIME * 1000; + +// Number of seconds between `9999-12-31T23:59:59.999999999Z` and the Unix +// epoch. +export const MAX_UNIX_TIME = 253402300799; +export const MAX_UNIX_TIME_MS = MAX_UNIX_TIME * 1000; + +export function isValidTimestamp(value: Timestamp) { + return value.seconds >= MIN_UNIX_TIME && value.seconds <= MAX_UNIX_TIME; +} + +export function timestampValue(init: MessageInitShape) { + return create(ValueSchema, { + kind: { + case: 'objectValue', + value: anyPack(TimestampSchema, create(TimestampSchema, init)), + }, + }); +} + +export function isTimestampValue(value: Value): value is Value & { + kind: { case: 'objectValue'; value: Any }; +} { + return ( + isObjectValue(value) && + value.kind.value.typeUrl === typeNameToUrl(TimestampSchema.typeName) + ); +} + +export function unwrapTimestampValue(value: Value) { + if (isTimestampValue(value)) { + return anyUnpack(value.kind.value, WKT_REGISTRY) as Timestamp; + } + return null; +} diff --git a/packages/cel/src/lib/common/types/traits/comparer.ts b/packages/cel/src/lib/common/types/traits/comparer.ts new file mode 100644 index 0000000..5bf1a2f --- /dev/null +++ b/packages/cel/src/lib/common/types/traits/comparer.ts @@ -0,0 +1,17 @@ +import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb'; +import { compareBoolValue } from '../bool'; +import { compareDoubleValue } from '../double'; +import { compareInt64Value } from '../int'; + +export function compare(value: Value, other: Value) { + switch (value.kind.case) { + case 'boolValue': + return compareBoolValue(value, other); + case 'doubleValue': + return compareDoubleValue(value, other); + case 'int64Value': + return compareInt64Value(value, other); + default: + return new Error('no such overload'); + } +} diff --git a/packages/cel/src/lib/common/types/traits/math.ts b/packages/cel/src/lib/common/types/traits/math.ts new file mode 100644 index 0000000..26023a6 --- /dev/null +++ b/packages/cel/src/lib/common/types/traits/math.ts @@ -0,0 +1,70 @@ +import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { addBytesValue } from '../bytes'; +import { + addDoubleValue, + divideDoubleValue, + multiplyDoubleValue, + subtractDoubleValue, +} from '../double'; +import { + addInt64Value, + divideInt64Value, + moduloInt64Value, + multiplyInt64Value, + subtractInt64Value, +} from '../int'; + +export function adder(value: Value, other: Value) { + switch (value.kind.case) { + case 'bytesValue': + return addBytesValue(value, other); + case 'doubleValue': + return addDoubleValue(value, other); + case 'int64Value': + return addInt64Value(value, other); + default: + return new Error('no such overload'); + } +} + +export function divider(value: Value, other: Value) { + switch (value.kind.case) { + case 'doubleValue': + return divideDoubleValue(value, other); + case 'int64Value': + return divideInt64Value(value, other); + default: + return new Error('no such overload'); + } +} + +export function modder(value: Value, other: Value) { + switch (value.kind.case) { + case 'int64Value': + return moduloInt64Value(value, other); + default: + return new Error('no such overload'); + } +} + +export function multiplier(value: Value, other: Value) { + switch (value.kind.case) { + case 'doubleValue': + return multiplyDoubleValue(value, other); + case 'int64Value': + return multiplyInt64Value(value, other); + default: + return new Error('no such overload'); + } +} + +export function subtractor(value: Value, other: Value) { + switch (value.kind.case) { + case 'doubleValue': + return subtractDoubleValue(value, other); + case 'int64Value': + return subtractInt64Value(value, other); + default: + return new Error('no such overload'); + } +} diff --git a/packages/cel/src/lib/common/types/traits/negater.ts b/packages/cel/src/lib/common/types/traits/negater.ts new file mode 100644 index 0000000..5a443be --- /dev/null +++ b/packages/cel/src/lib/common/types/traits/negater.ts @@ -0,0 +1,17 @@ +import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { negateBoolValue } from '../bool'; +import { negateDoubleValue } from '../double'; +import { negateInt64Value } from '../int'; + +export function negate(value: Value) { + switch (value.kind.case) { + case 'boolValue': + return negateBoolValue(value); + case 'doubleValue': + return negateDoubleValue(value); + case 'int64Value': + return negateInt64Value(value); + default: + return new Error('no such overload'); + } +} diff --git a/packages/cel/src/lib/common/types/traits/sizer.ts b/packages/cel/src/lib/common/types/traits/sizer.ts new file mode 100644 index 0000000..591ae70 --- /dev/null +++ b/packages/cel/src/lib/common/types/traits/sizer.ts @@ -0,0 +1,11 @@ +import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { sizeBytesValue } from '../bytes'; + +export function sizer(value: Value) { + switch (value.kind.case) { + case 'bytesValue': + return sizeBytesValue(value); + default: + return new Error('no such overload'); + } +} diff --git a/packages/cel/src/lib/common/types/traits/trait.ts b/packages/cel/src/lib/common/types/traits/trait.ts new file mode 100644 index 0000000..7080a13 --- /dev/null +++ b/packages/cel/src/lib/common/types/traits/trait.ts @@ -0,0 +1,49 @@ +export enum Trait { + // AdderType types provide a '+' operator overload. + ADDER_TYPE = 1, + + // ComparerType types support ordering comparisons '<', '<=', '>', '>='. + COMPARER_TYPE = 2, + + // ContainerType types support 'in' operations. + CONTAINER_TYPE = 3, + + // DividerType types support '/' operations. + DIVIDER_TYPE = 4, + + // FieldTesterType types support the detection of field value presence. + FIELD_TESTER_TYPE = 5, + + // IndexerType types support index access with dynamic values. + INDEXER_TYPE = 6, + + // IterableType types can be iterated over in comprehensions. + ITERABLE_TYPE = 7, + + // IteratorType types support iterator semantics. + ITERATOR_TYPE = 8, + + // MatcherType types support pattern matching via 'matches' method. + MATCHER_TYPE = 9, + + // ModderType types support modulus operations '%' + MODDER_TYPE = 10, + + // MultiplierType types support '*' operations. + MULTIPLIER_TYPE = 11, + + // NegatorType types support either negation via '!' or '-' + NEGATER_TYPE = 12, + + // ReceiverType types support dynamic dispatch to instance methods. + RECEIVER_TYPE = 13, + + // SizerType types support the size() method. + SIZER_TYPE = 14, + + // SubtractorType types support '-' operations. + SUBTRACTOR_TYPE = 15, + + // FoldableType types support comprehensions v2 macros which iterate over (key, value) pairs. + FOLDABLE_TYPE = 16, +} diff --git a/packages/cel/src/lib/common/types/type.ts b/packages/cel/src/lib/common/types/type.ts index 440aa4b..1dbd66b 100644 --- a/packages/cel/src/lib/common/types/type.ts +++ b/packages/cel/src/lib/common/types/type.ts @@ -13,6 +13,14 @@ export function typeType(value: Type) { }); } +export const TYPE_TYPE = create(TypeSchema, { + typeKind: { + case: 'type', + // eslint-disable-next-line @typescript-eslint/no-explicit-any + value: null as any, + }, +}); + export function isTypeType(value: Type): value is Type & { typeKind: { case: 'type'; value: Type }; } { diff --git a/packages/cel/src/lib/common/types/uint.ts b/packages/cel/src/lib/common/types/uint.ts index 1bd073b..812dccb 100644 --- a/packages/cel/src/lib/common/types/uint.ts +++ b/packages/cel/src/lib/common/types/uint.ts @@ -14,6 +14,7 @@ import { } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; import { create } from '@bufbuild/protobuf'; import { isConstExpr } from './constant'; +import { MAX_INT64 } from './int'; import { primitiveType } from './primitive'; export const UINT64_TYPE = primitiveType(Type_PrimitiveType.UINT64); @@ -82,3 +83,12 @@ export function isUint64Value(value: Value): value is Value & { } { return value.kind.case === 'uint64Value'; } + +export function isValidUint64(value: bigint) { + return ( + !Number.isNaN(value) && + value >= BigInt(0) && + value <= MAX_INT64 && + value <= Infinity + ); +} diff --git a/packages/cel/src/lib/common/types/utils.ts b/packages/cel/src/lib/common/types/utils.ts index 260999a..aa78f17 100644 --- a/packages/cel/src/lib/common/types/utils.ts +++ b/packages/cel/src/lib/common/types/utils.ts @@ -146,3 +146,7 @@ export function getWellKNownTypeName(type: Type_WellKnownType): string | null { return null; } } + +export function typeNameToUrl(name: string): string { + return `type.googleapis.com/${name}`; +} diff --git a/packages/cel/src/lib/common/types/wkt.ts b/packages/cel/src/lib/common/types/wkt.ts index fd912e8..675277c 100644 --- a/packages/cel/src/lib/common/types/wkt.ts +++ b/packages/cel/src/lib/common/types/wkt.ts @@ -3,7 +3,12 @@ import { TypeSchema, Type_WellKnownType, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb'; -import { create } from '@bufbuild/protobuf'; +import { create, createRegistry } from '@bufbuild/protobuf'; +import { + AnySchema, + DurationSchema, + TimestampSchema, +} from '@bufbuild/protobuf/wkt'; import { BOOL_TYPE } from './bool'; import { BYTES_TYPE } from './bytes'; import { DOUBLE_TYPE } from './double'; @@ -106,3 +111,9 @@ export function getCheckedWellKnownType(value: string) { return null; } } + +export const WKT_REGISTRY = createRegistry( + AnySchema, + DurationSchema, + TimestampSchema +); diff --git a/packages/cel/src/lib/common/utils.ts b/packages/cel/src/lib/common/utils.ts index 0e10477..d66d671 100644 --- a/packages/cel/src/lib/common/utils.ts +++ b/packages/cel/src/lib/common/utils.ts @@ -28,6 +28,16 @@ export function mapToObject( return obj; } +export function objectToMap( + obj: Record +) { + const map = new Map(); + for (const key of Object.keys(obj) as K[]) { + map.set(key, obj[key]); + } + return map; +} + /** * Converts an expression AST into a qualified name if possible, or an empty * string otherwise. diff --git a/packages/cel/src/lib/interpreter/activation.ts b/packages/cel/src/lib/interpreter/activation.ts new file mode 100644 index 0000000..16ee234 --- /dev/null +++ b/packages/cel/src/lib/interpreter/activation.ts @@ -0,0 +1,41 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import { isMap, isNil } from '@bearclaw/is'; +import { dequal } from 'dequal'; +import { objectToMap } from '../common/utils'; + +export class ResolvedValue { + public static readonly NULL_VALUE = new ResolvedValue(null, true); + public static readonly ABSENT = new ResolvedValue(null, false); + + constructor(public readonly value: T, public readonly present: boolean) {} + + equals(other: ResolvedValue): boolean { + return dequal(this, other); + } +} + +export abstract class Activation { + abstract resolveName(name: string): ResolvedValue | null; +} + +export class MapActivation implements Activation { + #bindings: Map; + + constructor(bindings: Map | Record) { + this.#bindings = isMap(bindings) + ? bindings + : objectToMap(bindings); + } + + public resolveName(name: string): ResolvedValue { + if (!this.#bindings.has(name)) { + return ResolvedValue.ABSENT as ResolvedValue; + } + const obj: T = this.#bindings.get(name); + if (isNil(obj)) { + return ResolvedValue.NULL_VALUE as ResolvedValue; + } + return new ResolvedValue(obj, true); + } +} diff --git a/packages/cel/src/lib/interpreter/attributes.ts b/packages/cel/src/lib/interpreter/attributes.ts new file mode 100644 index 0000000..70531c2 --- /dev/null +++ b/packages/cel/src/lib/interpreter/attributes.ts @@ -0,0 +1,231 @@ +// /* eslint-disable @typescript-eslint/no-explicit-any */ +// import { isNil } from '@bearclaw/is'; +// import { Type } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb'; +// import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb'; +// import { Registry } from '@bufbuild/protobuf'; +// import { CELContainer } from '../cel'; +// import { Activation } from './activation'; +// import { Interpretable } from './interpretable'; + +// // AttributeFactory provides methods creating Attribute and Qualifier values. +// export class AttributeFactory { +// constructor( +// protected readonly container: CELContainer, +// protected readonly registry: Registry, +// protected readonly errorOnBadPresenceTest: boolean +// ) {} + +// // AbsoluteAttribute creates an attribute that refers to a top-level +// // variable name. +// // +// // Checked expressions generate absolute attribute with a single name. +// // Parse-only expressions may have more than one possible absolute +// // identifier when the expression is created within a container, e.g. +// // package or namespace. +// // +// // When there is more than one name supplied to the AbsoluteAttribute call, +// // the names must be in CEL's namespace resolution order. The name +// // arguments provided here are returned in the same order as they were +// // provided by the NamespacedAttribute +// // CandidateVariableNames method. +// absoluteAttribute(id: bigint, ...names: string[]): NamespacedAttribute { +// return new AbsoluteAttribute( +// id, +// names, +// [], +// this.registry, +// this, +// this.errorOnBadPresenceTest +// ); +// } + +// // ConditionalAttribute creates an attribute with two Attribute branches, +// // where the Attribute that is resolved depends on the boolean evaluation of +// // the input 'expr'. +// conditionalAttribute( +// id: bigint, +// expr: Interpretable, +// t: Attribute, +// f: Attribute +// ): Attribute; + +// // MaybeAttribute creates an attribute that refers to either a field +// // selection or a namespaced variable name. +// // +// // Only expressions which have not been type-checked may generate oneof +// // attributes. +// maybeAttribute(id: bigint, name: string): Attribute; + +// // RelativeAttribute creates an attribute whose value is a qualification of a +// // dynamic computation rather than a static variable reference. +// relativeAttribute(id: bigint, operand: Interpretable): Attribute; + +// // NewQualifier creates a qualifier on the target object with a given value. +// // +// // The 'val' may be an Attribute or any proto-supported map key type: bool, +// // int, string, uint. +// // +// // The qualifier may consider the object type being qualified, if present. +// // If absent, the qualification should be considered dynamic and the +// // qualification should still work, though it may be sub-optimal. +// newQualifier( +// objType: Type, +// qualID: bigint, +// val: any, +// opt: boolean +// ): Qualifier | Error; +// } + +// // Qualifier marker interface for designating different qualifier values and +// // where they appear within field selections and index call expressions \ +// // (`_[_]`). +// export class Qualifier { +// // ID where the qualifier appears within an expression. +// id(): bigint; + +// // IsOptional specifies whether the qualifier is optional. +// // Instead of a direct qualification, an optional qualifier will be resolved +// // via QualifyIfPresent rather than Qualify. A non-optional qualifier may +// // also be resolved through QualifyIfPresent if the object to qualify is +// // itself optional. +// isOptional(): boolean; + +// // Qualify performs a qualification, e.g. field selection, on the input +// // object and returns the value of the access and whether the value was set. +// // A non-nil value with a false presence test result indicates that the value +// // being returned is the default value. +// qualify(vars: Activation, obj: any): any | Error; + +// // QualifyIfPresent qualifies the object if the qualifier is declared or +// // defined on the object. +// // The 'presenceOnly' flag indicates that the value is not necessary, just a +// // boolean status as to whether the qualifier is present. +// qualifyIfPresent( +// vars: Activation, +// obj: any, +// presenceOnly: boolean +// ): any | boolean | Error; +// } + +// // ConstantQualifier interface embeds the Qualifier interface and provides an +// // option to inspect the qualifier's constant value. +// // +// // Non-constant qualifiers are of Attribute type. +// export class ConstantQualifier extends Qualifier { +// // Value returns the constant value associated with the qualifier. +// value(): Value; +// } + +// // Attribute values are a variable or value with an optional set of qualifiers, +// // such as field, key, or index accesses. +// export class Attribute extends Qualifier { +// // AddQualifier adds a qualifier on the Attribute or error if the +// // qualification is not a valid qualifier type. +// addQualifier(qualifier: Qualifier): Attribute | Error; + +// // Resolve returns the value of the Attribute and whether it was present +// // given an Activation. +// // For objects which support safe traversal, the value may be non-nil and +// // the presence flag be false. +// // +// // If an error is encountered during attribute resolution, it will be +// // returned immediately. +// // If the attribute cannot be resolved within the Activation, the result +// // must be: `nil`, `error` +// // with the error indicating which variable was missing. +// resolve(activation: Activation): any | Error; +// } + +// // NamespacedAttribute values are a variable within a namespace, and an optional set of qualifiers +// // such as field, key, or index accesses. +// export interface NamespacedAttribute extends Attribute { +// // CandidateVariableNames returns the possible namespaced variable names for +// // this Attribute in the CEL namespace resolution order. +// candidateVariableNames(): string[]; + +// // Qualifiers returns the list of qualifiers associated with the Attribute. +// qualifiers(): Qualifier[]; +// } + +// export class AbsoluteAttribute { +// constructor( +// protected readonly _id: bigint, +// protected readonly _namespacedNames: string[], +// protected readonly _qualifiers: Qualifier[], +// protected readonly _registry: Registry, +// protected readonly _fac: AttributeFactory, +// protected readonly _errorOnBadPresenceTest: boolean +// ) {} + +// // ID implements the Attribute interface method. +// id(): bigint { +// if (this._qualifiers.length === 0) { +// return this._id; +// } +// return this._qualifiers[this._qualifiers.length - 1].id(); +// } + +// // IsOptional returns trivially false for an attribute as the attribute +// // represents a fully qualified variable name. If the attribute is used in an +// // optional manner, then an attrQualifier is created and marks the attribute +// // as optional. +// isOptional(): boolean { +// return false; +// } + +// // AddQualifier implements the Attribute interface method. +// addQualifier(qualifier: Qualifier): Attribute | Error { +// this._qualifiers.push(qualifier); +// return this; +// } + +// // CandidateVariableNames implements the NamespaceAttribute interface method. +// candidateVariableNames(): string[] { +// return this._namespacedNames; +// } + +// // Qualifiers returns the list of Qualifier instances associated with the \ +// // namespaced attribute. +// qualifiers(): Qualifier[] { +// return this._qualifiers; +// } + +// // Qualify is an implementation of the Qualifier interface method. +// qualify(vars: Activation, obj: any): any | Error { +// // TODO: Implement +// } + +// // QualifyIfPresent is an implementation of the Qualifier interface method. +// qualifyIfPresent( +// vars: Activation, +// obj: any, +// presenceOnly: boolean +// ): any | boolean | Error { +// // TODO: Implement +// } + +// // String implements the Stringer interface method. +// string(): string { +// return `id: ${this.id()}, names: ${this._namespacedNames.join(', ')}`; +// } + +// // Resolve returns the resolved Attribute value given the Activation, or +// // error if the Attribute variable is not found, or if its Qualifiers cannot +// // be applied successfully. +// // +// // If the variable name cannot be found as an Activation variable or in the +// // TypeProvider as a type, then the result is `nil`, `error` with the error +// // indicating the name of the first variable searched as missing. +// resolve(vars: Activation): any | Error { +// for (const name of this._namespacedNames) { +// // If the variable is found, process it. Otherwise, wait until the checks +// // to determine whether the type is unknown before returning. +// const obj = vars.resolveName(name); +// if (!isNil(obj)) { +// if (obj instanceof Error) { +// return obj; +// } +// } +// } +// } +// } diff --git a/packages/cel/src/lib/interpreter/dispatcher.ts b/packages/cel/src/lib/interpreter/dispatcher.ts new file mode 100644 index 0000000..2acf7ab --- /dev/null +++ b/packages/cel/src/lib/interpreter/dispatcher.ts @@ -0,0 +1,48 @@ +import { Overload } from './overload'; + +/** + * Dispatcher resolves function calls to their appropriate overload. + */ +export class Dispatcher { + #parent: Dispatcher | null = null; + #overloads: Map = new Map(); + + /** + * Add one or more overloads, returning an error if any Overload has the + * same name. + * + * @param overloads the overloads to add + */ + add(...overloads: Overload[]) { + for (let i = 0; i < overloads.length; i++) { + const overload = overloads[i]; + if (this.#overloads.has(overload.operator)) { + throw new Error(`Overload ${overload.operator} already exists`); + } + this.#overloads.set(overload.operator, overload); + } + } + + /** + * Returns an Overload definition matching the provided name. + * + * @param overload the name of the overload to find + * @returns the Overload definition or null if not found + */ + findOverload(overload: string): Overload | null { + return this.#overloads.get(overload) || null; + } + + /** + * Returns the set of all overload identifiers configured for dispatch. + * + * @returns the set of overload identifiers + */ + overloadIds(): string[] { + const overloadIds = []; + for (const overload of this.#overloads.values()) { + overloadIds.push(overload.operator); + } + return overloadIds; + } +} diff --git a/packages/cel/src/lib/interpreter/interpretable.ts b/packages/cel/src/lib/interpreter/interpretable.ts new file mode 100644 index 0000000..18e66c8 --- /dev/null +++ b/packages/cel/src/lib/interpreter/interpretable.ts @@ -0,0 +1,17 @@ +import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb'; +import { Activation } from './activation'; + +export interface Interpretable { + // ID value corresponding to the expression node. + id: bigint; + + // Eval an Activation to produce an output. + eval: (ctx: Activation) => Value | Error; +} + +// InterpretableConst interface for tracking whether the Interpretable is a +// constant value. +export interface InterpretableConst extends Interpretable { + // Value returns the constant value of the instruction. + value: Value; +} diff --git a/packages/cel/src/lib/interpreter/overload.ts b/packages/cel/src/lib/interpreter/overload.ts new file mode 100644 index 0000000..e704140 --- /dev/null +++ b/packages/cel/src/lib/interpreter/overload.ts @@ -0,0 +1,63 @@ +import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { Trait } from '../common/types/traits/trait'; + +/** + * A function that takes a single value and produces an output. + */ +export type UnaryOp = (value: Value) => Value; + +/** + * A function that takes two values and produces an output. + */ +export type BinaryOp = (left: Value, right: Value) => Value; + +/** + * A function which accepts zero or more arguments and produces a value or + * error as a result + */ +export type FunctionOp = (values: Value[]) => Value; + +/** + * Defines a named overload of a function, indicating an operand trait + * which must be present on the first argument to the overload as well as one + * of either a unary, binary, or function implementation. + * + * The majority of operators within the expression language are unary or binary + * and the specializations simplify the call contract for implementers of + * types with operator overloads. Any added complexity is assumed to be handled + * by the generic FunctionOp. + */ +export interface Overload { + /** + * Operator name as written in an expression + */ + operator: string; + + /** + * Operand trait used to dispatch the call. The zero-value indicates a + * global function overload or that one of the Unary / Binary / Function + * definitions should be used to execute the call. + */ + operandTrait: Trait; + + /** + * Unary defines the overload with a UnaryOp implementation. May be nil. + */ + unary?: UnaryOp; + + /** + * Binary defines the overload with a BinaryOp implementation. May be nil. + */ + binary?: BinaryOp; + + /** + * Function defines the overload with a FunctionOp implementation. May be nil. + */ + function?: FunctionOp; + + /** + * NonStrict specifies whether the Overload will tolerate arguments that are + * types.Err or types.Unknown. + */ + nonStrict: boolean; +} diff --git a/packages/cel/src/lib/interpreter/planner.ts b/packages/cel/src/lib/interpreter/planner.ts new file mode 100644 index 0000000..e69de29 From 627b67e5cc69598d0b2157705f7babe3d7cdb315 Mon Sep 17 00:00:00 2001 From: jafaircl Date: Wed, 30 Oct 2024 20:37:23 -0400 Subject: [PATCH 28/34] feat(cel): interpreter checkpoint --- packages/cel/src/lib/common/ref/adapter.ts | 13 ++ packages/cel/src/lib/common/ref/field-type.ts | 14 ++ packages/cel/src/lib/common/ref/provider.ts | 46 ++++++ .../cel/src/lib/interpreter/activation.ts | 142 ++++++++++++++++-- packages/cel/src/lib/interpreter/coster.ts | 46 ++++++ .../cel/src/lib/interpreter/resolved-value.ts | 13 ++ 6 files changed, 260 insertions(+), 14 deletions(-) create mode 100644 packages/cel/src/lib/common/ref/adapter.ts create mode 100644 packages/cel/src/lib/common/ref/field-type.ts create mode 100644 packages/cel/src/lib/common/ref/provider.ts create mode 100644 packages/cel/src/lib/interpreter/coster.ts create mode 100644 packages/cel/src/lib/interpreter/resolved-value.ts diff --git a/packages/cel/src/lib/common/ref/adapter.ts b/packages/cel/src/lib/common/ref/adapter.ts new file mode 100644 index 0000000..acbe4b8 --- /dev/null +++ b/packages/cel/src/lib/common/ref/adapter.ts @@ -0,0 +1,13 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; + +/** + * TypeAdapter converts native Go values of varying type and complexity to + * equivalent CEL values. + */ +export interface TypeAdapter { + /** + * NativeToValue converts the input `value` to a CEL `Value`. + */ + nativeToValue(value: any): Value; +} diff --git a/packages/cel/src/lib/common/ref/field-type.ts b/packages/cel/src/lib/common/ref/field-type.ts new file mode 100644 index 0000000..75d24e9 --- /dev/null +++ b/packages/cel/src/lib/common/ref/field-type.ts @@ -0,0 +1,14 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { Type } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; + +/** + * FieldType represents a field's type value and whether that field supports + * presence detection. + */ +export class FieldType { + constructor( + public readonly type: Type, + public readonly isSet: (obj: any) => boolean, + public readonly getFrom: (obj: any) => any + ) {} +} diff --git a/packages/cel/src/lib/common/ref/provider.ts b/packages/cel/src/lib/common/ref/provider.ts new file mode 100644 index 0000000..bae51bd --- /dev/null +++ b/packages/cel/src/lib/common/ref/provider.ts @@ -0,0 +1,46 @@ +import { Type } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { FieldType } from './field-type'; + +/** + * TypeProvider specifies functions for creating new object instances and for + * resolving enum values by name. + */ +export interface TypeProvider { + /** + * EnumValue returns the numeric value of the given enum value name. + */ + enumValue(enumName: string): Value; + + /** + * FindIdent takes a qualified identifier name and returns a Value if one + * exists. + */ + findIdent(identName: string): Value | null; + + /** + * FindType looks up the Type given a qualified typeName. Returns null if + * not found. + * + * Used during type-checking only. + */ + findType(typeName: string): Type | null; + + /** + * FieldFieldType returns the field type for a checked type value. Returns + * null if the field could not be found. + * + *

Used during type-checking only. + */ + findFieldType(messageType: string, fieldName: string): FieldType | null; + + /** + * NewValue creates a new type value from a qualified name and map of field + * name to value. + * + * Note, for each value, the Val.ConvertToNative function will be invoked to + * convert the Val to the field's native type. If an error occurs during + * conversion, the NewValue will be an Error. + */ + newValue(typeName: string, fields: Record): Value | Error; +} diff --git a/packages/cel/src/lib/interpreter/activation.ts b/packages/cel/src/lib/interpreter/activation.ts index 16ee234..50c3c7b 100644 --- a/packages/cel/src/lib/interpreter/activation.ts +++ b/packages/cel/src/lib/interpreter/activation.ts @@ -1,24 +1,35 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { isMap, isNil } from '@bearclaw/is'; -import { dequal } from 'dequal'; +import { isMap, isNil, isPlainObject } from '@bearclaw/is'; import { objectToMap } from '../common/utils'; +import { ResolvedValue } from './resolved-value'; -export class ResolvedValue { - public static readonly NULL_VALUE = new ResolvedValue(null, true); - public static readonly ABSENT = new ResolvedValue(null, false); +/** + * Activation used to resolve identifiers by name and references by id. + * + * An Activation is the primary mechanism by which a caller supplies input + * into a CEL program. + */ +export interface Activation { + /** + * ResolveName returns a value from the activation by qualified name, or + * false if the name could not be found. + */ + resolveName(name: string): ResolvedValue | null; - constructor(public readonly value: T, public readonly present: boolean) {} - - equals(other: ResolvedValue): boolean { - return dequal(this, other); - } -} - -export abstract class Activation { - abstract resolveName(name: string): ResolvedValue | null; + /** + * Parent returns the parent of the current activation, may be nil. If + * non-nil, the parent will be searched during resolve calls. + */ + parent(): Activation | null; } +/** + * mapActivation which implements Activation and maps of named values. + * + * Named bindings may lazily supply values by providing a function which + * accepts no arguments and produces an interface value. + */ export class MapActivation implements Activation { #bindings: Map; @@ -38,4 +49,107 @@ export class MapActivation implements Activation { } return new ResolvedValue(obj, true); } + + public parent(): Activation | null { + return null; + } +} + +/** + * FunctionActivation which implements Activation and a provider of named + * values. + */ +export class FunctionActivation implements Activation { + #provider: (name: string) => any; + + constructor(provider: (name: string) => any) { + this.#provider = provider; + } + + parent(): Activation | null { + return null; + } + + resolveName(name: string): ResolvedValue | null { + const obj = this.#provider(name); + if (obj instanceof ResolvedValue) { + return obj; + } else if (isNil(obj)) { + return ResolvedValue.ABSENT as ResolvedValue; + } + return new ResolvedValue(obj, true); + } +} + +/** + * HierarchicalActivation which implements Activation and contains a parent and + * child activation. + */ +export class HierarchicalActivation implements Activation { + #parent: Activation; + #child: Activation; + + constructor(parent: Activation, child: Activation) { + this.#parent = parent; + this.#child = child; + } + + public resolveName(name: string): ResolvedValue | null { + const value = this.#child.resolveName(name); + if (!isNil(value)) { + return value; + } + return this.#parent.resolveName(name); + } + + public parent(): Activation | null { + return this.#parent; + } +} + +/** + * NewActivation returns an activation based on a map-based binding where the + * map keys are expected to be qualified names used with ResolveName calls. + * + * The input `bindings` may either be of type `Activation` or + * `map[stringinterface{}`. + * + * Lazy bindings may be supplied within the map-based input in either of the + * following forms: + * - func() interface{} + * - func() ref.Val + * + * The output of the lazy binding will overwrite the variable reference in the + * internal map. + * + * Values which are not represented as ref.Val types on input may be adapted to + * a ref.Val using the ref.TypeAdapter configured in the environment. + */ +export function newActivation(bindings: any) { + if (isNil(bindings)) { + throw new Error('bindings must be non-nil'); + } + if ( + bindings instanceof MapActivation || + bindings instanceof FunctionActivation || + bindings instanceof HierarchicalActivation + ) { + return bindings; + } + if (bindings instanceof Map || isPlainObject(bindings)) { + return new MapActivation(bindings); + } + if (typeof bindings === 'function') { + return new FunctionActivation(bindings); + } + throw new Error( + `activation input must be an activation or map[string]interface: got ${typeof bindings}` + ); +} + +/** + * EmptyActivation returns a variable free activation. + */ +export function emptyActivation() { + return newActivation(new Map()); } diff --git a/packages/cel/src/lib/interpreter/coster.ts b/packages/cel/src/lib/interpreter/coster.ts new file mode 100644 index 0000000..a56cfef --- /dev/null +++ b/packages/cel/src/lib/interpreter/coster.ts @@ -0,0 +1,46 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +export class Cost { + public static Unknown: Cost = new Cost(0, Number.MAX_VALUE); + public static None: Cost = new Cost(0, 0); + public static OneOne: Cost = new Cost(1, 1); + public readonly min: number; + public readonly max: number; + + constructor(min: number, max: number) { + this.min = min; + this.max = max; + } + + /** + * estimateCost returns the heuristic cost interval for the program. + */ + public estimateCost(obj: any): Cost { + if (obj instanceof Coster) { + return obj.cost(); + } + return Cost.Unknown; + } + + equals(other: Cost): boolean { + return this.min === other.min && this.max === other.max; + } + + add(other: Cost): Cost { + return new Cost(this.min + other.min, this.max + other.max); + } + + multiply(multiplier: number): Cost { + return new Cost(this.min * multiplier, this.max * multiplier); + } +} + +/** + * Coster calculates the heuristic cost incurred during evaluation. + */ +export class Coster { + constructor(private readonly _cost: Cost = Cost.Unknown) {} + + cost(): Cost { + return this._cost; + } +} diff --git a/packages/cel/src/lib/interpreter/resolved-value.ts b/packages/cel/src/lib/interpreter/resolved-value.ts new file mode 100644 index 0000000..7d2e8ff --- /dev/null +++ b/packages/cel/src/lib/interpreter/resolved-value.ts @@ -0,0 +1,13 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { dequal } from 'dequal'; + +export class ResolvedValue { + public static readonly NULL_VALUE = new ResolvedValue(null, true); + public static readonly ABSENT = new ResolvedValue(null, false); + + constructor(public readonly value: T, public readonly present: boolean) {} + + equals(other: ResolvedValue): boolean { + return dequal(this, other); + } +} From bdb35d112f19b9bfc8d009e79d3676e1c67a43c8 Mon Sep 17 00:00:00 2001 From: jafaircl Date: Thu, 31 Oct 2024 17:15:21 -0400 Subject: [PATCH 29/34] feat(cel): interpreter checkpoint --- .../src/lib/interpreter/attribute-factory.ts | 632 ++++++++++++++++++ .../src/lib/interpreter/attribute-pattern.ts | 22 + .../cel/src/lib/interpreter/attributes.ts | 231 ------- packages/cel/src/lib/interpreter/coster.ts | 14 +- .../cel/src/lib/interpreter/interpretable.ts | 5 +- .../cel/src/lib/interpreter/resolved-value.ts | 2 +- 6 files changed, 664 insertions(+), 242 deletions(-) create mode 100644 packages/cel/src/lib/interpreter/attribute-factory.ts create mode 100644 packages/cel/src/lib/interpreter/attribute-pattern.ts delete mode 100644 packages/cel/src/lib/interpreter/attributes.ts diff --git a/packages/cel/src/lib/interpreter/attribute-factory.ts b/packages/cel/src/lib/interpreter/attribute-factory.ts new file mode 100644 index 0000000..4871f3d --- /dev/null +++ b/packages/cel/src/lib/interpreter/attribute-factory.ts @@ -0,0 +1,632 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { isFunction, isNil } from '@bearclaw/is'; +import { Type } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { ExprValue } from '@buf/google_cel-spec.bufbuild_es/cel/expr/eval_pb.js'; +import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { CELContainer } from '../cel'; +import { + isExprValueError, + isExprValueUnknown, + isExprValueValue, +} from '../common/expr-value'; +import { TypeAdapter } from '../common/ref/adapter'; +import { TypeProvider } from '../common/ref/provider'; +import { isBoolValue } from '../common/types/bool'; +import { isStringValue } from '../common/types/string'; +import { Activation } from './activation'; +import { QualifierValueEquator } from './attribute-pattern'; +import { Cost, Coster } from './coster'; +import { Interpretable } from './interpretable'; + +/** + * AttributeFactory provides methods creating Attribute and Qualifier values. + */ +export interface AttributeFactory { + /** + * AbsoluteAttribute creates an attribute that refers to a top-level variable + * name. + * + * Checked expressions generate absolute attribute with a single name. + * Parse-only expressions may have more than one possible absolute identifier + * when the expression is created within a container, e.g. package or + * namespace. + * + * When there is more than one name supplied to the AbsoluteAttribute call, + * the names must be in CEL's namespace resolution order. The name arguments + * provided here are returned in the same order as they were provided by the + * NamespacedAttribute CandidateVariableNames method. + */ + absoluteAttribute(id: bigint, ...names: string[]): NamespacedAttribute; + + /** + * ConditionalAttribute creates an attribute with two Attribute branches, + * where the Attribute that is resolved depends on the boolean evaluation of + * the input 'expr'. + */ + conditionalAttribute( + id: bigint, + expr: Interpretable, + t: Attribute, + f: Attribute + ): Attribute; + + /** + * MaybeAttribute creates an attribute that refers to either a field + * selection or a namespaced variable name. + * + * Only expressions which have not been type-checked may generate oneof + * attributes. + */ + maybeAttribute(id: bigint, name: string): Attribute; + + /** + * RelativeAttribute creates an attribute whose value is a qualification of a + * dynamic computation rather than a static variable reference. + */ + relativeAttribute(id: bigint, operand: Interpretable): Attribute; + + /** + * NewQualifier creates a qualifier on the target object with a given value. + * + * The 'val' may be an Attribute or any proto-supported map key type: bool, + * int, string, uint. + * + * The qualifier may consider the object type being qualified, if present. If + * absent, the qualification should be considered dynamic and the + * qualification should still work, though it may be sub-optimal. + */ + newQualifier(objType: Type | null, qualID: bigint, val: any): Qualifier; +} + +/** + * Qualifier marker interface for designating different qualifier values and + * where they appear within field selections and index call expressions + * (`_[_]`). + */ +export interface Qualifier { + /** + * ID where the qualifier appears within an expression. + */ + id(): bigint; + + /** + * Qualify performs a qualification, e.g. field selection, on the input + * object and returns the value or error that results. + */ + qualify(vars: Activation, obj: any): ExprValue; +} + +/** + * ConstantQualifier interface embeds the Qualifier interface and provides an + * option to inspect the qualifier's constant value. + * + * Non-constant qualifiers are of Attribute type. + */ +export interface ConstantQualifier extends Qualifier { + value(): Value; +} + +export interface ConstantQualifierEquator + extends QualifierValueEquator, + ConstantQualifier {} + +/** + * Attribute values are a variable or value with an optional set of qualifiers, + * such as field, key, or index accesses. + */ +interface Attribute extends Qualifier { + /** + * AddQualifier adds a qualifier on the Attribute or error if the + * qualification is not a valid qualifier type. + */ + addQualifier(q: Qualifier): Attribute; + + /** + * Resolve returns the value of the Attribute given the current Activation. + */ + resolve(a: Activation): ExprValue; +} + +/** + * NamespacedAttribute values are a variable within a namespace, and an + * optional set of qualifiers such as field, key, or index accesses. + */ +export interface NamespacedAttribute extends Attribute { + /** + * CandidateVariableNames returns the possible namespaced variable names for + * this Attribute in the CEL namespace resolution order. + */ + candidateVariableNames(): string[]; + + /** + * Qualifiers returns the list of qualifiers associated with the Attribute.s */ + qualifiers(): Qualifier[]; + + /** + * TryResolve attempts to return the value of the attribute given the current + * Activation. If an error is encountered during attribute resolution, it + * will be returned immediately. If the attribute cannot be resolved within + * the Activation, the result must be: `nil`, `false`, `nil`. + */ + tryResolve(a: Activation): ExprValue | null; +} + +export class AttrFactory implements AttributeFactory { + readonly #container: CELContainer; + readonly #adapter: TypeAdapter; + readonly #provider: TypeProvider; + + constructor( + container: CELContainer, + adapter: TypeAdapter, + provider: TypeProvider + ) { + this.#container = container; + this.#adapter = adapter; + this.#provider = provider; + } + + absoluteAttribute(id: bigint, ...names: string[]): NamespacedAttribute { + return new AbsoluteAttribute( + id, + names, + [], + this.#adapter, + this.#provider, + this + ); + } + + conditionalAttribute( + id: bigint, + expr: Interpretable, + t: Attribute, + f: Attribute + ): Attribute { + return new ConditionalAttribute(id, expr, t, f, this.#adapter, this); + } + + maybeAttribute(id: bigint, name: string): Attribute { + const attrs = [ + this.absoluteAttribute( + id, + ...this.#container.resolveCandidateNames(name) + ), + ]; + return new MaybeAttribute(id, attrs, this.#adapter, this.#provider, this); + } + + relativeAttribute(id: bigint, operand: Interpretable): Attribute { + return new RelativeAttribute(id, operand, [], this.#adapter, this); + } + + newQualifier(objType: Type, qualID: bigint, val: any): Qualifier { + throw new Error('Method not implemented.'); + } +} + +export class AbsoluteAttribute + implements Qualifier, NamespacedAttribute, Coster +{ + readonly #id: bigint; + /** + * namespaceNames represent the names the variable could have based on + * declared container (package) of the expression. + */ + readonly #namespacedNames: string[]; + readonly #qualifiers: Qualifier[]; + readonly #adapter: TypeAdapter; + readonly #provider: TypeProvider; + readonly #fac: AttributeFactory; + + constructor( + id: bigint, + namespacedNames: string[], + qualifiers: Qualifier[], + adapter: TypeAdapter, + provider: TypeProvider, + fac: AttributeFactory + ) { + this.#id = id; + this.#namespacedNames = namespacedNames; + this.#qualifiers = qualifiers; + this.#adapter = adapter; + this.#provider = provider; + this.#fac = fac; + } + + id(): bigint { + return this.#id; + } + + /** + * Cost implements the Coster interface method. + */ + cost(): Cost { + let min = 0; + let max = 0; + for (const qualifier of this.#qualifiers) { + const qc = Cost.estimateCost(qualifier); + min += qc.min; + max += qc.max; + } + min++; // For object retrieval. + max++; + return new Cost(min, max); + } + + qualifiers(): Qualifier[] { + return this.#qualifiers; + } + + addQualifier(q: Qualifier): Attribute { + this.#qualifiers.push(q); + return this; + } + + candidateVariableNames(): string[] { + return this.#namespacedNames; + } + + qualify(vars: Activation, obj: any): any { + const val = this.resolve(vars); + if (isExprValueUnknown(val)) { + return val; + } + const qual = this.#fac.newQualifier(null, this.#id, val); + return qual.qualify(vars, obj); + } + + resolve(vars: Activation): T { + return this.tryResolve(vars); + } + + tryResolve(vars: Activation): T { + for (const nm of this.#namespacedNames) { + // If the variable is found, process it. Otherwise, wait until the checks\ + // to determine whether the type is unknown before returning. + const obj = vars.resolveName(nm); + if (obj?.present) { + let op = obj.value; + for (const qual of this.#qualifiers) { + const op2 = qual.qualify(vars, op); + if (op2 instanceof Error) { + return op2 as T; + } + if (op2 == null) { + break; + } + op = op2; + } + return op as T; + } + // Attempt to resolve the qualified type name if the name is not a + // variable identifier. + const typ = this.#provider.findIdent(nm); + if (!isNil(typ)) { + if (this.#qualifiers.length === 0) { + return typ as T; + } + throw noSuchAttributeException(this.toString()); + } + } + throw noSuchAttributeException(this.toString()); + } + + /** + * String implements the Stringer interface method. + */ + toString() { + return 'id: ' + this.#id + ', names: ' + this.#namespacedNames.join(', '); + } +} + +export class ConditionalAttribute implements Qualifier, Attribute, Coster { + readonly #id: bigint; + readonly #expr: Interpretable; + readonly #truthy: Attribute; + readonly #falsy: Attribute; + readonly #adapter: TypeAdapter; + readonly #fac: AttributeFactory; + + constructor( + id: bigint, + expr: Interpretable, + truthy: Attribute, + falsy: Attribute, + adapter: TypeAdapter, + fac: AttributeFactory + ) { + this.#id = id; + this.#expr = expr; + this.#truthy = truthy; + this.#falsy = falsy; + this.#adapter = adapter; + this.#fac = fac; + } + + id(): bigint { + return this.#id; + } + + /** + * Cost provides the heuristic cost of a ternary operation `expr ? t : f`. + * The cost is computed as `cost(expr)` plus the min/max costs of evaluating + * either `t` or `f`. + */ + cost(): Cost { + const t = Cost.estimateCost(this.#truthy); + const f = Cost.estimateCost(this.#falsy); + const e = Cost.estimateCost(this.#expr); + return new Cost( + e.min + Math.min(t.min, f.min), + e.max + Math.max(t.max, f.max) + ); + } + + /** + * AddQualifier appends the same qualifier to both sides of the conditional, + * in effect managing the qualification of alternate attributes. + */ + addQualifier(q: Qualifier): Attribute { + this.#truthy.addQualifier(q); + this.#falsy.addQualifier(q); + return this; + } + + qualify(vars: Activation, obj: any) { + const val = this.resolve(vars); + if (isExprValueUnknown(val)) { + return val; + } + const qual = this.#fac.newQualifier(null, this.#id, val); + return qual.qualify(vars, obj); + } + + resolve(vars: Activation) { + const val = this.#expr.eval(vars); + if (isExprValueError(val)) { + throw new Error( + `messsage: ${val.kind.value.errors.map((e) => e.message).join(', ')}` + ); + } + if (isExprValueValue(val)) { + const v = val.kind.value; + if (!isBoolValue(v)) { + // This should never happen + throw new Error('conditional expression must be a boolean'); + } + if (v.kind.value) { + return this.#truthy.resolve(vars); + } + return this.#falsy.resolve(vars); + } + if (isExprValueUnknown(val)) { + return val; + } + return val; + } + + toString() { + return `id: ${ + this.#id + }, truthy attribute: ${this.#truthy.id()}, falsy attribute: ${this.#falsy.id()}`; + } +} + +export class MaybeAttribute implements Coster, Attribute, Qualifier { + readonly #id: bigint; + readonly #attrs: NamespacedAttribute[]; + readonly #adapter: TypeAdapter; + readonly #provider: TypeProvider; + readonly #fac: AttributeFactory; + + constructor( + id: bigint, + attrs: NamespacedAttribute[], + adapter: TypeAdapter, + provider: TypeProvider, + fac: AttributeFactory + ) { + this.#id = id; + this.#attrs = attrs; + this.#adapter = adapter; + this.#provider = provider; + this.#fac = fac; + } + + id(): bigint { + return this.#id; + } + + /** + * Cost implements the Coster interface method. The min cost is computed as + * the minimal cost among all the possible attributes, the max cost ditto. + */ + cost(): Cost { + let min = Number.MAX_VALUE; + let max = 0; + for (const attr of this.#attrs) { + const ac = Cost.estimateCost(attr); + min = Math.min(min, ac.min); + max = Math.max(max, ac.max); + } + return new Cost(min, max); + } + + /** + * AddQualifier adds a qualifier to each possible attribute variant, and also + * creates a new namespaced variable from the qualified value. + * + * The algorithm for building the maybe attribute is as follows: + * + * - Create a maybe attribute from a simple identifier when it occurs in a + * parsed-only expression `mb = MaybeAttribute(id, "a")` + * - Initializing the maybe attribute creates an absolute attribute + * internally which includes the possible namespaced names of the attribute. + * In this example, let's assume we are in namespace 'ns', then the maybe is + * either one of the following variable names: + * - possible variables names -- ns.a, a + * - Adding a qualifier to the maybe means that the variable name could be + * a longer qualified name, or a field selection on one of the possible + * variable names produced earlier: + * `mb.AddQualifier("b")` + * - possible variables names -- ns.a.b, a.b
+ * - possible field selection -- ns.a['b'], a['b'] + * + * If none of the attributes within the maybe resolves a value, the result is + * an error. + */ + addQualifier(qual: Qualifier): Attribute { + let str = ''; + let isStr = false; + if (isFunction((qual as ConstantQualifier).value)) { + const cq = qual as ConstantQualifier; + const cqv = cq.value(); + if (isStringValue(cqv)) { + str = cqv.kind.value; + isStr = true; + } + } + const augmentedNames: string[] = []; + // First add the qualifier to all existing attributes in the oneof. + for (const attr of this.#attrs) { + if (isStr && attr.qualifiers().length === 0) { + const candidateVars = attr.candidateVariableNames(); + for (let i = 0; i < candidateVars.length; i++) { + const name = candidateVars[i]; + augmentedNames[i] = `${name}.${str}`; + } + } + attr.addQualifier(qual); + } + // Next, ensure the most specific variable / type reference is searched + // first. + if (this.#attrs.length === 0) { + this.#attrs.push( + this.#fac.absoluteAttribute(this.#id, ...augmentedNames) + ); + } else { + this.#attrs.unshift( + this.#fac.absoluteAttribute(this.#id, ...augmentedNames) + ); + } + return this; + } + + qualify(vars: Activation, obj: any) { + const val = this.resolve(vars); + if (isExprValueUnknown(val)) { + return val; + } + const qual = this.#fac.newQualifier(null, this.#id, val); + return qual.qualify(vars, obj); + } + + resolve(vars: Activation) { + for (const attr of this.#attrs) { + try { + const val = attr.tryResolve(vars); + if (!isNil(val)) { + return val; + } + } catch { + // Do nothing + } + } + throw noSuchAttributeException(this.toString()); + } + + toString() { + return `id: ${this.#id}, attributes: ${this.#attrs.join(', ')}`; + } +} + +export class RelativeAttribute implements Coster, Qualifier, Attribute { + readonly #id: bigint; + readonly #operand: Interpretable; + readonly #qualifiers: Qualifier[]; + readonly #adapter: TypeAdapter; + readonly #fac: AttributeFactory; + + constructor( + id: bigint, + operand: Interpretable, + qualifiers: Qualifier[], + adapter: TypeAdapter, + fac: AttributeFactory + ) { + this.#id = id; + this.#operand = operand; + this.#qualifiers = qualifiers; + this.#adapter = adapter; + this.#fac = fac; + } + + id(): bigint { + return this.#id; + } + + cost() { + const c = Cost.estimateCost(this.#operand); + let min = c.min; + let max = c.max; + for (const qual of this.#qualifiers) { + const q = Cost.estimateCost(qual); + min += q.min; + max += q.max; + } + return new Cost(min, max); + } + + addQualifier(q: Qualifier): Attribute { + this.#qualifiers.push(q); + return this; + } + + qualify(vars: Activation, obj: any): ExprValue { + const val = this.resolve(vars); + if (isExprValueUnknown(val)) { + return val; + } + const qual = this.#fac.newQualifier(null, this.#id, val); + return qual.qualify(vars, obj); + } + + resolve(vars: Activation): ExprValue { + // First, evaluate the operand. + const v = this.#operand.eval(vars); + if (isExprValueError(v)) { + throw new Error( + `message: ${v.kind.value.errors.map((e) => e.message).join(', ')}` + ); + } + if (isExprValueUnknown(v)) { + return v; + } + // Next, qualify it. Qualification handles unkonwns as well, so there's no + // need to recheck. + let obj = v; + for (const qual of this.#qualifiers) { + if (isNil(obj)) { + throw noSuchAttributeException(this.toString()); + } + obj = qual.qualify(vars, obj); + if (isExprValueError(obj)) { + return obj; + } + } + if (isNil(obj)) { + throw noSuchAttributeException(this.toString()); + } + return obj; + } + + toString() { + return `id: ${this.id()}, operand: ${this.#operand.id}`; + } +} + +function noSuchAttributeException(context: string) { + return new Error(`undeclared reference to '${context}' (in container '')`); +} diff --git a/packages/cel/src/lib/interpreter/attribute-pattern.ts b/packages/cel/src/lib/interpreter/attribute-pattern.ts new file mode 100644 index 0000000..0381f52 --- /dev/null +++ b/packages/cel/src/lib/interpreter/attribute-pattern.ts @@ -0,0 +1,22 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/** + * qualifierValueEquator defines an interface for determining if an input + * value, of valid map key type, is equal to the value held in the Qualifier. + * This interface is used by the AttributeQualifierPattern to determine pattern + * matches for non-wildcard qualifier patterns. + * + * Note: Attribute values are also Qualifier values; however, Attriutes are + * resolved before qualification happens. This is an implementation detail, but + * one relevant to why the Attribute types do not surface in the list of + * implementations. + * + * See: partialAttributeFactory.matchesUnknownPatterns for more details on how + * this interface is used. + */ +export interface QualifierValueEquator { + /** + * QualifierValueEquals returns true if the input value is equal to the value + * held in the Qualifier. + */ + qualifierValueEquals(value: any): boolean; +} diff --git a/packages/cel/src/lib/interpreter/attributes.ts b/packages/cel/src/lib/interpreter/attributes.ts deleted file mode 100644 index 70531c2..0000000 --- a/packages/cel/src/lib/interpreter/attributes.ts +++ /dev/null @@ -1,231 +0,0 @@ -// /* eslint-disable @typescript-eslint/no-explicit-any */ -// import { isNil } from '@bearclaw/is'; -// import { Type } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb'; -// import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb'; -// import { Registry } from '@bufbuild/protobuf'; -// import { CELContainer } from '../cel'; -// import { Activation } from './activation'; -// import { Interpretable } from './interpretable'; - -// // AttributeFactory provides methods creating Attribute and Qualifier values. -// export class AttributeFactory { -// constructor( -// protected readonly container: CELContainer, -// protected readonly registry: Registry, -// protected readonly errorOnBadPresenceTest: boolean -// ) {} - -// // AbsoluteAttribute creates an attribute that refers to a top-level -// // variable name. -// // -// // Checked expressions generate absolute attribute with a single name. -// // Parse-only expressions may have more than one possible absolute -// // identifier when the expression is created within a container, e.g. -// // package or namespace. -// // -// // When there is more than one name supplied to the AbsoluteAttribute call, -// // the names must be in CEL's namespace resolution order. The name -// // arguments provided here are returned in the same order as they were -// // provided by the NamespacedAttribute -// // CandidateVariableNames method. -// absoluteAttribute(id: bigint, ...names: string[]): NamespacedAttribute { -// return new AbsoluteAttribute( -// id, -// names, -// [], -// this.registry, -// this, -// this.errorOnBadPresenceTest -// ); -// } - -// // ConditionalAttribute creates an attribute with two Attribute branches, -// // where the Attribute that is resolved depends on the boolean evaluation of -// // the input 'expr'. -// conditionalAttribute( -// id: bigint, -// expr: Interpretable, -// t: Attribute, -// f: Attribute -// ): Attribute; - -// // MaybeAttribute creates an attribute that refers to either a field -// // selection or a namespaced variable name. -// // -// // Only expressions which have not been type-checked may generate oneof -// // attributes. -// maybeAttribute(id: bigint, name: string): Attribute; - -// // RelativeAttribute creates an attribute whose value is a qualification of a -// // dynamic computation rather than a static variable reference. -// relativeAttribute(id: bigint, operand: Interpretable): Attribute; - -// // NewQualifier creates a qualifier on the target object with a given value. -// // -// // The 'val' may be an Attribute or any proto-supported map key type: bool, -// // int, string, uint. -// // -// // The qualifier may consider the object type being qualified, if present. -// // If absent, the qualification should be considered dynamic and the -// // qualification should still work, though it may be sub-optimal. -// newQualifier( -// objType: Type, -// qualID: bigint, -// val: any, -// opt: boolean -// ): Qualifier | Error; -// } - -// // Qualifier marker interface for designating different qualifier values and -// // where they appear within field selections and index call expressions \ -// // (`_[_]`). -// export class Qualifier { -// // ID where the qualifier appears within an expression. -// id(): bigint; - -// // IsOptional specifies whether the qualifier is optional. -// // Instead of a direct qualification, an optional qualifier will be resolved -// // via QualifyIfPresent rather than Qualify. A non-optional qualifier may -// // also be resolved through QualifyIfPresent if the object to qualify is -// // itself optional. -// isOptional(): boolean; - -// // Qualify performs a qualification, e.g. field selection, on the input -// // object and returns the value of the access and whether the value was set. -// // A non-nil value with a false presence test result indicates that the value -// // being returned is the default value. -// qualify(vars: Activation, obj: any): any | Error; - -// // QualifyIfPresent qualifies the object if the qualifier is declared or -// // defined on the object. -// // The 'presenceOnly' flag indicates that the value is not necessary, just a -// // boolean status as to whether the qualifier is present. -// qualifyIfPresent( -// vars: Activation, -// obj: any, -// presenceOnly: boolean -// ): any | boolean | Error; -// } - -// // ConstantQualifier interface embeds the Qualifier interface and provides an -// // option to inspect the qualifier's constant value. -// // -// // Non-constant qualifiers are of Attribute type. -// export class ConstantQualifier extends Qualifier { -// // Value returns the constant value associated with the qualifier. -// value(): Value; -// } - -// // Attribute values are a variable or value with an optional set of qualifiers, -// // such as field, key, or index accesses. -// export class Attribute extends Qualifier { -// // AddQualifier adds a qualifier on the Attribute or error if the -// // qualification is not a valid qualifier type. -// addQualifier(qualifier: Qualifier): Attribute | Error; - -// // Resolve returns the value of the Attribute and whether it was present -// // given an Activation. -// // For objects which support safe traversal, the value may be non-nil and -// // the presence flag be false. -// // -// // If an error is encountered during attribute resolution, it will be -// // returned immediately. -// // If the attribute cannot be resolved within the Activation, the result -// // must be: `nil`, `error` -// // with the error indicating which variable was missing. -// resolve(activation: Activation): any | Error; -// } - -// // NamespacedAttribute values are a variable within a namespace, and an optional set of qualifiers -// // such as field, key, or index accesses. -// export interface NamespacedAttribute extends Attribute { -// // CandidateVariableNames returns the possible namespaced variable names for -// // this Attribute in the CEL namespace resolution order. -// candidateVariableNames(): string[]; - -// // Qualifiers returns the list of qualifiers associated with the Attribute. -// qualifiers(): Qualifier[]; -// } - -// export class AbsoluteAttribute { -// constructor( -// protected readonly _id: bigint, -// protected readonly _namespacedNames: string[], -// protected readonly _qualifiers: Qualifier[], -// protected readonly _registry: Registry, -// protected readonly _fac: AttributeFactory, -// protected readonly _errorOnBadPresenceTest: boolean -// ) {} - -// // ID implements the Attribute interface method. -// id(): bigint { -// if (this._qualifiers.length === 0) { -// return this._id; -// } -// return this._qualifiers[this._qualifiers.length - 1].id(); -// } - -// // IsOptional returns trivially false for an attribute as the attribute -// // represents a fully qualified variable name. If the attribute is used in an -// // optional manner, then an attrQualifier is created and marks the attribute -// // as optional. -// isOptional(): boolean { -// return false; -// } - -// // AddQualifier implements the Attribute interface method. -// addQualifier(qualifier: Qualifier): Attribute | Error { -// this._qualifiers.push(qualifier); -// return this; -// } - -// // CandidateVariableNames implements the NamespaceAttribute interface method. -// candidateVariableNames(): string[] { -// return this._namespacedNames; -// } - -// // Qualifiers returns the list of Qualifier instances associated with the \ -// // namespaced attribute. -// qualifiers(): Qualifier[] { -// return this._qualifiers; -// } - -// // Qualify is an implementation of the Qualifier interface method. -// qualify(vars: Activation, obj: any): any | Error { -// // TODO: Implement -// } - -// // QualifyIfPresent is an implementation of the Qualifier interface method. -// qualifyIfPresent( -// vars: Activation, -// obj: any, -// presenceOnly: boolean -// ): any | boolean | Error { -// // TODO: Implement -// } - -// // String implements the Stringer interface method. -// string(): string { -// return `id: ${this.id()}, names: ${this._namespacedNames.join(', ')}`; -// } - -// // Resolve returns the resolved Attribute value given the Activation, or -// // error if the Attribute variable is not found, or if its Qualifiers cannot -// // be applied successfully. -// // -// // If the variable name cannot be found as an Activation variable or in the -// // TypeProvider as a type, then the result is `nil`, `error` with the error -// // indicating the name of the first variable searched as missing. -// resolve(vars: Activation): any | Error { -// for (const name of this._namespacedNames) { -// // If the variable is found, process it. Otherwise, wait until the checks -// // to determine whether the type is unknown before returning. -// const obj = vars.resolveName(name); -// if (!isNil(obj)) { -// if (obj instanceof Error) { -// return obj; -// } -// } -// } -// } -// } diff --git a/packages/cel/src/lib/interpreter/coster.ts b/packages/cel/src/lib/interpreter/coster.ts index a56cfef..1a7a01d 100644 --- a/packages/cel/src/lib/interpreter/coster.ts +++ b/packages/cel/src/lib/interpreter/coster.ts @@ -1,3 +1,5 @@ +import { isFunction } from '@bearclaw/is'; + /* eslint-disable @typescript-eslint/no-explicit-any */ export class Cost { public static Unknown: Cost = new Cost(0, Number.MAX_VALUE); @@ -14,8 +16,8 @@ export class Cost { /** * estimateCost returns the heuristic cost interval for the program. */ - public estimateCost(obj: any): Cost { - if (obj instanceof Coster) { + public static estimateCost(obj: any): Cost { + if (isFunction(obj.cost)) { return obj.cost(); } return Cost.Unknown; @@ -37,10 +39,6 @@ export class Cost { /** * Coster calculates the heuristic cost incurred during evaluation. */ -export class Coster { - constructor(private readonly _cost: Cost = Cost.Unknown) {} - - cost(): Cost { - return this._cost; - } +export interface Coster { + cost(): Cost; } diff --git a/packages/cel/src/lib/interpreter/interpretable.ts b/packages/cel/src/lib/interpreter/interpretable.ts index 18e66c8..5e68bd5 100644 --- a/packages/cel/src/lib/interpreter/interpretable.ts +++ b/packages/cel/src/lib/interpreter/interpretable.ts @@ -1,4 +1,5 @@ -import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb'; +import { ExprValue } from '@buf/google_cel-spec.bufbuild_es/cel/expr/eval_pb.js'; +import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; import { Activation } from './activation'; export interface Interpretable { @@ -6,7 +7,7 @@ export interface Interpretable { id: bigint; // Eval an Activation to produce an output. - eval: (ctx: Activation) => Value | Error; + eval: (ctx: Activation) => ExprValue; } // InterpretableConst interface for tracking whether the Interpretable is a diff --git a/packages/cel/src/lib/interpreter/resolved-value.ts b/packages/cel/src/lib/interpreter/resolved-value.ts index 7d2e8ff..03e0ef3 100644 --- a/packages/cel/src/lib/interpreter/resolved-value.ts +++ b/packages/cel/src/lib/interpreter/resolved-value.ts @@ -8,6 +8,6 @@ export class ResolvedValue { constructor(public readonly value: T, public readonly present: boolean) {} equals(other: ResolvedValue): boolean { - return dequal(this, other); + return this.present === other.present && dequal(this.value, other.value); } } From a6414e8d93843646c469f7037037c1eb07681df9 Mon Sep 17 00:00:00 2001 From: jafaircl Date: Mon, 4 Nov 2024 19:16:40 -0500 Subject: [PATCH 30/34] feat(cel): interpreter checkpoint --- package-lock.json | 11 + package.json | 1 + .../src/lib/common/pb/proto-type-registry.ts | 176 ++++ packages/cel/src/lib/common/ref/adapter.ts | 2 +- packages/cel/src/lib/common/ref/field-type.ts | 3 +- packages/cel/src/lib/common/ref/provider.ts | 4 +- packages/cel/src/lib/common/ref/registry.ts | 34 + packages/cel/src/lib/common/types/convert.ts | 15 + packages/cel/src/lib/common/types/duration.ts | 27 + packages/cel/src/lib/common/types/list.ts | 3 + packages/cel/src/lib/common/types/map.ts | 6 + packages/cel/src/lib/common/types/native.ts | 2 + .../cel/src/lib/common/types/string.spec.ts | 301 ++++++- packages/cel/src/lib/common/types/string.ts | 230 ++++++ .../src/lib/common/types/traits/comparer.ts | 8 +- .../src/lib/common/types/traits/equaler.ts | 26 + .../src/lib/common/types/traits/matcher.ts | 11 + .../cel/src/lib/common/types/traits/math.ts | 20 + .../src/lib/common/types/traits/negater.ts | 2 +- .../src/lib/common/types/traits/receiver.ts | 16 + .../cel/src/lib/common/types/traits/sizer.ts | 3 + .../cel/src/lib/common/types/traits/zeroer.ts | 29 + packages/cel/src/lib/common/types/type.ts | 20 + .../cel/src/lib/common/types/uint.spec.ts | 348 +++++++- packages/cel/src/lib/common/types/uint.ts | 239 +++++- packages/cel/src/lib/common/types/unknown.ts | 19 + packages/cel/src/lib/common/types/value.ts | 71 ++ .../cel/src/lib/interpreter/activation.ts | 2 +- .../lib/interpreter/attribute-factory.spec.ts | 51 ++ .../src/lib/interpreter/attribute-factory.ts | 778 ++++++++++++++++-- .../cel/src/lib/interpreter/interpretable.ts | 479 ++++++++++- packages/cel/src/lib/interpreter/overload.ts | 2 +- 32 files changed, 2869 insertions(+), 70 deletions(-) create mode 100644 packages/cel/src/lib/common/pb/proto-type-registry.ts create mode 100644 packages/cel/src/lib/common/ref/registry.ts create mode 100644 packages/cel/src/lib/common/types/traits/equaler.ts create mode 100644 packages/cel/src/lib/common/types/traits/matcher.ts create mode 100644 packages/cel/src/lib/common/types/traits/receiver.ts create mode 100644 packages/cel/src/lib/common/types/traits/zeroer.ts create mode 100644 packages/cel/src/lib/common/types/unknown.ts create mode 100644 packages/cel/src/lib/common/types/value.ts create mode 100644 packages/cel/src/lib/interpreter/attribute-factory.spec.ts diff --git a/package-lock.json b/package-lock.json index 92a6a10..f03e847 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "dequal": "^2.0.3", "fast-json-stable-stringify": "^2.1.0", "immer": "^9.0.15", + "iso8601-duration": "^2.1.2", "just-extend": "^6.1.1", "tslib": "^2.0.0" }, @@ -11864,6 +11865,11 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "node_modules/iso8601-duration": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/iso8601-duration/-/iso8601-duration-2.1.2.tgz", + "integrity": "sha512-yXteYUiKv6x8seaDzyBwnZtPpmx766KfvQuaVNyPifYOjmPdOo3ajd4phDNa7Y5mTQGnXsNEcXFtVun1FjYXxQ==" + }, "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -25975,6 +25981,11 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "iso8601-duration": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/iso8601-duration/-/iso8601-duration-2.1.2.tgz", + "integrity": "sha512-yXteYUiKv6x8seaDzyBwnZtPpmx766KfvQuaVNyPifYOjmPdOo3ajd4phDNa7Y5mTQGnXsNEcXFtVun1FjYXxQ==" + }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", diff --git a/package.json b/package.json index a30b884..191e248 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "dequal": "^2.0.3", "fast-json-stable-stringify": "^2.1.0", "immer": "^9.0.15", + "iso8601-duration": "^2.1.2", "just-extend": "^6.1.1", "tslib": "^2.0.0" }, diff --git a/packages/cel/src/lib/common/pb/proto-type-registry.ts b/packages/cel/src/lib/common/pb/proto-type-registry.ts new file mode 100644 index 0000000..f16eaf5 --- /dev/null +++ b/packages/cel/src/lib/common/pb/proto-type-registry.ts @@ -0,0 +1,176 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { isEmpty, isNil } from '@bearclaw/is'; +import { + Type, + TypeSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { + Value, + ValueSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { + DescEnum, + DescMessage, + MutableRegistry, + Registry, + create, + createMutableRegistry, + isMessage, +} from '@bufbuild/protobuf'; +import { formatCELType } from '../format'; +import { FieldType } from '../ref/field-type'; +import { STANDARD_DESCRIPTORS } from '../standard'; +import { BOOL_TYPE, isBoolValue } from '../types/bool'; +import { BYTES_TYPE } from '../types/bytes'; +import { DOUBLE_TYPE } from '../types/double'; +import { INT64_TYPE } from '../types/int'; +import { LIST_TYPE } from '../types/list'; +import { MAP_TYPE } from '../types/map'; +import { messageType } from '../types/message'; +import { NULL_TYPE } from '../types/null'; +import { STRING_TYPE } from '../types/string'; +import { isZeroValue } from '../types/traits/zeroer'; +import { TYPE_TYPE } from '../types/type'; +import { UINT64_TYPE } from '../types/uint'; +import { getFieldDescriptorType } from '../types/utils'; +import { valueOf } from '../types/value'; +import { DURATION_TYPE, TIMESTAMP_TYPE } from '../types/wkt'; +import { TypeRegistry } from './../ref/registry'; + +export class ProtoTypeRegistry implements TypeRegistry { + readonly #refTypeMap = new Map(); + readonly #registry: MutableRegistry; + + constructor(typeMap: Map = new Map(), registry?: Registry) { + const descriptors = STANDARD_DESCRIPTORS; + if (!isNil(registry)) { + descriptors.push(registry); + } + this.#registry = createMutableRegistry(...descriptors); + this.registerType( + BOOL_TYPE, + BYTES_TYPE, + DOUBLE_TYPE, + DURATION_TYPE, + INT64_TYPE, + LIST_TYPE, + MAP_TYPE, + NULL_TYPE, + STRING_TYPE, + TIMESTAMP_TYPE, + TYPE_TYPE, + UINT64_TYPE + ); + for (const [k, v] of typeMap) { + this.#refTypeMap.set(k, v); + } + } + + copy(): TypeRegistry { + return new ProtoTypeRegistry(this.#refTypeMap, this.#registry); + } + + register(t: Type | DescEnum | DescMessage): void { + if (isMessage(t, TypeSchema)) { + this.registerType(t); + } else { + this.#registry.add(t); + } + } + + registerType(...types: Type[]): void { + for (const type of types) { + this.#refTypeMap.set(formatCELType(type), type); + } + } + + enumValue(enumName: string) { + for (const desc of this.#registry) { + if (desc.kind === 'enum') { + const v = desc.values.find((v) => v.name === enumName); + if (!isNil(v)) { + return create(ValueSchema, { + kind: { + case: 'enumValue', + value: { + type: desc.typeName, + value: v.number, + }, + }, + }); + } + } + } + return new Error(`unknown enum name '${enumName}'`); + } + + findIdent(identName: string) { + if (this.#refTypeMap.has(identName)) { + return create(ValueSchema, { + kind: { + case: 'typeValue', + value: identName, + }, + }); + } + const enumValue = this.enumValue(identName); + if (!(enumValue instanceof Error)) { + return enumValue; + } + return null; + } + + findType(typeName: string): Type | null { + if (isNil(this.#registry.get(typeName))) { + return null; + } + if (!isEmpty(typeName) && typeName.charAt(0) == '.') { + typeName = typeName.substring(1); + } + return messageType(typeName); + } + + findFieldType(messageType: string, fieldName: string): FieldType | Error { + const desc = this.#registry.getMessage(messageType); + if (isNil(desc)) { + return new Error(`unknown type '${messageType}'`); + } + if (desc.kind !== 'message') { + return new Error(`type '${messageType}' is not a message`); + } + const field = desc.fields.find((f) => f.name === fieldName); + if (isNil(field)) { + return new Error(`no such field '${fieldName}' on type '${messageType}'`); + } + return new FieldType( + getFieldDescriptorType(field), + (obj) => { + const isZero = isZeroValue(obj); + if (isZero instanceof Error || !isBoolValue(isZero)) { + return false; + } + return isZero.kind.value; + }, + () => null // TODO: implement + ); + } + + newValue(typeName: string, fields: Record): Value | Error { + const type = this.#registry.getMessage(typeName); + if (isNil(type)) { + return new Error(`unknown type '${typeName}'`); + } + // TODO: implement + return create(ValueSchema, { + kind: { + case: 'objectValue', + value: {}, + }, + }); + } + + nativeToValue(value: any) { + // TODO: this is not correct + return valueOf(value); + } +} diff --git a/packages/cel/src/lib/common/ref/adapter.ts b/packages/cel/src/lib/common/ref/adapter.ts index acbe4b8..c5ea86a 100644 --- a/packages/cel/src/lib/common/ref/adapter.ts +++ b/packages/cel/src/lib/common/ref/adapter.ts @@ -9,5 +9,5 @@ export interface TypeAdapter { /** * NativeToValue converts the input `value` to a CEL `Value`. */ - nativeToValue(value: any): Value; + nativeToValue(value: any): Value | Error; } diff --git a/packages/cel/src/lib/common/ref/field-type.ts b/packages/cel/src/lib/common/ref/field-type.ts index 75d24e9..e02cf9b 100644 --- a/packages/cel/src/lib/common/ref/field-type.ts +++ b/packages/cel/src/lib/common/ref/field-type.ts @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { Type } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; /** * FieldType represents a field's type value and whether that field supports @@ -8,7 +9,7 @@ import { Type } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; export class FieldType { constructor( public readonly type: Type, - public readonly isSet: (obj: any) => boolean, + public readonly isSet: (obj: Value) => boolean, public readonly getFrom: (obj: any) => any ) {} } diff --git a/packages/cel/src/lib/common/ref/provider.ts b/packages/cel/src/lib/common/ref/provider.ts index bae51bd..8647035 100644 --- a/packages/cel/src/lib/common/ref/provider.ts +++ b/packages/cel/src/lib/common/ref/provider.ts @@ -10,7 +10,7 @@ export interface TypeProvider { /** * EnumValue returns the numeric value of the given enum value name. */ - enumValue(enumName: string): Value; + enumValue(enumName: string): Value | Error; /** * FindIdent takes a qualified identifier name and returns a Value if one @@ -32,7 +32,7 @@ export interface TypeProvider { * *

Used during type-checking only. */ - findFieldType(messageType: string, fieldName: string): FieldType | null; + findFieldType(messageType: string, fieldName: string): FieldType | Error; /** * NewValue creates a new type value from a qualified name and map of field diff --git a/packages/cel/src/lib/common/ref/registry.ts b/packages/cel/src/lib/common/ref/registry.ts new file mode 100644 index 0000000..21cde9c --- /dev/null +++ b/packages/cel/src/lib/common/ref/registry.ts @@ -0,0 +1,34 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { Type } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb'; +import { TypeAdapter } from './adapter'; +import { TypeProvider } from './provider'; + +/** + * TypeRegistry allows third-parties to add custom types to CEL. Not all + * `TypeProvider` implementations support type-customization, so these features + * are optional. However, a `TypeRegistry` should be a `TypeProvider` and a + * `TypeAdapter` to ensure that types which are registered can be converted to + * CEL representations. + */ +export interface TypeRegistry extends TypeProvider, TypeAdapter { + /** + * Copy the TypeRegistry and return a new registry whose mutable state is + * isolated. + */ + copy(): TypeRegistry; + + /** + * Register a type via a materialized object, which the provider can turn + * into a type. + */ + register(t: any): void; + + /** + * RegisterType registers a type value with the provider which ensures the + * provider is aware of how to map the type to an identifier. + * + * If a type is provided more than once with an alternative definition, the + * call will result in an error. + */ + registerType(...types: Type[]): void; +} diff --git a/packages/cel/src/lib/common/types/convert.ts b/packages/cel/src/lib/common/types/convert.ts index b315fa7..1493f9a 100644 --- a/packages/cel/src/lib/common/types/convert.ts +++ b/packages/cel/src/lib/common/types/convert.ts @@ -3,7 +3,10 @@ import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; import { convertBoolValueToNative, convertBoolValueToType } from './bool'; import { convertBytesValueToNative, convertBytesValueToType } from './bytes'; import { convertDoubleValueToNative, convertDoubleValueToType } from './double'; +import { convertInt64ValueToNative, convertInt64ValueToType } from './int'; import { NativeType } from './native'; +import { convertStringValueToNative, convertStringValueToType } from './string'; +import { convertUint64ValueToNative } from './uint'; export function convertToNative(value: Value, type: NativeType) { switch (value.kind.case) { @@ -13,6 +16,12 @@ export function convertToNative(value: Value, type: NativeType) { return convertBytesValueToNative(value, type); case 'doubleValue': return convertDoubleValueToNative(value, type); + case 'int64Value': + return convertInt64ValueToNative(value, type); + case 'stringValue': + return convertStringValueToNative(value, type); + case 'uint64Value': + return convertUint64ValueToNative(value, type); default: return new Error('no such overload'); } @@ -26,6 +35,12 @@ export function convertToType(value: Value, type: Type) { return convertBytesValueToType(value, type); case 'doubleValue': return convertDoubleValueToType(value, type); + case 'int64Value': + return convertInt64ValueToType(value, type); + case 'stringValue': + return convertStringValueToType(value, type); + case 'uint64Value': + return convertStringValueToType(value, type); default: return new Error('no such overload'); } diff --git a/packages/cel/src/lib/common/types/duration.ts b/packages/cel/src/lib/common/types/duration.ts index 2524411..00ec19f 100644 --- a/packages/cel/src/lib/common/types/duration.ts +++ b/packages/cel/src/lib/common/types/duration.ts @@ -18,6 +18,10 @@ import { anyPack, anyUnpack, } from '@bufbuild/protobuf/wkt'; +import { + toSeconds as durationToSeconds, + parse as parseDuration, +} from 'iso8601-duration'; import { formatCELType } from '../format'; import { int64Value } from './int'; import { NativeType } from './native'; @@ -110,3 +114,26 @@ export function convertDurationValueToType(value: Value, type: Type) { )}' to '${formatCELType(type)}'` ); } + +export function parseISO8061DurationString(text: string) { + try { + const duration = parseDuration(`P${text.toUpperCase()}`); + const seconds = durationToSeconds(duration); + return create(DurationSchema, { + seconds: BigInt(Math.trunc(seconds)), + nanos: Math.trunc((seconds % 1) * 1e9), + }); + } catch { + try { + const duration = parseDuration(`PT${text.toUpperCase()}`); + const seconds = durationToSeconds(duration); + return create(DurationSchema, { + seconds: BigInt(Math.trunc(seconds)), + nanos: Math.trunc((seconds % 1) * 1e9), + }); + } catch (e) { + console.log(e); + return new Error(`cannot parse duration: ${text}`); + } + } +} diff --git a/packages/cel/src/lib/common/types/list.ts b/packages/cel/src/lib/common/types/list.ts index 361bc84..3f34ee2 100644 --- a/packages/cel/src/lib/common/types/list.ts +++ b/packages/cel/src/lib/common/types/list.ts @@ -14,6 +14,9 @@ import { ValueSchema, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; import { MessageInitShape, create } from '@bufbuild/protobuf'; +import { DYN_TYPE } from './dyn'; + +export const LIST_TYPE = listType({ elemType: DYN_TYPE }); export function listType(value: MessageInitShape) { return create(TypeSchema, { diff --git a/packages/cel/src/lib/common/types/map.ts b/packages/cel/src/lib/common/types/map.ts index 1dc977f..acf5866 100644 --- a/packages/cel/src/lib/common/types/map.ts +++ b/packages/cel/src/lib/common/types/map.ts @@ -4,6 +4,12 @@ import { Type_MapTypeSchema, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; import { MessageInitShape, create } from '@bufbuild/protobuf'; +import { DYN_TYPE } from './dyn'; + +export const MAP_TYPE = mapType({ + keyType: DYN_TYPE, + valueType: DYN_TYPE, +}); export function mapType(value: MessageInitShape) { return create(TypeSchema, { diff --git a/packages/cel/src/lib/common/types/native.ts b/packages/cel/src/lib/common/types/native.ts index 8836447..39ef879 100644 --- a/packages/cel/src/lib/common/types/native.ts +++ b/packages/cel/src/lib/common/types/native.ts @@ -10,6 +10,7 @@ import { StringValueSchema, StructSchema, TimestampSchema, + UInt32ValueSchema, UInt64ValueSchema, } from '@bufbuild/protobuf/wkt'; @@ -37,4 +38,5 @@ export type NativeType = | typeof StringValueSchema | typeof StructSchema | typeof TimestampSchema + | typeof UInt32ValueSchema | typeof UInt64ValueSchema; diff --git a/packages/cel/src/lib/common/types/string.spec.ts b/packages/cel/src/lib/common/types/string.spec.ts index 356e307..84cfd4c 100644 --- a/packages/cel/src/lib/common/types/string.spec.ts +++ b/packages/cel/src/lib/common/types/string.spec.ts @@ -4,7 +4,37 @@ import { } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; import { create } from '@bufbuild/protobuf'; -import { stringConstant, stringExpr, stringValue } from './string'; +import { + AnySchema, + StringValueSchema, + anyPack, + timestampFromDate, +} from '@bufbuild/protobuf/wkt'; +import { CONTAINS_OVERLOAD } from '../../overloads'; +import { BOOL_TYPE, boolValue } from './bool'; +import { BYTES_TYPE, bytesValue } from './bytes'; +import { DOUBLE_TYPE, doubleValue } from './double'; +import { durationValue } from './duration'; +import { INT64_TYPE, int64Value } from './int'; +import { + STRING_TYPE, + addStringValue, + compareStringValue, + convertStringValueToNative, + convertStringValueToType, + equalStringValue, + isZeroStringValue, + matchStringValue, + receiveStringValue, + sizeStringValue, + stringConstant, + stringExpr, + stringValue, +} from './string'; +import { timestampValue } from './timestamp'; +import { TYPE_TYPE } from './type'; +import { UINT64_TYPE, uint64Value } from './uint'; +import { DURATION_TYPE, TIMESTAMP_TYPE } from './wkt'; describe('string', () => { it('stringConstant', () => { @@ -47,4 +77,273 @@ describe('string', () => { }); // TODO: validations + + it('convertStringValueToNative ', () => { + expect(() => { + convertStringValueToNative(doubleValue(42), String); + }).toThrow(); + expect(convertStringValueToNative(stringValue('hello'), String)).toEqual( + 'hello' + ); + expect( + convertStringValueToNative(stringValue('world'), Uint8Array) + ).toEqual(new TextEncoder().encode('world')); + expect( + convertStringValueToNative(stringValue('hey buddy'), AnySchema) + ).toEqual( + anyPack( + StringValueSchema, + create(StringValueSchema, { value: 'hey buddy' }) + ) + ); + expect( + convertStringValueToNative(stringValue('hey buddy'), StringValueSchema) + ).toEqual(create(StringValueSchema, { value: 'hey buddy' })); + expect( + convertStringValueToNative(stringValue('hey buddy'), Number) + ).toEqual(new Error(`type conversion error from 'string' to 'Number'`)); + }); + + it('convertStringValueToType', () => { + expect(() => { + convertStringValueToType(doubleValue(42), STRING_TYPE); + }).toThrow(); + const tests = [ + { + value: stringValue('hello'), + type: TYPE_TYPE, + expected: STRING_TYPE, + }, + { + value: stringValue('hello'), + type: STRING_TYPE, + expected: stringValue('hello'), + }, + { + value: stringValue('-1'), + type: INT64_TYPE, + expected: int64Value(BigInt(-1)), + }, + { + value: stringValue('3.14'), + type: DOUBLE_TYPE, + expected: doubleValue(3.14), + }, + { + value: stringValue('42'), + type: UINT64_TYPE, + expected: uint64Value(BigInt(42)), + }, + { + value: stringValue('true'), + type: BOOL_TYPE, + expected: boolValue(true), + }, + { + value: stringValue('false'), + type: BOOL_TYPE, + expected: boolValue(false), + }, + { + value: stringValue('hello'), + type: BYTES_TYPE, + expected: bytesValue(new TextEncoder().encode('hello')), + }, + { + value: stringValue('2021-01-01T00:00:00Z'), + type: TIMESTAMP_TYPE, + expected: timestampValue( + timestampFromDate(new Date('2021-01-01T00:00:00Z')) + ), + }, + { + value: stringValue('42s'), + type: DURATION_TYPE, + expected: durationValue({ seconds: BigInt(42), nanos: 0 }), + }, + { + value: stringValue('1h5s'), + type: DURATION_TYPE, + expected: durationValue({ seconds: BigInt(3605), nanos: 0 }), + }, + { + value: stringValue('3.14s'), + type: DURATION_TYPE, + expected: durationValue({ seconds: BigInt(3), nanos: 0.14 * 1e9 }), + }, + ]; + for (const test of tests) { + expect(convertStringValueToType(test.value, test.type)).toEqual( + test.expected + ); + } + }); + + it('equalStringValue', () => { + expect(() => { + equalStringValue(doubleValue(42), stringValue('hello')); + }).toThrow(); + expect( + equalStringValue(stringValue('hello'), stringValue('hello')) + ).toEqual(boolValue(true)); + expect( + equalStringValue(stringValue('hello'), stringValue('world')) + ).toEqual(boolValue(false)); + expect(equalStringValue(stringValue('hello'), doubleValue(42))).toEqual( + boolValue(false) + ); + }); + + it('isZeroStringValue', () => { + expect(() => { + isZeroStringValue(doubleValue(42)); + }).toThrow(); + expect(isZeroStringValue(stringValue('hello'))).toEqual(boolValue(false)); + expect(isZeroStringValue(stringValue(''))).toEqual(boolValue(true)); + }); + + it('addStringValue', () => { + expect(() => { + addStringValue(doubleValue(42), stringValue('hello')); + }).toThrow(); + expect(addStringValue(stringValue('hello'), stringValue('world'))).toEqual( + stringValue('helloworld') + ); + expect(addStringValue(stringValue('hello'), doubleValue(2))).toEqual( + new Error('no such overload') + ); + }); + + it('compareStringValue', () => { + expect(() => { + compareStringValue(doubleValue(42), stringValue('hello')); + }); + const a = stringValue('a'); + const b = stringValue('bbbb'); + const c = stringValue('c'); + expect(compareStringValue(a, b)).toEqual(int64Value(BigInt(-1))); + expect(compareStringValue(a, a)).toEqual(int64Value(BigInt(0))); + expect(compareStringValue(c, b)).toEqual(int64Value(BigInt(1))); + expect(compareStringValue(a, doubleValue(42))).toEqual( + new Error('no such overload') + ); + }); + + it('matchStringValue', () => { + expect(() => { + matchStringValue(doubleValue(42), stringValue('hello')); + }).toThrow(); + const str = stringValue('hello 1 world'); + const sw = stringValue('^hello'); + const ew = stringValue('\\d world$'); + expect(matchStringValue(str, sw)).toEqual(boolValue(true)); + expect(matchStringValue(str, ew)).toEqual(boolValue(true)); + expect(matchStringValue(stringValue('ello 1 worlds'), sw)).toEqual( + boolValue(false) + ); + expect(matchStringValue(str, doubleValue(42))).toEqual( + new Error('no such overload') + ); + }); + + it('receiveStringValue', () => { + expect(() => { + receiveStringValue(doubleValue(42), '', ''); + }).toThrow(); + // Unknown overload + expect( + receiveStringValue(stringValue('hello'), 'unknown', '', stringValue('')) + ).toEqual(new Error('no such overload')); + + // Contains + expect( + receiveStringValue( + stringValue('goodbye'), + CONTAINS_OVERLOAD, + '', + stringValue('db') + ) + ).toEqual(boolValue(true)); + expect( + receiveStringValue( + stringValue('goodbye'), + CONTAINS_OVERLOAD, + '', + stringValue('aa') + ) + ).toEqual(boolValue(false)); + expect( + receiveStringValue( + stringValue('goodbye'), + CONTAINS_OVERLOAD, + '', + doubleValue(42) + ) + ).toEqual(new Error('no such overload')); + + // StartsWith + expect( + receiveStringValue( + stringValue('goodbye'), + 'startsWith', + '', + stringValue('good') + ) + ).toEqual(boolValue(true)); + expect( + receiveStringValue( + stringValue('goodbye'), + 'startsWith', + '', + stringValue('bye') + ) + ).toEqual(boolValue(false)); + expect( + receiveStringValue( + stringValue('goodbye'), + 'startsWith', + '', + doubleValue(42) + ) + ).toEqual(new Error('no such overload')); + + // EndsWith + expect( + receiveStringValue( + stringValue('goodbye'), + 'endsWith', + '', + stringValue('bye') + ) + ).toEqual(boolValue(true)); + expect( + receiveStringValue( + stringValue('goodbye'), + 'endsWith', + '', + stringValue('good') + ) + ).toEqual(boolValue(false)); + expect( + receiveStringValue( + stringValue('goodbye'), + 'endsWith', + '', + doubleValue(42) + ) + ).toEqual(new Error('no such overload')); + }); + + it('sizeStringValue', () => { + expect(() => { + sizeStringValue(doubleValue(42)); + }).toThrow(); + expect(sizeStringValue(stringValue(''))).toEqual(int64Value(BigInt(0))); + expect(sizeStringValue(stringValue('hello world'))).toEqual( + int64Value(BigInt(11)) + ); + expect(sizeStringValue(stringValue('\u65e5\u672c\u8a9e'))).toEqual( + int64Value(BigInt(3)) + ); + }); }); diff --git a/packages/cel/src/lib/common/types/string.ts b/packages/cel/src/lib/common/types/string.ts index 13f2613..5594b7b 100644 --- a/packages/cel/src/lib/common/types/string.ts +++ b/packages/cel/src/lib/common/types/string.ts @@ -1,6 +1,8 @@ +/* eslint-disable no-case-declarations */ import { Type, Type_PrimitiveType, + Type_WellKnownType, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; import { Constant, @@ -13,8 +15,30 @@ import { ValueSchema, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; import { create } from '@bufbuild/protobuf'; +import { + AnySchema, + StringValueSchema, + anyPack, + timestampFromDate, +} from '@bufbuild/protobuf/wkt'; +import { + CONTAINS_OVERLOAD, + ENDS_WITH_OVERLOAD, + STARTS_WITH_OVERLOAD, +} from '../../overloads'; +import { parseBytesConstant } from '../constants'; +import { formatCELType } from '../format'; +import { boolValue } from './bool'; +import { bytesValue } from './bytes'; import { isConstExpr } from './constant'; +import { doubleValue } from './double'; +import { durationValue, parseISO8061DurationString } from './duration'; +import { int64Value } from './int'; +import { NativeType } from './native'; import { primitiveType } from './primitive'; +import { timestampValue } from './timestamp'; +import { Trait } from './traits/trait'; +import { uint64Value } from './uint'; export const STRING_TYPE = primitiveType(Type_PrimitiveType.STRING); @@ -84,3 +108,209 @@ export function isStringValue(value: Value): value is Value & { } { return value.kind.case === 'stringValue'; } + +export function convertStringValueToNative(value: Value, type: NativeType) { + if (!isStringValue(value)) { + throw new Error('string value is not a string'); + } + switch (type) { + case String: + return value.kind.value; + case Uint8Array: + return parseBytesConstant(`b"${value.kind.value}"`).constantKind + .value as Uint8Array; + case AnySchema: + return anyPack( + StringValueSchema, + create(StringValueSchema, { value: value.kind.value }) + ); + case StringValueSchema: + return create(StringValueSchema, { value: value.kind.value }); + default: + break; + } + return new Error( + `type conversion error from '${formatCELType(STRING_TYPE)}' to '${ + type.name + }'` + ); +} + +export function convertStringValueToType(value: Value, type: Type) { + if (!isStringValue(value)) { + throw new Error('string value is not a string'); + } + switch (type.typeKind.case) { + case 'primitive': + switch (type.typeKind.value) { + case Type_PrimitiveType.BOOL: + return boolValue(value.kind.value === 'true'); + case Type_PrimitiveType.BYTES: + return bytesValue( + parseBytesConstant(`b"${value.kind.value}"`).constantKind + .value as Uint8Array + ); + case Type_PrimitiveType.DOUBLE: + return doubleValue(parseFloat(value.kind.value)); + case Type_PrimitiveType.INT64: + return int64Value(BigInt(parseInt(value.kind.value))); + case Type_PrimitiveType.STRING: + return stringValue(value.kind.value.toString()); + case Type_PrimitiveType.UINT64: + return uint64Value(BigInt(parseInt(value.kind.value))); + default: + break; + } + break; + case 'wellKnown': + switch (type.typeKind.value) { + case Type_WellKnownType.DURATION: + const duration = parseISO8061DurationString( + value.kind.value.toUpperCase() + ); + if (duration instanceof Error) { + return duration; + } + return durationValue(duration); + case Type_WellKnownType.TIMESTAMP: + return timestampValue(timestampFromDate(new Date(value.kind.value))); + default: + break; + } + break; + case 'type': + return STRING_TYPE; + default: + break; + } + return new Error( + `type conversion error from '${formatCELType( + STRING_TYPE + )}' to '${formatCELType(type)}'` + ); +} + +export function equalStringValue(value: Value, other: Value) { + if (!isStringValue(value)) { + // This should never happen + throw new Error('value is not a string'); + } + if (!isStringValue(other)) { + return boolValue(false); + } + return boolValue(value.kind.value === other.kind.value); +} + +export function isZeroStringValue(value: Value) { + if (!isStringValue(value)) { + throw new Error('string value is not a string'); + } + return boolValue(value.kind.value === ''); +} + +export const STRING_TRAITS = new Set([ + Trait.ADDER_TYPE, + Trait.COMPARER_TYPE, + Trait.MATCHER_TYPE, + Trait.RECEIVER_TYPE, + Trait.SIZER_TYPE, +]); + +export function addStringValue(value: Value, other: Value) { + if (!isStringValue(value)) { + throw new Error('string value is not a string'); + } + if (!isStringValue(other)) { + return new Error('no such overload'); + } + return stringValue(value.kind.value + other.kind.value); +} + +export function compareStringValue(value: Value, other: Value) { + if (!isStringValue(value)) { + throw new Error('string value is not a string'); + } + if (!isStringValue(other)) { + return new Error('no such overload'); + } + if (value.kind.value < other.kind.value) { + return int64Value(BigInt(-1)); + } + if (value.kind.value > other.kind.value) { + return int64Value(BigInt(1)); + } + return int64Value(BigInt(0)); +} + +export function matchStringValue(value: Value, other: Value) { + if (!isStringValue(value)) { + throw new Error('string value is not a string'); + } + if (!isStringValue(other)) { + return new Error('no such overload'); + } + const pattern = new RegExp(other.kind.value); + return boolValue(pattern.test(value.kind.value)); +} + +function stringValueContains(value: Value, other: Value) { + if (!isStringValue(value)) { + throw new Error('string value is not a string'); + } + if (!isStringValue(other)) { + return new Error('no such overload'); + } + return boolValue(value.kind.value.includes(other.kind.value)); +} + +function stringValueStartsWith(value: Value, other: Value) { + if (!isStringValue(value)) { + throw new Error('string value is not a string'); + } + if (!isStringValue(other)) { + return new Error('no such overload'); + } + return boolValue(value.kind.value.startsWith(other.kind.value)); +} + +function stringValueEndsWith(value: Value, other: Value) { + if (!isStringValue(value)) { + throw new Error('string value is not a string'); + } + if (!isStringValue(other)) { + return new Error('no such overload'); + } + return boolValue(value.kind.value.endsWith(other.kind.value)); +} + +export const STRING_OVERLOADS = new Map< + string, + (value: Value, other: Value) => Value | Error +>([ + [CONTAINS_OVERLOAD, stringValueContains], + [STARTS_WITH_OVERLOAD, stringValueStartsWith], + [ENDS_WITH_OVERLOAD, stringValueEndsWith], +]); + +export function receiveStringValue( + value: Value, + fn: string, + overload: string, + ...args: Value[] +) { + if (!isStringValue(value)) { + throw new Error('string value is not a string'); + } + const f = STRING_OVERLOADS.get(fn); + if (f) { + return f(value, args[0]); + } + return new Error('no such overload'); +} + +export function sizeStringValue(value: Value) { + if (!isStringValue(value)) { + throw new Error('string value is not a string'); + } + return int64Value(BigInt(value.kind.value.length)); +} diff --git a/packages/cel/src/lib/common/types/traits/comparer.ts b/packages/cel/src/lib/common/types/traits/comparer.ts index 5bf1a2f..8dde281 100644 --- a/packages/cel/src/lib/common/types/traits/comparer.ts +++ b/packages/cel/src/lib/common/types/traits/comparer.ts @@ -2,8 +2,10 @@ import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb'; import { compareBoolValue } from '../bool'; import { compareDoubleValue } from '../double'; import { compareInt64Value } from '../int'; +import { compareStringValue } from '../string'; +import { compareUint64Value } from '../uint'; -export function compare(value: Value, other: Value) { +export function comparer(value: Value, other: Value) { switch (value.kind.case) { case 'boolValue': return compareBoolValue(value, other); @@ -11,6 +13,10 @@ export function compare(value: Value, other: Value) { return compareDoubleValue(value, other); case 'int64Value': return compareInt64Value(value, other); + case 'stringValue': + return compareStringValue(value, other); + case 'uint64Value': + return compareUint64Value(value, other); default: return new Error('no such overload'); } diff --git a/packages/cel/src/lib/common/types/traits/equaler.ts b/packages/cel/src/lib/common/types/traits/equaler.ts new file mode 100644 index 0000000..f3d7615 --- /dev/null +++ b/packages/cel/src/lib/common/types/traits/equaler.ts @@ -0,0 +1,26 @@ +import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { equalBoolValue } from '../bool'; +import { equalBytesValue } from '../bytes'; +import { equalDoubleValue } from '../double'; +import { equalInt64Value } from '../int'; +import { equalStringValue } from '../string'; +import { equalUint64Value } from '../uint'; + +export function equalValue(value: Value, other: Value) { + switch (value.kind.case) { + case 'boolValue': + return equalBoolValue(value, other); + case 'bytesValue': + return equalBytesValue(value, other); + case 'doubleValue': + return equalDoubleValue(value, other); + case 'int64Value': + return equalInt64Value(value, other); + case 'stringValue': + return equalStringValue(value, other); + case 'uint64Value': + return equalUint64Value(value, other); + default: + return new Error('no such overload'); + } +} diff --git a/packages/cel/src/lib/common/types/traits/matcher.ts b/packages/cel/src/lib/common/types/traits/matcher.ts new file mode 100644 index 0000000..4efff3e --- /dev/null +++ b/packages/cel/src/lib/common/types/traits/matcher.ts @@ -0,0 +1,11 @@ +import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb'; +import { matchStringValue } from '../string'; + +export function matcher(value: Value, other: Value) { + switch (value.kind.case) { + case 'stringValue': + return matchStringValue(value, other); + default: + return new Error('no such overload'); + } +} diff --git a/packages/cel/src/lib/common/types/traits/math.ts b/packages/cel/src/lib/common/types/traits/math.ts index 26023a6..afc5257 100644 --- a/packages/cel/src/lib/common/types/traits/math.ts +++ b/packages/cel/src/lib/common/types/traits/math.ts @@ -13,6 +13,14 @@ import { multiplyInt64Value, subtractInt64Value, } from '../int'; +import { addStringValue } from '../string'; +import { + addUint64Value, + divideUint64Value, + moduloUint64Value, + multiplyUint64Value, + subtractUint64Value, +} from '../uint'; export function adder(value: Value, other: Value) { switch (value.kind.case) { @@ -22,6 +30,10 @@ export function adder(value: Value, other: Value) { return addDoubleValue(value, other); case 'int64Value': return addInt64Value(value, other); + case 'stringValue': + return addStringValue(value, other); + case 'uint64Value': + return addUint64Value(value, other); default: return new Error('no such overload'); } @@ -33,6 +45,8 @@ export function divider(value: Value, other: Value) { return divideDoubleValue(value, other); case 'int64Value': return divideInt64Value(value, other); + case 'uint64Value': + return divideUint64Value(value, other); default: return new Error('no such overload'); } @@ -42,6 +56,8 @@ export function modder(value: Value, other: Value) { switch (value.kind.case) { case 'int64Value': return moduloInt64Value(value, other); + case 'uint64Value': + return moduloUint64Value(value, other); default: return new Error('no such overload'); } @@ -53,6 +69,8 @@ export function multiplier(value: Value, other: Value) { return multiplyDoubleValue(value, other); case 'int64Value': return multiplyInt64Value(value, other); + case 'uint64Value': + return multiplyUint64Value(value, other); default: return new Error('no such overload'); } @@ -64,6 +82,8 @@ export function subtractor(value: Value, other: Value) { return subtractDoubleValue(value, other); case 'int64Value': return subtractInt64Value(value, other); + case 'uint64Value': + return subtractUint64Value(value, other); default: return new Error('no such overload'); } diff --git a/packages/cel/src/lib/common/types/traits/negater.ts b/packages/cel/src/lib/common/types/traits/negater.ts index 5a443be..a5b05a2 100644 --- a/packages/cel/src/lib/common/types/traits/negater.ts +++ b/packages/cel/src/lib/common/types/traits/negater.ts @@ -3,7 +3,7 @@ import { negateBoolValue } from '../bool'; import { negateDoubleValue } from '../double'; import { negateInt64Value } from '../int'; -export function negate(value: Value) { +export function negater(value: Value) { switch (value.kind.case) { case 'boolValue': return negateBoolValue(value); diff --git a/packages/cel/src/lib/common/types/traits/receiver.ts b/packages/cel/src/lib/common/types/traits/receiver.ts new file mode 100644 index 0000000..78f328e --- /dev/null +++ b/packages/cel/src/lib/common/types/traits/receiver.ts @@ -0,0 +1,16 @@ +import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { receiveStringValue } from '../string'; + +export function receiver( + value: Value, + fn: string, + overload: string, + ...args: Value[] +) { + switch (value.kind.case) { + case 'stringValue': + return receiveStringValue(value, fn, overload, ...args); + default: + return new Error('no such overload'); + } +} diff --git a/packages/cel/src/lib/common/types/traits/sizer.ts b/packages/cel/src/lib/common/types/traits/sizer.ts index 591ae70..798466a 100644 --- a/packages/cel/src/lib/common/types/traits/sizer.ts +++ b/packages/cel/src/lib/common/types/traits/sizer.ts @@ -1,10 +1,13 @@ import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; import { sizeBytesValue } from '../bytes'; +import { sizeStringValue } from '../string'; export function sizer(value: Value) { switch (value.kind.case) { case 'bytesValue': return sizeBytesValue(value); + case 'stringValue': + return sizeStringValue(value); default: return new Error('no such overload'); } diff --git a/packages/cel/src/lib/common/types/traits/zeroer.ts b/packages/cel/src/lib/common/types/traits/zeroer.ts new file mode 100644 index 0000000..7f3223b --- /dev/null +++ b/packages/cel/src/lib/common/types/traits/zeroer.ts @@ -0,0 +1,29 @@ +import { isNil } from '@bearclaw/is'; +import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { boolValue, isZeroBoolValue } from '../bool'; +import { isZeroDoubleValue } from '../double'; +import { isZeroInt64Value } from '../int'; +import { isZeroStringValue } from '../string'; +import { isZeroUint64Value } from '../uint'; + +export function isZeroValue(value: Value | null | undefined) { + if (isNil(value)) { + return boolValue(true); + } + switch (value.kind.value) { + case 'boolValue': + return isZeroBoolValue(value); + case 'bytesValue': + return isZeroBoolValue(value); + case 'doubleValue': + return isZeroDoubleValue(value); + case 'int64Value': + return isZeroInt64Value(value); + case 'stringValue': + return isZeroStringValue(value); + case 'uint64Value': + return isZeroUint64Value(value); + default: + return new Error('no such overload'); + } +} diff --git a/packages/cel/src/lib/common/types/type.ts b/packages/cel/src/lib/common/types/type.ts index 1dbd66b..aa4e589 100644 --- a/packages/cel/src/lib/common/types/type.ts +++ b/packages/cel/src/lib/common/types/type.ts @@ -2,7 +2,12 @@ import { Type, TypeSchema, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { + Value, + ValueSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb'; import { create } from '@bufbuild/protobuf'; +import { formatCELType } from '../format'; export function typeType(value: Type) { return create(TypeSchema, { @@ -33,3 +38,18 @@ export function unwrapTypeType(value: Type) { } return null; } + +export function typeValue(value: Type) { + return create(ValueSchema, { + kind: { + case: 'typeValue', + value: formatCELType(value), + }, + }); +} + +export function isTypeValue(value: Value): value is Value & { + kind: { case: 'typeValue'; value: string }; +} { + return value.kind.case === 'typeValue'; +} diff --git a/packages/cel/src/lib/common/types/uint.spec.ts b/packages/cel/src/lib/common/types/uint.spec.ts index 7192948..4f4480b 100644 --- a/packages/cel/src/lib/common/types/uint.spec.ts +++ b/packages/cel/src/lib/common/types/uint.spec.ts @@ -4,7 +4,33 @@ import { } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; import { create } from '@bufbuild/protobuf'; -import { uint64Constant, uint64Expr, uint64Value } from './uint'; +import { + AnySchema, + UInt32ValueSchema, + UInt64ValueSchema, + anyPack, +} from '@bufbuild/protobuf/wkt'; +import { boolValue } from './bool'; +import { DOUBLE_TYPE, doubleValue } from './double'; +import { INT64_TYPE, MAX_INT64, int64Value } from './int'; +import { STRING_TYPE, stringValue } from './string'; +import { TYPE_TYPE } from './type'; +import { + UINT64_TYPE, + addUint64Value, + compareUint64Value, + convertUint64ValueToNative, + convertUint64ValueToType, + divideUint64Value, + equalUint64Value, + isZeroUint64Value, + moduloUint64Value, + multiplyUint64Value, + subtractUint64Value, + uint64Constant, + uint64Expr, + uint64Value, +} from './uint'; describe('uint', () => { it('uint64Constant', () => { @@ -45,4 +71,324 @@ describe('uint', () => { }) ); }); + + // TODO; validations + + it('convertUint64ValueToNative', () => { + expect(() => { + convertUint64ValueToNative(stringValue('abc'), Number); + }).toThrow(); + const tests = [ + { + input: uint64Value(BigInt(1)), + type: BigInt, + output: BigInt(1), + }, + { + input: uint64Value(BigInt(2)), + type: Number, + output: 2, + }, + { + input: uint64Value(BigInt(42)), + type: AnySchema, + output: anyPack( + UInt64ValueSchema, + create(UInt64ValueSchema, { value: BigInt(42) }) + ), + }, + { + input: uint64Value(BigInt(1234)), + type: UInt32ValueSchema, + output: create(UInt32ValueSchema, { value: 1234 }), + }, + { + input: uint64Value(BigInt(5678)), + type: UInt64ValueSchema, + output: create(UInt64ValueSchema, { value: BigInt(5678) }), + }, + { + input: uint64Value(BigInt(5678)), + type: String, + output: new Error(`type conversion error from 'uint' to 'String'`), + }, + ]; + for (const test of tests) { + expect(convertUint64ValueToNative(test.input, test.type)).toEqual( + test.output + ); + } + }); + + it('convertUint64ValueToType', () => { + expect(() => { + convertUint64ValueToType(stringValue('abc'), UINT64_TYPE); + }).toThrow(); + + const tests = [ + { + in: uint64Value(BigInt(42)), + type: TYPE_TYPE, + out: UINT64_TYPE, + }, + { + in: uint64Value(BigInt(46)), + type: UINT64_TYPE, + out: uint64Value(BigInt(46)), + }, + { + in: uint64Value(BigInt(312)), + type: INT64_TYPE, + out: int64Value(BigInt(312)), + }, + { + in: uint64Value(BigInt(894)), + type: DOUBLE_TYPE, + out: doubleValue(894), + }, + { + in: uint64Value(BigInt(5848)), + type: STRING_TYPE, + out: stringValue('5848'), + }, + { + in: uint64Value(MAX_INT64 + BigInt(1)), + type: INT64_TYPE, + out: new Error('integer overflow'), + }, + { + in: uint64Value(MAX_INT64 + BigInt(1)), + type: UINT64_TYPE, + out: new Error('unsigned integer overflow'), + }, + ]; + for (const test of tests) { + expect(convertUint64ValueToType(test.in, test.type)).toEqual(test.out); + } + }); + + it('equalUint64Value', () => { + expect(() => { + equalUint64Value(stringValue('abc'), uint64Value(BigInt(1))); + }).toThrow(); + const tests = [ + { + a: uint64Value(BigInt(10)), + b: uint64Value(BigInt(10)), + out: boolValue(true), + }, + { + a: uint64Value(BigInt(10)), + b: int64Value(BigInt(-10)), + out: boolValue(false), + }, + { + a: uint64Value(BigInt(10)), + b: int64Value(BigInt(10)), + out: boolValue(true), + }, + { + a: uint64Value(BigInt(9)), + b: int64Value(BigInt(10)), + out: boolValue(false), + }, + { + a: uint64Value(BigInt(10)), + b: doubleValue(10), + out: boolValue(true), + }, + { + a: uint64Value(BigInt(10)), + b: doubleValue(-10.5), + out: boolValue(false), + }, + { + a: uint64Value(BigInt(10)), + b: doubleValue(NaN), + out: boolValue(false), + }, + ]; + for (const test of tests) { + expect(equalUint64Value(test.a, test.b)).toEqual(test.out); + } + }); + + it('isZeroUint64Value', () => { + expect(() => { + isZeroUint64Value(stringValue('abc')); + }).toThrow(); + expect(isZeroUint64Value(uint64Value(BigInt(0)))).toEqual(boolValue(true)); + expect(isZeroUint64Value(uint64Value(BigInt(1)))).toEqual(boolValue(false)); + }); + + it('addUint64Value', () => { + expect(() => { + addUint64Value(stringValue('abc'), uint64Value(BigInt(1))); + }).toThrow(); + expect( + addUint64Value(uint64Value(BigInt(1)), uint64Value(BigInt(2))) + ).toEqual(uint64Value(BigInt(3))); + expect(addUint64Value(uint64Value(BigInt(1)), stringValue('2'))).toEqual( + new Error('no such overload') + ); + expect( + addUint64Value(uint64Value(MAX_INT64), uint64Value(BigInt(1))) + ).toEqual(new Error('unsigned integer overflow')); + expect( + addUint64Value(uint64Value(BigInt(1)), int64Value(BigInt(-1000))) + ).toEqual(new Error('unsigned integer overflow')); + expect( + addUint64Value(uint64Value(MAX_INT64 - BigInt(1)), uint64Value(BigInt(1))) + ).toEqual(uint64Value(MAX_INT64)); + }); + + it('compareUint64Value', () => { + expect(() => { + compareUint64Value(stringValue('abc'), uint64Value(BigInt(1))); + }).toThrow(); + const tests = [ + { + a: uint64Value(BigInt(42)), + b: uint64Value(BigInt(42)), + out: int64Value(BigInt(0)), + }, + { + a: uint64Value(BigInt(42)), + b: int64Value(BigInt(42)), + out: int64Value(BigInt(0)), + }, + { + a: uint64Value(BigInt(42)), + b: doubleValue(42), + out: int64Value(BigInt(0)), + }, + { + a: uint64Value(BigInt(13)), + b: int64Value(BigInt(204)), + out: int64Value(BigInt(-1)), + }, + { + a: uint64Value(BigInt(13)), + b: uint64Value(BigInt(204)), + out: int64Value(BigInt(-1)), + }, + { + a: uint64Value(BigInt(204)), + b: doubleValue(204.1), + out: int64Value(BigInt(-1)), + }, + { + a: uint64Value(BigInt(204)), + b: int64Value(BigInt(205)), + out: int64Value(BigInt(-1)), + }, + { + a: uint64Value(BigInt(204)), + b: doubleValue(Number(MAX_INT64) + 2049.0), + out: int64Value(BigInt(-1)), + }, + { + a: uint64Value(BigInt(204)), + b: doubleValue(NaN), + out: new Error('NaN values cannot be ordered'), + }, + { + a: uint64Value(BigInt(1300)), + b: int64Value(BigInt(-1)), + out: int64Value(BigInt(1)), + }, + { + a: uint64Value(BigInt(204)), + b: uint64Value(BigInt(13)), + out: int64Value(BigInt(1)), + }, + { + a: uint64Value(BigInt(204)), + b: doubleValue(203.9), + out: int64Value(BigInt(1)), + }, + { + a: uint64Value(BigInt(204)), + b: doubleValue(-1.0), + out: int64Value(BigInt(1)), + }, + { + a: uint64Value(BigInt(12)), + b: stringValue('1'), + out: new Error('no such overload'), + }, + ]; + for (const test of tests) { + expect(compareUint64Value(test.a, test.b)).toEqual(test.out); + } + }); + + it('divideUint64Value', () => { + expect(() => { + divideUint64Value(stringValue('abc'), uint64Value(BigInt(1))); + }).toThrow(); + expect( + divideUint64Value(uint64Value(BigInt(3)), uint64Value(BigInt(2))) + ).toEqual(uint64Value(BigInt(1))); + expect(divideUint64Value(uint64Value(BigInt(3)), stringValue('2'))).toEqual( + new Error('no such overload') + ); + expect( + divideUint64Value(uint64Value(BigInt(3)), uint64Value(BigInt(0))) + ).toEqual(new Error('divide by zero')); + }); + + it('moduloUint64Value', () => { + expect(() => { + moduloUint64Value(stringValue('abc'), uint64Value(BigInt(1))); + }).toThrow(); + expect( + moduloUint64Value(uint64Value(BigInt(21)), uint64Value(BigInt(2))) + ).toEqual(uint64Value(BigInt(1))); + expect(moduloUint64Value(uint64Value(BigInt(3)), stringValue('2'))).toEqual( + new Error('no such overload') + ); + expect( + moduloUint64Value(uint64Value(BigInt(3)), uint64Value(BigInt(0))) + ).toEqual(new Error('modulus by zero')); + }); + + it('multiplyUint64Value', () => { + expect(() => { + multiplyUint64Value(stringValue('abc'), uint64Value(BigInt(1))); + }).toThrow(); + expect( + multiplyUint64Value(uint64Value(BigInt(3)), uint64Value(BigInt(2))) + ).toEqual(uint64Value(BigInt(6))); + expect( + multiplyUint64Value(uint64Value(BigInt(3)), stringValue('2')) + ).toEqual(new Error('no such overload')); + expect( + multiplyUint64Value(uint64Value(BigInt(3)), uint64Value(BigInt(0))) + ).toEqual(uint64Value(BigInt(0))); + expect( + multiplyUint64Value(uint64Value(MAX_INT64), uint64Value(BigInt(2))) + ).toEqual(new Error('unsigned integer overflow')); + expect( + multiplyUint64Value(uint64Value(BigInt(42)), int64Value(BigInt(-1))) + ).toEqual(new Error('unsigned integer overflow')); + }); + + it('subtractUint64Value', () => { + expect(() => { + subtractUint64Value(stringValue('abc'), uint64Value(BigInt(1))); + }).toThrow(); + expect( + subtractUint64Value(uint64Value(BigInt(3)), uint64Value(BigInt(2))) + ).toEqual(uint64Value(BigInt(1))); + expect( + subtractUint64Value(uint64Value(BigInt(3)), stringValue('2')) + ).toEqual(new Error('no such overload')); + expect( + subtractUint64Value(uint64Value(BigInt(3)), uint64Value(BigInt(4))) + ).toEqual(new Error('unsigned integer overflow')); + expect( + subtractUint64Value(uint64Value(MAX_INT64), int64Value(BigInt(-1))) + ).toEqual(new Error('unsigned integer overflow')); + }); }); diff --git a/packages/cel/src/lib/common/types/uint.ts b/packages/cel/src/lib/common/types/uint.ts index 812dccb..d54c957 100644 --- a/packages/cel/src/lib/common/types/uint.ts +++ b/packages/cel/src/lib/common/types/uint.ts @@ -13,9 +13,23 @@ import { ValueSchema, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; import { create } from '@bufbuild/protobuf'; +import { + AnySchema, + UInt32ValueSchema, + UInt64ValueSchema, + anyPack, +} from '@bufbuild/protobuf/wkt'; +import { formatCELType } from '../format'; +import { boolValue } from './bool'; +import { compareNumberValues } from './compare'; import { isConstExpr } from './constant'; -import { MAX_INT64 } from './int'; +import { doubleValue, isDoubleValue } from './double'; +import { MAX_INT64, int64Value } from './int'; +import { NativeType } from './native'; +import { isNumberValue } from './number'; import { primitiveType } from './primitive'; +import { stringValue } from './string'; +import { Trait } from './traits/trait'; export const UINT64_TYPE = primitiveType(Type_PrimitiveType.UINT64); @@ -84,6 +98,15 @@ export function isUint64Value(value: Value): value is Value & { return value.kind.case === 'uint64Value'; } +export function isValidUint32(value: number) { + return ( + !Number.isNaN(value) && + value >= 0 && + value <= Number.MAX_SAFE_INTEGER && + value <= Infinity + ); +} + export function isValidUint64(value: bigint) { return ( !Number.isNaN(value) && @@ -92,3 +115,217 @@ export function isValidUint64(value: bigint) { value <= Infinity ); } + +export function convertUint64ValueToNative(value: Value, type: NativeType) { + if (!isUint64Value(value)) { + throw new Error('int64 value is not a int64'); + } + switch (type) { + case BigInt: + return value.kind.value; + case Number: + return Number(value.kind.value); + case AnySchema: + return anyPack( + UInt64ValueSchema, + create(UInt64ValueSchema, { value: value.kind.value }) + ); + case UInt32ValueSchema: + if (!isValidUint32(Number(value.kind.value))) { + return new Error('unsigned integer overflow'); + } + return create(UInt32ValueSchema, { value: Number(value.kind.value) }); + case UInt64ValueSchema: + if (!isValidUint64(value.kind.value)) { + return new Error('unsigned integer overflow'); + } + return create(UInt64ValueSchema, { value: value.kind.value }); + default: + break; + } + return new Error( + `type conversion error from '${formatCELType(UINT64_TYPE)}' to '${ + type.name + }'` + ); +} + +export function convertUint64ValueToType(value: Value, type: Type) { + if (!isUint64Value(value)) { + throw new Error('int64 value is not a int64'); + } + switch (type.typeKind.case) { + case 'primitive': + switch (type.typeKind.value) { + case Type_PrimitiveType.INT64: + if ( + Number.isNaN(value.kind.value) || + !isValidUint64(value.kind.value) + ) { + return new Error('integer overflow'); + } + return int64Value(value.kind.value); + case Type_PrimitiveType.UINT64: + if ( + Number.isNaN(value.kind.value) || + !isValidUint64(value.kind.value) + ) { + return new Error('unsigned integer overflow'); + } + return uint64Value(value.kind.value); + case Type_PrimitiveType.DOUBLE: + return doubleValue(Number(value.kind.value)); + case Type_PrimitiveType.STRING: + return stringValue(value.kind.value.toString()); + default: + break; + } + break; + case 'type': + return UINT64_TYPE; + default: + break; + } + return new Error( + `type conversion error from '${formatCELType( + UINT64_TYPE + )}' to '${formatCELType(type)}'` + ); +} + +export function equalUint64Value(value: Value, other: Value) { + if (!isUint64Value(value)) { + throw new Error('int64 value is not a int64'); + } + if (!isNumberValue(other)) { + return boolValue(false); + } + if ( + Number.isNaN(Number(value.kind.value)) || + Number.isNaN(Number(other.kind.value)) + ) { + return boolValue(false); + } + const compared = compareNumberValues(value, other); + if (compared instanceof Error) { + return boolValue(false); + } + return boolValue(compared.kind.value === BigInt(0)); +} + +export function isZeroUint64Value(value: Value) { + if (!isUint64Value(value)) { + throw new Error('int64 value is not a int64'); + } + return boolValue(value.kind.value === BigInt(0)); +} + +export const UINT64_TRAITS = new Set([ + Trait.ADDER_TYPE, + Trait.COMPARER_TYPE, + Trait.DIVIDER_TYPE, + Trait.MODDER_TYPE, + Trait.MULTIPLIER_TYPE, + Trait.SUBTRACTOR_TYPE, +]); + +export function addUint64Value(value: Value, other: Value) { + if (!isUint64Value(value)) { + throw new Error('int64 value is not a int64'); + } + if (!isNumberValue(other)) { + return new Error('no such overload'); + } + if ( + (other.kind.value > 0 && + value.kind.value > MAX_INT64 - BigInt(other.kind.value)) || + (other.kind.value < 0 && + value.kind.value < Math.abs(Number(other.kind.value))) + ) { + return new Error('unsigned integer overflow'); + } + return uint64Value(value.kind.value + BigInt(other.kind.value)); +} + +export function compareUint64Value(value: Value, other: Value) { + if (!isUint64Value(value)) { + throw new Error('int64 value is not a int64'); + } + if (!isNumberValue(other)) { + return new Error('no such overload'); + } + if ( + Number.isNaN(Number(value.kind.value)) || + Number.isNaN(Number(other.kind.value)) + ) { + return new Error('NaN values cannot be ordered'); + } + if (isDoubleValue(other) && value.kind.value < Number.MIN_SAFE_INTEGER) { + return uint64Value(BigInt(-1)); + } + if (isDoubleValue(other) && value.kind.value > Number.MAX_SAFE_INTEGER) { + return uint64Value(BigInt(1)); + } + return compareNumberValues(value, other); +} + +export function divideUint64Value(value: Value, other: Value) { + if (!isUint64Value(value)) { + throw new Error('int64 value is not a int64'); + } + if (!isNumberValue(other)) { + return new Error('no such overload'); + } + if (Number(other.kind.value) === 0) { + return new Error('divide by zero'); + } + return uint64Value(value.kind.value / BigInt(other.kind.value)); +} + +export function moduloUint64Value(value: Value, other: Value) { + if (!isUint64Value(value)) { + throw new Error('int64 value is not a int64'); + } + if (!isNumberValue(other)) { + return new Error('no such overload'); + } + if (Number(other.kind.value) === 0) { + return new Error('modulus by zero'); + } + return uint64Value(value.kind.value % BigInt(other.kind.value)); +} + +export function multiplyUint64Value(value: Value, other: Value) { + if (!isUint64Value(value)) { + throw new Error('int64 value is not a int64'); + } + if (!isNumberValue(other)) { + return new Error('no such overload'); + } + const x = value.kind.value; + const y = BigInt(other.kind.value); + // Detecting multiplication overflow is more complicated than the others. The + // first two detect attempting to negate MinUint64, which would result in + // MaxUint64+1. The other four detect normal overflow conditions. + if (y !== BigInt(0) && x > MAX_INT64 / y) { + return new Error('unsigned integer overflow'); + } + return uint64Value(value.kind.value * BigInt(other.kind.value)); +} + +export function subtractUint64Value(value: Value, other: Value) { + if (!isUint64Value(value)) { + throw new Error('int64 value is not a int64'); + } + if (!isNumberValue(other)) { + return new Error('no such overload'); + } + if (other.kind.value > value.kind.value) { + return new Error('unsigned integer overflow'); + } + const result = value.kind.value - BigInt(other.kind.value); + if (result < BigInt(0) || result > MAX_INT64) { + return new Error('unsigned integer overflow'); + } + return uint64Value(result); +} diff --git a/packages/cel/src/lib/common/types/unknown.ts b/packages/cel/src/lib/common/types/unknown.ts new file mode 100644 index 0000000..d25ae53 --- /dev/null +++ b/packages/cel/src/lib/common/types/unknown.ts @@ -0,0 +1,19 @@ +import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { create } from '@bufbuild/protobuf'; +import { ValueSchema } from '@bufbuild/protobuf/wkt'; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function unknownValue(value: any) { + return create(ValueSchema, { + kind: { + case: undefined, + value, + }, + }); +} + +export function isUnknownValue(value: Value): value is Value & { + kind: { case: undefined }; +} { + return value.kind.case === undefined; +} diff --git a/packages/cel/src/lib/common/types/value.ts b/packages/cel/src/lib/common/types/value.ts new file mode 100644 index 0000000..3b4d941 --- /dev/null +++ b/packages/cel/src/lib/common/types/value.ts @@ -0,0 +1,71 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { isBigInt, isBoolean, isNumber, isString, isType } from '@bearclaw/is'; +import { + Value, + ValueSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb'; +import { isMessage } from '@bufbuild/protobuf'; +import { DurationSchema, TimestampSchema } from '@bufbuild/protobuf/wkt'; +import { BOOL_TRAITS, boolValue } from './bool'; +import { BYTES_TRAITS, bytesValue } from './bytes'; +import { DOUBLE_TRAITS, doubleValue } from './double'; +import { durationValue } from './duration'; +import { INT64_TRAITS, int64Value } from './int'; +import { STRING_TRAITS, stringValue } from './string'; +import { timestampValue } from './timestamp'; +import { Trait } from './traits/trait'; +import { UINT64_TRAITS } from './uint'; + +/** + * Convert an arbitrary value to a CEL Value. + * + * @param obj the object to convert to a Value + * @returns a CEL Value or an Error + */ +export function valueOf(obj: any): Value | Error { + if (isMessage(obj, ValueSchema)) { + return obj; + } + if (isBoolean(obj)) { + return boolValue(obj); + } + if (isType(obj, 'Uint8Array')) { + return bytesValue(obj); + } + if (isString(obj)) { + return stringValue(obj); + } + if (isNumber(obj)) { + return doubleValue(obj); + } + if (isBigInt(obj)) { + return int64Value(obj); + } + if (isMessage(obj, TimestampSchema)) { + return timestampValue(obj); + } + if (isMessage(obj, DurationSchema)) { + return durationValue(obj); + } + return new Error(`cannot convert ${obj} to Value`); +} + +export function valueHasTrait(value: Value, trait: Trait): boolean { + switch (value.kind.case) { + case 'boolValue': + return BOOL_TRAITS.has(trait); + case 'bytesValue': + return BYTES_TRAITS.has(trait); + case 'doubleValue': + return DOUBLE_TRAITS.has(trait); + case 'int64Value': + return INT64_TRAITS.has(trait); + case 'stringValue': + return STRING_TRAITS.has(trait); + case 'uint64Value': + return UINT64_TRAITS.has(trait); + // TODO: other types + default: + return false; + } +} diff --git a/packages/cel/src/lib/interpreter/activation.ts b/packages/cel/src/lib/interpreter/activation.ts index 50c3c7b..b8e0d7f 100644 --- a/packages/cel/src/lib/interpreter/activation.ts +++ b/packages/cel/src/lib/interpreter/activation.ts @@ -33,7 +33,7 @@ export interface Activation { export class MapActivation implements Activation { #bindings: Map; - constructor(bindings: Map | Record) { + constructor(bindings: Map | Record = new Map()) { this.#bindings = isMap(bindings) ? bindings : objectToMap(bindings); diff --git a/packages/cel/src/lib/interpreter/attribute-factory.spec.ts b/packages/cel/src/lib/interpreter/attribute-factory.spec.ts new file mode 100644 index 0000000..8f266a1 --- /dev/null +++ b/packages/cel/src/lib/interpreter/attribute-factory.spec.ts @@ -0,0 +1,51 @@ +import { CELContainer } from '../common/container'; +import { ProtoTypeRegistry } from '../common/pb/proto-type-registry'; +import { INT64_TYPE } from '../common/types/int'; +import { stringValue } from '../common/types/string'; +import { typeValue } from '../common/types/type'; +import { MapActivation } from './activation'; +import { AbsoluteAttribute, AttrFactory } from './attribute-factory'; +import { Cost } from './coster'; + +describe('AttributeFactory', () => { + it('AbsoluteAttribute', () => { + const reg = new ProtoTypeRegistry(); + const container = new CELContainer('acme.ns'); + const attrs = new AttrFactory(container, reg, reg); + const vars = new MapActivation({ + 'acme.a': { + b: { + 4: { + false: 'success', + }, + }, + }, + }); + + // acme.a.b[4][false] + const attr = attrs.absoluteAttribute( + BigInt(1), + 'acme.a' + ) as AbsoluteAttribute; + const qualB = attrs.newQualifier(null, BigInt(2), 'b'); + const qual4 = attrs.newQualifier(null, BigInt(3), 4); + const qualFalse = attrs.newQualifier(null, BigInt(4), false); + attr.addQualifier(qualB); + attr.addQualifier(qual4); + attr.addQualifier(qualFalse); + const out = attr.resolve(vars); + expect(out).toEqual(stringValue('success')); + expect(attr.cost()).toEqual(new Cost(1, 1)); + }); + + it('AbosluteAttribute_Type', () => { + const reg = new ProtoTypeRegistry(); + const attrs = new AttrFactory(new CELContainer(), reg, reg); + + // int + const attr = attrs.absoluteAttribute(BigInt(1), 'int') as AbsoluteAttribute; + const out = attr.resolve(new MapActivation()); + expect(out).toEqual(typeValue(INT64_TYPE)); + expect(attr.cost()).toEqual(new Cost(1, 1)); + }); +}); diff --git a/packages/cel/src/lib/interpreter/attribute-factory.ts b/packages/cel/src/lib/interpreter/attribute-factory.ts index 4871f3d..2494057 100644 --- a/packages/cel/src/lib/interpreter/attribute-factory.ts +++ b/packages/cel/src/lib/interpreter/attribute-factory.ts @@ -1,18 +1,37 @@ +import { NULL_VALUE, isNullValue } from './../common/types/null'; /* eslint-disable @typescript-eslint/no-explicit-any */ -import { isFunction, isNil } from '@bearclaw/is'; +import { + isArray, + isBigInt, + isBoolean, + isFunction, + isNil, + isNumber, + isString, +} from '@bearclaw/is'; import { Type } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; -import { ExprValue } from '@buf/google_cel-spec.bufbuild_es/cel/expr/eval_pb.js'; -import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; -import { CELContainer } from '../cel'; import { - isExprValueError, - isExprValueUnknown, - isExprValueValue, -} from '../common/expr-value'; + Value, + ValueSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { isMessage } from '@bufbuild/protobuf'; +import { NullValue } from '@bufbuild/protobuf/wkt'; +import { CELContainer } from '../cel'; import { TypeAdapter } from '../common/ref/adapter'; +import { FieldType } from '../common/ref/field-type'; import { TypeProvider } from '../common/ref/provider'; -import { isBoolValue } from '../common/types/bool'; -import { isStringValue } from '../common/types/string'; +import { boolValue, equalBoolValue, isBoolValue } from '../common/types/bool'; +import { doubleValue, equalDoubleValue } from '../common/types/double'; +import { equalInt64Value, int64Value } from '../common/types/int'; +import { isMessageType } from '../common/types/message'; +import { + equalStringValue, + isStringValue, + stringValue, +} from '../common/types/string'; +import { equalUint64Value } from '../common/types/uint'; +import { isUnknownValue } from '../common/types/unknown'; +import { valueOf } from '../common/types/value'; import { Activation } from './activation'; import { QualifierValueEquator } from './attribute-pattern'; import { Cost, Coster } from './coster'; @@ -93,7 +112,11 @@ export interface Qualifier { * Qualify performs a qualification, e.g. field selection, on the input * object and returns the value or error that results. */ - qualify(vars: Activation, obj: any): ExprValue; + qualify(vars: Activation, obj: any): Value | Error; +} + +export function isQualifier(value: any): value is Qualifier { + return isFunction(value.id) && isFunction(value.qualify); } /** @@ -103,9 +126,16 @@ export interface Qualifier { * Non-constant qualifiers are of Attribute type. */ export interface ConstantQualifier extends Qualifier { + /** + * Value returns the constant value of the qualifier. + */ value(): Value; } +export function isConstantQualifier(value: any): value is ConstantQualifier { + return isFunction(value.value) && isQualifier(value); +} + export interface ConstantQualifierEquator extends QualifierValueEquator, ConstantQualifier {} @@ -114,7 +144,7 @@ export interface ConstantQualifierEquator * Attribute values are a variable or value with an optional set of qualifiers, * such as field, key, or index accesses. */ -interface Attribute extends Qualifier { +export interface Attribute extends Qualifier { /** * AddQualifier adds a qualifier on the Attribute or error if the * qualification is not a valid qualifier type. @@ -124,7 +154,15 @@ interface Attribute extends Qualifier { /** * Resolve returns the value of the Attribute given the current Activation. */ - resolve(a: Activation): ExprValue; + resolve(a: Activation): Value | Error; +} + +export function isAttribute(value: any): value is Attribute { + return ( + isFunction(value.addQualifier) && + isFunction(value.resolve) && + isQualifier(value) + ); } /** @@ -148,7 +186,7 @@ export interface NamespacedAttribute extends Attribute { * will be returned immediately. If the attribute cannot be resolved within * the Activation, the result must be: `nil`, `false`, `nil`. */ - tryResolve(a: Activation): ExprValue | null; + tryResolve(a: Activation): Value | Error | null; } export class AttrFactory implements AttributeFactory { @@ -200,8 +238,20 @@ export class AttrFactory implements AttributeFactory { return new RelativeAttribute(id, operand, [], this.#adapter, this); } - newQualifier(objType: Type, qualID: bigint, val: any): Qualifier { - throw new Error('Method not implemented.'); + newQualifier(objType: Type | null, qualID: bigint, val: any): Qualifier { + // Before creating a new qualifier check to see if this is a protobuf + // message field access. + // If so, use the precomputed GetFrom qualification method rather than the + // standard stringQualifier. + if (isString(val)) { + if (!isNil(objType) && isMessageType(objType)) { + const ft = this.#provider.findFieldType(objType.typeKind.value, val); + if (!isNil(ft) && ft instanceof FieldType) { + return new FieldQualifier(qualID, val, ft, this.#adapter); + } + } + } + return newQualifier(this.#adapter, qualID, val); } } @@ -268,20 +318,23 @@ export class AbsoluteAttribute return this.#namespacedNames; } - qualify(vars: Activation, obj: any): any { + qualify(vars: Activation, obj: any) { const val = this.resolve(vars); - if (isExprValueUnknown(val)) { + if (val instanceof Error) { + return val; + } + if (isUnknownValue(val)) { return val; } const qual = this.#fac.newQualifier(null, this.#id, val); return qual.qualify(vars, obj); } - resolve(vars: Activation): T { + resolve(vars: Activation): Value | Error { return this.tryResolve(vars); } - tryResolve(vars: Activation): T { + tryResolve(vars: Activation): Value | Error { for (const nm of this.#namespacedNames) { // If the variable is found, process it. Otherwise, wait until the checks\ // to determine whether the type is unknown before returning. @@ -291,21 +344,21 @@ export class AbsoluteAttribute for (const qual of this.#qualifiers) { const op2 = qual.qualify(vars, op); if (op2 instanceof Error) { - return op2 as T; + return op2; } if (op2 == null) { break; } op = op2; } - return op as T; + return valueOf(op); } // Attempt to resolve the qualified type name if the name is not a // variable identifier. const typ = this.#provider.findIdent(nm); if (!isNil(typ)) { if (this.#qualifiers.length === 0) { - return typ as T; + return typ; } throw noSuchAttributeException(this.toString()); } @@ -376,7 +429,10 @@ export class ConditionalAttribute implements Qualifier, Attribute, Coster { qualify(vars: Activation, obj: any) { const val = this.resolve(vars); - if (isExprValueUnknown(val)) { + if (val instanceof Error) { + return val; + } + if (isUnknownValue(val)) { return val; } const qual = this.#fac.newQualifier(null, this.#id, val); @@ -385,26 +441,20 @@ export class ConditionalAttribute implements Qualifier, Attribute, Coster { resolve(vars: Activation) { const val = this.#expr.eval(vars); - if (isExprValueError(val)) { - throw new Error( - `messsage: ${val.kind.value.errors.map((e) => e.message).join(', ')}` - ); - } - if (isExprValueValue(val)) { - const v = val.kind.value; - if (!isBoolValue(v)) { - // This should never happen - throw new Error('conditional expression must be a boolean'); - } - if (v.kind.value) { - return this.#truthy.resolve(vars); - } - return this.#falsy.resolve(vars); + if (val instanceof Error) { + throw new Error(`messsage: ${val.message}`); } - if (isExprValueUnknown(val)) { + if (isUnknownValue(val)) { return val; } - return val; + if (!isBoolValue(val)) { + // This should never happen + throw new Error('conditional expression must be a boolean'); + } + if (val.kind.value) { + return this.#truthy.resolve(vars); + } + return this.#falsy.resolve(vars); } toString() { @@ -516,7 +566,10 @@ export class MaybeAttribute implements Coster, Attribute, Qualifier { qualify(vars: Activation, obj: any) { const val = this.resolve(vars); - if (isExprValueUnknown(val)) { + if (val instanceof Error) { + return val; + } + if (isUnknownValue(val)) { return val; } const qual = this.#fac.newQualifier(null, this.#id, val); @@ -584,35 +637,36 @@ export class RelativeAttribute implements Coster, Qualifier, Attribute { return this; } - qualify(vars: Activation, obj: any): ExprValue { + qualify(vars: Activation, obj: any) { const val = this.resolve(vars); - if (isExprValueUnknown(val)) { + if (val instanceof Error) { + return val; + } + if (isUnknownValue(val)) { return val; } const qual = this.#fac.newQualifier(null, this.#id, val); return qual.qualify(vars, obj); } - resolve(vars: Activation): ExprValue { + resolve(vars: Activation) { // First, evaluate the operand. const v = this.#operand.eval(vars); - if (isExprValueError(v)) { - throw new Error( - `message: ${v.kind.value.errors.map((e) => e.message).join(', ')}` - ); + if (v instanceof Error) { + throw new Error(`message: ${v.message}`); } - if (isExprValueUnknown(v)) { + if (isUnknownValue(v)) { return v; } // Next, qualify it. Qualification handles unkonwns as well, so there's no // need to recheck. - let obj = v; + let obj: Value | Error = v; for (const qual of this.#qualifiers) { if (isNil(obj)) { throw noSuchAttributeException(this.toString()); } obj = qual.qualify(vars, obj); - if (isExprValueError(obj)) { + if (obj instanceof Error) { return obj; } } @@ -627,6 +681,626 @@ export class RelativeAttribute implements Coster, Qualifier, Attribute { } } +export function newQualifier( + adapter: TypeAdapter, + id: bigint, + v: any +): Qualifier { + if (isAttribute(v)) { + return v; + } + + if (isMessage(ValueSchema, v)) { + switch (v.kind.case) { + case 'stringValue': + return new StringQualifier(id, v.kind.value, v, adapter); + case 'doubleValue': + return new DoubleQualifier(id, v.kind.value, v, adapter); + case 'int64Value': + return new IntQualifier(id, v.kind.value, v, adapter); + case 'uint64Value': + return new UintQualifier(id, v.kind.value, v, adapter); + case 'boolValue': + return new BoolQualifier(id, v.kind.value, v, adapter); + case 'nullValue': + return new NullQualifier(id, v, adapter); + default: + throw new Error('unsupported value type'); + } + } + if (isString(v)) { + return new StringQualifier(id, v, stringValue(v), adapter); + } + if (isNumber(v)) { + return new DoubleQualifier(id, v, doubleValue(v), adapter); + } + if (isBigInt(v)) { + return new IntQualifier(id, v, int64Value(v), adapter); + } + if (isBoolean(v)) { + return new BoolQualifier(id, v, boolValue(v), adapter); + } + throw new Error(`invalid qualifier type: ${v}`); +} + +export class AttrQualifier implements Coster, Attribute { + readonly #id: bigint; + readonly #attribute: Attribute; + + constructor(id: bigint, attribute: Attribute) { + this.#id = id; + this.#attribute = attribute; + } + + id(): bigint { + return this.#id; + } + + /** + * Cost returns zero for constant field qualifiers + */ + cost(): Cost { + return Cost.estimateCost(this.#attribute); + } + + addQualifier(q: Qualifier): Attribute { + return this.#attribute.addQualifier(q); + } + + resolve(vars: Activation) { + return this.#attribute.resolve(vars); + } + + qualify(vars: Activation, obj: any) { + return this.#attribute.qualify(vars, obj); + } + + toString() { + return `AttrQualifier{id=${this.id()}, attribute=${this.#attribute.toString()}};`; + } +} + +export class StringQualifier + implements Coster, ConstantQualifierEquator, QualifierValueEquator +{ + readonly #id: bigint; + readonly #value: string; + readonly #celValue: Value; + readonly #adapter: TypeAdapter; + + constructor( + id: bigint, + value: string, + celValue: Value, + adapter: TypeAdapter + ) { + this.#id = id; + this.#value = value; + this.#celValue = celValue; + this.#adapter = adapter; + } + + id(): bigint { + return this.#id; + } + + /** + * Cost returns zero for constant field qualifiers + */ + cost(): Cost { + return Cost.None; + } + + value(): Value { + return this.#celValue; + } + + qualifierValueEquals(value: any): boolean { + if (isMessage(ValueSchema, value)) { + return equalStringValue(this.#celValue, value).kind.value as boolean; + } + if (isString(value)) { + return this.#value === value; + } + return false; + } + + qualify(vars: Activation, obj: any) { + if (obj instanceof Map) { + const found = obj.get(this.#value); + if (isNil(found)) { + if (obj.has(this.#value)) { + return NULL_VALUE; + } + throw noSuchKeyException(this.#value); + } + } else if (obj instanceof Object) { + if (this.#value in obj) { + if (isNil(obj[this.#value])) { + return NULL_VALUE; + } + return obj[this.#value]; + } + throw noSuchKeyException(this.#value); + } else if (isUnknownValue(obj)) { + return obj; + } + return refResolve(this.#adapter, this.#celValue, obj); + } + + toString() { + return `StringQualifier{id=${this.#id}, value=${this.#value}}`; + } +} + +export class DoubleQualifier + implements Coster, ConstantQualifierEquator, QualifierValueEquator +{ + readonly #id: bigint; + readonly #value: number; + readonly #celValue: Value; + readonly #adapter: TypeAdapter; + + constructor( + id: bigint, + value: number, + celValue: Value, + adapter: TypeAdapter + ) { + this.#id = id; + this.#value = value; + this.#celValue = celValue; + this.#adapter = adapter; + } + + id(): bigint { + return this.#id; + } + + value(): Value { + return this.#celValue; + } + + /** + * Cost returns zero for constant field qualifiers + */ + cost(): Cost { + return Cost.None; + } + + qualify(vars: Activation, obj: any) { + const i = this.#value; + if (obj instanceof Map) { + const found = obj.get(i); + if (isNil(found)) { + if (obj.has(i)) { + return NULL_VALUE; + } + throw noSuchKeyException(i.toString()); + } + return obj; + } else if (obj instanceof Object) { + if (i in obj) { + if (isNil(obj[i])) { + return NULL_VALUE; + } + return obj[i]; + } + throw noSuchKeyException(i.toString()); + } else if (isArray(obj)) { + if (i < 0 || i >= obj.length) { + throw indexOutOfBoundsException(i); + } + return obj[i]; + } + if (isUnknownValue(obj)) { + return obj; + } + return refResolve(this.#adapter, this.#celValue, obj); + } + + qualifierValueEquals(value: any): boolean { + if (isMessage(ValueSchema, value)) { + return equalDoubleValue(this.#celValue, value).kind.value as boolean; + } + if (isNumber(value)) { + return this.#value === value; + } + return false; + } + + toString() { + return `DoubleQualifier{id=${this.#id}, value=${this.#value}}`; + } +} + +export class IntQualifier + implements Coster, ConstantQualifierEquator, QualifierValueEquator +{ + readonly #id: bigint; + readonly #value: bigint; + readonly #celValue: Value; + readonly #adapter: TypeAdapter; + + constructor( + id: bigint, + value: bigint, + celValue: Value, + adapter: TypeAdapter + ) { + this.#id = id; + this.#value = value; + this.#celValue = celValue; + this.#adapter = adapter; + } + + id(): bigint { + return this.#id; + } + + value(): Value { + return this.#celValue; + } + + /** + * Cost returns zero for constant field qualifiers + */ + cost(): Cost { + return Cost.None; + } + + qualify(vars: Activation, obj: any) { + const i = this.#value; + if (obj instanceof Map) { + const found = obj.get(i); + if (isNil(found)) { + if (obj.has(i)) { + return NULL_VALUE; + } + throw noSuchKeyException(i.toString()); + } + return obj; + } else if (obj instanceof Object) { + if (Number(i) in obj) { + if (isNil(obj[Number(i)])) { + return NULL_VALUE; + } + return obj[Number(i)]; + } + throw noSuchKeyException(i.toString()); + } else if (isArray(obj)) { + if (i < 0 || i >= obj.length) { + throw indexOutOfBoundsException(Number(i)); + } + return obj[Number(i)]; + } + if (isUnknownValue(obj)) { + return obj; + } + return refResolve(this.#adapter, this.#celValue, obj); + } + + qualifierValueEquals(value: any): boolean { + if (isMessage(ValueSchema, value)) { + return equalInt64Value(this.#celValue, value).kind.value as boolean; + } + if (isBigInt(value)) { + return this.#value === value; + } + return false; + } + + toString() { + return `IntQualifier{id=${this.#id}, value=${this.#value}}`; + } +} + +export class UintQualifier + implements Coster, ConstantQualifierEquator, QualifierValueEquator +{ + readonly #id: bigint; + readonly #value: bigint; + readonly #celValue: Value; + readonly #adapter: TypeAdapter; + + constructor( + id: bigint, + value: bigint, + celValue: Value, + adapter: TypeAdapter + ) { + this.#id = id; + this.#value = value; + this.#celValue = celValue; + this.#adapter = adapter; + } + + id(): bigint { + return this.#id; + } + + value(): Value { + return this.#celValue; + } + + /** + * Cost returns zero for constant field qualifiers + */ + cost(): Cost { + return Cost.None; + } + + qualify(vars: Activation, obj: any) { + const i = this.#value; + if (obj instanceof Map) { + const found = obj.get(i); + if (isNil(found)) { + if (obj.has(i)) { + return NULL_VALUE; + } + throw noSuchKeyException(i.toString()); + } + return obj; + } else if (obj instanceof Object) { + if (Number(i) in obj) { + if (isNil(obj[Number(i)])) { + return NULL_VALUE; + } + return obj[Number(i)]; + } + throw noSuchKeyException(i.toString()); + } else if (isArray(obj)) { + if (i < 0 || i >= obj.length) { + throw indexOutOfBoundsException(Number(i)); + } + return obj[Number(i)]; + } + if (isUnknownValue(obj)) { + return obj; + } + return refResolve(this.#adapter, this.#celValue, obj); + } + + qualifierValueEquals(value: any): boolean { + if (isMessage(ValueSchema, value)) { + return equalUint64Value(this.#celValue, value).kind.value as boolean; + } + if (isBigInt(value)) { + return this.#value === value; + } + return false; + } + + toString() { + return `UintQualifier{id=${this.#id}, value=${this.#value}}`; + } +} + +export class BoolQualifier + implements Coster, ConstantQualifierEquator, QualifierValueEquator +{ + readonly #id: bigint; + readonly #value: boolean; + readonly #celValue: Value; + readonly #adapter: TypeAdapter; + + constructor( + id: bigint, + value: boolean, + celValue: Value, + adapter: TypeAdapter + ) { + this.#id = id; + this.#value = value; + this.#celValue = celValue; + this.#adapter = adapter; + } + + id(): bigint { + return this.#id; + } + + /** + * Cost returns zero for constant field qualifiers + */ + cost(): Cost { + return Cost.None; + } + + value(): Value { + return this.#celValue; + } + + qualifierValueEquals(value: any): boolean { + if (isMessage(ValueSchema, value)) { + return equalBoolValue(this.#celValue, value).kind.value as boolean; + } + if (isBoolean(value)) { + return this.#value === value; + } + return false; + } + + qualify(vars: Activation, obj: any) { + const valString = this.#value.toString(); + if (obj instanceof Map) { + const found = obj.get(valString); + if (isNil(found)) { + if (obj.has(valString)) { + return NULL_VALUE; + } + throw noSuchKeyException(valString); + } + } else if (obj instanceof Object) { + if (valString in obj) { + if (isNil(obj[valString])) { + return NULL_VALUE; + } + return obj[valString]; + } + throw noSuchKeyException(valString); + } else if (isUnknownValue(obj)) { + return obj; + } + return refResolve(this.#adapter, this.#celValue, obj); + } + + toString() { + return `BoolQualifier{id=${this.#id}, value=${this.#value}}`; + } +} + +/** + * Not actually a qualifier, but conformance-tests require this, although it's + * actually an error condition. + */ +export class NullQualifier + implements Coster, ConstantQualifierEquator, QualifierValueEquator +{ + readonly #id: bigint; + readonly #celValue: Value; + readonly #adapter: TypeAdapter; + + constructor(id: bigint, celValue: Value, adapter: TypeAdapter) { + this.#id = id; + this.#celValue = celValue; + this.#adapter = adapter; + } + + id(): bigint { + return this.#id; + } + + /** + * Cost returns zero for constant field qualifiers + */ + cost(): Cost { + return Cost.None; + } + + value(): Value { + return this.#celValue; + } + + qualifierValueEquals(value: any): boolean { + return ( + value === null || value === NullValue.NULL_VALUE || isNullValue(value) + ); + } + + qualify(vars: Activation, obj: any) { + return null as any; + } + + toString() { + return `NullQualifier{id=${this.#id}}`; + } +} + +/** + * FieldQualifier indicates that the qualification is a well-defined field with + * a known field type. When the field type is known this can be used to improve + * the speed and efficiency of field resolution. + */ +export class FieldQualifier implements Coster, ConstantQualifierEquator { + readonly #id: bigint; + readonly #name: string; + readonly #fieldType: FieldType; + readonly #adapter: TypeAdapter; + + constructor( + id: bigint, + name: string, + fieldType: FieldType, + adapter: TypeAdapter + ) { + this.#id = id; + this.#name = name; + this.#fieldType = fieldType; + this.#adapter = adapter; + } + + id(): bigint { + return this.#id; + } + + /** + * Cost returns zero for constant field qualifiers + */ + cost(): Cost { + return Cost.None; + } + + value(): Value { + return stringValue(this.#name); + } + + qualifierValueEquals(value: any): boolean { + if (isMessage(ValueSchema, value)) { + return equalStringValue(this.value(), value).kind.value as boolean; + } + if (isString(value)) { + return this.#name === value; + } + return false; + } + + qualify(vars: Activation, obj: any) { + const valString = this.#name; + if (obj instanceof Map) { + const found = obj.get(valString); + if (isNil(found)) { + if (obj.has(valString)) { + return NULL_VALUE; + } + throw noSuchKeyException(valString); + } + } else if (obj instanceof Object) { + if (valString in obj) { + if (isNil(obj[valString])) { + return NULL_VALUE; + } + return obj[valString]; + } + throw noSuchKeyException(valString); + } else if (isUnknownValue(obj)) { + return obj; + } + return refResolve(this.#adapter, this.value(), obj); + } + + toString() { + return `FieldQualifier{id=${this.#id}, value=${this.#name}}`; + } +} + function noSuchAttributeException(context: string) { return new Error(`undeclared reference to '${context}' (in container '')`); } + +function noSuchKeyException(key: string) { + return new Error(`no such key: ${key}`); +} + +function indexOutOfBoundsException(index: number) { + return new Error(`index out of bounds: ${index}`); +} + +/** + * refResolve attempts to convert the value to a CEL value and then uses + * reflection methods to try and resolve the qualifier. + */ +function refResolve(adapter: TypeAdapter, idx: Value, obj: any) { + const celVal = adapter.nativeToValue(obj); + if (isFunction((celVal as any).find)) { + const elem = (celVal as any).find(idx); + if (isNil(elem)) { + return new Error(`no such key: ${idx}`); + } + return elem as Value; + } + if (celVal instanceof Error || isUnknownValue(celVal)) { + return celVal; + } + return new Error('no such overload'); +} diff --git a/packages/cel/src/lib/interpreter/interpretable.ts b/packages/cel/src/lib/interpreter/interpretable.ts index 5e68bd5..c3ce19f 100644 --- a/packages/cel/src/lib/interpreter/interpretable.ts +++ b/packages/cel/src/lib/interpreter/interpretable.ts @@ -1,18 +1,483 @@ -import { ExprValue } from '@buf/google_cel-spec.bufbuild_es/cel/expr/eval_pb.js'; +/* eslint-disable @typescript-eslint/no-explicit-any */ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +/* eslint-disable no-case-declarations */ +import { isFunction, isNil, isObject } from '@bearclaw/is'; import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { TypeAdapter } from '../common/ref/adapter'; +import { FieldType } from '../common/ref/field-type'; +import { boolValue } from '../common/types/bool'; +import { equalValue } from '../common/types/traits/equaler'; +import { receiver } from '../common/types/traits/receiver'; +import { Trait } from '../common/types/traits/trait'; +import { isZeroValue } from '../common/types/traits/zeroer'; +import { isUnknownValue } from '../common/types/unknown'; +import { valueHasTrait } from '../common/types/value'; +import { LOGICAL_OR_OPERATOR } from '../operators'; import { Activation } from './activation'; +import { Attribute, Qualifier } from './attribute-factory'; +import { Cost, Coster } from './coster'; +import { FunctionOp, UnaryOp } from './overload'; export interface Interpretable { // ID value corresponding to the expression node. - id: bigint; + id(): bigint; // Eval an Activation to produce an output. - eval: (ctx: Activation) => ExprValue; + eval: (ctx: Activation) => Value | Error; } -// InterpretableConst interface for tracking whether the Interpretable is a -// constant value. +function isInterpretable(val: any): val is Interpretable { + return isObject(val) && isFunction(val['id']) && isFunction(val['eval']); +} + +/** + * InterpretableConst interface for tracking whether the Interpretable is a + * constant value. + */ export interface InterpretableConst extends Interpretable { - // Value returns the constant value of the instruction. - value: Value; + /** + * Value returns the constant value of the instruction. + */ + value(): Value; +} + +function isInterpretableConst(val: any): val is InterpretableConst { + return isFunction(val['value']) && isInterpretable(val); +} + +/** + * InterpretableAttribute interface for tracking whether the Interpretable is + * an attribute. + */ +export interface InterpretableAttribute + extends Interpretable, + Qualifier, + Attribute { + /** + * Attr returns the Attribute value. + */ + attr(): Attribute; + + /** + * Adapter returns the type adapter to be used for adapting resolved + * Attribute values. + */ + adapter(): TypeAdapter; +} + +function isInterpretableAttribute(val: any): val is InterpretableAttribute { + return ( + isFunction(val['attr']) && + isFunction(val['adapter']) && + isInterpretable(val) + ); +} + +/** + * InterpretableCall interface for inspecting Interpretable instructions + * related to function calls. + */ +export interface InterpretableCall extends Interpretable { + /** + * Function returns the function name as it appears in text or mangled + * operator name as it appears in the operators.go file. + */ + function(): string; + + /** + * OverloadID returns the overload id associated with the function + * specialization. Overload ids are stable across language boundaries and can + * be treated as synonymous with a unique function signature. + */ + overloadID(): string; + + /** + * Args returns the normalized arguments to the function overload. For + * receiver-style functions, the receiver target is arg 0. + */ + args(): Interpretable[]; +} + +function isInterpretableCall(val: any) { + return ( + isFunction(val['function']) && + isFunction(val['overloadID']) && + isFunction(val['args']) && + isInterpretable(val) + ); +} + +// Core Interpretable implementations used during the program planning phase. + +export class EvalTestOnly implements Interpretable, Coster { + readonly #id: bigint; + readonly #op: Interpretable; + readonly #field: Value; // string + readonly #fieldType: FieldType; + + constructor( + id: bigint, + op: Interpretable, + field: Value, + fieldType: FieldType + ) { + this.#id = id; + this.#op = op; + this.#field = field; + this.#fieldType = fieldType; + } + + id() { + return this.#id; + } + + cost() { + const c = Cost.estimateCost(this.#op); + return c.add(Cost.OneOne); + } + + eval(ctx: Activation) { + // Handle field selection on a proto in the most efficient way possible. + if (!isNil(this.#fieldType)) { + if (isInterpretableAttribute(this.#op)) { + const opVal = this.#op.resolve(ctx); + if (opVal instanceof Error) { + return opVal; + } + if (this.#fieldType.isSet(opVal)) { + return boolValue(true); + } + return boolValue(false); + } + } + const obj = this.#op.eval(ctx); + if (obj instanceof Error) { + return obj; + } + switch (obj.kind.case) { + case 'listValue': + return boolValue( + obj.kind.value.values.some((v) => equalValue(v, this.#field)) + ); + case 'mapValue': + return boolValue( + obj.kind.value.entries.some( + (f) => equalValue(f.key!, this.#field) && !isZeroValue(f.value) + ) + ); + default: + return new Error('invalid type for field selection'); + } + } +} + +export class EvalConst implements InterpretableConst, Coster { + readonly #id: bigint; + readonly #val: Value; + + constructor(id: bigint, val: Value) { + this.#id = id; + this.#val = val; + } + + id() { + return this.#id; + } + + cost() { + return Cost.None; + } + + eval() { + return this.#val; + } + + value() { + return this.#val; + } +} + +export class EvalOr implements Interpretable, Coster { + readonly #id: bigint; + readonly #left: Interpretable; + readonly #right: Interpretable; + + constructor(id: bigint, left: Interpretable, right: Interpretable) { + this.#id = id; + this.#left = left; + this.#right = right; + } + + id() { + return this.#id; + } + + cost() { + const l = Cost.estimateCost(this.#left); + const r = Cost.estimateCost(this.#right); + return new Cost(l.min, l.max + r.max + 1); + } + + eval(ctx: Activation) { + // Short-circuit lhs. + const l = this.#left.eval(ctx); + if (l instanceof Error) { + return l; + } + if (l.kind.value === true) { + return l; + } + // Short-circuit rhs. + const r = this.#right.eval(ctx); + if (r instanceof Error) { + return r; + } + if (r.kind.value === true) { + return r; + } + // Return false if both sides are false. + if (l.kind.value === false && r.kind.value === false) { + return boolValue(false); + } + // Check for unknown values + if (isUnknownValue(l)) { + return l; + } + if (isUnknownValue(r)) { + return r; + } + return new Error(`no such overload for '${LOGICAL_OR_OPERATOR}`); + } +} + +export class EvalAnd implements Interpretable, Coster { + readonly #id: bigint; + readonly #left: Interpretable; + readonly #right: Interpretable; + + constructor(id: bigint, left: Interpretable, right: Interpretable) { + this.#id = id; + this.#left = left; + this.#right = right; + } + + id() { + return this.#id; + } + + cost() { + const l = Cost.estimateCost(this.#left); + const r = Cost.estimateCost(this.#right); + return new Cost(l.min, l.max + r.max + 1); + } + + eval(ctx: Activation) { + // Short-circuit lhs. + const l = this.#left.eval(ctx); + if (l instanceof Error) { + return l; + } + if (l.kind.value === false) { + return l; + } + // Short-circuit rhs. + const r = this.#right.eval(ctx); + if (r instanceof Error) { + return r; + } + if (r.kind.value === false) { + return r; + } + // Return true if both sides are true. + if (l.kind.value === true && r.kind.value === true) { + return boolValue(true); + } + // Check for unknown values + if (isUnknownValue(l)) { + return l; + } + if (isUnknownValue(r)) { + return r; + } + return new Error(`no such overload for '${LOGICAL_OR_OPERATOR}`); + } +} + +export class EvalEq implements Interpretable, Coster { + readonly #id: bigint; + readonly #left: Interpretable; + readonly #right: Interpretable; + + constructor(id: bigint, left: Interpretable, right: Interpretable) { + this.#id = id; + this.#left = left; + this.#right = right; + } + + id() { + return this.#id; + } + + cost() { + const l = Cost.estimateCost(this.#left); + const r = Cost.estimateCost(this.#right); + return Cost.OneOne.add(l).add(r); + } + + eval(ctx: Activation) { + const l = this.#left.eval(ctx); + if (l instanceof Error) { + return l; + } + const r = this.#right.eval(ctx); + if (r instanceof Error) { + return r; + } + return equalValue(l, r); + } +} + +export class EvalNe implements Interpretable, Coster { + readonly #id: bigint; + readonly #left: Interpretable; + readonly #right: Interpretable; + + constructor(id: bigint, left: Interpretable, right: Interpretable) { + this.#id = id; + this.#left = left; + this.#right = right; + } + + id() { + return this.#id; + } + + cost() { + const l = Cost.estimateCost(this.#left); + const r = Cost.estimateCost(this.#right); + return Cost.OneOne.add(l).add(r); + } + + eval(ctx: Activation) { + const l = this.#left.eval(ctx); + if (l instanceof Error) { + return l; + } + const r = this.#right.eval(ctx); + if (r instanceof Error) { + return r; + } + const isEqual = equalValue(l, r); + if (isEqual instanceof Error) { + return isEqual; + } + return boolValue(!isEqual.kind.value); + } +} + +export class EvalZeroArity implements InterpretableCall, Coster { + readonly #id: bigint; + readonly #fn: string; + readonly #overloadID: string; + readonly #impl: FunctionOp; + + constructor(id: bigint, fn: string, overloadID: string, impl: FunctionOp) { + this.#id = id; + this.#fn = fn; + this.#overloadID = overloadID; + this.#impl = impl; + } + + id() { + return this.#id; + } + + cost() { + return Cost.OneOne; + } + + eval() { + return this.#impl(); + } + + function() { + return this.#fn; + } + + overloadID() { + return this.#overloadID; + } + + args() { + return []; + } +} + +export class EvalUnary implements InterpretableCall, Coster { + readonly #id: bigint; + readonly #fn: string; + readonly #overloadID: string; + readonly #arg: Interpretable; + readonly #trait: Trait; + readonly #impl: UnaryOp; + + constructor( + id: bigint, + fn: string, + overloadID: string, + arg: Interpretable, + trait: Trait, + impl: FunctionOp + ) { + this.#id = id; + this.#fn = fn; + this.#overloadID = overloadID; + this.#arg = arg; + this.#trait = trait; + this.#impl = impl; + } + + id() { + return this.#id; + } + + cost() { + return Cost.OneOne.add(Cost.estimateCost(this.#arg)); + } + + eval(ctx: Activation) { + const arg = this.#arg.eval(ctx); + if (arg instanceof Error) { + return arg; + } + if (isUnknownValue(arg)) { + return arg; + } + // If the implementation is bound and the argument value has the right + // traits required to invoke it, then call the implementation. + if ( + !isNil(this.#impl) && + (isNil(this.#trait) || valueHasTrait(arg, this.#trait)) + ) { + return this.#impl(arg); + } + // Otherwise, if the argument is a ReceiverType attempt to invoke the + // receiver method on the operand (arg0). + if (valueHasTrait(arg, Trait.RECEIVER_TYPE)) { + return receiver(arg, this.#fn, this.#overloadID); + } + return new Error(`no such overload for '${this.#fn}'`); + } + + function() { + return this.#fn; + } + + overloadID() { + return this.#overloadID; + } + + args() { + return [this.#arg]; + } } diff --git a/packages/cel/src/lib/interpreter/overload.ts b/packages/cel/src/lib/interpreter/overload.ts index e704140..29ce26a 100644 --- a/packages/cel/src/lib/interpreter/overload.ts +++ b/packages/cel/src/lib/interpreter/overload.ts @@ -15,7 +15,7 @@ export type BinaryOp = (left: Value, right: Value) => Value; * A function which accepts zero or more arguments and produces a value or * error as a result */ -export type FunctionOp = (values: Value[]) => Value; +export type FunctionOp = (...values: Value[]) => Value; /** * Defines a named overload of a function, indicating an operand trait From 8b664f4a8435deabaa1206b5fcd3be136b33619a Mon Sep 17 00:00:00 2001 From: jafaircl Date: Tue, 5 Nov 2024 08:28:47 -0500 Subject: [PATCH 31/34] feat(cel): bring checker environment in line with other implementations --- packages/cel/src/lib/checker/checker.spec.ts | 235 ++++++++------ packages/cel/src/lib/checker/checker.ts | 86 ++--- packages/cel/src/lib/checker/env.spec.ts | 36 +++ packages/cel/src/lib/checker/env.ts | 303 ++++++++++++++++++ packages/cel/src/lib/checker/scopes.ts | 188 +++++++++++ .../cel/src/lib/common/decls/function-decl.ts | 12 + .../src/lib/common/pb/proto-type-registry.ts | 74 +++-- packages/cel/src/lib/common/standard.ts | 2 +- packages/cel/src/lib/common/types/enum.ts | 36 +++ packages/cel/src/lib/environment.ts | 4 +- 10 files changed, 802 insertions(+), 174 deletions(-) create mode 100644 packages/cel/src/lib/checker/env.spec.ts create mode 100644 packages/cel/src/lib/checker/env.ts create mode 100644 packages/cel/src/lib/checker/scopes.ts create mode 100644 packages/cel/src/lib/common/types/enum.ts diff --git a/packages/cel/src/lib/checker/checker.spec.ts b/packages/cel/src/lib/checker/checker.spec.ts index 96b19d2..0dc159c 100644 --- a/packages/cel/src/lib/checker/checker.spec.ts +++ b/packages/cel/src/lib/checker/checker.spec.ts @@ -9,11 +9,20 @@ import { TestAllTypes_NestedEnumSchema as TestAllTypes_NestedEnumSchemaProto3, TestAllTypes_NestedMessageSchema as TestAllTypes_NestedMessageSchemaProto3, } from '@buf/cel_spec.bufbuild_es/proto/test/v1/proto3/test_all_types_pb.js'; -import { Type } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { + Decl, + Type, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; import { createMutableRegistry } from '@bufbuild/protobuf'; import { CELContainer } from '../common/container'; import { functionDecl, overloadDecl } from '../common/decls/function-decl'; import { identDecl } from '../common/decls/ident-decl'; +import { ProtoTypeRegistry } from '../common/pb/proto-type-registry'; +import { + STANDARD_DESCRIPTORS, + STANDARD_FUNCTION_DECLARATIONS, + STANDARD_IDENT_DECLARATIONS, +} from '../common/standard'; import { abstractType } from '../common/types/abstract'; import { BOOL_TYPE } from '../common/types/bool'; import { BYTES_TYPE } from '../common/types/bytes'; @@ -30,9 +39,9 @@ import { ABSTRACT_OPTIONAL_TYPE, optionalType } from '../common/types/optional'; import { STRING_TYPE } from '../common/types/string'; import { typeParamType } from '../common/types/type-param'; import { UINT64_TYPE } from '../common/types/uint'; -import { CELEnvironment, STANDARD_ENV } from '../environment'; import { CELParser, CELParserOptions } from '../parser/parser'; import { CELChecker } from './checker'; +import { CheckerEnv } from './env'; interface TestInfo { // in contains the expression to be parsed. @@ -48,7 +57,7 @@ interface TestInfo { container?: string; // env is the environment to use for testing. - env?: CELEnvironment; + env?: CheckerEnv; // err is the expected error for negative test cases. err?: string; @@ -62,45 +71,71 @@ interface TestInfo { } function getDefaultEnv() { - return STANDARD_ENV().extend({ - registry: createMutableRegistry( - TestAllTypesSchemaProto3, - TestAllTypes_NestedMessageSchemaProto3, - TestAllTypes_NestedEnumSchemaProto3, - TestAllTypesSchemaProto2, - TestAllTypes_NestedMessageSchemaProto2, - TestAllTypes_NestedEnumSchemaProto2 - ), - idents: [ - identDecl('is', { type: STRING_TYPE }), - identDecl('ii', { type: INT64_TYPE }), - identDecl('iu', { type: UINT64_TYPE }), - identDecl('iz', { type: BOOL_TYPE }), - identDecl('ib', { type: BYTES_TYPE }), - identDecl('id', { type: DOUBLE_TYPE }), - identDecl('ix', { type: NULL_TYPE }), - ], - functions: [ - functionDecl('fg_s', { - overloads: [ - { - overloadId: 'fg_s_0', - resultType: STRING_TYPE, - }, - ], - }), - functionDecl('fi_s_s', { - overloads: [ - { - overloadId: 'fi_s_s_0', - params: [STRING_TYPE], - resultType: STRING_TYPE, - isInstanceFunction: true, - }, - ], - }), - ], - }); + const container = new CELContainer(); + const registry = createMutableRegistry( + ...STANDARD_DESCRIPTORS, + TestAllTypesSchemaProto3, + TestAllTypes_NestedMessageSchemaProto3, + TestAllTypes_NestedEnumSchemaProto3, + TestAllTypesSchemaProto2, + TestAllTypes_NestedMessageSchemaProto2, + TestAllTypes_NestedEnumSchemaProto2 + ); + const provider = new ProtoTypeRegistry(undefined, registry); + const env = new CheckerEnv(container, provider); + env.addIdents( + ...STANDARD_IDENT_DECLARATIONS, + identDecl('is', { type: STRING_TYPE }), + identDecl('ii', { type: INT64_TYPE }), + identDecl('iu', { type: UINT64_TYPE }), + identDecl('iz', { type: BOOL_TYPE }), + identDecl('ib', { type: BYTES_TYPE }), + identDecl('id', { type: DOUBLE_TYPE }), + identDecl('ix', { type: NULL_TYPE }) + ); + env.addFunctions( + ...STANDARD_FUNCTION_DECLARATIONS, + functionDecl('fg_s', { + overloads: [ + { + overloadId: 'fg_s_0', + resultType: STRING_TYPE, + }, + ], + }), + functionDecl('fi_s_s', { + overloads: [ + { + overloadId: 'fi_s_s_0', + params: [STRING_TYPE], + resultType: STRING_TYPE, + isInstanceFunction: true, + }, + ], + }) + ); + return env; +} + +function extendEnv( + env: CheckerEnv, + options: { container?: CELContainer; idents?: Decl[]; functions?: Decl[] } +) { + const container = options.container ?? env.container; + const idents = options.idents ?? []; + const functions = options.functions ?? []; + const provider = env.provider; + const newEnv = new CheckerEnv(container, provider); + for (const ident of [...idents, ...env.declarations.scopes.idents.values()]) { + newEnv.addIdent(ident); + } + for (const fn of [ + ...functions, + ...env.declarations.scopes.functions.values(), + ]) { + newEnv.setFunction(fn); + } + return newEnv; } const testCases: TestInfo[] = [ @@ -109,7 +144,7 @@ const testCases: TestInfo[] = [ in: `a.b`, out: `a.b~bool`, outType: STRING_TYPE, - env: new CELEnvironment({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('a', { type: mapType({ @@ -311,7 +346,7 @@ _+_( single_int64 : 2~int }~google.api.expr.test.v1.proto3.TestAllTypes^google.api.expr.test.v1.proto3.TestAllTypes`, outType: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { container: new CELContainer('google.api.expr.test.v1.proto3'), }), }, @@ -322,7 +357,7 @@ _+_( ERROR: :1:26: expected type of field 'single_int32' is 'int' but provided type is 'uint' | TestAllTypes{single_int32: 1u} | .........................^`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { container: new CELContainer('google.api.expr.test.v1.proto3'), }), }, @@ -333,7 +368,7 @@ ERROR: :1:26: expected type of field 'single_int32' is 'int' but provided ERROR: :1:40: undefined field 'undefined' | TestAllTypes{single_int32: 1, undefined: 2} | .......................................^`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { container: new CELContainer('google.api.expr.test.v1.proto3'), }), }, @@ -342,7 +377,7 @@ ERROR: :1:40: undefined field 'undefined' out: ` _==_(size(x~list(int)^x)~int^size_list, x~list(int)^x.size()~int^list_size) ~bool^equals`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [identDecl('x', { type: listType({ elemType: INT64_TYPE }) })], }), outType: BOOL_TYPE, @@ -435,7 +470,7 @@ _!=_(_-_(_+_(1~double, _*_(2~double, 3~double)~double^multiply_double) }, { in: `x.single_int32 != null`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: messageType('google.api.expr.test.v1.proto3.Proto2Message'), @@ -450,7 +485,7 @@ ERROR: :1:2: unexpected failed resolution of 'google.api.expr.test.v1.pro }, { in: `x.single_value + 1 / x.single_struct.y == 23`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), @@ -471,7 +506,7 @@ ERROR: :1:2: unexpected failed resolution of 'google.api.expr.test.v1.pro }, { in: `x.single_value[23] + x.single_struct['y']`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), @@ -494,7 +529,7 @@ ERROR: :1:2: unexpected failed resolution of 'google.api.expr.test.v1.pro { in: `TestAllTypes.NestedEnum.BAR != 99`, container: 'google.api.expr.test.v1.proto3', - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { container: new CELContainer('google.api.expr.test.v1.proto3'), }), out: `_!=_(google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum.BAR @@ -552,7 +587,7 @@ ERROR: :1:2: unexpected failed resolution of 'google.api.expr.test.v1.pro )~bool^equals )~bool^logical_and )~bool^logical_and`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: messageType('google.protobuf.Struct') }), identDecl('y', { type: messageType('google.protobuf.ListValue') }), @@ -563,7 +598,7 @@ ERROR: :1:2: unexpected failed resolution of 'google.api.expr.test.v1.pro }, { in: `x + y`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: listType({ @@ -583,7 +618,7 @@ ERROR: :1:2: unexpected failed resolution of 'google.api.expr.test.v1.pro }, { in: `x[1u]`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: listType({ @@ -602,7 +637,7 @@ ERROR: :1:2: found no matching overload for '_[_]' applied to '(list(goog }, { in: `(x + x)[1].single_int32 == size(x)`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: listType({ @@ -629,7 +664,7 @@ ERROR: :1:2: found no matching overload for '_[_]' applied to '(list(goog }, { in: `x.repeated_int64[x.single_int32] == 23`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), @@ -646,7 +681,7 @@ ERROR: :1:2: found no matching overload for '_[_]' applied to '(list(goog }, { in: `size(x.map_int64_nested_type) == 0`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), @@ -664,7 +699,7 @@ ERROR: :1:2: found no matching overload for '_[_]' applied to '(list(goog }, { in: `x.all(y, y == true)`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [identDecl('x', { type: BOOL_TYPE })], }), out: ` @@ -698,7 +733,7 @@ ERROR: :1:2: found no matching overload for '_[_]' applied to '(list(goog }, { in: `x.repeated_int64.map(x, double(x))`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), @@ -733,7 +768,7 @@ ERROR: :1:2: found no matching overload for '_[_]' applied to '(list(goog }, { in: `x[2].single_int32 == 23`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: mapType({ @@ -753,7 +788,7 @@ ERROR: :1:2: found no matching overload for '_[_]' applied to '(list(goog }, { in: `x["a"].single_int32 == 23`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: mapType({ @@ -777,7 +812,7 @@ ERROR: :1:2: found no matching overload for '_[_]' applied to '(list(goog }, { in: `x.single_nested_message.bb == 43 && has(x.single_nested_message)`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), @@ -796,7 +831,7 @@ ERROR: :1:2: found no matching overload for '_[_]' applied to '(list(goog }, { in: `x.single_nested_message.undefined == x.undefined && has(x.single_int32) && has(x.repeated_int32)`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), @@ -813,7 +848,7 @@ ERROR: :1:39: undefined field 'undefined' }, { in: `x.single_nested_message != null`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), @@ -830,7 +865,7 @@ ERROR: :1:39: undefined field 'undefined' }, { in: `x.single_int64 != null`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), @@ -845,7 +880,7 @@ ERROR: :1:16: found no matching overload for '_!=_' applied to '(int, nul }, { in: `x.single_int64_wrapper == null`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), @@ -870,7 +905,7 @@ ERROR: :1:16: found no matching overload for '_!=_' applied to '(int, nul && x.single_string_wrapper == 'hi' && x.single_uint32_wrapper == 1u && x.single_uint64_wrapper != 42u`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), @@ -932,7 +967,7 @@ ERROR: :1:16: found no matching overload for '_!=_' applied to '(int, nul { in: `x.single_timestamp == google.protobuf.Timestamp{seconds: 20} && x.single_duration < google.protobuf.Duration{seconds: 10}`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), @@ -952,7 +987,7 @@ ERROR: :1:16: found no matching overload for '_!=_' applied to '(int, nul && x.single_string_wrapper == google.protobuf.Value{string_value: 'hi'} && x.single_uint32_wrapper == google.protobuf.UInt32Value{value: 1u} && x.single_uint64_wrapper != google.protobuf.UInt64Value{value: 42u}`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), @@ -963,7 +998,7 @@ ERROR: :1:16: found no matching overload for '_!=_' applied to '(int, nul }, { in: `x.repeated_int64.exists(y, y > 10) && y < 5`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), @@ -976,7 +1011,7 @@ ERROR: :1:16: found no matching overload for '_!=_' applied to '(int, nul }, { in: `x.repeated_int64.all(e, e > 0) && x.repeated_int64.exists(e, e < 0) && x.repeated_int64.exists_one(e, e == 0)`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), @@ -1067,7 +1102,7 @@ ERROR: :1:16: found no matching overload for '_!=_' applied to '(int, nul }, { in: `x.all(e, 0)`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), @@ -1122,7 +1157,7 @@ ERROR: :1:1: found no matching overload for '_&&_' applied to '(bool, int // Result __result__~list(dyn)^__result__)~list(dyn)`, outType: listType({ elemType: DYN_TYPE }), - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [identDecl('lists', { type: DYN_TYPE })], }), }, @@ -1161,7 +1196,7 @@ ERROR: :1:5: undeclared reference to 'x' (in container '') // || x == google.api.expr.test.v1.proto3.TestAllTypes{} // || y < x // || x >= x`, - // env: getDefaultEnv().extend({ + // env: extendEnv(getDefaultEnv(), { // idents: [ // identDecl('x', { type: ANY_TYPE }), // identDecl('y', { type: nullableType(INT64_TYPE) }), @@ -1208,7 +1243,7 @@ ERROR: :1:5: undeclared reference to 'x' (in container '') // || x == google.api.expr.test.v1.proto3.TestAllTypes{} // || y < x // || x >= x`, - // env: getDefaultEnv().extend({ + // env: extendEnv(getDefaultEnv(), { // idents: [ // identDecl('x', { type: ANY_TYPE }), // identDecl('y', { type: nullableType(INT64_TYPE) }), @@ -1248,7 +1283,7 @@ ERROR: :1:5: undeclared reference to 'x' (in container '') // { // in: `x`, // container: 'container', - // env: getDefaultEnv().extend({ + // env: extendEnv(getDefaultEnv(), { // idents: [ // identDecl('container.x', { // type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), @@ -1273,7 +1308,7 @@ _==_(map~type(map(dyn, dyn))^map, }, { in: `size(x) > 4`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), @@ -1297,7 +1332,7 @@ _==_(map~type(map(dyn, dyn))^map, }, { in: `x.single_int64_wrapper + 1 != 23`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), @@ -1316,7 +1351,7 @@ _!=_(_+_(x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_int64_wrapper }, { in: `x.single_int64_wrapper + y != 23`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('x', { type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), @@ -1490,7 +1525,7 @@ _!=_( )~list(dyn)^conditional, // Result __result__~list(dyn)^__result__)~list(dyn)`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('args', { type: mapType({ keyType: STRING_TYPE, valueType: DYN_TYPE }), @@ -1511,7 +1546,7 @@ _!=_( 0~int )~dyn^index_list|index_map )~bool^equals`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [identDecl('a', { type: typeParamType('T') })], }), outType: BOOL_TYPE, @@ -1523,7 +1558,7 @@ _!=_( && !has(pb3.single_int64) && !has(pb3.repeated_int32) && !has(pb3.map_string_string)`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('pb2', { type: messageType('google.api.expr.test.v1.proto2.TestAllTypes'), @@ -1592,7 +1627,7 @@ google.api.expr.test.v1.proto2.TestAllTypes.repeated_nested_message }, { in: `base64.encode('hello')`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { functions: [ functionDecl('base64.encode', { overloads: [ @@ -1615,7 +1650,7 @@ google.api.expr.test.v1.proto2.TestAllTypes.repeated_nested_message // { // in: `encode('hello')`, // container: `base64`, - // env: getDefaultEnv().extend({ + // env: extendEnv(getDefaultEnv(), { // functions: [ // functionDecl('base64.encode', { // overloads: [ @@ -1649,7 +1684,7 @@ set( 3~int ]~list(int) )~set(int)^set_list`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { functions: [ functionDecl('set', { overloads: [ @@ -1674,7 +1709,7 @@ set( set([1~int, 2~int]~list(int))~set(int)^set_list, set([2~int, 1~int]~list(int))~set(int)^set_list )~bool^equals`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { functions: [ functionDecl('set', { overloads: [ @@ -1699,7 +1734,7 @@ _==_( set([1~int, 2~int]~list(int))~set(int)^set_list, x~set(int)^x )~bool^equals`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { functions: [ functionDecl('set', { overloads: [ @@ -2041,7 +2076,7 @@ _==_( { in: `values.filter(i, i.content != "").map(i, i.content)`, outType: listType({ elemType: STRING_TYPE }), - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('values', { type: listType({ @@ -2159,7 +2194,7 @@ _==_( // TODO: nestedgroup does not exist on TestAllTypes. Revisit when we switch to the buf-managed proto // { // in: 'type(testAllTypes.nestedgroup.nested_id) == int', - // env: getDefaultEnv().extend({ + // env: extendEnv(getDefaultEnv(), { // idents: [ // identDecl('testAllTypes', { // type: messageType('google.api.expr.test.v1.proto3.TestAllTypes'), @@ -2177,7 +2212,7 @@ _==_( // TODO: Optionals { in: `a.?b`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('a', { type: mapType({ @@ -2196,7 +2231,7 @@ _==_( }, { in: `type(a.?b) == optional_type`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('optional_type', { type: ABSTRACT_OPTIONAL_TYPE }), identDecl('a', { @@ -2221,7 +2256,7 @@ _==_( }, { in: `a.b`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('a', { type: optionalType( @@ -2238,7 +2273,7 @@ _==_( }, { in: `a.dynamic`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('a', { type: optionalType(DYN_TYPE), @@ -2250,7 +2285,7 @@ _==_( }, { in: `has(a.dynamic)`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('a', { type: optionalType(DYN_TYPE), @@ -2262,7 +2297,7 @@ _==_( }, { in: `has(a.?b.c)`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('a', { type: optionalType( @@ -2315,7 +2350,7 @@ _==_( { in: `{?'nested': a.b}`, parserOptions: { enableOptionalSyntax: true }, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('a', { type: optionalType( @@ -2348,7 +2383,7 @@ _==_( // { // in: `[?a, ?b, 'world']`, // parserOptions: { enableOptionalSyntax: true }, - // env: getDefaultEnv().extend({ + // env: extendEnv(getDefaultEnv(), { // idents: [ // identDecl('a', { // type: optionalType(STRING_TYPE), @@ -2408,7 +2443,7 @@ _==_( }, { in: `null_int == null || null == null_int || null_msg == null || null == null_msg`, - env: getDefaultEnv().extend({ + env: extendEnv(getDefaultEnv(), { idents: [ identDecl('null_int', { type: nullableType(INT64_TYPE) }), identDecl('null_msg', { @@ -2423,7 +2458,7 @@ _==_( // TODO: nullables // { // in: `NotAMessage{}`, - // env: getDefaultEnv().extend({ + // env: extendEnv(getDefaultEnv(), { // idents: [identDecl('NotAMessage', { type: nullableType(INT64_TYPE) })], // }), // err: `ERROR: :1:12: 'wrapper(int)' is not a type @@ -2467,7 +2502,7 @@ describe('CELChecker', () => { for (const testCase of testCases) { it(`should check ${testCase.in}`, () => { const container = new CELContainer(testCase.container ?? ''); - const env = testCase.env ?? getDefaultEnv().extend({ container }); + const env = testCase.env ?? extendEnv(getDefaultEnv(), { container }); const parser = new CELParser(testCase.in, testCase.parserOptions); const parsed = parser.parse(); if (isNil(parsed.expr)) { diff --git a/packages/cel/src/lib/checker/checker.ts b/packages/cel/src/lib/checker/checker.ts index f2f5924..25e9055 100644 --- a/packages/cel/src/lib/checker/checker.ts +++ b/packages/cel/src/lib/checker/checker.ts @@ -58,8 +58,8 @@ import { wellKnownType, } from '../common/types/wkt'; import { mapToObject, toQualifiedName } from '../common/utils'; -import { CELEnvironment } from '../environment'; import { OPT_SELECT_OPERATOR } from '../operators'; +import { CheckerEnv } from './env'; import { isAssignable, isAssignableList, @@ -83,7 +83,7 @@ export class CELChecker { constructor( public readonly parsed: ParsedExpr, public readonly source: string, - public env: CELEnvironment + public env: CheckerEnv ) { this.#errors = new Errors(source); } @@ -509,7 +509,7 @@ export class CELChecker { } // Ensure the type name is fully qualified in the AST. mapVal.messageName = decl.name; - const ident = decl.declKind.value as Decl_IdentDecl; + const ident = unwrapIdentDecl(decl)!; this.setReference(expr.id, identReference(decl.name, ident.value!)); const identKind = ident.type!.typeKind.case; if (identKind === 'type') { @@ -547,24 +547,14 @@ export class CELChecker { this.checkExpr(value); let fieldType: Type = ERROR_TYPE; - const t = this.env.lookupFieldType(mapVal.messageName, field); + const t = this._lookupFieldType( + expr.id, + entry.id, + mapVal.messageName, + field + ); if (!isNil(t)) { fieldType = t; - } else { - const msg = this.env.lookupStructType(mapVal.messageName); - if (isNil(msg)) { - this.#errors.reportUnexpectedFailedResolution( - expr.id, - this.getLocationById(expr.id), - mapVal.messageName - ); - } else { - this.#errors.reportUndefinedField( - entry.id, - this.getLocationById(entry.id), - field - ); - } } if (!this._isAssignable(fieldType, this.getType(value.id)!)) { this.#errors.reportFieldTypeMismatch( @@ -621,10 +611,10 @@ export class CELChecker { // Create a scope for the comprehension since it has a local accumulation // variable. This scope will contain the accumulation variable used to // compute the result. - this.env.enterScope(); + this.env = this.env.enterScope(); this.env.addIdent(identDecl(comp.accuVar, { type: accuType })); // Create a block scope for the loop. - this.env.enterScope(); + this.env = this.env.enterScope(); this.env.addIdent(identDecl(comp.iterVar, { type: varType })); // Check the variable references in the condition and step. this.checkExpr(comp.loopCondition); @@ -632,10 +622,10 @@ export class CELChecker { this.checkExpr(comp.loopStep); this._assertType(comp.loopStep!, accuType!); // Exit the loop's block scope before checking the result. - this.env.exitScope(); + this.env = this.env.exitScope(); this.checkExpr(comp.result); // Exit the comprehension scope. - this.env.exitScope(); + this.env = this.env.exitScope(); this.setType(expr.id, this.getType(comp.result!.id)!); return expr; } @@ -695,29 +685,16 @@ export class CELChecker { resultType = targetType.typeKind.value.valueType!; break; case 'messageType': - // Objects yield their field type declaration as the selection result type, but only if - // the field is defined. - const fieldType = this.env.lookupFieldType( + // Objects yield their field type declaration as the selection result + // type, but only if the field is defined. + const fieldType = this._lookupFieldType( + expr.id, + expr.id, targetType.typeKind.value, field ); if (!isNil(fieldType)) { resultType = fieldType; - } else { - const msg = this.env.lookupStructType(targetType.typeKind.value); - if (isNil(msg)) { - this.#errors.reportUnexpectedFailedResolution( - expr.id, - this.getLocationById(expr.id), - targetType.typeKind.value - ); - } else { - this.#errors.reportUndefinedField( - expr.id, - this.getLocationById(expr.id), - field - ); - } } break; case 'wellKnown': @@ -836,4 +813,31 @@ export class CELChecker { ); } } + + private _lookupFieldType( + messageId: bigint, + fieldId: bigint, + structType: string, + fieldName: string + ) { + const st = this.env.lookupIdent(structType); + if (isNil(st)) { + this.#errors.reportUnexpectedFailedResolution( + messageId, + this.getLocationById(messageId), + structType + ); + return null; + } + const ft = this.env.provider.findFieldType(structType, fieldName); + if (ft instanceof Error) { + this.#errors.reportUndefinedField( + fieldId, + this.getLocationById(fieldId), + fieldName + ); + return null; + } + return ft.type; + } } diff --git a/packages/cel/src/lib/checker/env.spec.ts b/packages/cel/src/lib/checker/env.spec.ts new file mode 100644 index 0000000..b216bbe --- /dev/null +++ b/packages/cel/src/lib/checker/env.spec.ts @@ -0,0 +1,36 @@ +import { CELContainer } from '../cel'; +import { identDecl } from '../common/decls/ident-decl'; +import { ProtoTypeRegistry } from '../common/pb/proto-type-registry'; +import { + STANDARD_FUNCTION_DECLARATIONS, + STANDARD_IDENT_DECLARATIONS, +} from '../common/standard'; +import { TYPE_TYPE } from '../common/types/type'; +import { CheckerEnv } from './env'; + +describe('CheckerEnv', () => { + it('overlapping identifier', () => { + const env = standardEnv(); + const errs = env.addIdents(identDecl('int', { type: TYPE_TYPE })); + expect(errs).not.toBeNull(); + expect(errs?.message).toContain('overlapping identifier'); + }); + + // TODO: fix this test + // it('overlapping function', () => { + // const env = standardEnv(); + // const errs = env.addFunctions(identDecl('int', { type: TYPE_TYPE })); + // console.log(errs); + // expect(errs).not.toBeNull(); + // expect(errs?.message).toContain('overlapping identifier'); + // }); +}); + +function standardEnv() { + const container = new CELContainer(); + const provider = new ProtoTypeRegistry(); + const env = new CheckerEnv(container, provider); + env.addIdents(...STANDARD_IDENT_DECLARATIONS); + env.addFunctions(...STANDARD_FUNCTION_DECLARATIONS); + return env; +} diff --git a/packages/cel/src/lib/checker/env.ts b/packages/cel/src/lib/checker/env.ts new file mode 100644 index 0000000..15d9576 --- /dev/null +++ b/packages/cel/src/lib/checker/env.ts @@ -0,0 +1,303 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +import { isNil } from '@bearclaw/is'; +import { Decl } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb'; +import { dequal } from 'dequal'; +import { CELContainer } from '../common/container'; +import { mergeFunctionDecls } from '../common/decls/function-decl'; +import { identDecl } from '../common/decls/ident-decl'; +import { TypeProvider } from '../common/ref/provider'; +import { DYN_TYPE } from '../common/types/dyn'; +import { INT64_TYPE } from '../common/types/int'; +import { mapType } from '../common/types/map'; +import { STRING_TYPE } from '../common/types/string'; +import { LESS_DOUBLE_INT64_OVERLOAD } from '../overloads'; +import { + GREATER_DOUBLE_INT64_OVERLOAD, + GREATER_DOUBLE_UINT64_OVERLOAD, + GREATER_EQUALS_DOUBLE_INT64_OVERLOAD, + GREATER_EQUALS_DOUBLE_UINT64_OVERLOAD, + GREATER_EQUALS_INT64_DOUBLE_OVERLOAD, + GREATER_EQUALS_INT64_UINT64_OVERLOAD, + GREATER_EQUALS_UINT64_DOUBLE_OVERLOAD, + GREATER_EQUALS_UINT64_INT64_OVERLOAD, + GREATER_INT64_DOUBLE_OVERLOAD, + GREATER_INT64_UINT64_OVERLOAD, + GREATER_UINT64_DOUBLE_OVERLOAD, + GREATER_UINT64_INT64_OVERLOAD, + LESS_DOUBLE_UINT64_OVERLOAD, + LESS_EQUALS_DOUBLE_INT64_OVERLOAD, + LESS_EQUALS_DOUBLE_UINT64_OVERLOAD, + LESS_EQUALS_INT64_DOUBLE_OVERLOAD, + LESS_EQUALS_INT64_UINT64_OVERLOAD, + LESS_EQUALS_UINT64_DOUBLE_OVERLOAD, + LESS_EQUALS_UINT64_INT64_OVERLOAD, + LESS_INT64_DOUBLE_OVERLOAD, + LESS_INT64_UINT64_OVERLOAD, + LESS_UINT64_DOUBLE_OVERLOAD, + LESS_UINT64_INT64_OVERLOAD, +} from './../overloads'; +import { Scopes } from './scopes'; + +export interface CheckerEnvOptions { + crossTypeNumericComparisons?: boolean; + homogeneousAggregateLiterals?: boolean; + validatedDeclarations?: Scopes; +} + +export const CROSS_TYPE_NUMERIC_COMPARISON_OVERLOADS = new Set([ + // double <-> int | uint + LESS_DOUBLE_INT64_OVERLOAD, + LESS_DOUBLE_UINT64_OVERLOAD, + LESS_EQUALS_DOUBLE_INT64_OVERLOAD, + LESS_EQUALS_DOUBLE_UINT64_OVERLOAD, + GREATER_DOUBLE_INT64_OVERLOAD, + GREATER_DOUBLE_UINT64_OVERLOAD, + GREATER_EQUALS_DOUBLE_INT64_OVERLOAD, + GREATER_EQUALS_DOUBLE_UINT64_OVERLOAD, + // int <-> double | uint + LESS_INT64_DOUBLE_OVERLOAD, + LESS_INT64_UINT64_OVERLOAD, + LESS_EQUALS_INT64_DOUBLE_OVERLOAD, + LESS_EQUALS_INT64_UINT64_OVERLOAD, + GREATER_INT64_DOUBLE_OVERLOAD, + GREATER_INT64_UINT64_OVERLOAD, + GREATER_EQUALS_INT64_DOUBLE_OVERLOAD, + GREATER_EQUALS_INT64_UINT64_OVERLOAD, + // uint <-> double | int + LESS_UINT64_DOUBLE_OVERLOAD, + LESS_UINT64_INT64_OVERLOAD, + LESS_EQUALS_UINT64_DOUBLE_OVERLOAD, + LESS_EQUALS_UINT64_INT64_OVERLOAD, + GREATER_UINT64_DOUBLE_OVERLOAD, + GREATER_UINT64_INT64_OVERLOAD, + GREATER_EQUALS_UINT64_DOUBLE_OVERLOAD, + GREATER_EQUALS_UINT64_INT64_OVERLOAD, +]); + +/** + * Env is the environment for type checking. + * + * The Env is comprised of a container, type provider, declarations, and other + * related objects which can be used to assist with type-checking. + */ +export class CheckerEnv { + readonly #container: CELContainer; + readonly #provider: TypeProvider; + readonly #declarations: Scopes; + readonly #aggLitElemType = DYN_TYPE; + readonly #filteredOverloadIDs = new Set(); + + constructor( + container: CELContainer, + provider: TypeProvider, + private readonly options?: CheckerEnvOptions + ) { + this.#container = container; + this.#provider = provider; + + this.#declarations = new Scopes(); + this.#declarations.push(); + + if (options?.homogeneousAggregateLiterals) { + // this.#aggLitElemType = DYN_TYPE; // TODO: what type should this be + } + this.#filteredOverloadIDs = CROSS_TYPE_NUMERIC_COMPARISON_OVERLOADS; + if (options?.crossTypeNumericComparisons) { + this.#filteredOverloadIDs = new Set(); + } + if (options?.validatedDeclarations) { + this.#declarations = options.validatedDeclarations; + } + } + + get aggLitElemType() { + return this.#aggLitElemType; + } + + get container() { + return this.#container; + } + + get provider() { + return this.#provider; + } + + get declarations() { + return this.#declarations; + } + + /** + * AddIdents configures the checker with a list of variable declarations. + */ + addIdents(...decls: Decl[]) { + const errs: Error[] = []; + for (const decl of decls) { + const err = this.addIdent(decl); + if (!isNil(err)) { + errs.push(err); + } + } + if (errs.length > 0) { + return new Error(errs.map((e) => e.message).join('\n')); + } + return null; + } + + /** + * AddFunctions configures the checker with a list of function declarations. + */ + addFunctions(...decls: Decl[]) { + const errs: Error[] = []; + for (const decl of decls) { + const err = this.setFunction(decl); + if (err.length > 0) { + errs.push(...err); + } + } + if (errs.length > 0) { + return new Error(errs.map((e) => e.message).join('\n')); + } + return null; + } + + /** + * LookupIdent returns a Decl proto for typeName as an identifier in the Env. + * Returns nil if no such identifier is found in the Env. + */ + lookupIdent(name: string): Decl | null { + for (const candidate of this.#container.resolveCandidateNames(name)) { + const ident = this.#declarations.findIdent(candidate); + if (!isNil(ident)) { + return ident; + } + + // Next try to import the name as a reference to a message type. If + // found, the declaration is added to the outest (global) scope of the + // environment, so next time we can access it faster. + const t = this.#provider.findType(candidate); + if (!isNil(t)) { + const decl = identDecl(candidate, { type: t }); + this.#declarations.addIdent(decl); + return decl; + } + + // Next try to import this as an enum value by splitting the name in a + // type prefix and the enum inside. + const enumValue = this.#provider.enumValue(candidate); + if (!(enumValue instanceof Error)) { + const decl = identDecl(candidate, { + type: mapType({ + keyType: STRING_TYPE, + valueType: INT64_TYPE, + }), + }); + this.#declarations.addIdent(decl); + return decl; + } + } + return null; + } + + /** + * LookupFunction returns a Decl proto for typeName as a function in env. + * Returns nil if no such function is found in env. + */ + lookupFunction(name: string): Decl | null { + for (const candidate of this.#container.resolveCandidateNames(name)) { + const fn = this.#declarations.findFunction(candidate); + if (!isNil(fn)) { + return fn; + } + } + return null; + } + + /** + * setFunction adds the function Decl to the Env. + * Adds a function decl if one doesn't already exist, then adds all overloads + * from the Decl. If overload overlaps with an existing overload, adds to the + * errors in the Env instead. + */ + setFunction(fn: Decl) { + const errors: Error[] = []; + let current = this.lookupFunction(fn.name); + if (!isNil(current)) { + const merged = mergeFunctionDecls(current, fn); + if (merged instanceof Error) { + errors.push(merged); + return errors; + } else { + current = merged; + } + } else { + current = fn; + } + // TODO: check for existing macro names + // const currentDecl = unwrapFunctionDecl(current)!; + // for (const overload of currentDecl.overloads) { + // for (const macro of STANDARD_MACROS) { + // if (macro === current.name) { + // errors.push(new Error(`function '${overload.name}' is a reserved macro name`)); + // } + // } + // } + this.#declarations.setFunction(current); + return errors; + } + + /** + * addIdent adds the Decl to the declarations in the Env. + * + * Returns a non-empty errorMsg if the identifier is already declared in the + * scope. + */ + addIdent(decl: Decl): Error | null { + const current = this.#declarations.findIdentInScope(decl.name); + if (!isNil(current)) { + if (dequal(current, decl)) { + return null; + } + return new Error(`overlapping identifier for name '${decl.name}'`); + } + this.#declarations.addIdent(decl); + return null; + } + + /** + * isOverloadDisabled returns whether the overloadID is disabled in the + * current environment. + */ + isOverloadDisabled(overloadID: string): boolean { + return this.#filteredOverloadIDs.has(overloadID); + } + + /** + * validatedDeclarations returns a reference to the validated variable and + * function declaration scope stack. must be copied before use. + */ + validatedDeclarations(): Scopes { + return this.#declarations; + } + + /** + * enterScope creates a new Env instance with a new innermost declaration + * scope. + */ + enterScope() { + return new CheckerEnv(this.#container, this.#provider, { + ...this.options, + validatedDeclarations: this.#declarations.push(), + }); + } + + /** + * exitScope creates a new Env instance with the nearest outer declaration + * scope. + */ + exitScope() { + return new CheckerEnv(this.#container, this.#provider, { + ...this.options, + validatedDeclarations: this.#declarations.pop(), + }); + } +} diff --git a/packages/cel/src/lib/checker/scopes.ts b/packages/cel/src/lib/checker/scopes.ts new file mode 100644 index 0000000..5f83cf3 --- /dev/null +++ b/packages/cel/src/lib/checker/scopes.ts @@ -0,0 +1,188 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +import { isNil } from '@bearclaw/is'; +import { + Decl, + Type, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { identDecl, unwrapIdentDecl } from '../common/decls/ident-decl'; +import { + getCheckedWellKnownType, + isCheckedWellKnownType, +} from '../common/types/wkt'; + +/** + * Scopes represents nested Decl sets where the Scopes value contains a Groups + * containing all identifiers in scope and an optional parent representing + * outer scopes. + * + * Each Groups value is a mapping of names to Decls in the ident and function + * namespaces. + * + * Lookups are performed such that bindings in inner scopes shadow those in + * outer scopes. + */ +export class Scopes { + readonly #scopes: Group; + readonly #parent: Scopes | null; + + constructor(scopes?: Group, parent?: Scopes) { + this.#scopes = scopes ?? new Group(); + this.#parent = parent ?? null; + } + + get scopes() { + return this.#scopes; + } + + get parent() { + return this.#parent; + } + + /** + * Copy creates a copy of the current Scopes values, including a copy of its + * parent if non-nil. + */ + copy(): Scopes { + return new Scopes(this.#scopes?.copy(), this.#parent?.copy()); + } + + /** + * Push creates a new Scopes value which references the current Scope as its + * parent. + */ + push() { + return new Scopes(new Group(), this); + } + + /** + * Pop returns the parent Scopes value for the current scope, or the current + * scope if the parent is nil. + */ + pop() { + if (!isNil(this.#parent)) { + return this.#parent; + } + return this; + } + + /** + * AddIdent adds the ident Decl in the current scope. + * + * Note: If the name collides with an existing identifier in the scope, the + * Decl is overwritten. + */ + addIdent(decl: Decl) { + this.#scopes.idents.set(decl.name, this.sanitizeIdent(decl)); + } + + /** + * FindIdent finds the first ident Decl with a matching name in Scopes, or + * nil if one cannot be found. + * + * Note: The search is performed from innermost to outermost. + */ + findIdent(name: string): Decl | null { + if (this.#scopes.idents.has(name)) { + return this.#scopes.idents.get(name)!; + } + if (!isNil(this.#parent)) { + return this.#parent.findIdent(name); + } + return null; + } + + /** + * FindIdentInScope finds the first ident Decl with a matching name in the + * current Scopes value, or nil if one does not exist. + * + * Note: The search is only performed on the current scope and does not + * search outer scopes. + */ + findIdentInScope(name: string): Decl | null { + if (this.#scopes.idents.has(name)) { + return this.#scopes.idents.get(name)!; + } + return null; + } + + /** + * SetFunction adds the function Decl to the current scope. + * + * Note: Any previous entry for a function in the current scope with the same + * name is overwritten. + */ + setFunction(decl: Decl) { + this.#scopes.functions.set(decl.name, decl); + } + + /** + * FindFunction finds the first function Decl with a matching name in Scopes. + * The search is performed from innermost to outermost. Returns nil if no + * such function in Scopes. + */ + findFunction(name: string): Decl | null { + if (this.#scopes.functions.has(name)) { + return this.#scopes.functions.get(name)!; + } + if (!isNil(this.#parent)) { + return this.#parent.findFunction(name); + } + return null; + } + + /** + * FindFunctionInScope finds the first function Decl with a matching name in + * the current Scopes value, or nil if one does not exist. + * + * Note: The search is only performed on the current scope and does not + * search outer scopes. + */ + findFunctionInScope(name: string): Decl | null { + if (this.#scopes.functions.has(name)) { + return this.#scopes.functions.get(name)!; + } + return null; + } + + /** + * sanitizeIdent replaces the identifier's well-known types referenced by + * message name with references to CEL built-in type instances. + */ + sanitizeIdent(decl: Decl) { + const ident = unwrapIdentDecl(decl)!; + if (!isNil(ident.type) && isCheckedWellKnownType(ident.type)) { + return identDecl(decl.name, { + type: getCheckedWellKnownType( + ident.type.typeKind.value as string + ) as Type, + }); + } + return decl; + } +} + +/** + * Group is a set of Decls that is pushed on or popped off a Scopes as a unit. + * Contains separate namespaces for identifier and function Decls. + */ +export class Group { + readonly #idents: Map; + readonly #functions: Map; + + constructor(idents?: Map, functions?: Map) { + this.#idents = idents ?? new Map(); + this.#functions = functions ?? new Map(); + } + + get idents() { + return this.#idents; + } + + get functions() { + return this.#functions; + } + + copy() { + return new Group(new Map(this.#idents), new Map(this.#functions)); + } +} diff --git a/packages/cel/src/lib/common/decls/function-decl.ts b/packages/cel/src/lib/common/decls/function-decl.ts index 72f9a0c..f2eebf1 100644 --- a/packages/cel/src/lib/common/decls/function-decl.ts +++ b/packages/cel/src/lib/common/decls/function-decl.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ import { Decl, DeclSchema, @@ -45,3 +46,14 @@ export function functionReference(overloadId: string[]) { overloadId, }); } + +export function mergeFunctionDecls(decl: Decl, other: Decl) { + if (!isFunctionDecl(decl) || !isFunctionDecl(other)) { + return new Error('not a function decl'); + } + const declOverloads = unwrapFunctionDecl(decl)!; + const otherOverloads = unwrapFunctionDecl(other)!; + return functionDecl(decl.name, { + overloads: [...declOverloads.overloads, ...otherOverloads.overloads], + }); +} diff --git a/packages/cel/src/lib/common/pb/proto-type-registry.ts b/packages/cel/src/lib/common/pb/proto-type-registry.ts index f16eaf5..f998f9a 100644 --- a/packages/cel/src/lib/common/pb/proto-type-registry.ts +++ b/packages/cel/src/lib/common/pb/proto-type-registry.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-case-declarations */ /* eslint-disable @typescript-eslint/no-explicit-any */ import { isEmpty, isNil } from '@bearclaw/is'; import { @@ -23,6 +24,7 @@ import { STANDARD_DESCRIPTORS } from '../standard'; import { BOOL_TYPE, isBoolValue } from '../types/bool'; import { BYTES_TYPE } from '../types/bytes'; import { DOUBLE_TYPE } from '../types/double'; +import { enumValue } from '../types/enum'; import { INT64_TYPE } from '../types/int'; import { LIST_TYPE } from '../types/list'; import { MAP_TYPE } from '../types/map'; @@ -42,11 +44,12 @@ export class ProtoTypeRegistry implements TypeRegistry { readonly #registry: MutableRegistry; constructor(typeMap: Map = new Map(), registry?: Registry) { - const descriptors = STANDARD_DESCRIPTORS; + this.#registry = createMutableRegistry(...STANDARD_DESCRIPTORS); if (!isNil(registry)) { - descriptors.push(registry); + for (const r of registry) { + this.#registry.add(r); + } } - this.#registry = createMutableRegistry(...descriptors); this.registerType( BOOL_TYPE, BYTES_TYPE, @@ -89,15 +92,7 @@ export class ProtoTypeRegistry implements TypeRegistry { if (desc.kind === 'enum') { const v = desc.values.find((v) => v.name === enumName); if (!isNil(v)) { - return create(ValueSchema, { - kind: { - case: 'enumValue', - value: { - type: desc.typeName, - value: v.number, - }, - }, - }); + return enumValue(desc.typeName, v.number); } } } @@ -131,28 +126,47 @@ export class ProtoTypeRegistry implements TypeRegistry { } findFieldType(messageType: string, fieldName: string): FieldType | Error { - const desc = this.#registry.getMessage(messageType); + const desc = this.#registry.get(messageType); if (isNil(desc)) { return new Error(`unknown type '${messageType}'`); } - if (desc.kind !== 'message') { - return new Error(`type '${messageType}' is not a message`); - } - const field = desc.fields.find((f) => f.name === fieldName); - if (isNil(field)) { - return new Error(`no such field '${fieldName}' on type '${messageType}'`); - } - return new FieldType( - getFieldDescriptorType(field), - (obj) => { - const isZero = isZeroValue(obj); - if (isZero instanceof Error || !isBoolValue(isZero)) { - return false; + switch (desc.kind) { + case 'enum': + const enumeration = desc.values.find((v) => v.name === fieldName); + if (isNil(enumeration)) { + return new Error( + `no such field '${fieldName}' on type '${messageType}'` + ); } - return isZero.kind.value; - }, - () => null // TODO: implement - ); + return new FieldType( + INT64_TYPE, + (obj) => { + const zero = desc.values.find((v) => v.number === 0); + return obj.kind.value === zero?.name; + }, + () => null // TODO: implement + ); + case 'message': + const field = desc.fields.find((f) => f.name === fieldName); + if (isNil(field)) { + return new Error( + `no such field '${fieldName}' on type '${messageType}'` + ); + } + return new FieldType( + getFieldDescriptorType(field), + (obj) => { + const isZero = isZeroValue(obj); + if (isZero instanceof Error || !isBoolValue(isZero)) { + return false; + } + return isZero.kind.value; + }, + () => null // TODO: implement + ); + default: + return new Error(`type '${messageType}' is not a message or enum`); + } } newValue(typeName: string, fields: Record): Value | Error { diff --git a/packages/cel/src/lib/common/standard.ts b/packages/cel/src/lib/common/standard.ts index e361a5c..1fb4e4d 100644 --- a/packages/cel/src/lib/common/standard.ts +++ b/packages/cel/src/lib/common/standard.ts @@ -273,7 +273,7 @@ export const STANDARD_DESCRIPTORS: ( DurationSchema, ]; -export const STANDARD_IDENTS: Decl[] = [ +export const STANDARD_IDENT_DECLARATIONS: Decl[] = [ identDecl('bool', { type: typeType(BOOL_TYPE) }), identDecl('bytes', { type: typeType(BYTES_TYPE) }), identDecl('double', { type: typeType(DOUBLE_TYPE) }), diff --git a/packages/cel/src/lib/common/types/enum.ts b/packages/cel/src/lib/common/types/enum.ts new file mode 100644 index 0000000..4a737e0 --- /dev/null +++ b/packages/cel/src/lib/common/types/enum.ts @@ -0,0 +1,36 @@ +import { + Value, + ValueSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { create } from '@bufbuild/protobuf'; + +export function enumValue(type: string, value: number): Value { + return create(ValueSchema, { + kind: { + case: 'enumValue', + value: { + type, + value, + }, + }, + }); +} + +export function isEnumValue(value: Value): value is Value & { + kind: { + case: 'enumValue'; + value: { + type: string; + value: number; + }; + }; +} { + return value.kind.case === 'enumValue'; +} + +export function unwrapEnumValue(value: Value) { + if (isEnumValue(value)) { + return value.kind.value; + } + return null; +} diff --git a/packages/cel/src/lib/environment.ts b/packages/cel/src/lib/environment.ts index 04038a6..8478957 100644 --- a/packages/cel/src/lib/environment.ts +++ b/packages/cel/src/lib/environment.ts @@ -17,7 +17,7 @@ import { identDecl } from './common/decls/ident-decl'; import { STANDARD_DESCRIPTORS, STANDARD_FUNCTION_DECLARATIONS, - STANDARD_IDENTS, + STANDARD_IDENT_DECLARATIONS, } from './common/standard'; import { DYN_TYPE } from './common/types/dyn'; import { INT64_TYPE } from './common/types/int'; @@ -362,7 +362,7 @@ export function STANDARD_ENV() { container: new CELContainer(), registry: createMutableRegistry(...STANDARD_DESCRIPTORS), functions: STANDARD_FUNCTION_DECLARATIONS, - idents: STANDARD_IDENTS, + idents: STANDARD_IDENT_DECLARATIONS, }); } From 760984fc60567814ebd93f7533e5a58ab482a182 Mon Sep 17 00:00:00 2001 From: jafaircl Date: Tue, 5 Nov 2024 19:52:10 -0500 Subject: [PATCH 32/34] feat(cel): handle some todos --- packages/cel/src/lib/checker/env.spec.ts | 29 +++++--- packages/cel/src/lib/checker/env.ts | 48 ++++++++----- packages/cel/src/lib/parser/macros.ts | 91 +++++++++++++++++++++--- 3 files changed, 133 insertions(+), 35 deletions(-) diff --git a/packages/cel/src/lib/checker/env.spec.ts b/packages/cel/src/lib/checker/env.spec.ts index b216bbe..eb65376 100644 --- a/packages/cel/src/lib/checker/env.spec.ts +++ b/packages/cel/src/lib/checker/env.spec.ts @@ -1,10 +1,13 @@ import { CELContainer } from '../cel'; +import { functionDecl, overloadDecl } from '../common/decls/function-decl'; import { identDecl } from '../common/decls/ident-decl'; import { ProtoTypeRegistry } from '../common/pb/proto-type-registry'; import { STANDARD_FUNCTION_DECLARATIONS, STANDARD_IDENT_DECLARATIONS, } from '../common/standard'; +import { BOOL_TYPE } from '../common/types/bool'; +import { DYN_TYPE } from '../common/types/dyn'; import { TYPE_TYPE } from '../common/types/type'; import { CheckerEnv } from './env'; @@ -16,14 +19,24 @@ describe('CheckerEnv', () => { expect(errs?.message).toContain('overlapping identifier'); }); - // TODO: fix this test - // it('overlapping function', () => { - // const env = standardEnv(); - // const errs = env.addFunctions(identDecl('int', { type: TYPE_TYPE })); - // console.log(errs); - // expect(errs).not.toBeNull(); - // expect(errs?.message).toContain('overlapping identifier'); - // }); + it('overlapping function', () => { + const env = standardEnv(); + const errs = env.addFunctions( + functionDecl('has', { + overloads: [ + overloadDecl({ + isInstanceFunction: false, + params: [DYN_TYPE], + resultType: BOOL_TYPE, + }), + ], + }) + ); + expect(errs).not.toBeNull(); + expect(errs?.message).toEqual( + `overlapping macro for name 'has' with 1 args` + ); + }); }); function standardEnv() { diff --git a/packages/cel/src/lib/checker/env.ts b/packages/cel/src/lib/checker/env.ts index 15d9576..63ad767 100644 --- a/packages/cel/src/lib/checker/env.ts +++ b/packages/cel/src/lib/checker/env.ts @@ -3,14 +3,17 @@ import { isNil } from '@bearclaw/is'; import { Decl } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb'; import { dequal } from 'dequal'; import { CELContainer } from '../common/container'; -import { mergeFunctionDecls } from '../common/decls/function-decl'; +import { + mergeFunctionDecls, + unwrapFunctionDecl, +} from '../common/decls/function-decl'; import { identDecl } from '../common/decls/ident-decl'; import { TypeProvider } from '../common/ref/provider'; import { DYN_TYPE } from '../common/types/dyn'; -import { INT64_TYPE } from '../common/types/int'; -import { mapType } from '../common/types/map'; -import { STRING_TYPE } from '../common/types/string'; +import { unwrapEnumValue } from '../common/types/enum'; +import { INT64_TYPE, int64Constant } from '../common/types/int'; import { LESS_DOUBLE_INT64_OVERLOAD } from '../overloads'; +import { STANDARD_MACRO_DECLARATIONS } from '../parser/macros'; import { GREATER_DOUBLE_INT64_OVERLOAD, GREATER_DOUBLE_UINT64_OVERLOAD, @@ -185,11 +188,10 @@ export class CheckerEnv { // type prefix and the enum inside. const enumValue = this.#provider.enumValue(candidate); if (!(enumValue instanceof Error)) { + const unwrappedEnum = unwrapEnumValue(enumValue)!; const decl = identDecl(candidate, { - type: mapType({ - keyType: STRING_TYPE, - valueType: INT64_TYPE, - }), + type: INT64_TYPE, + value: int64Constant(BigInt(unwrappedEnum.value)), }); this.#declarations.addIdent(decl); return decl; @@ -232,15 +234,27 @@ export class CheckerEnv { } else { current = fn; } - // TODO: check for existing macro names - // const currentDecl = unwrapFunctionDecl(current)!; - // for (const overload of currentDecl.overloads) { - // for (const macro of STANDARD_MACROS) { - // if (macro === current.name) { - // errors.push(new Error(`function '${overload.name}' is a reserved macro name`)); - // } - // } - // } + const currentDecl = unwrapFunctionDecl(current)!; + for (const overload of currentDecl.overloads) { + for (const macroDecl of STANDARD_MACRO_DECLARATIONS) { + const macro = unwrapFunctionDecl(macroDecl)!; + const macroOverload = macro.overloads[0]; + if ( + macroDecl.name === current.name && + macroOverload.isInstanceFunction === overload.isInstanceFunction && + macroOverload.params.length === overload.params.length + ) { + errors.push( + new Error( + `overlapping macro for name '${current.name}' with ${overload.params.length} args` + ) + ); + } + } + if (errors.length > 0) { + return errors; + } + } this.#declarations.setFunction(current); return errors; } diff --git a/packages/cel/src/lib/parser/macros.ts b/packages/cel/src/lib/parser/macros.ts index 9b9982c..9b2e811 100644 --- a/packages/cel/src/lib/parser/macros.ts +++ b/packages/cel/src/lib/parser/macros.ts @@ -4,9 +4,11 @@ import { Expr } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; import { ParserRuleContext, Token } from 'antlr4'; import { Location, OffsetRange } from '../common/ast'; import { ACCUMULATOR_VAR } from '../common/constants'; -import { boolExpr } from '../common/types/bool'; +import { functionDecl, overloadDecl } from '../common/decls/function-decl'; +import { BOOL_TYPE, boolExpr } from '../common/types/bool'; import { callExpr } from '../common/types/call'; import { comprehensionExpr } from '../common/types/comprehension'; +import { DYN_TYPE } from '../common/types/dyn'; import { identExpr, unwrapIdentExpr } from '../common/types/ident'; import { int64Expr } from '../common/types/int'; import { listExpr } from '../common/types/list'; @@ -28,18 +30,87 @@ import { } from '../operators'; import { ParserHelper } from './parser-helper'; -export const STANDARD_MACROS = new Set([ - HAS_MACRO, - ALL_MACRO, - EXISTS_MACRO, - EXISTS_ONE_MACRO, - MAP_MACRO, - // MAP_FILTER_MACRO, // TODO: Implement this - FILTER_MACRO, +export const STANDARD_MACRO_DECLARATIONS = new Set([ + // HasMacro expands "has(m.f)" which tests the presence of a field, avoiding + // the need to specify the field as a string. + functionDecl(HAS_MACRO, { + overloads: [ + overloadDecl({ + isInstanceFunction: false, + params: [DYN_TYPE], + resultType: BOOL_TYPE, + }), + ], + }), + // AllMacro expands "range.all(var, predicate)" into a comprehension which + // ensures that all elements in the range satisfy the predicate. + functionDecl(ALL_MACRO, { + overloads: [ + overloadDecl({ + isInstanceFunction: true, + params: [DYN_TYPE, DYN_TYPE], + resultType: BOOL_TYPE, + }), + ], + }), + // ExistsMacro expands "range.exists(var, predicate)" into a comprehension + // which ensures that some element in the range satisfies the predicate. + functionDecl(EXISTS_MACRO, { + overloads: [ + overloadDecl({ + isInstanceFunction: true, + params: [DYN_TYPE, DYN_TYPE], + resultType: BOOL_TYPE, + }), + ], + }), + // ExistsOneMacro expands "range.exists_one(var, predicate)", which is true + // if for exactly one element in range the predicate holds. + functionDecl(EXISTS_ONE_MACRO, { + overloads: [ + overloadDecl({ + isInstanceFunction: true, + params: [DYN_TYPE, DYN_TYPE], + resultType: BOOL_TYPE, + }), + ], + }), + // MapMacro expands "range.map(var, function)" into a comprehension which + // applies the function to each element in the range to produce a new list. + functionDecl(MAP_MACRO, { + overloads: [ + overloadDecl({ + isInstanceFunction: true, + params: [DYN_TYPE, DYN_TYPE], + resultType: DYN_TYPE, + }), + ], + }), + // MapFilterMacro expands "range.map(var, predicate, function)" into a + // comprehension which first filters the elements in the range by the + // predicate, then applies the transform function to produce a new list. + // // MAP_FILTER_MACRO, // TODO: Implement this + // FilterMacro expands "range.filter(var, predicate)" into a comprehension + // which filters elements in the range, producing a new list from the + // elements that satisfy the predicate. + functionDecl(FILTER_MACRO, { + overloads: [ + overloadDecl({ + isInstanceFunction: true, + params: [DYN_TYPE, DYN_TYPE], + resultType: DYN_TYPE, + }), + ], + }), ]); export function findMacro(name: string) { - return STANDARD_MACROS.has(name) ? name : undefined; + for (const macro of STANDARD_MACRO_DECLARATIONS) { + if (macro.name === name) { + return name; + } + } + return null; } export function expandMacro( From 5a1fdb6e3286fa4ebd761e5a7a014d98ccde17a6 Mon Sep 17 00:00:00 2001 From: jafaircl Date: Thu, 7 Nov 2024 18:13:11 -0500 Subject: [PATCH 33/34] feat(cel): converting to use of refvals checkpoint --- packages/cel/src/lib/checker/checker.spec.ts | 265 ++++----- packages/cel/src/lib/checker/checker.ts | 28 +- packages/cel/src/lib/checker/env.spec.ts | 4 +- packages/cel/src/lib/checker/env.ts | 4 +- .../src/lib/common/pb/proto-type-registry.ts | 26 +- packages/cel/src/lib/common/ref/reference.ts | 115 ++++ packages/cel/src/lib/common/standard.ts | 524 +++++++++--------- .../cel/src/lib/common/types/bool.spec.ts | 104 ++-- packages/cel/src/lib/common/types/bool.ts | 128 ++++- .../cel/src/lib/common/types/bytes.spec.ts | 169 +++--- packages/cel/src/lib/common/types/bytes.ts | 147 ++++- packages/cel/src/lib/common/types/compare.ts | 25 +- .../cel/src/lib/common/types/double.spec.ts | 317 +++++------ packages/cel/src/lib/common/types/double.ts | 223 +++++++- .../cel/src/lib/common/types/duration.spec.ts | 263 +++++++-- packages/cel/src/lib/common/types/duration.ts | 276 ++++++++- packages/cel/src/lib/common/types/error.ts | 188 ++++++- packages/cel/src/lib/common/types/int.spec.ts | 457 +++++++-------- packages/cel/src/lib/common/types/int.ts | 301 +++++++++- packages/cel/src/lib/common/types/native.ts | 1 + packages/cel/src/lib/common/types/number.ts | 13 + .../cel/src/lib/common/types/string.spec.ts | 361 +++++------- packages/cel/src/lib/common/types/string.ts | 202 ++++++- .../src/lib/common/types/timestamp.spec.ts | 9 + .../cel/src/lib/common/types/timestamp.ts | 198 ++++++- .../src/lib/common/types/traits/comparer.ts | 23 + .../src/lib/common/types/traits/container.ts | 17 + .../lib/common/types/traits/field-tester.ts | 22 + .../src/lib/common/types/traits/indexer.ts | 17 + .../src/lib/common/types/traits/iterator.ts | 72 +++ .../cel/src/lib/common/types/traits/lister.ts | 47 ++ .../cel/src/lib/common/types/traits/mapper.ts | 63 +++ .../src/lib/common/types/traits/matcher.ts | 17 + .../cel/src/lib/common/types/traits/math.ts | 96 ++++ .../src/lib/common/types/traits/receiver.ts | 18 + .../cel/src/lib/common/types/traits/sizer.ts | 17 + .../cel/src/lib/common/types/traits/zeroer.ts | 18 +- packages/cel/src/lib/common/types/type.ts | 72 +++ .../cel/src/lib/common/types/uint.spec.ts | 338 +++++------ packages/cel/src/lib/common/types/uint.ts | 258 ++++++++- packages/cel/src/lib/common/types/unknown.ts | 70 +++ .../cel/src/lib/common/types/utils.spec.ts | 20 +- packages/cel/src/lib/common/types/wkt.ts | 26 +- packages/cel/src/lib/environment.ts | 8 +- .../lib/interpreter/attribute-factory.spec.ts | 4 +- packages/cel/src/lib/parser/macros.ts | 10 +- 46 files changed, 4005 insertions(+), 1576 deletions(-) create mode 100644 packages/cel/src/lib/common/ref/reference.ts create mode 100644 packages/cel/src/lib/common/types/traits/container.ts create mode 100644 packages/cel/src/lib/common/types/traits/field-tester.ts create mode 100644 packages/cel/src/lib/common/types/traits/indexer.ts create mode 100644 packages/cel/src/lib/common/types/traits/iterator.ts create mode 100644 packages/cel/src/lib/common/types/traits/lister.ts create mode 100644 packages/cel/src/lib/common/types/traits/mapper.ts diff --git a/packages/cel/src/lib/checker/checker.spec.ts b/packages/cel/src/lib/checker/checker.spec.ts index 0dc159c..f9b9fba 100644 --- a/packages/cel/src/lib/checker/checker.spec.ts +++ b/packages/cel/src/lib/checker/checker.spec.ts @@ -24,21 +24,21 @@ import { STANDARD_IDENT_DECLARATIONS, } from '../common/standard'; import { abstractType } from '../common/types/abstract'; -import { BOOL_TYPE } from '../common/types/bool'; -import { BYTES_TYPE } from '../common/types/bytes'; -import { DOUBLE_TYPE } from '../common/types/double'; +import { BOOL_CEL_TYPE } from '../common/types/bool'; +import { BYTES_CEL_TYPE } from '../common/types/bytes'; +import { DOUBLE_CEL_TYPE } from '../common/types/double'; import { DYN_TYPE } from '../common/types/dyn'; import { ERROR_TYPE } from '../common/types/error'; -import { INT64_TYPE } from '../common/types/int'; +import { INT_CEL_TYPE } from '../common/types/int'; import { listType } from '../common/types/list'; import { mapType } from '../common/types/map'; import { messageType } from '../common/types/message'; import { NULL_TYPE } from '../common/types/null'; import { nullableType } from '../common/types/nullable'; import { ABSTRACT_OPTIONAL_TYPE, optionalType } from '../common/types/optional'; -import { STRING_TYPE } from '../common/types/string'; +import { STRING_CEL_TYPE } from '../common/types/string'; import { typeParamType } from '../common/types/type-param'; -import { UINT64_TYPE } from '../common/types/uint'; +import { UINT_CEL_TYPE } from '../common/types/uint'; import { CELParser, CELParserOptions } from '../parser/parser'; import { CELChecker } from './checker'; import { CheckerEnv } from './env'; @@ -85,12 +85,12 @@ function getDefaultEnv() { const env = new CheckerEnv(container, provider); env.addIdents( ...STANDARD_IDENT_DECLARATIONS, - identDecl('is', { type: STRING_TYPE }), - identDecl('ii', { type: INT64_TYPE }), - identDecl('iu', { type: UINT64_TYPE }), - identDecl('iz', { type: BOOL_TYPE }), - identDecl('ib', { type: BYTES_TYPE }), - identDecl('id', { type: DOUBLE_TYPE }), + identDecl('is', { type: STRING_CEL_TYPE }), + identDecl('ii', { type: INT_CEL_TYPE }), + identDecl('iu', { type: UINT_CEL_TYPE }), + identDecl('iz', { type: BOOL_CEL_TYPE }), + identDecl('ib', { type: BYTES_CEL_TYPE }), + identDecl('id', { type: DOUBLE_CEL_TYPE }), identDecl('ix', { type: NULL_TYPE }) ); env.addFunctions( @@ -99,7 +99,7 @@ function getDefaultEnv() { overloads: [ { overloadId: 'fg_s_0', - resultType: STRING_TYPE, + resultType: STRING_CEL_TYPE, }, ], }), @@ -107,8 +107,8 @@ function getDefaultEnv() { overloads: [ { overloadId: 'fi_s_s_0', - params: [STRING_TYPE], - resultType: STRING_TYPE, + params: [STRING_CEL_TYPE], + resultType: STRING_CEL_TYPE, isInstanceFunction: true, }, ], @@ -143,13 +143,13 @@ const testCases: TestInfo[] = [ { in: `a.b`, out: `a.b~bool`, - outType: STRING_TYPE, + outType: STRING_CEL_TYPE, env: extendEnv(getDefaultEnv(), { idents: [ identDecl('a', { type: mapType({ - keyType: STRING_TYPE, - valueType: STRING_TYPE, + keyType: STRING_CEL_TYPE, + valueType: STRING_CEL_TYPE, }), }), ], @@ -159,32 +159,32 @@ const testCases: TestInfo[] = [ { in: `"A"`, out: `"A"~string`, - outType: STRING_TYPE, + outType: STRING_CEL_TYPE, }, { in: `12`, out: `12~int`, - outType: INT64_TYPE, + outType: INT_CEL_TYPE, }, { in: `12u`, out: `12u~uint`, - outType: UINT64_TYPE, + outType: UINT_CEL_TYPE, }, { in: `true`, out: `true~bool`, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `false`, out: `false~bool`, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `12.23`, out: `12.23~double`, - outType: DOUBLE_TYPE, + outType: DOUBLE_CEL_TYPE, }, { in: `null`, @@ -194,37 +194,37 @@ const testCases: TestInfo[] = [ { in: `b"ABC"`, out: `b"ABC"~bytes`, - outType: BYTES_TYPE, + outType: BYTES_CEL_TYPE, }, // Ident types { in: `is`, out: `is~string^is`, - outType: STRING_TYPE, + outType: STRING_CEL_TYPE, env: getDefaultEnv(), }, { in: `ii`, out: `ii~int^ii`, - outType: INT64_TYPE, + outType: INT_CEL_TYPE, env: getDefaultEnv(), }, { in: `iu`, out: `iu~uint^iu`, - outType: UINT64_TYPE, + outType: UINT_CEL_TYPE, env: getDefaultEnv(), }, { in: `iz`, out: `iz~bool^iz`, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, env: getDefaultEnv(), }, { in: `id`, out: `id~double^id`, - outType: DOUBLE_TYPE, + outType: DOUBLE_CEL_TYPE, env: getDefaultEnv(), }, { @@ -236,13 +236,13 @@ const testCases: TestInfo[] = [ { in: `ib`, out: `ib~bytes^ib`, - outType: BYTES_TYPE, + outType: BYTES_CEL_TYPE, env: getDefaultEnv(), }, { in: `id`, out: `id~double^id`, - outType: DOUBLE_TYPE, + outType: DOUBLE_CEL_TYPE, env: getDefaultEnv(), }, { @@ -253,7 +253,7 @@ const testCases: TestInfo[] = [ { in: `[1]`, out: `[1~int]~list(int)`, - outType: listType({ elemType: INT64_TYPE }), + outType: listType({ elemType: INT_CEL_TYPE }), }, { in: `[1, "A"]`, @@ -272,36 +272,36 @@ const testCases: TestInfo[] = [ { in: `fg_s()`, out: `fg_s()~string^fg_s_0`, - outType: STRING_TYPE, + outType: STRING_CEL_TYPE, env: getDefaultEnv(), }, { in: `is.fi_s_s()`, out: `is~string^is.fi_s_s()~string^fi_s_s_0`, - outType: STRING_TYPE, + outType: STRING_CEL_TYPE, env: getDefaultEnv(), }, { in: `1 + 2`, out: `_+_(1~int, 2~int)~int^add_int64`, - outType: INT64_TYPE, + outType: INT_CEL_TYPE, env: getDefaultEnv(), }, { in: `1 + ii`, out: `_+_(1~int, ii~int^ii)~int^add_int64`, - outType: INT64_TYPE, + outType: INT_CEL_TYPE, env: getDefaultEnv(), }, { in: `[1] + [2]`, out: `_+_([1~int]~list(int), [2~int]~list(int))~list(int)^add_list`, - outType: listType({ elemType: INT64_TYPE }), + outType: listType({ elemType: INT_CEL_TYPE }), env: getDefaultEnv(), }, { in: `[] + [1,2,3,] + [4]`, - outType: listType({ elemType: INT64_TYPE }), + outType: listType({ elemType: INT_CEL_TYPE }), out: ` _+_( _+_( @@ -324,12 +324,12 @@ _+_( }, { in: `{1:2u, 2:3u}`, - outType: mapType({ keyType: INT64_TYPE, valueType: UINT64_TYPE }), + outType: mapType({ keyType: INT_CEL_TYPE, valueType: UINT_CEL_TYPE }), out: `{1~int : 2u~uint, 2~int : 3u~uint}~map(int, uint)`, }, { in: `{"a":1, "b":2}.a`, - outType: INT64_TYPE, + outType: INT_CEL_TYPE, out: `{"a"~string : 1~int, "b"~string : 2~int}~map(string, int).a~int`, }, { @@ -378,9 +378,9 @@ ERROR: :1:40: undefined field 'undefined' _==_(size(x~list(int)^x)~int^size_list, x~list(int)^x.size()~int^list_size) ~bool^equals`, env: extendEnv(getDefaultEnv(), { - idents: [identDecl('x', { type: listType({ elemType: INT64_TYPE }) })], + idents: [identDecl('x', { type: listType({ elemType: INT_CEL_TYPE }) })], }), - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `int(1u) + int(uint("1"))`, @@ -388,7 +388,7 @@ _==_(size(x~list(int)^x)~int^size_list, x~list(int)^x.size()~int^list_size) _+_(int(1u~uint)~int^uint64_to_int64, int(uint("1"~string)~uint^string_to_uint64)~int^uint64_to_int64) ~int^add_int64`, - outType: INT64_TYPE, + outType: INT_CEL_TYPE, }, { in: `false && !true || false ? 2 : 3`, @@ -400,12 +400,12 @@ _?_:_(_||_(_&&_(false~bool, !_(true~bool)~bool^logical_not)~bool^logical_and, 3~int) ~int^conditional `, - outType: INT64_TYPE, + outType: INT_CEL_TYPE, }, { in: `b"abc" + b"def"`, out: `_+_(b"abc"~bytes, b"def"~bytes)~bytes^add_bytes`, - outType: BYTES_TYPE, + outType: BYTES_CEL_TYPE, }, { in: `1.0 + 2.0 * 3.0 - 1.0 / 2.20202 != 66.6`, @@ -416,7 +416,7 @@ _!=_(_-_(_+_(1~double, _*_(2~double, 3~double)~double^multiply_double) ~double^subtract_double, 66.6~double) ~bool^not_equals`, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `null == null && null != null`, @@ -431,7 +431,7 @@ _!=_(_-_(_+_(1~double, _*_(2~double, 3~double)~double^multiply_double) null~null )~bool^not_equals )~bool^logical_and`, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `1 == 1 && 2 != 1`, @@ -446,17 +446,17 @@ _!=_(_-_(_+_(1~double, _*_(2~double, 3~double)~double^multiply_double) 1~int )~bool^not_equals )~bool^logical_and`, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `1 + 2 * 3 - 1 / 2 == 6 % 1`, out: ` _==_(_-_(_+_(1~int, _*_(2~int, 3~int)~int^multiply_int64)~int^add_int64, _/_(1~int, 2~int)~int^divide_int64)~int^subtract_int64, _%_(6~int, 1~int)~int^modulo_int64)~bool^equals`, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `"abc" + "def"`, out: `_+_("abc"~string, "def"~string)~string^add_string`, - outType: STRING_TYPE, + outType: STRING_CEL_TYPE, }, { in: `1u + 2u * 3u - 1u / 2u == 6u % 1u`, @@ -466,7 +466,7 @@ _!=_(_-_(_+_(1~double, _*_(2~double, 3~double)~double^multiply_double) ~uint^subtract_uint64, _%_(6u~uint, 1u~uint)~uint^modulo_uint64) ~bool^equals`, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `x.single_int32 != null`, @@ -502,7 +502,7 @@ ERROR: :1:2: unexpected failed resolution of 'google.api.expr.test.v1.pro )~int^add_int64, 23~int )~bool^equals`, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `x.single_value[23] + x.single_struct['y']`, @@ -536,12 +536,12 @@ ERROR: :1:2: unexpected failed resolution of 'google.api.expr.test.v1.pro ~int^google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum.BAR, 99~int) ~bool^not_equals`, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `size([] + [1])`, out: `size(_+_([]~list(int), [1~int]~list(int))~list(int)^add_list)~int^size_list`, - outType: INT64_TYPE, + outType: INT_CEL_TYPE, }, { in: `x["claims"]["groups"][0].name == "dummy" @@ -594,7 +594,7 @@ ERROR: :1:2: unexpected failed resolution of 'google.api.expr.test.v1.pro identDecl('z', { type: messageType('google.protobuf.Value') }), ], }), - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `x + y`, @@ -607,7 +607,7 @@ ERROR: :1:2: unexpected failed resolution of 'google.api.expr.test.v1.pro ), }), }), - identDecl('y', { type: listType({ elemType: INT64_TYPE }) }), + identDecl('y', { type: listType({ elemType: INT_CEL_TYPE }) }), ], }), err: ` @@ -660,7 +660,7 @@ ERROR: :1:2: found no matching overload for '_[_]' applied to '(list(goog size(x~list(google.api.expr.test.v1.proto3.TestAllTypes)^x)~int^size_list) ~bool^equals `, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `x.repeated_int64[x.single_int32] == 23`, @@ -677,7 +677,7 @@ ERROR: :1:2: found no matching overload for '_[_]' applied to '(list(goog ~int^index_list, 23~int) ~bool^equals`, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `size(x.map_int64_nested_type) == 0`, @@ -695,12 +695,12 @@ ERROR: :1:2: found no matching overload for '_[_]' applied to '(list(goog 0~int) ~bool^equals `, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `x.all(y, y == true)`, env: extendEnv(getDefaultEnv(), { - idents: [identDecl('x', { type: BOOL_TYPE })], + idents: [identDecl('x', { type: BOOL_CEL_TYPE })], }), out: ` __comprehension__( @@ -764,7 +764,7 @@ ERROR: :1:2: found no matching overload for '_[_]' applied to '(list(goog // Result __result__~list(double)^__result__)~list(double) `, - outType: listType({ elemType: DOUBLE_TYPE }), + outType: listType({ elemType: DOUBLE_CEL_TYPE }), }, { in: `x[2].single_int32 == 23`, @@ -772,7 +772,7 @@ ERROR: :1:2: found no matching overload for '_[_]' applied to '(list(goog idents: [ identDecl('x', { type: mapType({ - keyType: STRING_TYPE, + keyType: STRING_CEL_TYPE, valueType: messageType( 'google.api.expr.test.v1.proto3.TestAllTypes' ), @@ -792,7 +792,7 @@ ERROR: :1:2: found no matching overload for '_[_]' applied to '(list(goog idents: [ identDecl('x', { type: mapType({ - keyType: STRING_TYPE, + keyType: STRING_CEL_TYPE, valueType: messageType( 'google.api.expr.test.v1.proto3.TestAllTypes' ), @@ -808,7 +808,7 @@ ERROR: :1:2: found no matching overload for '_[_]' applied to '(list(goog ~int, 23~int) ~bool^equals`, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `x.single_nested_message.bb == 43 && has(x.single_nested_message)`, @@ -827,7 +827,7 @@ ERROR: :1:2: found no matching overload for '_[_]' applied to '(list(goog )~bool^equals, x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_nested_message~test-only~~bool )~bool^logical_and`, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `x.single_nested_message.undefined == x.undefined && has(x.single_int32) && has(x.repeated_int32)`, @@ -861,7 +861,7 @@ ERROR: :1:39: undefined field 'undefined' null~null) ~bool^not_equals `, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `x.single_int64 != null`, @@ -893,7 +893,7 @@ ERROR: :1:16: found no matching overload for '_!=_' applied to '(int, nul null~null) ~bool^equals `, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `x.single_bool_wrapper @@ -962,7 +962,7 @@ ERROR: :1:16: found no matching overload for '_!=_' applied to '(int, nul )~bool^logical_and )~bool^logical_and )~bool^logical_and`, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `x.single_timestamp == google.protobuf.Timestamp{seconds: 20} && @@ -974,7 +974,7 @@ ERROR: :1:16: found no matching overload for '_!=_' applied to '(int, nul }), ], }), - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `x.single_bool_wrapper == google.protobuf.BoolValue{value: true} @@ -994,7 +994,7 @@ ERROR: :1:16: found no matching overload for '_!=_' applied to '(int, nul }), ], }), - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `x.repeated_int64.exists(y, y > 10) && y < 5`, @@ -1098,7 +1098,7 @@ ERROR: :1:16: found no matching overload for '_!=_' applied to '(int, nul 1~int )~bool^equals)~bool )~bool^logical_and`, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `x.all(e, 0)`, @@ -1199,7 +1199,7 @@ ERROR: :1:5: undeclared reference to 'x' (in container '') // env: extendEnv(getDefaultEnv(), { // idents: [ // identDecl('x', { type: ANY_TYPE }), - // identDecl('y', { type: nullableType(INT64_TYPE) }), + // identDecl('y', { type: nullableType(INT_CEL_TYPE) }), // ], // }), // out: ` @@ -1234,7 +1234,7 @@ ERROR: :1:5: undeclared reference to 'x' (in container '') // )~bool^logical_or // )~bool^logical_or // `, - // outType: BOOL_TYPE, + // outType: BOOL_CEL_TYPE, // }, // { // in: `x == google.protobuf.Any{ @@ -1246,7 +1246,7 @@ ERROR: :1:5: undeclared reference to 'x' (in container '') // env: extendEnv(getDefaultEnv(), { // idents: [ // identDecl('x', { type: ANY_TYPE }), - // identDecl('y', { type: nullableType(INT64_TYPE) }), + // identDecl('y', { type: nullableType(INT_CEL_TYPE) }), // ], // }), // out: ` @@ -1304,7 +1304,7 @@ _==_(map~type(map(dyn, dyn))^map, ~bool^equals) ~bool^logical_and `, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `size(x) > 4`, @@ -1322,13 +1322,13 @@ _==_(map~type(map(dyn, dyn))^map, params: [ messageType('google.api.expr.test.v1.proto3.TestAllTypes'), ], - resultType: INT64_TYPE, + resultType: INT_CEL_TYPE, }), ], }), ], }), - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `x.single_int64_wrapper + 1 != 23`, @@ -1347,7 +1347,7 @@ _!=_(_+_(x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_int64_wrapper 23~int) ~bool^not_equals `, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `x.single_int64_wrapper + y != 23`, @@ -1368,7 +1368,7 @@ _!=_( 23~int )~bool^not_equals `, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `1 in [1, 2, 3]`, @@ -1380,7 +1380,7 @@ _!=_( 3~int ]~list(int) )~bool^in_list`, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `1 in dyn([1, 2, 3])`, @@ -1394,7 +1394,7 @@ _!=_( ]~list(int) )~dyn^to_dyn )~bool^in_list|in_map`, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `type(null) == null_type`, @@ -1404,7 +1404,7 @@ _!=_( )~type(null)^type, null_type~type(null)^null_type )~bool^equals`, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `type(type) == type`, @@ -1414,7 +1414,7 @@ _!=_( )~type(type(type))^type, type~type(type)^type )~bool^equals`, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `([[[1]], [[2]], [[3]]][0][0] + [2, 3, {'four': {'five': 'six'}}])[3]`, @@ -1528,7 +1528,7 @@ _!=_( env: extendEnv(getDefaultEnv(), { idents: [ identDecl('args', { - type: mapType({ keyType: STRING_TYPE, valueType: DYN_TYPE }), + type: mapType({ keyType: STRING_CEL_TYPE, valueType: DYN_TYPE }), }), ], }), @@ -1549,7 +1549,7 @@ _!=_( env: extendEnv(getDefaultEnv(), { idents: [identDecl('a', { type: typeParamType('T') })], }), - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `!has(pb2.single_int64) @@ -1597,7 +1597,7 @@ _!=_( )~bool^logical_not )~bool^logical_and )~bool^logical_and`, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `TestAllTypes{}.repeated_nested_message`, @@ -1633,8 +1633,8 @@ google.api.expr.test.v1.proto2.TestAllTypes.repeated_nested_message overloads: [ overloadDecl({ overloadId: 'base64_encode_string', - params: [STRING_TYPE], - resultType: STRING_TYPE, + params: [STRING_CEL_TYPE], + resultType: STRING_CEL_TYPE, }), ], }), @@ -1644,7 +1644,7 @@ google.api.expr.test.v1.proto2.TestAllTypes.repeated_nested_message base64.encode( "hello"~string )~string^base64_encode_string`, - outType: STRING_TYPE, + outType: STRING_CEL_TYPE, }, // TODO: namespaced functions // { @@ -1656,8 +1656,8 @@ google.api.expr.test.v1.proto2.TestAllTypes.repeated_nested_message // overloads: [ // overloadDecl({ // overloadId: 'base64_encode_string', - // params: [STRING_TYPE], - // resultType: STRING_TYPE, + // params: [STRING_CEL_TYPE], + // resultType: STRING_CEL_TYPE, // }), // ], // }), @@ -1667,7 +1667,7 @@ google.api.expr.test.v1.proto2.TestAllTypes.repeated_nested_message // base64.encode( // "hello"~string // )~string^base64_encode_string`, - // outType: STRING_TYPE, + // outType: STRING_CEL_TYPE, // }, { in: `{}`, @@ -1700,7 +1700,7 @@ set( }), ], }), - outType: abstractType({ name: 'set', parameterTypes: [INT64_TYPE] }), + outType: abstractType({ name: 'set', parameterTypes: [INT_CEL_TYPE] }), }, { in: `set([1, 2]) == set([2, 1])`, @@ -1725,7 +1725,7 @@ set( }), ], }), - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `set([1, 2]) == x`, @@ -1758,7 +1758,7 @@ _==_( }), ], }), - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, { in: `int{}`, @@ -1828,7 +1828,7 @@ _==_( { in: `1 <= 1.0 && 1u <= 1.0 && 1.0 <= 1 && 1.0 <= 1u && 1 <= 1u && 1u <= 1`, // opts: []Option{CrossTypeNumericComparisons(true)}, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, out: ` _&&_( _&&_( @@ -1868,7 +1868,7 @@ _==_( { in: `1 < 1.0 && 1u < 1.0 && 1.0 < 1 && 1.0 < 1u && 1 < 1u && 1u < 1`, // opts: []Option{CrossTypeNumericComparisons(true)}, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, out: ` _&&_( _&&_( @@ -1908,7 +1908,7 @@ _==_( { in: `1 > 1.0 && 1u > 1.0 && 1.0 > 1 && 1.0 > 1u && 1 > 1u && 1u > 1`, // opts: []Option{CrossTypeNumericComparisons(true)}, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, out: ` _&&_( _&&_( @@ -1948,7 +1948,7 @@ _==_( { in: `1 >= 1.0 && 1u >= 1.0 && 1.0 >= 1 && 1.0 >= 1u && 1 >= 1u && 1u >= 1`, // opts: []Option{CrossTypeNumericComparisons(true)}, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, out: ` _&&_( _&&_( @@ -1990,7 +1990,7 @@ _==_( in: `1 >= 1.0 && 1u >= 1.0 && 1.0 >= 1 && 1.0 >= 1u && 1 >= 1u && 1u >= 1`, // opts: []Option{CrossTypeNumericComparisons(true)}, // env: testEnv{variadicASTs: true}, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, out: ` _&&_( _>=_( @@ -2022,7 +2022,7 @@ _==_( { in: `[1].map(x, [x, x]).map(x, [x, x])`, outType: listType({ - elemType: listType({ elemType: listType({ elemType: INT64_TYPE }) }), + elemType: listType({ elemType: listType({ elemType: INT_CEL_TYPE }) }), }), out: `__comprehension__( // Variable @@ -2075,12 +2075,15 @@ _==_( }, { in: `values.filter(i, i.content != "").map(i, i.content)`, - outType: listType({ elemType: STRING_TYPE }), + outType: listType({ elemType: STRING_CEL_TYPE }), env: extendEnv(getDefaultEnv(), { idents: [ identDecl('values', { type: listType({ - elemType: mapType({ keyType: STRING_TYPE, valueType: STRING_TYPE }), + elemType: mapType({ + keyType: STRING_CEL_TYPE, + valueType: STRING_CEL_TYPE, + }), }), }), ], @@ -2135,7 +2138,7 @@ _==_( // TODO: Not sure the 3rd param for map is implemented // { // in: `[{}.map(c,c,c)]+[{}.map(c,c,c)]`, - // outType: listType({ elemType: listType({ elemType: BOOL_TYPE }) }), + // outType: listType({ elemType: listType({ elemType: BOOL_CEL_TYPE }) }), // out: `_+_( // [ // __comprehension__( @@ -2201,7 +2204,7 @@ _==_( // }), // ], // }), - // outType: BOOL_TYPE, + // outType: BOOL_CEL_TYPE, // out: `_==_( // type( // testAllTypes~google.api.expr.test.v1.proto3.TestAllTypes^testAllTypes.nestedgroup~google.api.expr.test.v1.proto3.TestAllTypes.NestedGroup.nested_id~int @@ -2216,14 +2219,14 @@ _==_( idents: [ identDecl('a', { type: mapType({ - keyType: STRING_TYPE, - valueType: STRING_TYPE, + keyType: STRING_CEL_TYPE, + valueType: STRING_CEL_TYPE, }), }), ], }), parserOptions: { enableOptionalSyntax: true }, - outType: optionalType(STRING_TYPE), + outType: optionalType(STRING_CEL_TYPE), out: `_?._( a~map(string, string)^a, "b" @@ -2236,14 +2239,14 @@ _==_( identDecl('optional_type', { type: ABSTRACT_OPTIONAL_TYPE }), identDecl('a', { type: mapType({ - keyType: STRING_TYPE, - valueType: STRING_TYPE, + keyType: STRING_CEL_TYPE, + valueType: STRING_CEL_TYPE, }), }), ], }), parserOptions: { enableOptionalSyntax: true }, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, out: `_==_( type( _?._( @@ -2261,14 +2264,14 @@ _==_( identDecl('a', { type: optionalType( mapType({ - keyType: STRING_TYPE, - valueType: STRING_TYPE, + keyType: STRING_CEL_TYPE, + valueType: STRING_CEL_TYPE, }) ), }), ], }), - outType: optionalType(STRING_TYPE), + outType: optionalType(STRING_CEL_TYPE), out: `a~optional_type(map(string, string))^a.b~optional_type(string)`, }, { @@ -2292,7 +2295,7 @@ _==_( }), ], }), - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, out: `a~optional_type(dyn)^a.dynamic~test-only~~bool`, }, { @@ -2302,7 +2305,7 @@ _==_( identDecl('a', { type: optionalType( mapType({ - keyType: STRING_TYPE, + keyType: STRING_CEL_TYPE, valueType: DYN_TYPE, }) ), @@ -2310,7 +2313,7 @@ _==_( ], }), parserOptions: { enableOptionalSyntax: true }, - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, out: `_?._( a~optional_type(map(string, dyn))^a, "b" @@ -2320,9 +2323,9 @@ _==_( in: `{?'key': {'a': 'b'}.?value}`, parserOptions: { enableOptionalSyntax: true }, outType: mapType({ - keyType: STRING_TYPE, + keyType: STRING_CEL_TYPE, // TODO: the go test has this as just a string type, but it seems like it should be optional. And the test passes with this change - valueType: optionalType(STRING_TYPE), + valueType: optionalType(STRING_CEL_TYPE), }), out: `{ ?"key"~string:_?._( @@ -2337,7 +2340,7 @@ _==_( in: `{?'key': {'a': 'b'}.?value}.key`, parserOptions: { enableOptionalSyntax: true }, // TODO: the go test has this as just a string type, but it seems like it should be optional. And the test passes with this change - outType: optionalType(STRING_TYPE), + outType: optionalType(STRING_CEL_TYPE), out: `{ ?"key"~string:_?._( { @@ -2355,17 +2358,17 @@ _==_( identDecl('a', { type: optionalType( mapType({ - keyType: STRING_TYPE, - valueType: STRING_TYPE, + keyType: STRING_CEL_TYPE, + valueType: STRING_CEL_TYPE, }) ), }), ], }), outType: mapType({ - keyType: STRING_TYPE, + keyType: STRING_CEL_TYPE, // TODO: the go test has this as just a string type, but it seems like it should be optional. And the test passes with this change - valueType: optionalType(STRING_TYPE), + valueType: optionalType(STRING_CEL_TYPE), }), out: `{ ?"nested"~string:a~optional_type(map(string, string))^a.b~optional_type(string) @@ -2386,14 +2389,14 @@ _==_( // env: extendEnv(getDefaultEnv(), { // idents: [ // identDecl('a', { - // type: optionalType(STRING_TYPE), + // type: optionalType(STRING_CEL_TYPE), // }), // identDecl('b', { - // type: optionalType(STRING_TYPE), + // type: optionalType(STRING_CEL_TYPE), // }), // ], // }), - // outType: listType({ elemType: STRING_TYPE }), + // outType: listType({ elemType: STRING_CEL_TYPE }), // out: `[ // a~optional_type(string)^a, // b~optional_type(string)^b, @@ -2445,7 +2448,7 @@ _==_( in: `null_int == null || null == null_int || null_msg == null || null == null_msg`, env: extendEnv(getDefaultEnv(), { idents: [ - identDecl('null_int', { type: nullableType(INT64_TYPE) }), + identDecl('null_int', { type: nullableType(INT_CEL_TYPE) }), identDecl('null_msg', { type: nullableType( messageType('google.api.expr.test.v1.proto2.TestAllTypes') @@ -2453,13 +2456,13 @@ _==_( }), ], }), - outType: BOOL_TYPE, + outType: BOOL_CEL_TYPE, }, // TODO: nullables // { // in: `NotAMessage{}`, // env: extendEnv(getDefaultEnv(), { - // idents: [identDecl('NotAMessage', { type: nullableType(INT64_TYPE) })], + // idents: [identDecl('NotAMessage', { type: nullableType(INT_CEL_TYPE) })], // }), // err: `ERROR: :1:12: 'wrapper(int)' is not a type // | NotAMessage{} diff --git a/packages/cel/src/lib/checker/checker.ts b/packages/cel/src/lib/checker/checker.ts index 25e9055..b64cf5b 100644 --- a/packages/cel/src/lib/checker/checker.ts +++ b/packages/cel/src/lib/checker/checker.ts @@ -26,17 +26,17 @@ import { } from '../common/decls/ident-decl'; import { Errors } from '../common/errors'; import { formatCELType } from '../common/format'; -import { BOOL_TYPE } from '../common/types/bool'; -import { BYTES_TYPE } from '../common/types/bytes'; +import { BOOL_CEL_TYPE } from '../common/types/bool'; +import { BYTES_CEL_TYPE } from '../common/types/bytes'; import { unwrapCallExpr } from '../common/types/call'; import { unwrapComprehensionExpr } from '../common/types/comprehension'; import { isConstExpr, unwrapConstExpr } from '../common/types/constant'; -import { DOUBLE_TYPE } from '../common/types/double'; +import { DOUBLE_CEL_TYPE } from '../common/types/double'; import { DYN_TYPE, isDynType } from '../common/types/dyn'; import { ERROR_TYPE } from '../common/types/error'; import { functionType } from '../common/types/function'; import { unwrapIdentExpr } from '../common/types/ident'; -import { INT64_TYPE } from '../common/types/int'; +import { INT_CEL_TYPE } from '../common/types/int'; import { listType, unwrapCreateList } from '../common/types/list'; import { mapType } from '../common/types/map'; import { NULL_TYPE } from '../common/types/null'; @@ -46,10 +46,10 @@ import { optionalType, } from '../common/types/optional'; import { unwrapSelectExpr } from '../common/types/select'; -import { STRING_TYPE } from '../common/types/string'; +import { STRING_CEL_TYPE } from '../common/types/string'; import { unwrapStructExpr } from '../common/types/struct'; import { typeParamType } from '../common/types/type-param'; -import { UINT64_TYPE } from '../common/types/uint'; +import { UINT_CEL_TYPE } from '../common/types/uint'; import { isDynTypeOrErrorType } from '../common/types/utils'; import { DURATION_TYPE, @@ -167,25 +167,25 @@ export class CELChecker { const constant = unwrapConstExpr(expr)!; switch (constant.constantKind.case) { case 'boolValue': - this.setType(expr.id, BOOL_TYPE); + this.setType(expr.id, BOOL_CEL_TYPE); break; case 'bytesValue': - this.setType(expr.id, BYTES_TYPE); + this.setType(expr.id, BYTES_CEL_TYPE); break; case 'doubleValue': - this.setType(expr.id, DOUBLE_TYPE); + this.setType(expr.id, DOUBLE_CEL_TYPE); break; case 'int64Value': - this.setType(expr.id, INT64_TYPE); + this.setType(expr.id, INT_CEL_TYPE); break; case 'nullValue': this.setType(expr.id, NULL_TYPE); break; case 'stringValue': - this.setType(expr.id, STRING_TYPE); + this.setType(expr.id, STRING_CEL_TYPE); break; case 'uint64Value': - this.setType(expr.id, UINT64_TYPE); + this.setType(expr.id, UINT_CEL_TYPE); break; case 'durationValue': this.setType(expr.id, DURATION_TYPE); @@ -253,7 +253,7 @@ export class CELChecker { false ); if (sel.testOnly) { - resultType = BOOL_TYPE; + resultType = BOOL_CEL_TYPE; } this.setType(expr.id, resultType); return expr; @@ -618,7 +618,7 @@ export class CELChecker { this.env.addIdent(identDecl(comp.iterVar, { type: varType })); // Check the variable references in the condition and step. this.checkExpr(comp.loopCondition); - this._assertType(comp.loopCondition!, BOOL_TYPE); + this._assertType(comp.loopCondition!, BOOL_CEL_TYPE); this.checkExpr(comp.loopStep); this._assertType(comp.loopStep!, accuType!); // Exit the loop's block scope before checking the result. diff --git a/packages/cel/src/lib/checker/env.spec.ts b/packages/cel/src/lib/checker/env.spec.ts index eb65376..a08fc01 100644 --- a/packages/cel/src/lib/checker/env.spec.ts +++ b/packages/cel/src/lib/checker/env.spec.ts @@ -6,7 +6,7 @@ import { STANDARD_FUNCTION_DECLARATIONS, STANDARD_IDENT_DECLARATIONS, } from '../common/standard'; -import { BOOL_TYPE } from '../common/types/bool'; +import { BOOL_CEL_TYPE } from '../common/types/bool'; import { DYN_TYPE } from '../common/types/dyn'; import { TYPE_TYPE } from '../common/types/type'; import { CheckerEnv } from './env'; @@ -27,7 +27,7 @@ describe('CheckerEnv', () => { overloadDecl({ isInstanceFunction: false, params: [DYN_TYPE], - resultType: BOOL_TYPE, + resultType: BOOL_CEL_TYPE, }), ], }) diff --git a/packages/cel/src/lib/checker/env.ts b/packages/cel/src/lib/checker/env.ts index 63ad767..60de410 100644 --- a/packages/cel/src/lib/checker/env.ts +++ b/packages/cel/src/lib/checker/env.ts @@ -11,7 +11,7 @@ import { identDecl } from '../common/decls/ident-decl'; import { TypeProvider } from '../common/ref/provider'; import { DYN_TYPE } from '../common/types/dyn'; import { unwrapEnumValue } from '../common/types/enum'; -import { INT64_TYPE, int64Constant } from '../common/types/int'; +import { INT_CEL_TYPE, int64Constant } from '../common/types/int'; import { LESS_DOUBLE_INT64_OVERLOAD } from '../overloads'; import { STANDARD_MACRO_DECLARATIONS } from '../parser/macros'; import { @@ -190,7 +190,7 @@ export class CheckerEnv { if (!(enumValue instanceof Error)) { const unwrappedEnum = unwrapEnumValue(enumValue)!; const decl = identDecl(candidate, { - type: INT64_TYPE, + type: INT_CEL_TYPE, value: int64Constant(BigInt(unwrappedEnum.value)), }); this.#declarations.addIdent(decl); diff --git a/packages/cel/src/lib/common/pb/proto-type-registry.ts b/packages/cel/src/lib/common/pb/proto-type-registry.ts index f998f9a..5001dc4 100644 --- a/packages/cel/src/lib/common/pb/proto-type-registry.ts +++ b/packages/cel/src/lib/common/pb/proto-type-registry.ts @@ -21,19 +21,19 @@ import { import { formatCELType } from '../format'; import { FieldType } from '../ref/field-type'; import { STANDARD_DESCRIPTORS } from '../standard'; -import { BOOL_TYPE, isBoolValue } from '../types/bool'; -import { BYTES_TYPE } from '../types/bytes'; -import { DOUBLE_TYPE } from '../types/double'; +import { BOOL_CEL_TYPE, isBoolValue } from '../types/bool'; +import { BYTES_CEL_TYPE } from '../types/bytes'; +import { DOUBLE_CEL_TYPE } from '../types/double'; import { enumValue } from '../types/enum'; -import { INT64_TYPE } from '../types/int'; +import { INT_CEL_TYPE } from '../types/int'; import { LIST_TYPE } from '../types/list'; import { MAP_TYPE } from '../types/map'; import { messageType } from '../types/message'; import { NULL_TYPE } from '../types/null'; -import { STRING_TYPE } from '../types/string'; +import { STRING_CEL_TYPE } from '../types/string'; import { isZeroValue } from '../types/traits/zeroer'; import { TYPE_TYPE } from '../types/type'; -import { UINT64_TYPE } from '../types/uint'; +import { UINT_CEL_TYPE } from '../types/uint'; import { getFieldDescriptorType } from '../types/utils'; import { valueOf } from '../types/value'; import { DURATION_TYPE, TIMESTAMP_TYPE } from '../types/wkt'; @@ -51,18 +51,18 @@ export class ProtoTypeRegistry implements TypeRegistry { } } this.registerType( - BOOL_TYPE, - BYTES_TYPE, - DOUBLE_TYPE, + BOOL_CEL_TYPE, + BYTES_CEL_TYPE, + DOUBLE_CEL_TYPE, DURATION_TYPE, - INT64_TYPE, + INT_CEL_TYPE, LIST_TYPE, MAP_TYPE, NULL_TYPE, - STRING_TYPE, + STRING_CEL_TYPE, TIMESTAMP_TYPE, TYPE_TYPE, - UINT64_TYPE + UINT_CEL_TYPE ); for (const [k, v] of typeMap) { this.#refTypeMap.set(k, v); @@ -139,7 +139,7 @@ export class ProtoTypeRegistry implements TypeRegistry { ); } return new FieldType( - INT64_TYPE, + INT_CEL_TYPE, (obj) => { const zero = desc.values.find((v) => v.number === 0); return obj.kind.value === zero?.name; diff --git a/packages/cel/src/lib/common/ref/reference.ts b/packages/cel/src/lib/common/ref/reference.ts new file mode 100644 index 0000000..3140b62 --- /dev/null +++ b/packages/cel/src/lib/common/ref/reference.ts @@ -0,0 +1,115 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { isFunction } from '@bearclaw/is'; +import { Type } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb'; +import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb'; +import { NativeType } from '../types/native'; +import { Trait } from '../types/traits/trait'; + +export enum RefTypeEnum { + BOOL = 'bool', + BYTES = 'bytes', + DOUBLE = 'double', + DURATION = 'google.protobuf.Duration', + ERR = 'error', + INT = 'int', + LIST = 'list', + MAP = 'map', + NULL = 'null_type', + OBJECT = 'object', + STRING = 'string', + TIMESTAMP = 'google.protobuf.Timestamp', + TYPE = 'type', + UINT = 'uint', + UNKNOWN = 'unknown', +} + +/** + * Type interface indicate the name of a given type. + */ +export interface RefType { + /** + * CelType returns the CEL type of the type. + */ + celType(): Type; + /** + * HasTrait returns whether the type has a given trait associated with it. + * + * See common/types/traits/traits.ts for a list of supported traits. + */ + hasTrait(trait: Trait): boolean; + + /** + * TypeName returns the qualified type name of the type. + * + * The type name is also used as the type's identifier name at type-check and + * interpretation time. + */ + typeName(): string; +} + +export function isRefType(value: any): value is RefType { + return isFunction(value.hasTrait) && isFunction(value.typeName); +} + +/** + * Val interface defines the functions supported by all expression values. + * Val implementations may specialize the behavior of the value through the + * addition of traits. + */ +export interface RefVal { + /** + * CelValue returns the CEL value of the value. + */ + celValue(): Value; + + /** + * ConvertToNative converts the Value to a native Go struct according to the + * reflected type description, or error if the conversion is not feasible. + * + * The ConvertToNative method is intended to be used to support conversion + * between CEL types and native types during object creation expressions or + * by clients who need to adapt the, returned CEL value into an equivalent TS + * value instance. + * + * When implementing or using ConvertToNative, the following guidelines apply: + * - Use ConvertToNative when marshalling CEL evaluation results to native + * types. + * - Do not use ConvertToNative within CEL extension functions. + * - Document whether your implementation supports non-CEL field types, such + * as TS or Protobuf. + */ + convertToNative(type: NativeType): any; + + /** + * ConvertToType supports type conversions between CEL value types supported + * by the expression language. + */ + convertToType(type: RefType): RefVal; + + /** + * Equal returns true if the `other` value has the same type and content as + * the implementing struct. + */ + equal(other: RefVal): RefVal; + + /** + * Type returns the TypeValue of the value. + */ + type(): RefType; + + /** + * Value returns the raw value of the instance which may not be directly + * compatible with the expression language types. + */ + value(): any; +} + +export function isRefVal(value: any): value is RefVal { + return ( + isFunction(value.convertToNative) && + isFunction(value.convertToType) && + isFunction(value.equal) && + isFunction(value.type) && + isFunction(value.value) + ); +} diff --git a/packages/cel/src/lib/common/standard.ts b/packages/cel/src/lib/common/standard.ts index 1fb4e4d..22ed657 100644 --- a/packages/cel/src/lib/common/standard.ts +++ b/packages/cel/src/lib/common/standard.ts @@ -234,18 +234,18 @@ import { import { functionDecl } from './decls/function-decl'; import { identDecl } from './decls/ident-decl'; import { ABSTRACT_TYPE_TYPE } from './types/abstract'; -import { BOOL_TYPE } from './types/bool'; -import { BYTES_TYPE } from './types/bytes'; -import { DOUBLE_TYPE } from './types/double'; +import { BOOL_CEL_TYPE } from './types/bool'; +import { BYTES_CEL_TYPE } from './types/bytes'; +import { DOUBLE_CEL_TYPE } from './types/double'; import { DYN_TYPE } from './types/dyn'; -import { INT64_TYPE } from './types/int'; +import { INT_CEL_TYPE } from './types/int'; import { listType } from './types/list'; import { mapType } from './types/map'; import { NULL_TYPE } from './types/null'; -import { STRING_TYPE } from './types/string'; +import { STRING_CEL_TYPE } from './types/string'; import { typeType } from './types/type'; import { typeParamType } from './types/type-param'; -import { UINT64_TYPE } from './types/uint'; +import { UINT_CEL_TYPE } from './types/uint'; import { DURATION_TYPE, TIMESTAMP_TYPE } from './types/wkt'; export const STANDARD_DESCRIPTORS: ( @@ -274,15 +274,15 @@ export const STANDARD_DESCRIPTORS: ( ]; export const STANDARD_IDENT_DECLARATIONS: Decl[] = [ - identDecl('bool', { type: typeType(BOOL_TYPE) }), - identDecl('bytes', { type: typeType(BYTES_TYPE) }), - identDecl('double', { type: typeType(DOUBLE_TYPE) }), + identDecl('bool', { type: typeType(BOOL_CEL_TYPE) }), + identDecl('bytes', { type: typeType(BYTES_CEL_TYPE) }), + identDecl('double', { type: typeType(DOUBLE_CEL_TYPE) }), identDecl('duration', { type: typeType(DURATION_TYPE) }), identDecl('dyn', { type: typeType(DYN_TYPE) }), - identDecl('int', { type: typeType(INT64_TYPE) }), - identDecl('string', { type: typeType(STRING_TYPE) }), + identDecl('int', { type: typeType(INT_CEL_TYPE) }), + identDecl('string', { type: typeType(STRING_CEL_TYPE) }), identDecl('timestamp', { type: typeType(TIMESTAMP_TYPE) }), - identDecl('uint', { type: typeType(UINT64_TYPE) }), + identDecl('uint', { type: typeType(UINT_CEL_TYPE) }), identDecl('list', { type: typeType(listType({ elemType: DYN_TYPE })) }), identDecl('map', { type: typeType(mapType({ keyType: DYN_TYPE, valueType: DYN_TYPE })), @@ -306,7 +306,7 @@ export const CONDITIONAL_FUNCTION_DECL = functionDecl(CONDITIONAL_OPERATOR, { overloads: [ { overloadId: CONDITIONAL_OVERLOAD, - params: [BOOL_TYPE, paramA, paramA], + params: [BOOL_CEL_TYPE, paramA, paramA], resultType: paramA, typeParams: typeParamAList, }, @@ -316,8 +316,8 @@ export const LOGICAL_AND_FUNCTION_DECL = functionDecl(LOGICAL_AND_OPERATOR, { overloads: [ { overloadId: LOGICAL_AND_OVERLOAD, - params: [BOOL_TYPE, BOOL_TYPE], - resultType: BOOL_TYPE, + params: [BOOL_CEL_TYPE, BOOL_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, ], }); @@ -325,8 +325,8 @@ export const LOGICAL_OR_FUNCTION_DECL = functionDecl(LOGICAL_OR_OPERATOR, { overloads: [ { overloadId: LOGICAL_OR_OVERLOAD, - params: [BOOL_TYPE, BOOL_TYPE], - resultType: BOOL_TYPE, + params: [BOOL_CEL_TYPE, BOOL_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, ], }); @@ -334,8 +334,8 @@ export const LOGICAL_NOT_FUNCTION_DECL = functionDecl(LOGICAL_NOT_OPERATOR, { overloads: [ { overloadId: LOGICAL_NOT_OVERLOAD, - params: [BOOL_TYPE], - resultType: BOOL_TYPE, + params: [BOOL_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, ], }); @@ -347,8 +347,8 @@ export const NOT_STRICTLY_FALSE_FUNCTION_DECL = functionDecl( overloads: [ { overloadId: NOT_STRICTLY_FALSE_OVERLOAD, - params: [BOOL_TYPE], - resultType: BOOL_TYPE, + params: [BOOL_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, ], } @@ -360,7 +360,7 @@ export const EQUALS_FUNCTION_DECL = functionDecl(EQUALS_OPERATOR, { { overloadId: EQUALS_OVERLOAD, params: [paramA, paramB], - resultType: BOOL_TYPE, + resultType: BOOL_CEL_TYPE, typeParams: typeParamABList, }, ], @@ -370,7 +370,7 @@ export const NOT_EQUALS_FUNCTION_DECL = functionDecl(NOT_EQUALS_OPERATOR, { { overloadId: NOT_EQUALS_OVERLOAD, params: [paramA, paramA], - resultType: BOOL_TYPE, + resultType: BOOL_CEL_TYPE, typeParams: typeParamABList, }, ], @@ -381,13 +381,13 @@ export const ADD_FUNCTION_DECL = functionDecl(ADD_OPERATOR, { overloads: [ { overloadId: ADD_BYTES_OVERLOAD, - params: [BYTES_TYPE, BYTES_TYPE], - resultType: BYTES_TYPE, + params: [BYTES_CEL_TYPE, BYTES_CEL_TYPE], + resultType: BYTES_CEL_TYPE, }, { overloadId: ADD_DOUBLE_OVERLOAD, - params: [DOUBLE_TYPE, DOUBLE_TYPE], - resultType: DOUBLE_TYPE, + params: [DOUBLE_CEL_TYPE, DOUBLE_CEL_TYPE], + resultType: DOUBLE_CEL_TYPE, }, { overloadId: ADD_DURATION_DURATION_OVERLOAD, @@ -406,8 +406,8 @@ export const ADD_FUNCTION_DECL = functionDecl(ADD_OPERATOR, { }, { overloadId: ADD_INT64_OVERLOAD, - params: [INT64_TYPE, INT64_TYPE], - resultType: INT64_TYPE, + params: [INT_CEL_TYPE, INT_CEL_TYPE], + resultType: INT_CEL_TYPE, }, { overloadId: ADD_LIST_OVERLOAD, @@ -417,13 +417,13 @@ export const ADD_FUNCTION_DECL = functionDecl(ADD_OPERATOR, { }, { overloadId: ADD_STRING_OVERLOAD, - params: [STRING_TYPE, STRING_TYPE], - resultType: STRING_TYPE, + params: [STRING_CEL_TYPE, STRING_CEL_TYPE], + resultType: STRING_CEL_TYPE, }, { overloadId: ADD_UINT64_OVERLOAD, - params: [UINT64_TYPE, UINT64_TYPE], - resultType: UINT64_TYPE, + params: [UINT_CEL_TYPE, UINT_CEL_TYPE], + resultType: UINT_CEL_TYPE, }, ], }); @@ -431,18 +431,18 @@ export const DIVIDE_FUNCTION_DECL = functionDecl(DIVIDE_OPERATOR, { overloads: [ { overloadId: DIVIDE_DOUBLE_OVERLOAD, - params: [DOUBLE_TYPE, DOUBLE_TYPE], - resultType: DOUBLE_TYPE, + params: [DOUBLE_CEL_TYPE, DOUBLE_CEL_TYPE], + resultType: DOUBLE_CEL_TYPE, }, { overloadId: DIVIDE_INT64_OVERLOAD, - params: [INT64_TYPE, INT64_TYPE], - resultType: INT64_TYPE, + params: [INT_CEL_TYPE, INT_CEL_TYPE], + resultType: INT_CEL_TYPE, }, { overloadId: DIVIDE_UINT64_OVERLOAD, - params: [UINT64_TYPE, UINT64_TYPE], - resultType: UINT64_TYPE, + params: [UINT_CEL_TYPE, UINT_CEL_TYPE], + resultType: UINT_CEL_TYPE, }, ], }); @@ -450,13 +450,13 @@ export const MODULO_FUNCTION_DECL = functionDecl(MODULO_OPERATOR, { overloads: [ { overloadId: MODULO_INT64_OVERLOAD, - params: [INT64_TYPE, INT64_TYPE], - resultType: INT64_TYPE, + params: [INT_CEL_TYPE, INT_CEL_TYPE], + resultType: INT_CEL_TYPE, }, { overloadId: MODULO_UINT64_OVERLOAD, - params: [UINT64_TYPE, UINT64_TYPE], - resultType: UINT64_TYPE, + params: [UINT_CEL_TYPE, UINT_CEL_TYPE], + resultType: UINT_CEL_TYPE, }, ], }); @@ -464,18 +464,18 @@ export const MULTIPLY_FUNCTION_DECL = functionDecl(MULTIPLY_OPERATOR, { overloads: [ { overloadId: MULTIPLY_DOUBLE_OVERLOAD, - params: [DOUBLE_TYPE, DOUBLE_TYPE], - resultType: DOUBLE_TYPE, + params: [DOUBLE_CEL_TYPE, DOUBLE_CEL_TYPE], + resultType: DOUBLE_CEL_TYPE, }, { overloadId: MULTIPLY_INT64_OVERLOAD, - params: [INT64_TYPE, INT64_TYPE], - resultType: INT64_TYPE, + params: [INT_CEL_TYPE, INT_CEL_TYPE], + resultType: INT_CEL_TYPE, }, { overloadId: MULTIPLY_UINT64_OVERLOAD, - params: [UINT64_TYPE, UINT64_TYPE], - resultType: UINT64_TYPE, + params: [UINT_CEL_TYPE, UINT_CEL_TYPE], + resultType: UINT_CEL_TYPE, }, ], }); @@ -483,13 +483,13 @@ export const NEGATE_FUNCTION_DECL = functionDecl(NEGATE_OPERATOR, { overloads: [ { overloadId: NEGATE_DOUBLE_OVERLOAD, - params: [DOUBLE_TYPE], - resultType: DOUBLE_TYPE, + params: [DOUBLE_CEL_TYPE], + resultType: DOUBLE_CEL_TYPE, }, { overloadId: NEGATE_INT64_OVERLOAD, - params: [INT64_TYPE], - resultType: INT64_TYPE, + params: [INT_CEL_TYPE], + resultType: INT_CEL_TYPE, }, ], }); @@ -497,18 +497,18 @@ export const SUBTRACT_FUNCTION_DECL = functionDecl(SUBTRACT_OPERATOR, { overloads: [ { overloadId: SUBTRACT_DOUBLE_OVERLOAD, - params: [DOUBLE_TYPE, DOUBLE_TYPE], - resultType: DOUBLE_TYPE, + params: [DOUBLE_CEL_TYPE, DOUBLE_CEL_TYPE], + resultType: DOUBLE_CEL_TYPE, }, { overloadId: SUBTRACT_INT64_OVERLOAD, - params: [INT64_TYPE, INT64_TYPE], - resultType: INT64_TYPE, + params: [INT_CEL_TYPE, INT_CEL_TYPE], + resultType: INT_CEL_TYPE, }, { overloadId: SUBTRACT_UINT64_OVERLOAD, - params: [UINT64_TYPE, UINT64_TYPE], - resultType: UINT64_TYPE, + params: [UINT_CEL_TYPE, UINT_CEL_TYPE], + resultType: UINT_CEL_TYPE, }, { overloadId: SUBTRACT_DURATION_DURATION_OVERLOAD, @@ -533,73 +533,73 @@ export const LESS_FUNCTION_DECL = functionDecl(LESS_OPERATOR, { overloads: [ { overloadId: LESS_BOOL_OVERLOAD, - params: [BOOL_TYPE, BOOL_TYPE], - resultType: BOOL_TYPE, + params: [BOOL_CEL_TYPE, BOOL_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: LESS_INT64_OVERLOAD, - params: [INT64_TYPE, INT64_TYPE], - resultType: BOOL_TYPE, + params: [INT_CEL_TYPE, INT_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: LESS_INT64_DOUBLE_OVERLOAD, - params: [INT64_TYPE, DOUBLE_TYPE], - resultType: BOOL_TYPE, + params: [INT_CEL_TYPE, DOUBLE_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: LESS_INT64_UINT64_OVERLOAD, - params: [INT64_TYPE, UINT64_TYPE], - resultType: BOOL_TYPE, + params: [INT_CEL_TYPE, UINT_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: LESS_UINT64_OVERLOAD, - params: [UINT64_TYPE, UINT64_TYPE], - resultType: BOOL_TYPE, + params: [UINT_CEL_TYPE, UINT_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: LESS_UINT64_DOUBLE_OVERLOAD, - params: [UINT64_TYPE, DOUBLE_TYPE], - resultType: BOOL_TYPE, + params: [UINT_CEL_TYPE, DOUBLE_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: LESS_UINT64_INT64_OVERLOAD, - params: [UINT64_TYPE, INT64_TYPE], - resultType: BOOL_TYPE, + params: [UINT_CEL_TYPE, INT_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: LESS_DOUBLE_OVERLOAD, - params: [DOUBLE_TYPE, DOUBLE_TYPE], - resultType: BOOL_TYPE, + params: [DOUBLE_CEL_TYPE, DOUBLE_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: LESS_DOUBLE_INT64_OVERLOAD, - params: [DOUBLE_TYPE, INT64_TYPE], - resultType: BOOL_TYPE, + params: [DOUBLE_CEL_TYPE, INT_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: LESS_DOUBLE_UINT64_OVERLOAD, - params: [DOUBLE_TYPE, UINT64_TYPE], - resultType: BOOL_TYPE, + params: [DOUBLE_CEL_TYPE, UINT_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: LESS_STRING_OVERLOAD, - params: [STRING_TYPE, STRING_TYPE], - resultType: BOOL_TYPE, + params: [STRING_CEL_TYPE, STRING_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: LESS_BYTES_OVERLOAD, - params: [BYTES_TYPE, BYTES_TYPE], - resultType: BOOL_TYPE, + params: [BYTES_CEL_TYPE, BYTES_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: LESS_TIMESTAMP_OVERLOAD, params: [TIMESTAMP_TYPE, TIMESTAMP_TYPE], - resultType: BOOL_TYPE, + resultType: BOOL_CEL_TYPE, }, { overloadId: LESS_DURATION_OVERLOAD, params: [DURATION_TYPE, DURATION_TYPE], - resultType: BOOL_TYPE, + resultType: BOOL_CEL_TYPE, }, ], }); @@ -607,68 +607,68 @@ export const LESS_EQUALS_FUNCTION_DECL = functionDecl(LESS_EQUALS_OPERATOR, { overloads: [ { overloadId: LESS_EQUALS_INT64_OVERLOAD, - params: [INT64_TYPE, INT64_TYPE], - resultType: BOOL_TYPE, + params: [INT_CEL_TYPE, INT_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: LESS_EQUALS_INT64_DOUBLE_OVERLOAD, - params: [INT64_TYPE, DOUBLE_TYPE], - resultType: BOOL_TYPE, + params: [INT_CEL_TYPE, DOUBLE_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: LESS_EQUALS_INT64_UINT64_OVERLOAD, - params: [INT64_TYPE, UINT64_TYPE], - resultType: BOOL_TYPE, + params: [INT_CEL_TYPE, UINT_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: LESS_EQUALS_UINT64_OVERLOAD, - params: [UINT64_TYPE, UINT64_TYPE], - resultType: BOOL_TYPE, + params: [UINT_CEL_TYPE, UINT_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: LESS_EQUALS_UINT64_DOUBLE_OVERLOAD, - params: [UINT64_TYPE, DOUBLE_TYPE], - resultType: BOOL_TYPE, + params: [UINT_CEL_TYPE, DOUBLE_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: LESS_EQUALS_UINT64_INT64_OVERLOAD, - params: [UINT64_TYPE, INT64_TYPE], - resultType: BOOL_TYPE, + params: [UINT_CEL_TYPE, INT_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: LESS_EQUALS_DOUBLE_OVERLOAD, - params: [DOUBLE_TYPE, DOUBLE_TYPE], - resultType: BOOL_TYPE, + params: [DOUBLE_CEL_TYPE, DOUBLE_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: LESS_EQUALS_DOUBLE_INT64_OVERLOAD, - params: [DOUBLE_TYPE, INT64_TYPE], - resultType: BOOL_TYPE, + params: [DOUBLE_CEL_TYPE, INT_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: LESS_EQUALS_DOUBLE_UINT64_OVERLOAD, - params: [DOUBLE_TYPE, UINT64_TYPE], - resultType: BOOL_TYPE, + params: [DOUBLE_CEL_TYPE, UINT_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: LESS_EQUALS_STRING_OVERLOAD, - params: [STRING_TYPE, STRING_TYPE], - resultType: BOOL_TYPE, + params: [STRING_CEL_TYPE, STRING_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: LESS_EQUALS_BYTES_OVERLOAD, - params: [BYTES_TYPE, BYTES_TYPE], - resultType: BOOL_TYPE, + params: [BYTES_CEL_TYPE, BYTES_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: LESS_EQUALS_DURATION_OVERLOAD, params: [DURATION_TYPE, DURATION_TYPE], - resultType: BOOL_TYPE, + resultType: BOOL_CEL_TYPE, }, { overloadId: LESS_EQUALS_TIMESTAMP_OVERLOAD, params: [TIMESTAMP_TYPE, TIMESTAMP_TYPE], - resultType: BOOL_TYPE, + resultType: BOOL_CEL_TYPE, }, ], }); @@ -676,73 +676,73 @@ export const GREATER_FUNCTION_DECL = functionDecl(GREATER_OPERATOR, { overloads: [ { overloadId: GREATER_BOOL_OVERLOAD, - params: [BOOL_TYPE, BOOL_TYPE], - resultType: BOOL_TYPE, + params: [BOOL_CEL_TYPE, BOOL_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_INT64_OVERLOAD, - params: [INT64_TYPE, INT64_TYPE], - resultType: BOOL_TYPE, + params: [INT_CEL_TYPE, INT_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_INT64_DOUBLE_OVERLOAD, - params: [INT64_TYPE, DOUBLE_TYPE], - resultType: BOOL_TYPE, + params: [INT_CEL_TYPE, DOUBLE_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_INT64_UINT64_OVERLOAD, - params: [INT64_TYPE, UINT64_TYPE], - resultType: BOOL_TYPE, + params: [INT_CEL_TYPE, UINT_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_UINT64_OVERLOAD, - params: [UINT64_TYPE, UINT64_TYPE], - resultType: BOOL_TYPE, + params: [UINT_CEL_TYPE, UINT_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_UINT64_DOUBLE_OVERLOAD, - params: [UINT64_TYPE, DOUBLE_TYPE], - resultType: BOOL_TYPE, + params: [UINT_CEL_TYPE, DOUBLE_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_UINT64_INT64_OVERLOAD, - params: [UINT64_TYPE, INT64_TYPE], - resultType: BOOL_TYPE, + params: [UINT_CEL_TYPE, INT_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_DOUBLE_OVERLOAD, - params: [DOUBLE_TYPE, DOUBLE_TYPE], - resultType: BOOL_TYPE, + params: [DOUBLE_CEL_TYPE, DOUBLE_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_DOUBLE_INT64_OVERLOAD, - params: [DOUBLE_TYPE, INT64_TYPE], - resultType: BOOL_TYPE, + params: [DOUBLE_CEL_TYPE, INT_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_DOUBLE_UINT64_OVERLOAD, - params: [DOUBLE_TYPE, UINT64_TYPE], - resultType: BOOL_TYPE, + params: [DOUBLE_CEL_TYPE, UINT_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_STRING_OVERLOAD, - params: [STRING_TYPE, STRING_TYPE], - resultType: BOOL_TYPE, + params: [STRING_CEL_TYPE, STRING_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_BYTES_OVERLOAD, - params: [BYTES_TYPE, BYTES_TYPE], - resultType: BOOL_TYPE, + params: [BYTES_CEL_TYPE, BYTES_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_TIMESTAMP_OVERLOAD, params: [TIMESTAMP_TYPE, TIMESTAMP_TYPE], - resultType: BOOL_TYPE, + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_DURATION_OVERLOAD, params: [DURATION_TYPE, DURATION_TYPE], - resultType: BOOL_TYPE, + resultType: BOOL_CEL_TYPE, }, ], }); @@ -752,73 +752,73 @@ export const GREATER_EQUALS_FUNCTION_DECL = functionDecl( overloads: [ { overloadId: GREATER_EQUALS_BOOL_OVERLOAD, - params: [BOOL_TYPE, BOOL_TYPE], - resultType: BOOL_TYPE, + params: [BOOL_CEL_TYPE, BOOL_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_EQUALS_INT64_OVERLOAD, - params: [INT64_TYPE, INT64_TYPE], - resultType: BOOL_TYPE, + params: [INT_CEL_TYPE, INT_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_EQUALS_INT64_DOUBLE_OVERLOAD, - params: [INT64_TYPE, DOUBLE_TYPE], - resultType: BOOL_TYPE, + params: [INT_CEL_TYPE, DOUBLE_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_EQUALS_INT64_UINT64_OVERLOAD, - params: [INT64_TYPE, UINT64_TYPE], - resultType: BOOL_TYPE, + params: [INT_CEL_TYPE, UINT_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_EQUALS_UINT64_OVERLOAD, - params: [UINT64_TYPE, UINT64_TYPE], - resultType: BOOL_TYPE, + params: [UINT_CEL_TYPE, UINT_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_EQUALS_UINT64_DOUBLE_OVERLOAD, - params: [UINT64_TYPE, DOUBLE_TYPE], - resultType: BOOL_TYPE, + params: [UINT_CEL_TYPE, DOUBLE_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_EQUALS_UINT64_INT64_OVERLOAD, - params: [UINT64_TYPE, INT64_TYPE], - resultType: BOOL_TYPE, + params: [UINT_CEL_TYPE, INT_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_EQUALS_DOUBLE_OVERLOAD, - params: [DOUBLE_TYPE, DOUBLE_TYPE], - resultType: BOOL_TYPE, + params: [DOUBLE_CEL_TYPE, DOUBLE_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_EQUALS_DOUBLE_INT64_OVERLOAD, - params: [DOUBLE_TYPE, INT64_TYPE], - resultType: BOOL_TYPE, + params: [DOUBLE_CEL_TYPE, INT_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_EQUALS_DOUBLE_UINT64_OVERLOAD, - params: [DOUBLE_TYPE, UINT64_TYPE], - resultType: BOOL_TYPE, + params: [DOUBLE_CEL_TYPE, UINT_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_EQUALS_STRING_OVERLOAD, - params: [STRING_TYPE, STRING_TYPE], - resultType: BOOL_TYPE, + params: [STRING_CEL_TYPE, STRING_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_EQUALS_BYTES_OVERLOAD, - params: [BYTES_TYPE, BYTES_TYPE], - resultType: BOOL_TYPE, + params: [BYTES_CEL_TYPE, BYTES_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_EQUALS_DURATION_OVERLOAD, params: [DURATION_TYPE, DURATION_TYPE], - resultType: BOOL_TYPE, + resultType: BOOL_CEL_TYPE, }, { overloadId: GREATER_EQUALS_TIMESTAMP_OVERLOAD, params: [TIMESTAMP_TYPE, TIMESTAMP_TYPE], - resultType: BOOL_TYPE, + resultType: BOOL_CEL_TYPE, }, ], } @@ -835,7 +835,7 @@ export const INDEX_FUNCTION_DECL = functionDecl(INDEX_OPERATOR, { }, { overloadId: INDEX_LIST_OVERLOAD, - params: [listOfA, INT64_TYPE], + params: [listOfA, INT_CEL_TYPE], resultType: paramA, typeParams: typeParamAList, }, @@ -848,13 +848,13 @@ export const IN_FUNCTION_DECL = functionDecl(IN_OPERATOR, { { overloadId: IN_LIST_OVERLOAD, params: [paramA, listOfA], - resultType: BOOL_TYPE, + resultType: BOOL_CEL_TYPE, typeParams: typeParamAList, }, { overloadId: IN_MAP_OVERLOAD, params: [paramA, mapOfAB], - resultType: BOOL_TYPE, + resultType: BOOL_CEL_TYPE, typeParams: typeParamABList, }, ], @@ -863,50 +863,50 @@ export const SIZE_FUNCTION_DECL = functionDecl(SIZE_OVERLOAD, { overloads: [ { overloadId: SIZE_BYTES_OVERLOAD, - params: [BYTES_TYPE], - resultType: INT64_TYPE, + params: [BYTES_CEL_TYPE], + resultType: INT_CEL_TYPE, }, { overloadId: SIZE_BYTES_INST_OVERLOAD, - params: [BYTES_TYPE], - resultType: INT64_TYPE, + params: [BYTES_CEL_TYPE], + resultType: INT_CEL_TYPE, isInstanceFunction: true, }, { overloadId: SIZE_LIST_OVERLOAD, params: [listOfA], - resultType: INT64_TYPE, + resultType: INT_CEL_TYPE, typeParams: typeParamAList, }, { overloadId: SIZE_LIST_INST_OVERLOAD, params: [listOfA], - resultType: INT64_TYPE, + resultType: INT_CEL_TYPE, typeParams: typeParamAList, isInstanceFunction: true, }, { overloadId: SIZE_MAP_OVERLOAD, params: [mapOfAB], - resultType: INT64_TYPE, + resultType: INT_CEL_TYPE, typeParams: typeParamABList, }, { overloadId: SIZE_MAP_INST_OVERLOAD, params: [mapOfAB], - resultType: INT64_TYPE, + resultType: INT_CEL_TYPE, typeParams: typeParamABList, isInstanceFunction: true, }, { overloadId: SIZE_STRING_OVERLOAD, - params: [STRING_TYPE], - resultType: INT64_TYPE, + params: [STRING_CEL_TYPE], + resultType: INT_CEL_TYPE, }, { overloadId: SIZE_STRING_INST_OVERLOAD, - params: [STRING_TYPE], - resultType: INT64_TYPE, + params: [STRING_CEL_TYPE], + resultType: INT_CEL_TYPE, isInstanceFunction: true, }, ], @@ -934,13 +934,13 @@ export const TYPE_CONVERT_BOOL_FUNCTION_DECL = functionDecl( overloads: [ { overloadId: BOOL_TO_BOOL_OVERLOAD, - params: [BOOL_TYPE], - resultType: BOOL_TYPE, + params: [BOOL_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: STRING_TO_BOOL_OVERLOAD, - params: [STRING_TYPE], - resultType: BOOL_TYPE, + params: [STRING_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, ], } @@ -953,13 +953,13 @@ export const TYPE_CONVERT_BYTES_FUNCTION_DECL = functionDecl( overloads: [ { overloadId: BYTES_TO_BYTES_OVERLOAD, - params: [BYTES_TYPE], - resultType: BYTES_TYPE, + params: [BYTES_CEL_TYPE], + resultType: BYTES_CEL_TYPE, }, { overloadId: STRING_TO_BYTES_OVERLOAD, - params: [STRING_TYPE], - resultType: BYTES_TYPE, + params: [STRING_CEL_TYPE], + resultType: BYTES_CEL_TYPE, }, ], } @@ -972,23 +972,23 @@ export const TYPE_CONVERT_DOUBLE_FUNCTION_DECL = functionDecl( overloads: [ { overloadId: DOUBLE_TO_DOUBLE_OVERLOAD, - params: [DOUBLE_TYPE], - resultType: DOUBLE_TYPE, + params: [DOUBLE_CEL_TYPE], + resultType: DOUBLE_CEL_TYPE, }, { overloadId: INT_TO_DOUBLE_OVERLOAD, - params: [INT64_TYPE], - resultType: DOUBLE_TYPE, + params: [INT_CEL_TYPE], + resultType: DOUBLE_CEL_TYPE, }, { overloadId: STRING_TO_DOUBLE_OVERLOAD, - params: [STRING_TYPE], - resultType: DOUBLE_TYPE, + params: [STRING_CEL_TYPE], + resultType: DOUBLE_CEL_TYPE, }, { overloadId: UINT_TO_DOUBLE_OVERLOAD, - params: [UINT64_TYPE], - resultType: DOUBLE_TYPE, + params: [UINT_CEL_TYPE], + resultType: DOUBLE_CEL_TYPE, }, ], } @@ -1006,12 +1006,12 @@ export const TYPE_CONVERT_DURATION_FUNCTION_DECL = functionDecl( }, { overloadId: INT_TO_DURATION_OVERLOAD, - params: [INT64_TYPE], + params: [INT_CEL_TYPE], resultType: DURATION_TYPE, }, { overloadId: STRING_TO_DURATION_OVERLOAD, - params: [STRING_TYPE], + params: [STRING_CEL_TYPE], resultType: DURATION_TYPE, }, ], @@ -1040,33 +1040,33 @@ export const TYPE_CONVERT_INT_FUNCTION_DECL = functionDecl( overloads: [ { overloadId: INT_TO_INT_OVERLOAD, - params: [INT64_TYPE], - resultType: INT64_TYPE, + params: [INT_CEL_TYPE], + resultType: INT_CEL_TYPE, }, { overloadId: DOUBLE_TO_INT_OVERLOAD, - params: [DOUBLE_TYPE], - resultType: INT64_TYPE, + params: [DOUBLE_CEL_TYPE], + resultType: INT_CEL_TYPE, }, { overloadId: DURATION_TO_INT_OVERLOAD, params: [DURATION_TYPE], - resultType: INT64_TYPE, + resultType: INT_CEL_TYPE, }, { overloadId: STRING_TO_INT_OVERLOAD, - params: [STRING_TYPE], - resultType: INT64_TYPE, + params: [STRING_CEL_TYPE], + resultType: INT_CEL_TYPE, }, { overloadId: TIMESTAMP_TO_INT_OVERLOAD, params: [TIMESTAMP_TYPE], - resultType: INT64_TYPE, + resultType: INT_CEL_TYPE, }, { overloadId: UINT_TO_INT_OVERLOAD, - params: [UINT64_TYPE], - resultType: INT64_TYPE, + params: [UINT_CEL_TYPE], + resultType: INT_CEL_TYPE, }, ], } @@ -1079,43 +1079,43 @@ export const TYPE_CONVERT_STRING_FUNCTION_DECL = functionDecl( overloads: [ { overloadId: STRING_TO_STRING_OVERLOAD, - params: [STRING_TYPE], - resultType: STRING_TYPE, + params: [STRING_CEL_TYPE], + resultType: STRING_CEL_TYPE, }, { overloadId: BOOL_TO_STRING_OVERLOAD, - params: [BOOL_TYPE], - resultType: STRING_TYPE, + params: [BOOL_CEL_TYPE], + resultType: STRING_CEL_TYPE, }, { overloadId: BYTES_TO_STRING_OVERLOAD, - params: [BYTES_TYPE], - resultType: STRING_TYPE, + params: [BYTES_CEL_TYPE], + resultType: STRING_CEL_TYPE, }, { overloadId: DOUBLE_TO_STRING_OVERLOAD, - params: [DOUBLE_TYPE], - resultType: STRING_TYPE, + params: [DOUBLE_CEL_TYPE], + resultType: STRING_CEL_TYPE, }, { overloadId: INT_TO_STRING_OVERLOAD, - params: [INT64_TYPE], - resultType: STRING_TYPE, + params: [INT_CEL_TYPE], + resultType: STRING_CEL_TYPE, }, { overloadId: UINT_TO_STRING_OVERLOAD, - params: [UINT64_TYPE], - resultType: STRING_TYPE, + params: [UINT_CEL_TYPE], + resultType: STRING_CEL_TYPE, }, { overloadId: DURATION_TO_STRING_OVERLOAD, params: [DURATION_TYPE], - resultType: STRING_TYPE, + resultType: STRING_CEL_TYPE, }, { overloadId: TIMESTAMP_TO_STRING_OVERLOAD, params: [TIMESTAMP_TYPE], - resultType: STRING_TYPE, + resultType: STRING_CEL_TYPE, }, ], } @@ -1133,12 +1133,12 @@ export const TYPE_CONVERT_TIMESTAMP_FUNCTION_DECL = functionDecl( }, { overloadId: INT_TO_TIMESTAMP_OVERLOAD, - params: [INT64_TYPE], + params: [INT_CEL_TYPE], resultType: TIMESTAMP_TYPE, }, { overloadId: STRING_TO_TIMESTAMP_OVERLOAD, - params: [STRING_TYPE], + params: [STRING_CEL_TYPE], resultType: TIMESTAMP_TYPE, }, ], @@ -1152,23 +1152,23 @@ export const TYPE_CONVERT_UINT_FUNCTION_DECL = functionDecl( overloads: [ { overloadId: UINT_TO_UINT_OVERLOAD, - params: [UINT64_TYPE], - resultType: UINT64_TYPE, + params: [UINT_CEL_TYPE], + resultType: UINT_CEL_TYPE, }, { overloadId: DOUBLE_TO_UINT_OVERLOAD, - params: [DOUBLE_TYPE], - resultType: UINT64_TYPE, + params: [DOUBLE_CEL_TYPE], + resultType: UINT_CEL_TYPE, }, { overloadId: INT_TO_UINT_OVERLOAD, - params: [INT64_TYPE], - resultType: UINT64_TYPE, + params: [INT_CEL_TYPE], + resultType: UINT_CEL_TYPE, }, { overloadId: STRING_TO_UINT_OVERLOAD, - params: [STRING_TYPE], - resultType: UINT64_TYPE, + params: [STRING_CEL_TYPE], + resultType: UINT_CEL_TYPE, }, ], } @@ -1179,8 +1179,8 @@ export const STRING_CONTAINS_FUNCTION_DECL = functionDecl(CONTAINS_OVERLOAD, { overloads: [ { overloadId: CONTAINS_STRING_OVERLOAD, - params: [STRING_TYPE, STRING_TYPE], - resultType: BOOL_TYPE, + params: [STRING_CEL_TYPE, STRING_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, ], }); @@ -1188,8 +1188,8 @@ export const STRING_ENDSWITH_FUNCTION_DECL = functionDecl(ENDS_WITH_OVERLOAD, { overloads: [ { overloadId: ENDS_WITH_STRING_OVERLOAD, - params: [STRING_TYPE, STRING_TYPE], - resultType: BOOL_TYPE, + params: [STRING_CEL_TYPE, STRING_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, ], }); @@ -1199,8 +1199,8 @@ export const STRING_STARTSWITH_FUNCTION_DECL = functionDecl( overloads: [ { overloadId: STARTS_WITH_STRING_OVERLOAD, - params: [STRING_TYPE, STRING_TYPE], - resultType: BOOL_TYPE, + params: [STRING_CEL_TYPE, STRING_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, ], } @@ -1209,13 +1209,13 @@ export const STRING_MATCHES_FUNCTION_DECL = functionDecl(MATCHES_OVERLOAD, { overloads: [ { overloadId: MATCHES_OVERLOAD, - params: [STRING_TYPE, STRING_TYPE], - resultType: BOOL_TYPE, + params: [STRING_CEL_TYPE, STRING_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, { overloadId: MATCHES_STRING_OVERLOAD, - params: [STRING_TYPE, STRING_TYPE], - resultType: BOOL_TYPE, + params: [STRING_CEL_TYPE, STRING_CEL_TYPE], + resultType: BOOL_CEL_TYPE, }, ], }); @@ -1228,13 +1228,13 @@ export const TIME_GET_FULL_YEAR_FUNCTION_DECL = functionDecl( { overloadId: TIMESTAMP_TO_YEAR_OVERLOAD, params: [TIMESTAMP_TYPE], - resultType: INT64_TYPE, + resultType: INT_CEL_TYPE, isInstanceFunction: true, }, { overloadId: TIMESTAMP_TO_YEAR_WITH_TZ_OVERLOAD, params: [TIMESTAMP_TYPE], - resultType: STRING_TYPE, + resultType: STRING_CEL_TYPE, isInstanceFunction: true, }, ], @@ -1247,13 +1247,13 @@ export const TIME_GET_MONTH_FUNCTION_DECL = functionDecl( { overloadId: TIMESTAMP_TO_MONTH_OVERLOAD, params: [TIMESTAMP_TYPE], - resultType: INT64_TYPE, + resultType: INT_CEL_TYPE, isInstanceFunction: true, }, { overloadId: TIMESTAMP_TO_MONTH_WITH_TZ_OVERLOAD, params: [TIMESTAMP_TYPE], - resultType: STRING_TYPE, + resultType: STRING_CEL_TYPE, isInstanceFunction: true, }, ], @@ -1266,13 +1266,13 @@ export const TIME_GET_DAY_OF_YEAR_FUNCTION_DECL = functionDecl( { overloadId: TIMESTAMP_TO_DAY_OF_YEAR_OVERLOAD, params: [TIMESTAMP_TYPE], - resultType: INT64_TYPE, + resultType: INT_CEL_TYPE, isInstanceFunction: true, }, { overloadId: TIMESTAMP_TO_DAY_OF_YEAR_WITH_TZ_OVERLOAD, params: [TIMESTAMP_TYPE], - resultType: STRING_TYPE, + resultType: STRING_CEL_TYPE, isInstanceFunction: true, }, ], @@ -1285,13 +1285,13 @@ export const TIME_GET_DAY_OF_MONTH_FUNCTION_DECL = functionDecl( { overloadId: TIMESTAMP_TO_DAY_OF_MONTH_ZERO_BASED_OVERLOAD, params: [TIMESTAMP_TYPE], - resultType: INT64_TYPE, + resultType: INT_CEL_TYPE, isInstanceFunction: true, }, { overloadId: TIMESTAMP_TO_DAY_OF_MONTH_ZERO_BASED_WITH_TZ_OVERLOAD, params: [TIMESTAMP_TYPE], - resultType: STRING_TYPE, + resultType: STRING_CEL_TYPE, isInstanceFunction: true, }, ], @@ -1304,13 +1304,13 @@ export const TIME_GET_DATE_FUNCTION_DECL = functionDecl( { overloadId: TIMESTAMP_TO_DAY_OF_MONTH_ONE_BASED_OVERLOAD, params: [TIMESTAMP_TYPE], - resultType: INT64_TYPE, + resultType: INT_CEL_TYPE, isInstanceFunction: true, }, { overloadId: TIMESTAMP_TO_DAY_OF_MONTH_ONE_BASED_WITH_TZ_OVERLOAD, params: [TIMESTAMP_TYPE], - resultType: STRING_TYPE, + resultType: STRING_CEL_TYPE, isInstanceFunction: true, }, ], @@ -1323,13 +1323,13 @@ export const TIME_GET_DAY_OF_WEEK_FUNCTION_DECL = functionDecl( { overloadId: TIMESTAMP_TO_DAY_OF_WEEK_OVERLOAD, params: [TIMESTAMP_TYPE], - resultType: INT64_TYPE, + resultType: INT_CEL_TYPE, isInstanceFunction: true, }, { overloadId: TIMESTAMP_TO_DAY_OF_WEEK_WITH_TZ_OVERLOAD, params: [TIMESTAMP_TYPE], - resultType: STRING_TYPE, + resultType: STRING_CEL_TYPE, isInstanceFunction: true, }, ], @@ -1342,19 +1342,19 @@ export const TIME_GET_HOURS_FUNCTION_DECL = functionDecl( { overloadId: TIMESTAMP_TO_HOURS_OVERLOAD, params: [TIMESTAMP_TYPE], - resultType: INT64_TYPE, + resultType: INT_CEL_TYPE, isInstanceFunction: true, }, { overloadId: TIMESTAMP_TO_HOURS_WITH_TZ_OVERLOAD, params: [TIMESTAMP_TYPE], - resultType: STRING_TYPE, + resultType: STRING_CEL_TYPE, isInstanceFunction: true, }, { overloadId: DURATION_TO_HOURS_OVERLOAD, params: [DURATION_TYPE], - resultType: INT64_TYPE, + resultType: INT_CEL_TYPE, isInstanceFunction: true, }, ], @@ -1367,19 +1367,19 @@ export const TIME_GET_MINUTES_FUNCTION_DECL = functionDecl( { overloadId: TIMESTAMP_TO_MINUTES_OVERLOAD, params: [TIMESTAMP_TYPE], - resultType: INT64_TYPE, + resultType: INT_CEL_TYPE, isInstanceFunction: true, }, { overloadId: TIMESTAMP_TO_MINUTES_WITH_TZ_OVERLOAD, params: [TIMESTAMP_TYPE], - resultType: STRING_TYPE, + resultType: STRING_CEL_TYPE, isInstanceFunction: true, }, { overloadId: DURATION_TO_MINUTES_OVERLOAD, params: [DURATION_TYPE], - resultType: INT64_TYPE, + resultType: INT_CEL_TYPE, isInstanceFunction: true, }, ], @@ -1392,19 +1392,19 @@ export const TIME_GET_SECONDS_FUNCTION_DECL = functionDecl( { overloadId: TIMESTAMP_TO_SECONDS_OVERLOAD, params: [TIMESTAMP_TYPE], - resultType: INT64_TYPE, + resultType: INT_CEL_TYPE, isInstanceFunction: true, }, { overloadId: TIMESTAMP_TO_SECONDS_WITH_TZ_OVERLOAD, params: [TIMESTAMP_TYPE], - resultType: STRING_TYPE, + resultType: STRING_CEL_TYPE, isInstanceFunction: true, }, { overloadId: DURATION_TO_SECONDS_OVERLOAD, params: [DURATION_TYPE], - resultType: INT64_TYPE, + resultType: INT_CEL_TYPE, isInstanceFunction: true, }, ], @@ -1417,19 +1417,19 @@ export const TIME_GET_MILLISECONDS_FUNCTION_DECL = functionDecl( { overloadId: TIMESTAMP_TO_MILLISECONDS_OVERLOAD, params: [TIMESTAMP_TYPE], - resultType: INT64_TYPE, + resultType: INT_CEL_TYPE, isInstanceFunction: true, }, { overloadId: TIMESTAMP_TO_MILLISECONDS_WITH_TZ_OVERLOAD, params: [TIMESTAMP_TYPE], - resultType: STRING_TYPE, + resultType: STRING_CEL_TYPE, isInstanceFunction: true, }, { overloadId: DURATION_TO_MILLISECONDS_OVERLOAD, params: [DURATION_TYPE], - resultType: INT64_TYPE, + resultType: INT_CEL_TYPE, isInstanceFunction: true, }, ], diff --git a/packages/cel/src/lib/common/types/bool.spec.ts b/packages/cel/src/lib/common/types/bool.spec.ts index 048f061..2122b4c 100644 --- a/packages/cel/src/lib/common/types/bool.spec.ts +++ b/packages/cel/src/lib/common/types/bool.spec.ts @@ -6,20 +6,16 @@ import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb' import { create } from '@bufbuild/protobuf'; import { AnySchema, BoolValueSchema, anyPack } from '@bufbuild/protobuf/wkt'; import { - BOOL_TYPE, + BOOL_REF_TYPE, + BoolRefVal, boolConstant, boolExpr, boolValue, - compareBoolValue, - convertBoolValueToNative, - convertBoolValueToType, - equalBoolValue, - isZeroBoolValue, - negateBoolValue, } from './bool'; -import { int64Value } from './int'; -import { STRING_TYPE, stringValue } from './string'; -import { TYPE_TYPE } from './type'; +import { ErrorRefVal } from './error'; +import { IntRefVal } from './int'; +import { STRING_REF_TYPE, StringRefVal } from './string'; +import { TYPE_REF_TYPE, TypeRefVal } from './type'; describe('bool', () => { it('boolConstant', () => { @@ -64,94 +60,80 @@ describe('bool', () => { // TODO: validations it('convertBoolValueToNative - js boolean', () => { - expect(() => { - convertBoolValueToNative(stringValue('true'), Boolean); - }).toThrow(); - const value = boolValue(true); - expect(convertBoolValueToNative(value, Boolean)).toEqual(true); + const value = new BoolRefVal(true); + expect(value.convertToNative(Boolean)).toEqual(true); }); it('convertBoolValueToNative - anyPack', () => { - const value = boolValue(true); + const value = new BoolRefVal(true); const packed = anyPack( BoolValueSchema, create(BoolValueSchema, { value: true }) ); - expect(convertBoolValueToNative(value, AnySchema)).toEqual(packed); + expect(value.convertToNative(AnySchema)).toEqual(packed); }); it('convertBoolValueToNative - bool wrapper', () => { - const value = boolValue(true); - expect(convertBoolValueToNative(value, BoolValueSchema)).toEqual( + const value = new BoolRefVal(true); + expect(value.convertToNative(BoolValueSchema)).toEqual( create(BoolValueSchema, { value: true }) ); }); it('convertBoolValueToNative - invalid type', () => { - const value = boolValue(true); - expect(convertBoolValueToNative(value, Array)).toEqual( - new Error(`type conversion error from 'bool' to 'Array'`) + const value = new BoolRefVal(true); + expect(value.convertToNative(Array)).toEqual( + ErrorRefVal.nativeTypeConversionError(value, Array) ); }); it('convertBoolValueToType', () => { - expect(() => { - convertBoolValueToType(stringValue('true'), BOOL_TYPE); - }).toThrow(); - const value = boolValue(true); - expect(convertBoolValueToType(value, BOOL_TYPE)).toEqual(boolValue(true)); - expect(convertBoolValueToType(value, STRING_TYPE)).toEqual( - stringValue('true') - ); - expect(convertBoolValueToType(value, TYPE_TYPE)).toEqual(BOOL_TYPE); + const value = new BoolRefVal(true); + expect(value.convertToType(BOOL_REF_TYPE)).toStrictEqual( + new BoolRefVal(true) + ); + expect(value.convertToType(STRING_REF_TYPE)).toStrictEqual( + new StringRefVal('true') + ); + expect(value.convertToType(TYPE_REF_TYPE)).toStrictEqual( + new TypeRefVal(BOOL_REF_TYPE) + ); }); it('equalBoolValue', () => { - expect(() => { - equalBoolValue(stringValue('true'), boolValue(true)); - }).toThrow(); - expect(equalBoolValue(boolValue(true), boolValue(true))).toEqual( - boolValue(true) + expect(BoolRefVal.True.equal(BoolRefVal.True)).toStrictEqual( + BoolRefVal.True ); - expect(equalBoolValue(boolValue(false), boolValue(true))).toEqual( - boolValue(false) + expect(BoolRefVal.False.equal(BoolRefVal.True)).toStrictEqual( + BoolRefVal.False ); - expect(equalBoolValue(boolValue(true), boolValue(false))).toEqual( - boolValue(false) + expect(BoolRefVal.True.equal(BoolRefVal.False)).toStrictEqual( + BoolRefVal.False ); }); it('isZeroBoolValue', () => { - expect(() => { - isZeroBoolValue(stringValue('true')); - }).toThrow(); - expect(isZeroBoolValue(boolValue(true))).toEqual(boolValue(false)); - expect(isZeroBoolValue(boolValue(false))).toEqual(boolValue(true)); + expect(BoolRefVal.True.isZeroValue()).toEqual(false); + expect(BoolRefVal.False.isZeroValue()).toEqual(true); }); it('compareBoolValue', () => { - expect(() => { - compareBoolValue(stringValue('true'), boolValue(true)); - }).toThrow(); - expect(compareBoolValue(boolValue(true), boolValue(true))).toEqual( - int64Value(BigInt(0)) + expect(BoolRefVal.True.compare(BoolRefVal.True)).toStrictEqual( + IntRefVal.IntZero ); - expect(compareBoolValue(boolValue(false), boolValue(true))).toEqual( - int64Value(BigInt(-1)) + expect(BoolRefVal.False.compare(BoolRefVal.True)).toStrictEqual( + IntRefVal.IntNegOne ); - expect(compareBoolValue(boolValue(true), boolValue(false))).toEqual( - int64Value(BigInt(1)) + expect(BoolRefVal.True.compare(BoolRefVal.False)).toStrictEqual( + IntRefVal.IntOne ); - expect(compareBoolValue(boolValue(true), stringValue('true'))).toEqual( - new Error('no such overload') + expect(BoolRefVal.True.compare(new IntRefVal(BigInt(1)))).toStrictEqual( + ErrorRefVal.errNoSuchOverload ); }); it('negateBoolValue', () => { - expect(() => { - negateBoolValue(stringValue('true')); - }).toThrow(); - expect(negateBoolValue(boolValue(true))).toEqual(boolValue(false)); - expect(negateBoolValue(boolValue(false))).toEqual(boolValue(true)); + expect(BoolRefVal.True.negate()).toStrictEqual(BoolRefVal.False); + expect(BoolRefVal.False.negate()).toStrictEqual(BoolRefVal.True); }); }); diff --git a/packages/cel/src/lib/common/types/bool.ts b/packages/cel/src/lib/common/types/bool.ts index a1436fe..80752be 100644 --- a/packages/cel/src/lib/common/types/bool.ts +++ b/packages/cel/src/lib/common/types/bool.ts @@ -15,14 +15,20 @@ import { import { create } from '@bufbuild/protobuf'; import { AnySchema, BoolValueSchema, anyPack } from '@bufbuild/protobuf/wkt'; import { formatCELType } from '../format'; +import { RefType, RefTypeEnum, RefVal } from '../ref/reference'; import { isConstExpr } from './constant'; -import { int64Value } from './int'; +import { ErrorRefVal } from './error'; +import { IntRefVal, int64Value } from './int'; import { NativeType } from './native'; import { primitiveType } from './primitive'; -import { stringValue } from './string'; +import { StringRefVal, stringValue } from './string'; +import { Comparer } from './traits/comparer'; +import { Negater } from './traits/math'; import { Trait } from './traits/trait'; +import { Zeroer } from './traits/zeroer'; +import { TypeRefVal } from './type'; -export const BOOL_TYPE = primitiveType(Type_PrimitiveType.BOOL); +export const BOOL_CEL_TYPE = primitiveType(Type_PrimitiveType.BOOL); export function isBoolType(type: Type) { return ( @@ -99,7 +105,9 @@ export function convertBoolValueToNative(value: Value, type: NativeType) { break; } return new Error( - `type conversion error from '${formatCELType(BOOL_TYPE)}' to '${type.name}'` + `type conversion error from '${formatCELType(BOOL_CEL_TYPE)}' to '${ + type.name + }'` ); } @@ -120,13 +128,13 @@ export function convertBoolValueToType(value: Value, type: Type) { } break; case 'type': - return BOOL_TYPE; + return BOOL_CEL_TYPE; default: break; } return new Error( `type conversion error from '${formatCELType( - BOOL_TYPE + BOOL_CEL_TYPE )}' to '${formatCELType(type)}'` ); } @@ -176,3 +184,111 @@ export function negateBoolValue(value: Value) { } return boolValue(!value.kind.value); } + +export class BoolRefType implements RefType { + // This has to be a TS private field instead of a # private field because + // otherwise the tests will not be able to access it to check for equality. + // TODO: do we want to alter the tests to use the getter instead? + readonly _traits = BOOL_TRAITS; + + celType(): Type { + return BOOL_CEL_TYPE; + } + + hasTrait(trait: Trait): boolean { + return this._traits.has(trait); + } + + typeName(): string { + return 'bool'; + } +} + +export const BOOL_REF_TYPE = new BoolRefType(); + +export class BoolRefVal implements RefVal, Comparer, Zeroer, Negater { + // This has to be a TS private field instead of a # private field because + // otherwise the tests will not be able to access it to check for equality. + // TODO: do we want to alter the tests to use the getter instead? + private readonly _value: boolean; + + constructor(value: boolean) { + this._value = value; + } + + static True = new BoolRefVal(true); + static False = new BoolRefVal(false); + + celValue(): Value { + return boolValue(this._value); + } + + convertToNative(type: NativeType) { + switch (type) { + case Boolean: + return this._value; + case AnySchema: + return anyPack( + BoolValueSchema, + create(BoolValueSchema, { value: this._value }) + ); + case BoolValueSchema: + return create(BoolValueSchema, { value: this._value }); + default: + return ErrorRefVal.nativeTypeConversionError(this, type); + } + } + + convertToType(type: RefType): RefVal { + switch (type.typeName()) { + case RefTypeEnum.BOOL: + return new BoolRefVal(this._value); + case RefTypeEnum.STRING: + return new StringRefVal(this._value ? 'true' : 'false'); + case RefTypeEnum.TYPE: + return new TypeRefVal(BOOL_REF_TYPE); + default: + return ErrorRefVal.typeConversionError(this, type); + } + } + + equal(other: RefVal): RefVal { + switch (other.type().typeName()) { + case RefTypeEnum.BOOL: + return new BoolRefVal(this._value === other.value()); + default: + return BoolRefVal.False; + } + } + + type(): RefType { + return BOOL_REF_TYPE; + } + + value(): boolean { + return this._value; + } + + compare(other: RefVal) { + switch (other.type().typeName()) { + case RefTypeEnum.BOOL: + if (other.value() === this.value()) { + return IntRefVal.IntZero; + } + if (!this.value() && other.value()) { + return IntRefVal.IntNegOne; + } + return IntRefVal.IntOne; + default: + return ErrorRefVal.maybeNoSuchOverload(other); + } + } + + isZeroValue(): boolean { + return this._value === false; + } + + negate(): RefVal { + return new BoolRefVal(!this._value); + } +} diff --git a/packages/cel/src/lib/common/types/bytes.spec.ts b/packages/cel/src/lib/common/types/bytes.spec.ts index 84c479b..9d5a799 100644 --- a/packages/cel/src/lib/common/types/bytes.spec.ts +++ b/packages/cel/src/lib/common/types/bytes.spec.ts @@ -5,23 +5,18 @@ import { import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb'; import { create } from '@bufbuild/protobuf'; import { AnySchema, BytesValueSchema, anyPack } from '@bufbuild/protobuf/wkt'; -import { boolValue } from './bool'; +import { BOOL_REF_TYPE, BoolRefVal } from './bool'; import { - BYTES_TYPE, - addBytesValue, + BYTES_REF_TYPE, + BytesRefVal, bytesConstant, bytesExpr, bytesValue, - compareBytesValue, - convertBytesValueToNative, - convertBytesValueToType, - equalBytesValue, - isZeroBytesValue, - sizeBytesValue, } from './bytes'; -import { int64Value } from './int'; -import { STRING_TYPE, stringValue } from './string'; -import { TYPE_TYPE } from './type'; +import { ErrorRefVal } from './error'; +import { IntRefVal } from './int'; +import { STRING_REF_TYPE, StringRefVal } from './string'; +import { TYPE_REF_TYPE, TypeRefVal } from './type'; describe('bytes', () => { it('bytesConstant', () => { @@ -66,146 +61,116 @@ describe('bytes', () => { // TODO: validations it('convertBytesValueToNative - js Uint8Array', () => { - expect(() => { - convertBytesValueToNative(stringValue('foo'), Uint8Array); - }).toThrow(); expect( - convertBytesValueToNative( - bytesValue(new Uint8Array([1, 2, 3])), - Uint8Array - ) - ).toEqual(new Uint8Array([1, 2, 3])); + new BytesRefVal(new Uint8Array([1, 2, 3])).convertToNative(Uint8Array) + ).toStrictEqual(new Uint8Array([1, 2, 3])); }); it('convertBytesValueToNative - anyPack', () => { - const value = bytesValue(new Uint8Array([1, 2, 3])); + const value = new BytesRefVal(new Uint8Array([1, 2, 3])); const packed = anyPack( BytesValueSchema, create(BytesValueSchema, { value: new Uint8Array([1, 2, 3]) }) ); - expect(convertBytesValueToNative(value, AnySchema)).toEqual(packed); + expect(value.convertToNative(AnySchema)).toStrictEqual(packed); }); it('convertBytesValueToNative - bytes wrapper', () => { - const value = bytesValue(new Uint8Array([1, 2, 3])); - expect(convertBytesValueToNative(value, BytesValueSchema)).toEqual( + const value = new BytesRefVal(new Uint8Array([1, 2, 3])); + expect(value.convertToNative(BytesValueSchema)).toStrictEqual( create(BytesValueSchema, { value: new Uint8Array([1, 2, 3]) }) ); }); it('convertBytesValueToNative - invalid type', () => { - const value = bytesValue(new Uint8Array([1, 2, 3])); - expect(convertBytesValueToNative(value, Boolean)).toEqual( - new Error(`type conversion error from 'bytes' to 'Boolean'`) + const value = new BytesRefVal(new Uint8Array([1, 2, 3])); + expect(value.convertToNative(Boolean)).toStrictEqual( + ErrorRefVal.nativeTypeConversionError(value, Boolean) ); }); it('convertBytesValueToType', () => { - expect(() => { - convertBytesValueToType(stringValue('true'), BYTES_TYPE); - }).toThrow(); - const value = bytesValue(new TextEncoder().encode('helloworld')); - expect(convertBytesValueToType(value, BYTES_TYPE)).toEqual(value); - expect(convertBytesValueToType(value, STRING_TYPE)).toEqual( - stringValue('helloworld') + const value = new BytesRefVal(new TextEncoder().encode('helloworld')); + expect(value.convertToType(BYTES_REF_TYPE)).toStrictEqual(value); + expect(value.convertToType(STRING_REF_TYPE)).toStrictEqual( + new StringRefVal('helloworld') + ); + expect(value.convertToType(TYPE_REF_TYPE)).toStrictEqual( + new TypeRefVal(BYTES_REF_TYPE) + ); + expect(value.convertToType(BOOL_REF_TYPE)).toStrictEqual( + ErrorRefVal.typeConversionError(value, BOOL_REF_TYPE) ); - expect(convertBytesValueToType(value, TYPE_TYPE)).toEqual(BYTES_TYPE); }); it('equalBytesValue', () => { - expect(() => { - equalBytesValue( - stringValue('foo'), - bytesValue(new Uint8Array([1, 2, 3])) - ); - }).toThrow(); + const value = new BytesRefVal(new Uint8Array([1, 2, 3])); expect( - equalBytesValue( - bytesValue(new Uint8Array([1, 2, 3])), - bytesValue(new Uint8Array([1, 2, 3])) - ) - ).toEqual(boolValue(true)); + value.equal(new BytesRefVal(new Uint8Array([1, 2, 3]))) + ).toStrictEqual(new BoolRefVal(true)); expect( - equalBytesValue( - bytesValue(new Uint8Array([1, 2, 3])), - bytesValue(new Uint8Array([1, 2])) - ) - ).toEqual(boolValue(false)); - expect( - equalBytesValue(bytesValue(new Uint8Array([1, 2, 3])), stringValue('')) - ).toEqual(boolValue(false)); + value.equal(new BytesRefVal(new Uint8Array([1, 2, 4]))) + ).toStrictEqual(new BoolRefVal(false)); + expect(value.equal(new BoolRefVal(true))).toStrictEqual(BoolRefVal.False); }); it('isZeroBytesValue', () => { - expect(() => { - isZeroBytesValue(stringValue('foo')); - }).toThrow(); - expect(isZeroBytesValue(bytesValue(new Uint8Array([1, 2, 3])))).toEqual( - boolValue(false) - ); - expect(isZeroBytesValue(bytesValue(new Uint8Array([])))).toEqual( - boolValue(true) + expect(new BytesRefVal(new Uint8Array([1, 2, 3])).isZeroValue()).toEqual( + false ); + expect(new BytesRefVal(new Uint8Array([])).isZeroValue()).toEqual(true); }); it('addBytesValue', () => { - expect(() => { - addBytesValue(stringValue('foo'), bytesValue(new Uint8Array([1, 2, 3]))); - }).toThrow(); expect( - addBytesValue( - bytesValue(new TextEncoder().encode('foo')), - bytesValue(new TextEncoder().encode('bar')) + new BytesRefVal(new Uint8Array([1, 2, 3])).add( + new BytesRefVal(new Uint8Array([4, 5, 6])) ) - ).toEqual(bytesValue(new TextEncoder().encode('foobar'))); + ).toStrictEqual(new BytesRefVal(new Uint8Array([1, 2, 3, 4, 5, 6]))); expect( - addBytesValue( - bytesValue(new TextEncoder().encode('foo')), - stringValue('bar') + new BytesRefVal(new Uint8Array([1, 2, 3])).add( + new BytesRefVal(new Uint8Array([])) ) - ).toEqual(new Error('no such overload')); + ).toStrictEqual(new BytesRefVal(new Uint8Array([1, 2, 3]))); + expect( + new BytesRefVal(new Uint8Array([])).add( + new BytesRefVal(new Uint8Array([1, 2, 3])) + ) + ).toStrictEqual(new BytesRefVal(new Uint8Array([1, 2, 3]))); + expect( + new BytesRefVal(new Uint8Array([])).add(new StringRefVal('foo')) + ).toStrictEqual(ErrorRefVal.errNoSuchOverload); }); it('compareBytesValue', () => { - expect(() => { - compareBytesValue( - stringValue('foo'), - bytesValue(new Uint8Array([1, 2, 3])) - ); - }).toThrow(); expect( - compareBytesValue( - bytesValue(new TextEncoder().encode('1234')), - bytesValue(new TextEncoder().encode('2345')) + new BytesRefVal(new Uint8Array([1, 2, 3, 4])).compare( + new BytesRefVal(new Uint8Array([2, 3, 4, 5])) ) - ).toEqual(int64Value(BigInt(-1))); + ).toStrictEqual(IntRefVal.IntNegOne); expect( - compareBytesValue( - bytesValue(new TextEncoder().encode('1234')), - bytesValue(new TextEncoder().encode('1234')) + new BytesRefVal(new Uint8Array([1, 2, 3, 4])).compare( + new BytesRefVal(new Uint8Array([1, 2, 3, 4])) ) - ).toEqual(int64Value(BigInt(0))); + ).toStrictEqual(IntRefVal.IntZero); expect( - compareBytesValue( - bytesValue(new TextEncoder().encode('2345')), - bytesValue(new TextEncoder().encode('1234')) + new BytesRefVal(new Uint8Array([2, 3, 4, 5])).compare( + new BytesRefVal(new Uint8Array([1, 2, 3, 4])) ) - ).toEqual(int64Value(BigInt(1))); + ).toStrictEqual(IntRefVal.IntOne); expect( - compareBytesValue( - bytesValue(new TextEncoder().encode('1234')), - stringValue('1234') + new BytesRefVal(new Uint8Array([1, 2, 3, 4])).compare( + new StringRefVal('foo') ) - ).toEqual(new Error('no such overload')); + ).toStrictEqual(ErrorRefVal.errNoSuchOverload); }); it('sizeBytesValue', () => { - expect(() => { - sizeBytesValue(stringValue('foo')); - }).toThrow(); - expect( - sizeBytesValue(bytesValue(new TextEncoder().encode('1234567890'))).kind - .value - ).toEqual(BigInt(10)); + expect(new BytesRefVal(new Uint8Array([1, 2, 3])).size()).toStrictEqual( + new IntRefVal(BigInt(3)) + ); + expect(new BytesRefVal(new Uint8Array([])).size()).toStrictEqual( + new IntRefVal(BigInt(0)) + ); }); }); diff --git a/packages/cel/src/lib/common/types/bytes.ts b/packages/cel/src/lib/common/types/bytes.ts index cb64711..227167d 100644 --- a/packages/cel/src/lib/common/types/bytes.ts +++ b/packages/cel/src/lib/common/types/bytes.ts @@ -16,15 +16,22 @@ import { create } from '@bufbuild/protobuf'; import { AnySchema, BytesValueSchema, anyPack } from '@bufbuild/protobuf/wkt'; import { dequal } from 'dequal'; import { formatCELType } from '../format'; -import { boolValue } from './bool'; +import { RefType, RefTypeEnum, RefVal } from '../ref/reference'; +import { BoolRefVal, boolValue } from './bool'; import { isConstExpr } from './constant'; -import { int64Value } from './int'; +import { ErrorRefVal } from './error'; +import { IntRefVal, int64Value } from './int'; import { NativeType } from './native'; import { primitiveType } from './primitive'; -import { stringValue } from './string'; +import { StringRefVal, stringValue } from './string'; +import { Comparer } from './traits/comparer'; +import { Adder } from './traits/math'; +import { Sizer } from './traits/sizer'; import { Trait } from './traits/trait'; +import { Zeroer } from './traits/zeroer'; +import { TypeRefVal } from './type'; -export const BYTES_TYPE = primitiveType(Type_PrimitiveType.BYTES); +export const BYTES_CEL_TYPE = primitiveType(Type_PrimitiveType.BYTES); export function isBytesType(val: Type) { return ( @@ -102,7 +109,7 @@ export function convertBytesValueToNative(value: Value, type: NativeType) { break; } return new Error( - `type conversion error from '${formatCELType(BYTES_TYPE)}' to '${ + `type conversion error from '${formatCELType(BYTES_CEL_TYPE)}' to '${ type.name }'` ); @@ -124,13 +131,13 @@ export function convertBytesValueToType(value: Value, type: Type) { } break; case 'type': - return BYTES_TYPE; + return BYTES_CEL_TYPE; default: break; } return new Error( `type conversion error from '${formatCELType( - BYTES_TYPE + BYTES_CEL_TYPE )}' to '${formatCELType(type)}'` ); } @@ -200,3 +207,129 @@ export function sizeBytesValue(value: Value) { } return int64Value(BigInt(value.kind.value.length)); } + +export class BytesRefType implements RefType { + // This has to be a TS private field instead of a # private field because + // otherwise the tests will not be able to access it to check for equality. + // TODO: do we want to alter the tests to use the getter instead? + readonly _traits = BYTES_TRAITS; + + celType(): Type { + return BYTES_CEL_TYPE; + } + + hasTrait(trait: Trait): boolean { + return this._traits.has(trait); + } + + typeName(): string { + return RefTypeEnum.BYTES; + } +} + +export const BYTES_REF_TYPE = new BytesRefType(); + +export class BytesRefVal implements RefVal, Adder, Comparer, Sizer, Zeroer { + // This has to be a TS private field instead of a # private field because + // otherwise the tests will not be able to access it to check for equality. + // TODO: do we want to alter the tests to use the getter instead? + private readonly _value: Uint8Array; + + constructor(value: Uint8Array) { + this._value = value; + } + + celValue(): Value { + return bytesValue(this._value); + } + + convertToNative(type: NativeType) { + switch (type) { + case Uint8Array: + return this._value; + case AnySchema: + return anyPack( + BytesValueSchema, + create(BytesValueSchema, { value: this._value }) + ); + case BytesValueSchema: + return create(BytesValueSchema, { value: this._value }); + default: + return ErrorRefVal.nativeTypeConversionError(this, type); + } + } + + convertToType(type: RefType): RefVal { + switch (type.typeName()) { + case RefTypeEnum.BYTES: + return new BytesRefVal(this._value); + case RefTypeEnum.STRING: + return new StringRefVal(new TextDecoder().decode(this._value)); + case RefTypeEnum.TYPE: + return new TypeRefVal(BYTES_REF_TYPE); + default: + return ErrorRefVal.typeConversionError(this, type); + } + } + + equal(other: RefVal): RefVal { + switch (other.type().typeName()) { + case RefTypeEnum.BYTES: + return new BoolRefVal(dequal(this._value, other.value())); + default: + return BoolRefVal.False; + } + } + + type(): RefType { + return BYTES_REF_TYPE; + } + + value() { + return this._value; + } + + add(other: RefVal): RefVal { + switch (other.type().typeName()) { + case RefTypeEnum.BYTES: + return new BytesRefVal( + new Uint8Array([...this._value, ...(other.value() as Uint8Array)]) + ); + default: + return ErrorRefVal.maybeNoSuchOverload(other); + } + } + + compare(other: RefVal): RefVal { + switch (other.type().typeName()) { + case RefTypeEnum.BYTES: + if (this._value.length < other.value().length) { + return IntRefVal.IntNegOne; + } + if (this._value.length > other.value().length) { + return IntRefVal.IntOne; + } + for (let i = 0; i < this._value.length; i++) { + const v = this._value[i]; + const o = other.value()[i]; + if (v < o) { + return IntRefVal.IntNegOne; + } + if (v > o) { + return IntRefVal.IntOne; + } + } + return IntRefVal.IntZero; + default: + return ErrorRefVal.maybeNoSuchOverload(other); + } + } + + size(): RefVal { + return new IntRefVal(BigInt(this._value.length)); + } + + isZeroValue(): boolean { + return this._value.length === 0; + } +} diff --git a/packages/cel/src/lib/common/types/compare.ts b/packages/cel/src/lib/common/types/compare.ts index bfa2487..112dfb0 100644 --- a/packages/cel/src/lib/common/types/compare.ts +++ b/packages/cel/src/lib/common/types/compare.ts @@ -1,6 +1,8 @@ import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; -import { int64Value } from './int'; -import { isNumberValue } from './number'; +import { RefVal } from '../ref/reference'; +import { ErrorRefVal } from './error'; +import { IntRefVal, int64Value } from './int'; +import { isNumberRefVal, isNumberValue } from './number'; export function compareNumberValues(value: Value, other: Value) { if (!isNumberValue(value)) { @@ -17,3 +19,22 @@ export function compareNumberValues(value: Value, other: Value) { } return int64Value(BigInt(0)); } + +export function compareNumberRefVals( + val: RefVal, + other: RefVal +): IntRefVal | ErrorRefVal { + if (!isNumberRefVal(val)) { + return ErrorRefVal.maybeNoSuchOverload(val) as ErrorRefVal; + } + if (!isNumberRefVal(other)) { + return ErrorRefVal.maybeNoSuchOverload(other) as ErrorRefVal; + } + if (val.value() < other.value()) { + return IntRefVal.IntNegOne; + } + if (val.value() > other.value()) { + return IntRefVal.IntOne; + } + return IntRefVal.IntZero; +} diff --git a/packages/cel/src/lib/common/types/double.spec.ts b/packages/cel/src/lib/common/types/double.spec.ts index 9cada17..8a23339 100644 --- a/packages/cel/src/lib/common/types/double.spec.ts +++ b/packages/cel/src/lib/common/types/double.spec.ts @@ -10,25 +10,19 @@ import { FloatValueSchema, anyPack, } from '@bufbuild/protobuf/wkt'; -import { boolValue } from './bool'; +import { BoolRefVal } from './bool'; import { - DOUBLE_TYPE, - addDoubleValue, - compareDoubleValue, - convertDoubleValueToNative, - convertDoubleValueToType, - divideDoubleValue, + DOUBLE_REF_TYPE, + DoubleRefVal, doubleConstant, doubleExpr, doubleValue, - equalDoubleValue, - isZeroDoubleValue, - multiplyDoubleValue, } from './double'; -import { INT64_TYPE, int64Value } from './int'; -import { STRING_TYPE, stringValue } from './string'; -import { TYPE_TYPE } from './type'; -import { UINT64_TYPE, uint64Value } from './uint'; +import { ErrorRefVal } from './error'; +import { INT_REF_TYPE, IntRefVal } from './int'; +import { STRING_REF_TYPE, StringRefVal } from './string'; +import { TYPE_REF_TYPE, TypeRefVal } from './type'; +import { UINT_REF_TYPE, UintRefVal } from './uint'; describe('double', () => { it('doubleConstant', () => { @@ -73,282 +67,261 @@ describe('double', () => { // TODO: validations it('convertDoubleValueToNative - js Number', () => { - expect(() => { - convertDoubleValueToNative(stringValue('foo'), Number); - }).toThrow(); - expect(convertDoubleValueToNative(doubleValue(3.14), Number)).toEqual(3.14); + const value = new DoubleRefVal(3.14); + expect(value.convertToNative(Number)).toStrictEqual(3.14); }); it('convertDoubleValueToNative - anyPack', () => { - const value = doubleValue(-1.4); + const value = new DoubleRefVal(-1.4); const packed = anyPack( DoubleValueSchema, create(DoubleValueSchema, { value: -1.4 }) ); - expect(convertDoubleValueToNative(value, AnySchema)).toEqual(packed); + expect(value.convertToNative(AnySchema)).toStrictEqual(packed); }); it('convertDoubleValueToNative - double wrapper', () => { - const value = doubleValue(30000000.1); - expect(convertDoubleValueToNative(value, DoubleValueSchema)).toEqual( + const value = new DoubleRefVal(30000000.1); + expect(value.convertToNative(DoubleValueSchema)).toStrictEqual( create(DoubleValueSchema, { value: 30000000.1 }) ); }); it('convertDoubleValueToNative - double wrapper', () => { - const value = doubleValue(1.7976931348623157); - expect(convertDoubleValueToNative(value, FloatValueSchema)).toEqual( + const value = new DoubleRefVal(1.7976931348623157); + expect(value.convertToNative(FloatValueSchema)).toStrictEqual( create(FloatValueSchema, { value: 1.7976931348623157 }) ); }); it('convertDoubleValueToNative - invalid type', () => { - const value = doubleValue(-3.14159); - expect(convertDoubleValueToNative(value, Boolean)).toEqual( - new Error(`type conversion error from 'double' to 'Boolean'`) + const value = new DoubleRefVal(-3.14159); + expect(value.convertToNative(Boolean)).toStrictEqual( + ErrorRefVal.nativeTypeConversionError(value, Boolean) ); }); it('convertDoubleValueToType', () => { - expect(() => { - convertDoubleValueToType(stringValue('true'), DOUBLE_TYPE); - }).toThrow(); - const value = doubleValue(1234.5); - expect(convertDoubleValueToType(value, DOUBLE_TYPE)).toEqual(value); - expect(convertDoubleValueToType(value, STRING_TYPE)).toEqual( - stringValue('1234.5') + const value = new DoubleRefVal(1234.5); + expect(value.convertToType(DOUBLE_REF_TYPE)).toStrictEqual(value); + expect(value.convertToType(STRING_REF_TYPE)).toStrictEqual( + new StringRefVal('1234.5') ); - expect(convertDoubleValueToType(value, TYPE_TYPE)).toEqual(DOUBLE_TYPE); - // Int64 errors - expect(convertDoubleValueToType(doubleValue(NaN), INT64_TYPE)).toEqual( - new Error('integer overflow') + expect(value.convertToType(TYPE_REF_TYPE)).toStrictEqual( + new TypeRefVal(DOUBLE_REF_TYPE) ); - expect(convertDoubleValueToType(doubleValue(Infinity), INT64_TYPE)).toEqual( - new Error('integer overflow') + // Int64 errors + expect(new DoubleRefVal(NaN).convertToType(INT_REF_TYPE)).toStrictEqual( + ErrorRefVal.errIntOverflow ); expect( - convertDoubleValueToType(doubleValue(-Infinity), INT64_TYPE) - ).toEqual(new Error('integer overflow')); + new DoubleRefVal(Infinity).convertToType(INT_REF_TYPE) + ).toStrictEqual(ErrorRefVal.errIntOverflow); + expect( + new DoubleRefVal(-Infinity).convertToType(INT_REF_TYPE) + ).toStrictEqual(ErrorRefVal.errIntOverflow); expect( - convertDoubleValueToType(doubleValue(Number.MAX_VALUE), INT64_TYPE) - ).toEqual(new Error('integer overflow')); + new DoubleRefVal(Number.MAX_VALUE).convertToType(INT_REF_TYPE) + ).toStrictEqual(ErrorRefVal.errIntOverflow); expect( - convertDoubleValueToType(doubleValue(-1 * Number.MAX_VALUE), INT64_TYPE) - ).toEqual(new Error('integer overflow')); + new DoubleRefVal(-1 * Number.MAX_VALUE).convertToType(INT_REF_TYPE) + ).toStrictEqual(ErrorRefVal.errIntOverflow); // Uint64 errors - expect(convertDoubleValueToType(doubleValue(NaN), UINT64_TYPE)).toEqual( - new Error('unsigned integer overflow') + expect(new DoubleRefVal(NaN).convertToType(UINT_REF_TYPE)).toStrictEqual( + ErrorRefVal.errUintOverflow ); expect( - convertDoubleValueToType(doubleValue(Infinity), UINT64_TYPE) - ).toEqual(new Error('unsigned integer overflow')); - expect(convertDoubleValueToType(doubleValue(-1), UINT64_TYPE)).toEqual( - new Error('unsigned integer overflow') + new DoubleRefVal(Infinity).convertToType(UINT_REF_TYPE) + ).toStrictEqual(ErrorRefVal.errUintOverflow); + expect(new DoubleRefVal(-1).convertToType(UINT_REF_TYPE)).toStrictEqual( + ErrorRefVal.errUintOverflow ); expect( - convertDoubleValueToType(doubleValue(Number.MAX_VALUE), UINT64_TYPE) - ).toEqual(new Error('unsigned integer overflow')); + new DoubleRefVal(Number.MAX_VALUE).convertToType(UINT_REF_TYPE) + ).toStrictEqual(ErrorRefVal.errUintOverflow); }); it('equalDoubleValue', () => { - expect(() => { - equalDoubleValue(stringValue('foo'), doubleValue(1)); - }).toThrow(); const testCases = [ { - a: doubleValue(-10), - b: doubleValue(-10), - out: boolValue(true), + a: new DoubleRefVal(-10), + b: new DoubleRefVal(-10), + out: new BoolRefVal(true), }, { - a: doubleValue(-10), - b: doubleValue(10), - out: boolValue(false), + a: new DoubleRefVal(-10), + b: new DoubleRefVal(10), + out: new BoolRefVal(false), }, { - a: doubleValue(10), - b: uint64Value(BigInt(10)), - out: boolValue(true), + a: new DoubleRefVal(10), + b: new UintRefVal(BigInt(10)), + out: new BoolRefVal(true), }, { - a: doubleValue(9), - b: uint64Value(BigInt(10)), - out: boolValue(false), + a: new DoubleRefVal(9), + b: new UintRefVal(BigInt(10)), + out: new BoolRefVal(false), }, { - a: doubleValue(10), - b: int64Value(BigInt(10)), - out: boolValue(true), + a: new DoubleRefVal(10), + b: new IntRefVal(BigInt(10)), + out: new BoolRefVal(true), }, { - a: doubleValue(10), - b: int64Value(BigInt(-15)), - out: boolValue(false), + a: new DoubleRefVal(10), + b: new IntRefVal(BigInt(-15)), + out: new BoolRefVal(false), }, { - a: doubleValue(NaN), - b: int64Value(BigInt(10)), - out: boolValue(false), + a: new DoubleRefVal(NaN), + b: new IntRefVal(BigInt(10)), + out: new BoolRefVal(false), }, { - a: doubleValue(10), - b: doubleValue(NaN), - out: boolValue(false), + a: new DoubleRefVal(10), + b: new DoubleRefVal(NaN), + out: new BoolRefVal(false), }, ]; for (const testCase of testCases) { - expect(equalDoubleValue(testCase.a, testCase.b)).toEqual(testCase.out); + expect(testCase.a.equal(testCase.b)).toStrictEqual(testCase.out); } }); it('isZeroDoubleValue', () => { - expect(() => { - isZeroDoubleValue(stringValue('foo')); - }).toThrow(); - expect(isZeroDoubleValue(doubleValue(0))).toEqual(boolValue(true)); - expect(isZeroDoubleValue(doubleValue(1))).toEqual(boolValue(false)); + expect(new DoubleRefVal(0).isZeroValue()).toEqual(true); + expect(new DoubleRefVal(1).isZeroValue()).toEqual(false); }); it('addDoubleValue', () => { - expect(() => { - addDoubleValue(stringValue('foo'), doubleValue(1)); - }).toThrow(); - expect(addDoubleValue(doubleValue(1), doubleValue(2))).toEqual( - doubleValue(3) + expect(new DoubleRefVal(1).add(new DoubleRefVal(2))).toStrictEqual( + new DoubleRefVal(3) ); - expect(addDoubleValue(doubleValue(1), uint64Value(BigInt(2)))).toEqual( - doubleValue(3) + expect(new DoubleRefVal(1).add(new UintRefVal(BigInt(2)))).toStrictEqual( + new DoubleRefVal(3) ); - expect(addDoubleValue(doubleValue(1), int64Value(BigInt(2)))).toEqual( - doubleValue(3) + expect(new DoubleRefVal(1).add(new IntRefVal(BigInt(2)))).toStrictEqual( + new DoubleRefVal(3) ); - expect(addDoubleValue(doubleValue(1), stringValue('2'))).toEqual( - new Error('no such overload') + expect(new DoubleRefVal(1).add(new StringRefVal('2'))).toStrictEqual( + ErrorRefVal.errNoSuchOverload ); }); it('compareDoubleValue', () => { - expect(() => { - compareDoubleValue(stringValue('foo'), doubleValue(1)); - }).toThrow(); const testCases = [ { - a: doubleValue(42), - b: doubleValue(42), - out: int64Value(BigInt(0)), + a: new DoubleRefVal(42), + b: new DoubleRefVal(42), + out: new IntRefVal(BigInt(0)), }, { - a: doubleValue(42), - b: uint64Value(BigInt(42)), - out: int64Value(BigInt(0)), + a: new DoubleRefVal(42), + b: new UintRefVal(BigInt(42)), + out: new IntRefVal(BigInt(0)), }, { - a: doubleValue(42), - b: int64Value(BigInt(42)), - out: int64Value(BigInt(0)), + a: new DoubleRefVal(42), + b: new IntRefVal(BigInt(42)), + out: new IntRefVal(BigInt(0)), }, { - a: doubleValue(-1300), - b: doubleValue(204), - out: int64Value(BigInt(-1)), + a: new DoubleRefVal(-1300), + b: new DoubleRefVal(204), + out: new IntRefVal(BigInt(-1)), }, { - a: doubleValue(-1300), - b: uint64Value(BigInt(204)), - out: int64Value(BigInt(-1)), + a: new DoubleRefVal(-1300), + b: new UintRefVal(BigInt(204)), + out: new IntRefVal(BigInt(-1)), }, { - a: doubleValue(203.9), - b: int64Value(BigInt(204)), - out: int64Value(BigInt(-1)), + a: new DoubleRefVal(203.9), + b: new IntRefVal(BigInt(204)), + out: new IntRefVal(BigInt(-1)), }, { - a: doubleValue(1300), - b: uint64Value(BigInt(Number.MAX_SAFE_INTEGER + 1)), - out: int64Value(BigInt(-1)), + a: new DoubleRefVal(1300), + b: new UintRefVal(BigInt(Number.MAX_SAFE_INTEGER + 1)), + out: new IntRefVal(BigInt(-1)), }, { - a: doubleValue(204), - b: uint64Value(BigInt(205)), - out: int64Value(BigInt(-1)), + a: new DoubleRefVal(204), + b: new UintRefVal(BigInt(205)), + out: new IntRefVal(BigInt(-1)), }, { - a: doubleValue(204), - b: doubleValue(Number.MAX_SAFE_INTEGER + 1025), - out: int64Value(BigInt(-1)), + a: new DoubleRefVal(204), + b: new DoubleRefVal(Number.MAX_SAFE_INTEGER + 1025), + out: new IntRefVal(BigInt(-1)), }, { - a: doubleValue(204), - b: doubleValue(NaN), - out: new Error('NaN values cannot be ordered'), + a: new DoubleRefVal(204), + b: new DoubleRefVal(NaN), + out: new ErrorRefVal('NaN values cannot be ordered'), }, { - a: doubleValue(NaN), - b: doubleValue(204), - out: new Error('NaN values cannot be ordered'), + a: new DoubleRefVal(NaN), + b: new DoubleRefVal(204), + out: new ErrorRefVal('NaN values cannot be ordered'), }, { - a: doubleValue(204), - b: doubleValue(-1300), - out: int64Value(BigInt(1)), + a: new DoubleRefVal(204), + b: new DoubleRefVal(-1300), + out: new IntRefVal(BigInt(1)), }, { - a: doubleValue(204), - b: uint64Value(BigInt(10)), - out: int64Value(BigInt(1)), + a: new DoubleRefVal(204), + b: new UintRefVal(BigInt(10)), + out: new IntRefVal(BigInt(1)), }, { - a: doubleValue(204.1), - b: int64Value(BigInt(204)), - out: int64Value(BigInt(1)), + a: new DoubleRefVal(204.1), + b: new IntRefVal(BigInt(204)), + out: new IntRefVal(BigInt(1)), }, { - a: doubleValue(1), - b: stringValue('1'), - out: new Error('no such overload'), + a: new DoubleRefVal(1), + b: new StringRefVal('1'), + out: ErrorRefVal.errNoSuchOverload, }, ]; for (const testCase of testCases) { - expect(compareDoubleValue(testCase.a, testCase.b)).toEqual(testCase.out); + expect(testCase.a.compare(testCase.b)).toStrictEqual(testCase.out); } }); it('divideDoubleValue', () => { - expect(() => { - divideDoubleValue(stringValue('foo'), doubleValue(1)); - }).toThrow(); - expect(divideDoubleValue(doubleValue(1), doubleValue(2))).toEqual( - doubleValue(0.5) + expect(new DoubleRefVal(1).divide(new DoubleRefVal(2))).toStrictEqual( + new DoubleRefVal(0.5) ); - expect(divideDoubleValue(doubleValue(1), uint64Value(BigInt(2)))).toEqual( - doubleValue(0.5) + expect(new DoubleRefVal(1).divide(new UintRefVal(BigInt(2)))).toStrictEqual( + new DoubleRefVal(0.5) ); - expect(divideDoubleValue(doubleValue(1), int64Value(BigInt(2)))).toEqual( - doubleValue(0.5) + expect(new DoubleRefVal(1).divide(new IntRefVal(BigInt(2)))).toStrictEqual( + new DoubleRefVal(0.5) ); - expect(divideDoubleValue(doubleValue(1), stringValue('2'))).toEqual( - new Error('no such overload') + expect(new DoubleRefVal(1).divide(new StringRefVal('2'))).toStrictEqual( + ErrorRefVal.errNoSuchOverload ); - expect(divideDoubleValue(doubleValue(1), doubleValue(0))).toEqual( - doubleValue(Infinity) + expect(new DoubleRefVal(1).divide(new DoubleRefVal(0))).toStrictEqual( + new DoubleRefVal(Infinity) ); }); it('multiplyDoubleValue', () => { - expect(() => { - multiplyDoubleValue(stringValue('foo'), doubleValue(1)); - }).toThrow(); - expect(multiplyDoubleValue(doubleValue(2), doubleValue(21))).toEqual( - doubleValue(42) + expect(new DoubleRefVal(2).multiply(new DoubleRefVal(21))).toStrictEqual( + new DoubleRefVal(42) ); expect( - multiplyDoubleValue(doubleValue(2), uint64Value(BigInt(21))) - ).toEqual(doubleValue(42)); - expect(multiplyDoubleValue(doubleValue(2), int64Value(BigInt(21)))).toEqual( - doubleValue(42) - ); - expect(multiplyDoubleValue(doubleValue(2), stringValue('21'))).toEqual( - new Error('no such overload') + new DoubleRefVal(2).multiply(new UintRefVal(BigInt(21))) + ).toStrictEqual(new DoubleRefVal(42)); + expect( + new DoubleRefVal(2).multiply(new IntRefVal(BigInt(21))) + ).toStrictEqual(new DoubleRefVal(42)); + expect(new DoubleRefVal(2).multiply(new StringRefVal('21'))).toStrictEqual( + ErrorRefVal.errNoSuchOverload ); }); }); diff --git a/packages/cel/src/lib/common/types/double.ts b/packages/cel/src/lib/common/types/double.ts index f309b78..80616c6 100644 --- a/packages/cel/src/lib/common/types/double.ts +++ b/packages/cel/src/lib/common/types/double.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-case-declarations */ import { Type, Type_PrimitiveType, @@ -20,17 +21,23 @@ import { anyPack, } from '@bufbuild/protobuf/wkt'; import { formatCELType } from '../format'; -import { boolValue } from './bool'; -import { compareNumberValues } from './compare'; -import { int64Value, isValidInt64 } from './int'; +import { RefType, RefTypeEnum, RefVal } from '../ref/reference'; +import { BoolRefVal, boolValue } from './bool'; +import { compareNumberRefVals, compareNumberValues } from './compare'; +import { ErrorRefVal } from './error'; +import { IntRefVal, int64Value, isValidInt64 } from './int'; import { NativeType } from './native'; import { isNumberValue } from './number'; import { primitiveType } from './primitive'; -import { stringValue } from './string'; +import { StringRefVal, stringValue } from './string'; +import { Comparer } from './traits/comparer'; +import { Adder, Divider, Multiplier, Negater, Subtractor } from './traits/math'; import { Trait } from './traits/trait'; -import { isValidUint64, uint64Value } from './uint'; +import { Zeroer } from './traits/zeroer'; +import { TypeRefVal } from './type'; +import { UintRefVal, isValidUint64, uint64Value } from './uint'; -export const DOUBLE_TYPE = primitiveType(Type_PrimitiveType.DOUBLE); +export const DOUBLE_CEL_TYPE = primitiveType(Type_PrimitiveType.DOUBLE); export function isDoubleType(val: Type): val is Type & { typeKind: { case: 'primitive'; value: Type_PrimitiveType.DOUBLE }; @@ -121,7 +128,7 @@ export function convertDoubleValueToNative(value: Value, type: NativeType) { break; } return new Error( - `type conversion error from '${formatCELType(DOUBLE_TYPE)}' to '${ + `type conversion error from '${formatCELType(DOUBLE_CEL_TYPE)}' to '${ type.name }'` ); @@ -162,13 +169,13 @@ export function convertDoubleValueToType(value: Value, type: Type) { } break; case 'type': - return DOUBLE_TYPE; + return DOUBLE_CEL_TYPE; default: break; } return new Error( `type conversion error from '${formatCELType( - DOUBLE_TYPE + DOUBLE_CEL_TYPE )}' to '${formatCELType(type)}'` ); } @@ -277,3 +284,201 @@ export function subtractDoubleValue(value: Value, other: Value) { } return doubleValue(value.kind.value - Number(other.kind.value)); } + +export class DoubleRefType implements RefType { + // This has to be a TS private field instead of a # private field because + // otherwise the tests will not be able to access it to check for equality. + // TODO: do we want to alter the tests to use the getter instead? + readonly _traits = DOUBLE_TRAITS; + + celType(): Type { + return DOUBLE_CEL_TYPE; + } + + hasTrait(trait: Trait): boolean { + return this._traits.has(trait); + } + + typeName(): string { + return RefTypeEnum.DOUBLE; + } +} + +export const DOUBLE_REF_TYPE = new DoubleRefType(); + +export class DoubleRefVal + implements + RefVal, + Adder, + Comparer, + Divider, + Multiplier, + Negater, + Subtractor, + Zeroer +{ + // This has to be a TS private field instead of a # private field because + // otherwise the tests will not be able to access it to check for equality. + // TODO: do we want to alter the tests to use the getter instead? + private readonly _value: number; + + constructor(value: number) { + this._value = value; + } + + celValue(): Value { + return doubleValue(this._value); + } + + convertToNative(type: NativeType) { + switch (type) { + case Number: + return this._value; + case AnySchema: + return anyPack( + DoubleValueSchema, + create(DoubleValueSchema, { value: this._value }) + ); + case DoubleValueSchema: + return create(DoubleValueSchema, { value: this._value }); + case FloatValueSchema: + return create(FloatValueSchema, { value: this._value }); + default: + return ErrorRefVal.nativeTypeConversionError(this, type); + } + } + + convertToType(type: RefType): RefVal { + switch (type.typeName()) { + case RefTypeEnum.DOUBLE: + return new DoubleRefVal(this._value); + case RefTypeEnum.INT: + if ( + Number.isNaN(this._value) || + this._value >= Infinity || + this._value <= -Infinity || + !isValidInt64(BigInt(this._value)) + ) { + return ErrorRefVal.errIntOverflow; + } + return new IntRefVal(BigInt(this._value)); + case RefTypeEnum.STRING: + return new StringRefVal(this._value.toString()); + case RefTypeEnum.TYPE: + return new TypeRefVal(DOUBLE_REF_TYPE); + case RefTypeEnum.UINT: + if ( + Number.isNaN(this.value()) || + this.value() >= Infinity || + !isValidUint64(BigInt(this.value())) + ) { + return ErrorRefVal.errUintOverflow; + } + return new UintRefVal(BigInt(this.value())); + default: + return ErrorRefVal.typeConversionError(this, type); + } + } + + equal(other: RefVal): RefVal { + if (Number.isNaN(this._value) || Number.isNaN(other.value())) { + return BoolRefVal.False; + } + switch (other.type().typeName()) { + case RefTypeEnum.DOUBLE: + case RefTypeEnum.INT: + case RefTypeEnum.UINT: + const compared = compareNumberRefVals(this, other); + if (compared.type().typeName() === RefTypeEnum.ERR) { + return compared; + } + return new BoolRefVal(compared.value() === BigInt(0)); + default: + return BoolRefVal.False; + } + } + + type(): RefType { + return DOUBLE_REF_TYPE; + } + + value() { + return this._value; + } + + add(other: RefVal): RefVal { + switch (other.type().typeName()) { + case RefTypeEnum.DOUBLE: + case RefTypeEnum.INT: + case RefTypeEnum.UINT: + return new DoubleRefVal(this._value + Number(other.value())); + default: + return ErrorRefVal.maybeNoSuchOverload(other); + } + } + + compare(other: RefVal): RefVal { + if ( + Number.isNaN(Number(this._value)) || + Number.isNaN(Number(other.value())) + ) { + return new ErrorRefVal('NaN values cannot be ordered'); + } + switch (other.type().typeName()) { + case RefTypeEnum.DOUBLE: + if (this._value < Number.MIN_SAFE_INTEGER) { + return IntRefVal.IntNegOne; + } + if (this._value > Number.MAX_SAFE_INTEGER) { + return IntRefVal.IntOne; + } + return compareNumberRefVals(this, other); + case RefTypeEnum.INT: + case RefTypeEnum.UINT: + return compareNumberRefVals(this, other); + default: + return ErrorRefVal.maybeNoSuchOverload(other); + } + } + + divide(denominator: RefVal): RefVal { + switch (denominator.type().typeName()) { + case RefTypeEnum.DOUBLE: + case RefTypeEnum.INT: + case RefTypeEnum.UINT: + return new DoubleRefVal(this._value / Number(denominator.value())); + default: + return ErrorRefVal.maybeNoSuchOverload(denominator); + } + } + + multiply(other: RefVal): RefVal { + switch (other.type().typeName()) { + case RefTypeEnum.DOUBLE: + case RefTypeEnum.INT: + case RefTypeEnum.UINT: + return new DoubleRefVal(this._value * Number(other.value())); + default: + return ErrorRefVal.maybeNoSuchOverload(other); + } + } + + negate(): RefVal { + return new DoubleRefVal(-this._value); + } + + subtract(subtrahend: RefVal): RefVal { + switch (subtrahend.type().typeName()) { + case RefTypeEnum.DOUBLE: + case RefTypeEnum.INT: + case RefTypeEnum.UINT: + return new DoubleRefVal(this._value - Number(subtrahend.value())); + default: + return ErrorRefVal.maybeNoSuchOverload(subtrahend); + } + } + + isZeroValue(): boolean { + return this._value === 0; + } +} diff --git a/packages/cel/src/lib/common/types/duration.spec.ts b/packages/cel/src/lib/common/types/duration.spec.ts index eaa1187..21c4aea 100644 --- a/packages/cel/src/lib/common/types/duration.spec.ts +++ b/packages/cel/src/lib/common/types/duration.spec.ts @@ -1,12 +1,29 @@ import { create } from '@bufbuild/protobuf'; -import { DurationSchema, anyPack } from '@bufbuild/protobuf/wkt'; -import { convertDurationValueToType, durationValue } from './duration'; -import { INT64_TYPE, int64Value } from './int'; +import { AnySchema, DurationSchema, anyPack } from '@bufbuild/protobuf/wkt'; +import { + DURATION_TO_HOURS_OVERLOAD, + DURATION_TO_MILLISECONDS_OVERLOAD, + DURATION_TO_MINUTES_OVERLOAD, + DURATION_TO_SECONDS_OVERLOAD, + TIME_GET_HOURS_OVERLOAD, + TIME_GET_MILLISECONDS_OVERLOAD, + TIME_GET_MINUTES_OVERLOAD, + TIME_GET_SECONDS_OVERLOAD, +} from '../../overloads'; +import { BOOL_REF_TYPE, BoolRefVal } from './bool'; +import { + DURATION_REF_TYPE, + DurationRefVal, + duration, + durationFromNanos, + durationValue, +} from './duration'; +import { ErrorRefVal } from './error'; +import { INT_REF_TYPE, IntRefVal, MAX_INT64, MIN_INT64 } from './int'; import { objectValue } from './object'; -import { STRING_TYPE, stringValue } from './string'; -import { TYPE_TYPE } from './type'; -import { UINT64_TYPE } from './uint'; -import { DURATION_TYPE } from './wkt'; +import { STRING_REF_TYPE, StringRefVal } from './string'; +import { TYPE_REF_TYPE, TypeRefVal } from './type'; +import { UINT_REF_TYPE, UintRefVal } from './uint'; describe('duration', () => { it('durationValue', () => { @@ -22,47 +39,223 @@ describe('duration', () => { // TODO: validations - // TODO: convertDurationValueToNative + it('convertDurationValueToNative', () => { + const tests = [ + { + value: new DurationRefVal(duration(BigInt(42), 1234)), + type: BigInt, + want: BigInt(42 * 1e9) + BigInt(1234), + }, + { + value: new DurationRefVal(duration(BigInt(867), 5309)), + type: AnySchema, + want: anyPack(DurationSchema, duration(BigInt(867), 5309)), + }, + { + value: new DurationRefVal(duration(BigInt(776), 2323)), + type: DurationSchema, + want: duration(BigInt(776), 2323), + }, + { + value: new DurationRefVal(duration(BigInt(42), 1234)), + type: String, + want: `42.000001234s`, + }, + { + value: new DurationRefVal(duration(BigInt(42), 1234)), + type: Boolean, + want: ErrorRefVal.errNoSuchOverload, + }, + ]; + for (const test of tests) { + expect(test.value.convertToNative(test.type)).toStrictEqual(test.want); + } + }); it('convertDurationValueToType', () => { - expect(() => { - convertDurationValueToType(stringValue('foo'), INT64_TYPE); - }).toThrow(); + const tests = [ + { + value: new DurationRefVal(duration(BigInt(42))), + type: STRING_REF_TYPE, + want: new StringRefVal('42s'), + }, + { + value: new DurationRefVal(duration(BigInt(42), 1234)), + type: STRING_REF_TYPE, + want: new StringRefVal('42.000001234s'), + }, + { + value: new DurationRefVal(duration(BigInt(42), 1234)), + type: INT_REF_TYPE, + want: new IntRefVal(BigInt(42000001234)), + }, + { + value: new DurationRefVal(duration(BigInt(42), 1234)), + type: DURATION_REF_TYPE, + want: new DurationRefVal(duration(BigInt(42), 1234)), + }, + { + value: new DurationRefVal(duration(BigInt(42), 1234)), + type: TYPE_REF_TYPE, + want: new TypeRefVal(DURATION_REF_TYPE), + }, + { + value: new DurationRefVal(duration(BigInt(42), 1234)), + type: UINT_REF_TYPE, + want: new UintRefVal(BigInt(42 * 1e9) + BigInt(1234)), + }, + { + value: new DurationRefVal(duration(BigInt(42), 1234)), + type: BOOL_REF_TYPE, + want: ErrorRefVal.errNoSuchOverload, + }, + ]; + for (const test of tests) { + expect(test.value.convertToType(test.type)).toStrictEqual(test.want); + } + }); + + it('equalDurationValue', () => { + expect( + new DurationRefVal(duration(BigInt(42))).equal( + new DurationRefVal(duration(BigInt(42))) + ) + ).toStrictEqual(new BoolRefVal(true)); + expect( + new DurationRefVal(duration(BigInt(42))).equal( + new DurationRefVal(duration(BigInt(43))) + ) + ).toStrictEqual(new BoolRefVal(false)); + expect( + new DurationRefVal(duration(BigInt(42))).equal(new BoolRefVal(true)) + ).toStrictEqual(BoolRefVal.False); + }); + + it('addDurationValue', () => { + expect( + new DurationRefVal(duration(BigInt(42))).add( + new DurationRefVal(duration(BigInt(43))) + ) + ).toStrictEqual(new DurationRefVal(duration(BigInt(85)))); + expect( + new DurationRefVal(duration(MAX_INT64)).add( + new DurationRefVal(duration(BigInt(0), 1)) + ) + ).toStrictEqual(ErrorRefVal.errIntOverflow); + expect( + new DurationRefVal(duration(MAX_INT64)).add( + new DurationRefVal(duration(BigInt(1))) + ) + ).toStrictEqual(ErrorRefVal.errIntOverflow); + expect( + new DurationRefVal(duration(MIN_INT64)).add( + new DurationRefVal(duration(BigInt(0), -1)) + ) + ).toStrictEqual(ErrorRefVal.errIntOverflow); + expect( + new DurationRefVal(duration(MIN_INT64)).add( + new DurationRefVal(duration(BigInt(-1))) + ) + ).toStrictEqual(ErrorRefVal.errIntOverflow); + // TODO: timestamps + }); + + it('compareDurationValue', () => { + expect( + new DurationRefVal(duration(BigInt(42))).compare( + new DurationRefVal(duration(BigInt(42))) + ) + ).toStrictEqual(IntRefVal.IntZero); expect( - convertDurationValueToType( - durationValue({ seconds: BigInt(42) }), - STRING_TYPE + new DurationRefVal(duration(BigInt(42))).compare( + new DurationRefVal(duration(BigInt(43))) ) - ).toEqual(stringValue('42s')); + ).toStrictEqual(IntRefVal.IntNegOne); expect( - convertDurationValueToType( - durationValue({ seconds: BigInt(7506), nanos: 1000 }), - STRING_TYPE + new DurationRefVal(duration(BigInt(43))).compare( + new DurationRefVal(duration(BigInt(42))) ) - ).toEqual(stringValue('7506.000001s')); + ).toStrictEqual(IntRefVal.IntOne); + }); + + it('negateDurationValue', () => { + expect(new DurationRefVal(duration(BigInt(42))).negate()).toStrictEqual( + new DurationRefVal(duration(BigInt(-42))) + ); + expect( + new DurationRefVal(durationFromNanos(MIN_INT64)).negate() + ).toStrictEqual(ErrorRefVal.errIntOverflow); + }); + + it('durationGetHours', () => { + expect( + new DurationRefVal(duration(BigInt(7506))) + .receive(TIME_GET_HOURS_OVERLOAD, DURATION_TO_HOURS_OVERLOAD, []) + .value() + ).toStrictEqual(new IntRefVal(BigInt(2)).value()); + }); + + it('durationGetMinutes', () => { + expect( + new DurationRefVal(duration(BigInt(7506))) + .receive(TIME_GET_MINUTES_OVERLOAD, DURATION_TO_MINUTES_OVERLOAD, []) + .value() + ).toStrictEqual(new IntRefVal(BigInt(125)).value()); + }); + + it('durationGetSeconds', () => { expect( - convertDurationValueToType( - durationValue({ seconds: BigInt(7506), nanos: 1000 }), - INT64_TYPE + new DurationRefVal(duration(BigInt(7506))) + .receive(TIME_GET_SECONDS_OVERLOAD, DURATION_TO_SECONDS_OVERLOAD, []) + .value() + ).toStrictEqual(new IntRefVal(BigInt(7506)).value()); + }); + + it('durationGetMilliseconds', () => { + expect( + new DurationRefVal(duration(BigInt(7506))) + .receive( + TIME_GET_MILLISECONDS_OVERLOAD, + DURATION_TO_MILLISECONDS_OVERLOAD, + [] + ) + .value() + ).toStrictEqual(new IntRefVal(BigInt(7506000)).value()); + }); + + it('subtractDurationValue', () => { + expect( + new DurationRefVal(duration(BigInt(42))).subtract( + new DurationRefVal(duration(BigInt(43))) + ) + ).toStrictEqual(new DurationRefVal(duration(BigInt(-1)))); + expect( + new DurationRefVal(duration(MAX_INT64)).subtract( + new DurationRefVal(duration(BigInt(0), -1)) ) - ).toEqual(int64Value(BigInt(7506000001000))); + ).toStrictEqual(ErrorRefVal.errIntOverflow); expect( - convertDurationValueToType( - durationValue({ seconds: BigInt(42) }), - DURATION_TYPE + new DurationRefVal(duration(MAX_INT64)).subtract( + new DurationRefVal(duration(BigInt(-1))) ) - ).toEqual(durationValue({ seconds: BigInt(42) })); + ).toStrictEqual(ErrorRefVal.errIntOverflow); expect( - convertDurationValueToType( - durationValue({ seconds: BigInt(42) }), - TYPE_TYPE + new DurationRefVal(duration(MIN_INT64)).subtract( + new DurationRefVal(duration(BigInt(0), 1)) ) - ).toEqual(DURATION_TYPE); + ).toStrictEqual(ErrorRefVal.errIntOverflow); expect( - convertDurationValueToType( - durationValue({ seconds: BigInt(42) }), - UINT64_TYPE + new DurationRefVal(duration(MIN_INT64)).subtract( + new DurationRefVal(duration(BigInt(1))) ) - ).toEqual(new Error(`type conversion error from 'duration' to 'uint'`)); + ).toStrictEqual(ErrorRefVal.errIntOverflow); + // TODO: timestamps + }); + + it('durationValueIsZero', () => { + expect(new DurationRefVal(duration(BigInt(0))).isZeroValue()).toEqual(true); + expect(new DurationRefVal(duration(BigInt(1))).isZeroValue()).toEqual( + false + ); }); }); diff --git a/packages/cel/src/lib/common/types/duration.ts b/packages/cel/src/lib/common/types/duration.ts index 00ec19f..0c64f2e 100644 --- a/packages/cel/src/lib/common/types/duration.ts +++ b/packages/cel/src/lib/common/types/duration.ts @@ -2,6 +2,7 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import { Type, + TypeSchema, Type_PrimitiveType, Type_WellKnownType, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; @@ -19,22 +20,49 @@ import { anyUnpack, } from '@bufbuild/protobuf/wkt'; import { - toSeconds as durationToSeconds, - parse as parseDuration, + toSeconds as iso8601durationToSeconds, + parse as parseIso8601Duration, } from 'iso8601-duration'; +import { + TIME_GET_HOURS_OVERLOAD, + TIME_GET_MILLISECONDS_OVERLOAD, + TIME_GET_MINUTES_OVERLOAD, + TIME_GET_SECONDS_OVERLOAD, +} from '../../overloads'; import { formatCELType } from '../format'; -import { int64Value } from './int'; +import { RefType, RefTypeEnum, RefVal } from '../ref/reference'; +import { BoolRefVal } from './bool'; +import { ErrorRefVal } from './error'; +import { IntRefVal, MAX_INT64, MIN_INT64, int64Value } from './int'; import { NativeType } from './native'; import { isObjectValue } from './object'; -import { stringValue } from './string'; +import { StringRefVal, stringValue } from './string'; +import { Comparer } from './traits/comparer'; +import { Adder, Negater, Subtractor } from './traits/math'; +import { Receiver } from './traits/receiver'; +import { Trait } from './traits/trait'; +import { Zeroer } from './traits/zeroer'; +import { TypeRefVal } from './type'; +import { UintRefVal } from './uint'; import { typeNameToUrl } from './utils'; import { DURATION_TYPE, WKT_REGISTRY } from './wkt'; +export const DURATION_CEL_TYPE = create(TypeSchema, { + typeKind: { + case: 'wellKnown', + value: Type_WellKnownType.DURATION, + }, +}); + +export function duration(seconds?: bigint, nanos?: number) { + return create(DurationSchema, { seconds, nanos }); +} + export function durationValue(init: MessageInitShape) { return create(ValueSchema, { kind: { case: 'objectValue', - value: anyPack(DurationSchema, create(DurationSchema, init)), + value: anyPack(DurationSchema, duration(init.seconds, init.nanos)), }, }); } @@ -117,23 +145,237 @@ export function convertDurationValueToType(value: Value, type: Type) { export function parseISO8061DurationString(text: string) { try { - const duration = parseDuration(`P${text.toUpperCase()}`); - const seconds = durationToSeconds(duration); - return create(DurationSchema, { - seconds: BigInt(Math.trunc(seconds)), - nanos: Math.trunc((seconds % 1) * 1e9), - }); + const duration = parseIso8601Duration(`P${text.toUpperCase()}`); + const seconds = iso8601durationToSeconds(duration); + return durationFromSeconds(seconds); } catch { try { - const duration = parseDuration(`PT${text.toUpperCase()}`); - const seconds = durationToSeconds(duration); - return create(DurationSchema, { - seconds: BigInt(Math.trunc(seconds)), - nanos: Math.trunc((seconds % 1) * 1e9), - }); + const duration = parseIso8601Duration(`PT${text.toUpperCase()}`); + const seconds = iso8601durationToSeconds(duration); + return durationFromSeconds(seconds); } catch (e) { console.log(e); return new Error(`cannot parse duration: ${text}`); } } } + +export function durationFromNanos(nanos: bigint) { + return duration(nanos / BigInt(1e9), Number(nanos % BigInt(1e9))); +} + +export function durationFromSeconds(seconds: number) { + return duration(BigInt(Math.trunc(seconds)), Math.trunc((seconds % 1) * 1e9)); +} + +export function durationToNanos(duration: Duration) { + return duration.seconds * BigInt(1e9) + BigInt(duration.nanos); +} + +export function durationToSeconds(duration: Duration) { + return Number(duration.seconds) + duration.nanos * 1e-9; +} + +export const DURATION_TRAITS = new Set([ + Trait.ADDER_TYPE, + Trait.COMPARER_TYPE, + Trait.NEGATER_TYPE, + Trait.RECEIVER_TYPE, + Trait.SUBTRACTOR_TYPE, +]); + +export class DurationRefType implements RefType { + // This has to be a TS private field instead of a # private field because + // otherwise the tests will not be able to access it to check for equality. + // TODO: do we want to alter the tests to use the getter instead? + readonly _traits = new Set(); + + celType(): Type { + return DURATION_CEL_TYPE; + } + + hasTrait(trait: Trait): boolean { + return this._traits.has(trait); + } + + typeName(): string { + return RefTypeEnum.DURATION; + } +} + +export const DURATION_REF_TYPE = new DurationRefType(); + +export class DurationRefVal + implements RefVal, Adder, Comparer, Negater, Receiver, Subtractor, Zeroer +{ + // This has to be a TS private field instead of a # private field because + // otherwise the tests will not be able to access it to check for equality. + // TODO: do we want to alter the tests to use the getter instead? + private readonly _value: Duration; + + constructor(value: Duration) { + this._value = value; + } + + static durationGetHours(duration: Duration) { + const nanos = durationToNanos(duration); + return new IntRefVal(nanos / BigInt(1e9 * 60 * 60)); + } + + static durationGetMinutes(duration: Duration) { + const nanos = durationToNanos(duration); + return new IntRefVal(nanos / BigInt(1e9 * 60)); + } + + static durationGetSeconds(duration: Duration) { + const nanos = durationToNanos(duration); + return new IntRefVal(nanos / BigInt(1e9)); + } + + static durationGetMilliseconds(duration: Duration) { + const nanos = durationToNanos(duration); + return new IntRefVal(nanos / BigInt(1e6)); + } + + static Overloads = new Map([ + [TIME_GET_HOURS_OVERLOAD, DurationRefVal.durationGetHours], + [TIME_GET_MINUTES_OVERLOAD, DurationRefVal.durationGetMinutes], + [TIME_GET_SECONDS_OVERLOAD, DurationRefVal.durationGetSeconds], + [TIME_GET_MILLISECONDS_OVERLOAD, DurationRefVal.durationGetMilliseconds], + ]); + + celValue(): Value { + return durationValue(this._value); + } + + convertToNative(type: NativeType) { + switch (type) { + case BigInt: + return durationToNanos(this._value); + case String: + return `${durationToSeconds(this._value)}s`; + case AnySchema: + return anyPack(DurationSchema, this._value); + case DurationSchema: + return clone(DurationSchema, this._value); + default: + return ErrorRefVal.nativeTypeConversionError(this, type); + } + } + + convertToType(type: RefType): RefVal { + switch (type.typeName()) { + case RefTypeEnum.DURATION: + return new DurationRefVal(this._value); + case RefTypeEnum.INT: + return new IntRefVal(durationToNanos(this._value)); + case RefTypeEnum.STRING: + return new StringRefVal(`${durationToSeconds(this._value)}s`); + case RefTypeEnum.TYPE: + return new TypeRefVal(DURATION_REF_TYPE); + case RefTypeEnum.UINT: + return new UintRefVal(durationToNanos(this._value)); + default: + return ErrorRefVal.typeConversionError(this, type); + } + } + + equal(other: RefVal): RefVal { + switch (other.type().typeName()) { + case RefTypeEnum.DURATION: + return new BoolRefVal( + this._value.seconds === other.value().seconds && + this._value.nanos === other.value().nanos + ); + default: + return BoolRefVal.False; + } + } + + type(): RefType { + return DURATION_REF_TYPE; + } + + value() { + return this._value; + } + + add(other: RefVal): RefVal { + switch (other.type().typeName()) { + case RefTypeEnum.DURATION: + const thisNanos = durationToNanos(this._value); + const otherNanos = durationToNanos(other.value()); + if ( + (otherNanos > 0 && thisNanos > MAX_INT64 - BigInt(otherNanos)) || + (otherNanos < 0 && thisNanos < MIN_INT64 - BigInt(otherNanos)) + ) { + return ErrorRefVal.errIntOverflow; + } + return new DurationRefVal(durationFromNanos(thisNanos + otherNanos)); + // TODO: timestamp + default: + return ErrorRefVal.maybeNoSuchOverload(other); + } + } + + compare(other: RefVal): RefVal { + switch (other.type().typeName()) { + case RefTypeEnum.DURATION: + const d1 = durationToNanos(this._value); + const d2 = durationToNanos(other.value()); + if (d1 < d2) { + return IntRefVal.IntNegOne; + } + if (d1 > d2) { + return IntRefVal.IntOne; + } + return IntRefVal.IntZero; + default: + return ErrorRefVal.maybeNoSuchOverload(other); + } + } + + negate(): RefVal { + const nanos = durationToNanos(this._value); + if (nanos === MIN_INT64) { + return ErrorRefVal.errIntOverflow; + } + return new DurationRefVal(durationFromNanos(-nanos)); + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + receive(fn: string, overload: string, args: RefVal[]): RefVal { + const f = DurationRefVal.Overloads.get(fn); + if (f) { + return f(this._value); + } + return ErrorRefVal.errNoSuchOverload; + } + + subtract(subtrahend: RefVal): RefVal { + switch (subtrahend.type().typeName()) { + case RefTypeEnum.DURATION: + const thisNanos = durationToNanos(this._value); + const otherNanos = durationToNanos(subtrahend.value()); + if ( + (otherNanos < 0 && thisNanos > MAX_INT64 + BigInt(otherNanos)) || + (otherNanos > 0 && thisNanos < MIN_INT64 + BigInt(otherNanos)) + ) { + return ErrorRefVal.errIntOverflow; + } + return new DurationRefVal( + duration( + this._value.seconds - subtrahend.value().seconds, + this._value.nanos - subtrahend.value().nanos + ) + ); + // TODO: timestamp + default: + return ErrorRefVal.maybeNoSuchOverload(subtrahend); + } + } + + isZeroValue(): boolean { + return durationToNanos(this._value) === BigInt(0); + } +} diff --git a/packages/cel/src/lib/common/types/error.ts b/packages/cel/src/lib/common/types/error.ts index cb3959f..2af7c0d 100644 --- a/packages/cel/src/lib/common/types/error.ts +++ b/packages/cel/src/lib/common/types/error.ts @@ -1,9 +1,19 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { isNil } from '@bearclaw/is'; import { Type, TypeSchema, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; +import { ErrorSetSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/eval_pb'; +import { + Value, + ValueSchema, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb'; import { create } from '@bufbuild/protobuf'; -import { Empty, EmptySchema } from '@bufbuild/protobuf/wkt'; +import { Empty, EmptySchema, anyPack } from '@bufbuild/protobuf/wkt'; +import { RefType, RefTypeEnum, RefVal } from '../ref/reference'; +import { NativeType } from './native'; +import { Trait } from './traits/trait'; export const ERROR_TYPE = create(TypeSchema, { typeKind: { @@ -24,3 +34,179 @@ export function unwrapErrorType(val: Type) { } return null; } + +export class ErrorRefType implements RefType { + #traits = new Set(); + + celType(): Type { + return create(TypeSchema, { + typeKind: { + case: 'error', + value: create(EmptySchema), + }, + }); + } + + hasTrait(trait: Trait): boolean { + return this.#traits.has(trait); + } + + typeName(): string { + return RefTypeEnum.ERR; + } +} + +export const ERROR_REF_TYPE = new ErrorRefType(); + +export class ErrorRefVal implements RefVal { + #val: Error; + + constructor(message: string) { + this.#val = new Error(message); + } + + static errDivideByZero = new ErrorRefVal('divide by zero'); + + static errModulusByZero = new ErrorRefVal('modulus by zero'); + + static errIntOverflow = new ErrorRefVal('integer overflow'); + + static errUintOverflow = new ErrorRefVal('unsigned integer overflow'); + + static errDurationOverflow = new ErrorRefVal('duration overflow'); + + static errDurationOutOfRange = new ErrorRefVal('duration out of range'); + + static errTimestampOverflow = new ErrorRefVal('timestamp overflow'); + + static errTimestampOutOfRange = new ErrorRefVal('timestamp out of range'); + + static errNoMoreElements = new ErrorRefVal('no more elements'); + + static errNoSuchOverload = new ErrorRefVal('no such overload'); + + static nativeTypeConversionError(from: RefVal, to: NativeType) { + return new ErrorRefVal( + `native type conversion error from '${from.type().typeName()}' to '${ + to.name + }'` + ); + } + + static typeConversionError(from: RefVal, to: RefType) { + return new ErrorRefVal( + `type conversion error from '${from + .type() + .typeName()}' to '${to.typeName()}'` + ); + } + + static noSuchMethodOverload(val: RefVal | null, fn: string, args: RefVal[]) { + let formattedArgs = args.map((arg) => arg.type().typeName()).join(', '); + if (formattedArgs.indexOf(',') > -1) { + formattedArgs = `${formattedArgs},...`; + } + if (isNil(val)) { + return new ErrorRefVal(`no such overload: *.${fn}(${formattedArgs})`); + } + return new ErrorRefVal( + `no such overload: ${val.type().typeName()}.${fn}(${formattedArgs})` + ); + } + + static noSuchIndexMethodOverload( + val: RefVal, + fn: string, + overload: string, + args: RefType[] + ) { + const formattedArgs = args.map((arg) => arg.typeName()).join(', '); + return new ErrorRefVal( + `no such overload: ${val + .type() + .typeName()}.${fn}[${overload}](${formattedArgs})` + ); + } + + static maybeNoSuchOverload(val: RefVal) { + return ErrorRefVal.valOrErr(val, 'no such overload'); + } + + /** + * ValOrErr either returns the existing error or create a new one. + */ + static valOrErr(val: RefVal, err: string) { + if (isNil(val)) { + return new ErrorRefVal(err); + } + // TODO: or Unknown + if (val.type().typeName() === RefTypeEnum.ERR) { + return val; + } + return new ErrorRefVal(err); + } + + /** + * UnsupportedRefValConversionErr returns a types.NewErr instance with a no + * such conversion message that indicates that the native value could not be + * converted to a CEL ref.Val. + */ + static unsupportedRefValConversionErr(val: any) { + return new ErrorRefVal( + `unsupported conversion to ref.Val: (${val.name})${val}` + ); + } + + static noSuchField(field: any) { + return new ErrorRefVal(`no such field '${field}'`); + } + + static unknownType(field: any) { + return new ErrorRefVal(`unknown type '${field}'`); + } + + static rangeError(from: any, to: any) { + return new ErrorRefVal(`range error converting ${from} to ${to}`); + } + + static noSuchAttribute(attr: string) { + return new ErrorRefVal(`no such attribute '${attr}' (in container '')`); + } + + celValue(): Value { + return create(ValueSchema, { + kind: { + case: 'objectValue', + value: anyPack( + ErrorSetSchema, + create(ErrorSetSchema, { errors: [{ message: this.#val.message }] }) + ), + }, + }); + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + convertToNative(typeDesc: NativeType) { + throw new Error('Unsupported operation'); + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + convertToType(typeValue: RefType): RefVal { + // Errors are not convertible to other representations. + return this; + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + equal(other: RefVal): RefVal { + // An error cannot be equal to any other value, so it returns itself. + return this; + } + + type(): RefType { + return ERROR_REF_TYPE; + } + + value(): Error { + return this.#val; + } +} diff --git a/packages/cel/src/lib/common/types/int.spec.ts b/packages/cel/src/lib/common/types/int.spec.ts index 8f5fbcd..2c81552 100644 --- a/packages/cel/src/lib/common/types/int.spec.ts +++ b/packages/cel/src/lib/common/types/int.spec.ts @@ -9,38 +9,22 @@ import { Int32ValueSchema, Int64ValueSchema, anyPack, - timestampFromMs, } from '@bufbuild/protobuf/wkt'; -import { boolValue } from './bool'; -import { DOUBLE_TYPE, doubleValue } from './double'; +import { BoolRefVal } from './bool'; +import { DOUBLE_REF_TYPE, DoubleRefVal } from './double'; +import { ErrorRefVal } from './error'; import { - INT64_TYPE, + INT_REF_TYPE, + IntRefVal, MAX_INT64, MIN_INT64, - addInt64Value, - compareInt64Value, - convertInt64ValueToNative, - convertInt64ValueToType, - divideInt64Value, - equalInt64Value, int64Constant, int64Expr, int64Value, - isZeroInt64Value, - moduloInt64Value, - multiplyInt64Value, - negateInt64Value, - subtractInt64Value, } from './int'; -import { STRING_TYPE, stringValue } from './string'; -import { - MAX_UNIX_TIME_MS, - MIN_UNIX_TIME_MS, - timestampValue, -} from './timestamp'; -import { TYPE_TYPE } from './type'; -import { UINT64_TYPE, uint64Value } from './uint'; -import { TIMESTAMP_TYPE } from './wkt'; +import { STRING_REF_TYPE, StringRefVal } from './string'; +import { TYPE_REF_TYPE, TypeRefVal } from './type'; +import { UINT_REF_TYPE, UintRefVal } from './uint'; describe('int', () => { it('int64Constant', () => { @@ -85,404 +69,341 @@ describe('int', () => { // TODO: validations it('convertInt64ValueToNative - js BigInt', () => { - expect(() => { - convertInt64ValueToNative(stringValue('foo'), Number); - }).toThrow(); - expect(convertInt64ValueToNative(int64Value(BigInt(42)), BigInt)).toEqual( - BigInt(42) - ); + const value = new IntRefVal(BigInt(42)); + expect(value.convertToNative(BigInt)).toEqual(BigInt(42)); }); it('convertInt64ValueToNative - anyPack', () => { - const value = int64Value(BigInt(-42)); + const value = new IntRefVal(BigInt(-42)); const packed = anyPack( Int64ValueSchema, create(Int64ValueSchema, { value: BigInt(-42) }) ); - expect(convertInt64ValueToNative(value, AnySchema)).toEqual(packed); + expect(value.convertToNative(AnySchema)).toEqual(packed); }); it('convertInt64ValueToNative - int64 wrapper', () => { - const value = int64Value(BigInt(30000000)); - expect(convertInt64ValueToNative(value, Int64ValueSchema)).toEqual( + const value = new IntRefVal(BigInt(30000000)); + expect(value.convertToNative(Int64ValueSchema)).toEqual( create(Int64ValueSchema, { value: BigInt(30000000) }) ); // Value errors expect( - convertInt64ValueToNative( - int64Value(MAX_INT64 + BigInt(1)), - Int64ValueSchema - ) - ).toEqual(new Error('integer overflow')); + new IntRefVal(MAX_INT64 + BigInt(1)).convertToNative(Int64ValueSchema) + ).toEqual(ErrorRefVal.errIntOverflow); expect( - convertInt64ValueToNative( - int64Value(MIN_INT64 - BigInt(1)), - Int64ValueSchema - ) - ).toEqual(new Error('integer overflow')); + new IntRefVal(MIN_INT64 - BigInt(1)).convertToNative(Int64ValueSchema) + ).toEqual(ErrorRefVal.errIntOverflow); }); it('convertInt64ValueToNative - int32 wrapper', () => { - const value = int64Value(BigInt(7976931348623157)); - expect(convertInt64ValueToNative(value, Int32ValueSchema)).toEqual( + const value = new IntRefVal(BigInt(7976931348623157)); + expect(value.convertToNative(Int32ValueSchema)).toEqual( create(Int32ValueSchema, { value: 7976931348623157 }) ); // Value errors expect( - convertInt64ValueToNative( - int64Value(BigInt(Number.MAX_SAFE_INTEGER + 1)), + new IntRefVal(BigInt(Number.MAX_SAFE_INTEGER + 1)).convertToNative( Int32ValueSchema ) - ).toEqual(new Error('integer overflow')); + ).toEqual(ErrorRefVal.errIntOverflow); expect( - convertInt64ValueToNative( - int64Value(BigInt(Number.MIN_SAFE_INTEGER - 1)), + new IntRefVal(BigInt(Number.MIN_SAFE_INTEGER - 1)).convertToNative( Int32ValueSchema ) - ).toEqual(new Error('integer overflow')); + ).toEqual(ErrorRefVal.errIntOverflow); }); it('convertInt64ValueToNative - invalid type', () => { - const value = int64Value(BigInt(-314159)); - expect(convertInt64ValueToNative(value, Boolean)).toEqual( - new Error(`type conversion error from 'int' to 'Boolean'`) + const value = new IntRefVal(BigInt(-314159)); + expect(value.convertToNative(Boolean)).toEqual( + ErrorRefVal.nativeTypeConversionError(value, Boolean) ); }); it('convertInt64ValueToType', () => { - expect(() => { - convertInt64ValueToType(stringValue('foo'), TYPE_TYPE); - }).toThrow(); const tests = [ { - in: int64Value(BigInt(42)), - type: TYPE_TYPE, - out: INT64_TYPE, - }, - { - in: int64Value(BigInt(42)), - type: INT64_TYPE, - out: int64Value(BigInt(42)), + in: new IntRefVal(BigInt(42)), + type: TYPE_REF_TYPE, + out: new TypeRefVal(INT_REF_TYPE), }, { - in: int64Value(BigInt(42)), - type: UINT64_TYPE, - out: uint64Value(BigInt(42)), + in: new IntRefVal(BigInt(42)), + type: INT_REF_TYPE, + out: new IntRefVal(BigInt(42)), }, { - in: int64Value(BigInt(-42)), - type: UINT64_TYPE, - out: new Error('unsigned integer overflow'), + in: new IntRefVal(BigInt(42)), + type: UINT_REF_TYPE, + out: new UintRefVal(BigInt(42)), }, { - in: int64Value(BigInt(42)), - type: DOUBLE_TYPE, - out: doubleValue(42), + in: new IntRefVal(BigInt(-42)), + type: UINT_REF_TYPE, + out: ErrorRefVal.errIntOverflow, }, { - in: int64Value(BigInt(-42)), - type: STRING_TYPE, - out: stringValue('-42'), + in: new IntRefVal(BigInt(42)), + type: DOUBLE_REF_TYPE, + out: new DoubleRefVal(42), }, { - in: int64Value(BigInt(946684800)), - type: TIMESTAMP_TYPE, - out: timestampValue(timestampFromMs(946684800)), - }, - { - in: int64Value(BigInt(MAX_UNIX_TIME_MS + 1)), - type: TIMESTAMP_TYPE, - out: new Error('timestamp overflow'), - }, - { - in: int64Value(BigInt(MIN_UNIX_TIME_MS - 1)), - type: TIMESTAMP_TYPE, - out: new Error('timestamp overflow'), + in: new IntRefVal(BigInt(-42)), + type: STRING_REF_TYPE, + out: new StringRefVal('-42'), }, + // TODO: Timestamp types + // { + // in: new IntRefVal(BigInt(946684800)), + // type: TIMESTAMP_TYPE, + // out: timestampValue(timestampFromMs(946684800)), + // }, + // { + // in: int64Value(BigInt(MAX_UNIX_TIME_MS + 1)), + // type: TIMESTAMP_TYPE, + // out: new Error('timestamp overflow'), + // }, + // { + // in: int64Value(BigInt(MIN_UNIX_TIME_MS - 1)), + // type: TIMESTAMP_TYPE, + // out: new Error('timestamp overflow'), + // }, ]; for (const test of tests) { - expect(convertInt64ValueToType(test.in, test.type)).toEqual(test.out); + expect(test.in.convertToType(test.type)).toStrictEqual(test.out); } }); it('equalInt64Value', () => { - expect(() => { - equalInt64Value(stringValue('foo'), int64Value(BigInt(42))); - }).toThrow(); const tests = [ { - a: int64Value(BigInt(-10)), - b: int64Value(BigInt(-10)), - out: boolValue(true), + a: new IntRefVal(BigInt(-10)), + b: new IntRefVal(BigInt(-10)), + out: new BoolRefVal(true), }, { - a: int64Value(BigInt(10)), - b: int64Value(BigInt(-10)), - out: boolValue(false), + a: new IntRefVal(BigInt(10)), + b: new IntRefVal(BigInt(-10)), + out: new BoolRefVal(false), }, { - a: int64Value(BigInt(10)), - b: uint64Value(BigInt(10)), - out: boolValue(true), + a: new IntRefVal(BigInt(10)), + b: new UintRefVal(BigInt(10)), + out: new BoolRefVal(true), }, { - a: int64Value(BigInt(9)), - b: uint64Value(BigInt(10)), - out: boolValue(false), + a: new IntRefVal(BigInt(9)), + b: new UintRefVal(BigInt(10)), + out: new BoolRefVal(false), }, { - a: int64Value(BigInt(10)), - b: doubleValue(10), - out: boolValue(true), + a: new IntRefVal(BigInt(10)), + b: new DoubleRefVal(10), + out: new BoolRefVal(true), }, { - a: int64Value(BigInt(10)), - b: doubleValue(-10.5), - out: boolValue(false), + a: new IntRefVal(BigInt(10)), + b: new DoubleRefVal(-10.5), + out: new BoolRefVal(false), }, { - a: int64Value(BigInt(10)), - b: doubleValue(NaN), - out: boolValue(false), + a: new IntRefVal(BigInt(10)), + b: new DoubleRefVal(NaN), + out: new BoolRefVal(false), }, { - a: int64Value(BigInt(10)), - b: stringValue('10'), - out: boolValue(false), + a: new IntRefVal(BigInt(10)), + b: new StringRefVal('10'), + out: new BoolRefVal(false), }, ]; for (const test of tests) { - expect(equalInt64Value(test.a, test.b)).toEqual(test.out); + expect(test.a.equal(test.b)).toStrictEqual(test.out); } }); it('isZeroInt64Value', () => { - expect(isZeroInt64Value(int64Value(BigInt(0)))).toEqual(boolValue(true)); - expect(isZeroInt64Value(int64Value(BigInt(1)))).toEqual(boolValue(false)); + expect(new IntRefVal(BigInt(0)).isZeroValue()).toEqual(true); + expect(new IntRefVal(BigInt(1)).isZeroValue()).toEqual(false); }); it('addInt64Value', () => { - expect(() => { - addInt64Value(stringValue('foo'), int64Value(BigInt(42))); - }).toThrow(); - expect(addInt64Value(int64Value(BigInt(1)), int64Value(BigInt(2)))).toEqual( - int64Value(BigInt(3)) - ); - expect(addInt64Value(int64Value(BigInt(1)), stringValue('-4'))).toEqual( - new Error('no such overload') - ); - expect(addInt64Value(int64Value(MAX_INT64), int64Value(BigInt(1)))).toEqual( - new Error('integer overflow') + expect( + new IntRefVal(BigInt(1)).add(new IntRefVal(BigInt(2))) + ).toStrictEqual(new IntRefVal(BigInt(3))); + expect(new IntRefVal(BigInt(1)).add(new StringRefVal('-4'))).toStrictEqual( + ErrorRefVal.errNoSuchOverload ); expect( - addInt64Value(int64Value(MIN_INT64), int64Value(BigInt(-1))) - ).toEqual(new Error('integer overflow')); + new IntRefVal(MAX_INT64).add(new IntRefVal(BigInt(1))) + ).toStrictEqual(ErrorRefVal.errIntOverflow); + expect( + new IntRefVal(MIN_INT64).add(new IntRefVal(BigInt(-1))) + ).toStrictEqual(ErrorRefVal.errIntOverflow); expect( - addInt64Value(int64Value(MAX_INT64 - BigInt(1)), int64Value(BigInt(1))) - ).toEqual(int64Value(MAX_INT64)); + new IntRefVal(MAX_INT64 - BigInt(1)).add(new IntRefVal(BigInt(1))) + ).toStrictEqual(new IntRefVal(MAX_INT64)); expect( - addInt64Value(int64Value(MIN_INT64 + BigInt(1)), int64Value(BigInt(-1))) - ).toEqual(int64Value(MIN_INT64)); + new IntRefVal(MIN_INT64 + BigInt(1)).add(new IntRefVal(BigInt(-1))) + ).toStrictEqual(new IntRefVal(MIN_INT64)); }); it('compareInt64Value', () => { - expect(() => { - compareInt64Value(stringValue('foo'), int64Value(BigInt(42))); - }).toThrow(); const tests = [ { - a: int64Value(BigInt(42)), - b: int64Value(BigInt(42)), - out: int64Value(BigInt(0)), + a: new IntRefVal(BigInt(42)), + b: new IntRefVal(BigInt(42)), + out: new IntRefVal(BigInt(0)), }, { - a: int64Value(BigInt(42)), - b: uint64Value(BigInt(42)), - out: int64Value(BigInt(0)), + a: new IntRefVal(BigInt(42)), + b: new UintRefVal(BigInt(42)), + out: new IntRefVal(BigInt(0)), }, { - a: int64Value(BigInt(42)), - b: doubleValue(42), - out: int64Value(BigInt(0)), + a: new IntRefVal(BigInt(42)), + b: new DoubleRefVal(42), + out: new IntRefVal(BigInt(0)), }, { - a: int64Value(BigInt(-1300)), - b: int64Value(BigInt(204)), - out: int64Value(BigInt(-1)), + a: new IntRefVal(BigInt(-1300)), + b: new IntRefVal(BigInt(204)), + out: new IntRefVal(BigInt(-1)), }, { - a: int64Value(BigInt(204)), - b: doubleValue(204.1), - out: int64Value(BigInt(-1)), + a: new IntRefVal(BigInt(204)), + b: new DoubleRefVal(204.1), + out: new IntRefVal(BigInt(-1)), }, { - a: int64Value(BigInt(1300)), - b: uint64Value(MAX_INT64 + BigInt(1)), - out: int64Value(BigInt(-1)), + a: new IntRefVal(BigInt(1300)), + b: new UintRefVal(MAX_INT64 + BigInt(1)), + out: new IntRefVal(BigInt(-1)), }, { - a: int64Value(BigInt(204)), - b: uint64Value(BigInt(205)), - out: int64Value(BigInt(-1)), + a: new IntRefVal(BigInt(204)), + b: new UintRefVal(BigInt(205)), + out: new IntRefVal(BigInt(-1)), }, { - a: int64Value(BigInt(204)), - b: doubleValue(Number(MAX_INT64) + 1025.0), - out: int64Value(BigInt(-1)), + a: new IntRefVal(BigInt(204)), + b: new DoubleRefVal(Number(MAX_INT64) + 1025.0), + out: new IntRefVal(BigInt(-1)), }, { - a: int64Value(BigInt(204)), - b: doubleValue(NaN), - out: new Error('NaN values cannot be ordered'), + a: new IntRefVal(BigInt(204)), + b: new DoubleRefVal(NaN), + out: new ErrorRefVal('NaN values cannot be ordered'), }, { - a: int64Value(BigInt(204)), - b: int64Value(BigInt(-1300)), - out: int64Value(BigInt(1)), + a: new IntRefVal(BigInt(204)), + b: new IntRefVal(BigInt(-1300)), + out: new IntRefVal(BigInt(1)), }, { - a: int64Value(BigInt(204)), - b: uint64Value(BigInt(10)), - out: int64Value(BigInt(1)), + a: new IntRefVal(BigInt(204)), + b: new UintRefVal(BigInt(10)), + out: new IntRefVal(BigInt(1)), }, { - a: int64Value(BigInt(204)), - b: doubleValue(203.9), - out: int64Value(BigInt(1)), + a: new IntRefVal(BigInt(204)), + b: new DoubleRefVal(203.9), + out: new IntRefVal(BigInt(1)), }, { - a: int64Value(BigInt(204)), - b: doubleValue(Number(MIN_INT64) - 1025.0), - out: int64Value(BigInt(1)), + a: new IntRefVal(BigInt(204)), + b: new DoubleRefVal(Number(MIN_INT64) - 1025.0), + out: new IntRefVal(BigInt(1)), }, { - a: int64Value(BigInt(1)), - b: stringValue('1'), - out: new Error('no such overload'), + a: new IntRefVal(BigInt(1)), + b: new StringRefVal('1'), + out: ErrorRefVal.errNoSuchOverload, }, ]; for (const test of tests) { - expect(compareInt64Value(test.a, test.b)).toEqual(test.out); + expect(test.a.compare(test.b)).toStrictEqual(test.out); } }); it('divideInt64Value', () => { - expect(() => { - divideInt64Value(stringValue('foo'), int64Value(BigInt(42))); - }).toThrow(); expect( - divideInt64Value(int64Value(BigInt(3)), int64Value(BigInt(2))) - ).toEqual(int64Value(BigInt(1))); + new IntRefVal(BigInt(3)).divide(new IntRefVal(BigInt(2))) + ).toStrictEqual(new IntRefVal(BigInt(1))); expect( - divideInt64Value(int64Value(BigInt(3)), int64Value(BigInt(0))) - ).toEqual(new Error('divide by zero')); + new IntRefVal(BigInt(3)).divide(new IntRefVal(BigInt(0))) + ).toStrictEqual(ErrorRefVal.errDivideByZero); expect( - divideInt64Value(int64Value(MIN_INT64), int64Value(BigInt(-1))) - ).toEqual(new Error('integer overflow')); + new IntRefVal(MIN_INT64).divide(new IntRefVal(BigInt(-1))) + ).toStrictEqual(ErrorRefVal.errIntOverflow); }); it('moduloInt64Value', () => { - expect(() => { - moduloInt64Value(stringValue('foo'), int64Value(BigInt(42))); - }).toThrow(); expect( - moduloInt64Value(int64Value(BigInt(21)), int64Value(BigInt(2))) - ).toEqual(int64Value(BigInt(1))); + new IntRefVal(BigInt(21)).modulo(new IntRefVal(BigInt(2))) + ).toStrictEqual(new IntRefVal(BigInt(1))); expect( - moduloInt64Value(int64Value(BigInt(21)), int64Value(BigInt(0))) - ).toEqual(new Error('modulus by zero')); + new IntRefVal(BigInt(21)).modulo(new IntRefVal(BigInt(0))) + ).toStrictEqual(ErrorRefVal.errModulusByZero); expect( - moduloInt64Value(int64Value(MIN_INT64), int64Value(BigInt(-1))) - ).toEqual(new Error('integer overflow')); + new IntRefVal(MIN_INT64).modulo(new IntRefVal(BigInt(-1))) + ).toStrictEqual(ErrorRefVal.errIntOverflow); }); it('multiplyInt64Value', () => { - expect(() => { - multiplyInt64Value(stringValue('foo'), int64Value(BigInt(42))); - }).toThrow(); expect( - multiplyInt64Value(int64Value(BigInt(2)), int64Value(BigInt(-2))) - ).toEqual(int64Value(BigInt(-4))); + new IntRefVal(BigInt(2)).multiply(new IntRefVal(BigInt(-2))) + ).toStrictEqual(new IntRefVal(BigInt(-4))); expect( - multiplyInt64Value( - int64Value(MAX_INT64 / BigInt(2)), - int64Value(BigInt(3)) - ) - ).toEqual(new Error('integer overflow')); + new IntRefVal(MAX_INT64 / BigInt(2)).multiply(new IntRefVal(BigInt(3))) + ).toStrictEqual(ErrorRefVal.errIntOverflow); expect( - multiplyInt64Value( - int64Value(MIN_INT64 / BigInt(2)), - int64Value(BigInt(3)) - ) - ).toEqual(new Error('integer overflow')); + new IntRefVal(MAX_INT64 / BigInt(2)).multiply(new IntRefVal(BigInt(2))) + ).toStrictEqual(new IntRefVal(MAX_INT64 - BigInt(1))); expect( - multiplyInt64Value( - int64Value(MAX_INT64 / BigInt(2)), - int64Value(BigInt(2)) - ) - ).toEqual(int64Value(MAX_INT64 - BigInt(1))); + new IntRefVal(MIN_INT64 / BigInt(2)).multiply(new IntRefVal(BigInt(2))) + ).toStrictEqual(new IntRefVal(MIN_INT64)); expect( - multiplyInt64Value( - int64Value(MIN_INT64 / BigInt(2)), - int64Value(BigInt(2)) - ) - ).toEqual(int64Value(MIN_INT64)); - expect( - multiplyInt64Value( - int64Value(MAX_INT64 / BigInt(2)), - int64Value(BigInt(-2)) - ) - ).toEqual(int64Value(MIN_INT64 + BigInt(2))); + new IntRefVal(MAX_INT64 / BigInt(2)).multiply(new IntRefVal(BigInt(-2))) + ).toStrictEqual(new IntRefVal(MIN_INT64 + BigInt(2))); expect( - multiplyInt64Value( - int64Value((MIN_INT64 + BigInt(2)) / BigInt(2)), - int64Value(BigInt(-2)) + new IntRefVal((MIN_INT64 + BigInt(2)) / BigInt(2)).multiply( + new IntRefVal(BigInt(-2)) ) - ).toEqual(int64Value(MAX_INT64 - BigInt(1))); + ).toStrictEqual(new IntRefVal(MAX_INT64 - BigInt(1))); expect( - multiplyInt64Value(int64Value(MIN_INT64), int64Value(BigInt(-1))) - ).toEqual(new Error('integer overflow')); + new IntRefVal(MIN_INT64).multiply(new IntRefVal(BigInt(-1))) + ).toStrictEqual(ErrorRefVal.errIntOverflow); }); it('negateInt64Value', () => { - expect(() => { - negateInt64Value(stringValue('foo')); - }).toThrow(); - expect(negateInt64Value(int64Value(BigInt(42)))).toEqual( - int64Value(BigInt(-42)) + expect(new IntRefVal(BigInt(42)).negate()).toStrictEqual( + new IntRefVal(BigInt(-42)) ); - expect(negateInt64Value(int64Value(MIN_INT64))).toEqual( - new Error('integer overflow') + expect(new IntRefVal(MIN_INT64).negate()).toStrictEqual( + ErrorRefVal.errIntOverflow ); - expect(negateInt64Value(int64Value(MAX_INT64))).toEqual( - int64Value(MIN_INT64 + BigInt(1)) + expect(new IntRefVal(MAX_INT64).negate()).toStrictEqual( + new IntRefVal(MIN_INT64 + BigInt(1)) ); }); it('subtractInt64Value', () => { - expect(() => { - subtractInt64Value(stringValue('foo'), int64Value(BigInt(42))); - }).toThrow(); expect( - subtractInt64Value(int64Value(BigInt(4)), int64Value(BigInt(-3))) - ).toEqual(int64Value(BigInt(7))); + new IntRefVal(BigInt(4)).subtract(new IntRefVal(BigInt(-3))) + ).toStrictEqual(new IntRefVal(BigInt(7))); expect( - subtractInt64Value(int64Value(MAX_INT64), int64Value(BigInt(-1))) - ).toEqual(new Error('integer overflow')); + new IntRefVal(MAX_INT64).subtract(new IntRefVal(BigInt(-1))) + ).toStrictEqual(ErrorRefVal.errIntOverflow); expect( - subtractInt64Value(int64Value(MIN_INT64), int64Value(BigInt(1))) - ).toEqual(new Error('integer overflow')); + new IntRefVal(MIN_INT64).subtract(new IntRefVal(BigInt(1))) + ).toStrictEqual(ErrorRefVal.errIntOverflow); expect( - subtractInt64Value( - int64Value(MAX_INT64 - BigInt(1)), - int64Value(BigInt(-1)) - ) - ).toEqual(int64Value(MAX_INT64)); + new IntRefVal(MAX_INT64 - BigInt(1)).subtract(new IntRefVal(BigInt(-1))) + ).toStrictEqual(new IntRefVal(MAX_INT64)); expect( - subtractInt64Value( - int64Value(MIN_INT64 + BigInt(1)), - int64Value(BigInt(1)) - ) - ).toEqual(int64Value(MIN_INT64)); + new IntRefVal(MIN_INT64 + BigInt(1)).subtract(new IntRefVal(BigInt(1))) + ).toStrictEqual(new IntRefVal(MIN_INT64)); }); }); diff --git a/packages/cel/src/lib/common/types/int.ts b/packages/cel/src/lib/common/types/int.ts index 72282fc..7f5ce21 100644 --- a/packages/cel/src/lib/common/types/int.ts +++ b/packages/cel/src/lib/common/types/int.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-case-declarations */ import { Type, Type_PrimitiveType, @@ -22,22 +23,35 @@ import { timestampFromMs, } from '@bufbuild/protobuf/wkt'; import { formatCELType } from '../format'; -import { boolValue } from './bool'; -import { compareNumberValues } from './compare'; +import { RefType, RefTypeEnum, RefVal } from '../ref/reference'; +import { BoolRefVal, boolValue } from './bool'; +import { compareNumberRefVals, compareNumberValues } from './compare'; import { isConstExpr } from './constant'; -import { doubleValue, isDoubleValue } from './double'; +import { DoubleRefVal, doubleValue, isDoubleValue } from './double'; +import { ErrorRefVal } from './error'; import { NativeType } from './native'; import { isNumberValue } from './number'; import { primitiveType } from './primitive'; -import { stringValue } from './string'; +import { StringRefVal, stringValue } from './string'; import { MAX_UNIX_TIME, MIN_UNIX_TIME, timestampValue } from './timestamp'; +import { Comparer } from './traits/comparer'; +import { + Adder, + Divider, + Modder, + Multiplier, + Negater, + Subtractor, +} from './traits/math'; import { Trait } from './traits/trait'; -import { isValidUint64, uint64Value } from './uint'; +import { Zeroer } from './traits/zeroer'; +import { TypeRefVal } from './type'; +import { UintRefVal, isValidUint64, uint64Value } from './uint'; export const MAX_INT64 = BigInt(2) ** BigInt(63) - BigInt(1); export const MIN_INT64 = BigInt(-1) * BigInt(2) ** BigInt(63); -export const INT64_TYPE = primitiveType(Type_PrimitiveType.INT64); +export const INT_CEL_TYPE = primitiveType(Type_PrimitiveType.INT64); export function isInt64Type(val: Type): val is Type & { typeKind: { case: 'primitive'; value: Type_PrimitiveType.INT64 }; @@ -152,7 +166,7 @@ export function convertInt64ValueToNative(value: Value, type: NativeType) { break; } return new Error( - `type conversion error from '${formatCELType(INT64_TYPE)}' to '${ + `type conversion error from '${formatCELType(INT_CEL_TYPE)}' to '${ type.name }'` ); @@ -205,13 +219,13 @@ export function convertInt64ValueToType(value: Value, type: Type) { } break; case 'type': - return INT64_TYPE; + return INT_CEL_TYPE; default: break; } return new Error( `type conversion error from '${formatCELType( - INT64_TYPE + INT_CEL_TYPE )}' to '${formatCELType(type)}'` ); } @@ -387,3 +401,272 @@ export function subtractInt64Value(value: Value, other: Value) { } return int64Value(value.kind.value - BigInt(other.kind.value)); } + +export class IntRefType implements RefType { + // This has to be a TS private field instead of a # private field because + // otherwise the tests will not be able to access it to check for equality. + // TODO: do we want to alter the tests to use the getter instead? + private readonly _traits = INT64_TRAITS; + + celType(): Type { + return INT_CEL_TYPE; + } + + hasTrait(trait: Trait): boolean { + return this._traits.has(trait); + } + + typeName(): string { + return RefTypeEnum.INT; + } +} + +export const INT_REF_TYPE = new IntRefType(); + +export class IntRefVal + implements + RefVal, + Adder, + Comparer, + Divider, + Modder, + Multiplier, + Negater, + Subtractor, + Zeroer +{ + // This has to be a TS private field instead of a # private field because + // otherwise the tests will not be able to access it to check for equality. + // TODO: do we want to alter the tests to use the getter instead? + private readonly _value: bigint; + + constructor(value: bigint) { + this._value = value; + } + + static IntNegOne = new IntRefVal(BigInt(-1)); + static IntZero = new IntRefVal(BigInt(0)); + static IntOne = new IntRefVal(BigInt(1)); + static Min = MIN_INT64; + static Max = MAX_INT64; + + celValue(): Value { + return int64Value(this._value); + } + + convertToNative(type: NativeType) { + switch (type) { + case BigInt: + return this._value; + case Number: + return Number(this._value); + case AnySchema: + return anyPack( + Int64ValueSchema, + create(Int64ValueSchema, { value: this._value }) + ); + case Int32ValueSchema: + if (!isValidInt32(Number(this._value))) { + return ErrorRefVal.errIntOverflow; + } + return create(Int32ValueSchema, { value: Number(this._value) }); + case Int64ValueSchema: + if (!isValidInt64(this._value)) { + return ErrorRefVal.errIntOverflow; + } + return create(Int64ValueSchema, { value: this._value }); + default: + return ErrorRefVal.nativeTypeConversionError(this, type); + } + } + + convertToType(type: RefType): RefVal { + switch (type.typeName()) { + case RefTypeEnum.DOUBLE: + return new DoubleRefVal(Number(this._value)); + case RefTypeEnum.INT: + if (Number.isNaN(this._value) || !isValidInt64(this._value)) { + return ErrorRefVal.errIntOverflow; + } + return new IntRefVal(this._value); + case RefTypeEnum.STRING: + return new StringRefVal(this._value.toString()); + case RefTypeEnum.TYPE: + return new TypeRefVal(INT_REF_TYPE); + case RefTypeEnum.UINT: + if (Number.isNaN(this._value) || !isValidUint64(this._value)) { + return ErrorRefVal.errUintOverflow; + } + return new UintRefVal(this._value); + // TODO: Implement the rest of the types. + default: + return ErrorRefVal.typeConversionError(this, type); + } + } + + equal(other: RefVal): RefVal { + if (Number.isNaN(this._value) || Number.isNaN(other.value())) { + return BoolRefVal.False; + } + switch (other.type().typeName()) { + case RefTypeEnum.DOUBLE: + case RefTypeEnum.INT: + case RefTypeEnum.UINT: + const compared = compareNumberRefVals(this, other); + if (compared.type().typeName() === RefTypeEnum.ERR) { + return compared; + } + return new BoolRefVal(compared.value() === BigInt(0)); + default: + return BoolRefVal.False; + } + } + + type(): RefType { + return INT_REF_TYPE; + } + + value() { + return this._value; + } + + isZeroValue(): boolean { + return this._value === BigInt(0); + } + + add(other: RefVal): RefVal { + switch (other.type().typeName()) { + case RefTypeEnum.DOUBLE: + case RefTypeEnum.INT: + case RefTypeEnum.UINT: + if ( + (other.value() > 0 && + this._value > MAX_INT64 - BigInt(other.value())) || + (other.value() < 0 && this._value < MIN_INT64 - BigInt(other.value())) + ) { + return ErrorRefVal.errIntOverflow; + } + return new IntRefVal(this._value + BigInt(other.value())); + default: + return ErrorRefVal.maybeNoSuchOverload(other); + } + } + + compare(other: RefVal): RefVal { + if ( + Number.isNaN(Number(this._value)) || + Number.isNaN(Number(other.value())) + ) { + return new ErrorRefVal('NaN values cannot be ordered'); + } + switch (other.type().typeName()) { + case RefTypeEnum.DOUBLE: + if (this._value < Number.MIN_SAFE_INTEGER) { + return IntRefVal.IntNegOne; + } + if (this._value > Number.MAX_SAFE_INTEGER) { + return IntRefVal.IntOne; + } + return compareNumberRefVals(this, other); + case RefTypeEnum.INT: + case RefTypeEnum.UINT: + return compareNumberRefVals(this, other); + default: + return ErrorRefVal.maybeNoSuchOverload(other); + } + } + + divide(denominator: RefVal): RefVal { + switch (denominator.type().typeName()) { + case RefTypeEnum.DOUBLE: + case RefTypeEnum.INT: + case RefTypeEnum.UINT: + if (Number(denominator.value()) === 0) { + return ErrorRefVal.errDivideByZero; + } + // Negating MinInt64 would result in a valid of MaxInt64+1. + if (this._value === MIN_INT64 && Number(denominator.value()) === -1) { + return ErrorRefVal.errIntOverflow; + } + return new IntRefVal(this._value / BigInt(denominator.value())); + default: + return ErrorRefVal.maybeNoSuchOverload(denominator); + } + } + + modulo(denominator: RefVal): RefVal { + switch (denominator.type().typeName()) { + case RefTypeEnum.DOUBLE: + case RefTypeEnum.INT: + case RefTypeEnum.UINT: + if (Number(denominator.value()) === 0) { + return ErrorRefVal.errModulusByZero; + } + // Negating MinInt64 would result in a valid of MaxInt64+1. + if (this._value === MIN_INT64 && Number(denominator.value()) === -1) { + return ErrorRefVal.errIntOverflow; + } + return new IntRefVal(this._value % BigInt(denominator.value())); + default: + return ErrorRefVal.maybeNoSuchOverload(denominator); + } + } + + multiply(other: RefVal): RefVal { + switch (other.type().typeName()) { + case RefTypeEnum.DOUBLE: + case RefTypeEnum.INT: + case RefTypeEnum.UINT: + const x = this.value(); + const y = BigInt(other.value()); + // Detecting multiplication overflow is more complicated than the + // others. The first two detect attempting to negate MinInt64, which + // would result in MaxInt64+1. The other four detect normal overflow + // conditions. + if ( + (x === BigInt(-1) && y == MIN_INT64) || + (y === BigInt(-1) && x == MIN_INT64) || + // x is positive, y is positive + (x > 0 && y > 0 && x > MAX_INT64 / y) || + // x is positive, y is negative + (x > 0 && y < 0 && y < MIN_INT64 / x) || + // x is negative, y is positive + (x < 0 && y > 0 && x < MIN_INT64 / y) || + // x is negative, y is negative + (x < 0 && y < 0 && y < MAX_INT64 / x) + ) { + return ErrorRefVal.errIntOverflow; + } + return new IntRefVal(x * y); + default: + return ErrorRefVal.maybeNoSuchOverload(other); + } + } + + negate(): RefVal { + // Negating MinInt64 would result in a value of MaxInt64+1. + if (this._value === MIN_INT64) { + return ErrorRefVal.errIntOverflow; + } + return new IntRefVal(-this._value); + } + + subtract(subtrahend: RefVal): RefVal { + switch (subtrahend.type().typeName()) { + case RefTypeEnum.DOUBLE: + case RefTypeEnum.INT: + case RefTypeEnum.UINT: + if ( + (subtrahend.value() < 0 && + this._value > MAX_INT64 + BigInt(subtrahend.value())) || + (subtrahend.value() > 0 && + this._value < MIN_INT64 + BigInt(subtrahend.value())) + ) { + return ErrorRefVal.errIntOverflow; + } + return new IntRefVal(this._value - BigInt(subtrahend.value())); + default: + return ErrorRefVal.maybeNoSuchOverload(subtrahend); + } + } +} diff --git a/packages/cel/src/lib/common/types/native.ts b/packages/cel/src/lib/common/types/native.ts index 39ef879..5f9da7a 100644 --- a/packages/cel/src/lib/common/types/native.ts +++ b/packages/cel/src/lib/common/types/native.ts @@ -19,6 +19,7 @@ import { */ export type NativeType = | typeof Boolean + | typeof Date | typeof Number | typeof String | typeof Object diff --git a/packages/cel/src/lib/common/types/number.ts b/packages/cel/src/lib/common/types/number.ts index 2b903be..34bb344 100644 --- a/packages/cel/src/lib/common/types/number.ts +++ b/packages/cel/src/lib/common/types/number.ts @@ -1,4 +1,5 @@ import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { RefTypeEnum, RefVal } from '../ref/reference'; import { isDoubleValue } from './double'; import { isInt64Value } from './int'; import { isUint64Value } from './uint'; @@ -12,6 +13,18 @@ export function isNumberValue(value: Value): value is Value & { return isDoubleValue(value) || isInt64Value(value) || isUint64Value(value); } +// TODO: type narrowing +export function isNumberRefVal(value: RefVal) { + switch (value.type().typeName()) { + case RefTypeEnum.DOUBLE: + case RefTypeEnum.INT: + case RefTypeEnum.UINT: + return true; + default: + return false; + } +} + export function unwrapNumberValue(value: Value): number | bigint | null { switch (value.kind.case) { case 'int64Value': diff --git a/packages/cel/src/lib/common/types/string.spec.ts b/packages/cel/src/lib/common/types/string.spec.ts index 84cfd4c..55978a0 100644 --- a/packages/cel/src/lib/common/types/string.spec.ts +++ b/packages/cel/src/lib/common/types/string.spec.ts @@ -4,37 +4,21 @@ import { } from '@buf/google_cel-spec.bufbuild_es/cel/expr/syntax_pb.js'; import { ValueSchema } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; import { create } from '@bufbuild/protobuf'; -import { - AnySchema, - StringValueSchema, - anyPack, - timestampFromDate, -} from '@bufbuild/protobuf/wkt'; +import { AnySchema, StringValueSchema, anyPack } from '@bufbuild/protobuf/wkt'; import { CONTAINS_OVERLOAD } from '../../overloads'; -import { BOOL_TYPE, boolValue } from './bool'; -import { BYTES_TYPE, bytesValue } from './bytes'; -import { DOUBLE_TYPE, doubleValue } from './double'; -import { durationValue } from './duration'; -import { INT64_TYPE, int64Value } from './int'; +import { BOOL_REF_TYPE, BoolRefVal } from './bool'; +import { DOUBLE_REF_TYPE, DoubleRefVal } from './double'; +import { ErrorRefVal } from './error'; +import { INT_REF_TYPE, IntRefVal } from './int'; import { - STRING_TYPE, - addStringValue, - compareStringValue, - convertStringValueToNative, - convertStringValueToType, - equalStringValue, - isZeroStringValue, - matchStringValue, - receiveStringValue, - sizeStringValue, + STRING_REF_TYPE, + StringRefVal, stringConstant, stringExpr, stringValue, } from './string'; -import { timestampValue } from './timestamp'; -import { TYPE_TYPE } from './type'; -import { UINT64_TYPE, uint64Value } from './uint'; -import { DURATION_TYPE, TIMESTAMP_TYPE } from './wkt'; +import { TYPE_REF_TYPE, TypeRefVal } from './type'; +import { UINT_REF_TYPE, UintRefVal } from './uint'; describe('string', () => { it('stringConstant', () => { @@ -79,271 +63,218 @@ describe('string', () => { // TODO: validations it('convertStringValueToNative ', () => { - expect(() => { - convertStringValueToNative(doubleValue(42), String); - }).toThrow(); - expect(convertStringValueToNative(stringValue('hello'), String)).toEqual( + expect(new StringRefVal('hello').convertToNative(String)).toStrictEqual( 'hello' ); + expect(new StringRefVal('hello').convertToNative(Uint8Array)).toStrictEqual( + new TextEncoder().encode('hello') + ); expect( - convertStringValueToNative(stringValue('world'), Uint8Array) - ).toEqual(new TextEncoder().encode('world')); - expect( - convertStringValueToNative(stringValue('hey buddy'), AnySchema) - ).toEqual( + new StringRefVal('hey buddy').convertToNative(AnySchema) + ).toStrictEqual( anyPack( StringValueSchema, create(StringValueSchema, { value: 'hey buddy' }) ) ); expect( - convertStringValueToNative(stringValue('hey buddy'), StringValueSchema) - ).toEqual(create(StringValueSchema, { value: 'hey buddy' })); - expect( - convertStringValueToNative(stringValue('hey buddy'), Number) - ).toEqual(new Error(`type conversion error from 'string' to 'Number'`)); + new StringRefVal('hey buddy').convertToNative(StringValueSchema) + ).toStrictEqual(create(StringValueSchema, { value: 'hey buddy' })); + const val = new StringRefVal('hey buddy'); + expect(val.convertToNative(Number)).toStrictEqual( + ErrorRefVal.nativeTypeConversionError(val, Number) + ); }); it('convertStringValueToType', () => { - expect(() => { - convertStringValueToType(doubleValue(42), STRING_TYPE); - }).toThrow(); const tests = [ { - value: stringValue('hello'), - type: TYPE_TYPE, - expected: STRING_TYPE, - }, - { - value: stringValue('hello'), - type: STRING_TYPE, - expected: stringValue('hello'), - }, - { - value: stringValue('-1'), - type: INT64_TYPE, - expected: int64Value(BigInt(-1)), - }, - { - value: stringValue('3.14'), - type: DOUBLE_TYPE, - expected: doubleValue(3.14), - }, - { - value: stringValue('42'), - type: UINT64_TYPE, - expected: uint64Value(BigInt(42)), - }, - { - value: stringValue('true'), - type: BOOL_TYPE, - expected: boolValue(true), + value: new StringRefVal('hello'), + type: TYPE_REF_TYPE, + expected: new TypeRefVal(STRING_REF_TYPE), }, { - value: stringValue('false'), - type: BOOL_TYPE, - expected: boolValue(false), + value: new StringRefVal('hello'), + type: STRING_REF_TYPE, + expected: new StringRefVal('hello'), }, { - value: stringValue('hello'), - type: BYTES_TYPE, - expected: bytesValue(new TextEncoder().encode('hello')), + value: new StringRefVal('-1'), + type: INT_REF_TYPE, + expected: new IntRefVal(BigInt(-1)), }, { - value: stringValue('2021-01-01T00:00:00Z'), - type: TIMESTAMP_TYPE, - expected: timestampValue( - timestampFromDate(new Date('2021-01-01T00:00:00Z')) - ), + value: new StringRefVal('3.14'), + type: DOUBLE_REF_TYPE, + expected: new DoubleRefVal(3.14), }, { - value: stringValue('42s'), - type: DURATION_TYPE, - expected: durationValue({ seconds: BigInt(42), nanos: 0 }), + value: new StringRefVal('42'), + type: UINT_REF_TYPE, + expected: new UintRefVal(BigInt(42)), }, { - value: stringValue('1h5s'), - type: DURATION_TYPE, - expected: durationValue({ seconds: BigInt(3605), nanos: 0 }), + value: new StringRefVal('true'), + type: BOOL_REF_TYPE, + expected: new BoolRefVal(true), }, { - value: stringValue('3.14s'), - type: DURATION_TYPE, - expected: durationValue({ seconds: BigInt(3), nanos: 0.14 * 1e9 }), + value: new StringRefVal('false'), + type: BOOL_REF_TYPE, + expected: new BoolRefVal(false), }, + // TODO: bytes type + // { + // value: new StringRefVal('hello'), + // type: BYTES_TYPE, + // expected: bytesValue(new TextEncoder().encode('hello')), + // }, + // TODO: timestamp & duration types + // { + // value: new StringRefVal('2021-01-01T00:00:00Z'), + // type: TIMESTAMP_TYPE, + // expected: timestampValue( + // timestampFromDate(new Date('2021-01-01T00:00:00Z')) + // ), + // }, + // { + // value: stringValue('42s'), + // type: DURATION_TYPE, + // expected: durationValue({ seconds: BigInt(42), nanos: 0 }), + // }, + // { + // value: stringValue('1h5s'), + // type: DURATION_TYPE, + // expected: durationValue({ seconds: BigInt(3605), nanos: 0 }), + // }, + // { + // value: stringValue('3.14s'), + // type: DURATION_TYPE, + // expected: durationValue({ seconds: BigInt(3), nanos: 0.14 * 1e9 }), + // }, ]; for (const test of tests) { - expect(convertStringValueToType(test.value, test.type)).toEqual( - test.expected - ); + expect(test.value.convertToType(test.type)).toStrictEqual(test.expected); } }); it('equalStringValue', () => { - expect(() => { - equalStringValue(doubleValue(42), stringValue('hello')); - }).toThrow(); expect( - equalStringValue(stringValue('hello'), stringValue('hello')) - ).toEqual(boolValue(true)); + new StringRefVal('hello').equal(new StringRefVal('hello')) + ).toStrictEqual(new BoolRefVal(true)); expect( - equalStringValue(stringValue('hello'), stringValue('world')) - ).toEqual(boolValue(false)); - expect(equalStringValue(stringValue('hello'), doubleValue(42))).toEqual( - boolValue(false) + new StringRefVal('hello').equal(new StringRefVal('world')) + ).toStrictEqual(new BoolRefVal(false)); + expect(new StringRefVal('hello').equal(new DoubleRefVal(42))).toStrictEqual( + new BoolRefVal(false) ); }); it('isZeroStringValue', () => { - expect(() => { - isZeroStringValue(doubleValue(42)); - }).toThrow(); - expect(isZeroStringValue(stringValue('hello'))).toEqual(boolValue(false)); - expect(isZeroStringValue(stringValue(''))).toEqual(boolValue(true)); + expect(new StringRefVal('hello').isZeroValue()).toStrictEqual(false); + expect(new StringRefVal('').isZeroValue()).toStrictEqual(true); }); it('addStringValue', () => { - expect(() => { - addStringValue(doubleValue(42), stringValue('hello')); - }).toThrow(); - expect(addStringValue(stringValue('hello'), stringValue('world'))).toEqual( - stringValue('helloworld') - ); - expect(addStringValue(stringValue('hello'), doubleValue(2))).toEqual( - new Error('no such overload') + expect( + new StringRefVal('hello').add(new StringRefVal('world')) + ).toStrictEqual(new StringRefVal('helloworld')); + expect(new StringRefVal('hello').add(new DoubleRefVal(2))).toStrictEqual( + ErrorRefVal.errNoSuchOverload ); }); it('compareStringValue', () => { - expect(() => { - compareStringValue(doubleValue(42), stringValue('hello')); - }); - const a = stringValue('a'); - const b = stringValue('bbbb'); - const c = stringValue('c'); - expect(compareStringValue(a, b)).toEqual(int64Value(BigInt(-1))); - expect(compareStringValue(a, a)).toEqual(int64Value(BigInt(0))); - expect(compareStringValue(c, b)).toEqual(int64Value(BigInt(1))); - expect(compareStringValue(a, doubleValue(42))).toEqual( - new Error('no such overload') + const a = new StringRefVal('a'); + const b = new StringRefVal('bbbb'); + const c = new StringRefVal('c'); + expect(a.compare(b)).toStrictEqual(IntRefVal.IntNegOne); + expect(a.compare(a)).toStrictEqual(IntRefVal.IntZero); + expect(c.compare(b)).toStrictEqual(IntRefVal.IntOne); + expect(a.compare(new DoubleRefVal(42))).toStrictEqual( + ErrorRefVal.errNoSuchOverload ); }); it('matchStringValue', () => { - expect(() => { - matchStringValue(doubleValue(42), stringValue('hello')); - }).toThrow(); - const str = stringValue('hello 1 world'); - const sw = stringValue('^hello'); - const ew = stringValue('\\d world$'); - expect(matchStringValue(str, sw)).toEqual(boolValue(true)); - expect(matchStringValue(str, ew)).toEqual(boolValue(true)); - expect(matchStringValue(stringValue('ello 1 worlds'), sw)).toEqual( - boolValue(false) + const str = new StringRefVal('hello 1 world'); + const sw = new StringRefVal('^hello'); + const ew = new StringRefVal('\\d world$'); + expect(str.match(sw)).toStrictEqual(new BoolRefVal(true)); + expect(str.match(ew)).toStrictEqual(new BoolRefVal(true)); + expect(new StringRefVal('ello 1 worlds').match(sw)).toStrictEqual( + new BoolRefVal(false) ); - expect(matchStringValue(str, doubleValue(42))).toEqual( - new Error('no such overload') + expect(str.match(new DoubleRefVal(42))).toStrictEqual( + ErrorRefVal.errNoSuchOverload ); }); it('receiveStringValue', () => { - expect(() => { - receiveStringValue(doubleValue(42), '', ''); - }).toThrow(); // Unknown overload - expect( - receiveStringValue(stringValue('hello'), 'unknown', '', stringValue('')) - ).toEqual(new Error('no such overload')); + expect(new StringRefVal('hello').receive('unknown', '', [])).toStrictEqual( + ErrorRefVal.errNoSuchOverload + ); // Contains expect( - receiveStringValue( - stringValue('goodbye'), - CONTAINS_OVERLOAD, - '', - stringValue('db') - ) - ).toEqual(boolValue(true)); + new StringRefVal('goodbye').receive(CONTAINS_OVERLOAD, '', [ + new StringRefVal('db'), + ]) + ).toStrictEqual(new BoolRefVal(true)); expect( - receiveStringValue( - stringValue('goodbye'), - CONTAINS_OVERLOAD, - '', - stringValue('aa') - ) - ).toEqual(boolValue(false)); + new StringRefVal('goodbye').receive(CONTAINS_OVERLOAD, '', [ + new StringRefVal('aa'), + ]) + ).toStrictEqual(new BoolRefVal(false)); expect( - receiveStringValue( - stringValue('goodbye'), - CONTAINS_OVERLOAD, - '', - doubleValue(42) - ) - ).toEqual(new Error('no such overload')); + new StringRefVal('goodbye').receive(CONTAINS_OVERLOAD, '', [ + new DoubleRefVal(42), + ]) + ).toStrictEqual(ErrorRefVal.errNoSuchOverload); // StartsWith expect( - receiveStringValue( - stringValue('goodbye'), - 'startsWith', - '', - stringValue('good') - ) - ).toEqual(boolValue(true)); + new StringRefVal('goodbye').receive('startsWith', '', [ + new StringRefVal('good'), + ]) + ).toStrictEqual(new BoolRefVal(true)); expect( - receiveStringValue( - stringValue('goodbye'), - 'startsWith', - '', - stringValue('bye') - ) - ).toEqual(boolValue(false)); + new StringRefVal('goodbye').receive('startsWith', '', [ + new StringRefVal('bye'), + ]) + ).toStrictEqual(new BoolRefVal(false)); expect( - receiveStringValue( - stringValue('goodbye'), - 'startsWith', - '', - doubleValue(42) - ) - ).toEqual(new Error('no such overload')); + new StringRefVal('goodbye').receive('startsWith', '', [ + new DoubleRefVal(42), + ]) + ).toStrictEqual(ErrorRefVal.errNoSuchOverload); // EndsWith expect( - receiveStringValue( - stringValue('goodbye'), - 'endsWith', - '', - stringValue('bye') - ) - ).toEqual(boolValue(true)); + new StringRefVal('goodbye').receive('endsWith', '', [ + new StringRefVal('bye'), + ]) + ).toStrictEqual(new BoolRefVal(true)); expect( - receiveStringValue( - stringValue('goodbye'), - 'endsWith', - '', - stringValue('good') - ) - ).toEqual(boolValue(false)); + new StringRefVal('goodbye').receive('endsWith', '', [ + new StringRefVal('good'), + ]) + ).toStrictEqual(new BoolRefVal(false)); expect( - receiveStringValue( - stringValue('goodbye'), - 'endsWith', - '', - doubleValue(42) - ) - ).toEqual(new Error('no such overload')); + new StringRefVal('goodbye').receive('endsWith', '', [ + new DoubleRefVal(42), + ]) + ).toStrictEqual(ErrorRefVal.errNoSuchOverload); }); it('sizeStringValue', () => { - expect(() => { - sizeStringValue(doubleValue(42)); - }).toThrow(); - expect(sizeStringValue(stringValue(''))).toEqual(int64Value(BigInt(0))); - expect(sizeStringValue(stringValue('hello world'))).toEqual( - int64Value(BigInt(11)) + expect(new StringRefVal('').size()).toStrictEqual(new IntRefVal(BigInt(0))); + expect(new StringRefVal('hello world').size()).toStrictEqual( + new IntRefVal(BigInt(11)) ); - expect(sizeStringValue(stringValue('\u65e5\u672c\u8a9e'))).toEqual( - int64Value(BigInt(3)) + expect(new StringRefVal('\u65e5\u672c\u8a9e').size()).toStrictEqual( + new IntRefVal(BigInt(3)) ); }); }); diff --git a/packages/cel/src/lib/common/types/string.ts b/packages/cel/src/lib/common/types/string.ts index 5594b7b..4b7f8e2 100644 --- a/packages/cel/src/lib/common/types/string.ts +++ b/packages/cel/src/lib/common/types/string.ts @@ -28,19 +28,28 @@ import { } from '../../overloads'; import { parseBytesConstant } from '../constants'; import { formatCELType } from '../format'; -import { boolValue } from './bool'; +import { RefType, RefTypeEnum, RefVal } from '../ref/reference'; +import { BoolRefVal, boolValue } from './bool'; import { bytesValue } from './bytes'; import { isConstExpr } from './constant'; -import { doubleValue } from './double'; +import { DoubleRefVal, doubleValue } from './double'; import { durationValue, parseISO8061DurationString } from './duration'; -import { int64Value } from './int'; +import { ErrorRefVal } from './error'; +import { IntRefVal, int64Value } from './int'; import { NativeType } from './native'; import { primitiveType } from './primitive'; import { timestampValue } from './timestamp'; +import { Comparer } from './traits/comparer'; +import { Matcher } from './traits/matcher'; +import { Adder } from './traits/math'; +import { Receiver } from './traits/receiver'; +import { Sizer } from './traits/sizer'; import { Trait } from './traits/trait'; -import { uint64Value } from './uint'; +import { Zeroer } from './traits/zeroer'; +import { TypeRefVal } from './type'; +import { UintRefVal, uint64Value } from './uint'; -export const STRING_TYPE = primitiveType(Type_PrimitiveType.STRING); +export const STRING_CEL_TYPE = primitiveType(Type_PrimitiveType.STRING); export function isStringType(val: Type): val is Type & { typeKind: { case: 'primitive'; value: Type_PrimitiveType }; @@ -130,7 +139,7 @@ export function convertStringValueToNative(value: Value, type: NativeType) { break; } return new Error( - `type conversion error from '${formatCELType(STRING_TYPE)}' to '${ + `type conversion error from '${formatCELType(STRING_CEL_TYPE)}' to '${ type.name }'` ); @@ -179,13 +188,13 @@ export function convertStringValueToType(value: Value, type: Type) { } break; case 'type': - return STRING_TYPE; + return STRING_CEL_TYPE; default: break; } return new Error( `type conversion error from '${formatCELType( - STRING_TYPE + STRING_CEL_TYPE )}' to '${formatCELType(type)}'` ); } @@ -314,3 +323,180 @@ export function sizeStringValue(value: Value) { } return int64Value(BigInt(value.kind.value.length)); } + +export class StringRefType implements RefType { + // This has to be a TS private field instead of a # private field because + // otherwise the tests will not be able to access it to check for equality. + // TODO: do we want to alter the tests to use the getter instead? + readonly _traits = STRING_TRAITS; + + celType(): Type { + return STRING_CEL_TYPE; + } + + hasTrait(trait: Trait): boolean { + return this._traits.has(trait); + } + + typeName(): string { + return RefTypeEnum.STRING; + } +} + +export const STRING_REF_TYPE = new StringRefType(); + +export class StringRefVal + implements RefVal, Adder, Comparer, Matcher, Receiver, Sizer, Zeroer +{ + // This has to be a TS private field instead of a # private field because + // otherwise the tests will not be able to access it to check for equality. + // TODO: do we want to alter the tests to use the getter instead? + private readonly _value: string; + + constructor(value: string) { + this._value = value; + } + + static stringContains(str: string, substr: RefVal) { + switch (substr.type().typeName()) { + case RefTypeEnum.STRING: + return new BoolRefVal(str.includes(substr.value())); + default: + return ErrorRefVal.maybeNoSuchOverload(substr); + } + } + + static stringStartsWith(str: string, prefix: RefVal) { + switch (prefix.type().typeName()) { + case RefTypeEnum.STRING: + return new BoolRefVal(str.startsWith(prefix.value())); + default: + return ErrorRefVal.maybeNoSuchOverload(prefix); + } + } + + static stringEndsWith(str: string, suffix: RefVal) { + switch (suffix.type().typeName()) { + case RefTypeEnum.STRING: + return new BoolRefVal(str.endsWith(suffix.value())); + default: + return ErrorRefVal.maybeNoSuchOverload(suffix); + } + } + + static Overloads = new Map([ + [CONTAINS_OVERLOAD, StringRefVal.stringContains], + [STARTS_WITH_OVERLOAD, StringRefVal.stringStartsWith], + [ENDS_WITH_OVERLOAD, StringRefVal.stringEndsWith], + ]); + + celValue(): Value { + return stringValue(this._value); + } + + convertToNative(type: NativeType) { + switch (type) { + case String: + return this._value; + case Uint8Array: + return parseBytesConstant(`b"${this._value}"`).constantKind + .value as Uint8Array; + case AnySchema: + return anyPack( + StringValueSchema, + create(StringValueSchema, { value: this._value }) + ); + case StringValueSchema: + return create(StringValueSchema, { value: this._value }); + default: + return ErrorRefVal.nativeTypeConversionError(this, type); + } + } + + convertToType(type: RefType): RefVal { + switch (type.typeName()) { + case RefTypeEnum.BOOL: + return new BoolRefVal(this._value === 'true'); + case RefTypeEnum.DOUBLE: + return new DoubleRefVal(parseFloat(this._value)); + case RefTypeEnum.INT: + return new IntRefVal(BigInt(parseInt(this._value, 10))); + case RefTypeEnum.STRING: + return new StringRefVal(this._value); + case RefTypeEnum.TYPE: + return new TypeRefVal(STRING_REF_TYPE); + case RefTypeEnum.UINT: + return new UintRefVal(BigInt(parseInt(this._value, 10))); + // TODO: implement other conversions + default: + return ErrorRefVal.typeConversionError(this, type); + } + } + + equal(other: RefVal): RefVal { + switch (other.type().typeName()) { + case RefTypeEnum.STRING: + return new BoolRefVal(this._value === other.value()); + default: + return BoolRefVal.False; + } + } + + type(): RefType { + return STRING_REF_TYPE; + } + + value() { + return this._value; + } + + add(other: RefVal): RefVal { + switch (other.type().typeName()) { + case RefTypeEnum.STRING: + return new StringRefVal(this._value + other.value()); + default: + return ErrorRefVal.maybeNoSuchOverload(other); + } + } + + compare(other: RefVal): RefVal { + switch (other.type().typeName()) { + case RefTypeEnum.STRING: + if (this._value < other.value()) { + return IntRefVal.IntNegOne; + } + if (this._value > other.value()) { + return IntRefVal.IntOne; + } + return IntRefVal.IntZero; + default: + return ErrorRefVal.maybeNoSuchOverload(other); + } + } + + match(pattern: RefVal): RefVal { + switch (pattern.type().typeName()) { + case RefTypeEnum.STRING: + const regexp = new RegExp(pattern.value()); + return new BoolRefVal(regexp.test(this._value)); + default: + return ErrorRefVal.maybeNoSuchOverload(pattern); + } + } + + receive(fn: string, overload: string, args: RefVal[]): RefVal { + const f = StringRefVal.Overloads.get(fn); + if (f) { + return f(this._value, args[0]); + } + return ErrorRefVal.errNoSuchOverload; + } + + size(): RefVal { + return new IntRefVal(BigInt(this._value.length)); + } + + isZeroValue(): boolean { + return this._value === ''; + } +} diff --git a/packages/cel/src/lib/common/types/timestamp.spec.ts b/packages/cel/src/lib/common/types/timestamp.spec.ts index 04c1954..040a238 100644 --- a/packages/cel/src/lib/common/types/timestamp.spec.ts +++ b/packages/cel/src/lib/common/types/timestamp.spec.ts @@ -6,6 +6,8 @@ import { import { objectValue } from './object'; import { isTimestampValue, + timestamp, + timestampFromRfc3339nano, timestampValue, unwrapTimestampValue, } from './timestamp'; @@ -20,4 +22,11 @@ describe('timestamp', () => { expect(isTimestampValue(value)).toBe(true); expect(unwrapTimestampValue(value)).toEqual(timestampFromDate(now)); }); + + it('timestampFromRfc3339nano', () => { + const ts = timestampFromDate(new Date('1970-01-01T02:07:34.000Z')); + expect( + timestampFromRfc3339nano('1970-01-01T02:07:34.000000321Z') + ).toStrictEqual(timestamp(ts.seconds, 321)); + }); }); diff --git a/packages/cel/src/lib/common/types/timestamp.ts b/packages/cel/src/lib/common/types/timestamp.ts index 0d4278b..1debe95 100644 --- a/packages/cel/src/lib/common/types/timestamp.ts +++ b/packages/cel/src/lib/common/types/timestamp.ts @@ -1,37 +1,79 @@ +import { + Type, + TypeSchema, + Type_WellKnownType, +} from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb.js'; import { Value, ValueSchema, } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; -import { MessageInitShape, create } from '@bufbuild/protobuf'; +import { MessageInitShape, clone, create } from '@bufbuild/protobuf'; import { Any, + AnySchema, Timestamp, TimestampSchema, anyPack, anyUnpack, + timestampDate, } from '@bufbuild/protobuf/wkt'; +import { RefType, RefTypeEnum, RefVal } from './../ref/reference'; +import { BoolRefVal } from './bool'; +import { ErrorRefVal } from './error'; +import { IntRefVal } from './int'; +import { NativeType } from './native'; import { isObjectValue } from './object'; +import { StringRefVal } from './string'; +import { Comparer } from './traits/comparer'; +import { Adder, Subtractor } from './traits/math'; +import { Receiver } from './traits/receiver'; +import { Trait } from './traits/trait'; +import { Zeroer } from './traits/zeroer'; +import { TypeRefVal } from './type'; import { typeNameToUrl } from './utils'; import { WKT_REGISTRY } from './wkt'; -// Number of seconds between `0001-01-01T00:00:00Z` and the Unix epoch. +/** + * The number of seconds between year 1 and year 1970. This is borrowed from + * https://golang.org/src/time/time.go. + */ +export const UNIX_TO_INTERNAL = + (1969 * 365 + 1969 / 4 - 1969 / 100 + 1969 / 400) * (60 * 60 * 24); + +/** + * Number of seconds between `0001-01-01T00:00:00Z` and the Unix epoch. + */ export const MIN_UNIX_TIME = -62135596800; -export const MIN_UNIX_TIME_MS = MIN_UNIX_TIME * 1000; -// Number of seconds between `9999-12-31T23:59:59.999999999Z` and the Unix -// epoch. +/** + * Number of seconds between `9999-12-31T23:59:59.999999999Z` and the Unix + * epoch. + */ export const MAX_UNIX_TIME = 253402300799; -export const MAX_UNIX_TIME_MS = MAX_UNIX_TIME * 1000; + +export const TIMESTAMP_CEL_TYPE = create(TypeSchema, { + typeKind: { + case: 'wellKnown', + value: Type_WellKnownType.TIMESTAMP, + }, +}); + +export function timestamp(seconds?: bigint, nanos?: number) { + return create(TimestampSchema, { + seconds, + nanos, + }); +} export function isValidTimestamp(value: Timestamp) { return value.seconds >= MIN_UNIX_TIME && value.seconds <= MAX_UNIX_TIME; } -export function timestampValue(init: MessageInitShape) { +export function timestampValue(ts: MessageInitShape) { return create(ValueSchema, { kind: { case: 'objectValue', - value: anyPack(TimestampSchema, create(TimestampSchema, init)), + value: anyPack(TimestampSchema, timestamp(ts.seconds, ts.nanos)), }, }); } @@ -51,3 +93,143 @@ export function unwrapTimestampValue(value: Value) { } return null; } + +export function timestampFromNanos(nanos: bigint) { + return timestamp(nanos / BigInt(1e9), Number(nanos % BigInt(1e9))); +} + +export function timestampToNanos(ts: Timestamp) { + return ts.seconds * BigInt(1e9) + BigInt(ts.nanos); +} + +export function timestampFromRfc3339nano(value: string) { + const stReg = + /(\d\d\d\d)(-)?(\d\d)(-)?(\d\d)(T)?(\d\d)(:)?(\d\d)?(:)?(\d\d)?([.,]\d+)?($|Z|([+-])(\d\d)(:)?(\d\d)?)/i; + const nsReg = /(^[^.]*)(\.\d*)(Z.*$)/; + if (!value || !stReg.test(value)) { + return null; + } + const dt = new Date( + value + .replace(nsReg, '$1$3') + .replace(/Z-/i, '-') + .replace(/Z\+/i, '+') + .replace(/Z/i, '+') + .replace(/\+$/, 'Z') + ); + const ns = value.replace(nsReg, '$2'); + return timestamp(BigInt(dt.getTime() / 1000), Number(ns) * 1e9); +} + +export const TIMESTAMP_TRAITS = new Set([ + Trait.ADDER_TYPE, + Trait.COMPARER_TYPE, + Trait.RECEIVER_TYPE, + Trait.SUBTRACTOR_TYPE, +]); + +export class TimestampRefType implements RefType { + // This has to be a TS private field instead of a # private field because + // otherwise the tests will not be able to access it to check for equality. + // TODO: do we want to alter the tests to use the getter instead? + private readonly _traits = TIMESTAMP_TRAITS; + + celType(): Type { + return TIMESTAMP_CEL_TYPE; + } + + hasTrait(trait: Trait): boolean { + return this._traits.has(trait); + } + + typeName(): string { + return RefTypeEnum.TIMESTAMP; + } +} + +export const TIMESTAMP_REF_TYPE = new TimestampRefType(); + +export class TimestampRefVal + implements RefVal, Adder, Comparer, Receiver, Subtractor, Zeroer +{ + // This has to be a TS private field instead of a # private field because + // otherwise the tests will not be able to access it to check for equality. + // TODO: do we want to alter the tests to use the getter instead? + private readonly _value: Timestamp; + + constructor(value: Timestamp) { + this._value = value; + } + + celValue(): Value { + return timestampValue(this._value); + } + + convertToNative(type: NativeType) { + switch (type) { + case Date: + return timestampDate(this._value); + case AnySchema: + return anyPack(TimestampSchema, create(TimestampSchema, this._value)); + case TimestampSchema: + return clone(TimestampSchema, this._value); + default: + return ErrorRefVal.nativeTypeConversionError(this, type); + } + } + + convertToType(type: RefType): RefVal { + switch (type.typeName()) { + case RefTypeEnum.INT: + return new IntRefVal(this._value.seconds); + case RefTypeEnum.STRING: + return new StringRefVal(this.toString()); + case RefTypeEnum.TIMESTAMP: + return new TimestampRefVal(this._value); + case RefTypeEnum.TYPE: + return new TypeRefVal(TIMESTAMP_REF_TYPE); + default: + return ErrorRefVal.typeConversionError(this, type); + } + } + + equal(other: RefVal): RefVal { + switch (other.type().typeName()) { + case RefTypeEnum.TIMESTAMP: + return new BoolRefVal( + timestampToNanos(this._value) === + timestampToNanos((other as TimestampRefVal)._value) + ); + default: + return BoolRefVal.False; + } + } + + type(): RefType { + return TIMESTAMP_REF_TYPE; + } + + value() { + return this._value; + } + + add(other: RefVal): RefVal { + throw new Error('Method not implemented.'); + } + + compare(other: RefVal): RefVal { + throw new Error('Method not implemented.'); + } + + receive(fn: string, overload: string, args: RefVal[]): RefVal { + throw new Error('Method not implemented.'); + } + + subtract(subtrahend: RefVal): RefVal { + throw new Error('Method not implemented.'); + } + + isZeroValue(): boolean { + throw new Error('Method not implemented.'); + } +} diff --git a/packages/cel/src/lib/common/types/traits/comparer.ts b/packages/cel/src/lib/common/types/traits/comparer.ts index 8dde281..0d9bd93 100644 --- a/packages/cel/src/lib/common/types/traits/comparer.ts +++ b/packages/cel/src/lib/common/types/traits/comparer.ts @@ -1,4 +1,7 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { isFunction } from '@bearclaw/is'; import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb'; +import { RefVal } from '../../ref/reference'; import { compareBoolValue } from '../bool'; import { compareDoubleValue } from '../double'; import { compareInt64Value } from '../int'; @@ -21,3 +24,23 @@ export function comparer(value: Value, other: Value) { return new Error('no such overload'); } } + +/** + * Comparer interface for ordering comparisons between values in order to + * support '<', '<=', '>=', '>' overloads. + */ +export interface Comparer { + /** + * Compare this value to the input other value, returning an Int: + * this < other -> Int(-1) + * this == other -> Int(0) + * this > other -> Int(1) + * If the comparison cannot be made or is not supported, an error should + * be returned. + */ + compare(other: RefVal): RefVal; +} + +export function isComparer(value: any): value is Comparer { + return value && isFunction(value.compare); +} diff --git a/packages/cel/src/lib/common/types/traits/container.ts b/packages/cel/src/lib/common/types/traits/container.ts new file mode 100644 index 0000000..88ddda7 --- /dev/null +++ b/packages/cel/src/lib/common/types/traits/container.ts @@ -0,0 +1,17 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { isFunction } from '@bearclaw/is'; +import { RefVal } from '../../ref/reference'; + +/** + * Container interface which permits containment tests such as 'a in b'. + */ +export interface Container { + /** + * Contains returns true if the value exists within the object. + */ + contains(value: RefVal): RefVal; +} + +export function isContainer(value: any): value is Container { + return value && isFunction(value.contains); +} diff --git a/packages/cel/src/lib/common/types/traits/field-tester.ts b/packages/cel/src/lib/common/types/traits/field-tester.ts new file mode 100644 index 0000000..6cb4875 --- /dev/null +++ b/packages/cel/src/lib/common/types/traits/field-tester.ts @@ -0,0 +1,22 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { isFunction } from '@bearclaw/is'; +import { RefVal } from '../../ref/reference'; + +/** + * FieldTester indicates if a defined field on an object type is set to a + * non-default value. + * + * For use with the `has()` macro. + */ +export interface FieldTester { + /** + * IsSet returns true if the field is defined and set to a non-default value. + * The method will return false if defined and not set, and an error if the + * field is not defined. + */ + isSet(field: RefVal): RefVal; +} + +export function isFieldTester(value: any): value is FieldTester { + return value && isFunction(value.isSet); +} diff --git a/packages/cel/src/lib/common/types/traits/indexer.ts b/packages/cel/src/lib/common/types/traits/indexer.ts new file mode 100644 index 0000000..ff69658 --- /dev/null +++ b/packages/cel/src/lib/common/types/traits/indexer.ts @@ -0,0 +1,17 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { isFunction } from '@bearclaw/is'; +import { RefVal } from '../../ref/reference'; + +/** + * Indexer permits random access of elements by index 'a[b()]'. + */ +export interface Indexer { + /** + * Get the value at the specified index or error. + */ + get(index: RefVal): RefVal; +} + +export function isIndexer(value: any): value is Indexer { + return value && isFunction(value.get); +} diff --git a/packages/cel/src/lib/common/types/traits/iterator.ts b/packages/cel/src/lib/common/types/traits/iterator.ts new file mode 100644 index 0000000..4cc2f16 --- /dev/null +++ b/packages/cel/src/lib/common/types/traits/iterator.ts @@ -0,0 +1,72 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { isFunction } from '@bearclaw/is'; +import { RefVal, isRefVal } from '../../ref/reference'; + +/** + * Iterable aggregate types permit traversal over their elements. + */ +export interface Iterable { + /** + * Iterator returns a new iterator view of the struct. + */ + iterator(): Iterator; +} + +export function isIterable(value: any): value is Iterable { + return value && isFunction(value.iterator); +} + +/** + * Iterator permits safe traversal over the contents of an aggregate type. + */ +export interface Iterator extends RefVal { + /** + * HasNext returns true if there are unvisited elements in the Iterator. + */ + hasNext(): RefVal; + + /** + * Next returns the next element. + */ + next(): RefVal; +} + +export function isIterator(value: any): value is Iterator { + return ( + value && + isFunction(value.hasNext) && + isFunction(value.next) && + isRefVal(value) + ); +} + +/** + * Foldable aggregate types support iteration over (key, value) or (index, + * value) pairs. + */ +export interface Foldable { + /** + * Fold invokes the Folder.FoldEntry for all entries in the type + */ + fold(folder: Folder): void; +} + +export function isFoldable(value: any): value is Foldable { + return value && isFunction(value.fold); +} + +/** + * Folder performs a fold on a given entry and indicates whether to continue + * folding. + */ +export interface Folder { + /** + * FoldEntry indicates the key, value pair associated with the entry. If the + * output is true, continue folding. Otherwise, terminate the fold. + */ + foldEntry(key: any, val: any): boolean; +} + +export function isFolder(value: any): value is Folder { + return value && isFunction(value.foldEntry); +} diff --git a/packages/cel/src/lib/common/types/traits/lister.ts b/packages/cel/src/lib/common/types/traits/lister.ts new file mode 100644 index 0000000..df67ffb --- /dev/null +++ b/packages/cel/src/lib/common/types/traits/lister.ts @@ -0,0 +1,47 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { isFunction } from '@bearclaw/is'; +import { RefVal, isRefVal } from '../../ref/reference'; +import { Container, isContainer } from './container'; +import { Indexer, isIndexer } from './indexer'; +import { Iterable, isIterable } from './iterator'; +import { Adder, isAdder } from './math'; +import { Sizer, isSizer } from './sizer'; + +/** + * Lister interface which aggregates the traits of a list. + */ +export interface Lister + extends RefVal, + Adder, + Sizer, + Container, + Indexer, + Iterable {} + +export function isLister(value: any): value is Lister { + return ( + value && + isRefVal(value) && + isAdder(value) && + isSizer(value) && + isContainer(value) && + isIndexer(value) && + isIterable(value) + ); +} + +/** + * MutableLister interface which emits an immutable result after an + * intermediate computation. + * + * Note, this interface is intended only to be used within Comprehensions where + * the mutable value is not directly observable within the user-authored CEL + * expression. + */ +export interface MutableLister extends Lister { + toImmutableList(): Lister; +} + +export function isMutableLister(value: any): value is MutableLister { + return value && isFunction(value.toImmutableList) && isLister(value); +} diff --git a/packages/cel/src/lib/common/types/traits/mapper.ts b/packages/cel/src/lib/common/types/traits/mapper.ts new file mode 100644 index 0000000..3f0c826 --- /dev/null +++ b/packages/cel/src/lib/common/types/traits/mapper.ts @@ -0,0 +1,63 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { isFunction } from '@bearclaw/is'; +import { RefVal, isRefVal } from './../../ref/reference'; +import { Container, isContainer } from './container'; +import { Indexer, isIndexer } from './indexer'; +import { Iterable, isIterable } from './iterator'; +import { Sizer, isSizer } from './sizer'; + +/** + * Mapper interface which aggregates the traits of a maps. + */ +export interface Mapper extends RefVal, Container, Indexer, Iterable, Sizer { + /** + * Find returns a value, if one exists, for the input key. + * + * If the key is not found the function returns (nil, false). If the input + * key is not valid for the map, or is Err or Unknown the function returns + * (Unknown|Err, false). + */ + find(key: RefVal): RefVal; +} + +export function isMapper(value: any): value is Mapper { + return ( + value && + isFunction(value.find) && + isRefVal(value) && + isContainer(value) && + isIndexer(value) && + isIterable(value) && + isSizer(value) + ); +} + +/** + * MutableMapper interface which emits an immutable result after an + * intermediate computation. + * + * Note, this interface is intended only to be used within Comprehensions where + * the mutable value is not directly observable within the user-authored CEL + * expression. + */ +export interface MutableMapper extends Mapper { + /** + * Insert a key, value pair into the map, returning the map if the insert is + * successful and an error if key already exists in the mutable map. + */ + insert(k: RefVal, v: RefVal): RefVal; + + /** + * ToImmutableMap converts a mutable map into an immutable map. + */ + toImmutableMap(): Mapper; +} + +export function isMutableMapper(value: any): value is MutableMapper { + return ( + value && + isFunction(value.insert) && + isFunction(value.toImmutableMap) && + isMapper(value) + ); +} diff --git a/packages/cel/src/lib/common/types/traits/matcher.ts b/packages/cel/src/lib/common/types/traits/matcher.ts index 4efff3e..93c3b3e 100644 --- a/packages/cel/src/lib/common/types/traits/matcher.ts +++ b/packages/cel/src/lib/common/types/traits/matcher.ts @@ -1,4 +1,7 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { isFunction } from '@bearclaw/is'; import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb'; +import { RefVal } from '../../ref/reference'; import { matchStringValue } from '../string'; export function matcher(value: Value, other: Value) { @@ -9,3 +12,17 @@ export function matcher(value: Value, other: Value) { return new Error('no such overload'); } } + +/** + * Matcher interface for supporting 'matches()' overloads. + */ +export interface Matcher { + /** + * Match returns true if the pattern matches the current value. + */ + match(pattern: RefVal): RefVal; +} + +export function isMatcher(value: any): value is Matcher { + return value && isFunction(value.match); +} diff --git a/packages/cel/src/lib/common/types/traits/math.ts b/packages/cel/src/lib/common/types/traits/math.ts index afc5257..29ff95c 100644 --- a/packages/cel/src/lib/common/types/traits/math.ts +++ b/packages/cel/src/lib/common/types/traits/math.ts @@ -1,4 +1,7 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { isFunction } from '@bearclaw/is'; import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { RefVal } from '../../ref/reference'; import { addBytesValue } from '../bytes'; import { addDoubleValue, @@ -88,3 +91,96 @@ export function subtractor(value: Value, other: Value) { return new Error('no such overload'); } } + +/** + * Adder interface to support '+' operator overloads. + */ +export interface Adder { + /** + * Add returns a combination of the current value and other value. + * + * If the other value is an unsupported type, an error is returned. + */ + add(other: RefVal): RefVal; +} + +export function isAdder(value: any): value is Adder { + return value && isFunction(value.add); +} + +/** + * Divider interface to support '/' operator overloads. + */ +export interface Divider { + /** + * Divide returns the result of dividing the current value by the input + * denominator. + * + * A denominator value of zero results in an error. + */ + divide(denominator: RefVal): RefVal; +} + +export function isDivider(value: any): value is Divider { + return value && isFunction(value.divide); +} + +/** + * Modder interface to support '%' operator overloads. + */ +export interface Modder { + /** + * Modulo returns the result of taking the modulus of the current value + * by the denominator. + * + * A denominator value of zero results in an error. + */ + modulo(denominator: RefVal): RefVal; +} + +export function isModder(value: any): value is Modder { + return value && isFunction(value.modulo); +} + +/** + * Multiplier interface to support '*' operator overloads. + */ +export interface Multiplier { + /** + * Multiply returns the result of multiplying the current and input value. + */ + multiply(other: RefVal): RefVal; +} + +export function isMultiplier(value: any): value is Multiplier { + return value && isFunction(value.multiply); +} + +/** + * Negater interface to support unary '-' and '!' operator overloads. + */ +export interface Negater { + /** + * Negate returns the complement of the current value. + */ + negate(): RefVal; +} + +export function isNegater(value: any): value is Negater { + return value && isFunction(value.negate); +} + +/** + * Subtractor interface to support binary '-' operator overloads. + */ +export interface Subtractor { + /** + * Subtract returns the result of subtracting the input from the current + * value. + */ + subtract(subtrahend: RefVal): RefVal; +} + +export function isSubtractor(value: any): value is Subtractor { + return value && isFunction(value.subtract); +} diff --git a/packages/cel/src/lib/common/types/traits/receiver.ts b/packages/cel/src/lib/common/types/traits/receiver.ts index 78f328e..582164e 100644 --- a/packages/cel/src/lib/common/types/traits/receiver.ts +++ b/packages/cel/src/lib/common/types/traits/receiver.ts @@ -1,5 +1,8 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { isFunction } from '@bearclaw/is'; import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; import { receiveStringValue } from '../string'; +import { RefVal } from './../../ref/reference'; export function receiver( value: Value, @@ -14,3 +17,18 @@ export function receiver( return new Error('no such overload'); } } + +/** + * Receiver interface for routing instance method calls within a value. + */ +export interface Receiver { + /** + * Receive accepts a function name, overload id, and arguments and returns a + * value. + */ + receive(fn: string, overload: string, args: RefVal[]): RefVal; +} + +export function isReceiver(value: any): value is Receiver { + return value && isFunction(value.receive); +} diff --git a/packages/cel/src/lib/common/types/traits/sizer.ts b/packages/cel/src/lib/common/types/traits/sizer.ts index 798466a..8a8b50b 100644 --- a/packages/cel/src/lib/common/types/traits/sizer.ts +++ b/packages/cel/src/lib/common/types/traits/sizer.ts @@ -1,4 +1,7 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { isFunction } from '@bearclaw/is'; import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; +import { RefVal } from '../../ref/reference'; import { sizeBytesValue } from '../bytes'; import { sizeStringValue } from '../string'; @@ -12,3 +15,17 @@ export function sizer(value: Value) { return new Error('no such overload'); } } + +/** + * Sizer interface for supporting 'size()' overloads. + */ +export interface Sizer { + /** + * Size returns the number of elements or length of the value. + */ + size(): RefVal; +} + +export function isSizer(value: any): value is Sizer { + return value && isFunction(value.size); +} diff --git a/packages/cel/src/lib/common/types/traits/zeroer.ts b/packages/cel/src/lib/common/types/traits/zeroer.ts index 7f3223b..30688a4 100644 --- a/packages/cel/src/lib/common/types/traits/zeroer.ts +++ b/packages/cel/src/lib/common/types/traits/zeroer.ts @@ -1,4 +1,5 @@ -import { isNil } from '@bearclaw/is'; +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { isFunction, isNil } from '@bearclaw/is'; import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; import { boolValue, isZeroBoolValue } from '../bool'; import { isZeroDoubleValue } from '../double'; @@ -27,3 +28,18 @@ export function isZeroValue(value: Value | null | undefined) { return new Error('no such overload'); } } + +/** + * Zeroer interface for testing whether a CEL value is a zero value for its + * type. + */ +export interface Zeroer { + /** + * IsZeroValue indicates whether the object is the zero value for the type. + */ + isZeroValue(): boolean; +} + +export function isZeroer(value: any): value is Zeroer { + return value && isFunction(value.isZeroValue); +} diff --git a/packages/cel/src/lib/common/types/type.ts b/packages/cel/src/lib/common/types/type.ts index aa4e589..75e8066 100644 --- a/packages/cel/src/lib/common/types/type.ts +++ b/packages/cel/src/lib/common/types/type.ts @@ -8,6 +8,11 @@ import { } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb'; import { create } from '@bufbuild/protobuf'; import { formatCELType } from '../format'; +import { RefType, RefTypeEnum, RefVal } from '../ref/reference'; +import { BoolRefVal } from './bool'; +import { ErrorRefVal } from './error'; +import { NativeType } from './native'; +import { Trait } from './traits/trait'; export function typeType(value: Type) { return create(TypeSchema, { @@ -53,3 +58,70 @@ export function isTypeValue(value: Value): value is Value & { } { return value.kind.case === 'typeValue'; } + +export class TypeRefType implements RefType { + // This has to be a TS private field instead of a # private field because + // otherwise the tests will not be able to access it to check for equality. + // TODO: do we want to alter the tests to use the getter instead? + readonly _traits = new Set(); + + celType(): Type { + return create(TypeSchema, { + typeKind: { + case: 'type', + // eslint-disable-next-line @typescript-eslint/no-explicit-any + value: null as any, + }, + }); + } + + hasTrait(trait: Trait): boolean { + return this._traits.has(trait); + } + + typeName(): string { + return RefTypeEnum.TYPE; + } +} + +export const TYPE_REF_TYPE = new TypeRefType(); + +export class TypeRefVal implements RefVal { + // This has to be a TS private field instead of a # private field because + // otherwise the tests will not be able to access it to check for equality. + // TODO: do we want to alter the tests to use the getter instead? + private readonly _value: RefType; + + constructor(value: RefType) { + this._value = value; + } + + celValue(): Value { + return create(ValueSchema, { + kind: { + case: 'typeValue', + value: this._value.typeName(), + }, + }); + } + + convertToNative(type: NativeType) { + return ErrorRefVal.nativeTypeConversionError(this, type); + } + + convertToType(type: RefType): RefVal { + return ErrorRefVal.typeConversionError(this, type); + } + + equal(other: RefVal): RefVal { + return new BoolRefVal(this._value.typeName() === other.type().typeName()); + } + + type(): RefType { + return TYPE_REF_TYPE; + } + + value() { + return this._value; + } +} diff --git a/packages/cel/src/lib/common/types/uint.spec.ts b/packages/cel/src/lib/common/types/uint.spec.ts index 4f4480b..ae1405b 100644 --- a/packages/cel/src/lib/common/types/uint.spec.ts +++ b/packages/cel/src/lib/common/types/uint.spec.ts @@ -10,23 +10,15 @@ import { UInt64ValueSchema, anyPack, } from '@bufbuild/protobuf/wkt'; -import { boolValue } from './bool'; -import { DOUBLE_TYPE, doubleValue } from './double'; -import { INT64_TYPE, MAX_INT64, int64Value } from './int'; -import { STRING_TYPE, stringValue } from './string'; -import { TYPE_TYPE } from './type'; +import { BoolRefVal } from './bool'; +import { DOUBLE_REF_TYPE, DoubleRefVal } from './double'; +import { ErrorRefVal } from './error'; +import { INT_REF_TYPE, IntRefVal, MAX_INT64 } from './int'; +import { STRING_REF_TYPE, StringRefVal } from './string'; +import { TYPE_REF_TYPE, TypeRefVal } from './type'; import { - UINT64_TYPE, - addUint64Value, - compareUint64Value, - convertUint64ValueToNative, - convertUint64ValueToType, - divideUint64Value, - equalUint64Value, - isZeroUint64Value, - moduloUint64Value, - multiplyUint64Value, - subtractUint64Value, + UINT_REF_TYPE, + UintRefVal, uint64Constant, uint64Expr, uint64Value, @@ -75,22 +67,19 @@ describe('uint', () => { // TODO; validations it('convertUint64ValueToNative', () => { - expect(() => { - convertUint64ValueToNative(stringValue('abc'), Number); - }).toThrow(); const tests = [ { - input: uint64Value(BigInt(1)), + input: new UintRefVal(BigInt(1)), type: BigInt, output: BigInt(1), }, { - input: uint64Value(BigInt(2)), + input: new UintRefVal(BigInt(2)), type: Number, output: 2, }, { - input: uint64Value(BigInt(42)), + input: new UintRefVal(BigInt(42)), type: AnySchema, output: anyPack( UInt64ValueSchema, @@ -98,297 +87,270 @@ describe('uint', () => { ), }, { - input: uint64Value(BigInt(1234)), + input: new UintRefVal(BigInt(1234)), type: UInt32ValueSchema, output: create(UInt32ValueSchema, { value: 1234 }), }, { - input: uint64Value(BigInt(5678)), + input: new UintRefVal(BigInt(5678)), type: UInt64ValueSchema, output: create(UInt64ValueSchema, { value: BigInt(5678) }), }, { - input: uint64Value(BigInt(5678)), + input: new UintRefVal(BigInt(5678)), type: String, - output: new Error(`type conversion error from 'uint' to 'String'`), + output: ErrorRefVal.nativeTypeConversionError( + new UintRefVal(BigInt(0)), + String + ), }, ]; for (const test of tests) { - expect(convertUint64ValueToNative(test.input, test.type)).toEqual( - test.output - ); + expect(test.input.convertToNative(test.type)).toStrictEqual(test.output); } }); it('convertUint64ValueToType', () => { - expect(() => { - convertUint64ValueToType(stringValue('abc'), UINT64_TYPE); - }).toThrow(); - const tests = [ { - in: uint64Value(BigInt(42)), - type: TYPE_TYPE, - out: UINT64_TYPE, + in: new UintRefVal(BigInt(42)), + type: TYPE_REF_TYPE, + out: new TypeRefVal(UINT_REF_TYPE), }, { - in: uint64Value(BigInt(46)), - type: UINT64_TYPE, - out: uint64Value(BigInt(46)), + in: new UintRefVal(BigInt(46)), + type: UINT_REF_TYPE, + out: new UintRefVal(BigInt(46)), }, { - in: uint64Value(BigInt(312)), - type: INT64_TYPE, - out: int64Value(BigInt(312)), + in: new UintRefVal(BigInt(312)), + type: INT_REF_TYPE, + out: new IntRefVal(BigInt(312)), }, { - in: uint64Value(BigInt(894)), - type: DOUBLE_TYPE, - out: doubleValue(894), + in: new UintRefVal(BigInt(894)), + type: DOUBLE_REF_TYPE, + out: new DoubleRefVal(894), }, { - in: uint64Value(BigInt(5848)), - type: STRING_TYPE, - out: stringValue('5848'), + in: new UintRefVal(BigInt(5848)), + type: STRING_REF_TYPE, + out: new StringRefVal('5848'), }, { - in: uint64Value(MAX_INT64 + BigInt(1)), - type: INT64_TYPE, - out: new Error('integer overflow'), + in: new UintRefVal(MAX_INT64 + BigInt(1)), + type: INT_REF_TYPE, + out: ErrorRefVal.errIntOverflow, }, { - in: uint64Value(MAX_INT64 + BigInt(1)), - type: UINT64_TYPE, - out: new Error('unsigned integer overflow'), + in: new UintRefVal(MAX_INT64 + BigInt(1)), + type: UINT_REF_TYPE, + out: ErrorRefVal.errUintOverflow, }, ]; for (const test of tests) { - expect(convertUint64ValueToType(test.in, test.type)).toEqual(test.out); + expect(test.in.convertToType(test.type)).toStrictEqual(test.out); } }); it('equalUint64Value', () => { - expect(() => { - equalUint64Value(stringValue('abc'), uint64Value(BigInt(1))); - }).toThrow(); const tests = [ { - a: uint64Value(BigInt(10)), - b: uint64Value(BigInt(10)), - out: boolValue(true), + a: new UintRefVal(BigInt(10)), + b: new UintRefVal(BigInt(10)), + out: new BoolRefVal(true), }, { - a: uint64Value(BigInt(10)), - b: int64Value(BigInt(-10)), - out: boolValue(false), + a: new UintRefVal(BigInt(10)), + b: new IntRefVal(BigInt(-10)), + out: new BoolRefVal(false), }, { - a: uint64Value(BigInt(10)), - b: int64Value(BigInt(10)), - out: boolValue(true), + a: new UintRefVal(BigInt(10)), + b: new IntRefVal(BigInt(10)), + out: new BoolRefVal(true), }, { - a: uint64Value(BigInt(9)), - b: int64Value(BigInt(10)), - out: boolValue(false), + a: new UintRefVal(BigInt(9)), + b: new IntRefVal(BigInt(10)), + out: new BoolRefVal(false), }, { - a: uint64Value(BigInt(10)), - b: doubleValue(10), - out: boolValue(true), + a: new UintRefVal(BigInt(10)), + b: new DoubleRefVal(10), + out: new BoolRefVal(true), }, { - a: uint64Value(BigInt(10)), - b: doubleValue(-10.5), - out: boolValue(false), + a: new UintRefVal(BigInt(10)), + b: new DoubleRefVal(-10.5), + out: new BoolRefVal(false), }, { - a: uint64Value(BigInt(10)), - b: doubleValue(NaN), - out: boolValue(false), + a: new UintRefVal(BigInt(10)), + b: new DoubleRefVal(NaN), + out: new BoolRefVal(false), }, ]; for (const test of tests) { - expect(equalUint64Value(test.a, test.b)).toEqual(test.out); + expect(test.a.equal(test.b)).toStrictEqual(test.out); } }); it('isZeroUint64Value', () => { - expect(() => { - isZeroUint64Value(stringValue('abc')); - }).toThrow(); - expect(isZeroUint64Value(uint64Value(BigInt(0)))).toEqual(boolValue(true)); - expect(isZeroUint64Value(uint64Value(BigInt(1)))).toEqual(boolValue(false)); + expect(new UintRefVal(BigInt(0)).isZeroValue()).toEqual(true); + expect(new UintRefVal(BigInt(1)).isZeroValue()).toEqual(false); }); it('addUint64Value', () => { - expect(() => { - addUint64Value(stringValue('abc'), uint64Value(BigInt(1))); - }).toThrow(); expect( - addUint64Value(uint64Value(BigInt(1)), uint64Value(BigInt(2))) - ).toEqual(uint64Value(BigInt(3))); - expect(addUint64Value(uint64Value(BigInt(1)), stringValue('2'))).toEqual( - new Error('no such overload') + new UintRefVal(BigInt(1)).add(new UintRefVal(BigInt(2))) + ).toStrictEqual(new UintRefVal(BigInt(3))); + expect(new UintRefVal(BigInt(1)).add(new StringRefVal('2'))).toStrictEqual( + ErrorRefVal.errNoSuchOverload ); expect( - addUint64Value(uint64Value(MAX_INT64), uint64Value(BigInt(1))) - ).toEqual(new Error('unsigned integer overflow')); + new UintRefVal(BigInt(1)).add(new UintRefVal(MAX_INT64)) + ).toStrictEqual(ErrorRefVal.errUintOverflow); expect( - addUint64Value(uint64Value(BigInt(1)), int64Value(BigInt(-1000))) - ).toEqual(new Error('unsigned integer overflow')); + new UintRefVal(BigInt(1)).add(new IntRefVal(BigInt(-1000))) + ).toStrictEqual(ErrorRefVal.errUintOverflow); expect( - addUint64Value(uint64Value(MAX_INT64 - BigInt(1)), uint64Value(BigInt(1))) - ).toEqual(uint64Value(MAX_INT64)); + new UintRefVal(MAX_INT64 - BigInt(1)).add(new UintRefVal(BigInt(1))) + ).toStrictEqual(new UintRefVal(MAX_INT64)); }); it('compareUint64Value', () => { - expect(() => { - compareUint64Value(stringValue('abc'), uint64Value(BigInt(1))); - }).toThrow(); const tests = [ { - a: uint64Value(BigInt(42)), - b: uint64Value(BigInt(42)), - out: int64Value(BigInt(0)), + a: new UintRefVal(BigInt(42)), + b: new UintRefVal(BigInt(42)), + out: new IntRefVal(BigInt(0)), }, { - a: uint64Value(BigInt(42)), - b: int64Value(BigInt(42)), - out: int64Value(BigInt(0)), + a: new UintRefVal(BigInt(42)), + b: new IntRefVal(BigInt(42)), + out: new IntRefVal(BigInt(0)), }, { - a: uint64Value(BigInt(42)), - b: doubleValue(42), - out: int64Value(BigInt(0)), + a: new UintRefVal(BigInt(42)), + b: new DoubleRefVal(42), + out: new IntRefVal(BigInt(0)), }, { - a: uint64Value(BigInt(13)), - b: int64Value(BigInt(204)), - out: int64Value(BigInt(-1)), + a: new UintRefVal(BigInt(13)), + b: new IntRefVal(BigInt(204)), + out: new IntRefVal(BigInt(-1)), }, { - a: uint64Value(BigInt(13)), - b: uint64Value(BigInt(204)), - out: int64Value(BigInt(-1)), + a: new UintRefVal(BigInt(13)), + b: new UintRefVal(BigInt(204)), + out: new IntRefVal(BigInt(-1)), }, { - a: uint64Value(BigInt(204)), - b: doubleValue(204.1), - out: int64Value(BigInt(-1)), + a: new UintRefVal(BigInt(204)), + b: new DoubleRefVal(204.1), + out: new IntRefVal(BigInt(-1)), }, { - a: uint64Value(BigInt(204)), - b: int64Value(BigInt(205)), - out: int64Value(BigInt(-1)), + a: new UintRefVal(BigInt(204)), + b: new IntRefVal(BigInt(205)), + out: new IntRefVal(BigInt(-1)), }, { - a: uint64Value(BigInt(204)), - b: doubleValue(Number(MAX_INT64) + 2049.0), - out: int64Value(BigInt(-1)), + a: new UintRefVal(BigInt(204)), + b: new DoubleRefVal(Number(MAX_INT64) + 2049.0), + out: new IntRefVal(BigInt(-1)), }, { - a: uint64Value(BigInt(204)), - b: doubleValue(NaN), - out: new Error('NaN values cannot be ordered'), + a: new UintRefVal(BigInt(204)), + b: new DoubleRefVal(NaN), + out: new ErrorRefVal('NaN values cannot be ordered'), }, { - a: uint64Value(BigInt(1300)), - b: int64Value(BigInt(-1)), - out: int64Value(BigInt(1)), + a: new UintRefVal(BigInt(1300)), + b: new IntRefVal(BigInt(-1)), + out: new IntRefVal(BigInt(1)), }, { - a: uint64Value(BigInt(204)), - b: uint64Value(BigInt(13)), - out: int64Value(BigInt(1)), + a: new UintRefVal(BigInt(204)), + b: new UintRefVal(BigInt(13)), + out: new IntRefVal(BigInt(1)), }, { - a: uint64Value(BigInt(204)), - b: doubleValue(203.9), - out: int64Value(BigInt(1)), + a: new UintRefVal(BigInt(204)), + b: new DoubleRefVal(203.9), + out: new IntRefVal(BigInt(1)), }, { - a: uint64Value(BigInt(204)), - b: doubleValue(-1.0), - out: int64Value(BigInt(1)), + a: new UintRefVal(BigInt(204)), + b: new DoubleRefVal(-1.0), + out: new IntRefVal(BigInt(1)), }, { - a: uint64Value(BigInt(12)), - b: stringValue('1'), - out: new Error('no such overload'), + a: new UintRefVal(BigInt(12)), + b: new StringRefVal('1'), + out: ErrorRefVal.errNoSuchOverload, }, ]; for (const test of tests) { - expect(compareUint64Value(test.a, test.b)).toEqual(test.out); + expect(test.a.compare(test.b)).toStrictEqual(test.out); } }); it('divideUint64Value', () => { - expect(() => { - divideUint64Value(stringValue('abc'), uint64Value(BigInt(1))); - }).toThrow(); expect( - divideUint64Value(uint64Value(BigInt(3)), uint64Value(BigInt(2))) - ).toEqual(uint64Value(BigInt(1))); - expect(divideUint64Value(uint64Value(BigInt(3)), stringValue('2'))).toEqual( - new Error('no such overload') - ); + new UintRefVal(BigInt(3)).divide(new UintRefVal(BigInt(2))) + ).toStrictEqual(new UintRefVal(BigInt(1))); expect( - divideUint64Value(uint64Value(BigInt(3)), uint64Value(BigInt(0))) - ).toEqual(new Error('divide by zero')); + new UintRefVal(BigInt(3)).divide(new StringRefVal('2')) + ).toStrictEqual(ErrorRefVal.errNoSuchOverload); + expect( + new UintRefVal(BigInt(3)).divide(new UintRefVal(BigInt(0))) + ).toStrictEqual(ErrorRefVal.errDivideByZero); }); it('moduloUint64Value', () => { - expect(() => { - moduloUint64Value(stringValue('abc'), uint64Value(BigInt(1))); - }).toThrow(); expect( - moduloUint64Value(uint64Value(BigInt(21)), uint64Value(BigInt(2))) - ).toEqual(uint64Value(BigInt(1))); - expect(moduloUint64Value(uint64Value(BigInt(3)), stringValue('2'))).toEqual( - new Error('no such overload') - ); + new UintRefVal(BigInt(21)).modulo(new UintRefVal(BigInt(2))) + ).toStrictEqual(new UintRefVal(BigInt(1))); + expect( + new UintRefVal(BigInt(3)).modulo(new StringRefVal('2')) + ).toStrictEqual(ErrorRefVal.errNoSuchOverload); expect( - moduloUint64Value(uint64Value(BigInt(3)), uint64Value(BigInt(0))) - ).toEqual(new Error('modulus by zero')); + new UintRefVal(BigInt(3)).modulo(new UintRefVal(BigInt(0))) + ).toStrictEqual(ErrorRefVal.errModulusByZero); }); it('multiplyUint64Value', () => { - expect(() => { - multiplyUint64Value(stringValue('abc'), uint64Value(BigInt(1))); - }).toThrow(); expect( - multiplyUint64Value(uint64Value(BigInt(3)), uint64Value(BigInt(2))) - ).toEqual(uint64Value(BigInt(6))); + new UintRefVal(BigInt(3)).multiply(new UintRefVal(BigInt(2))) + ).toStrictEqual(new UintRefVal(BigInt(6))); expect( - multiplyUint64Value(uint64Value(BigInt(3)), stringValue('2')) - ).toEqual(new Error('no such overload')); + new UintRefVal(BigInt(3)).multiply(new StringRefVal('2')) + ).toStrictEqual(ErrorRefVal.errNoSuchOverload); expect( - multiplyUint64Value(uint64Value(BigInt(3)), uint64Value(BigInt(0))) - ).toEqual(uint64Value(BigInt(0))); + new UintRefVal(BigInt(3)).multiply(new UintRefVal(BigInt(0))) + ).toStrictEqual(new UintRefVal(BigInt(0))); expect( - multiplyUint64Value(uint64Value(MAX_INT64), uint64Value(BigInt(2))) - ).toEqual(new Error('unsigned integer overflow')); + new UintRefVal(MAX_INT64).multiply(new UintRefVal(BigInt(2))) + ).toStrictEqual(ErrorRefVal.errUintOverflow); expect( - multiplyUint64Value(uint64Value(BigInt(42)), int64Value(BigInt(-1))) - ).toEqual(new Error('unsigned integer overflow')); + new UintRefVal(BigInt(42)).multiply(new IntRefVal(BigInt(-1))) + ).toStrictEqual(ErrorRefVal.errUintOverflow); }); it('subtractUint64Value', () => { - expect(() => { - subtractUint64Value(stringValue('abc'), uint64Value(BigInt(1))); - }).toThrow(); expect( - subtractUint64Value(uint64Value(BigInt(3)), uint64Value(BigInt(2))) - ).toEqual(uint64Value(BigInt(1))); + new UintRefVal(BigInt(3)).subtract(new UintRefVal(BigInt(2))) + ).toStrictEqual(new UintRefVal(BigInt(1))); expect( - subtractUint64Value(uint64Value(BigInt(3)), stringValue('2')) - ).toEqual(new Error('no such overload')); + new UintRefVal(BigInt(3)).subtract(new StringRefVal('2')) + ).toStrictEqual(ErrorRefVal.errNoSuchOverload); expect( - subtractUint64Value(uint64Value(BigInt(3)), uint64Value(BigInt(4))) - ).toEqual(new Error('unsigned integer overflow')); + new UintRefVal(BigInt(3)).subtract(new UintRefVal(BigInt(4))) + ).toStrictEqual(ErrorRefVal.errUintOverflow); expect( - subtractUint64Value(uint64Value(MAX_INT64), int64Value(BigInt(-1))) - ).toEqual(new Error('unsigned integer overflow')); + new UintRefVal(MAX_INT64).subtract(new IntRefVal(BigInt(-1))) + ).toStrictEqual(ErrorRefVal.errUintOverflow); }); }); diff --git a/packages/cel/src/lib/common/types/uint.ts b/packages/cel/src/lib/common/types/uint.ts index d54c957..4003cc7 100644 --- a/packages/cel/src/lib/common/types/uint.ts +++ b/packages/cel/src/lib/common/types/uint.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-case-declarations */ import { Type, Type_PrimitiveType, @@ -20,18 +21,24 @@ import { anyPack, } from '@bufbuild/protobuf/wkt'; import { formatCELType } from '../format'; -import { boolValue } from './bool'; -import { compareNumberValues } from './compare'; +import { RefType, RefTypeEnum, RefVal } from './../ref/reference'; +import { BoolRefVal, boolValue } from './bool'; +import { compareNumberRefVals, compareNumberValues } from './compare'; import { isConstExpr } from './constant'; -import { doubleValue, isDoubleValue } from './double'; -import { MAX_INT64, int64Value } from './int'; +import { DoubleRefVal, doubleValue, isDoubleValue } from './double'; +import { ErrorRefVal } from './error'; +import { IntRefVal, MAX_INT64, int64Value } from './int'; import { NativeType } from './native'; import { isNumberValue } from './number'; import { primitiveType } from './primitive'; -import { stringValue } from './string'; +import { StringRefVal, stringValue } from './string'; +import { Comparer } from './traits/comparer'; +import { Adder, Divider, Modder, Multiplier, Subtractor } from './traits/math'; import { Trait } from './traits/trait'; +import { Zeroer } from './traits/zeroer'; +import { TypeRefVal } from './type'; -export const UINT64_TYPE = primitiveType(Type_PrimitiveType.UINT64); +export const UINT_CEL_TYPE = primitiveType(Type_PrimitiveType.UINT64); export function isUint64Type(type: Type): type is Type & { typeKind: { case: 'primitive'; value: Type_PrimitiveType }; @@ -144,7 +151,7 @@ export function convertUint64ValueToNative(value: Value, type: NativeType) { break; } return new Error( - `type conversion error from '${formatCELType(UINT64_TYPE)}' to '${ + `type conversion error from '${formatCELType(UINT_CEL_TYPE)}' to '${ type.name }'` ); @@ -182,13 +189,13 @@ export function convertUint64ValueToType(value: Value, type: Type) { } break; case 'type': - return UINT64_TYPE; + return UINT_CEL_TYPE; default: break; } return new Error( `type conversion error from '${formatCELType( - UINT64_TYPE + UINT_CEL_TYPE )}' to '${formatCELType(type)}'` ); } @@ -329,3 +336,236 @@ export function subtractUint64Value(value: Value, other: Value) { } return uint64Value(result); } + +export class UintRefType implements RefType { + // This has to be a TS private field instead of a # private field because + // otherwise the tests will not be able to access it to check for equality. + // TODO: do we want to alter the tests to use the getter instead? + private readonly _traits = UINT64_TRAITS; + + celType(): Type { + return UINT_CEL_TYPE; + } + + hasTrait(trait: Trait): boolean { + return this._traits.has(trait); + } + + typeName(): string { + return RefTypeEnum.UINT; + } +} + +export const UINT_REF_TYPE = new UintRefType(); + +export class UintRefVal + implements + RefVal, + Adder, + Comparer, + Divider, + Modder, + Multiplier, + Subtractor, + Zeroer +{ + // This has to be a TS private field instead of a # private field because + // otherwise the tests will not be able to access it to check for equality. + // TODO: do we want to alter the tests to use the getter instead? + private readonly _value: bigint; + + constructor(value: bigint) { + this._value = value; + } + + celValue(): Value { + return uint64Value(this._value); + } + + convertToNative(type: NativeType) { + switch (type) { + case BigInt: + return this._value; + case Number: + return Number(this._value); + case AnySchema: + return anyPack( + UInt64ValueSchema, + create(UInt64ValueSchema, { value: this._value }) + ); + case UInt32ValueSchema: + if (!isValidUint32(Number(this._value))) { + return ErrorRefVal.errUintOverflow; + } + return create(UInt32ValueSchema, { value: Number(this._value) }); + case UInt64ValueSchema: + if (!isValidUint64(this._value)) { + return ErrorRefVal.errUintOverflow; + } + return create(UInt64ValueSchema, { value: this._value }); + default: + return ErrorRefVal.nativeTypeConversionError(this, type); + } + } + + convertToType(type: RefType): RefVal { + switch (type.typeName()) { + case RefTypeEnum.DOUBLE: + return new DoubleRefVal(Number(this._value)); + case RefTypeEnum.INT: + if (Number.isNaN(this._value) || !isValidUint64(this._value)) { + return ErrorRefVal.errIntOverflow; + } + return new IntRefVal(this._value); + case RefTypeEnum.STRING: + return new StringRefVal(this._value.toString()); + case RefTypeEnum.TYPE: + return new TypeRefVal(UINT_REF_TYPE); + case RefTypeEnum.UINT: + if (Number.isNaN(this._value) || !isValidUint64(this._value)) { + return ErrorRefVal.errUintOverflow; + } + return new UintRefVal(this._value); + default: + return ErrorRefVal.typeConversionError(this, type); + } + } + + equal(other: RefVal): RefVal { + if (Number.isNaN(this._value) || Number.isNaN(other.value())) { + return BoolRefVal.False; + } + switch (other.type().typeName()) { + case RefTypeEnum.DOUBLE: + case RefTypeEnum.INT: + case RefTypeEnum.UINT: + const compared = compareNumberRefVals(this, other); + if (compared.type().typeName() === RefTypeEnum.ERR) { + return compared; + } + return new BoolRefVal(compared.value() === BigInt(0)); + default: + return BoolRefVal.False; + } + } + + type(): RefType { + return UINT_REF_TYPE; + } + + value() { + return this._value; + } + + add(other: RefVal): RefVal { + switch (other.type().typeName()) { + case RefTypeEnum.DOUBLE: + case RefTypeEnum.INT: + case RefTypeEnum.UINT: + if ( + (other.value() > 0 && + this._value > MAX_INT64 - BigInt(other.value())) || + (other.value() < 0 && this._value < Math.abs(Number(other.value()))) + ) { + return ErrorRefVal.errUintOverflow; + } + return new UintRefVal(this._value + BigInt(other.value())); + default: + return ErrorRefVal.maybeNoSuchOverload(other); + } + } + + compare(other: RefVal): RefVal { + if ( + Number.isNaN(Number(this._value)) || + Number.isNaN(Number(other.value())) + ) { + return new ErrorRefVal('NaN values cannot be ordered'); + } + switch (other.type().typeName()) { + case RefTypeEnum.DOUBLE: + if (this._value < Number.MIN_SAFE_INTEGER) { + return IntRefVal.IntNegOne; + } + if (this._value > Number.MAX_SAFE_INTEGER) { + return IntRefVal.IntOne; + } + return compareNumberRefVals(this, other); + case RefTypeEnum.INT: + case RefTypeEnum.UINT: + return compareNumberRefVals(this, other); + default: + return ErrorRefVal.maybeNoSuchOverload(other); + } + } + + divide(denominator: RefVal): RefVal { + switch (denominator.type().typeName()) { + case RefTypeEnum.DOUBLE: + case RefTypeEnum.INT: + case RefTypeEnum.UINT: + if (Number(denominator.value()) === 0) { + return ErrorRefVal.errDivideByZero; + } + return new UintRefVal(this._value / BigInt(denominator.value())); + default: + return ErrorRefVal.maybeNoSuchOverload(denominator); + } + } + + modulo(denominator: RefVal): RefVal { + switch (denominator.type().typeName()) { + case RefTypeEnum.DOUBLE: + case RefTypeEnum.INT: + case RefTypeEnum.UINT: + if (Number(denominator.value()) === 0) { + return ErrorRefVal.errModulusByZero; + } + return new UintRefVal(this._value % BigInt(denominator.value())); + default: + return ErrorRefVal.maybeNoSuchOverload(denominator); + } + } + + multiply(other: RefVal): RefVal { + switch (other.type().typeName()) { + case RefTypeEnum.DOUBLE: + case RefTypeEnum.INT: + case RefTypeEnum.UINT: + const x = this._value; + const y = BigInt(other.value()); + // Detecting multiplication overflow is more complicated than the + // others. The first two detect attempting to negate MinUint64, which + // would result in MaxUint64+1. The other four detect normal overflow + // conditions. + if (y !== BigInt(0) && x > MAX_INT64 / y) { + return ErrorRefVal.errUintOverflow; + } + return new UintRefVal(x * y); + default: + return ErrorRefVal.maybeNoSuchOverload(other); + } + } + + subtract(subtrahend: RefVal): RefVal { + switch (subtrahend.type().typeName()) { + case RefTypeEnum.DOUBLE: + case RefTypeEnum.INT: + case RefTypeEnum.UINT: + if (subtrahend.value() > this._value) { + return ErrorRefVal.errUintOverflow; + } + const result = this._value - BigInt(subtrahend.value()); + if (result < BigInt(0) || result > MAX_INT64) { + return ErrorRefVal.errUintOverflow; + } + return new UintRefVal(result); + default: + return ErrorRefVal.maybeNoSuchOverload(subtrahend); + } + } + + isZeroValue(): boolean { + return this._value === BigInt(0); + } +} diff --git a/packages/cel/src/lib/common/types/unknown.ts b/packages/cel/src/lib/common/types/unknown.ts index d25ae53..ea2d24e 100644 --- a/packages/cel/src/lib/common/types/unknown.ts +++ b/packages/cel/src/lib/common/types/unknown.ts @@ -1,6 +1,12 @@ +import { Type } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb'; import { Value } from '@buf/google_cel-spec.bufbuild_es/cel/expr/value_pb.js'; import { create } from '@bufbuild/protobuf'; import { ValueSchema } from '@bufbuild/protobuf/wkt'; +import { RefType, RefTypeEnum, RefVal } from '../ref/reference'; +import { BoolRefVal } from './bool'; +import { ErrorRefVal } from './error'; +import { NativeType } from './native'; +import { Trait } from './traits/trait'; // eslint-disable-next-line @typescript-eslint/no-explicit-any export function unknownValue(value: any) { @@ -17,3 +23,67 @@ export function isUnknownValue(value: Value): value is Value & { } { return value.kind.case === undefined; } + +export class UnknownRefType implements RefType { + readonly #traits = new Set(); + + celType(): Type { + throw new Error('Method not implemented.'); + } + + hasTrait(trait: Trait): boolean { + return this.#traits.has(trait); + } + + typeName(): string { + return RefTypeEnum.UNKNOWN; + } +} + +export const UNKNOWN_REF_TYPE = new UnknownRefType(); + +/** + * Unknown type implementation which collects expression ids which caused the + * current value to become unknown. + */ +export class UnknownRefVal implements RefVal { + readonly #value: bigint; + + constructor(value: bigint) { + this.#value = value; + } + + celValue(): Value { + throw new Error('Method not implemented.'); + } + + convertToNative(typeDesc: NativeType) { + switch (typeDesc) { + case Number: + return Number(this.#value); + case BigInt: + return this.#value; + case String: + return this.#value.toString(); + default: + return ErrorRefVal.nativeTypeConversionError(this, typeDesc); + } + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + convertToType(typeValue: RefType): RefVal { + return this; + } + + equal(other: RefVal): RefVal { + return new BoolRefVal(this.type().typeName() === other.type().typeName()); + } + + type(): RefType { + return UNKNOWN_REF_TYPE; + } + + value() { + return this.#value; + } +} diff --git a/packages/cel/src/lib/common/types/utils.spec.ts b/packages/cel/src/lib/common/types/utils.spec.ts index 8258a26..ffa0730 100644 --- a/packages/cel/src/lib/common/types/utils.spec.ts +++ b/packages/cel/src/lib/common/types/utils.spec.ts @@ -1,24 +1,24 @@ import { Type_PrimitiveType } from '@buf/google_cel-spec.bufbuild_es/cel/expr/checked_pb'; import { ScalarType } from '@bufbuild/protobuf'; -import { BOOL_TYPE } from './bool'; -import { BYTES_TYPE } from './bytes'; +import { BOOL_CEL_TYPE } from './bool'; +import { BYTES_CEL_TYPE } from './bytes'; import { DYN_TYPE } from './dyn'; import { ERROR_TYPE } from './error'; -import { INT64_TYPE } from './int'; +import { INT_CEL_TYPE } from './int'; import { primitiveType } from './primitive'; -import { STRING_TYPE } from './string'; -import { UINT64_TYPE } from './uint'; +import { STRING_CEL_TYPE } from './string'; +import { UINT_CEL_TYPE } from './uint'; import { isDynTypeOrErrorType, scalarTypeToPrimitiveType } from './utils'; describe('utils', () => { it('isDynTypeOrErrorType', () => { expect(isDynTypeOrErrorType(DYN_TYPE)).toBe(true); expect(isDynTypeOrErrorType(ERROR_TYPE)).toBe(true); - expect(isDynTypeOrErrorType(BOOL_TYPE)).toBe(false); - expect(isDynTypeOrErrorType(BYTES_TYPE)).toBe(false); - expect(isDynTypeOrErrorType(INT64_TYPE)).toBe(false); - expect(isDynTypeOrErrorType(STRING_TYPE)).toBe(false); - expect(isDynTypeOrErrorType(UINT64_TYPE)).toBe(false); + expect(isDynTypeOrErrorType(BOOL_CEL_TYPE)).toBe(false); + expect(isDynTypeOrErrorType(BYTES_CEL_TYPE)).toBe(false); + expect(isDynTypeOrErrorType(INT_CEL_TYPE)).toBe(false); + expect(isDynTypeOrErrorType(STRING_CEL_TYPE)).toBe(false); + expect(isDynTypeOrErrorType(UINT_CEL_TYPE)).toBe(false); }); it('scalarTypeToPrimitiveType', () => { diff --git a/packages/cel/src/lib/common/types/wkt.ts b/packages/cel/src/lib/common/types/wkt.ts index 675277c..6749126 100644 --- a/packages/cel/src/lib/common/types/wkt.ts +++ b/packages/cel/src/lib/common/types/wkt.ts @@ -9,16 +9,16 @@ import { DurationSchema, TimestampSchema, } from '@bufbuild/protobuf/wkt'; -import { BOOL_TYPE } from './bool'; -import { BYTES_TYPE } from './bytes'; -import { DOUBLE_TYPE } from './double'; +import { BOOL_CEL_TYPE } from './bool'; +import { BYTES_CEL_TYPE } from './bytes'; +import { DOUBLE_CEL_TYPE } from './double'; import { DYN_TYPE } from './dyn'; -import { INT64_TYPE } from './int'; +import { INT_CEL_TYPE } from './int'; import { listType } from './list'; import { mapType } from './map'; import { NULL_TYPE } from './null'; -import { STRING_TYPE } from './string'; -import { UINT64_TYPE } from './uint'; +import { STRING_CEL_TYPE } from './string'; +import { UINT_CEL_TYPE } from './uint'; export function wellKnownType(value: Type_WellKnownType) { return create(TypeSchema, { @@ -77,20 +77,20 @@ export function getCheckedWellKnownType(value: string) { switch (value) { // Wrapper types. case 'google.protobuf.BoolValue': - return BOOL_TYPE; + return BOOL_CEL_TYPE; case 'google.protobuf.BytesValue': - return BYTES_TYPE; + return BYTES_CEL_TYPE; case 'google.protobuf.DoubleValue': case 'google.protobuf.FloatValue': - return DOUBLE_TYPE; + return DOUBLE_CEL_TYPE; case 'google.protobuf.Int64Value': case 'google.protobuf.Int32Value': - return INT64_TYPE; + return INT_CEL_TYPE; case 'google.protobuf.UInt64Value': case 'google.protobuf.UInt32Value': - return UINT64_TYPE; + return UINT_CEL_TYPE; case 'google.protobuf.StringValue': - return STRING_TYPE; + return STRING_CEL_TYPE; // Well-known types. case 'google.protobuf.Any': return ANY_TYPE; @@ -104,7 +104,7 @@ export function getCheckedWellKnownType(value: string) { case 'google.protobuf.NullValue': return NULL_TYPE; case 'google.protobuf.Struct': - return mapType({ keyType: STRING_TYPE, valueType: DYN_TYPE }); + return mapType({ keyType: STRING_CEL_TYPE, valueType: DYN_TYPE }); case 'google.protobuf.Value': return DYN_TYPE; default: diff --git a/packages/cel/src/lib/environment.ts b/packages/cel/src/lib/environment.ts index 8478957..1305328 100644 --- a/packages/cel/src/lib/environment.ts +++ b/packages/cel/src/lib/environment.ts @@ -20,10 +20,10 @@ import { STANDARD_IDENT_DECLARATIONS, } from './common/standard'; import { DYN_TYPE } from './common/types/dyn'; -import { INT64_TYPE } from './common/types/int'; +import { INT_CEL_TYPE } from './common/types/int'; import { mapType } from './common/types/map'; import { messageType } from './common/types/message'; -import { STRING_TYPE } from './common/types/string'; +import { STRING_CEL_TYPE } from './common/types/string'; import { getFieldDescriptorType } from './common/types/utils'; import { getCheckedWellKnownType, @@ -274,8 +274,8 @@ export class CELEnvironment { if (!isNil(enumDesc)) { const decl = identDecl(candidateName, { type: mapType({ - keyType: STRING_TYPE, - valueType: INT64_TYPE, + keyType: STRING_CEL_TYPE, + valueType: INT_CEL_TYPE, }), }); this.addIdent(decl); diff --git a/packages/cel/src/lib/interpreter/attribute-factory.spec.ts b/packages/cel/src/lib/interpreter/attribute-factory.spec.ts index 8f266a1..42e8fd5 100644 --- a/packages/cel/src/lib/interpreter/attribute-factory.spec.ts +++ b/packages/cel/src/lib/interpreter/attribute-factory.spec.ts @@ -1,6 +1,6 @@ import { CELContainer } from '../common/container'; import { ProtoTypeRegistry } from '../common/pb/proto-type-registry'; -import { INT64_TYPE } from '../common/types/int'; +import { INT_CEL_TYPE } from '../common/types/int'; import { stringValue } from '../common/types/string'; import { typeValue } from '../common/types/type'; import { MapActivation } from './activation'; @@ -45,7 +45,7 @@ describe('AttributeFactory', () => { // int const attr = attrs.absoluteAttribute(BigInt(1), 'int') as AbsoluteAttribute; const out = attr.resolve(new MapActivation()); - expect(out).toEqual(typeValue(INT64_TYPE)); + expect(out).toEqual(typeValue(INT_CEL_TYPE)); expect(attr.cost()).toEqual(new Cost(1, 1)); }); }); diff --git a/packages/cel/src/lib/parser/macros.ts b/packages/cel/src/lib/parser/macros.ts index 9b2e811..8870148 100644 --- a/packages/cel/src/lib/parser/macros.ts +++ b/packages/cel/src/lib/parser/macros.ts @@ -5,7 +5,7 @@ import { ParserRuleContext, Token } from 'antlr4'; import { Location, OffsetRange } from '../common/ast'; import { ACCUMULATOR_VAR } from '../common/constants'; import { functionDecl, overloadDecl } from '../common/decls/function-decl'; -import { BOOL_TYPE, boolExpr } from '../common/types/bool'; +import { BOOL_CEL_TYPE, boolExpr } from '../common/types/bool'; import { callExpr } from '../common/types/call'; import { comprehensionExpr } from '../common/types/comprehension'; import { DYN_TYPE } from '../common/types/dyn'; @@ -38,7 +38,7 @@ export const STANDARD_MACRO_DECLARATIONS = new Set([ overloadDecl({ isInstanceFunction: false, params: [DYN_TYPE], - resultType: BOOL_TYPE, + resultType: BOOL_CEL_TYPE, }), ], }), @@ -49,7 +49,7 @@ export const STANDARD_MACRO_DECLARATIONS = new Set([ overloadDecl({ isInstanceFunction: true, params: [DYN_TYPE, DYN_TYPE], - resultType: BOOL_TYPE, + resultType: BOOL_CEL_TYPE, }), ], }), @@ -60,7 +60,7 @@ export const STANDARD_MACRO_DECLARATIONS = new Set([ overloadDecl({ isInstanceFunction: true, params: [DYN_TYPE, DYN_TYPE], - resultType: BOOL_TYPE, + resultType: BOOL_CEL_TYPE, }), ], }), @@ -71,7 +71,7 @@ export const STANDARD_MACRO_DECLARATIONS = new Set([ overloadDecl({ isInstanceFunction: true, params: [DYN_TYPE, DYN_TYPE], - resultType: BOOL_TYPE, + resultType: BOOL_CEL_TYPE, }), ], }), From b1a318614a42d1dc10e9a2ab4262c5671048c3c0 Mon Sep 17 00:00:00 2001 From: jafaircl Date: Thu, 7 Nov 2024 22:16:17 -0500 Subject: [PATCH 34/34] feat(cel): timestamp date parsing --- .../src/lib/common/types/timestamp.spec.ts | 35 +++++- .../cel/src/lib/common/types/timestamp.ts | 116 +++++++++++++++--- 2 files changed, 130 insertions(+), 21 deletions(-) diff --git a/packages/cel/src/lib/common/types/timestamp.spec.ts b/packages/cel/src/lib/common/types/timestamp.spec.ts index 040a238..008ca1b 100644 --- a/packages/cel/src/lib/common/types/timestamp.spec.ts +++ b/packages/cel/src/lib/common/types/timestamp.spec.ts @@ -7,7 +7,8 @@ import { objectValue } from './object'; import { isTimestampValue, timestamp, - timestampFromRfc3339nano, + timestampFromDateString, + timestampToDateString, timestampValue, unwrapTimestampValue, } from './timestamp'; @@ -23,10 +24,34 @@ describe('timestamp', () => { expect(unwrapTimestampValue(value)).toEqual(timestampFromDate(now)); }); - it('timestampFromRfc3339nano', () => { - const ts = timestampFromDate(new Date('1970-01-01T02:07:34.000Z')); + it('timestampFromDateString', () => { + // Iso8601 without timezone + expect(timestampFromDateString('2011-10-05T14:48:00.000Z')).toStrictEqual( + timestamp(BigInt(1317826080), 0) + ); + + // Iso8601 with timezone + expect( + timestampFromDateString('2011-10-05T14:48:00.000-04:00') + ).toStrictEqual(timestamp(BigInt(1317811680), 0)); + + // Nanos without timezone + expect( + timestampFromDateString('1970-01-01T02:07:34.000000321Z') + ).toStrictEqual(timestamp(BigInt(7654), 321)); + + // Nanos with timezone expect( - timestampFromRfc3339nano('1970-01-01T02:07:34.000000321Z') - ).toStrictEqual(timestamp(ts.seconds, 321)); + timestampFromDateString('1970-01-01T02:07:34.000000321+07:00') + ).toStrictEqual(timestamp(BigInt(32854), 321)); + }); + + it('timestampToDateString', () => { + expect(timestampToDateString(timestamp(BigInt(1317826080), 0))).toEqual( + '2011-10-05T14:48:00.000Z' + ); + expect(timestampToDateString(timestamp(BigInt(1317826080), 321))).toEqual( + '2011-10-05T14:48:00.000000321Z' + ); }); }); diff --git a/packages/cel/src/lib/common/types/timestamp.ts b/packages/cel/src/lib/common/types/timestamp.ts index 1debe95..49804b2 100644 --- a/packages/cel/src/lib/common/types/timestamp.ts +++ b/packages/cel/src/lib/common/types/timestamp.ts @@ -16,6 +16,7 @@ import { anyPack, anyUnpack, timestampDate, + timestampFromDate, } from '@bufbuild/protobuf/wkt'; import { RefType, RefTypeEnum, RefVal } from './../ref/reference'; import { BoolRefVal } from './bool'; @@ -102,23 +103,104 @@ export function timestampToNanos(ts: Timestamp) { return ts.seconds * BigInt(1e9) + BigInt(ts.nanos); } -export function timestampFromRfc3339nano(value: string) { - const stReg = - /(\d\d\d\d)(-)?(\d\d)(-)?(\d\d)(T)?(\d\d)(:)?(\d\d)?(:)?(\d\d)?([.,]\d+)?($|Z|([+-])(\d\d)(:)?(\d\d)?)/i; - const nsReg = /(^[^.]*)(\.\d*)(Z.*$)/; - if (!value || !stReg.test(value)) { +/** + * Parses a timestamp from a string. Will accept RFC3339 timestamps with or + * without nanoseconds and with or without a timezone or ISO8601 timestamps + * with or without a timezone. + * + * Example values: + * - `1970-01-01T02:07:34.000000321Z` + * - `1970-01-01T02:07:34.000000321+07:00` + * - `2011-10-05T14:48:00.000Z` + * - `2011-10-05T14:48:00.000-04:00` + * + * This function is based on the Go implementation of RFC3339 parsing: + * @see https://cs.opensource.google/go/go/+/refs/tags/go1.23.3:src/time/format_rfc3339.go + * + * 1970-01-01T02:07:34.000000321Z + */ +export function timestampFromDateString(value: string) { + /** + * Parses a string as an unsigned integer between min and max. + * + * @param s the string to parse + * @param min the minimum value + * @param max the maximum value + * @returns the parsed integer or the min value if the string is invalid + */ + function parseUint(s: string, min: number, max: number) { + const parsed = parseInt(s, 10); + if (Number.isNaN(parsed) || parsed < min || parsed > max) { + return min; + } + return parsed; + } + + if (value.length < '2006-01-02T15:04:05'.length) { return null; } - const dt = new Date( - value - .replace(nsReg, '$1$3') - .replace(/Z-/i, '-') - .replace(/Z\+/i, '+') - .replace(/Z/i, '+') - .replace(/\+$/, 'Z') - ); - const ns = value.replace(nsReg, '$2'); - return timestamp(BigInt(dt.getTime() / 1000), Number(ns) * 1e9); + const year = parseUint(value.slice(0, 4), 0, 9999); // e.g., 2006 + const month = parseUint(value.slice(5, 7), 1, 12); // e.g., 01 + // TODO: handle months with fewer than 31 days + const day = parseUint(value.slice(8, 10), 1, 31); // e.g., 02 + const hour = parseUint(value.slice(11, 13), 0, 23); // e.g., 15 + const min = parseUint(value.slice(14, 16), 0, 59); // e.g., 04 + const sec = parseUint(value.slice(17, 19), 0, 59); // e.g., 05 + + value = value.slice(19); + + // Parse the fractional second. + let nanos = 0; + if (value.length > 1 && value[0] === '.') { + value = value.slice(2); + let i = 0; + while (i < value.length && '0' <= value[i] && value[i] <= '9') { + i++; + } + const frac = value.slice(0, i); + nanos = parseInt(frac, 10); + value = value.slice(i); + } + + // Construct the date object + const date = new Date(Date.UTC(year, month - 1, day, hour, min, sec)); + + // Parse the timezone + if (value.length !== 1 || value !== 'Z') { + if ( + value.length !== '-07:00'.length || + (value[0] !== '+' && value[0] !== '-') || + value[3] !== ':' + ) { + return null; + } + const hr = parseUint(value.slice(1, 3), 0, 23); // e.g., 07 + const mm = parseUint(value.slice(4, 6), 0, 59); // e.g., 00 + let zoneOffset = hr * 60 + mm; + if (value[0] === '-') { + zoneOffset = -zoneOffset; + } + date.setMinutes(date.getMinutes() + zoneOffset); + } + const ts = timestampFromDate(date); + return timestamp(ts.seconds, nanos); +} + +/** + * Converts a timestamp to a string. The string will be in RFC3339 format with + * nanoseconds if the timestamp has nanoseconds. Otherwise, it will be in + * ISO8061 format. The string will always be in UTC. + * + * @param ts the timestamp to convert + * @returns the timestamp as a string + */ +export function timestampToDateString(ts: Timestamp) { + const date = timestampDate(ts); + if (ts.nanos === 0) { + return date.toISOString(); + } + const paddedNanos = ts.nanos.toString().padStart(9, '0'); + return date.toISOString().replace(/\.\d+Z$/, `.${paddedNanos}Z`); } export const TIMESTAMP_TRAITS = new Set([ @@ -169,6 +251,8 @@ export class TimestampRefVal switch (type) { case Date: return timestampDate(this._value); + case String: + return timestampToDateString(this._value); case AnySchema: return anyPack(TimestampSchema, create(TimestampSchema, this._value)); case TimestampSchema: @@ -183,7 +267,7 @@ export class TimestampRefVal case RefTypeEnum.INT: return new IntRefVal(this._value.seconds); case RefTypeEnum.STRING: - return new StringRefVal(this.toString()); + return new StringRefVal(timestampToDateString(this._value)); case RefTypeEnum.TIMESTAMP: return new TimestampRefVal(this._value); case RefTypeEnum.TYPE: