diff --git a/.prettierignore b/.prettierignore index 4e393838..ce54e856 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,2 +1,3 @@ **/*.hbs packages/*/dist +**/*.ejs diff --git a/package-lock.json b/package-lock.json index c7eea3c8..844e25d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15427,6 +15427,436 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@jsonjoy.com/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/buffers": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-17.67.0.tgz", + "integrity": "sha512-tfExRpYxBvi32vPs9ZHaTjSP4fHAfzSmcahOfNxtvGHcyJel+aibkPlGeBB+7AoC6hL7lXIE++8okecBxx7lcw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/codegen": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/codegen/-/codegen-1.0.0.tgz", + "integrity": "sha512-E8Oy+08cmCf0EK/NMxpaJZmOxPqM+6iSe2S4nlSBrPZOORoDJILxtbSUEDKQyTamm/BVAhIGllOBNU79/dwf0g==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-core": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-core/-/fs-core-4.57.1.tgz", + "integrity": "sha512-YrEi/ZPmgc+GfdO0esBF04qv8boK9Dg9WpRQw/+vM8Qt3nnVIJWIa8HwZ/LXVZ0DB11XUROM8El/7yYTJX+WtA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-node-builtins": "4.57.1", + "@jsonjoy.com/fs-node-utils": "4.57.1", + "thingies": "^2.5.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-fsa": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-fsa/-/fs-fsa-4.57.1.tgz", + "integrity": "sha512-ooEPvSW/HQDivPDPZMibHGKZf/QS4WRir1czGZmXmp3MsQqLECZEpN0JobrD8iV9BzsuwdIv+PxtWX9WpPLsIA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-core": "4.57.1", + "@jsonjoy.com/fs-node-builtins": "4.57.1", + "@jsonjoy.com/fs-node-utils": "4.57.1", + "thingies": "^2.5.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node/-/fs-node-4.57.1.tgz", + "integrity": "sha512-3YaKhP8gXEKN+2O49GLNfNb5l2gbnCFHyAaybbA2JkkbQP3dpdef7WcUaHAulg/c5Dg4VncHsA3NWAUSZMR5KQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-core": "4.57.1", + "@jsonjoy.com/fs-node-builtins": "4.57.1", + "@jsonjoy.com/fs-node-utils": "4.57.1", + "@jsonjoy.com/fs-print": "4.57.1", + "@jsonjoy.com/fs-snapshot": "4.57.1", + "glob-to-regex.js": "^1.0.0", + "thingies": "^2.5.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node-builtins": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-builtins/-/fs-node-builtins-4.57.1.tgz", + "integrity": "sha512-XHkFKQ5GSH3uxm8c3ZYXVrexGdscpWKIcMWKFQpMpMJc8gA3AwOMBJXJlgpdJqmrhPyQXxaY9nbkNeYpacC0Og==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node-to-fsa": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-to-fsa/-/fs-node-to-fsa-4.57.1.tgz", + "integrity": "sha512-pqGHyWWzNck4jRfaGV39hkqpY5QjRUQ/nRbNT7FYbBa0xf4bDG+TE1Gt2KWZrSkrkZZDE3qZUjYMbjwSliX6pg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-fsa": "4.57.1", + "@jsonjoy.com/fs-node-builtins": "4.57.1", + "@jsonjoy.com/fs-node-utils": "4.57.1" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node-utils": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-utils/-/fs-node-utils-4.57.1.tgz", + "integrity": "sha512-vp+7ZzIB8v43G+GLXTS4oDUSQmhAsRz532QmmWBbdYA20s465JvwhkSFvX9cVTqRRAQg+vZ7zWDaIEh0lFe2gw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-node-builtins": "4.57.1" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-print": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-print/-/fs-print-4.57.1.tgz", + "integrity": "sha512-Ynct7ZJmfk6qoXDOKfpovNA36ITUx8rChLmRQtW08J73VOiuNsU8PB6d/Xs7fxJC2ohWR3a5AqyjmLojfrw5yw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-node-utils": "4.57.1", + "tree-dump": "^1.1.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-snapshot/-/fs-snapshot-4.57.1.tgz", + "integrity": "sha512-/oG8xBNFMbDXTq9J7vepSA1kerS5vpgd3p5QZSPd+nX59uwodGJftI51gDYyHRpP57P3WCQf7LHtBYPqwUg2Bg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/buffers": "^17.65.0", + "@jsonjoy.com/fs-node-utils": "4.57.1", + "@jsonjoy.com/json-pack": "^17.65.0", + "@jsonjoy.com/util": "^17.65.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/base64": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-17.67.0.tgz", + "integrity": "sha512-5SEsJGsm15aP8TQGkDfJvz9axgPwAEm98S5DxOuYe8e1EbfajcDmgeXXzccEjh+mLnjqEKrkBdjHWS5vFNwDdw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/codegen": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/codegen/-/codegen-17.67.0.tgz", + "integrity": "sha512-idnkUplROpdBOV0HMcwhsCUS5TRUi9poagdGs70A6S4ux9+/aPuKbh8+UYRTLYQHtXvAdNfQWXDqZEx5k4Dj2Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/json-pack": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-17.67.0.tgz", + "integrity": "sha512-t0ejURcGaZsn1ClbJ/3kFqSOjlryd92eQY465IYrezsXmPcfHPE/av4twRSxf6WE+TkZgLY+71vCZbiIiFKA/w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/base64": "17.67.0", + "@jsonjoy.com/buffers": "17.67.0", + "@jsonjoy.com/codegen": "17.67.0", + "@jsonjoy.com/json-pointer": "17.67.0", + "@jsonjoy.com/util": "17.67.0", + "hyperdyperid": "^1.2.0", + "thingies": "^2.5.0", + "tree-dump": "^1.1.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/json-pointer": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-17.67.0.tgz", + "integrity": "sha512-+iqOFInH+QZGmSuaybBUNdh7yvNrXvqR+h3wjXm0N/3JK1EyyFAeGJvqnmQL61d1ARLlk/wJdFKSL+LHJ1eaUA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/util": "17.67.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/util": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-17.67.0.tgz", + "integrity": "sha512-6+8xBaz1rLSohlGh68D1pdw3AwDi9xydm8QNlAFkvnavCJYSze+pxoW2VKP8p308jtlMRLs5NTHfPlZLd4w7ew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/buffers": "17.67.0", + "@jsonjoy.com/codegen": "17.67.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.21.0.tgz", + "integrity": "sha512-+AKG+R2cfZMShzrF2uQw34v3zbeDYUqnQ+jg7ORic3BGtfw9p/+N6RJbq/kkV8JmYZaINknaEQ2m0/f693ZPpg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/base64": "^1.1.2", + "@jsonjoy.com/buffers": "^1.2.0", + "@jsonjoy.com/codegen": "^1.0.0", + "@jsonjoy.com/json-pointer": "^1.0.2", + "@jsonjoy.com/util": "^1.9.0", + "hyperdyperid": "^1.2.0", + "thingies": "^2.5.0", + "tree-dump": "^1.1.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack/node_modules/@jsonjoy.com/buffers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-1.2.1.tgz", + "integrity": "sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pointer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-1.0.2.tgz", + "integrity": "sha512-Fsn6wM2zlDzY1U+v4Nc8bo3bVqgfNTGcn6dMgs6FjrEnt4ZCe60o6ByKRjOGlI2gow0aE/Q41QOigdTqkyK5fg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/codegen": "^1.0.0", + "@jsonjoy.com/util": "^1.9.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/util": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.9.0.tgz", + "integrity": "sha512-pLuQo+VPRnN8hfPqUTLTHk126wuYdXVxE6aDmjSeV4NCAgyxWbiOIeNJVtID3h1Vzpoi9m4jXezf73I6LgabgQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/buffers": "^1.0.0", + "@jsonjoy.com/codegen": "^1.0.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/util/node_modules/@jsonjoy.com/buffers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-1.2.1.tgz", + "integrity": "sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, "node_modules/@koa/cors": { "version": "5.0.0", "license": "MIT", @@ -19745,14 +20175,6 @@ "@types/node": "*" } }, - "node_modules/@types/fs-extra": { - "version": "9.0.13", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/http-assert": { "version": "1.5.6", "license": "MIT" @@ -25112,18 +25534,6 @@ "dev": true, "license": "MIT" }, - "node_modules/fs-extra": { - "version": "10.1.0", - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/fs-minipass": { "version": "2.1.0", "dev": true, @@ -25475,6 +25885,23 @@ "node": ">=10.13.0" } }, + "node_modules/glob-to-regex.js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/glob-to-regex.js/-/glob-to-regex.js-1.2.0.tgz", + "integrity": "sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, "node_modules/glob/node_modules/brace-expansion": { "version": "1.1.11", "dev": true, @@ -26032,6 +26459,16 @@ "ms": "^2.0.0" } }, + "node_modules/hyperdyperid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", + "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.18" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "dev": true, @@ -28526,6 +28963,36 @@ "node": ">= 0.6" } }, + "node_modules/memfs": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.57.1.tgz", + "integrity": "sha512-WvzrWPwMQT+PtbX2Et64R4qXKK0fj/8pO85MrUCzymX3twwCiJCdvntW3HdhG1teLJcHDDLIKx5+c3HckWYZtQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-core": "4.57.1", + "@jsonjoy.com/fs-fsa": "4.57.1", + "@jsonjoy.com/fs-node": "4.57.1", + "@jsonjoy.com/fs-node-builtins": "4.57.1", + "@jsonjoy.com/fs-node-to-fsa": "4.57.1", + "@jsonjoy.com/fs-node-utils": "4.57.1", + "@jsonjoy.com/fs-print": "4.57.1", + "@jsonjoy.com/fs-snapshot": "4.57.1", + "@jsonjoy.com/json-pack": "^1.11.0", + "@jsonjoy.com/util": "^1.9.0", + "glob-to-regex.js": "^1.0.1", + "thingies": "^2.5.0", + "tree-dump": "^1.0.3", + "tslib": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, "node_modules/meow": { "version": "8.1.2", "dev": true, @@ -35340,6 +35807,23 @@ "node": ">=0.8" } }, + "node_modules/thingies": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-2.6.0.tgz", + "integrity": "sha512-rMHRjmlFLM1R96UYPvpmnc3LYtdFrT33JIB7L9hetGue1qAPfn1N2LJeEjxUSidu1Iku+haLZXDuEXUHNGO/lg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "^2" + } + }, "node_modules/through": { "version": "2.3.8", "dev": true, @@ -35532,6 +36016,23 @@ "node": ">=18" } }, + "node_modules/tree-dump": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.1.0.tgz", + "integrity": "sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, "node_modules/tree-kill": { "version": "1.2.2", "dev": true, @@ -39670,10 +40171,10 @@ "@ldo/ldo": "^1.0.0-alpha.38", "@ldo/schema-converter-shex": "^1.0.0-alpha.38", "@shexjs/parser": "^1.0.0-alpha.24", + "camelcase": "^9.0.0", "child-process-promise": "^2.2.1", "commander": "^9.3.0", "ejs": "^3.1.8", - "fs-extra": "^10.1.0", "loading-cli": "^1.1.0", "prettier": "^3.0.3", "prompts": "^2.4.2", @@ -39688,14 +40189,26 @@ "devDependencies": { "@types/child-process-promise": "^2.2.2", "@types/ejs": "^3.1.1", - "@types/fs-extra": "^9.0.13", "@types/jsonld": "^1.5.15", "@types/prompts": "^2.4.9", "@types/shexj": "^2.1.4", "copyfiles": "^2.4.1", + "memfs": "^4.57.1", "rimraf": "^3.0.2" } }, + "packages/cli/node_modules/camelcase": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-9.0.0.tgz", + "integrity": "sha512-TO9xmyXTZ9HUHI8M1OnvExxYB0eYVS/1e5s7IDMTAoIcwUd+aNcFODs6Xk83mobk0velyHFQgA1yIrvYc6wclw==", + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "packages/cli/node_modules/rimraf": { "version": "3.0.2", "dev": true, diff --git a/packages/cli/package.json b/packages/cli/package.json index a694c825..a3cac84e 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -33,11 +33,11 @@ "devDependencies": { "@types/child-process-promise": "^2.2.2", "@types/ejs": "^3.1.1", - "@types/fs-extra": "^9.0.13", "@types/jsonld": "^1.5.15", "@types/prompts": "^2.4.9", "@types/shexj": "^2.1.4", "copyfiles": "^2.4.1", + "memfs": "^4.57.1", "rimraf": "^3.0.2" }, "dependencies": { @@ -45,10 +45,10 @@ "@ldo/ldo": "^1.0.0-alpha.38", "@ldo/schema-converter-shex": "^1.0.0-alpha.38", "@shexjs/parser": "^1.0.0-alpha.24", + "camelcase": "^9.0.0", "child-process-promise": "^2.2.1", "commander": "^9.3.0", "ejs": "^3.1.8", - "fs-extra": "^10.1.0", "loading-cli": "^1.1.0", "prettier": "^3.0.3", "prompts": "^2.4.2", diff --git a/packages/cli/src/build.ts b/packages/cli/src/build.ts index b24852f5..7b9891a3 100644 --- a/packages/cli/src/build.ts +++ b/packages/cli/src/build.ts @@ -1,8 +1,9 @@ -import fs from "fs-extra"; +import fs from "node:fs/promises"; import path from "path"; import type { Schema } from "shexj"; import parser from "@shexjs/parser"; import schemaConverterShex from "@ldo/schema-converter-shex"; +import toCamelCase from "camelcase"; import { renderFile } from "ejs"; import prettier from "prettier"; import loading from "loading-cli"; @@ -19,14 +20,26 @@ interface BuildOptions { output: string; } +async function exists(filename: string) { + try { + await fs.stat(filename); + return true; + } catch (e) { + if (e instanceof Error && (e as NodeJS.ErrnoException).code === "ENOENT") + return false; + + throw e; + } +} + export async function build(options: BuildOptions) { const load = loading("Preparing Environment"); load.start(); // Prepare new folder by clearing/and/or creating it - if (fs.existsSync(options.output)) { - await fs.promises.rm(options.output, { recursive: true }); + if (await exists(options.output)) { + await fs.rm(options.output, { recursive: true }); } - await fs.promises.mkdir(options.output); + await fs.mkdir(options.output); load.text = "Generating LDO Documents"; await forAllShapes(options.input, async (fileName, shexC) => { @@ -46,6 +59,9 @@ export async function build(options: BuildOptions) { } // Convert the content to types const [typings, context] = await schemaConverterShex(schema); + + const shapeName = toCamelCase(fileName); + await Promise.all( ["context", "schema", "shapeTypes", "typings"].map( async (templateName) => { @@ -54,12 +70,13 @@ export async function build(options: BuildOptions) { { typings: typings.typings, fileName, + shapeName, schema: JSON.stringify(schema, null, 2), context: JSON.stringify(context, null, 2), }, ); // Save conversion to document - await fs.promises.writeFile( + await fs.writeFile( path.join(options.output, `${fileName}.${templateName}.ts`), await prettier.format(finalContent, { parser: "typescript" }), ); diff --git a/packages/cli/src/create.ts b/packages/cli/src/create.ts index 832d1671..84902208 100644 --- a/packages/cli/src/create.ts +++ b/packages/cli/src/create.ts @@ -8,7 +8,7 @@ import path from "path"; import prompts from "prompts"; import type { PackageJson } from "type-fest"; import loading from "loading-cli"; -import { promises as fs } from "fs"; +import fs from "node:fs/promises"; import { dirname } from "node:path"; import { fileURLToPath } from "node:url"; diff --git a/packages/cli/src/generateReadme.ts b/packages/cli/src/generateReadme.ts index 41e77a21..291ff2cf 100644 --- a/packages/cli/src/generateReadme.ts +++ b/packages/cli/src/generateReadme.ts @@ -1,6 +1,6 @@ import { getPackageJson } from "./util/modifyPackageJson.js"; import { forAllShapes } from "./util/forAllShapes.js"; -import { promises as fs } from "fs"; +import fs from "node:fs/promises"; import path from "path"; import { Project } from "ts-morph"; import { renderFile } from "ejs"; diff --git a/packages/cli/src/init.ts b/packages/cli/src/init.ts index 393f5dcd..c5c49f1e 100644 --- a/packages/cli/src/init.ts +++ b/packages/cli/src/init.ts @@ -1,5 +1,5 @@ import { exec } from "child-process-promise"; -import fs from "fs-extra"; +import fs from "node:fs/promises"; import path from "path"; import { renderFile } from "ejs"; import { modifyPackageJson } from "./util/modifyPackageJson.js"; @@ -22,7 +22,7 @@ export async function init(directory?: string) { let parentDirectory = projectDirectory; parentDirectory = "./"; const allDirectories = ( - await fs.promises.readdir("./", { + await fs.readdir("./", { withFileTypes: true, }) ).filter((file) => file.isDirectory()); @@ -43,8 +43,8 @@ export async function init(directory?: string) { // Create "shapes" folder const shapesFolderPath = path.join(parentDirectory, DEFAULT_SHAPES_FOLDER); - await fs.promises.mkdir(shapesFolderPath); - const defaultShapePaths = await fs.promises.readdir( + await fs.mkdir(shapesFolderPath); + const defaultShapePaths = await fs.readdir( path.join(__dirname, "./templates/defaultShapes"), ); await Promise.all( @@ -53,7 +53,7 @@ export async function init(directory?: string) { path.join(__dirname, "./templates/defaultShapes", shapePath), {}, ); - await fs.promises.writeFile( + await fs.writeFile( path.join(shapesFolderPath, `${path.parse(shapePath).name}.shex`), shapeContent, ); diff --git a/packages/cli/src/templates/context.ejs b/packages/cli/src/templates/context.ejs index 0b6ffe62..090d3e1c 100644 --- a/packages/cli/src/templates/context.ejs +++ b/packages/cli/src/templates/context.ejs @@ -2,7 +2,7 @@ import type { LdoJsonldContext } from "@ldo/ldo"; /** * ============================================================================= - * <%- fileName %>Context: JSONLD Context for <%- fileName %> + * <%- shapeName %>Context: JSONLD Context for <%- fileName %> * ============================================================================= */ -export const <%- fileName %>Context: LdoJsonldContext = <%- context %>; +export const <%- shapeName %>Context: LdoJsonldContext = <%- context %>; diff --git a/packages/cli/src/templates/schema.ejs b/packages/cli/src/templates/schema.ejs index aae86865..09346fbd 100644 --- a/packages/cli/src/templates/schema.ejs +++ b/packages/cli/src/templates/schema.ejs @@ -2,7 +2,7 @@ import type { Schema } from "shexj"; /** * ============================================================================= - * <%- fileName %>Schema: ShexJ Schema for <%- fileName %> + * <%- shapeName %>Schema: ShexJ Schema for <%- fileName %> * ============================================================================= */ -export const <%- fileName %>Schema: Schema = <%- schema %>; +export const <%- shapeName %>Schema: Schema = <%- schema %>; diff --git a/packages/cli/src/templates/shapeTypes.ejs b/packages/cli/src/templates/shapeTypes.ejs index 553a0658..559b5dcc 100644 --- a/packages/cli/src/templates/shapeTypes.ejs +++ b/packages/cli/src/templates/shapeTypes.ejs @@ -1,6 +1,6 @@ import type { ShapeType } from "@ldo/ldo"; -import { <%- fileName %>Schema } from "./<%- fileName %>.schema"; -import { <%- fileName %>Context } from "./<%- fileName %>.context"; +import { <%- shapeName %>Schema } from "./<%- fileName %>.schema"; +import { <%- shapeName %>Context } from "./<%- fileName %>.context"; import type { <% typings.forEach((typing) => { -%> <%- typing.dts.name %>, @@ -17,8 +17,8 @@ import type { * <%- typing.dts.name %> ShapeType */ export const <%- typing.dts.name %>ShapeType: ShapeType<<%- typing.dts.name %>> = { - schema: <%- fileName %>Schema, + schema: <%- shapeName %>Schema, shape: "<%- typing.dts.shapeId %>", - context: <%- fileName %>Context, + context: <%- shapeName %>Context, }; <% }); -%> diff --git a/packages/cli/src/util/forAllShapes.ts b/packages/cli/src/util/forAllShapes.ts index b1adf326..93f2374f 100644 --- a/packages/cli/src/util/forAllShapes.ts +++ b/packages/cli/src/util/forAllShapes.ts @@ -1,4 +1,4 @@ -import fs from "fs"; +import fs from "node:fs/promises"; import path from "path"; import { shaclStoreToShexSchema, writeShexSchema } from "@jeswr/shacl2shex"; import { dereferenceToStore } from "rdf-dereference-store"; @@ -22,7 +22,7 @@ export async function forAllShapes( shapePath: string, callback: (filename: string, shape: string) => Promise, ): Promise { - const shapeDir = await fs.promises.readdir(shapePath, { + const shapeDir = await fs.readdir(shapePath, { withFileTypes: true, }); // Filter out non-shex documents @@ -33,10 +33,7 @@ export async function forAllShapes( shexFiles.map(async (file) => { const fileName = path.parse(file.name).name; // Get the content of each document - const shexC = await fs.promises.readFile( - path.join(shapePath, file.name), - "utf8", - ); + const shexC = await fs.readFile(path.join(shapePath, file.name), "utf8"); await callback(fileName, shexC); }), ); diff --git a/packages/cli/src/util/modifyPackageJson.ts b/packages/cli/src/util/modifyPackageJson.ts index 2bc0d548..2c4e77a2 100644 --- a/packages/cli/src/util/modifyPackageJson.ts +++ b/packages/cli/src/util/modifyPackageJson.ts @@ -1,14 +1,12 @@ import type { PackageJson } from "type-fest"; -import fs from "fs-extra"; +import fs from "node:fs/promises"; import path from "path"; export async function getPackageJson( projectFolder: string, ): Promise { return JSON.parse( - ( - await fs.promises.readFile(path.join(projectFolder, "./package.json")) - ).toString(), + (await fs.readFile(path.join(projectFolder, "./package.json"))).toString(), ); } @@ -16,8 +14,8 @@ export async function savePackageJson( projectFolder: string, packageJson: PackageJson, ): Promise { - await fs.promises.mkdir(projectFolder, { recursive: true }); - await fs.promises.writeFile( + await fs.mkdir(projectFolder, { recursive: true }); + await fs.writeFile( path.join(projectFolder, "./package.json"), JSON.stringify(packageJson, null, 2), ); diff --git a/packages/cli/test/build.test.ts b/packages/cli/test/build.test.ts new file mode 100644 index 00000000..3ba8d851 --- /dev/null +++ b/packages/cli/test/build.test.ts @@ -0,0 +1,95 @@ +import { fs, vol } from "memfs"; +import { exec, type ExecException } from "node:child_process"; +import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { build } from "../src/build.js"; + +const _runCli = (args: string) => { + return new Promise<{ + error: ExecException | null; + stdout: string; + stderr: string; + }>((resolve) => { + exec(`npx tsx ./src/index.ts ${args}`, (error, stdout, stderr) => { + resolve({ error, stdout, stderr }); + }); + }); +}; + +describe("cli build", () => { + // set up in-memory filesystem + beforeAll(() => { + vi.mock("node:fs/promises", async () => { + const memfs = await vi.importActual("memfs"); + const promises = (memfs.fs as typeof fs).promises; + return { default: promises, ...promises }; + }); + }); + beforeEach(() => { + vol.reset(); + }); + + it("generate shape types", async () => { + await fs.promises.mkdir("shapes/", { recursive: true }); + await fs.promises.writeFile( + "shapes/person.shex", + ` +PREFIX foaf: +PREFIX ex: + +ex:Person EXTRA a { + a [foaf:Person] ; + foaf:knows @ex:Person ; +}`, + ); + await expect( + async () => await fs.promises.readdir("output/"), + ).rejects.toThrowError(); + + await build({ input: "shapes/", output: "output/" }); + + const outputAfter = await fs.promises.readdir("output/"); + expect(outputAfter).toHaveLength(4); + + const result = await fs.promises.readFile( + "output/person.context.ts", + "utf8", + ); + + expect(result).toBeTypeOf("string"); + }); + + it("handle hyphen in shex filename without failing", async () => { + await fs.promises.mkdir("shapes/", { recursive: true }); + await fs.promises.writeFile( + "shapes/person-profile.shex", + ` +PREFIX foaf: +PREFIX ex: + +ex:Person EXTRA a { + a [foaf:Person] ; + foaf:knows @ex:Person ; +}`, + ); + await expect( + async () => await fs.promises.readdir("output/"), + ).rejects.toThrowError(); + + await build({ input: "shapes/", output: "output/" }); + + const outputAfter = await fs.promises.readdir("output/"); + expect(outputAfter).toHaveLength(4); + + // if we got here, the build has not failed, good! + + for (const output of ["context", "schema", "typings", "shapeTypes"]) { + const result = await fs.promises.readFile( + `output/person-profile.${output}.ts`, + "utf8", + ); + + // visually inspect results + console.log(result); + } + }); +});