diff options
-rw-r--r-- | package-lock.json | 509 | ||||
-rw-r--r-- | package.json | 1 | ||||
-rw-r--r-- | src/content/dependencies/generateAlbumReleaseInfo.js | 16 | ||||
-rw-r--r-- | src/static/js/search-worker.js | 1 | ||||
-rw-r--r-- | src/url-spec.js | 2 | ||||
-rw-r--r-- | src/util/search-spec.js | 9 | ||||
-rw-r--r-- | src/web-routes.js | 26 | ||||
-rw-r--r-- | src/write/build-modes/static-build.js | 120 | ||||
-rw-r--r-- | tap-snapshots/test/snapshot/generateAlbumTrackList.js.test.cjs | 50 | ||||
-rw-r--r-- | test/lib/composite.js | 33 | ||||
-rw-r--r-- | test/lib/index.js | 1 | ||||
-rw-r--r-- | test/unit/data/composite/control-flow/withResultOfAvailabilityCheck.js | 18 | ||||
-rw-r--r-- | test/unit/data/composite/data/withPropertiesFromObject.js | 59 | ||||
-rw-r--r-- | test/unit/data/composite/data/withPropertyFromObject.js | 23 | ||||
-rw-r--r-- | test/unit/data/composite/data/withUniqueItemsOnly.js | 23 |
15 files changed, 438 insertions, 453 deletions
diff --git a/package-lock.json b/package-lock.json index 7d5d3152..11bc6a41 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,7 +7,7 @@ "": { "name": "hsmusic-wiki", "version": "0.1.0", - "license": "GPL-3.0", + "license": "MIT", "dependencies": { "@js-temporal/polyfill": "^0.4.4", "chroma-js": "^2.4.2", @@ -20,6 +20,7 @@ "js-yaml": "^4.1.0", "marked": "^10.0.0", "msgpackr": "^1.10.2", + "rimraf": "^5.0.7", "striptags": "^4.0.0-alpha.4", "word-wrap": "^1.2.3" }, @@ -170,7 +171,6 @@ "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -187,7 +187,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, "engines": { "node": ">=12" }, @@ -199,7 +198,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, "dependencies": { "ansi-regex": "^6.0.1" }, @@ -658,7 +656,6 @@ "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, "optional": true, "engines": { "node": ">=14" @@ -954,70 +951,6 @@ "@tapjs/core": "2.0.1" } }, - "node_modules/@tapjs/fixture/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@tapjs/fixture/node_modules/glob": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", - "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@tapjs/fixture/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@tapjs/fixture/node_modules/rimraf": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.7.tgz", - "integrity": "sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==", - "dev": true, - "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@tapjs/intercept": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@tapjs/intercept/-/intercept-2.0.1.tgz", @@ -1264,24 +1197,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@tapjs/run/node_modules/rimraf": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.7.tgz", - "integrity": "sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==", - "dev": true, - "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@tapjs/run/node_modules/tcompare": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/tcompare/-/tcompare-7.0.1.tgz", @@ -1468,24 +1383,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@tapjs/test/node_modules/rimraf": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.7.tgz", - "integrity": "sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==", - "dev": true, - "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@tapjs/typescript": { "version": "1.4.6", "resolved": "https://registry.npmjs.org/@tapjs/typescript/-/typescript-1.4.6.tgz", @@ -1788,12 +1685,13 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -2236,14 +2134,12 @@ "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, "node_modules/encoding": { "version": "0.1.13", @@ -2473,10 +2369,11 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -2511,6 +2408,22 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/flat-cache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/flatted": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", @@ -2525,7 +2438,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "dev": true, "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -3050,6 +2962,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -3125,7 +3038,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.1.2.tgz", "integrity": "sha512-kWmLKn2tRtfYMF/BakihVVRzBKOxz4gJMiL2Rj91WnAB5TPZumSH99R/Yf1qE1u4uRimvCSJfm6hnxohXeEXjQ==", - "dev": true, "dependencies": { "@isaacs/cliui": "^8.0.2" }, @@ -3257,7 +3169,6 @@ "version": "10.2.2", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", - "dev": true, "engines": { "node": "14 || >=16.14" } @@ -3341,7 +3252,6 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, "engines": { "node": ">=16 || 14 >=14.17" } @@ -3975,7 +3885,6 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" @@ -4411,14 +4320,64 @@ } }, "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.7.tgz", + "integrity": "sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==", + "license": "ISC", "dependencies": { - "glob": "^7.1.3" + "glob": "^10.3.7" }, "bin": { - "rimraf": "bin.js" + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/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/rimraf/node_modules/glob": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", + "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -4497,7 +4456,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, "engines": { "node": ">=14" }, @@ -4705,7 +4663,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -4723,7 +4680,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -4736,14 +4692,12 @@ "node_modules/string-width-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -4752,7 +4706,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, "engines": { "node": ">=12" }, @@ -4764,7 +4717,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, "dependencies": { "ansi-regex": "^6.0.1" }, @@ -4791,7 +4743,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -4893,24 +4844,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/sync-content/node_modules/rimraf": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.7.tgz", - "integrity": "sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==", - "dev": true, - "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/tap": { "version": "19.0.2", "resolved": "https://registry.npmjs.org/tap/-/tap-19.0.2.tgz", @@ -5075,6 +5008,7 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -5137,28 +5071,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/tshy/node_modules/glob": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", - "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/tshy/node_modules/minimatch": { "version": "9.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", @@ -5174,24 +5086,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/tshy/node_modules/rimraf": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.7.tgz", - "integrity": "sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==", - "dev": true, - "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", @@ -5390,7 +5284,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -5408,7 +5301,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -5424,14 +5316,12 @@ "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -5440,7 +5330,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -5454,7 +5343,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, "engines": { "node": ">=12" }, @@ -5466,7 +5354,6 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, "engines": { "node": ">=12" }, @@ -5478,7 +5365,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, "dependencies": { "ansi-regex": "^6.0.1" }, @@ -5495,10 +5381,11 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "node_modules/ws": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", - "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.0.0" }, @@ -5727,7 +5614,6 @@ "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, "requires": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -5740,14 +5626,12 @@ "ansi-regex": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" }, "strip-ansi": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, "requires": { "ansi-regex": "^6.0.1" } @@ -6062,7 +5946,6 @@ "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, "optional": true }, "@sigstore/bundle": { @@ -6260,48 +6143,6 @@ "requires": { "mkdirp": "^3.0.0", "rimraf": "^5.0.5" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "glob": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", - "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", - "dev": true, - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "path-scurry": "^1.11.1" - } - }, - "minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "rimraf": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.7.tgz", - "integrity": "sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==", - "dev": true, - "requires": { - "glob": "^10.3.7" - } - } } }, "@tapjs/intercept": { @@ -6471,15 +6312,6 @@ "brace-expansion": "^2.0.1" } }, - "rimraf": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.7.tgz", - "integrity": "sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==", - "dev": true, - "requires": { - "glob": "^10.3.7" - } - }, "tcompare": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/tcompare/-/tcompare-7.0.1.tgz", @@ -6608,15 +6440,6 @@ "requires": { "brace-expansion": "^2.0.1" } - }, - "rimraf": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.7.tgz", - "integrity": "sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==", - "dev": true, - "requires": { - "glob": "^10.3.7" - } } } }, @@ -6846,12 +6669,12 @@ } }, "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "requires": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" } }, "c8": { @@ -7169,14 +6992,12 @@ "eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, "emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, "encoding": { "version": "0.1.13", @@ -7352,9 +7173,9 @@ } }, "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "requires": { "to-regex-range": "^5.0.1" @@ -7376,6 +7197,16 @@ "requires": { "flatted": "^3.1.0", "rimraf": "^3.0.2" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + } } }, "flatted": { @@ -7392,7 +7223,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "dev": true, "requires": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -7821,7 +7651,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.1.2.tgz", "integrity": "sha512-kWmLKn2tRtfYMF/BakihVVRzBKOxz4gJMiL2Rj91WnAB5TPZumSH99R/Yf1qE1u4uRimvCSJfm6hnxohXeEXjQ==", - "dev": true, "requires": { "@isaacs/cliui": "^8.0.2", "@pkgjs/parseargs": "^0.11.0" @@ -7919,8 +7748,7 @@ "lru-cache": { "version": "10.2.2", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", - "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", - "dev": true + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==" }, "make-dir": { "version": "4.0.0", @@ -7979,8 +7807,7 @@ "minipass": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==" }, "minipass-collect": { "version": "2.0.1", @@ -8448,7 +8275,6 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, "requires": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" @@ -8746,11 +8572,41 @@ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" }, "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.7.tgz", + "integrity": "sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==", "requires": { - "glob": "^7.1.3" + "glob": "^10.3.7" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", + "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "path-scurry": "^1.11.1" + } + }, + "minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "requires": { + "brace-expansion": "^2.0.1" + } + } } }, "run-parallel": { @@ -8799,8 +8655,7 @@ "signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" }, "sigstore": { "version": "2.3.1", @@ -8955,7 +8810,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, "requires": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -8965,14 +8819,12 @@ "ansi-regex": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" }, "strip-ansi": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, "requires": { "ansi-regex": "^6.0.1" } @@ -8983,7 +8835,6 @@ "version": "npm:string-width@4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -8993,14 +8844,12 @@ "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" } } }, @@ -9016,7 +8865,6 @@ "version": "npm:strip-ansi@6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "requires": { "ansi-regex": "^5.0.1" } @@ -9081,15 +8929,6 @@ "requires": { "brace-expansion": "^2.0.1" } - }, - "rimraf": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.7.tgz", - "integrity": "sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==", - "dev": true, - "requires": { - "glob": "^10.3.7" - } } } }, @@ -9263,19 +9102,6 @@ "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true }, - "glob": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", - "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", - "dev": true, - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "path-scurry": "^1.11.1" - } - }, "minimatch": { "version": "9.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", @@ -9284,15 +9110,6 @@ "requires": { "brace-expansion": "^2.0.1" } - }, - "rimraf": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.7.tgz", - "integrity": "sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==", - "dev": true, - "requires": { - "glob": "^10.3.7" - } } } }, @@ -9447,7 +9264,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, "requires": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -9457,20 +9273,17 @@ "ansi-regex": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" }, "ansi-styles": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" }, "strip-ansi": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, "requires": { "ansi-regex": "^6.0.1" } @@ -9481,7 +9294,6 @@ "version": "npm:wrap-ansi@7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "requires": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -9491,20 +9303,17 @@ "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -9519,9 +9328,9 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "ws": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", - "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "dev": true, "requires": {} }, diff --git a/package.json b/package.json index 95fdafba..5ae6772f 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,7 @@ "js-yaml": "^4.1.0", "marked": "^10.0.0", "msgpackr": "^1.10.2", + "rimraf": "^5.0.7", "striptags": "^4.0.0-alpha.4", "word-wrap": "^1.2.3" }, diff --git a/src/content/dependencies/generateAlbumReleaseInfo.js b/src/content/dependencies/generateAlbumReleaseInfo.js index 1cd638ce..26e2e160 100644 --- a/src/content/dependencies/generateAlbumReleaseInfo.js +++ b/src/content/dependencies/generateAlbumReleaseInfo.js @@ -1,4 +1,4 @@ -import {accumulateSum} from '#sugar'; +import {accumulateSum, empty} from '#sugar'; export default { contentDependencies: [ @@ -41,8 +41,18 @@ export default { data.coverArtDate = album.coverArtDate; } - data.duration = accumulateSum(album.tracks, track => track.duration); - data.durationApproximate = album.tracks.length > 1; + const durationTerms = + album.tracks + .map(track => track.duration) + .filter(value => value > 0); + + if (empty(durationTerms)) { + data.duration = null; + data.durationApproximate = null; + } else { + data.duration = accumulateSum(durationTerms); + data.durationApproximate = album.tracks.length > 1; + } data.numTracks = album.tracks.length; diff --git a/src/static/js/search-worker.js b/src/static/js/search-worker.js index 8e83fe02..8d987a74 100644 --- a/src/static/js/search-worker.js +++ b/src/static/js/search-worker.js @@ -409,6 +409,7 @@ function queryGenericIndex(index, query, options) { // flexsearch matching multiple field values in a single query. ['artTags', 'artTags'], + ['contributors', 'parentName'], ['contributors', 'groups'], ['primaryName', 'contributors'], ['primaryName'], diff --git a/src/url-spec.js b/src/url-spec.js index dc4673e5..64423a52 100644 --- a/src/url-spec.js +++ b/src/url-spec.js @@ -4,7 +4,7 @@ import {withEntries} from '#sugar'; // part of a build. This is so that multiple builds of a wiki can coexist // served from the same server / file system root: older builds' HTML files // refer to earlier values of STATIC_VERSION, avoiding name collisions. -const STATIC_VERSION = '2p2'; +const STATIC_VERSION = '3r2'; const genericPaths = { root: '', diff --git a/src/util/search-spec.js b/src/util/search-spec.js index 79e8ee95..bc24e1a1 100644 --- a/src/util/search-spec.js +++ b/src/util/search-spec.js @@ -118,12 +118,15 @@ export const searchSpec = { fields.primaryName = thing.name; + const kind = + thing.constructor[Symbol.for('Thing.referenceType')]; + fields.parentName = - (fields.kind === 'track' + (kind === 'track' ? thing.album.name - : fields.kind === 'group' + : kind === 'group' ? thing.category.name - : fields.kind === 'flash' + : kind === 'flash' ? thing.act.name : null); diff --git a/src/web-routes.js b/src/web-routes.js index 7e08d06f..762b26c3 100644 --- a/src/web-routes.js +++ b/src/web-routes.js @@ -18,21 +18,25 @@ export const stationaryCodeRoutes = [ { from: path.join(codeSrcPath, 'static', 'css'), to: ['staticCSS.root'], + statically: 'copy', }, { from: path.join(codeSrcPath, 'static', 'js'), to: ['staticJS.root'], + statically: 'copy', }, { from: path.join(codeSrcPath, 'static', 'misc'), to: ['staticMisc.root'], + statically: 'copy', }, { from: path.join(codeSrcPath, 'util'), to: ['staticSharedUtil.root'], + statically: 'copy', }, ]; @@ -50,6 +54,8 @@ function quickNodeDependency({ : root), to: ['staticLib.path', name], + + statically: 'copy', }, ]; } @@ -86,8 +92,17 @@ export async function identifyDynamicWebRoutes({ }) { const routeFunctions = [ () => Promise.resolve([ - {from: path.resolve(mediaPath), to: ['media.root']}, - {from: path.resolve(mediaCachePath), to: ['thumb.root']}, + { + from: path.resolve(mediaPath), + to: ['media.root'], + statically: 'symlink', + }, + + { + from: path.resolve(mediaCachePath), + to: ['thumb.root'], + statically: 'symlink', + }, ]), () => { @@ -98,7 +113,12 @@ export async function identifyDynamicWebRoutes({ return ( readdir(from).then( - () => [{from, to: ['searchData.root']}], + () => [ + { + from, + to: ['searchData.root'], + statically: 'copy', + }], () => [])); }, ]; diff --git a/src/write/build-modes/static-build.js b/src/write/build-modes/static-build.js index 1ab0604e..86e3da0f 100644 --- a/src/write/build-modes/static-build.js +++ b/src/write/build-modes/static-build.js @@ -2,6 +2,7 @@ import * as path from 'node:path'; import { copyFile, + cp, mkdir, stat, symlink, @@ -9,6 +10,8 @@ import { unlink, } from 'node:fs/promises'; +import {rimraf} from 'rimraf'; + import {quickLoadContentDependencies} from '#content-dependencies'; import {quickEvaluate} from '#content-function'; import * as html from '#html'; @@ -159,6 +162,11 @@ export async function go({ webRoutes, }); + await writeWebRouteCopies({ + outputPath, + webRoutes, + }); + if (writeAll) { await writeFavicon({ mediaPath, @@ -438,8 +446,11 @@ function writeWebRouteSymlinks({ outputPath, webRoutes, }) { + const symlinkRoutes = + webRoutes.filter(route => route.statically === 'symlink'); + const promises = - webRoutes.map(async route => { + symlinkRoutes.map(async route => { const parts = route.to.split('/'); const parentDirectoryParts = parts.slice(0, -1); const symlinkNamePart = parts.at(-1); @@ -471,6 +482,113 @@ function writeWebRouteSymlinks({ return progressPromiseAll(`Writing web route symlinks.`, promises); } +async function writeWebRouteCopies({ + outputPath, + webRoutes, +}) { + const copyRoutes = + webRoutes.filter(route => route.statically === 'copy'); + + const promises = + copyRoutes.map(async route => { + const permissionName = '__hsmusic-ok-for-deletion.txt'; + + const parts = route.to.split('/'); + const parentDirectoryParts = parts.slice(0, -1); + const copyNamePart = parts.at(-1); + + const parentDirectory = path.join(outputPath, ...parentDirectoryParts); + const copyPath = path.join(parentDirectory, copyNamePart); + + // We're going to do a rimraf call! This is freaking terrifying, + // so nope out on a couple important conditions. + + let needsDelete; + try { + await stat(copyPath); + needsDelete = true; + } catch (error) { + if (error.code === 'ENOENT') { + needsDelete = false; + } else { + throw error; + } + } + + if (needsDelete) { + // First remove it directly, in case it's a symlink. + try { + await unlink(copyPath); + needsDelete = false; + } catch (error) { + // EPERM is POSIX, but libuv may or may not flat-out just raise + // the system error (which is ostensibly EISDIR on Linux). + // https://github.com/nodejs/node-v0.x-archive/issues/5791 + // https://man7.org/linux/man-pages/man2/unlink.2.html + // + // Both of these indidcate "a directory, probably" and we'll + // still check for the deletion permission file where we expect + // it before actually touching anything. + if (error.code !== 'EPERM' && error.code !== 'EISDIR') { + throw error; + } + } + } + + if (needsDelete) { + // Then check that the deletion permission file exists + // where we expect it. + try { + await stat(path.join(copyPath, permissionName)); + } catch (error) { + if (error.code === 'ENOENT') { + throw new Error(`Couldn't find ${permissionName} in ${copyPath} - please delete or move away this folder manually`); + } else { + throw error; + } + } + + // And *then* actually delete that directory. + await rimraf(copyPath); + } + + // Actually copy the source path where it's wanted. + await cp(route.from, copyPath, {recursive: true}); + + // And certify that it's OK to delete this path, next time around. + await writeFile(path.join(copyPath, permissionName), + `The presence of this file (by its name, not its contents)\n` + + `indicates hsmusic may delete everything contained in this\n` + + `directory (the one which directly contains this file, *not*\n` + + `any further-up parent directories).\n` + + `\n` + + `If you make edits, or add any files, they will be deleted or\n` + + `overwritten the next time you run the build.\n` + + `\n` + + `If you delete *this* file, hsmusic will error during the next\n` + + `build, and will ask that you delete the containing directory\n` + + `yourself.\n`); + }); + + const results = + await Promise.allSettled(promises); + + const errors = + results + .filter(({status}) => status === 'rejected') + .map(({reason}) => reason) + .map(err => + (err.message.startsWith(`Couldn't find`) + ? err.message + : err)); + + if (empty(errors)) { + logInfo`Wrote web route copies.`; + } else { + throw new AggregateError(errors, `Errors copying internal files ("web routes")`); + } +} + async function writeFavicon({ mediaPath, outputPath, diff --git a/tap-snapshots/test/snapshot/generateAlbumTrackList.js.test.cjs b/tap-snapshots/test/snapshot/generateAlbumTrackList.js.test.cjs index b338f293..091f1b9f 100644 --- a/tap-snapshots/test/snapshot/generateAlbumTrackList.js.test.cjs +++ b/tap-snapshots/test/snapshot/generateAlbumTrackList.js.test.cjs @@ -16,7 +16,10 @@ exports[`test/snapshot/generateAlbumTrackList.js > TAP > generateAlbumTrackList exports[`test/snapshot/generateAlbumTrackList.js > TAP > generateAlbumTrackList (snapshot) > basic behavior, with track sections 1`] = ` <dl class="album-group-list"> - <dt class="content-heading" tabindex="0"><span class="content-heading-main-title">First section: (~1:00)</span></dt> + <dt class="content-heading" tabindex="0"> + <span class="content-heading-main-title">First section: (~1:00)</span> + <template class="content-heading-sticky-title">First section:</template> + </dt> <dd> <ul> <li>(0:20) <a href="track/t1/">Track 1</a></li> @@ -24,14 +27,20 @@ exports[`test/snapshot/generateAlbumTrackList.js > TAP > generateAlbumTrackList <li>(0:40) <a href="track/t3/">Track 3</a></li> </ul> </dd> - <dt class="content-heading" tabindex="0"><span class="content-heading-main-title">Second section:</span></dt> + <dt class="content-heading" tabindex="0"> + <span class="content-heading-main-title">Second section:</span> + <template class="content-heading-sticky-title">Second section:</template> + </dt> <dd><ul><li style="--primary-color: #ea2e83">[mocked: generateAlbumTrackListMissingDuration - slots: {}] <a href="track/t4/">Track 4</a> <span class="by"><span class="chunkwrap">by <a href="artist/apricot/">Apricot</a>,</span> <span class="chunkwrap"><a href="artist/peach/">Peach</a>,</span> <span class="chunkwrap">and <a href="artist/cerise/">Cerise</a></span></span></li></ul></dd> </dl> ` exports[`test/snapshot/generateAlbumTrackList.js > TAP > generateAlbumTrackList (snapshot) > collapseDurationScope: album 1`] = ` <dl class="album-group-list"> - <dt class="content-heading" tabindex="0"><span class="content-heading-main-title">First section: (~1:00)</span></dt> + <dt class="content-heading" tabindex="0"> + <span class="content-heading-main-title">First section: (~1:00)</span> + <template class="content-heading-sticky-title">First section:</template> + </dt> <dd> <ul> <li>(0:20) <a href="track/t1/">Track 1</a></li> @@ -39,7 +48,10 @@ exports[`test/snapshot/generateAlbumTrackList.js > TAP > generateAlbumTrackList <li>(0:40) <a href="track/t3/">Track 3</a></li> </ul> </dd> - <dt class="content-heading" tabindex="0"><span class="content-heading-main-title">Second section:</span></dt> + <dt class="content-heading" tabindex="0"> + <span class="content-heading-main-title">Second section:</span> + <template class="content-heading-sticky-title">Second section:</template> + </dt> <dd><ul><li style="--primary-color: #ea2e83">[mocked: generateAlbumTrackListMissingDuration - slots: {}] <a href="track/t4/">Track 4</a> <span class="by"><span class="chunkwrap">by <a href="artist/apricot/">Apricot</a>,</span> <span class="chunkwrap"><a href="artist/peach/">Peach</a>,</span> <span class="chunkwrap">and <a href="artist/cerise/">Cerise</a></span></span></li></ul></dd> </dl> <ul> @@ -56,7 +68,10 @@ exports[`test/snapshot/generateAlbumTrackList.js > TAP > generateAlbumTrackList exports[`test/snapshot/generateAlbumTrackList.js > TAP > generateAlbumTrackList (snapshot) > collapseDurationScope: never 1`] = ` <dl class="album-group-list"> - <dt class="content-heading" tabindex="0"><span class="content-heading-main-title">First section: (~1:00)</span></dt> + <dt class="content-heading" tabindex="0"> + <span class="content-heading-main-title">First section: (~1:00)</span> + <template class="content-heading-sticky-title">First section:</template> + </dt> <dd> <ul> <li>(0:20) <a href="track/t1/">Track 1</a></li> @@ -64,7 +79,10 @@ exports[`test/snapshot/generateAlbumTrackList.js > TAP > generateAlbumTrackList <li>(0:40) <a href="track/t3/">Track 3</a></li> </ul> </dd> - <dt class="content-heading" tabindex="0"><span class="content-heading-main-title">Second section:</span></dt> + <dt class="content-heading" tabindex="0"> + <span class="content-heading-main-title">Second section:</span> + <template class="content-heading-sticky-title">Second section:</template> + </dt> <dd><ul><li style="--primary-color: #ea2e83">[mocked: generateAlbumTrackListMissingDuration - slots: {}] <a href="track/t4/">Track 4</a> <span class="by"><span class="chunkwrap">by <a href="artist/apricot/">Apricot</a>,</span> <span class="chunkwrap"><a href="artist/peach/">Peach</a>,</span> <span class="chunkwrap">and <a href="artist/cerise/">Cerise</a></span></span></li></ul></dd> </dl> <ul> @@ -81,7 +99,10 @@ exports[`test/snapshot/generateAlbumTrackList.js > TAP > generateAlbumTrackList exports[`test/snapshot/generateAlbumTrackList.js > TAP > generateAlbumTrackList (snapshot) > collapseDurationScope: section 1`] = ` <dl class="album-group-list"> - <dt class="content-heading" tabindex="0"><span class="content-heading-main-title">First section: (~1:00)</span></dt> + <dt class="content-heading" tabindex="0"> + <span class="content-heading-main-title">First section: (~1:00)</span> + <template class="content-heading-sticky-title">First section:</template> + </dt> <dd> <ul> <li>(0:20) <a href="track/t1/">Track 1</a></li> @@ -89,7 +110,10 @@ exports[`test/snapshot/generateAlbumTrackList.js > TAP > generateAlbumTrackList <li>(0:40) <a href="track/t3/">Track 3</a></li> </ul> </dd> - <dt class="content-heading" tabindex="0"><span class="content-heading-main-title">Second section:</span></dt> + <dt class="content-heading" tabindex="0"> + <span class="content-heading-main-title">Second section:</span> + <template class="content-heading-sticky-title">Second section:</template> + </dt> <dd><ul><li style="--primary-color: #ea2e83"><a href="track/t4/">Track 4</a> <span class="by"><span class="chunkwrap">by <a href="artist/apricot/">Apricot</a>,</span> <span class="chunkwrap"><a href="artist/peach/">Peach</a>,</span> <span class="chunkwrap">and <a href="artist/cerise/">Cerise</a></span></span></li></ul></dd> </dl> <ul> @@ -106,7 +130,10 @@ exports[`test/snapshot/generateAlbumTrackList.js > TAP > generateAlbumTrackList exports[`test/snapshot/generateAlbumTrackList.js > TAP > generateAlbumTrackList (snapshot) > collapseDurationScope: track 1`] = ` <dl class="album-group-list"> - <dt class="content-heading" tabindex="0"><span class="content-heading-main-title">First section: (~1:00)</span></dt> + <dt class="content-heading" tabindex="0"> + <span class="content-heading-main-title">First section: (~1:00)</span> + <template class="content-heading-sticky-title">First section:</template> + </dt> <dd> <ul> <li>(0:20) <a href="track/t1/">Track 1</a></li> @@ -114,7 +141,10 @@ exports[`test/snapshot/generateAlbumTrackList.js > TAP > generateAlbumTrackList <li>(0:40) <a href="track/t3/">Track 3</a></li> </ul> </dd> - <dt class="content-heading" tabindex="0"><span class="content-heading-main-title">Second section:</span></dt> + <dt class="content-heading" tabindex="0"> + <span class="content-heading-main-title">Second section:</span> + <template class="content-heading-sticky-title">Second section:</template> + </dt> <dd><ul><li style="--primary-color: #ea2e83"><a href="track/t4/">Track 4</a> <span class="by"><span class="chunkwrap">by <a href="artist/apricot/">Apricot</a>,</span> <span class="chunkwrap"><a href="artist/peach/">Peach</a>,</span> <span class="chunkwrap">and <a href="artist/cerise/">Cerise</a></span></span></li></ul></dd> </dl> <ul> diff --git a/test/lib/composite.js b/test/lib/composite.js new file mode 100644 index 00000000..359d364d --- /dev/null +++ b/test/lib/composite.js @@ -0,0 +1,33 @@ +import {compositeFrom} from '#composite'; + +export function quickCheckCompositeOutputs(t, dependencies) { + return (step, outputDict) => { + t.same( + Object.keys(step.toDescription().outputs), + Object.keys(outputDict)); + + const composite = compositeFrom({ + compose: false, + steps: [ + step, + + { + dependencies: Object.keys(outputDict), + + // Access all dependencies by their expected keys - + // the composition runner actually provides a proxy + // and is checking that *we* access the dependencies + // we've specified. + compute: dependencies => + Object.fromEntries( + Object.keys(outputDict) + .map(key => [key, dependencies[key]])), + }, + ], + }); + + t.same( + composite.expose.compute(dependencies), + outputDict); + }; +} diff --git a/test/lib/index.js b/test/lib/index.js index 5fb5bf78..4c9ee23f 100644 --- a/test/lib/index.js +++ b/test/lib/index.js @@ -1,5 +1,6 @@ Error.stackTraceLimit = Infinity; +export * from './composite.js'; export * from './content-function.js'; export * from './generic-mock.js'; export * from './wiki-data.js'; diff --git a/test/unit/data/composite/control-flow/withResultOfAvailabilityCheck.js b/test/unit/data/composite/control-flow/withResultOfAvailabilityCheck.js index 2bcabb4f..9d588e4c 100644 --- a/test/unit/data/composite/control-flow/withResultOfAvailabilityCheck.js +++ b/test/unit/data/composite/control-flow/withResultOfAvailabilityCheck.js @@ -177,10 +177,11 @@ t.test(`withResultOfAvailabilityCheck: validate dynamic inputs`, t => { mode: 'banana', }), {message: `Error computing composition`, cause: - {message: `Error computing composition withResultOfAvailabilityCheck`, cause: - {message: `Errors in input values provided to withResultOfAvailabilityCheck`, errors: [ - {message: `mode: Expected one of null empty falsy index, got banana`}, - ]}}}); + {message: `Error in step 1 of 2, withResultOfAvailabilityCheck`, cause: + {message: `Error computing composition withResultOfAvailabilityCheck`, cause: + {message: `Errors in input values provided to withResultOfAvailabilityCheck`, errors: [ + {message: `mode: Expected one of null empty falsy index, got banana`}, + ]}}}}); t.throws( () => composite.expose.compute({ @@ -188,8 +189,9 @@ t.test(`withResultOfAvailabilityCheck: validate dynamic inputs`, t => { mode: null, }), {message: `Error computing composition`, cause: - {message: `Error computing composition withResultOfAvailabilityCheck`, cause: - {message: `Errors in input values provided to withResultOfAvailabilityCheck`, errors: [ - {message: `mode: Expected a value, got null`}, - ]}}}); + {message: `Error in step 1 of 2, withResultOfAvailabilityCheck`, cause: + {message: `Error computing composition withResultOfAvailabilityCheck`, cause: + {message: `Errors in input values provided to withResultOfAvailabilityCheck`, errors: [ + {message: `mode: Expected a value, got null`}, + ]}}}}); }); diff --git a/test/unit/data/composite/data/withPropertiesFromObject.js b/test/unit/data/composite/data/withPropertiesFromObject.js index 750dc8c4..b81d51a5 100644 --- a/test/unit/data/composite/data/withPropertiesFromObject.js +++ b/test/unit/data/composite/data/withPropertiesFromObject.js @@ -1,4 +1,5 @@ import t from 'tap'; +import {quickCheckCompositeOutputs} from '#test-lib'; import {compositeFrom, input} from '#composite'; import {exposeDependency} from '#composite/control-flow'; @@ -62,6 +63,8 @@ t.test(`withPropertiesFromObject: output shapes & values`, t => { ['foo', 'baz', 'missing3'], }; + const qcco = quickCheckCompositeOutputs(t, dependencies); + const mapLevel1 = [ [input.value('prefix_value'), [ ['object_dependency', [ @@ -153,28 +156,10 @@ t.test(`withPropertiesFromObject: output shapes & values`, t => { properties: propertiesInput, }); - quickCheckOutputs(step, outputDict); + qcco(step, outputDict); } } } - - function quickCheckOutputs(step, outputDict) { - t.same( - Object.keys(step.toDescription().outputs), - Object.keys(outputDict)); - - const composite = compositeFrom({ - compose: false, - steps: [step, { - dependencies: Object.keys(outputDict), - compute: dependencies => dependencies, - }], - }); - - t.same( - composite.expose.compute(dependencies), - outputDict); - } }); t.test(`withPropertiesFromObject: validate static inputs`, t => { @@ -226,11 +211,12 @@ t.test(`withPropertiesFromObject: validate dynamic inputs`, t => { properties: 'onceMore', }), {message: `Error computing composition`, cause: - {message: `Error computing composition withPropertiesFromObject`, cause: - {message: `Errors in input values provided to withPropertiesFromObject`, errors: [ - {message: `object: Expected an object, got string`}, - {message: `properties: Expected an array, got string`}, - ]}}}); + {message: `Error in step 1 of 2, withPropertiesFromObject`, cause: + {message: `Error computing composition withPropertiesFromObject`, cause: + {message: `Errors in input values provided to withPropertiesFromObject`, errors: [ + {message: `object: Expected an object, got string`}, + {message: `properties: Expected an array, got string`}, + ]}}}}); t.throws( () => composite.expose.compute({ @@ -238,17 +224,18 @@ t.test(`withPropertiesFromObject: validate dynamic inputs`, t => { properties: ['abc', 'def', 123], }), {message: `Error computing composition`, cause: - {message: `Error computing composition withPropertiesFromObject`, cause: - {message: `Errors in input values provided to withPropertiesFromObject`, errors: [ - {message: `object: Expected an object, got array`}, - {message: `properties: Errors validating array items`, errors: [ - { - [Symbol.for('hsmusic.annotateError.indexInSourceArray')]: 2, - message: `Error at zero-index 2: 123`, - cause: { - message: `Expected a string, got number`, + {message: `Error in step 1 of 2, withPropertiesFromObject`, cause: + {message: `Error computing composition withPropertiesFromObject`, cause: + {message: `Errors in input values provided to withPropertiesFromObject`, errors: [ + {message: `object: Expected an object, got array`}, + {message: `properties: Errors validating array items`, errors: [ + { + [Symbol.for('hsmusic.annotateError.indexInSourceArray')]: 2, + message: `Error at zero-index 2: 123`, + cause: { + message: `Expected a string, got number`, + }, }, - }, - ]}, - ]}}}); + ]}, + ]}}}}); }); diff --git a/test/unit/data/composite/data/withPropertyFromObject.js b/test/unit/data/composite/data/withPropertyFromObject.js index 6a772c36..50ee835c 100644 --- a/test/unit/data/composite/data/withPropertyFromObject.js +++ b/test/unit/data/composite/data/withPropertyFromObject.js @@ -1,4 +1,5 @@ import t from 'tap'; +import {quickCheckCompositeOutputs} from '#test-lib'; import {compositeFrom, input} from '#composite'; import {exposeDependency} from '#composite/control-flow'; @@ -56,6 +57,8 @@ t.test(`withPropertyFromObject: output shapes & values`, t => { 'baz', }; + const qcco = quickCheckCompositeOutputs(t, dependencies); + const mapLevel1 = [ ['object_dependency', [ ['property_dependency', { @@ -98,25 +101,7 @@ t.test(`withPropertyFromObject: output shapes & values`, t => { property: propertyInput, }); - quickCheckOutputs(step, outputDict); + qcco(step, outputDict); } } - - function quickCheckOutputs(step, outputDict) { - t.same( - Object.keys(step.toDescription().outputs), - Object.keys(outputDict)); - - const composite = compositeFrom({ - compose: false, - steps: [step, { - dependencies: Object.keys(outputDict), - compute: dependencies => dependencies, - }], - }); - - t.same( - composite.expose.compute(dependencies), - outputDict); - } }); diff --git a/test/unit/data/composite/data/withUniqueItemsOnly.js b/test/unit/data/composite/data/withUniqueItemsOnly.js index 965b14b5..50b16f43 100644 --- a/test/unit/data/composite/data/withUniqueItemsOnly.js +++ b/test/unit/data/composite/data/withUniqueItemsOnly.js @@ -1,4 +1,5 @@ import t from 'tap'; +import {quickCheckCompositeOutputs} from '#test-lib'; import {compositeFrom, input} from '#composite'; import {exposeDependency} from '#composite/control-flow'; @@ -44,6 +45,8 @@ t.test(`withUniqueItemsOnly: output shapes & values`, t => { [8, 8, 7, 6, 6, 5, 'bar', true, true, 5], }; + const qcco = quickCheckCompositeOutputs(t, dependencies); + const mapLevel1 = [ ['list_dependency', { '#list_dependency': [1, 2, 3, 4, 'foo', false], @@ -61,24 +64,6 @@ t.test(`withUniqueItemsOnly: output shapes & values`, t => { list: listInput, }); - quickCheckOutputs(step, outputDict); - } - - function quickCheckOutputs(step, outputDict) { - t.same( - Object.keys(step.toDescription().outputs), - Object.keys(outputDict)); - - const composite = compositeFrom({ - compose: false, - steps: [step, { - dependencies: Object.keys(outputDict), - compute: dependencies => dependencies, - }], - }); - - t.same( - composite.expose.compute(dependencies), - outputDict); + qcco(step, outputDict); } }); |