diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..0ec4fa0 --- /dev/null +++ b/bun.lock @@ -0,0 +1,566 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "get", + "devDependencies": { + "@biomejs/biome": "^2.2.3", + "@changesets/changelog-github": "^0.5.1", + "@changesets/cli": "^2.29.6", + "@types/bun": "^1.2.21", + "knip": "^5.63.1", + "sherif": "^1.6.1", + "typescript": "^5.9.2", + }, + }, + "packages/ast": { + "name": "@getlang/ast", + "version": "0.0.1", + "dependencies": { + "moo": "^0.5.2", + }, + }, + "packages/get": { + "name": "@getlang/get", + "version": "0.2.5", + "dependencies": { + "@getlang/ast": "workspace:^0.0.1", + "@getlang/lib": "workspace:^0.1.5", + "@getlang/parser": "workspace:^0.3.4", + "@getlang/walker": "workspace:^0.0.1", + "acorn": "^8.15.0", + "estree-toolkit": "^1.7.13", + "lodash-es": "^4.17.21", + }, + "devDependencies": { + "@types/lodash-es": "^4.17.12", + }, + }, + "packages/lib": { + "name": "@getlang/lib", + "version": "0.1.5", + "dependencies": { + "@getlang/ast": "workspace:^0.0.1", + "@getlang/xpath": "0.0.35-0", + "@types/esquery": "^1.5.4", + "@types/lodash-es": "^4.17.12", + "@types/set-cookie-parser": "^2.4.10", + "acorn": "^8.15.0", + "css-select": "^6.0.0", + "css-what": "^7.0.0", + "dom-serializer": "^2.0.0", + "domelementtype": "*", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "esquery": "^1.6.0", + "lodash-es": "^4.17.21", + "parse5": "^8.0.0", + "parse5-htmlparser2-tree-adapter": "^8.0.0", + "set-cookie-parser": "^2.7.1", + }, + }, + "packages/parser": { + "name": "@getlang/parser", + "version": "0.3.4", + "dependencies": { + "@getlang/ast": "workspace:^0.0.1", + "@getlang/lib": "workspace:^0.1.5", + "@getlang/walker": "workspace:^0.0.1", + "@types/moo": "^0.5.10", + "@types/nearley": "^2.11.5", + "acorn": "^8.15.0", + "estree-toolkit": "^1.7.13", + "globals": "^16.3.0", + "lodash-es": "^4.17.21", + "moo": "^0.5.2", + "nearley": "^2.20.1", + "prettier": "^3.6.2", + }, + "devDependencies": { + "@types/lodash-es": "^4.17.12", + }, + }, + "packages/walker": { + "name": "@getlang/walker", + "version": "0.0.1", + "dependencies": { + "@getlang/ast": "workspace:^0.0.1", + }, + }, + "test": { + "name": "test", + "dependencies": { + "@getlang/get": "workspace:*", + "@getlang/lib": "workspace:^0.1.5", + "@getlang/parser": "workspace:*", + "dedent": "^1.7.0", + }, + "devDependencies": { + "jest-diff": "^30.1.2", + }, + }, + }, + "packages": { + "@babel/runtime": ["@babel/runtime@7.28.4", "", {}, "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ=="], + + "@biomejs/biome": ["@biomejs/biome@2.2.3", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.2.3", "@biomejs/cli-darwin-x64": "2.2.3", "@biomejs/cli-linux-arm64": "2.2.3", "@biomejs/cli-linux-arm64-musl": "2.2.3", "@biomejs/cli-linux-x64": "2.2.3", "@biomejs/cli-linux-x64-musl": "2.2.3", "@biomejs/cli-win32-arm64": "2.2.3", "@biomejs/cli-win32-x64": "2.2.3" }, "bin": { "biome": "bin/biome" } }, "sha512-9w0uMTvPrIdvUrxazZ42Ib7t8Y2yoGLKLdNne93RLICmaHw7mcLv4PPb5LvZLJF3141gQHiCColOh/v6VWlWmg=="], + + "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.2.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-OrqQVBpadB5eqzinXN4+Q6honBz+tTlKVCsbEuEpljK8ASSItzIRZUA02mTikl3H/1nO2BMPFiJ0nkEZNy3B1w=="], + + "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.2.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-OCdBpb1TmyfsTgBAM1kPMXyYKTohQ48WpiN9tkt9xvU6gKVKHY4oVwteBebiOqyfyzCNaSiuKIPjmHjUZ2ZNMg=="], + + "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.2.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-g/Uta2DqYpECxG+vUmTAmUKlVhnGEcY7DXWgKP8ruLRa8Si1QHsWknPY3B/wCo0KgYiFIOAZ9hjsHfNb9L85+g=="], + + "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.2.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-q3w9jJ6JFPZPeqyvwwPeaiS/6NEszZ+pXKF+IczNo8Xj6fsii45a4gEEicKyKIytalV+s829ACZujQlXAiVLBQ=="], + + "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.2.3", "", { "os": "linux", "cpu": "x64" }, "sha512-LEtyYL1fJsvw35CxrbQ0gZoxOG3oZsAjzfRdvRBRHxOpQ91Q5doRVjvWW/wepgSdgk5hlaNzfeqpyGmfSD0Eyw=="], + + "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.2.3", "", { "os": "linux", "cpu": "x64" }, "sha512-y76Dn4vkP1sMRGPFlNc+OTETBhGPJ90jY3il6jAfur8XWrYBQV3swZ1Jo0R2g+JpOeeoA0cOwM7mJG6svDz79w=="], + + "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.2.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-Ms9zFYzjcJK7LV+AOMYnjN3pV3xL8Prxf9aWdDVL74onLn5kcvZ1ZMQswE5XHtnd/r/0bnUd928Rpbs14BzVmA=="], + + "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.2.3", "", { "os": "win32", "cpu": "x64" }, "sha512-gvCpewE7mBwBIpqk1YrUqNR4mCiyJm6UI3YWQQXkedSSEwzRdodRpaKhbdbHw1/hmTWOVXQ+Eih5Qctf4TCVOQ=="], + + "@changesets/apply-release-plan": ["@changesets/apply-release-plan@7.0.12", "", { "dependencies": { "@changesets/config": "^3.1.1", "@changesets/get-version-range-type": "^0.4.0", "@changesets/git": "^3.0.4", "@changesets/should-skip-package": "^0.1.2", "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3", "detect-indent": "^6.0.0", "fs-extra": "^7.0.1", "lodash.startcase": "^4.4.0", "outdent": "^0.5.0", "prettier": "^2.7.1", "resolve-from": "^5.0.0", "semver": "^7.5.3" } }, "sha512-EaET7As5CeuhTzvXTQCRZeBUcisoYPDDcXvgTE/2jmmypKp0RC7LxKj/yzqeh/1qFTZI7oDGFcL1PHRuQuketQ=="], + + "@changesets/assemble-release-plan": ["@changesets/assemble-release-plan@6.0.9", "", { "dependencies": { "@changesets/errors": "^0.2.0", "@changesets/get-dependents-graph": "^2.1.3", "@changesets/should-skip-package": "^0.1.2", "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3", "semver": "^7.5.3" } }, "sha512-tPgeeqCHIwNo8sypKlS3gOPmsS3wP0zHt67JDuL20P4QcXiw/O4Hl7oXiuLnP9yg+rXLQ2sScdV1Kkzde61iSQ=="], + + "@changesets/changelog-git": ["@changesets/changelog-git@0.2.1", "", { "dependencies": { "@changesets/types": "^6.1.0" } }, "sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q=="], + + "@changesets/changelog-github": ["@changesets/changelog-github@0.5.1", "", { "dependencies": { "@changesets/get-github-info": "^0.6.0", "@changesets/types": "^6.1.0", "dotenv": "^8.1.0" } }, "sha512-BVuHtF+hrhUScSoHnJwTELB4/INQxVFc+P/Qdt20BLiBFIHFJDDUaGsZw+8fQeJTRP5hJZrzpt3oZWh0G19rAQ=="], + + "@changesets/cli": ["@changesets/cli@2.29.6", "", { "dependencies": { "@changesets/apply-release-plan": "^7.0.12", "@changesets/assemble-release-plan": "^6.0.9", "@changesets/changelog-git": "^0.2.1", "@changesets/config": "^3.1.1", "@changesets/errors": "^0.2.0", "@changesets/get-dependents-graph": "^2.1.3", "@changesets/get-release-plan": "^4.0.13", "@changesets/git": "^3.0.4", "@changesets/logger": "^0.1.1", "@changesets/pre": "^2.0.2", "@changesets/read": "^0.6.5", "@changesets/should-skip-package": "^0.1.2", "@changesets/types": "^6.1.0", "@changesets/write": "^0.4.0", "@inquirer/external-editor": "^1.0.0", "@manypkg/get-packages": "^1.1.3", "ansi-colors": "^4.1.3", "ci-info": "^3.7.0", "enquirer": "^2.4.1", "fs-extra": "^7.0.1", "mri": "^1.2.0", "p-limit": "^2.2.0", "package-manager-detector": "^0.2.0", "picocolors": "^1.1.0", "resolve-from": "^5.0.0", "semver": "^7.5.3", "spawndamnit": "^3.0.1", "term-size": "^2.1.0" }, "bin": { "changeset": "bin.js" } }, "sha512-6qCcVsIG1KQLhpQ5zE8N0PckIx4+9QlHK3z6/lwKnw7Tir71Bjw8BeOZaxA/4Jt00pcgCnCSWZnyuZf5Il05QQ=="], + + "@changesets/config": ["@changesets/config@3.1.1", "", { "dependencies": { "@changesets/errors": "^0.2.0", "@changesets/get-dependents-graph": "^2.1.3", "@changesets/logger": "^0.1.1", "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3", "fs-extra": "^7.0.1", "micromatch": "^4.0.8" } }, "sha512-bd+3Ap2TKXxljCggI0mKPfzCQKeV/TU4yO2h2C6vAihIo8tzseAn2e7klSuiyYYXvgu53zMN1OeYMIQkaQoWnA=="], + + "@changesets/errors": ["@changesets/errors@0.2.0", "", { "dependencies": { "extendable-error": "^0.1.5" } }, "sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow=="], + + "@changesets/get-dependents-graph": ["@changesets/get-dependents-graph@2.1.3", "", { "dependencies": { "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3", "picocolors": "^1.1.0", "semver": "^7.5.3" } }, "sha512-gphr+v0mv2I3Oxt19VdWRRUxq3sseyUpX9DaHpTUmLj92Y10AGy+XOtV+kbM6L/fDcpx7/ISDFK6T8A/P3lOdQ=="], + + "@changesets/get-github-info": ["@changesets/get-github-info@0.6.0", "", { "dependencies": { "dataloader": "^1.4.0", "node-fetch": "^2.5.0" } }, "sha512-v/TSnFVXI8vzX9/w3DU2Ol+UlTZcu3m0kXTjTT4KlAdwSvwutcByYwyYn9hwerPWfPkT2JfpoX0KgvCEi8Q/SA=="], + + "@changesets/get-release-plan": ["@changesets/get-release-plan@4.0.13", "", { "dependencies": { "@changesets/assemble-release-plan": "^6.0.9", "@changesets/config": "^3.1.1", "@changesets/pre": "^2.0.2", "@changesets/read": "^0.6.5", "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3" } }, "sha512-DWG1pus72FcNeXkM12tx+xtExyH/c9I1z+2aXlObH3i9YA7+WZEVaiHzHl03thpvAgWTRaH64MpfHxozfF7Dvg=="], + + "@changesets/get-version-range-type": ["@changesets/get-version-range-type@0.4.0", "", {}, "sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ=="], + + "@changesets/git": ["@changesets/git@3.0.4", "", { "dependencies": { "@changesets/errors": "^0.2.0", "@manypkg/get-packages": "^1.1.3", "is-subdir": "^1.1.1", "micromatch": "^4.0.8", "spawndamnit": "^3.0.1" } }, "sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw=="], + + "@changesets/logger": ["@changesets/logger@0.1.1", "", { "dependencies": { "picocolors": "^1.1.0" } }, "sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg=="], + + "@changesets/parse": ["@changesets/parse@0.4.1", "", { "dependencies": { "@changesets/types": "^6.1.0", "js-yaml": "^3.13.1" } }, "sha512-iwksMs5Bf/wUItfcg+OXrEpravm5rEd9Bf4oyIPL4kVTmJQ7PNDSd6MDYkpSJR1pn7tz/k8Zf2DhTCqX08Ou+Q=="], + + "@changesets/pre": ["@changesets/pre@2.0.2", "", { "dependencies": { "@changesets/errors": "^0.2.0", "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3", "fs-extra": "^7.0.1" } }, "sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug=="], + + "@changesets/read": ["@changesets/read@0.6.5", "", { "dependencies": { "@changesets/git": "^3.0.4", "@changesets/logger": "^0.1.1", "@changesets/parse": "^0.4.1", "@changesets/types": "^6.1.0", "fs-extra": "^7.0.1", "p-filter": "^2.1.0", "picocolors": "^1.1.0" } }, "sha512-UPzNGhsSjHD3Veb0xO/MwvasGe8eMyNrR/sT9gR8Q3DhOQZirgKhhXv/8hVsI0QpPjR004Z9iFxoJU6in3uGMg=="], + + "@changesets/should-skip-package": ["@changesets/should-skip-package@0.1.2", "", { "dependencies": { "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3" } }, "sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw=="], + + "@changesets/types": ["@changesets/types@6.1.0", "", {}, "sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA=="], + + "@changesets/write": ["@changesets/write@0.4.0", "", { "dependencies": { "@changesets/types": "^6.1.0", "fs-extra": "^7.0.1", "human-id": "^4.1.1", "prettier": "^2.7.1" } }, "sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q=="], + + "@emnapi/core": ["@emnapi/core@1.5.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg=="], + + "@emnapi/runtime": ["@emnapi/runtime@1.5.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ=="], + + "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="], + + "@getlang/ast": ["@getlang/ast@workspace:packages/ast"], + + "@getlang/get": ["@getlang/get@workspace:packages/get"], + + "@getlang/lib": ["@getlang/lib@workspace:packages/lib"], + + "@getlang/parser": ["@getlang/parser@workspace:packages/parser"], + + "@getlang/walker": ["@getlang/walker@workspace:packages/walker"], + + "@getlang/xpath": ["@getlang/xpath@0.0.35-0", "", {}, "sha512-kXe2kSVp0cdra0q1N8px43oKz+jOJ9CiJ1vrDYJ/cEQp0T+DSTMSLf7XdeIiIPqoj/N1bJMdV5eqPyB7wo/G3w=="], + + "@inquirer/external-editor": ["@inquirer/external-editor@1.0.1", "", { "dependencies": { "chardet": "^2.1.0", "iconv-lite": "^0.6.3" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-Oau4yL24d2B5IL4ma4UpbQigkVhzPDXLoqy1ggK4gnHg/stmkffJE4oOXHXF3uz0UEpywG68KcyXsyYpA1Re/Q=="], + + "@jest/diff-sequences": ["@jest/diff-sequences@30.0.1", "", {}, "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw=="], + + "@jest/get-type": ["@jest/get-type@30.1.0", "", {}, "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA=="], + + "@jest/schemas": ["@jest/schemas@30.0.5", "", { "dependencies": { "@sinclair/typebox": "^0.34.0" } }, "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA=="], + + "@manypkg/find-root": ["@manypkg/find-root@1.1.0", "", { "dependencies": { "@babel/runtime": "^7.5.5", "@types/node": "^12.7.1", "find-up": "^4.1.0", "fs-extra": "^8.1.0" } }, "sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA=="], + + "@manypkg/get-packages": ["@manypkg/get-packages@1.1.3", "", { "dependencies": { "@babel/runtime": "^7.5.5", "@changesets/types": "^4.0.1", "@manypkg/find-root": "^1.1.0", "fs-extra": "^8.1.0", "globby": "^11.0.0", "read-yaml-file": "^1.1.0" } }, "sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A=="], + + "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.3", "", { "dependencies": { "@emnapi/core": "^1.4.5", "@emnapi/runtime": "^1.4.5", "@tybys/wasm-util": "^0.10.0" } }, "sha512-rZxtMsLwjdXkMUGC3WwsPwLNVqVqnTJT6MNIB6e+5fhMcSCPP0AOsNWuMQ5mdCq6HNjs/ZeWAEchpqeprqBD2Q=="], + + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], + + "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], + + "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + + "@oxc-resolver/binding-android-arm-eabi": ["@oxc-resolver/binding-android-arm-eabi@11.7.1", "", { "os": "android", "cpu": "arm" }, "sha512-K0gF1mD6CYMAuX0dMWe6XW1Js00xCOBh/+ZAAJReQMa4+jmAk3bIeitsc8VnDthDbzOOKp3riizP3o/tBvNpgw=="], + + "@oxc-resolver/binding-android-arm64": ["@oxc-resolver/binding-android-arm64@11.7.1", "", { "os": "android", "cpu": "arm64" }, "sha512-O1XEX/KxKX7baPgYHahP+3vT+9f4gasPA0px4DYrjy1mN9wWQqJPLLo/PO3cBw3qI3qRaaiAGT3eJSs8rKu8mA=="], + + "@oxc-resolver/binding-darwin-arm64": ["@oxc-resolver/binding-darwin-arm64@11.7.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-OSCJlXUTvGoal5dTMkdacmXL2R3YQ+97R7NMSdjkUVnh3TxvGBhoF9OebqY3PR7w2gQaY5LX+Ju+dYeHGBCGgw=="], + + "@oxc-resolver/binding-darwin-x64": ["@oxc-resolver/binding-darwin-x64@11.7.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-d0jKwK4r4Yw19xSijyt7wHZT77xh3v4GnJSbvEiPavLms27zqc//BqYJUSp9XgOTOkyFQ+oHno47JNiLTnsSnQ=="], + + "@oxc-resolver/binding-freebsd-x64": ["@oxc-resolver/binding-freebsd-x64@11.7.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-oNch5OpAnxFjukDZ5GJkuEDEPPYDirm10q2cJcbK0SETVM0rY+ou1cLqJAJC9R/dULbqGKC9fv2kuyuw9M6Fig=="], + + "@oxc-resolver/binding-linux-arm-gnueabihf": ["@oxc-resolver/binding-linux-arm-gnueabihf@11.7.1", "", { "os": "linux", "cpu": "arm" }, "sha512-ldUPUfV/0L56fTSfzUo86Bmgov8SAfau8Q4Y3WiAiQi6WHLA239abTZZViLZuXvrC+4RQF/kD0ySqKfBjW/X9g=="], + + "@oxc-resolver/binding-linux-arm-musleabihf": ["@oxc-resolver/binding-linux-arm-musleabihf@11.7.1", "", { "os": "linux", "cpu": "arm" }, "sha512-M+ORXlPV0dXCHleqOYLjKHwxn9kDmcJqnJ7zGZ07vggaxOCnpM6zqyGS92YTTyeYre2AqO3Xrx1D4rnUeozI8g=="], + + "@oxc-resolver/binding-linux-arm64-gnu": ["@oxc-resolver/binding-linux-arm64-gnu@11.7.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-ukHZp9Vm07AlxqdOLFf8Bj4inzpt+ISbbODvwwHxX32GfcMLWYYJGAYWc13IGhWoElvWnI7D1M9ifDGyTNRGzg=="], + + "@oxc-resolver/binding-linux-arm64-musl": ["@oxc-resolver/binding-linux-arm64-musl@11.7.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-atkZ1OIt6t90kjQz1iqq6cN3OpfPG5zUJlO64Vd1ieYeqHRkOFeRgnWEobTePUHi34NlYr7mNZqIaAg7gjPUFg=="], + + "@oxc-resolver/binding-linux-ppc64-gnu": ["@oxc-resolver/binding-linux-ppc64-gnu@11.7.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-HGgV4z3JwVF4Qvg2a1GhDnqn8mKLihy5Gp4rMfqNIAlERPSyIxo8oPQIL1XQKLYyyrkEEO99uwM+4cQGwhtbpQ=="], + + "@oxc-resolver/binding-linux-riscv64-gnu": ["@oxc-resolver/binding-linux-riscv64-gnu@11.7.1", "", { "os": "linux", "cpu": "none" }, "sha512-+vCO7iOR1s6VGefV02R2a702IASNWhSNm/MrR8RcWjKChmU0G+d1iC0oToUrGC4ovAEfstx2/O8EkROnfcLgrA=="], + + "@oxc-resolver/binding-linux-riscv64-musl": ["@oxc-resolver/binding-linux-riscv64-musl@11.7.1", "", { "os": "linux", "cpu": "none" }, "sha512-3folNmS5gYNFy/9HYzLcdeThqAGvDJU0gQKrhHn7RPWQa58yZ0ZPpBMk6KRSSO61+wkchkL+0sdcLsoe5wZW8g=="], + + "@oxc-resolver/binding-linux-s390x-gnu": ["@oxc-resolver/binding-linux-s390x-gnu@11.7.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-Ceo4z6g8vqPUKADROFL0b7MoyXlUdOBYCxTDu/fhd/5I3Ydk2S6bxkjJdzpBdlu+h2Z+eS9lTHFvkwkaORMPzw=="], + + "@oxc-resolver/binding-linux-x64-gnu": ["@oxc-resolver/binding-linux-x64-gnu@11.7.1", "", { "os": "linux", "cpu": "x64" }, "sha512-QyFW5e43imQLxiBpCImhOiP4hY9coWGjroEm8elDqGNNaA7vXooaMQS2N3avMQawSaKhsb/3RemxaZ852XG38Q=="], + + "@oxc-resolver/binding-linux-x64-musl": ["@oxc-resolver/binding-linux-x64-musl@11.7.1", "", { "os": "linux", "cpu": "x64" }, "sha512-JhuCqCqktqQyQVc37V+eDiP3buCIuyCLpb92tUEyAP8nY3dy2b/ojMrH1ZNnJUlfY/67AqoZPL6nQGAB2WA3Sg=="], + + "@oxc-resolver/binding-wasm32-wasi": ["@oxc-resolver/binding-wasm32-wasi@11.7.1", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.0.3" }, "cpu": "none" }, "sha512-sMXm5Z2rfBwkCUespZBJCPhCVbgh/fpYQ23BQs0PmnvWoXrGQHWvnvg1p/GYmleN+nwe8strBjfutirZFiC5lA=="], + + "@oxc-resolver/binding-win32-arm64-msvc": ["@oxc-resolver/binding-win32-arm64-msvc@11.7.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-C/Sam1RJi/h/F618IB/H3pCOhTf+2ArdTqrqQolN8ARV35iWTSezgy6qPjQGj7aWn/9M5vgtCInfS2SwnkBJ4w=="], + + "@oxc-resolver/binding-win32-ia32-msvc": ["@oxc-resolver/binding-win32-ia32-msvc@11.7.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-iNRgJxOkfmxeq9DiF9S4jtw3vq5kkAm6dsP4RPxoAO/WsShPPHOSlTpOqyB8bSj5Bt9DBLRoI43XcNfDKgM+jA=="], + + "@oxc-resolver/binding-win32-x64-msvc": ["@oxc-resolver/binding-win32-x64-msvc@11.7.1", "", { "os": "win32", "cpu": "x64" }, "sha512-MXS81efp8pu2MkjEPu+nDhgoyHwdWUygXYSzIh3gV2A8/qF0PVEzH+EpmKR7Pl8dEZIaG1YXA+CO6bmNZT8oSw=="], + + "@sinclair/typebox": ["@sinclair/typebox@0.34.41", "", {}, "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g=="], + + "@tybys/wasm-util": ["@tybys/wasm-util@0.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ=="], + + "@types/bun": ["@types/bun@1.2.21", "", { "dependencies": { "bun-types": "1.2.21" } }, "sha512-NiDnvEqmbfQ6dmZ3EeUO577s4P5bf4HCTXtI6trMc6f6RzirY5IrF3aIookuSpyslFzrnvv2lmEWv5HyC1X79A=="], + + "@types/esquery": ["@types/esquery@1.5.4", "", { "dependencies": { "@types/estree": "*" } }, "sha512-yYO4Q8H+KJHKW1rEeSzHxcZi90durqYgWVfnh5K6ZADVBjBv2e1NEveYX5yT2bffgN7RqzH3k9930m+i2yBoMA=="], + + "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], + + "@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="], + + "@types/lodash": ["@types/lodash@4.17.20", "", {}, "sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA=="], + + "@types/lodash-es": ["@types/lodash-es@4.17.12", "", { "dependencies": { "@types/lodash": "*" } }, "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ=="], + + "@types/moo": ["@types/moo@0.5.10", "", {}, "sha512-W6KzyZjXUYpwQfLK1O1UDzqcqYlul+lO7Bt71luyIIyNlOZwJaNeWWdqFs1C/f2hohZvUFHMk6oFNe9Rg48DbA=="], + + "@types/nearley": ["@types/nearley@2.11.5", "", {}, "sha512-dM7TrN0bVxGGXTYGx4YhGear8ysLO5SOuouAWM9oltjQ3m9oYa13qi8Z1DJp5zxVMPukvQdsrnZmgzpeuTSEQA=="], + + "@types/node": ["@types/node@24.3.1", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g=="], + + "@types/react": ["@types/react@19.1.12", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w=="], + + "@types/set-cookie-parser": ["@types/set-cookie-parser@2.4.10", "", { "dependencies": { "@types/node": "*" } }, "sha512-GGmQVGpQWUe5qglJozEjZV/5dyxbOOZ0LHe/lqyWssB88Y4svNfst0uqBVscdDeIKl5Jy5+aPSvy7mI9tYRguw=="], + + "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], + + "ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="], + + "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + + "array-union": ["array-union@2.1.0", "", {}, "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw=="], + + "better-path-resolve": ["better-path-resolve@1.0.0", "", { "dependencies": { "is-windows": "^1.0.0" } }, "sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g=="], + + "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], + + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + + "bun-types": ["bun-types@1.2.21", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-sa2Tj77Ijc/NTLS0/Odjq/qngmEPZfbfnOERi0KRUYhT9R8M4VBioWVmMWE5GrYbKMc+5lVybXygLdibHaqVqw=="], + + "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "chardet": ["chardet@2.1.0", "", {}, "sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA=="], + + "ci-info": ["ci-info@3.9.0", "", {}, "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ=="], + + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + + "commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], + + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + + "css-select": ["css-select@6.0.0", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^7.0.0", "domhandler": "^5.0.3", "domutils": "^3.2.2", "nth-check": "^2.1.1" } }, "sha512-rZZVSLle8v0+EY8QAkDWrKhpgt6SA5OtHsgBnsj6ZaLb5dmDVOWUDtQitd9ydxxvEjhewNudS6eTVU7uOyzvXw=="], + + "css-what": ["css-what@7.0.0", "", {}, "sha512-wD5oz5xibMOPHzy13CyGmogB3phdvcDaB5t0W/Nr5Z2O/agcB8YwOz6e2Lsp10pNDzBoDO9nVa3RGs/2BttpHQ=="], + + "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + + "dataloader": ["dataloader@1.4.0", "", {}, "sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw=="], + + "dedent": ["dedent@1.7.0", "", { "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, "optionalPeers": ["babel-plugin-macros"] }, "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ=="], + + "detect-indent": ["detect-indent@6.1.0", "", {}, "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA=="], + + "dir-glob": ["dir-glob@3.0.1", "", { "dependencies": { "path-type": "^4.0.0" } }, "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA=="], + + "discontinuous-range": ["discontinuous-range@1.0.0", "", {}, "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ=="], + + "dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="], + + "domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="], + + "domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="], + + "domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="], + + "dotenv": ["dotenv@8.6.0", "", {}, "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g=="], + + "enquirer": ["enquirer@2.4.1", "", { "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" } }, "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ=="], + + "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + + "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="], + + "esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="], + + "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + + "estree-toolkit": ["estree-toolkit@1.7.13", "", { "dependencies": { "@types/estree": ">=1.0.7", "@types/estree-jsx": ">=1.0.5" } }, "sha512-/fLCEcVBUgAtMkGXZHplPVyUv7wiSfsCGubBdM16n1iYCidPfyk1Kk1U0wAxLZADuA3z8k87DfVYXlBmHJeekg=="], + + "extendable-error": ["extendable-error@0.1.7", "", {}, "sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg=="], + + "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], + + "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], + + "fd-package-json": ["fd-package-json@2.0.0", "", { "dependencies": { "walk-up-path": "^4.0.0" } }, "sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ=="], + + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + + "find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="], + + "formatly": ["formatly@0.3.0", "", { "dependencies": { "fd-package-json": "^2.0.0" }, "bin": { "formatly": "bin/index.mjs" } }, "sha512-9XNj/o4wrRFyhSMJOvsuyMwy8aUfBaZ1VrqHVfohyXf0Sw0e+yfKG+xZaY3arGCOMdwFsqObtzVOc1gU9KiT9w=="], + + "fs-extra": ["fs-extra@7.0.1", "", { "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw=="], + + "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "globals": ["globals@16.3.0", "", {}, "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ=="], + + "globby": ["globby@11.1.0", "", { "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" } }, "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g=="], + + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + + "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + + "human-id": ["human-id@4.1.1", "", { "bin": { "human-id": "dist/cli.js" } }, "sha512-3gKm/gCSUipeLsRYZbbdA1BD83lBoWUkZ7G9VFrhWPAU76KwYo5KR8V28bpoPm/ygy0x5/GCbpRQdY7VLYCoIg=="], + + "iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], + + "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + + "is-subdir": ["is-subdir@1.2.0", "", { "dependencies": { "better-path-resolve": "1.0.0" } }, "sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw=="], + + "is-windows": ["is-windows@1.0.2", "", {}, "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="], + + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "jest-diff": ["jest-diff@30.1.2", "", { "dependencies": { "@jest/diff-sequences": "30.0.1", "@jest/get-type": "30.1.0", "chalk": "^4.1.2", "pretty-format": "30.0.5" } }, "sha512-4+prq+9J61mOVXCa4Qp8ZjavdxzrWQXrI80GNxP8f4tkI2syPuPrJgdRPZRrfUTRvIoUwcmNLbqEJy9W800+NQ=="], + + "jiti": ["jiti@2.5.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w=="], + + "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], + + "jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], + + "knip": ["knip@5.63.1", "", { "dependencies": { "@nodelib/fs.walk": "^1.2.3", "fast-glob": "^3.3.3", "formatly": "^0.3.0", "jiti": "^2.5.1", "js-yaml": "^4.1.0", "minimist": "^1.2.8", "oxc-resolver": "^11.6.2", "picocolors": "^1.1.1", "picomatch": "^4.0.1", "smol-toml": "^1.4.1", "strip-json-comments": "5.0.2", "zod": "^3.25.0", "zod-validation-error": "^3.0.3" }, "peerDependencies": { "@types/node": ">=18", "typescript": ">=5.0.4" }, "bin": { "knip": "bin/knip.js", "knip-bun": "bin/knip-bun.js" } }, "sha512-wSznedUAzcU4o9e0O2WPqDnP7Jttu8cesq/R23eregRY8QYQ9NLJ3aGt9fadJfRzPBoU4tRyutwVQu6chhGDlA=="], + + "locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], + + "lodash-es": ["lodash-es@4.17.21", "", {}, "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="], + + "lodash.startcase": ["lodash.startcase@4.4.0", "", {}, "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg=="], + + "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], + + "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + + "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], + + "moo": ["moo@0.5.2", "", {}, "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q=="], + + "mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="], + + "napi-postinstall": ["napi-postinstall@0.3.3", "", { "bin": { "napi-postinstall": "lib/cli.js" } }, "sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow=="], + + "nearley": ["nearley@2.20.1", "", { "dependencies": { "commander": "^2.19.0", "moo": "^0.5.0", "railroad-diagrams": "^1.0.0", "randexp": "0.4.6" }, "bin": { "nearleyc": "bin/nearleyc.js", "nearley-test": "bin/nearley-test.js", "nearley-unparse": "bin/nearley-unparse.js", "nearley-railroad": "bin/nearley-railroad.js" } }, "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ=="], + + "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], + + "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], + + "outdent": ["outdent@0.5.0", "", {}, "sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q=="], + + "oxc-resolver": ["oxc-resolver@11.7.1", "", { "dependencies": { "napi-postinstall": "^0.3.0" }, "optionalDependencies": { "@oxc-resolver/binding-android-arm-eabi": "11.7.1", "@oxc-resolver/binding-android-arm64": "11.7.1", "@oxc-resolver/binding-darwin-arm64": "11.7.1", "@oxc-resolver/binding-darwin-x64": "11.7.1", "@oxc-resolver/binding-freebsd-x64": "11.7.1", "@oxc-resolver/binding-linux-arm-gnueabihf": "11.7.1", "@oxc-resolver/binding-linux-arm-musleabihf": "11.7.1", "@oxc-resolver/binding-linux-arm64-gnu": "11.7.1", "@oxc-resolver/binding-linux-arm64-musl": "11.7.1", "@oxc-resolver/binding-linux-ppc64-gnu": "11.7.1", "@oxc-resolver/binding-linux-riscv64-gnu": "11.7.1", "@oxc-resolver/binding-linux-riscv64-musl": "11.7.1", "@oxc-resolver/binding-linux-s390x-gnu": "11.7.1", "@oxc-resolver/binding-linux-x64-gnu": "11.7.1", "@oxc-resolver/binding-linux-x64-musl": "11.7.1", "@oxc-resolver/binding-wasm32-wasi": "11.7.1", "@oxc-resolver/binding-win32-arm64-msvc": "11.7.1", "@oxc-resolver/binding-win32-ia32-msvc": "11.7.1", "@oxc-resolver/binding-win32-x64-msvc": "11.7.1" } }, "sha512-PzbEnD6NKTCFVKkUZtmQcX69ajdfM33RqI5kyb8mH9EdIqEUS00cWSXN0lsgYrtdTMzwo0EKKoH7hnGg6EDraQ=="], + + "p-filter": ["p-filter@2.1.0", "", { "dependencies": { "p-map": "^2.0.0" } }, "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw=="], + + "p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], + + "p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], + + "p-map": ["p-map@2.1.0", "", {}, "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw=="], + + "p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="], + + "package-manager-detector": ["package-manager-detector@0.2.11", "", { "dependencies": { "quansync": "^0.2.7" } }, "sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ=="], + + "parse5": ["parse5@8.0.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA=="], + + "parse5-htmlparser2-tree-adapter": ["parse5-htmlparser2-tree-adapter@8.0.0", "", { "dependencies": { "domhandler": "^5.0.3", "parse5": "^8.0.0" } }, "sha512-h4bXApvAdtcuv3MPcLQUCSQ2bJg9pG3cS5LwlXDJqweH06+0DjXVu1zwpjlbyu9tNsHiNnm4TM0nvTsGxQi5pw=="], + + "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], + + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + + "path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + + "pify": ["pify@4.0.1", "", {}, "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="], + + "prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="], + + "pretty-format": ["pretty-format@30.0.5", "", { "dependencies": { "@jest/schemas": "30.0.5", "ansi-styles": "^5.2.0", "react-is": "^18.3.1" } }, "sha512-D1tKtYvByrBkFLe2wHJl2bwMJIiT8rW+XA+TiataH79/FszLQMrpGEvzUVkzPau7OCO0Qnrhpe87PqtOAIB8Yw=="], + + "quansync": ["quansync@0.2.11", "", {}, "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA=="], + + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], + + "railroad-diagrams": ["railroad-diagrams@1.0.0", "", {}, "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A=="], + + "randexp": ["randexp@0.4.6", "", { "dependencies": { "discontinuous-range": "1.0.0", "ret": "~0.1.10" } }, "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ=="], + + "react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="], + + "read-yaml-file": ["read-yaml-file@1.1.0", "", { "dependencies": { "graceful-fs": "^4.1.5", "js-yaml": "^3.6.1", "pify": "^4.0.1", "strip-bom": "^3.0.0" } }, "sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA=="], + + "resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="], + + "ret": ["ret@0.1.15", "", {}, "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg=="], + + "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], + + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], + + "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], + + "semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], + + "set-cookie-parser": ["set-cookie-parser@2.7.1", "", {}, "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ=="], + + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], + + "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + + "sherif": ["sherif@1.6.1", "", { "optionalDependencies": { "sherif-darwin-arm64": "1.6.1", "sherif-darwin-x64": "1.6.1", "sherif-linux-arm64": "1.6.1", "sherif-linux-x64": "1.6.1", "sherif-windows-arm64": "1.6.1", "sherif-windows-x64": "1.6.1" }, "bin": { "sherif": "index.js" } }, "sha512-ZnwyTnmXoUOPClkOA37JWIyFxCoozMGHmhk/p7XbTREI554XXCnBAn3BMX8UsqkhSzQ9eNQsq4U+jnImEIppsQ=="], + + "sherif-darwin-arm64": ["sherif-darwin-arm64@1.6.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-J15oBJcrnCAZ0rQE8WbMShYw3204A18akCH6C/uZrILTwX/vZyJIqi7lAt5L00LzsadA3HcyQqVjLNNCvuihoQ=="], + + "sherif-darwin-x64": ["sherif-darwin-x64@1.6.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-oLA/GtvUasi+qCl35LczOhQ4g/xY2mxE5/eiTYQGT3Ow7FKLscnkE6v5l28bgkFeR/uke0AgZ/CgHhozAf0ulg=="], + + "sherif-linux-arm64": ["sherif-linux-arm64@1.6.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-OoltlucT7v9BZdkYZRbs1QU0DYMCQ5qgpMqQdMW1Rq3w3amr7+oEiV9NHntD83udOo8xRxKq0uPXfNYu+VptJw=="], + + "sherif-linux-x64": ["sherif-linux-x64@1.6.1", "", { "os": "linux", "cpu": "x64" }, "sha512-qyDyYqpi3ABGkRuCnjnxN3OMT8DxMiiLzhS9p9xC05Y9nr5hjkxvqP4DdJ4e5opm4E7vzRAS7VQoZ6m7h6tsgQ=="], + + "sherif-windows-arm64": ["sherif-windows-arm64@1.6.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-wAbCiqP//lo7bZUlHmZUV3/sGjnJxo6QB5/fqhz5/GUeWh4CTyvlSacJKZxLnXnzpiUSeFnWutquWnHkRov5Ug=="], + + "sherif-windows-x64": ["sherif-windows-x64@1.6.1", "", { "os": "win32", "cpu": "x64" }, "sha512-2r0qMxZGCMO2aq8Hlq7npxtAsUFVDsEFtUM/6dFo1npa/jHe2mbU7ii/Ymy0bloSa/qw/azrSfRV6GLU7Gjtxg=="], + + "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + + "slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="], + + "smol-toml": ["smol-toml@1.4.2", "", {}, "sha512-rInDH6lCNiEyn3+hH8KVGFdbjc099j47+OSgbMrfDYX1CmXLfdKd7qi6IfcWj2wFxvSVkuI46M+wPGYfEOEj6g=="], + + "spawndamnit": ["spawndamnit@3.0.1", "", { "dependencies": { "cross-spawn": "^7.0.5", "signal-exit": "^4.0.1" } }, "sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg=="], + + "sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="], + + "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="], + + "strip-json-comments": ["strip-json-comments@5.0.2", "", {}, "sha512-4X2FR3UwhNUE9G49aIsJW5hRRR3GXGTBTZRMfv568O60ojM8HcWjV/VxAxCDW3SUND33O6ZY66ZuRcdkj73q2g=="], + + "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + + "term-size": ["term-size@2.2.1", "", {}, "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg=="], + + "test": ["test@workspace:test"], + + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + + "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="], + + "undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="], + + "universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], + + "walk-up-path": ["walk-up-path@4.0.0", "", {}, "sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A=="], + + "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], + + "whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="], + + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], + + "zod-validation-error": ["zod-validation-error@3.5.3", "", { "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-OT5Y8lbUadqVZCsnyFaTQ4/O2mys4tj7PqhdbBCp7McPwvIEKfPtdA6QfPeFQK2/Rz5LgwmAXRJTugBNBi0btw=="], + + "@changesets/apply-release-plan/prettier": ["prettier@2.8.8", "", { "bin": { "prettier": "bin-prettier.js" } }, "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q=="], + + "@changesets/parse/js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="], + + "@changesets/write/prettier": ["prettier@2.8.8", "", { "bin": { "prettier": "bin-prettier.js" } }, "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q=="], + + "@manypkg/find-root/@types/node": ["@types/node@12.20.55", "", {}, "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ=="], + + "@manypkg/find-root/fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="], + + "@manypkg/get-packages/@changesets/types": ["@changesets/types@4.1.0", "", {}, "sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw=="], + + "@manypkg/get-packages/fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="], + + "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], + + "pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="], + + "read-yaml-file/js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="], + + "@changesets/parse/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], + + "read-yaml-file/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], + } +} diff --git a/bun.lockb b/bun.lockb deleted file mode 100755 index 756f218..0000000 Binary files a/bun.lockb and /dev/null differ diff --git a/package.json b/package.json index c32c2c1..f7cb58f 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "get", "license": "Apache-2.0", "private": true, - "packageManager": "bun@1.2.20", + "packageManager": "bun@1.2.21", "scripts": { "fmt": "biome check --write", "lint": "bun lint:check && bun lint:types && bun lint:unused && bun lint:repo", @@ -18,11 +18,11 @@ "test" ], "devDependencies": { - "@biomejs/biome": "^2.2.0", + "@biomejs/biome": "^2.2.3", "@changesets/changelog-github": "^0.5.1", "@changesets/cli": "^2.29.6", - "@types/bun": "^1.2.20", - "knip": "^5.62.0", + "@types/bun": "^1.2.21", + "knip": "^5.63.1", "sherif": "^1.6.1", "typescript": "^5.9.2" } diff --git a/packages/get/package.json b/packages/get/package.json index 86a5251..4f2b229 100644 --- a/packages/get/package.json +++ b/packages/get/package.json @@ -20,8 +20,9 @@ "@getlang/ast": "workspace:^0.0.1", "@getlang/lib": "workspace:^0.1.5", "@getlang/parser": "workspace:^0.3.4", - "@getlang/utils": "workspace:^0.1.6", "@getlang/walker": "workspace:^0.0.1", + "acorn": "^8.15.0", + "estree-toolkit": "^1.7.13", "lodash-es": "^4.17.21" }, "devDependencies": { diff --git a/packages/get/src/calls.ts b/packages/get/src/calls.ts new file mode 100644 index 0000000..b440885 --- /dev/null +++ b/packages/get/src/calls.ts @@ -0,0 +1,98 @@ +import type { TypeInfo } from '@getlang/ast' +import { Type } from '@getlang/ast' +import type { Hooks, Inputs } from '@getlang/lib' +import { cookies, html, invariant, js, json } from '@getlang/lib' +import { ImportError, ValueReferenceError } from '@getlang/lib/errors' +import { partition } from 'lodash-es' +import type { Entry, Registry } from './registry.js' +import type { RuntimeValue } from './value.js' +import { materialize } from './value.js' + +export async function callModifier( + registry: Registry, + mod: string, + args: Record, + context?: RuntimeValue, +) { + const entry = await registry.importMod(mod) + if (entry) { + return entry.mod(context?.data, args) + } + + invariant(context, 'Modifier requires context') + + if (mod === 'link') { + invariant(typeof args.base === 'string', '@link requires base url') + const data = html.findLink(context.data) + const link = materialize({ data, typeInfo: context.typeInfo }) + return new URL(link, args.base).toString() + } + + const doc = materialize(context) + + switch (mod) { + case 'html': + return html.parse(doc) + case 'js': + return js.parse(doc) + case 'json': + return json.parse(doc) + case 'cookies': + return cookies.parse(doc) + default: + throw new ValueReferenceError(`Unsupported modifier: ${mod}`) + } +} + +export type Execute = (entry: Entry, inputs: Inputs) => Promise + +export async function callModule( + registry: Registry, + execute: Execute, + hooks: Required, + module: string, + args: RuntimeValue, + contextType?: TypeInfo, +) { + let entry: Entry + try { + entry = await registry.import(module, [], contextType) + } catch (e) { + const err = `Failed to import module: ${module}` + throw new ImportError(err, { cause: e }) + } + const [inputArgs, attrArgs] = partition(Object.entries(args.data), e => + entry.inputs.has(e[0]), + ) + const inputs = Object.fromEntries(inputArgs) + let extracted = await hooks.call(module, inputs) + if (typeof extracted === 'undefined') { + extracted = await execute(entry, inputs) + } + await hooks.extract(module, inputs, extracted.data) + + function dropWarning(reason: string) { + if (attrArgs.length) { + const dropped = attrArgs.map(e => e[0]).join(', ') + const err = [ + `Module '${module}' ${reason}`, + `dropping view attributes: ${dropped}`, + ].join(', ') + console.warn(err) + } + } + + if (entry.returnType.type !== Type.Value) { + dropWarning('returned unmaterialized value') + return extracted + } + + if (typeof extracted !== 'object') { + dropWarning('returned a primitive') + return extracted + } + + const data = Object.fromEntries(attrArgs) + const raster = materialize({ data, typeInfo: args.typeInfo }) + return { ...raster, ...extracted } +} diff --git a/packages/get/src/execute.ts b/packages/get/src/execute.ts index 53901bc..3f2a420 100644 --- a/packages/get/src/execute.ts +++ b/packages/get/src/execute.ts @@ -1,14 +1,13 @@ import type { Expr, TypeInfo } from '@getlang/ast' import { isToken, Type } from '@getlang/ast' -import { cookies, headers, html, http, js, json } from '@getlang/lib' -import type { Hooks, Inputs } from '@getlang/utils' -import { invariant, NullSelection } from '@getlang/utils' -import * as errors from '@getlang/utils/errors' -import type { Path, ReduceVisitor } from '@getlang/walker' +import type { Hooks, Inputs } from '@getlang/lib' +import * as lib from '@getlang/lib' +import * as errors from '@getlang/lib/errors' +import type { ReduceVisitor } from '@getlang/walker' import { reduce, ScopeTracker } from '@getlang/walker' -import { callModifier } from './modifiers.js' -import type { Execute } from './modules.js' -import { Modules } from './modules.js' +import type { Execute } from './calls.js' +import { callModifier, callModule } from './calls.js' +import { Registry } from './registry.js' import type { RuntimeValue } from './value.js' import { assert, materialize } from './value.js' @@ -18,51 +17,46 @@ const { SliceError, UnknownInputsError, ValueTypeError, + ValueReferenceError, } = errors -class ExecutionTracker extends ScopeTracker { - override exit(value: RuntimeValue, path: Path) { - if ('typeInfo' in path.node) { - assert(value) - } - super.exit(value, path) - } -} - export async function execute( rootModule: string, rootInputs: Inputs, hooks: Required, ) { - const scope = new ExecutionTracker() + const scope = new ScopeTracker() const executeModule: Execute = async (entry, inputs) => { const provided = new Set(Object.keys(inputs)) const unknown = provided.difference(entry.inputs) - invariant(unknown.size === 0, new UnknownInputsError([...unknown])) + lib.invariant(unknown.size === 0, new UnknownInputsError([...unknown])) - async function withItemContext(expr: Expr): Promise { + async function withItemContext(expr: Expr): Promise { const ctx = scope.context if (ctx?.typeInfo.type !== Type.List) { - return reduce(expr, options) + const { data } = await reduce(expr, options) + return data } const list = [] for (const data of ctx.data) { scope.push({ data, typeInfo: ctx.typeInfo.of }) - const value = await withItemContext(expr) - list.push(value.data) + const item = await withItemContext(expr) + list.push(item) scope.pop() } - return { data: list, typeInfo: expr.typeInfo } + return list + } + + function lookup(id: string, typeInfo: TypeInfo) { + const value = scope.lookup(id) + lib.invariant(value, new ValueReferenceError(id)) + return { data: value.data, typeInfo } } let ex: RuntimeValue | undefined const visitor: ReduceVisitor = { - /** - * Statement nodes - */ - InputExpr(node) { const name = node.id.value let data = inputs[name] @@ -72,12 +66,16 @@ export async function execute( } else if (node.defaultValue) { data = node.defaultValue.data } else { - data = new NullSelection(`input:${name}`) + data = new lib.NullSelection(`input:${name}`) } } return { data, typeInfo: node.typeInfo } }, + AssignmentStmt(node) { + assert(node.value) + }, + LiteralExpr(node) { return { data: node.value, typeInfo: node.typeInfo } }, @@ -91,12 +89,9 @@ export async function execute( }, }, - /** - * Expression nodes - */ TemplateExpr(node, path) { const firstNull = node.elements.find( - el => 'data' in el && el.data instanceof NullSelection, + el => 'data' in el && el.data instanceof lib.NullSelection, ) if (firstNull) { const isRoot = path.parent?.node.kind !== 'TemplateExpr' @@ -114,7 +109,8 @@ export async function execute( const ctx = scope.context const deps = ctx && materialize(ctx) const ret = await hooks.slice(slice.value, deps) - const data = ret === undefined ? new NullSelection('') : ret + const data = + ret === undefined ? new lib.NullSelection('') : ret return { data, typeInfo } } catch (e) { throw new SliceError({ cause: e }) @@ -122,19 +118,18 @@ export async function execute( }, IdentifierExpr(node) { - return scope.lookup(node.id.value) + return lookup(node.id.value, node.typeInfo) }, DrillIdentifierExpr(node) { - const { data } = scope.lookup(node.id.value) - return { data, typeInfo: node.typeInfo } + return lookup(node.id.value, node.typeInfo) }, SelectorExpr(node) { - invariant(scope.context, 'Unresolved context') + lib.invariant(scope.context, 'Unresolved context') const selector = node.selector.data - invariant( + lib.invariant( typeof selector === 'string', new ValueTypeError('Expected selector string'), ) @@ -146,15 +141,15 @@ export async function execute( case Type.Maybe: return select(typeInfo.option) case Type.Html: - return html.select(...args) + return lib.html.select(...args) case Type.Js: - return js.select(...args) + return lib.js.select(...args) case Type.Headers: - return headers.select(...args) + return lib.headers.select(...args) case Type.Cookies: - return cookies.select(...args) + return lib.cookies.select(...args) default: - return json.select(...args) + return lib.json.select(...args) } } @@ -163,18 +158,21 @@ export async function execute( }, async ModifierExpr(node) { - const mod = node.modifier.value - const args = node.args.data - const entry = await modules.importMod(mod) - const data = entry - ? entry.mod(scope.context?.data, args) - : callModifier(mod, args, scope.context) + const data = await callModifier( + registry, + node.modifier.value, + node.args.data, + scope.context, + ) return { data, typeInfo: node.typeInfo } }, ModuleExpr(node) { if (node.call) { - return modules.call( + return callModule( + registry, + executeModule, + hooks, node.module.value, node.args, scope.context?.typeInfo, @@ -187,6 +185,7 @@ export async function execute( }, ObjectEntryExpr(node) { + assert(node.value) const data = [node.key.data, node.value.data] return { data, typeInfo: { type: Type.Value } } }, @@ -195,24 +194,23 @@ export async function execute( const data = Object.fromEntries( node.entries .map(e => e.data) - .filter(e => !(e[1] instanceof NullSelection)), + .filter(e => !(e[1] instanceof lib.NullSelection)), ) return { data, typeInfo: node.typeInfo } }, SubqueryExpr() { const ex = scope.extracted - invariant(ex, new QuerySyntaxError('Subquery must extract a value')) + lib.invariant(ex, new QuerySyntaxError('Subquery must extract a value')) return ex }, DrillExpr: { async enter(node, path) { for (const expr of node.body) { - scope.context = await withItemContext(expr) - const optional = expr.typeInfo.type === Type.Maybe - if (optional && scope.context.data instanceof NullSelection) { - break + if (!(scope.context?.data instanceof lib.NullSelection)) { + const data = await withItemContext(expr) + scope.context = { data, typeInfo: expr.typeInfo } } } path.replace(scope.context) @@ -227,7 +225,7 @@ export async function execute( const headers = node.headers.data[1] const blocks = Object.fromEntries(node.blocks.map(v => v.data)) - const data = await http.request( + const data = await lib.http.request( method, url, headers, @@ -242,7 +240,7 @@ export async function execute( const value = Object.fromEntries( node.entries .map(e => e.data) - .filter(e => !(e[1] instanceof NullSelection)), + .filter(e => !(e[1] instanceof lib.NullSelection)), ) const data = [node.name.value, value] return { data, typeInfo: node.typeInfo } @@ -259,8 +257,8 @@ export async function execute( return ex } - const modules = new Modules(hooks, executeModule) - const rootEntry = await modules.import(rootModule) + const registry = new Registry(hooks) + const rootEntry = await registry.import(rootModule) const ex = await executeModule(rootEntry, rootInputs) - return ex && materialize(ex) + return ex && assert(ex) && materialize(ex) } diff --git a/packages/get/src/hooks.spec.ts b/packages/get/src/hooks.spec.ts index 153e379..36c41f4 100644 --- a/packages/get/src/hooks.spec.ts +++ b/packages/get/src/hooks.spec.ts @@ -6,8 +6,8 @@ import type { ImportHook, RequestHook, SliceHook, -} from '@getlang/utils' -import { invariant } from '@getlang/utils' +} from '@getlang/lib' +import { invariant } from '@getlang/lib' import { execute } from './index.js' describe('hook', () => { diff --git a/packages/get/src/index.ts b/packages/get/src/index.ts index f11d056..24fc2ad 100644 --- a/packages/get/src/index.ts +++ b/packages/get/src/index.ts @@ -1,24 +1,7 @@ -import { http, slice } from '@getlang/lib' -import type { Hooks, Inputs } from '@getlang/utils' -import { invariant } from '@getlang/utils' -import { ImportError } from '@getlang/utils/errors' +import type { Hooks, Inputs } from '@getlang/lib' +import { buildHooks } from '@getlang/lib' import { execute as exec } from './execute.js' -function buildHooks(hooks: Hooks): Required { - return { - import: (module: string) => { - const err = 'Imports are not supported by the current runtime' - invariant(hooks.import, new ImportError(err)) - return hooks.import(module) - }, - modifier: modifier => hooks.modifier?.(modifier), - call: hooks.call ?? (() => {}), - request: hooks.request ?? http.requestHook, - slice: hooks.slice ?? slice.runSlice, - extract: hooks.extract ?? (() => {}), - } -} - export function execute( source: string, inputs: Inputs = {}, diff --git a/packages/get/src/modifiers.ts b/packages/get/src/modifiers.ts deleted file mode 100644 index edf3a09..0000000 --- a/packages/get/src/modifiers.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { cookies, html, js, json } from '@getlang/lib' -import { invariant } from '@getlang/utils' -import { ValueReferenceError } from '@getlang/utils/errors' -import type { RuntimeValue } from './value.js' -import { materialize } from './value.js' - -export function callModifier( - mod: string, - args: Record, - context?: RuntimeValue, -) { - let ctx = context - if (context && mod === 'link') { - let { data, typeInfo } = context - const tag = data.type === 'tag' ? data.name : undefined - if (tag === 'a') { - data = html.select(data, 'xpath:@href', false) - } else if (tag === 'img') { - data = html.select(data, 'xpath:@src', false) - } - ctx = { data, typeInfo } - } - - const doc = ctx && materialize(ctx) - - switch (mod) { - case 'link': - invariant(typeof args.base === 'string', '@link requires base url') - return new URL(doc, args.base).toString() - case 'html': - return html.parse(doc) - case 'js': - return js.parse(doc) - case 'json': - return json.parse(doc) - case 'cookies': - return cookies.parse(doc) - default: - throw new ValueReferenceError(`Unsupported modifier: ${mod}`) - } -} diff --git a/packages/get/src/modules.ts b/packages/get/src/modules.ts deleted file mode 100644 index 04c7372..0000000 --- a/packages/get/src/modules.ts +++ /dev/null @@ -1,185 +0,0 @@ -import type { Program, TypeInfo } from '@getlang/ast' -import { Type } from '@getlang/ast' -import { analyze, desugar, inference, parse } from '@getlang/parser' -import type { Hooks, Inputs, Modifier } from '@getlang/utils' -import { - ImportError, - RecursiveCallError, - ValueTypeError, -} from '@getlang/utils/errors' -import { partition } from 'lodash-es' -import type { RuntimeValue } from './value.js' -import { materialize } from './value.js' - -type Info = { - ast: Program - imports: Set - isMacro: boolean -} - -type Entry = { - program: Program - inputs: Set - returnType: TypeInfo -} - -type ModEntry = { - mod: Modifier - returnType: TypeInfo -} - -export type Execute = (entry: Entry, inputs: Inputs) => Promise - -function repr(ti: TypeInfo): string { - switch (ti.type) { - case Type.Maybe: - return `maybe<${repr(ti.option)}>` - case Type.List: - return `${repr(ti.of)}[]` - case Type.Struct: { - const fields = Object.entries(ti.schema) - .map(e => `${e[0]}: ${repr(e[1])};`) - .join(' ') - return `{ ${fields} }` - } - case Type.Context: - case Type.Never: - throw new ValueTypeError('Unsupported key type') - default: - return ti.type - } -} - -function buildImportKey(module: string, typeInfo?: TypeInfo) { - let key = module - if (typeInfo) { - key += `<${repr(typeInfo)}>` - } - return key -} - -export class Modules { - private info: Record> = {} - private entries: Record> = {} - private modifiers: Record> = {} - - constructor( - private hooks: Required, - private execute: Execute, - ) {} - - async load(module: string): Promise { - const source = await this.hooks.import(module) - const ast = parse(source) - const info = analyze(ast) - return { ast, ...info } - } - - async getInfo(module: string) { - this.info[module] ??= this.load(module) - return this.info[module] - } - - async compile( - module: string, - stack: string[], - contextType?: TypeInfo, - ): Promise { - const { ast, imports } = await this.getInfo(module) - const macros: string[] = [] - for (const i of imports) { - const depInfo = await this.getInfo(i) - if (depInfo.isMacro) { - macros.push(i) - } - } - const simplified = desugar(ast, macros) - const { inputs, calls, modifiers } = analyze(simplified) - - const returnTypes: Record = {} - for (const call of calls) { - const { returnType } = await this.import(call, stack) - returnTypes[call] = returnType - } - for (const mod of modifiers) { - const entry = await this.importMod(mod) - if (entry) { - returnTypes[mod] = entry.returnType - } - } - - const { program, returnType } = inference(simplified, { - returnTypes, - contextType, - }) - - return { program, inputs, returnType } - } - - import(module: string, prev: string[] = [], contextType?: TypeInfo) { - const stack = [...prev, module] - if (prev.includes(module)) { - throw new RecursiveCallError(stack) - } - const key = buildImportKey(module, contextType) - this.entries[key] ??= this.compile(module, stack, contextType) - return this.entries[key] - } - - async compileMod(mod: string): Promise { - const compiled = await this.hooks.modifier(mod) - if (!compiled) { - return null - } - return { mod: compiled.modifier, returnType: { type: Type.Value } } - } - - importMod(mod: string) { - this.modifiers[mod] ??= this.compileMod(mod) - return this.modifiers[mod] - } - - async call(module: string, args: RuntimeValue, contextType?: TypeInfo) { - let entry: Entry - try { - entry = await this.import(module, [], contextType) - } catch (e) { - const err = `Failed to import module: ${module}` - throw new ImportError(err, { cause: e }) - } - const [inputArgs, attrArgs] = partition(Object.entries(args.data), e => - entry.inputs.has(e[0]), - ) - const inputs = Object.fromEntries(inputArgs) - let extracted = await this.hooks.call(module, inputs) - if (typeof extracted === 'undefined') { - extracted = await this.execute(entry, inputs) - } - await this.hooks.extract(module, inputs, extracted.data) - - function dropWarning(reason: string) { - if (attrArgs.length) { - const dropped = attrArgs.map(e => e[0]).join(', ') - const err = [ - `Module '${module}' ${reason}`, - `dropping view attributes: ${dropped}`, - ].join(', ') - console.warn(err) - } - } - - if (entry.returnType.type !== Type.Value) { - dropWarning(`returned ${repr(entry.returnType)}`) - return extracted - } - - if (typeof extracted !== 'object') { - dropWarning('returned a primitive') - return extracted - } - - const data = Object.fromEntries(attrArgs) - const raster = materialize({ data, typeInfo: args.typeInfo }) - return { ...raster, ...extracted } - } -} diff --git a/packages/get/src/registry.ts b/packages/get/src/registry.ts new file mode 100644 index 0000000..dae0cdc --- /dev/null +++ b/packages/get/src/registry.ts @@ -0,0 +1,158 @@ +import type { Program, TypeInfo } from '@getlang/ast' +import { Type } from '@getlang/ast' +import type { Hooks, Modifier } from '@getlang/lib' +import { RecursiveCallError, ValueTypeError } from '@getlang/lib/errors' +import { analyze, desugar, inference, parse } from '@getlang/parser' +import type { Pattern } from 'acorn' +import { parse as acorn } from 'acorn' +import { traverse } from 'estree-toolkit' + +type ModEntry = { + mod: Modifier + useContext: boolean + returnType: TypeInfo +} + +type Info = { + ast: Program + imports: Set + isMacro: boolean +} + +export type Entry = { + program: Program + inputs: Set + returnType: TypeInfo +} + +function repr(ti: TypeInfo): string { + switch (ti.type) { + case Type.Maybe: + return `maybe<${repr(ti.option)}>` + case Type.List: + return `${repr(ti.of)}[]` + case Type.Struct: { + const fields = Object.entries(ti.schema) + .map(e => `${e[0]}: ${repr(e[1])};`) + .join(' ') + return `{ ${fields} }` + } + case Type.Context: + case Type.Never: + throw new ValueTypeError('Unsupported key type') + default: + return ti.type + } +} + +function buildImportKey(module: string, typeInfo?: TypeInfo) { + let key = module + if (typeInfo) { + key += `<${repr(typeInfo)}>` + } + return key +} + +function inferContext(mod: Modifier) { + const src = mod.toString() + const ast = acorn(src, { ecmaVersion: 'latest' }) + let useContext = false + traverse(ast, { + $: { scope: true }, + Program(path) { + const fn = ast.body[0] + let ctxParam: Pattern | undefined + if (fn?.type === 'FunctionDeclaration') { + ctxParam = fn.params[0] + } else if (fn?.type === 'ExpressionStatement') { + if (fn.expression.type === 'ArrowFunctionExpression') { + ctxParam = fn.expression.params[0] + } + } + const fnScope = path.scope?.children[0] + const bindings = Object.values(fnScope?.bindings || {}) + const ctxBinding = bindings.find(b => b?.identifierPath.node === ctxParam) + useContext = Boolean(ctxBinding?.references.length) + }, + }) + return useContext +} + +export class Registry { + private info: Record> = {} + private entries: Record> = {} + private modifiers: Record> = {} + + constructor(private hooks: Required) {} + + importMod(mod: string) { + this.modifiers[mod] ??= Promise.resolve().then(async () => { + const compiled = await this.hooks.modifier(mod) + if (!compiled) { + return null + } + const fn = compiled.modifier + const useContext = inferContext(fn) + const returnType = compiled.typeInfo || { type: Type.Value } + return { mod: fn, useContext, returnType } + }) + return this.modifiers[mod] + } + + private getInfo(module: string) { + this.info[module] ??= Promise.resolve().then(async () => { + const source = await this.hooks.import(module) + const ast = parse(source) + const { imports, ...info } = analyze(ast) + let isMacro = info.hasUnboundSelector + for (const [mod, unbound] of info.modifiers) { + if (unbound && !isMacro) { + const entry = await this.importMod(mod) + isMacro = entry?.useContext || false + } + } + return { ast, imports, isMacro } + }) + return this.info[module] + } + + import(module: string, prev: string[] = [], contextType?: TypeInfo) { + const stack = [...prev, module] + if (prev.includes(module)) { + throw new RecursiveCallError(stack) + } + const key = buildImportKey(module, contextType) + this.entries[key] ??= Promise.resolve().then(async () => { + const { ast, imports } = await this.getInfo(module) + const macros: string[] = [] + for (const i of imports) { + const depInfo = await this.getInfo(i) + if (depInfo.isMacro) { + macros.push(i) + } + } + const simplified = desugar(ast, macros) + const { inputs, calls, modifiers } = analyze(simplified) + + const returnTypes: Record = {} + for (const call of calls) { + const { returnType } = await this.import(call, stack) + returnTypes[call] = returnType + } + for (const mod of modifiers.keys()) { + const entry = await this.importMod(mod) + if (entry) { + returnTypes[mod] = entry.returnType + } + } + + const { program, returnType } = inference(simplified, { + returnTypes, + contextType, + }) + + return { program, inputs, returnType } + }) + return this.entries[key] + } +} diff --git a/packages/get/src/value.ts b/packages/get/src/value.ts index 4556b05..656bf49 100644 --- a/packages/get/src/value.ts +++ b/packages/get/src/value.ts @@ -1,9 +1,11 @@ import type { TypeInfo } from '@getlang/ast' import { Type } from '@getlang/ast' -import { cookies, headers, html, js } from '@getlang/lib' -import { NullSelection } from '@getlang/utils' -import { NullSelectionError, ValueTypeError } from '@getlang/utils/errors' +import { cookies, headers, html, js, NullSelection } from '@getlang/lib' import { mapValues } from 'lodash-es' +import { + NullSelectionError, + ValueTypeError, +} from '../../lib/src/core/errors.js' export type RuntimeValue = { data: any diff --git a/packages/lib/package.json b/packages/lib/package.json index 17b6981..ae53dc4 100644 --- a/packages/lib/package.json +++ b/packages/lib/package.json @@ -4,8 +4,14 @@ "license": "Apache-2.0", "type": "module", "exports": { - "bun": "./src/index.ts", - "default": "./dist/index.js" + ".": { + "bun": "./src/index.ts", + "default": "./dist/index.js" + }, + "./errors": { + "bun": "./src/core/errors.ts", + "default": "./dist/core/errors.js" + } }, "bugs": { "url": "https://github.com/getlang-dev/get/issues" @@ -17,7 +23,7 @@ }, "homepage": "https://getlang.dev", "dependencies": { - "@getlang/utils": "workspace:^0.1.5", + "@getlang/ast": "workspace:^0.0.1", "@getlang/xpath": "0.0.35-0", "@types/esquery": "^1.5.4", "@types/lodash-es": "^4.17.12", diff --git a/packages/utils/src/errors.ts b/packages/lib/src/core/errors.ts similarity index 87% rename from packages/utils/src/errors.ts rename to packages/lib/src/core/errors.ts index 6ca609e..88a86e8 100644 --- a/packages/utils/src/errors.ts +++ b/packages/lib/src/core/errors.ts @@ -73,9 +73,9 @@ export class NullInputError extends RuntimeError { } export class UnknownInputsError extends RuntimeError { - public override name = 'UnknownInputError' + public override name = 'UnknownInputsError' - constructor(inputNames: string[], options?: ErrorOptions) { + constructor(inputNames: string[] = [], options?: ErrorOptions) { const noun = inputNames.length > 1 ? 'inputs' : 'input' super(`Unknown ${noun} provided: ${inputNames.join(', ')}`, options) } @@ -99,3 +99,16 @@ export class RecursiveCallError extends RuntimeError { super(`Recursive call error: ${chain.join(' -> ')}`, options) } } + +export function invariant( + condition: unknown, + err: string | RuntimeError, +): asserts condition { + if (!condition) { + throw typeof err === 'string' ? new FatalError({ cause: err }) : err + } +} + +export class NullSelection { + constructor(public selector: string) {} +} diff --git a/packages/lib/src/core/hooks.ts b/packages/lib/src/core/hooks.ts new file mode 100644 index 0000000..ae37d96 --- /dev/null +++ b/packages/lib/src/core/hooks.ts @@ -0,0 +1,70 @@ +import type { TypeInfo } from '@getlang/ast' +import type { Inputs, MaybePromise } from '../index.js' +import { requestHook } from '../net/http.js' +import { runSlice } from '../slice.js' +import { ImportError, invariant } from './errors.js' + +export type ImportHook = (module: string) => MaybePromise + +export type CallHook = (module: string, inputs: Inputs) => MaybePromise + +export type RequestHook = ( + url: string, + opts: RequestInit, +) => MaybePromise + +export type SliceHook = ( + slice: string, + context?: unknown, +) => MaybePromise + +export type ExtractHook = ( + module: string, + inputs: Inputs, + value: any, +) => MaybePromise + +export type Modifier = (context: any, options: Record) => any +export type ModifierHook = (modifier: string) => MaybePromise< + | { + modifier: Modifier + typeInfo?: TypeInfo + } + | undefined +> + +export type Hooks = Partial<{ + import: ImportHook + request: RequestHook + slice: SliceHook + call: CallHook + extract: ExtractHook + modifier: ModifierHook +}> + +type RequestInit = { + method?: string + headers?: Headers + body?: string +} + +export type Response = { + status: number + headers: Headers + body?: string +} + +export function buildHooks(hooks: Hooks): Required { + return { + import: (module: string) => { + const err = 'Imports are not supported by the current runtime' + invariant(hooks.import, new ImportError(err)) + return hooks.import(module) + }, + modifier: modifier => hooks.modifier?.(modifier), + call: hooks.call ?? (() => {}), + request: hooks.request ?? requestHook, + slice: hooks.slice ?? runSlice, + extract: hooks.extract ?? (() => {}), + } +} diff --git a/packages/lib/src/index.ts b/packages/lib/src/index.ts index 4ef2db5..5d81bd4 100644 --- a/packages/lib/src/index.ts +++ b/packages/lib/src/index.ts @@ -1,14 +1,12 @@ +export { invariant, NullSelection } from './core/errors.js' +export * from './core/hooks.js' export * as http from './net/http.js' +export * as slice from './slice.js' export * as cookies from './values/cookies.js' export * as headers from './values/headers.js' export * as html from './values/html.js' export * as js from './values/js.js' export * as json from './values/json.js' -const AsyncFunction: any = (async () => {}).constructor - -function runSlice(slice: string, context: unknown = {}) { - return new AsyncFunction('$', slice)(context) -} - -export const slice = { runSlice } +export type Inputs = Record +export type MaybePromise = T | Promise diff --git a/packages/lib/src/net/http.ts b/packages/lib/src/net/http.ts index 21c0020..67a1443 100644 --- a/packages/lib/src/net/http.ts +++ b/packages/lib/src/net/http.ts @@ -1,5 +1,5 @@ -import type { RequestHook } from '@getlang/utils' -import { RequestError } from '@getlang/utils/errors' +import { RequestError } from '../core/errors.js' +import type { RequestHook } from '../core/hooks.js' type StringMap = Record diff --git a/packages/lib/src/slice.ts b/packages/lib/src/slice.ts new file mode 100644 index 0000000..911217c --- /dev/null +++ b/packages/lib/src/slice.ts @@ -0,0 +1,5 @@ +const AsyncFunction: any = (async () => {}).constructor + +export function runSlice(slice: string, context: unknown = {}) { + return new AsyncFunction('$', slice)(context) +} diff --git a/packages/lib/src/values/cookies.ts b/packages/lib/src/values/cookies.ts index 92cd4bf..d89795d 100644 --- a/packages/lib/src/values/cookies.ts +++ b/packages/lib/src/values/cookies.ts @@ -1,7 +1,6 @@ -import { invariant, NullSelection } from '@getlang/utils' -import { QuerySyntaxError } from '@getlang/utils/errors' import { mapValues } from 'lodash-es' import * as scp from 'set-cookie-parser' +import { invariant, NullSelection, QuerySyntaxError } from '../core/errors.js' export const parse = (source: string) => { const cookie = scp.splitCookiesString(source) diff --git a/packages/lib/src/values/headers.ts b/packages/lib/src/values/headers.ts index 24a4d63..7d1bb30 100644 --- a/packages/lib/src/values/headers.ts +++ b/packages/lib/src/values/headers.ts @@ -1,4 +1,4 @@ -import { NullSelection } from '@getlang/utils' +import { NullSelection } from '../core/errors.js' export const select = (headers: Headers, selector: string, expand: boolean) => { if (expand && selector === 'set-cookie') { diff --git a/packages/lib/src/values/html.ts b/packages/lib/src/values/html.ts index 487aa21..b223c4d 100644 --- a/packages/lib/src/values/html.ts +++ b/packages/lib/src/values/html.ts @@ -1,7 +1,5 @@ /// -import { invariant, NullSelection } from '@getlang/utils' -import { NullSelectionError, SelectorSyntaxError } from '@getlang/utils/errors' import xpath from '@getlang/xpath' import { selectAll, selectOne } from 'css-select' import { parse as parseCss } from 'css-what' @@ -9,6 +7,12 @@ import type { AnyHtmlNode } from 'domhandler' import { textContent } from 'domutils' import { parse as parse5 } from 'parse5' import { adapter } from 'parse5-htmlparser2-tree-adapter' +import { + invariant, + NullSelection, + NullSelectionError, + SelectorSyntaxError, +} from '../core/errors.js' import './html/patch-dom.js' export { Element } from 'domhandler' @@ -68,3 +72,15 @@ export const toValue = (el: AnyHtmlNode) => { } return str.trim() } + +export const findLink = (el: AnyHtmlNode) => { + const tag = el.type === 'tag' && el.name + switch (tag) { + case 'a': + return selectXpath(el, '@href', false) + case 'img': + return selectXpath(el, '@src', false) + default: + return el + } +} diff --git a/packages/lib/src/values/js.ts b/packages/lib/src/values/js.ts index bb76c9b..7a69fc1 100644 --- a/packages/lib/src/values/js.ts +++ b/packages/lib/src/values/js.ts @@ -1,12 +1,13 @@ -import { invariant, NullSelection } from '@getlang/utils' +import type { AnyNode } from 'acorn' +import { parse as acorn } from 'acorn' +import esquery from 'esquery' import { ConversionError, + invariant, + NullSelection, SelectorSyntaxError, SliceSyntaxError, -} from '@getlang/utils/errors' -import type { AnyNode } from 'acorn' -import { parse as acorn } from 'acorn' -import esquery from 'esquery' +} from '../core/errors.js' export const parse = (js: string): AnyNode => { try { diff --git a/packages/lib/src/values/json.ts b/packages/lib/src/values/json.ts index 39ac010..72481f6 100644 --- a/packages/lib/src/values/json.ts +++ b/packages/lib/src/values/json.ts @@ -1,5 +1,5 @@ -import { NullSelection } from '@getlang/utils' -import { get } from 'lodash-es' +import { get, toPath } from 'lodash-es' +import { NullSelection } from '../core/errors.js' export const parse = (json: string) => JSON.parse(json) @@ -7,5 +7,7 @@ export const parse = (json: string) => JSON.parse(json) // if result itself is null, the key is present. This is a // valid scenario that should not raise a NullSelectionError export const select = (value: any, selector: string, expand: boolean) => { - return get(value, selector, expand ? [] : new NullSelection(selector)) + const path = toPath(selector) + const fallback = expand ? [] : new NullSelection(selector) + return get(value, path, fallback) } diff --git a/packages/parser/package.json b/packages/parser/package.json index 49b91db..14bca1b 100644 --- a/packages/parser/package.json +++ b/packages/parser/package.json @@ -24,7 +24,7 @@ }, "dependencies": { "@getlang/ast": "workspace:^0.0.1", - "@getlang/utils": "workspace:^0.1.6", + "@getlang/lib": "workspace:^0.1.5", "@getlang/walker": "workspace:^0.0.1", "@types/moo": "^0.5.10", "@types/nearley": "^2.11.5", diff --git a/packages/parser/src/grammar/lex/slice.ts b/packages/parser/src/grammar/lex/slice.ts index 47d8780..88e2d01 100644 --- a/packages/parser/src/grammar/lex/slice.ts +++ b/packages/parser/src/grammar/lex/slice.ts @@ -1,5 +1,5 @@ -import { invariant } from '@getlang/utils' -import { QuerySyntaxError } from '@getlang/utils/errors' +import { invariant } from '@getlang/lib' +import { QuerySyntaxError } from '@getlang/lib/errors' import { until } from './templates.js' const getSliceValue = (text: string) => { diff --git a/packages/parser/src/grammar/parse.ts b/packages/parser/src/grammar/parse.ts index 81e1241..475da48 100644 --- a/packages/parser/src/grammar/parse.ts +++ b/packages/parser/src/grammar/parse.ts @@ -1,7 +1,7 @@ import type { Expr } from '@getlang/ast' import { isToken, t } from '@getlang/ast' -import { invariant } from '@getlang/utils' -import { QuerySyntaxError } from '@getlang/utils/errors' +import { invariant } from '@getlang/lib' +import { QuerySyntaxError } from '@getlang/lib/errors' import { tx } from '../utils.js' type PP = nearley.Postprocessor @@ -113,7 +113,7 @@ export const objectEntry: PP = ([callkey, identifier, optional, , , value]) => { export const objectEntryShorthandSelect: PP = ([identifier, optional]) => { const value = t.templateExpr([identifier]) - const selector = t.selectorExpr(value, false) + const selector = t.drillExpr([t.selectorExpr(value, false)]) return objectEntry([null, identifier, optional, null, null, selector]) } diff --git a/packages/parser/src/parse.ts b/packages/parser/src/parse.ts index 9998649..e8b7abf 100644 --- a/packages/parser/src/parse.ts +++ b/packages/parser/src/parse.ts @@ -1,6 +1,6 @@ import type { Program } from '@getlang/ast' -import { invariant } from '@getlang/utils' -import { QuerySyntaxError } from '@getlang/utils/errors' +import { invariant } from '@getlang/lib' +import { QuerySyntaxError } from '@getlang/lib/errors' import nearley from 'nearley' import lexer from './grammar/lexer.js' import grammar from './grammar.js' diff --git a/packages/parser/src/passes/analyze.ts b/packages/parser/src/passes/analyze.ts index 3ed9d6e..0e2bd1a 100644 --- a/packages/parser/src/passes/analyze.ts +++ b/packages/parser/src/passes/analyze.ts @@ -5,9 +5,9 @@ export function analyze(ast: Program) { const scope = new ScopeTracker() const inputs = new Set() const calls = new Set() - const modifiers = new Set() + const modifiers = new Map() const imports = new Set() - let isMacro = false + let hasUnboundSelector = false transform(ast, { scope, @@ -19,13 +19,20 @@ export function analyze(ast: Program) { node.call && calls.add(node.module.value) }, SelectorExpr() { - isMacro ||= !scope.context + hasUnboundSelector ||= !scope.context }, ModifierExpr(node) { - isMacro ||= !scope.context - modifiers.add(node.modifier.value) + const mod = node.modifier.value + const unbound = modifiers.get(mod) || !scope.context + modifiers.set(mod, unbound) }, }) - return { inputs, imports, calls, modifiers, isMacro } + return { + inputs, + imports, + calls, + modifiers, + hasUnboundSelector, + } } diff --git a/packages/parser/src/passes/desugar/context.ts b/packages/parser/src/passes/desugar/context.ts index 529282a..b45bbab 100644 --- a/packages/parser/src/passes/desugar/context.ts +++ b/packages/parser/src/passes/desugar/context.ts @@ -1,5 +1,5 @@ -import { invariant } from '@getlang/utils' -import { QuerySyntaxError } from '@getlang/utils/errors' +import { invariant } from '@getlang/lib' +import { QuerySyntaxError } from '@getlang/lib/errors' import { ScopeTracker, transform } from '@getlang/walker' import type { DesugarPass } from '../desugar.js' diff --git a/packages/parser/src/passes/desugar/links.ts b/packages/parser/src/passes/desugar/links.ts index 1bd5da9..b273864 100644 --- a/packages/parser/src/passes/desugar/links.ts +++ b/packages/parser/src/passes/desugar/links.ts @@ -1,6 +1,6 @@ import { t } from '@getlang/ast' -import { invariant } from '@getlang/utils' -import { QuerySyntaxError } from '@getlang/utils/errors' +import { invariant } from '@getlang/lib' +import { QuerySyntaxError } from '@getlang/lib/errors' import { transform } from '@getlang/walker' import { render, tx } from '../../utils.js' import type { DesugarPass } from '../desugar.js' diff --git a/packages/parser/src/passes/desugar/reqparse.ts b/packages/parser/src/passes/desugar/reqparse.ts index 88ffff3..3a6c793 100644 --- a/packages/parser/src/passes/desugar/reqparse.ts +++ b/packages/parser/src/passes/desugar/reqparse.ts @@ -1,7 +1,7 @@ import type { RequestExpr, Stmt } from '@getlang/ast' import { t } from '@getlang/ast' -import { invariant } from '@getlang/utils' -import { QuerySyntaxError } from '@getlang/utils/errors' +import { invariant } from '@getlang/lib' +import { QuerySyntaxError } from '@getlang/lib/errors' import { getContentField, tx } from '../../utils.js' type Parsers = Record diff --git a/packages/parser/src/passes/desugar/slicedeps.ts b/packages/parser/src/passes/desugar/slicedeps.ts index f3beb10..a9307f7 100644 --- a/packages/parser/src/passes/desugar/slicedeps.ts +++ b/packages/parser/src/passes/desugar/slicedeps.ts @@ -1,7 +1,7 @@ import type { Expr } from '@getlang/ast' import { t } from '@getlang/ast' -import { invariant } from '@getlang/utils' -import { SliceSyntaxError } from '@getlang/utils/errors' +import { invariant } from '@getlang/lib' +import { SliceSyntaxError } from '@getlang/lib/errors' import { ScopeTracker, transform } from '@getlang/walker' import { parse as acorn } from 'acorn' import { traverse } from 'estree-toolkit' diff --git a/packages/parser/src/passes/inference/typeinfo.ts b/packages/parser/src/passes/inference/typeinfo.ts index 4676980..9d5baf0 100644 --- a/packages/parser/src/passes/inference/typeinfo.ts +++ b/packages/parser/src/passes/inference/typeinfo.ts @@ -1,7 +1,7 @@ import type { Expr, Node, Program, TypeInfo } from '@getlang/ast' import { Type, t } from '@getlang/ast' -import { invariant } from '@getlang/utils' -import { QuerySyntaxError } from '@getlang/utils/errors' +import { invariant } from '@getlang/lib' +import { QuerySyntaxError, ValueReferenceError } from '@getlang/lib/errors' import type { Path, TransformVisitor } from '@getlang/walker' import { ScopeTracker, transform } from '@getlang/walker' import { toPath } from 'lodash-es' @@ -128,13 +128,17 @@ export function resolveTypes(ast: Program, options: ResolveTypeOptions) { }, IdentifierExpr(node) { - const value = scope.lookup(node.id.value) + const id = node.id.value + const value = scope.lookup(id) + invariant(value, new ValueReferenceError(id)) const typeInfo = structuredClone(value.typeInfo) return { ...node, typeInfo } }, DrillIdentifierExpr(node) { - const value = scope.lookup(node.id.value) + const id = node.id.value + const value = scope.lookup(id) + invariant(value, new ValueReferenceError(id)) let typeInfo = structuredClone(value.typeInfo) if (node.expand) { typeInfo = { type: Type.List, of: typeInfo } diff --git a/packages/parser/src/passes/lineage.ts b/packages/parser/src/passes/lineage.ts index 72497c2..9f5cc0e 100644 --- a/packages/parser/src/passes/lineage.ts +++ b/packages/parser/src/passes/lineage.ts @@ -1,4 +1,6 @@ import type { Expr, Node } from '@getlang/ast' +import { invariant } from '@getlang/lib' +import { ValueReferenceError } from '@getlang/lib/errors' import type { Path } from '@getlang/walker' import { ScopeTracker } from '@getlang/walker' @@ -22,9 +24,13 @@ export class LineageTracker extends ScopeTracker { switch (node.kind) { case 'IdentifierExpr': - case 'DrillIdentifierExpr': - derive(this.lookup(node.id.value)) + case 'DrillIdentifierExpr': { + const id = node.id.value + const value = this.lookup(id) + invariant(value, new ValueReferenceError(id)) + derive(value) break + } case 'DrillExpr': derive(node.body.at(-1)!) diff --git a/packages/utils/CHANGELOG.md b/packages/utils/CHANGELOG.md deleted file mode 100644 index 9bc4921..0000000 --- a/packages/utils/CHANGELOG.md +++ /dev/null @@ -1,43 +0,0 @@ -# @getlang/utils - -## 0.1.6 - -### Patch Changes - -- [#31](https://github.com/getlang-dev/get/pull/31) [`1a395f9`](https://github.com/getlang-dev/get/commit/1a395f9df71d3507bc5b3841eddc9336db3a69ee) Thanks [@mattfysh](https://github.com/mattfysh)! - request parsers - -## 0.1.5 - -### Patch Changes - -- [`aca9d92`](https://github.com/getlang-dev/get/commit/aca9d929e4877fc614b66740c9415f5bcd083c24) Thanks [@mattfysh](https://github.com/mattfysh)! - fix publish - -## 0.1.4 - -### Patch Changes - -- [`3660548`](https://github.com/getlang-dev/get/commit/3660548d79dd24e13a74bf0d6f24c1fec512062d) Thanks [@mattfysh](https://github.com/mattfysh)! - prevent tsconfig publish - -## 0.1.3 - -### Patch Changes - -- [#28](https://github.com/getlang-dev/get/pull/28) [`f1bdc2c`](https://github.com/getlang-dev/get/commit/f1bdc2c8433a942f84503606790e8bcf4fb37477) Thanks [@mattfysh](https://github.com/mattfysh)! - page links - -## 0.1.2 - -### Patch Changes - -- [#23](https://github.com/getlang-dev/get/pull/23) [`28d0ca8`](https://github.com/getlang-dev/get/commit/28d0ca8dcf840cfc70f002d06a48cace834edcf9) Thanks [@mattfysh](https://github.com/mattfysh)! - workspace layout updates - -## 0.1.1 - -### Patch Changes - -- [#14](https://github.com/getlang-dev/get/pull/14) [`58e9988`](https://github.com/getlang-dev/get/commit/58e99887e39956ee1e3eaf669cb92fbfa188a022) Thanks [@mattfysh](https://github.com/mattfysh)! - add contextual identifier to slices reference converted or raw context - -## 0.1.0 - -### Minor Changes - -- [`57ff46d`](https://github.com/getlang-dev/get/commit/57ff46d904484e3277ee7a8481cdf4cee4c3deb2) Thanks [@mattfysh](https://github.com/mattfysh)! - Release v0.1.0 diff --git a/packages/utils/package.json b/packages/utils/package.json deleted file mode 100644 index 5731fea..0000000 --- a/packages/utils/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@getlang/utils", - "version": "0.1.6", - "license": "Apache-2.0", - "type": "module", - "exports": { - ".": { - "bun": "./src/index.ts", - "default": "./dist/index.js" - }, - "./errors": { - "bun": "./src/errors.ts", - "default": "./dist/errors.js" - } - }, - "bugs": { - "url": "https://github.com/getlang-dev/get/issues" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/getlang-dev/get.git", - "directory": "packages/utils" - }, - "homepage": "https://getlang.dev" -} diff --git a/packages/utils/src/hooks.ts b/packages/utils/src/hooks.ts deleted file mode 100644 index 1a089f9..0000000 --- a/packages/utils/src/hooks.ts +++ /dev/null @@ -1,48 +0,0 @@ -import type { Inputs } from './index.js' -import type { MaybePromise } from './wait.js' - -export type ImportHook = (module: string) => MaybePromise - -export type CallHook = (module: string, inputs: Inputs) => MaybePromise - -export type RequestHook = ( - url: string, - opts: RequestInit, -) => MaybePromise - -export type SliceHook = ( - slice: string, - context?: unknown, -) => MaybePromise - -export type ExtractHook = ( - module: string, - inputs: Inputs, - value: any, -) => MaybePromise - -export type Modifier = (context: any, options: Record) => any -export type ModifierHook = ( - modifier: string, -) => MaybePromise<{ modifier: Modifier } | undefined> - -export type Hooks = Partial<{ - import: ImportHook - request: RequestHook - slice: SliceHook - call: CallHook - extract: ExtractHook - modifier: ModifierHook -}> - -type RequestInit = { - method?: string - headers?: Headers - body?: string -} - -export type Response = { - status: number - headers: Headers - body?: string -} diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts deleted file mode 100644 index 2e308ac..0000000 --- a/packages/utils/src/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type { RuntimeError } from './errors.js' -import { FatalError } from './errors.js' - -export * from './hooks.js' -export * from './wait.js' - -export type Inputs = Record - -export class NullSelection { - constructor(public selector: string) {} -} - -export function invariant( - condition: unknown, - err: string | RuntimeError, -): asserts condition { - if (!condition) { - throw typeof err === 'string' ? new FatalError({ cause: err }) : err - } -} diff --git a/packages/utils/tsconfig.json b/packages/utils/tsconfig.json deleted file mode 100644 index dafae0f..0000000 --- a/packages/utils/tsconfig.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "include": ["src/index.ts", "src/errors.ts"] -} diff --git a/packages/walker/package.json b/packages/walker/package.json index d606acc..41f01bf 100644 --- a/packages/walker/package.json +++ b/packages/walker/package.json @@ -19,7 +19,6 @@ }, "homepage": "https://getlang.dev", "dependencies": { - "@getlang/ast": "workspace:^0.0.1", - "@getlang/utils": "workspace:^0.1.6" + "@getlang/ast": "workspace:^0.0.1" } } diff --git a/packages/walker/src/index.ts b/packages/walker/src/index.ts index 818de2c..049e019 100644 --- a/packages/walker/src/index.ts +++ b/packages/walker/src/index.ts @@ -1,5 +1,4 @@ import type { Node } from '@getlang/ast' -import { wait, waitMap } from '@getlang/utils' import { Path } from './path.js' import type { ScopeTracker } from './scope.js' import type { @@ -8,6 +7,7 @@ import type { ReduceVisitor, TransformVisitor, } from './visitor.js' +import { wait, waitMap } from './wait.js' export { ScopeTracker } from './scope.js' export type { TransformVisitor, ReduceVisitor, Path } @@ -50,8 +50,10 @@ function walk( const path = parent?.add(node) || new Path(node) return wait(enter(node, path), () => { - let xnode: any = path.replacement - if (!xnode) { + let xnode: any + if (path.replacement) { + xnode = path.replacement.value + } else { const entries = waitMap(Object.entries(node), e => { const [key, value] = e let val = value diff --git a/packages/walker/src/path.ts b/packages/walker/src/path.ts index 20384e9..5531e38 100644 --- a/packages/walker/src/path.ts +++ b/packages/walker/src/path.ts @@ -1,5 +1,4 @@ import type { Node } from '@getlang/ast' -import { invariant } from '@getlang/utils' type Staging = { before: Node[] @@ -10,7 +9,7 @@ type Mutation = Map export class Path { private staging: Staging = { before: [] } protected mutations: Mutation = new Map() - public replacement: unknown + public replacement?: { value: unknown } constructor( public node: N, @@ -25,8 +24,8 @@ export class Path { this.staging.before.push(node) } - replace(value: any) { - this.replacement = value + replace(value?: any) { + this.replacement = { value } } private mutate(node: Node) { @@ -53,7 +52,9 @@ export class Path { apply(node: Node) { const applied = this.mutate(node) if (this.staging.before.length) { - invariant(this.parent, 'Unable to apply path mutations') + if (!this.parent) { + throw new Error('Unable to apply path mutations') + } this.parent.mutations.set(applied, this.staging) } return applied diff --git a/packages/walker/src/scope.ts b/packages/walker/src/scope.ts index 960a1b1..3632d74 100644 --- a/packages/walker/src/scope.ts +++ b/packages/walker/src/scope.ts @@ -1,6 +1,4 @@ import type { Node } from '@getlang/ast' -import { invariant } from '@getlang/utils' -import { ValueReferenceError } from '@getlang/utils/errors' import type { Path } from './index.js' class Scope { @@ -13,13 +11,12 @@ class Scope { lookup(id: string) { const value = id ? this.vars[id] : this.context - invariant(value !== undefined, new ValueReferenceError(id)) - return value + return value ?? null } } export class ScopeTracker { - scopeStack: Scope[] = [] + private scopeStack: Scope[] = [] push(context: T | undefined = this.head?.context) { const vars = Object.create(this.head?.vars ?? null) @@ -35,7 +32,9 @@ export class ScopeTracker { } private get ensure() { - invariant(this.head, new ValueReferenceError('Invalid scope stack')) + if (!this.head) { + throw new Error('Invalid scope stack') + } return this.head } diff --git a/packages/utils/src/wait.ts b/packages/walker/src/wait.ts similarity index 93% rename from packages/utils/src/wait.ts rename to packages/walker/src/wait.ts index 70ccfdb..a6dd0c6 100644 --- a/packages/utils/src/wait.ts +++ b/packages/walker/src/wait.ts @@ -1,4 +1,4 @@ -export type MaybePromise = T | Promise +type MaybePromise = T | Promise export function wait( value: MaybePromise, diff --git a/test/calls.spec.ts b/test/calls.spec.ts index 2e20226..6a618bf 100644 --- a/test/calls.spec.ts +++ b/test/calls.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from 'bun:test' -import { RecursiveCallError } from '@getlang/utils/errors' +import { RecursiveCallError } from '@getlang/lib/errors' import { execute } from './helpers.js' describe('calls', () => { @@ -212,7 +212,10 @@ describe('calls', () => { Home: ` GET http://stub/x/y/z - extract #a -> >#b -> @Link) >#c -> >#d + extract #a + -> :scope > #b + -> @Link) :scope > #c + -> :scope > #d `, Link: ` extract { diff --git a/test/helpers.ts b/test/helpers.ts index f46e983..f3f0166 100644 --- a/test/helpers.ts +++ b/test/helpers.ts @@ -1,9 +1,9 @@ import { expect } from 'bun:test' import { executeModule } from '@getlang/get' +import type { Hooks, Inputs, MaybePromise, ModifierHook } from '@getlang/lib' +import { invariant } from '@getlang/lib' +import { ImportError } from '@getlang/lib/errors' import { desugar, parse, print } from '@getlang/parser' -import type { Hooks, Inputs, MaybePromise, ModifierHook } from '@getlang/utils' -import { invariant } from '@getlang/utils' -import { ImportError } from '@getlang/utils/errors' import dedent from 'dedent' import './expect.js' diff --git a/test/modifiers.spec.ts b/test/modifiers.spec.ts index dd96f31..59193de 100644 --- a/test/modifiers.spec.ts +++ b/test/modifiers.spec.ts @@ -1,10 +1,14 @@ import { describe, expect, test } from 'bun:test' -import type { Modifier } from '@getlang/utils' -import { invariant } from '@getlang/utils' -import { ValueTypeError } from '@getlang/utils/errors' +import type { Modifier } from '@getlang/lib' +import { invariant } from '@getlang/lib' +import { ValueTypeError } from '@getlang/lib/errors' import { execute as exec } from './helpers.js' -function execute(source: string, name: string, modifier: Modifier) { +function execute( + source: string | Record, + name: string, + modifier: Modifier, +) { return exec( source, {}, @@ -25,7 +29,7 @@ describe('modifiers', () => { test('with context', async () => { const result = await execute( - 'extract `1` -> @add_one', + 'extract 1 -> @add_one', 'add_one', (ctx: number) => { expect(ctx).toEqual(1) @@ -37,7 +41,7 @@ describe('modifiers', () => { test('with args', async () => { const result = await execute( - 'extract @product({ a: `7`, b: `6` })', + 'extract @product({ a: 7, b: 6 })', 'product', (_ctx, { a, b }) => { invariant( @@ -51,4 +55,34 @@ describe('modifiers', () => { ) expect(result).toEqual(42) }) + + test('in macros', async () => { + const result = await execute( + { + MyMacro: `extract @add_ten`, + Home: `extract 4 -> @MyMacro`, + }, + 'add_ten', + function mymod(ctx: number) { + expect(ctx).toEqual(4) + return ctx + 10 + }, + ) + expect(result).toEqual(14) + }) + + test('in macros, arrow function', async () => { + const result = await execute( + { + MyMacro: `extract @add_ten`, + Home: `extract 4 -> @MyMacro`, + }, + 'add_ten', + (ctx: number) => { + expect(ctx).toEqual(4) + return ctx + 10 + }, + ) + expect(result).toEqual(14) + }) }) diff --git a/test/modules.spec.ts b/test/modules.spec.ts index aa1fe0d..3276db8 100644 --- a/test/modules.spec.ts +++ b/test/modules.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from 'bun:test' -import { NullInputError, UnknownInputsError } from '@getlang/utils/errors' +import { NullInputError, UnknownInputsError } from '@getlang/lib/errors' import { execute } from './helpers.js' describe('modules', () => { diff --git a/test/package.json b/test/package.json index 72258fa..2c6bbb2 100644 --- a/test/package.json +++ b/test/package.json @@ -4,11 +4,11 @@ "type": "module", "dependencies": { "@getlang/get": "workspace:*", + "@getlang/lib": "workspace:^0.1.5", "@getlang/parser": "workspace:*", - "@getlang/utils": "workspace:*", - "dedent": "^1.6.0" + "dedent": "^1.7.0" }, "devDependencies": { - "jest-diff": "^30.0.5" + "jest-diff": "^30.1.2" } } diff --git a/test/request.spec.ts b/test/request.spec.ts index 67b5db7..e20fa96 100644 --- a/test/request.spec.ts +++ b/test/request.spec.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, mock, test } from 'bun:test' -import type { Inputs } from '@getlang/utils' +import type { Inputs } from '@getlang/lib' import type { Fetch } from './helpers.js' import { execute as _exec } from './helpers.js' @@ -171,6 +171,18 @@ describe('request', () => { ) }) + test('querystring merge', async () => { + await execute(` + GET http://example.com/?a=1 + [query] + a: 2 + b: 4 + `) + await expect(mockFetch).toHaveServed('http://example.com/?a=1&a=2&b=4', { + method: 'GET', + }) + }) + test('cookies, encoded', async () => { await execute(` GET https://example.com @@ -502,4 +514,13 @@ describe('request', () => { expect(result).toEqual('jZDE5MDBhNzczNDMzMTk4') }) }) + + test('selector object shorthand', async () => { + const result = await execute(` + GET http://get.com + + extract { h1 } + `) + expect(result).toEqual({ h1: 'test' }) + }) }) diff --git a/test/slice.spec.ts b/test/slice.spec.ts index 072a3e6..96aafe9 100644 --- a/test/slice.spec.ts +++ b/test/slice.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, it, test } from 'bun:test' -import { SliceError } from '@getlang/utils/errors' +import { SliceError } from '@getlang/lib/errors' import { execute } from './helpers.js' describe('slice', () => { diff --git a/test/values.spec.ts b/test/values.spec.ts index fab08a6..6425f74 100644 --- a/test/values.spec.ts +++ b/test/values.spec.ts @@ -3,7 +3,7 @@ import { ConversionError, NullSelectionError, SelectorSyntaxError, -} from '@getlang/utils/errors' +} from '@getlang/lib/errors' import { execute, SELSYN } from './helpers.js' describe('values', () => { @@ -487,7 +487,7 @@ describe('values', () => { const result = await execute(` set ctx = |return { '12': 'pass', - '12.34': 'pass', + '123': { '4': 'pass' }, 'true': 'pass', 'false': 'pass', }| @@ -496,7 +496,7 @@ describe('values', () => { str_s: -> 'one' str_d: -> "two" int: -> 12 - float: -> 12.34 + float: -> 123.4 bool_on: -> true bool_off: -> false }