diff --git a/.gitignore b/.gitignore index 05ea2c6..f1dd33e 100644 --- a/.gitignore +++ b/.gitignore @@ -415,4 +415,6 @@ $RECYCLE.BIN/ public/ !server/services/local/ !test/services/local/ -!app/src/lib/ \ No newline at end of file +!app/src/lib/ + +bin/ \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 7d94ba8..340ad0d 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,7 +8,8 @@ "name": "Python Debugger: FastAPI", "type": "debugpy", "request": "launch", - "module": "main" + "module": "main", + "justMyCode": false }, { "name": "Launch Frontend", diff --git a/app/package-lock.json b/app/package-lock.json index dce3e8a..6d4fe8e 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -13,11 +13,13 @@ "@blueprintjs/select": "5.3.6", "@blueprintjs/table": "5.3.0", "@monaco-editor/react": "^4.6.0", + "@rmlio/yarrrml-parser": "^1.7.2", "@xyflow/react": "^12.3.6", "axios": "1.7.9", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "lucide-react": "^0.468.0", + "n3": "^1.23.1", "react": "^18.3.1", "react-dom": "^18.3.1", "react-icons": "^5.4.0", @@ -28,6 +30,7 @@ }, "devDependencies": { "@eslint/js": "9.16.0", + "@types/n3": "^1.21.1", "@types/node": "^22.10.2", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", @@ -1016,6 +1019,288 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@graphy/content.nq.read": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@graphy/content.nq.read/-/content.nq.read-4.3.7.tgz", + "integrity": "sha512-Q1wDp7BK9JLHOgkUu3YW5+HoSo6YKDNQxvfJ8Rrsy4sNXFxuaodx5XjyYjChKoQ0svFw/CZht3A5ndECJPIANw==", + "license": "ISC", + "dependencies": { + "@graphy/core.data.factory": "^4.3.7", + "@graphy/core.iso.stream": "^4.3.7" + }, + "engines": { + "node": ">=8.4.0" + } + }, + "node_modules/@graphy/content.nq.scan": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@graphy/content.nq.scan/-/content.nq.scan-4.3.7.tgz", + "integrity": "sha512-EblT1kgnXM78frfnWROh2LAriD6qKwqLP4l2pfgfjsz7x+iQVzrLGJrQYvAD1XDGKXABzkJcyt6LJDgwFRX1ag==", + "license": "ISC", + "dependencies": { + "@graphy/core.data.factory": "^4.3.7" + }, + "engines": { + "node": ">=8.4.0" + } + }, + "node_modules/@graphy/content.nq.scribe": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@graphy/content.nq.scribe/-/content.nq.scribe-4.3.7.tgz", + "integrity": "sha512-22sL3R7P750/qKmZTf31kHJD+l7pjIuR1N0RS/zMhOiueXhkWhp6Yh7/nqVpb703CqKM+lMfFEtIn8iLGXZXQA==", + "license": "ISC", + "dependencies": { + "@graphy/core.class.writable": "^4.3.7", + "@graphy/core.data.factory": "^4.3.7" + }, + "engines": { + "node": ">=8.4.0" + } + }, + "node_modules/@graphy/content.nq.write": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@graphy/content.nq.write/-/content.nq.write-4.3.7.tgz", + "integrity": "sha512-JR20Q6aAYYzdi273ShZj2ZmbIj9s9nWwLGLfcB+FtKt6J3OhzoSwSjcSoUO+OmTGT+AuWAwpqzkMAQuRmgFCUw==", + "license": "ISC", + "dependencies": { + "@graphy/core.class.writable": "^4.3.7", + "@graphy/core.data.factory": "^4.3.7" + }, + "engines": { + "node": ">=8.4.0" + } + }, + "node_modules/@graphy/content.nt.read": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@graphy/content.nt.read/-/content.nt.read-4.3.7.tgz", + "integrity": "sha512-KnCjg1m4p3fKKilxICsnS6jy6usINbo5WpXfJiRaKd35BaSrvz6Bek+HBFiWIzJWC7HobXvbGGDFKZssEGN7hw==", + "license": "ISC", + "dependencies": { + "@graphy/core.data.factory": "^4.3.7", + "@graphy/core.iso.stream": "^4.3.7" + }, + "engines": { + "node": ">=8.4.0" + } + }, + "node_modules/@graphy/content.nt.scan": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@graphy/content.nt.scan/-/content.nt.scan-4.3.7.tgz", + "integrity": "sha512-0iCrECxHDefYq61IkvPuM9RH0QlDC6m4kJPWuf3y3jGJ7akMv96k4q9RxzlCyPrn4PleoauvwF1J1cUOmcLMlw==", + "license": "ISC", + "dependencies": { + "@graphy/core.data.factory": "^4.3.7" + }, + "engines": { + "node": ">=8.4.0" + } + }, + "node_modules/@graphy/content.nt.scribe": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@graphy/content.nt.scribe/-/content.nt.scribe-4.3.7.tgz", + "integrity": "sha512-6aGQSz4MuQz7riqBK6RNnFGAd1wGRcMaf7CfwCntO+pPNoVTybQXPAdhMRbzKxYlZygNz1fIHQKsTMjUp2aLCg==", + "license": "ISC", + "dependencies": { + "@graphy/core.class.writable": "^4.3.7", + "@graphy/core.data.factory": "^4.3.7" + }, + "engines": { + "node": ">=8.4.0" + } + }, + "node_modules/@graphy/content.nt.write": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@graphy/content.nt.write/-/content.nt.write-4.3.7.tgz", + "integrity": "sha512-aWwOGA6WV4okeKSutBKhMBqfIT5o+tdwZif4Z/eRCOxKKFQ0KHslatgnc6eRgeLJOojUnvjewluEn8ldK8YCAg==", + "license": "ISC", + "dependencies": { + "@graphy/core.class.writable": "^4.3.7", + "@graphy/core.data.factory": "^4.3.7" + }, + "engines": { + "node": ">=8.4.0" + } + }, + "node_modules/@graphy/content.trig.read": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@graphy/content.trig.read/-/content.trig.read-4.3.7.tgz", + "integrity": "sha512-8ff6DB/2zAULSnSr1vU0JpjZQ9SJFxEoYLUtz7P1WUCFbAAV6+RAXDjpJEVqhyCKAVdiozc1Zp7JUh4np3q3Ag==", + "license": "ISC", + "dependencies": { + "@graphy/core.data.factory": "^4.3.7", + "@graphy/core.iso.stream": "^4.3.7", + "uri-js": "^4.4.0" + }, + "engines": { + "node": ">=8.4.0" + } + }, + "node_modules/@graphy/content.trig.scribe": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@graphy/content.trig.scribe/-/content.trig.scribe-4.3.7.tgz", + "integrity": "sha512-4PNMeRxGIwW2RxHOtHzR8gxCqi2D5XKAbrtYQgixIsGc4y5flOWr8jI1Jvmqj3EbidBCrGzZ8apqASAfgOBCuA==", + "license": "ISC", + "dependencies": { + "@graphy/core.class.writable": "^4.3.7", + "@graphy/core.data.factory": "^4.3.7" + }, + "engines": { + "node": ">=8.4.0" + } + }, + "node_modules/@graphy/content.trig.write": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@graphy/content.trig.write/-/content.trig.write-4.3.7.tgz", + "integrity": "sha512-NrzWQ3QC/nZwbSnyaW6npVSw2bEQwfCBQfyfnwASGDbtRleSH60jEQcaka3INhfIf25uWZ/XK4TgLS2mCbdXlA==", + "license": "ISC", + "dependencies": { + "@graphy/core.class.writable": "^4.3.7", + "@graphy/core.data.factory": "^4.3.7", + "big-integer": "^1.6.48" + }, + "engines": { + "node": ">=8.4.0" + } + }, + "node_modules/@graphy/content.ttl.read": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@graphy/content.ttl.read/-/content.ttl.read-4.3.7.tgz", + "integrity": "sha512-HGK4k75D5rrC8chzQePLYdq2u8JvRko2m8gOykHq3PXfOYteI9Y26QQgt04rRXazsJCw2VRyx2JJq/prRRTJog==", + "license": "ISC", + "dependencies": { + "@graphy/core.data.factory": "^4.3.7", + "@graphy/core.iso.stream": "^4.3.7", + "uri-js": "^4.4.0" + }, + "engines": { + "node": ">=8.4.0" + } + }, + "node_modules/@graphy/content.ttl.scribe": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@graphy/content.ttl.scribe/-/content.ttl.scribe-4.3.7.tgz", + "integrity": "sha512-8rKF7G5RaeWxBD47NQfG2lKs99i+JJn59p+UrMUKhsZeDGTui07VnIfrYgPt6/6VnOm7fm1jX+KrsTgQ/KU3lQ==", + "license": "ISC", + "dependencies": { + "@graphy/core.class.writable": "^4.3.7", + "@graphy/core.data.factory": "^4.3.7" + }, + "engines": { + "node": ">=8.4.0" + } + }, + "node_modules/@graphy/content.ttl.write": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@graphy/content.ttl.write/-/content.ttl.write-4.3.7.tgz", + "integrity": "sha512-QpSa3lMmU+DA8udvikrPDji+XvUf5wfU4ShhqXU9mQEdccDTNw/eOOlhtLITAC3Q0dsobAdb71fXtj7zqtDwQA==", + "license": "ISC", + "dependencies": { + "@graphy/core.class.writable": "^4.3.7", + "@graphy/core.data.factory": "^4.3.7", + "big-integer": "^1.6.48" + }, + "engines": { + "node": ">=8.4.0" + } + }, + "node_modules/@graphy/content.xml.scribe": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@graphy/content.xml.scribe/-/content.xml.scribe-4.3.7.tgz", + "integrity": "sha512-V6Ezv7jN4HGQ8a2nQmheDh+AmQ4kq9Rn4fvDmdozbMeDv9zkEyg6tA0/KGnyeOAVpZFQLv8mYfvsWMxMXh7sCw==", + "license": "ISC", + "dependencies": { + "@graphy/core.class.writable": "^4.3.7", + "@graphy/core.data.factory": "^4.3.7" + }, + "engines": { + "node": ">=8.4.0" + } + }, + "node_modules/@graphy/core.class.scribable": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@graphy/core.class.scribable/-/core.class.scribable-4.3.7.tgz", + "integrity": "sha512-XOR4hQOKiy34/q8svdcOzgcao27tClebSzpNaOfvdxSOC/E7plOhaLfVtWxPjfIbMJs7OtVihlyXEtD22Xnm1w==", + "license": "ISC", + "dependencies": { + "@graphy/core.data.factory": "^4.3.7", + "@graphy/core.iso.stream": "^4.3.7" + }, + "engines": { + "node": ">=8.4.0" + } + }, + "node_modules/@graphy/core.class.writable": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@graphy/core.class.writable/-/core.class.writable-4.3.7.tgz", + "integrity": "sha512-vUvYP9Sine5j9epaOlmkZ0Mll2Vlh/N3zc7weRlSnxNm2HhT/LhzF8PSCZyPg17rwpTabrjKW/Rj0xwQUqeEGQ==", + "license": "ISC", + "dependencies": { + "@graphy/core.class.scribable": "^4.3.7", + "@graphy/core.data.factory": "^4.3.7" + }, + "engines": { + "node": ">=8.4.0" + } + }, + "node_modules/@graphy/core.data.factory": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@graphy/core.data.factory/-/core.data.factory-4.3.7.tgz", + "integrity": "sha512-6uiNrClDnlfN52B8f0ZBjnyETXiCyYOyIUET2aGFTG+TXZTsiO1WcinsIo36YPt29i+boCDf0ldYDKhPKAibdw==", + "license": "ISC", + "dependencies": { + "uri-js": "^4.4.0" + }, + "engines": { + "node": ">=8.4.0" + } + }, + "node_modules/@graphy/core.iso.stream": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@graphy/core.iso.stream/-/core.iso.stream-4.3.7.tgz", + "integrity": "sha512-Rr7C+pPYmFVUGqP8OnYPh7D6VnwucT4LUQBDvlni4OSB9Px0QEenlUBTyqcfIByDTcDNb8fFek9qyjjrO6zlNQ==", + "license": "ISC", + "dependencies": { + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=8.4.0" + } + }, + "node_modules/@graphy/core.iso.threads": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@graphy/core.iso.threads/-/core.iso.threads-4.3.7.tgz", + "integrity": "sha512-xdoaaFJZL5dYzPtbM3C/CSH40ZMmmld1/6HxuBeM1G5fsVHtmNAXVYlakhXFVwo7d95zStmtfl4LUjftC6+mIw==", + "license": "ISC", + "engines": { + "node": ">=8.4.0" + } + }, + "node_modules/@graphy/memory.dataset.fast": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@graphy/memory.dataset.fast/-/memory.dataset.fast-4.3.7.tgz", + "integrity": "sha512-WIEQCNPBsq6V6Sy3hD4+i3TT+wh2UTizZara8+wttupQSGEv8HE8CgEjqIBLGfu6AjvPzFOQ6sxZuD2V/7adJg==", + "license": "ISC", + "dependencies": { + "@graphy/core.data.factory": "^4.3.7", + "@graphy/core.iso.stream": "^4.3.7" + }, + "engines": { + "node": ">=8.4.0" + } + }, + "node_modules/@graphy/util.dataset.tree": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@graphy/util.dataset.tree/-/util.dataset.tree-4.3.7.tgz", + "integrity": "sha512-xDtPLN1v63ZN02YEzIHsOfLFraxcJMCpQOD88BHUkZFE/F/cUoKRzETVCNxL3NOwgE+bw9AV6RXwuYTZPwhgpA==", + "license": "ISC", + "dependencies": { + "@graphy/core.data.factory": "^4.3.7", + "@graphy/core.iso.stream": "^4.3.7" + }, + "engines": { + "node": ">=8.4.0" + } + }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -1219,6 +1504,39 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/@rdfjs/types": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@rdfjs/types/-/types-1.1.2.tgz", + "integrity": "sha512-wqpOJK1QCbmsGNtyzYnojPU8gRDPid2JO0Q0kMtb4j65xhCK880cnKAfEOwC+dX85VJcCByQx5zOwyyfCjDJsg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@rmlio/yarrrml-parser": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@rmlio/yarrrml-parser/-/yarrrml-parser-1.7.2.tgz", + "integrity": "sha512-pLT9eeYWCHdzJxBRuVmDtYZWzusNW3unSNEmHIFzGrpDxN7fZAdZQbKxZs07l6GnGsLSuEajQMYmrzrN8PBaGA==", + "license": "MIT", + "dependencies": { + "commander": "^9.4.1", + "extend": "^3.0.2", + "glob": "^8.0.3", + "graphy": "^4.3.5", + "js-logger": "^1.6.1", + "n3": "^1.16.3", + "parse-author": "^2.0.0", + "pkginfo": "^0.4.1", + "prefix-ns": "^0.1.2", + "q": "^1.5.1", + "rdf-isomorphic": "^1.3.1", + "yamljs": "^0.3.0" + }, + "bin": { + "yarrrml-generator": "bin/generator.js", + "yarrrml-parser": "bin/parser.js" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.24.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz", @@ -1571,11 +1889,21 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/n3": { + "version": "1.21.1", + "resolved": "https://registry.npmjs.org/@types/n3/-/n3-1.21.1.tgz", + "integrity": "sha512-9KxFlFj3etnpdI2nyQEp/jHry5DHxWT22z9Nc/y/hdHe0CHVc9rKu+NacWKUyN06dDLDh7ZnjCzY8yBJ9lmzdw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rdfjs/types": "^1.1.0", + "@types/node": "*" + } + }, "node_modules/@types/node": { "version": "22.10.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "dev": true, "license": "MIT", "dependencies": { "undici-types": "~6.20.0" @@ -1904,6 +2232,18 @@ "d3-zoom": "^3.0.0" } }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/acorn": { "version": "8.14.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", @@ -1944,6 +2284,30 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -2076,6 +2440,15 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, + "node_modules/author-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/author-regex/-/author-regex-1.0.0.tgz", + "integrity": "sha512-KbWgR8wOYRAPekEmMXrYYdc7BRyhn2Ftk7KWfMUnQ43hFdojWEFRxhhRUm3/OFEdPa1r0KAvTTg9YQK57xTe0g==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, "node_modules/autoprefixer": { "version": "10.4.20", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", @@ -2145,14 +2518,46 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, "license": "MIT" }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "license": "Unlicense", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/bkit": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/bkit/-/bkit-2.1.3.tgz", + "integrity": "sha512-mgjJ0c8gx9secFYhU/WZIA4LuhtzVOlQQuuyWJUbL0aTs6cZT+P2Bpa86kOP8lsf64pd8NpM5fgo529AgZTt0Q==" + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -2205,6 +2610,30 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "node_modules/buffer-builder": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/buffer-builder/-/buffer-builder-0.2.0.tgz", @@ -2282,6 +2711,15 @@ "tslib": "^2.0.3" } }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001684", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001684.tgz", @@ -2314,6 +2752,34 @@ "upper-case-first": "^2.0.2" } }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/change-case": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", @@ -2358,6 +2824,17 @@ "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", "license": "MIT" }, + "node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, "node_modules/clsx": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", @@ -2371,7 +2848,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -2384,7 +2860,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, "license": "MIT" }, "node_modules/colorjs.io": { @@ -2406,11 +2881,19 @@ "node": ">= 0.8" } }, + "node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || >=14" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, "license": "MIT" }, "node_modules/constant-case": { @@ -2631,6 +3114,15 @@ } } }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -2738,6 +3230,12 @@ "dev": true, "license": "ISC" }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, "node_modules/enhanced-resolve": { "version": "5.17.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", @@ -3197,52 +3695,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/espree": { "version": "10.3.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", @@ -3307,6 +3759,30 @@ "node": ">=0.10.0" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -3490,6 +3966,12 @@ "url": "https://github.com/sponsors/rawify" } }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -3555,6 +4037,15 @@ "node": ">=6.9.0" } }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-intrinsic": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz", @@ -3611,6 +4102,26 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, + "node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -3624,6 +4135,27 @@ "node": ">=10.13.0" } }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/globals": { "version": "15.13.0", "resolved": "https://registry.npmjs.org/globals/-/globals-15.13.0.tgz", @@ -3681,6 +4213,49 @@ "dev": true, "license": "MIT" }, + "node_modules/graphy": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/graphy/-/graphy-4.3.7.tgz", + "integrity": "sha512-TTe4M+QzI9m5wlnSaC+Rq4vUn1nzFqsHdp2qY5GU04rVrZCISMwt5e760GPHEUj9H2sNeZDiRp0tXMf7JjzXjg==", + "license": "ISC", + "dependencies": { + "@graphy/content.nq.read": "4.3.7", + "@graphy/content.nq.scan": "4.3.7", + "@graphy/content.nq.scribe": "4.3.7", + "@graphy/content.nq.write": "4.3.7", + "@graphy/content.nt.read": "4.3.7", + "@graphy/content.nt.scan": "4.3.7", + "@graphy/content.nt.scribe": "4.3.7", + "@graphy/content.nt.write": "4.3.7", + "@graphy/content.trig.read": "4.3.7", + "@graphy/content.trig.scribe": "4.3.7", + "@graphy/content.trig.write": "4.3.7", + "@graphy/content.ttl.read": "4.3.7", + "@graphy/content.ttl.scribe": "4.3.7", + "@graphy/content.ttl.write": "4.3.7", + "@graphy/content.xml.scribe": "4.3.7", + "@graphy/core.class.scribable": "4.3.7", + "@graphy/core.class.writable": "4.3.7", + "@graphy/core.data.factory": "4.3.7", + "@graphy/core.iso.stream": "4.3.7", + "@graphy/core.iso.threads": "4.3.7", + "@graphy/memory.dataset.fast": "4.3.7", + "@graphy/util.dataset.tree": "4.3.7", + "big-integer": "^1.6.48", + "bkit": "^2.1.3", + "chalk": "^4.1.0", + "pegjs": "^0.10.0", + "readable-stream": "^3.6.0", + "uri-js": "^4.4.0", + "yargs": "^15.4.1" + }, + "bin": { + "graphy": "cli.js" + }, + "engines": { + "node": ">=8.4.0" + } + }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -3695,7 +4270,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -3759,6 +4333,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -3782,6 +4366,26 @@ "tslib": "^2.0.3" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -3826,6 +4430,23 @@ "node": ">=0.8.19" } }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, "node_modules/internal-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", @@ -4021,6 +4642,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/is-generator-function": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", @@ -4274,6 +4904,12 @@ "jiti": "bin/jiti.js" } }, + "node_modules/js-logger": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/js-logger/-/js-logger-1.6.1.tgz", + "integrity": "sha512-yTgMCPXVjhmg28CuUH8CKjU+cIKL/G+zTu4Fn4lQxs8mRFH/03QTNvEFngcxfg/gRDiQAOoyCKmMTOm9ayOzXA==", + "license": "MIT" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -4482,11 +5118,16 @@ "node": ">= 0.6" } }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "license": "ISC" + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -4519,6 +5160,36 @@ "dev": true, "license": "MIT" }, + "node_modules/n3": { + "version": "1.23.1", + "resolved": "https://registry.npmjs.org/n3/-/n3-1.23.1.tgz", + "integrity": "sha512-3f0IYJo+6+lXypothmlwPzm3wJNffsxUwnfONeFv2QqWq7RjTvyCMtkRXDUXW6XrZoOzaQX8xTTSYNlGjXcGtw==", + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "queue-microtask": "^1.1.2", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">=12.0" + } + }, + "node_modules/n3/node_modules/readable-stream": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.6.0.tgz", + "integrity": "sha512-cbAdYt0VcnpN2Bekq7PU+k363ZRsPwJoEEJOEtSJQlJXzwaxt3FIo/uL+KeDSGIjJqtkwyge4KQgD2S2kd+CQw==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/nanoid": { "version": "3.3.8", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", @@ -4681,6 +5352,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -4731,6 +5411,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -4754,6 +5443,18 @@ "node": ">=6" } }, + "node_modules/parse-author": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-author/-/parse-author-2.0.0.tgz", + "integrity": "sha512-yx5DfvkN8JsHL2xk2Os9oTia467qnvRgey4ahSm2X8epehBLx/gWLcy5KI+Y36ful5DzGbCS6RazqZGgy1gHNw==", + "license": "MIT", + "dependencies": { + "author-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/pascal-case": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", @@ -4778,12 +5479,20 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -4801,6 +5510,18 @@ "dev": true, "license": "MIT" }, + "node_modules/pegjs": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.10.0.tgz", + "integrity": "sha512-qI5+oFNEGi3L5HAxDwN2LA4Gg7irF70Zs25edhjld9QemOgp0CbvMtbFcMvFtEo1OityPrcCzkQFB8JP/hxgow==", + "license": "MIT", + "bin": { + "pegjs": "bin/pegjs" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -4821,6 +5542,15 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pkginfo": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.4.1.tgz", + "integrity": "sha512-8xCNE/aT/EXKenuMDZ+xTVwkT8gsoHN2z/Q29l80u0ppGEXVvsKRzNMbtKhg8LS8k1tJLAHHylf6p4VFmP6XUQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", @@ -4867,6 +5597,13 @@ "dev": true, "license": "MIT" }, + "node_modules/prefix-ns": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/prefix-ns/-/prefix-ns-0.1.2.tgz", + "integrity": "sha512-sMfjexR5XMvZfZBm7Amb44OpzWgT7wwvOq9wAgLGAwsb7j12c7ZMXZa98SgCyySD6YyevGjK3cj0e+O0T+FCgA==", + "hasInstallScript": true, + "license": "MIT" + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -4877,6 +5614,15 @@ "node": ">= 0.8.0" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -4904,17 +5650,26 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", + "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)", + "license": "MIT", + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, "funding": [ { "type": "github", @@ -4931,6 +5686,48 @@ ], "license": "MIT" }, + "node_modules/rdf-data-factory": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/rdf-data-factory/-/rdf-data-factory-1.1.2.tgz", + "integrity": "sha512-TfQD63Lokabd09ES1jAtKK8AA6rkr9rwyUBGo6olOt1CE0Um36CUQIqytyf0am2ouBPR0l7SaHxCiMcPGHkt1A==", + "license": "MIT", + "dependencies": { + "@rdfjs/types": "*" + } + }, + "node_modules/rdf-isomorphic": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rdf-isomorphic/-/rdf-isomorphic-1.3.1.tgz", + "integrity": "sha512-6uIhsXTVp2AtO6f41PdnRV5xZsa0zVZQDTBdn0br+DZuFf5M/YD+T6m8hKDUnALI6nFL/IujTMLgEs20MlNidQ==", + "license": "MIT", + "dependencies": { + "@rdfjs/types": "*", + "hash.js": "^1.1.7", + "rdf-string": "^1.6.0", + "rdf-terms": "^1.7.0" + } + }, + "node_modules/rdf-string": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/rdf-string/-/rdf-string-1.6.3.tgz", + "integrity": "sha512-HIVwQ2gOqf+ObsCLSUAGFZMIl3rh9uGcRf1KbM85UDhKqP+hy6qj7Vz8FKt3GA54RiThqK3mNcr66dm1LP0+6g==", + "license": "MIT", + "dependencies": { + "@rdfjs/types": "*", + "rdf-data-factory": "^1.1.0" + } + }, + "node_modules/rdf-terms": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/rdf-terms/-/rdf-terms-1.11.0.tgz", + "integrity": "sha512-iKlVgnMopRKl9pHVNrQrax7PtZKRCT/uJIgYqvuw1VVQb88zDvurtDr1xp0rt7N9JtKtFwUXoIQoEsjyRo20qQ==", + "license": "MIT", + "dependencies": { + "@rdfjs/types": "*", + "rdf-data-factory": "^1.1.0", + "rdf-string": "^1.6.0" + } + }, "node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", @@ -5093,6 +5890,20 @@ } } }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.8.tgz", @@ -5141,6 +5952,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "license": "ISC" + }, "node_modules/resolve": { "version": "1.22.9", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.9.tgz", @@ -5280,6 +6106,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/safe-regex-test": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", @@ -5713,6 +6559,12 @@ "upper-case-first": "^2.0.2" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" + }, "node_modules/set-cookie-parser": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", @@ -5872,6 +6724,12 @@ "node": ">=0.10.0" } }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause" + }, "node_modules/stable-hash": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.4.tgz", @@ -5885,6 +6743,29 @@ "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==", "license": "MIT" }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/string.prototype.trim": { "version": "1.2.10", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", @@ -5944,6 +6825,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -6244,7 +7137,6 @@ "version": "6.20.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "dev": true, "license": "MIT" }, "node_modules/update-browserslist-db": { @@ -6300,7 +7192,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" @@ -6315,6 +7206,12 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, "node_modules/uuid": { "version": "11.0.3", "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.3.tgz", @@ -6499,6 +7396,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "license": "ISC" + }, "node_modules/which-typed-array": { "version": "1.1.16", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.16.tgz", @@ -6529,6 +7432,32 @@ "node": ">=0.10.0" } }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "license": "ISC" + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", @@ -6551,6 +7480,137 @@ "node": ">= 14" } }, + "node_modules/yamljs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/yamljs/-/yamljs-0.3.0.tgz", + "integrity": "sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==", + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "glob": "^7.0.5" + }, + "bin": { + "json2yaml": "bin/json2yaml", + "yaml2json": "bin/yaml2json" + } + }, + "node_modules/yamljs/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/yamljs/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/app/package.json b/app/package.json index 6ace774..5e01f6e 100644 --- a/app/package.json +++ b/app/package.json @@ -15,11 +15,13 @@ "@blueprintjs/select": "5.3.6", "@blueprintjs/table": "5.3.0", "@monaco-editor/react": "^4.6.0", + "@rmlio/yarrrml-parser": "^1.7.2", "@xyflow/react": "^12.3.6", "axios": "1.7.9", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "lucide-react": "^0.468.0", + "n3": "^1.23.1", "react": "^18.3.1", "react-dom": "^18.3.1", "react-icons": "^5.4.0", @@ -30,6 +32,7 @@ }, "devDependencies": { "@eslint/js": "9.16.0", + "@types/n3": "^1.21.1", "@types/node": "^22.10.2", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", @@ -47,4 +50,4 @@ "typescript-eslint": "8.18.0", "vite": "6.0.3" } -} \ No newline at end of file +} diff --git a/app/src/lib/api/yarrrml_service/index.ts b/app/src/lib/api/yarrrml_service/index.ts new file mode 100644 index 0000000..7587743 --- /dev/null +++ b/app/src/lib/api/yarrrml_service/index.ts @@ -0,0 +1,67 @@ +import RMLGenerator from '@rmlio/yarrrml-parser/lib/rml-generator'; +import { Writer } from 'n3'; +import ApiService from '../../services/api_service'; + +class YARRRMLService { + private static getApiClient(): ApiService { + return ApiService.getInstance('default'); + } + + public static async getYARRRMLMapping( + workspaceUuid: string, + mappingUuid: string, + ): Promise { + const result = await this.getApiClient().callApi( + `/workspaces/${workspaceUuid}/mapping/${mappingUuid}/yarrrml`, + { + method: 'GET', + parser: data => data as string, + }, + ); + + if (result.type === 'success') { + return result.data; + } + + throw new Error( + `Failed to get YARRRML mapping: ${result.message} (status: ${result.status})`, + ); + } + + public static async yarrrmlToRML(yarrrml: string): Promise { + const y2r = new RMLGenerator(); + const quads = y2r.convert(yarrrml); + const writer = new Writer(); + writer.addQuads(quads); + return new Promise((resolve, reject) => { + writer.end((error, result) => { + if (error) { + reject(error); + } else { + resolve(result); + } + }); + }); + } + + public static async rmlToTTL(rml: string): Promise { + const result = await this.getApiClient().callApi( + '/rml/run-rml-mapping', + { + method: 'POST', + body: rml, + parser: data => data as string, + }, + ); + + if (result.type === 'success') { + return result.data; + } + + throw new Error( + `Failed to convert RML to TTL: ${result.message} (status: ${result.status})`, + ); + } +} + +export default YARRRMLService; diff --git a/app/src/pages/mapping_page/components/MappingDialog/index.tsx b/app/src/pages/mapping_page/components/MappingDialog/index.tsx new file mode 100644 index 0000000..5c72d66 --- /dev/null +++ b/app/src/pages/mapping_page/components/MappingDialog/index.tsx @@ -0,0 +1,95 @@ +import { + Button, + Dialog, + DialogBody, + DialogFooter, + Tab, + TabPanel, + Tabs, +} from '@blueprintjs/core'; +import { Editor } from '@monaco-editor/react'; +import { useState } from 'react'; + +type MappingDialogProps = { + open: boolean; + yarrrml: string; + rml: string; + ttl: string; + onClose: () => void; +}; + +const MappingDialog = ({ + open, + yarrrml, + rml, + ttl, + onClose, +}: MappingDialogProps) => { + const [activeTab, setActiveTab] = useState('yarrrml'); + + return ( + + + setActiveTab(String(newTabId))} + selectedTabId={activeTab} + > + + } + /> + + } + /> + + } + /> + + + + + + + + ); +}; + +export default MappingDialog; diff --git a/app/src/pages/mapping_page/components/Navbar/index.tsx b/app/src/pages/mapping_page/components/Navbar/index.tsx index 25f88e1..21b3ab3 100644 --- a/app/src/pages/mapping_page/components/Navbar/index.tsx +++ b/app/src/pages/mapping_page/components/Navbar/index.tsx @@ -13,6 +13,7 @@ type NavbarProps = { mapping_uuid: string | undefined; name: string | undefined; isLoading: string | null; + onCompleteMapping: () => void; }; const Navbar = ({ @@ -20,9 +21,11 @@ const Navbar = ({ mapping_uuid, name, isLoading, + onCompleteMapping, }: NavbarProps) => { const navigation = useNavigate(); const saveMapping = useMappingPage(state => state.saveMapping); + const isSaved = useMappingPage(state => state.isSaved); const mapping = useMappingPage(state => state.mapping); @@ -60,7 +63,9 @@ const Navbar = ({ > Save - + diff --git a/app/src/pages/mapping_page/index.tsx b/app/src/pages/mapping_page/index.tsx index 4259a17..9bf387c 100644 --- a/app/src/pages/mapping_page/index.tsx +++ b/app/src/pages/mapping_page/index.tsx @@ -1,6 +1,7 @@ +import MappingDialog from '@/pages/mapping_page/components/MappingDialog'; import { ReactFlowProvider } from '@xyflow/react'; import { languages } from 'monaco-editor'; -import { useEffect, useRef } from 'react'; +import { useEffect, useRef, useState } from 'react'; import { ImperativePanelHandle, Panel, @@ -38,7 +39,9 @@ const MappingPage = () => { const loadMapping = useMappingPage(state => state.loadMapping); const setSelectedTab = useMappingPage(state => state.setSelectedTab); const setIsCollapsed = useMappingPage(state => state.setIsSidePanelCollapsed); + const completeMapping = useMappingPage(state => state.completeMapping); + const [openDialog, setOpenDialog] = useState<'complete_mapping' | null>(null); useRegisterTheme('mapping-theme', mapping_theme); useRegisterLanguage('mapping_language', mapping_language, {}); useRegisterCompletionItemProvider('mapping_language', [ @@ -106,14 +109,38 @@ const MappingPage = () => { setIsCollapsed(false); }; + const [completeMappingResult, setCompleteMappingResult] = useState<{ + yarrrml: string; + rml: string; + ttl: string; + } | null>(null); + + const onCompleteMapping = async () => { + if (!props.uuid || !props.mapping_uuid) return; + const { yarrrml, rml, ttl } = await completeMapping( + props.uuid, + props.mapping_uuid, + ); + setCompleteMappingResult({ yarrrml, rml, ttl }); + setOpenDialog('complete_mapping'); + }; + return (
+ setOpenDialog(null)} + />
diff --git a/app/src/pages/mapping_page/state.ts b/app/src/pages/mapping_page/state.ts index 1619575..b87efa2 100644 --- a/app/src/pages/mapping_page/state.ts +++ b/app/src/pages/mapping_page/state.ts @@ -1,3 +1,4 @@ +import YARRRMLService from '@/lib/api/yarrrml_service'; import { XYEdgeType, XYNodeTypes, @@ -37,6 +38,10 @@ interface MappingPageStateActions { nodes: XYNodeTypes[], edges: XYEdgeType[], ) => Promise; + completeMapping: ( + workspaceUuid: string, + mappingUuid: string, + ) => Promise<{ yarrrml: string; rml: string; ttl: string }>; setIsSaved: (isSaved: boolean) => void; setSelectedTab: ( selectedTab: 'properties' | 'ai' | 'references' | 'search', @@ -126,6 +131,28 @@ const functions: ZustandActions = ( set({ isLoading: null }); } }, + completeMapping: async (workspaceUuid: string, mappingUuid: string) => { + set({ isLoading: 'Creating YARRRML' }); + try { + const yarrrml = await YARRRMLService.getYARRRMLMapping( + workspaceUuid, + mappingUuid, + ); + set({ isLoading: 'Creating RML' }); + const rml = await YARRRMLService.yarrrmlToRML(yarrrml); + set({ isLoading: 'Creating TTL' }); + const ttl = await YARRRMLService.rmlToTTL(rml); + set({ error: null, isLoading: null }); + return { yarrrml, rml, ttl }; + } catch (error) { + if (error instanceof Error) { + set({ error: error.message }); + } + throw error; + } finally { + set({ isLoading: null }); + } + }, setIsSaved(isSaved: boolean) { set({ isSaved }); }, diff --git a/app/src/pages/workspace_page/components/CreateMappingDialog/index.tsx b/app/src/pages/workspace_page/components/CreateMappingDialog/index.tsx index f04d5a0..58ab164 100644 --- a/app/src/pages/workspace_page/components/CreateMappingDialog/index.tsx +++ b/app/src/pages/workspace_page/components/CreateMappingDialog/index.tsx @@ -74,6 +74,11 @@ const CreateMappingDialog = (props: CreateMappingDialogProps) => { setError('Please fill all fields'); return; } + // json_path must end with '[*]' + if (sourceType === 'json' && json_path.value.slice(-3) !== '[*]') { + setError('JSON Path must end with "[*]"'); + return; + } const extra = sourceType === 'json' ? { json_path: json_path.value } : {}; diff --git a/app/src/yarrrml-parser.d.ts b/app/src/yarrrml-parser.d.ts new file mode 100644 index 0000000..3b6d7a1 --- /dev/null +++ b/app/src/yarrrml-parser.d.ts @@ -0,0 +1,176 @@ +declare module '@rmlio/yarrrml-parser/lib/rml-generator' { + import { NamedNode, Quad } from 'n3'; + import { AbstractGenerator } from './abstract-generator'; + + interface Yarrrml { + base?: string; + sources?: Record; + targets?: Record; + mappings?: Record; + } + + interface Source { + type?: string; + access?: string; + delimiter?: string; + iterator?: string; + query?: string; + queryFormulation?: string; + credentials?: { + username?: string; + password?: string; + }; + security?: Array; + } + + interface Target { + serialization?: string; + compression?: string; + type?: string; + access?: string; + ldes?: { + id: string; + generateImmutableIRI?: boolean; + shape?: string; + timestampPath?: string; + versionOfPath?: string; + }; + } + + class AbstractGenerator { + constructor(options?: unknown); + + convert( + yarrrml: string | Array<{ yarrrml: string; file?: string }>, + ): Quad[]; + + convertExpandedJSON(yarrrml: Yarrrml): void; + + private _combineExpandedJSONs(expandedJSONs: Yarrrml[]): Yarrrml; + + private _addSourceValuesToTarget( + sourceObj: Record, + targetObj: Record, + messageValue: string, + ): void; + + generateMapping( + tmSubject: NamedNode, + mapping: unknown, + mappingName: string, + sourceSubject: NamedNode | undefined, + targetsIRIMap: Record, + ): void; + + generateNormalObjectMap(omSubject: NamedNode, o: unknown): void; + + generateAllReferencingObjectMap(): void; + + generateReferencingObjectMap(pomSubject: NamedNode, o: unknown): void; + + generateCondition(condition: unknown, omSubject: NamedNode): void; + + saveReferencingObjectMapDetails( + mappingName: string, + pom: NamedNode, + o: unknown, + ): void; + + generateFunctionTermMap( + omSubject: NamedNode, + o: unknown, + sourceSubject: NamedNode, + termType: string, + ): void; + + generateGraphMap( + subject: NamedNode, + graph: unknown, + sourceSubject: NamedNode, + ): void; + + generateFnSource(fnSubject: NamedNode, sourceSubject: NamedNode): void; + + private _generateDatasetDescription(authors: Array): void; + + static parseTemplate(t: string): string; + + static escapeTemplate(t: string): string; + + static countReference(t: string): number; + + static hasConstantPart(t: string): boolean; + + static getFirstReference(t: string): string; + + private _replaceExternalReferences(str: string): string; + + getUniqueID(prefix?: string): string; + + static expandPrefix(str: string): string; + + addMappingIRI(mappingName: string, iri: NamedNode): void; + + getPrefixes(): Record; + + getBaseIRI(): string; + + getAppropriatePredicateAndObjectForValue( + value: string, + isIRI?: boolean, + ): { predicate: NamedNode; object: NamedNode | Literal }; + + convertEqualToIDLabEqual(fn: unknown): void; + + getLogger(): unknown; + + removeUnusedDatatypes(o: unknown): void; + + processDatatypeAndLanguageOfObject(o: unknown, omSubject: NamedNode): void; + } + + class RMLGenerator extends AbstractGenerator { + constructor(options?: unknown); + + convertExpandedJSON(yarrrml: Yarrrml): Quad[]; + + private _generateTargetId(target: unknown): string; + + generateMapping( + tmSubject: NamedNode, + mapping: unknown, + mappingName: string, + sourceSubject: NamedNode | undefined, + targetsIRIMap: Record, + ): void; + + generateSource( + source: Source, + tmSubject?: NamedNode, + sourceName?: string, + ): NamedNode; + + generateTarget(target: Target, targetName?: string): NamedNode; + + private _generateDatabaseDescription( + subject: NamedNode, + source: Source, + ): void; + + generateFnSource(fnSubject: NamedNode, sourceSubject: NamedNode): void; + + generateLanguageTerms(objectMap: NamedNode, value: unknown): NamedNode; + + generateCondition(condition: unknown, omSubject: NamedNode): void; + + getReferenceOnlyPredicate(): NamedNode; + + private _parametersContainsFunction(parameters: unknown[]): boolean; + + private _parametersContainsConstantValues(parameters: unknown[]): boolean; + + private _parametersContainsTemplates(parameters: unknown[]): boolean; + } + + export = RMLGenerator; +} diff --git a/justfile b/justfile index 278b55f..7cd19ed 100644 --- a/justfile +++ b/justfile @@ -10,27 +10,36 @@ test: install-dev @echo "Running tests..." uv run coverage run -m unittest discover -v -s ./test -p "*_test.py" + package-mac: install-dev @echo "Packaging for macOS..." - rm -rf build dist public + rm -rf build dist public bin + @echo "Downloading external binaries..." + mkdir -p bin + curl -L https://github.com/RMLio/rmlmapper-java/releases/download/v7.2.0/rmlmapper-7.2.0-r374-all.jar -o bin/mapper.jar npm run frontend:prod uv sync uv run nuitka \ --standalone \ --output-dir=dist \ --include-data-dir=public=public \ + --include-data-dir=bin=bin \ --macos-create-app-bundle \ --enable-console \ main.py package-win: install-dev @echo "Packaging for Windows..." - rm -rf build dist public + rm -rf build dist public bin + @echo "Downloading external binaries..." + mkdir -p bin + curl -L https://github.com/RMLio/rmlmapper-java/releases/download/v7.2.0/rmlmapper-7.2.0-r374-all.jar -o bin/mapper.jar npm run frontend:prod uv sync .venv/Scripts/python -m nuitka \ --standalone \ --output-dir=dist \ --include-data-dir=public=public \ + --include-data-dir=bin=bin \ --windows-disable-console \ main.py \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 5554fa2..cba2c4c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -75,6 +75,7 @@ dependencies = [ "websockets==13.1", "wrapt==1.16.0", "xmltodict==0.14.2", + "yatter>=1.2.1", "zipp==3.20.2", ] diff --git a/server/const/err_enums.py b/server/const/err_enums.py index 2343c79..1f37316 100644 --- a/server/const/err_enums.py +++ b/server/const/err_enums.py @@ -44,4 +44,11 @@ class ErrCodes(Enum): MAPPING_NODE_ID_NOT_FOUND = 141 ENTITY_URI_PATTERN_NOT_FOUND = 142 LITERAL_VALUE_NOT_FOUND = 143 - URIREF_URI_PATTERN_NOT_FOUND = 144 \ No newline at end of file + URIREF_URI_PATTERN_NOT_FOUND = 144 + + # RML Service + INVALID_YARRRML = 160 + + # RML Mapper Service + + RML_MAPPING_EXECUTION_ERROR = 180 diff --git a/server/routers/rml/__init__.py b/server/routers/rml/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/server/routers/rml/rml.py b/server/routers/rml/rml.py new file mode 100644 index 0000000..8779d31 --- /dev/null +++ b/server/routers/rml/rml.py @@ -0,0 +1,47 @@ +from typing import Annotated + +from fastapi.exceptions import HTTPException +from fastapi.params import Body, Depends +from fastapi.routing import APIRouter +from kink.container import di +from starlette.responses import PlainTextResponse + +from server.exceptions import ServerException +from server.service_protocols.rml_mapper_service_protocol import ( + RMLMapperServiceProtocol, +) + +router = APIRouter() + + +RMLMapperDep = Annotated[ + RMLMapperServiceProtocol, + Depends(lambda: di[RMLMapperServiceProtocol]), +] + + +@router.post( + "/run-rml-mapping", + response_class=PlainTextResponse, +) +async def run_rml_mapping( + rml: Annotated[ + str, + Body( + media_type="text/plain", + ), + ], + rml_mapper_service: RMLMapperDep, +) -> str: + try: + return rml_mapper_service.execute_rml_mapping(rml) + except ServerException as e: + raise HTTPException( + status_code=500, + detail=f"{e.code}: {e.message}", + ) + except Exception as e: + raise HTTPException( + status_code=500, + detail=str(e), + ) diff --git a/server/server.py b/server/server.py index bb71080..1b3c47e 100644 --- a/server/server.py +++ b/server/server.py @@ -17,6 +17,7 @@ ) from bootstrap import bootstrap, teardown +from server.routers.rml.rml import router as rml_router from server.routers.sources.sources import ( router as sources_router, ) @@ -146,6 +147,12 @@ async def logging_middleware( tags=["sources"], ) +app.include_router( + rml_router, + prefix="/api/rml", + tags=["rml"], +) + if not DEBUG: # Serve the React app current_dir = Path(__file__).parent.parent diff --git a/server/service_protocols/rml_mapper_service_protocol/__init__.py b/server/service_protocols/rml_mapper_service_protocol/__init__.py new file mode 100644 index 0000000..1385241 --- /dev/null +++ b/server/service_protocols/rml_mapper_service_protocol/__init__.py @@ -0,0 +1,15 @@ +from abc import ABC, abstractmethod + + +class RMLMapperServiceProtocol(ABC): + @abstractmethod + def execute_rml_mapping(self, mapping: str) -> str: + """ + Execute an RML mapping + + Args: + mapping (str): RML mapping + + Returns: + str: Result of the mapping + """ diff --git a/server/services/__init__.py b/server/services/__init__.py index 15e1154..d49323d 100644 --- a/server/services/__init__.py +++ b/server/services/__init__.py @@ -4,6 +4,9 @@ from server.services.core.mapping_to_yarrrml_service import ( MappingToYARRRMLService, ) +from server.services.core.rml_mapper_service import ( + RMLMapperService, +) from server.services.core.sqlite_db_service import DBService from server.services.core.workspace_metadata_service import ( WorkspaceMetadataService, @@ -34,4 +37,5 @@ "LocalSourceService", "LocalMappingService", "MappingToYARRRMLService", + "RMLMapperService", ] diff --git a/server/services/core/mapping_to_yarrrml_service.py b/server/services/core/mapping_to_yarrrml_service.py index c011da3..1387f66 100644 --- a/server/services/core/mapping_to_yarrrml_service.py +++ b/server/services/core/mapping_to_yarrrml_service.py @@ -1,4 +1,5 @@ import datetime +import logging from pathlib import Path from typing import cast @@ -26,6 +27,7 @@ class MappingToYARRRMLService( MappingToYARRRMLServiceProtocol ): def __init__(self, TEMP_DIR: Path) -> None: + self.logger = logging.getLogger(__name__) self.temp_dir = TEMP_DIR def convert_mapping_to_yarrrml( @@ -35,38 +37,109 @@ def convert_mapping_to_yarrrml( mapping: MappingGraph, fs_service: FSServiceProtocol, # Implementation might change depending the environment (local, cloud, etc) ) -> str: + self.logger.info( + f"Converting mapping {mapping.name} to YARRRML" + ) yarrrml_dict: dict = { "prefixes": prefixes, } + source_path = self._prepare_source_file( + source, fs_service + ) + yarrrml_dict["sources"] = self._get_source_dict( + source, source_path + ) + + yarrrml_dict["mappings"] = self._get_mappings_dict( + mapping + ) + + # Delete any empty keys + + yarrrml_dict = { + k: v + for k, v in yarrrml_dict.items() + if len(v) > 0 + } + + yaml_str = yaml.dump( + yarrrml_dict, + sort_keys=False, + default_flow_style=False, + ) + + # Write the YARRRML to a temporary file + + temp_file_path: Path = ( + self.temp_dir + / f"yarrrml-{mapping.name}-{datetime.datetime.now().isoformat()}.yml" + ) + + temp_file_path.touch() + + temp_file_path.write_text(yaml_str) + + return yaml_str + + def _prepare_source_file( + self, source: Source, fs_service: FSServiceProtocol + ) -> Path: + self.logger.info( + "Downloading source file content, to workaround a limitation in the RMLMapper (files must have a extension)" + ) + source_content = fs_service.download_file_with_uuid( + source.file_uuid + ) + + extension = ( + "csv" + if source.type == SourceType.CSV + else "json" + ) + + source_path = ( + self.temp_dir + / f"{source.file_uuid}.{extension}" + ) + + self.logger.info( + f"Writing source file content to {source_path}" + ) + + if source_path.exists(): + source_path.unlink() + + source_path.touch() + + source_path.write_bytes(source_content) + + return source_path + + def _get_source_dict( + self, source: Source, source_path: Path + ) -> dict: source_dict: dict = {} match source.type: case SourceType.CSV: source_dict["data"] = { - "access": str( - fs_service.provide_file_path_of_uuid( - source.uuid - ).absolute() - ), + "access": str(source_path.absolute()), "referenceFormulation": "csv", } case SourceType.JSON: source_dict["data"] = { - "access": str( - fs_service.provide_file_path_of_uuid( - source.uuid - ).absolute() - ), - "referenceFormulation": "json", + "access": str(source_path.absolute()), + "referenceFormulation": "jsonpath", "iterator": source.extra["json_path"], } - yarrrml_dict["sources"] = source_dict - - # Mappings + return source_dict + def _get_mappings_dict( + self, mapping: MappingGraph + ) -> dict: mappings: dict = {} entities: list[MappingNode] = [ @@ -76,114 +149,109 @@ def convert_mapping_to_yarrrml( ] for entity in entities: - if entity.uri_pattern == "": - raise ServerException( - f"Entity {entity.label} has no URI pattern", - code=ErrCodes.ENTITY_URI_PATTERN_NOT_FOUND, - ) - entity_dict: dict = { - "source": "data", - "s": entity.uri_pattern, - } - po: list[dict | list] = [ - { - "predicate": "http://www.w3.org/1999/02/22-rdf-syntax-ns#label", - "object": entity.label, - } - ] - - for rdf_type in entity.rdf_type: - po.append( - { - "predicate": "a", - "object": rdf_type, - "type": "iri", - } - ) - - outgoing_edges_target_nodes: list[ - tuple[ - MappingEdge, - MappingNode - | MappingLiteral - | MappingURIRef, - ] - ] = self._get_outgoing_edges(entity, mapping) + self._validate_entity(entity) + entity_dict = self._create_entity_dict(entity) + po = self._create_po_list(entity) + outgoing_edges_target_nodes = ( + self._get_outgoing_edges(entity, mapping) + ) for ( edge, target_node, ) in outgoing_edges_target_nodes: - if isinstance(target_node, MappingLiteral): - if target_node.value == "": - raise ServerException( - f"Literal with id {target_node.id} has no value", - code=ErrCodes.LITERAL_VALUE_NOT_FOUND, - ) - po.append( - { - "predicate": edge.source_handle, - "object": { - "value": target_node.value, - "datatype": target_node.literal_type, - }, - } - ) - elif isinstance(target_node, MappingURIRef): - if target_node.uri_pattern == "": - raise ServerException( - f"URIRef with id {target_node.id} has no URI pattern", - code=ErrCodes.URIREF_URI_PATTERN_NOT_FOUND, - ) - po.append( - { - "predicate": edge.source_handle, - "object": { - "value": target_node.uri_pattern, - "type": "iri", - }, - } - ) - elif isinstance(target_node, MappingNode): - if target_node.uri_pattern == "": - raise ServerException( - f"Node with id {target_node.id} has no URI pattern", - code=ErrCodes.ENTITY_URI_PATTERN_NOT_FOUND, - ) - po.append( - { - "predicate": edge.source_handle, - "object": { - "value": target_node.uri_pattern, - "type": "iri", - }, - } - ) + po.append( + self._create_po_entry(edge, target_node) + ) entity_dict["po"] = po - mappings[entity.id] = entity_dict - yarrrml_dict["mappings"] = mappings + return mappings - yaml_str = yaml.dump( - yarrrml_dict, - sort_keys=False, - default_flow_style=False, - ) + def _validate_entity(self, entity: MappingNode) -> None: + if entity.uri_pattern == "": + raise ServerException( + f"Entity {entity.label} has no URI pattern", + code=ErrCodes.ENTITY_URI_PATTERN_NOT_FOUND, + ) - # Write the YARRRML to a temporary file + def _create_entity_dict( + self, entity: MappingNode + ) -> dict: + return { + "source": "data", + "s": entity.uri_pattern, + } - temp_file_path: Path = ( - self.temp_dir - / f"yarrrml-{mapping.name}-{datetime.datetime.now().isoformat()}.yml" - ) + def _create_po_list(self, entity: MappingNode) -> list: + po = [ + { + "predicate": "http://www.w3.org/1999/02/22-rdf-syntax-ns#label", + "object": { + "value": entity.label, + "datatype": "http://www.w3.org/2001/XMLSchema#string", + }, + } + ] - temp_file_path.touch() + for rdf_type in entity.rdf_type: + po.append( + { + "predicate": "a", + "object": rdf_type, + "type": "iri", + } + ) - temp_file_path.write_text(yaml_str) + return po - return yaml_str + def _create_po_entry( + self, + edge: MappingEdge, + target_node: MappingNode + | MappingLiteral + | MappingURIRef, + ) -> dict: + if isinstance(target_node, MappingLiteral): + if target_node.value == "": + raise ServerException( + f"Literal with id {target_node.id} has no value", + code=ErrCodes.LITERAL_VALUE_NOT_FOUND, + ) + return { + "predicate": edge.source_handle, + "object": { + "value": target_node.value, + "datatype": target_node.literal_type, + }, + } + elif isinstance(target_node, MappingURIRef): + if target_node.uri_pattern == "": + raise ServerException( + f"URIRef with id {target_node.id} has no URI pattern", + code=ErrCodes.URIREF_URI_PATTERN_NOT_FOUND, + ) + return { + "predicate": edge.source_handle, + "object": { + "value": target_node.uri_pattern, + "type": "iri", + }, + } + elif isinstance(target_node, MappingNode): + if target_node.uri_pattern == "": + raise ServerException( + f"Node with id {target_node.id} has no URI pattern", + code=ErrCodes.ENTITY_URI_PATTERN_NOT_FOUND, + ) + return { + "predicate": edge.source_handle, + "object": { + "value": target_node.uri_pattern, + "type": "iri", + }, + } def _get_outgoing_edges( self, node: MappingNode, mapping: MappingGraph diff --git a/server/services/core/rml_mapper_service.py b/server/services/core/rml_mapper_service.py new file mode 100644 index 0000000..cd346c8 --- /dev/null +++ b/server/services/core/rml_mapper_service.py @@ -0,0 +1,120 @@ +import logging +import subprocess +from pathlib import Path +from uuid import uuid4 + +from kink import inject + +from server.exceptions import ErrCodes, ServerException +from server.service_protocols.config_service_protocol import ( + ConfigServiceProtocol, +) +from server.service_protocols.rml_mapper_service_protocol import ( + RMLMapperServiceProtocol, +) + + +@inject(alias=RMLMapperServiceProtocol) +class RMLMapperService(RMLMapperServiceProtocol): + def __init__( + self, + config_service: ConfigServiceProtocol, + TEMP_DIR: Path, + ): + self.logger = logging.getLogger(__name__) + self.TEMP_DIR = TEMP_DIR + self.logger.info("Instantiating RMLMapperService") + self.logger.info( + "Determining if system has Java installed" + ) + self.mapper_bin = Path("bin/mapper.jar") + custom_java_path = config_service.get("java_path") + self.java_memory = ( + config_service.get("java_memory") or "4G" + ) + self.java_path = None + if custom_java_path: + self.logger.info( + f"Using custom Java path: {custom_java_path}" + ) + try: + subprocess.run( + [custom_java_path, "-version"], + check=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + self.java_path = custom_java_path + except FileNotFoundError: + self.logger.error( + "Java not found, trying default Java path" + ) + if not self.java_path: + try: + subprocess.run( + ["java", "-version"], + check=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + self.java_path = "java" + except FileNotFoundError: + self.logger.error( + "Java not found, RML mappings will not be able to be executed" + ) + return + + self.logger.info( + f"Java found at {self.java_path}, checking for mapper" + ) + + if not self.mapper_bin.exists(): + self.logger.error( + "Mapper not found, RML mappings will not be able to be executed" + ) + + self.logger.info("RMLMapperService instantiated") + + def execute_rml_mapping(self, mapping: str) -> str: + self.logger.info("Executing RML mapping") + self.logger.info("Writing RML mapping to temp file") + process_uuid = uuid4().hex + rml_file: Path = ( + self.TEMP_DIR / f"rml_{process_uuid}.ttl" + ) + + rml_file.touch() + rml_file.write_text(mapping) + + rdf_output_file: Path = ( + self.TEMP_DIR / f"rdf_{process_uuid}.ttl" + ) + + cmd_rml = ( + f"java -Xmx{self.java_memory} -jar {self.mapper_bin} -m {rml_file} -o {rdf_output_file} -s" + " turtle" + ) + + self.logger.info(f"Executing command: {cmd_rml}") + + result = subprocess.run( + cmd_rml, + shell=True, + capture_output=True, + text=True, + ) + + if result.returncode != 0: + self.logger.error( + f"Error executing RML mapping: {result.stderr}" + ) + raise ServerException( + f"Error executing RML mapping: {result.stderr}", + ErrCodes.RML_MAPPING_EXECUTION_ERROR, + ) + + self.logger.info( + "RML mapping executed successfully" + ) + + return rdf_output_file.read_text() diff --git a/server/services/local/local_fs_service.py b/server/services/local/local_fs_service.py index da450a3..f2bc2b3 100644 --- a/server/services/local/local_fs_service.py +++ b/server/services/local/local_fs_service.py @@ -155,7 +155,17 @@ def download_file_with_uuid(self, uuid: str) -> bytes: return file_path.read_bytes() def provide_file_path_of_uuid(self, uuid: str) -> Path: - return self._FILE_DIR / uuid + self.logger.info( + f"Providing file path of UUID {uuid}" + ) + path = self._FILE_DIR / uuid + if not path.exists(): + raise ServerException( + f"File with UUID {uuid} does not exist", + code=ErrCodes.FILE_NOT_FOUND, + ) + + return path __all__ = ["LocalFSService"] diff --git a/server/services/local/local_source_service.py b/server/services/local/local_source_service.py index 32272d7..ed0ce5a 100644 --- a/server/services/local/local_source_service.py +++ b/server/services/local/local_source_service.py @@ -172,7 +172,7 @@ def create_source( type=type, references=references, file_uuid=file_metadata.uuid, - extra={}, + extra=extra, ) self.fs_service.upload_file( diff --git a/uv.lock b/uv.lock index b4a89b3..cac755f 100644 --- a/uv.lock +++ b/uv.lock @@ -119,6 +119,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, ] +[[package]] +name = "coloredlogs" +version = "15.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "humanfriendly" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cc/c7/eed8f27100517e8c0e6b923d5f0845d0cb99763da6fdee00478f91db7325/coloredlogs-15.0.1.tar.gz", hash = "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0", size = 278520 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/06/3d6badcf13db419e25b07041d9c7b4a2c331d3f4e7134445ec5df57714cd/coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934", size = 46018 }, +] + [[package]] name = "coverage" version = "7.6.8" @@ -313,6 +325,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/56/95/9377bcb415797e44274b51d46e3249eba641711cf3348050f76ee7b15ffc/httpx-0.27.2-py3-none-any.whl", hash = "sha256:7bb2708e112d8fdd7829cd4243970f0c223274051cb35ee80c03301ee29a3df0", size = 76395 }, ] +[[package]] +name = "humanfriendly" +version = "10.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyreadline3", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cc/3f/2c29224acb2e2df4d2046e4c73ee2662023c58ff5b113c4c1adac0886c43/humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc", size = 360702 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f0/0f/310fb31e39e2d734ccaa2c0fb981ee41f7bd5056ce9bc29b2248bd569169/humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477", size = 86794 }, +] + [[package]] name = "idna" version = "3.10" @@ -645,6 +669,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/be/ec/2eb3cd785efd67806c46c13a17339708ddc346cbb684eade7a6e6f79536a/pyparsing-3.2.0-py3-none-any.whl", hash = "sha256:93d9577b88da0bbea8cc8334ee8b918ed014968fd2ec383e868fb8afb1ccef84", size = 106921 }, ] +[[package]] +name = "pyreadline3" +version = "3.5.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/49/4cea918a08f02817aabae639e3d0ac046fef9f9180518a3ad394e22da148/pyreadline3-3.5.4.tar.gz", hash = "sha256:8d57d53039a1c75adba8e50dd3d992b28143480816187ea5efbd5c78e6c885b7", size = 99839 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/dc/491b7661614ab97483abf2056be1deee4dc2490ecbf7bff9ab5cdbac86e1/pyreadline3-3.5.4-py3-none-any.whl", hash = "sha256:eaf8e6cc3c49bcccf145fc6067ba8643d1df34d604a1ec0eccbf7a18e6d3fae6", size = 83178 }, +] + [[package]] name = "python-dateutil" version = "2.9.0.post0" @@ -818,6 +851,7 @@ dependencies = [ { name = "websockets" }, { name = "wrapt" }, { name = "xmltodict" }, + { name = "yatter" }, { name = "zipp" }, ] @@ -896,6 +930,7 @@ requires-dist = [ { name = "websockets", specifier = "==13.1" }, { name = "wrapt", specifier = "==1.16.0" }, { name = "xmltodict", specifier = "==0.14.2" }, + { name = "yatter", specifier = ">=1.2.1" }, { name = "zipp", specifier = "==3.20.2" }, ] @@ -931,6 +966,35 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/67/91/5474b84e505a6ccc295b2d322d90ff6aa0746745717839ee0c5fb4fdcceb/rich-13.9.2-py3-none-any.whl", hash = "sha256:8c82a3d3f8dcfe9e734771313e606b39d8247bb6b826e196f4914b333b743cf1", size = 242117 }, ] +[[package]] +name = "ruamel-yaml" +version = "0.18.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ruamel-yaml-clib", marker = "platform_python_implementation == 'CPython'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4a/9f/a073b2c0d916045c3decf885b6fea12d2d1b02f235e89a02606140111138/ruamel.yaml-0.18.8.tar.gz", hash = "sha256:1b7e14f28a4b8d09f8cd40dca158852db9b22ac84f22da5bb711def35cb5c548", size = 143528 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9f/01/bb9350e3446a3b31658054a1e254fb9d5ace2f931c4edad5cda2a8c991b8/ruamel.yaml-0.18.8-py3-none-any.whl", hash = "sha256:a7c02af6ec9789495b4d19335addabc4d04ab1e0dad3e491c0c9457bbc881100", size = 117497 }, +] + +[[package]] +name = "ruamel-yaml-clib" +version = "0.2.12" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/84/80203abff8ea4993a87d823a5f632e4d92831ef75d404c9fc78d0176d2b5/ruamel.yaml.clib-0.2.12.tar.gz", hash = "sha256:6c8fbb13ec503f99a91901ab46e0b07ae7941cd527393187039aec586fdfd36f", size = 225315 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/8f/683c6ad562f558cbc4f7c029abcd9599148c51c54b5ef0f24f2638da9fbb/ruamel.yaml.clib-0.2.12-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:4a6679521a58256a90b0d89e03992c15144c5f3858f40d7c18886023d7943db6", size = 132224 }, + { url = "https://files.pythonhosted.org/packages/3c/d2/b79b7d695e2f21da020bd44c782490578f300dd44f0a4c57a92575758a76/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:d84318609196d6bd6da0edfa25cedfbabd8dbde5140a0a23af29ad4b8f91fb1e", size = 641480 }, + { url = "https://files.pythonhosted.org/packages/68/6e/264c50ce2a31473a9fdbf4fa66ca9b2b17c7455b31ef585462343818bd6c/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb43a269eb827806502c7c8efb7ae7e9e9d0573257a46e8e952f4d4caba4f31e", size = 739068 }, + { url = "https://files.pythonhosted.org/packages/86/29/88c2567bc893c84d88b4c48027367c3562ae69121d568e8a3f3a8d363f4d/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:811ea1594b8a0fb466172c384267a4e5e367298af6b228931f273b111f17ef52", size = 703012 }, + { url = "https://files.pythonhosted.org/packages/11/46/879763c619b5470820f0cd6ca97d134771e502776bc2b844d2adb6e37753/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cf12567a7b565cbf65d438dec6cfbe2917d3c1bdddfce84a9930b7d35ea59642", size = 704352 }, + { url = "https://files.pythonhosted.org/packages/02/80/ece7e6034256a4186bbe50dee28cd032d816974941a6abf6a9d65e4228a7/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7dd5adc8b930b12c8fc5b99e2d535a09889941aa0d0bd06f4749e9a9397c71d2", size = 737344 }, + { url = "https://files.pythonhosted.org/packages/f0/ca/e4106ac7e80efbabdf4bf91d3d32fc424e41418458251712f5672eada9ce/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1492a6051dab8d912fc2adeef0e8c72216b24d57bd896ea607cb90bb0c4981d3", size = 714498 }, + { url = "https://files.pythonhosted.org/packages/67/58/b1f60a1d591b771298ffa0428237afb092c7f29ae23bad93420b1eb10703/ruamel.yaml.clib-0.2.12-cp311-cp311-win32.whl", hash = "sha256:bd0a08f0bab19093c54e18a14a10b4322e1eacc5217056f3c063bd2f59853ce4", size = 100205 }, + { url = "https://files.pythonhosted.org/packages/b4/4f/b52f634c9548a9291a70dfce26ca7ebce388235c93588a1068028ea23fcc/ruamel.yaml.clib-0.2.12-cp311-cp311-win_amd64.whl", hash = "sha256:a274fb2cb086c7a3dea4322ec27f4cb5cc4b6298adb583ab0e211a4682f241eb", size = 118185 }, +] + [[package]] name = "ruff" version = "0.8.0" @@ -1177,6 +1241,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d6/45/fc303eb433e8a2a271739c98e953728422fa61a3c1f36077a49e395c972e/xmltodict-0.14.2-py2.py3-none-any.whl", hash = "sha256:20cc7d723ed729276e808f26fb6b3599f786cbc37e06c65e192ba77c40f20aac", size = 9981 }, ] +[[package]] +name = "yatter" +version = "1.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "coloredlogs" }, + { name = "rdflib" }, + { name = "ruamel-yaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9e/b8/ef3cef6969a8a9f65d8bd52aab60a2f8b6c8bb727ee790aa417634150003/yatter-1.2.1.tar.gz", hash = "sha256:2081c886796685681392a78ff762546f9d2a82a8ee48cc6ad808e95ee5492969", size = 21206 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/86/91/a13fca21291e1d7e51d420d7588a376924b8f8b9c86ee6b8f63e36e169af/yatter-1.2.1-py3-none-any.whl", hash = "sha256:40a476538598c1bd874f3d03c3ba965fd4d158415fad03f8ac57593db69881e4", size = 22979 }, +] + [[package]] name = "zipp" version = "3.20.2"